chore(io): implement IE and IME

This commit is contained in:
Rekai Nyangadzayi Musuka 2022-01-12 02:19:26 -04:00
parent 769c67b9d4
commit 1c173eb4b8
2 changed files with 49 additions and 7 deletions

View File

@ -69,7 +69,7 @@ pub fn write32(self: *Self, addr: u32, word: u32) void {
// General Internal Memory // General Internal Memory
0x0200_0000...0x0203_FFFF => self.iwram.set32(addr - 0x0200_0000, word), 0x0200_0000...0x0203_FFFF => self.iwram.set32(addr - 0x0200_0000, word),
0x0300_0000...0x0300_7FFF => self.ewram.set32(addr - 0x0300_0000, word), 0x0300_0000...0x0300_7FFF => self.ewram.set32(addr - 0x0300_0000, word),
0x0400_0000...0x0400_03FE => std.debug.panic("[Bus:32] wrote 0x{X:} to 0x{X:} in I/O", .{ word, addr }), 0x0400_0000...0x0400_03FE => self.io.write32(addr, word),
// Internal Display Memory // Internal Display Memory
0x0500_0000...0x0500_03FF => self.ppu.palette.set32(@as(usize, addr - 0x0500_0000), word), 0x0500_0000...0x0500_03FF => self.ppu.palette.set32(@as(usize, addr - 0x0500_0000), word),
@ -153,7 +153,7 @@ pub fn write8(self: *Self, addr: u32, byte: u8) void {
// General Internal Memory // General Internal Memory
0x0200_0000...0x0203_FFFF => self.iwram.set8(addr - 0x0200_0000, byte), 0x0200_0000...0x0203_FFFF => self.iwram.set8(addr - 0x0200_0000, byte),
0x0300_0000...0x0300_7FFF => self.ewram.set8(addr - 0x0300_0000, byte), 0x0300_0000...0x0300_7FFF => self.ewram.set8(addr - 0x0300_0000, byte),
0x0400_0000...0x0400_03FE => self.io.set8(addr - 0x0400_0000, byte), 0x0400_0000...0x0400_03FE => self.io.write8(addr, byte),
// External Memory (Game Pak) // External Memory (Game Pak)
0x0E00_0000...0x0E00_FFFF => std.debug.panic("[Bus:8] write 0x{X:} to 0x{X:} in Game Pak SRAM", .{ byte, addr }), 0x0E00_0000...0x0E00_FFFF => std.debug.panic("[Bus:8] write 0x{X:} to 0x{X:} in Game Pak SRAM", .{ byte, addr }),

View File

@ -6,15 +6,20 @@ const Bitfield = @import("bitfield").Bitfield;
pub const Io = struct { pub const Io = struct {
const Self = @This(); const Self = @This();
dispcnt: DispCnt, dispcnt: DisplayControl,
dispstat: DispStat, dispstat: DisplayStatus,
vcount: VCount, vcount: VCount,
/// Read / Write
ime: bool,
ie: InterruptEnable,
pub fn init() Self { pub fn init() Self {
return .{ return .{
.dispcnt = .{ .raw = 0x0000_0000 }, .dispcnt = .{ .raw = 0x0000_0000 },
.dispstat = .{ .raw = 0x0000_0000 }, .dispstat = .{ .raw = 0x0000_0000 },
.vcount = .{ .raw = 0x0000_0000 }, .vcount = .{ .raw = 0x0000_0000 },
.ime = false,
.ie = .{ .raw = 0x0000_0000 },
}; };
} }
@ -23,15 +28,27 @@ pub const Io = struct {
0x0400_0000 => @as(u32, self.dispcnt.raw), 0x0400_0000 => @as(u32, self.dispcnt.raw),
0x0400_0004 => @as(u32, self.dispstat.raw), 0x0400_0004 => @as(u32, self.dispstat.raw),
0x0400_0006 => @as(u32, self.vcount.raw), 0x0400_0006 => @as(u32, self.vcount.raw),
0x0400_0200 => @as(u32, self.ie.raw),
0x0400_0208 => @boolToInt(self.ime),
else => std.debug.panic("[I/O:32] tried to read from {X:}", .{addr}), else => std.debug.panic("[I/O:32] tried to read from {X:}", .{addr}),
}; };
} }
pub fn write32(self: *Self, addr: u32, word: u32) void {
switch (addr) {
0x0400_0200 => self.ie.raw = @truncate(u16, word),
0x0400_0208 => self.ime = word & 1 == 1,
else => std.debug.panic("[I/O:32] tried to write 0x{X:} to 0x{X:}", .{ word, addr }),
}
}
pub fn read16(self: *const Self, addr: u32) u16 { pub fn read16(self: *const Self, addr: u32) u16 {
return switch (addr) { return switch (addr) {
0x0400_0000 => self.dispcnt.raw, 0x0400_0000 => self.dispcnt.raw,
0x0400_0004 => self.dispstat.raw, 0x0400_0004 => self.dispstat.raw,
0x0400_0006 => self.vcount.raw, 0x0400_0006 => self.vcount.raw,
0x0400_0200 => self.ie.raw,
0x0400_0208 => @boolToInt(self.ime),
else => std.debug.panic("[I/O:16] tried to read from {X:}", .{addr}), else => std.debug.panic("[I/O:16] tried to read from {X:}", .{addr}),
}; };
} }
@ -40,6 +57,8 @@ pub const Io = struct {
switch (addr) { switch (addr) {
0x0400_0000 => self.dispcnt.raw = halfword, 0x0400_0000 => self.dispcnt.raw = halfword,
0x0400_0004 => self.dispstat.raw = halfword, 0x0400_0004 => self.dispstat.raw = halfword,
0x0400_0200 => self.ie.raw = halfword,
0x0400_0208 => self.ime = halfword & 1 == 1,
else => std.debug.panic("[I/O:16] tried to write 0x{X:} to 0x{X:}", .{ halfword, addr }), else => std.debug.panic("[I/O:16] tried to write 0x{X:} to 0x{X:}", .{ halfword, addr }),
} }
} }
@ -48,17 +67,19 @@ pub const Io = struct {
return switch (addr) { return switch (addr) {
0x0400_0000 => @truncate(u8, self.dispcnt.raw), 0x0400_0000 => @truncate(u8, self.dispcnt.raw),
0x0400_0004 => @truncate(u8, self.dispstat.raw), 0x0400_0004 => @truncate(u8, self.dispstat.raw),
0x0400_0200 => @truncate(u8, self.ie.raw),
0x0400_0006 => @truncate(u8, self.vcount.raw), 0x0400_0006 => @truncate(u8, self.vcount.raw),
else => std.debug.panic("[I/O:8] tried to read from {X:}", .{addr}), else => std.debug.panic("[I/O:8] tried to read from {X:}", .{addr}),
}; };
} }
pub fn set8(_: *Self, addr: u32, byte: u8) void { pub fn write8(_: *Self, addr: u32, byte: u8) void {
std.debug.panic("[I/0:8] tried to write 0x{X:} to 0x{X:}", .{ byte, addr }); std.debug.panic("[I/0:8] tried to write 0x{X:} to 0x{X:}", .{ byte, addr });
} }
}; };
const DispCnt = extern union { /// Read / Write
const DisplayControl = extern union {
bg_mode: Bitfield(u16, 0, 3), bg_mode: Bitfield(u16, 0, 3),
frame_select: Bit(u16, 4), frame_select: Bit(u16, 4),
hblank_interval_free: Bit(u16, 5), hblank_interval_free: Bit(u16, 5),
@ -71,7 +92,8 @@ const DispCnt = extern union {
raw: u16, raw: u16,
}; };
const DispStat = extern union { /// Read / Write
const DisplayStatus = extern union {
vblank: Bit(u16, 0), vblank: Bit(u16, 0),
hblank: Bit(u16, 1), hblank: Bit(u16, 1),
coincidence: Bit(u16, 2), coincidence: Bit(u16, 2),
@ -82,7 +104,27 @@ const DispStat = extern union {
raw: u16, raw: u16,
}; };
/// Read Only
const VCount = extern union { const VCount = extern union {
scanline: Bitfield(u16, 0, 8), scanline: Bitfield(u16, 0, 8),
raw: u16, raw: u16,
}; };
/// Read / Write
const InterruptEnable = extern union {
vblank: Bit(u16, 0),
hblank: Bit(u16, 1),
coincidence: Bit(u16, 2),
tm0_overflow: Bit(u16, 3),
tm1_overflow: Bit(u16, 4),
tm2_overflow: Bit(u16, 5),
tm3_overflow: Bit(u16, 6),
serial: Bit(u16, 7),
dma0: Bit(u16, 8),
dma1: Bit(u16, 9),
dma2: Bit(u16, 10),
dma3: Bit(u16, 11),
keypad: Bit(u16, 12),
game_pak: Bit(u16, 13),
raw: u16,
};