From 1c173eb4b8d59a7e3196f67acd66967ed1478aec Mon Sep 17 00:00:00 2001 From: Rekai Musuka Date: Wed, 12 Jan 2022 02:19:26 -0400 Subject: [PATCH] chore(io): implement IE and IME --- src/Bus.zig | 4 ++-- src/bus/io.zig | 52 +++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 49 insertions(+), 7 deletions(-) diff --git a/src/Bus.zig b/src/Bus.zig index 0b0d7c6..0c30d49 100644 --- a/src/Bus.zig +++ b/src/Bus.zig @@ -69,7 +69,7 @@ pub fn write32(self: *Self, addr: u32, word: u32) void { // General Internal Memory 0x0200_0000...0x0203_FFFF => self.iwram.set32(addr - 0x0200_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 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 0x0200_0000...0x0203_FFFF => self.iwram.set8(addr - 0x0200_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) 0x0E00_0000...0x0E00_FFFF => std.debug.panic("[Bus:8] write 0x{X:} to 0x{X:} in Game Pak SRAM", .{ byte, addr }), diff --git a/src/bus/io.zig b/src/bus/io.zig index a934b7a..4fc915e 100644 --- a/src/bus/io.zig +++ b/src/bus/io.zig @@ -6,15 +6,20 @@ const Bitfield = @import("bitfield").Bitfield; pub const Io = struct { const Self = @This(); - dispcnt: DispCnt, - dispstat: DispStat, + dispcnt: DisplayControl, + dispstat: DisplayStatus, vcount: VCount, + /// Read / Write + ime: bool, + ie: InterruptEnable, pub fn init() Self { return .{ .dispcnt = .{ .raw = 0x0000_0000 }, .dispstat = .{ .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_0004 => @as(u32, self.dispstat.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}), }; } + 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 { return switch (addr) { 0x0400_0000 => self.dispcnt.raw, 0x0400_0004 => self.dispstat.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}), }; } @@ -40,6 +57,8 @@ pub const Io = struct { switch (addr) { 0x0400_0000 => self.dispcnt.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 }), } } @@ -48,17 +67,19 @@ pub const Io = struct { return switch (addr) { 0x0400_0000 => @truncate(u8, self.dispcnt.raw), 0x0400_0004 => @truncate(u8, self.dispstat.raw), + 0x0400_0200 => @truncate(u8, self.ie.raw), 0x0400_0006 => @truncate(u8, self.vcount.raw), 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 }); } }; -const DispCnt = extern union { +/// Read / Write +const DisplayControl = extern union { bg_mode: Bitfield(u16, 0, 3), frame_select: Bit(u16, 4), hblank_interval_free: Bit(u16, 5), @@ -71,7 +92,8 @@ const DispCnt = extern union { raw: u16, }; -const DispStat = extern union { +/// Read / Write +const DisplayStatus = extern union { vblank: Bit(u16, 0), hblank: Bit(u16, 1), coincidence: Bit(u16, 2), @@ -82,7 +104,27 @@ const DispStat = extern union { raw: u16, }; +/// Read Only const VCount = extern union { scanline: Bitfield(u16, 0, 8), 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, +};