chore(io): implement IE and IME
This commit is contained in:
		| @@ -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 }), | ||||
|   | ||||
| @@ -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, | ||||
| }; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user