From e5a76a3c025bf49a2f68944f4482ac8848fc8151 Mon Sep 17 00:00:00 2001 From: Rekai Musuka Date: Sun, 13 Feb 2022 04:27:20 -0400 Subject: [PATCH] chore: give DISPCNT DISPSTAT and VCOUNT to PPU struct --- src/bus/io.zig | 88 +++++++++++++---------------------------------- src/ppu.zig | 49 +++++++++++++++++++++++--- src/scheduler.zig | 12 +++---- 3 files changed, 73 insertions(+), 76 deletions(-) diff --git a/src/bus/io.zig b/src/bus/io.zig index 277c7b2..e25634b 100644 --- a/src/bus/io.zig +++ b/src/bus/io.zig @@ -7,60 +7,15 @@ const Bus = @import("../Bus.zig"); pub const Io = struct { const Self = @This(); - dispcnt: DisplayControl, - dispstat: DisplayStatus, - vcount: VCount, - /// Read / Write - bg0cnt: BackgroundControl, - /// Read / Write - bg1cnt: BackgroundControl, - /// Read / Write - bg2cnt: BackgroundControl, - /// Read / Write - bg3cnt: BackgroundControl, - - /// Write Only - bg0hofs: BackgroundOffset, - /// Write Only - bg0vofs: BackgroundOffset, - /// Write Only - bg1hofs: BackgroundOffset, - /// Write Only - bg1vofs: BackgroundOffset, - /// Write Only - bg2hofs: BackgroundOffset, - /// Write Only - bg2vofs: BackgroundOffset, - /// Write Only - bg3hofs: BackgroundOffset, - /// Write Only - bg3vofs: BackgroundOffset, - /// Read / Write ime: bool, ie: InterruptEnable, - /// Read / Write irq: InterruptRequest, keyinput: KeyInput, pub fn init() Self { return .{ - .dispcnt = .{ .raw = 0x0000 }, - .dispstat = .{ .raw = 0x0000 }, - .vcount = .{ .raw = 0x0000 }, - .bg0cnt = .{ .raw = 0x0000 }, - .bg1cnt = .{ .raw = 0x0000 }, - .bg2cnt = .{ .raw = 0x0000 }, - .bg3cnt = .{ .raw = 0x0000 }, - .bg0hofs = .{ .raw = 0x0000 }, - .bg0vofs = .{ .raw = 0x0000 }, - .bg1hofs = .{ .raw = 0x0000 }, - .bg1vofs = .{ .raw = 0x0000 }, - .bg2hofs = .{ .raw = 0x0000 }, - .bg2vofs = .{ .raw = 0x0000 }, - .bg3hofs = .{ .raw = 0x0000 }, - .bg3vofs = .{ .raw = 0x0000 }, .ime = false, .ie = .{ .raw = 0x0000 }, .irq = .{ .raw = 0x0000 }, @@ -70,7 +25,7 @@ pub const Io = struct { }; /// Read / Write -const DisplayControl = extern union { +pub const DisplayControl = extern union { bg_mode: Bitfield(u16, 0, 3), frame_select: Bit(u16, 4), hblank_interval_free: Bit(u16, 5), @@ -84,7 +39,7 @@ const DisplayControl = extern union { }; /// Read / Write -const DisplayStatus = extern union { +pub const DisplayStatus = extern union { vblank: Bit(u16, 0), hblank: Bit(u16, 1), coincidence: Bit(u16, 2), @@ -96,7 +51,7 @@ const DisplayStatus = extern union { }; /// Read Only -const VCount = extern union { +pub const VCount = extern union { scanline: Bitfield(u16, 0, 8), raw: u16, }; @@ -136,7 +91,8 @@ const KeyInput = extern union { raw: u16, }; -const BackgroundControl = extern union { +// Read / Write +pub const BackgroundControl = extern union { bg_priority: Bitfield(u16, 0, 2), char_base: Bitfield(u16, 2, 2), mosaic_enable: Bit(u16, 6), @@ -147,11 +103,13 @@ const BackgroundControl = extern union { raw: u16, }; -const BackgroundOffset = extern union { +/// Write Only +pub const BackgroundOffset = extern union { offset: Bitfield(u16, 0, 9), raw: u16, }; +/// Read / Write const InterruptRequest = extern union { vblank: Bit(u16, 0), hblank: Bit(u16, 1), @@ -172,9 +130,9 @@ const InterruptRequest = extern union { pub fn read32(bus: *const Bus, addr: u32) u32 { return switch (addr) { - 0x0400_0000 => bus.io.dispcnt.raw, - 0x0400_0004 => bus.io.dispstat.raw, - 0x0400_0006 => bus.io.vcount.raw, + 0x0400_0000 => bus.ppu.dispcnt.raw, + 0x0400_0004 => bus.ppu.dispstat.raw, + 0x0400_0006 => bus.ppu.vcount.raw, 0x0400_0200 => bus.io.ie.raw, 0x0400_0208 => @boolToInt(bus.io.ime), else => std.debug.panic("[I/O:32] tried to read from {X:}", .{addr}), @@ -183,7 +141,7 @@ pub fn read32(bus: *const Bus, addr: u32) u32 { pub fn write32(bus: *Bus, addr: u32, word: u32) void { switch (addr) { - 0x0400_0000 => bus.io.dispcnt.raw = @truncate(u16, word), + 0x0400_0000 => bus.ppu.dispcnt.raw = @truncate(u16, word), 0x0400_0200 => bus.io.ie.raw = @truncate(u16, word), 0x0400_0208 => bus.io.ime = word & 1 == 1, else => std.debug.panic("[I/O:32] tried to write 0x{X:} to 0x{X:}", .{ word, addr }), @@ -192,9 +150,9 @@ pub fn write32(bus: *Bus, addr: u32, word: u32) void { pub fn read16(bus: *const Bus, addr: u32) u16 { return switch (addr) { - 0x0400_0000 => bus.io.dispcnt.raw, - 0x0400_0004 => bus.io.dispstat.raw, - 0x0400_0006 => bus.io.vcount.raw, + 0x0400_0000 => bus.ppu.dispcnt.raw, + 0x0400_0004 => bus.ppu.dispstat.raw, + 0x0400_0006 => bus.ppu.vcount.raw, 0x0400_0130 => bus.io.keyinput.raw, 0x0400_0200 => bus.io.ie.raw, 0x0400_0208 => @boolToInt(bus.io.ime), @@ -204,11 +162,11 @@ pub fn read16(bus: *const Bus, addr: u32) u16 { pub fn write16(bus: *Bus, addr: u32, halfword: u16) void { switch (addr) { - 0x0400_0000 => bus.io.dispcnt.raw = halfword, - 0x0400_0004 => bus.io.dispstat.raw = halfword, - 0x0400_0008 => bus.io.bg0cnt.raw = halfword, - 0x0400_0010 => bus.io.bg0hofs.raw = halfword, - 0x0400_0012 => bus.io.bg0vofs.raw = halfword, + 0x0400_0000 => bus.ppu.dispcnt.raw = halfword, + 0x0400_0004 => bus.ppu.dispstat.raw = halfword, + 0x0400_0008 => bus.ppu.bg0.cnt.raw = halfword, + 0x0400_0010 => bus.ppu.bg0.hofs.raw = halfword, + 0x0400_0012 => bus.ppu.bg0.vofs.raw = halfword, 0x0400_0200 => bus.io.ie.raw = halfword, 0x0400_0202 => bus.io.irq.raw = halfword, 0x0400_0208 => bus.io.ime = halfword & 1 == 1, @@ -218,10 +176,10 @@ pub fn write16(bus: *Bus, addr: u32, halfword: u16) void { pub fn read8(bus: *const Bus, addr: u32) u8 { return switch (addr) { - 0x0400_0000 => @truncate(u8, bus.io.dispcnt.raw), - 0x0400_0004 => @truncate(u8, bus.io.dispstat.raw), + 0x0400_0000 => @truncate(u8, bus.ppu.dispcnt.raw), + 0x0400_0004 => @truncate(u8, bus.ppu.dispstat.raw), 0x0400_0200 => @truncate(u8, bus.io.ie.raw), - 0x0400_0006 => @truncate(u8, bus.io.vcount.raw), + 0x0400_0006 => @truncate(u8, bus.ppu.vcount.raw), else => std.debug.panic("[I/O:8] tried to read from {X:}", .{addr}), }; } diff --git a/src/ppu.zig b/src/ppu.zig index dbc555e..e72c520 100644 --- a/src/ppu.zig +++ b/src/ppu.zig @@ -1,10 +1,11 @@ const std = @import("std"); +const io = @import("bus/io.zig"); const EventKind = @import("scheduler.zig").EventKind; -const Io = @import("bus/io.zig").Io; const Scheduler = @import("scheduler.zig").Scheduler; const Allocator = std.mem.Allocator; + pub const width = 240; pub const height = 160; pub const framebuf_pitch = width * @sizeOf(u16); @@ -12,6 +13,16 @@ pub const framebuf_pitch = width * @sizeOf(u16); pub const Ppu = struct { const Self = @This(); + // Registers + bg0: Background, + bg1: Background, + bg2: Background, + bg3: Background, + + dispcnt: io.DisplayControl, + dispstat: io.DisplayStatus, + vcount: io.VCount, + vram: Vram, palette: Palette, oam: Oam, @@ -33,6 +44,15 @@ pub const Ppu = struct { .sched = sched, .framebuf = framebuf, .alloc = alloc, + + // Registers + .bg0 = Background.init(), + .bg1 = Background.init(), + .bg2 = Background.init(), + .bg3 = Background.init(), + .dispcnt = .{ .raw = 0x0000 }, + .dispstat = .{ .raw = 0x0000 }, + .vcount = .{ .raw = 0x0000 }, }; } @@ -42,9 +62,9 @@ pub const Ppu = struct { self.palette.deinit(); } - pub fn drawScanline(self: *Self, io: *const Io) void { - const bg_mode = io.dispcnt.bg_mode.read(); - const scanline = io.vcount.scanline.read(); + pub fn drawScanline(self: *Self) void { + const bg_mode = self.dispcnt.bg_mode.read(); + const scanline = self.vcount.scanline.read(); switch (bg_mode) { 0x0 => { @@ -58,7 +78,7 @@ pub const Ppu = struct { std.mem.copy(u8, self.framebuf[start..end], self.vram.buf[start..end]); }, 0x4 => { - const select = io.dispcnt.frame_select.read(); + const select = self.dispcnt.frame_select.read(); const vram_start = width * @as(usize, scanline); const buf_start = vram_start * @sizeOf(u16); @@ -205,3 +225,22 @@ const Oam = struct { return self.buf[idx]; } }; + +const Background = struct { + const Self = @This(); + + /// Read / Write + cnt: io.BackgroundControl, + /// Write Only + hofs: io.BackgroundOffset, + /// Write Only + vofs: io.BackgroundOffset, + + fn init() Self { + return .{ + .cnt = .{ .raw = 0x0000 }, + .hofs = .{ .raw = 0x0000 }, + .vofs = .{ .raw = 0x0000 }, + }; + } +}; diff --git a/src/scheduler.zig b/src/scheduler.zig index 7048e4d..ec161bb 100644 --- a/src/scheduler.zig +++ b/src/scheduler.zig @@ -38,28 +38,28 @@ pub const Scheduler = struct { }, .HBlank => { // The End of a Hblank (During Draw or Vblank) - const old_scanline = bus.io.vcount.scanline.read(); + const old_scanline = bus.ppu.vcount.scanline.read(); const scanline = (old_scanline + 1) % 228; - bus.io.vcount.scanline.write(scanline); - bus.io.dispstat.hblank.unset(); + bus.ppu.vcount.scanline.write(scanline); + bus.ppu.dispstat.hblank.unset(); if (scanline < 160) { // Transitioning to another Draw self.push(.Draw, self.tick + (240 * 4)); } else { // Transitioning to a Vblank - if (scanline < 227) bus.io.dispstat.vblank.set() else bus.io.dispstat.vblank.unset(); + if (scanline < 227) bus.ppu.dispstat.vblank.set() else bus.ppu.dispstat.vblank.unset(); self.push(.VBlank, self.tick + (240 * 4)); } }, .Draw => { // The end of a Draw - bus.ppu.drawScanline(&bus.io); + bus.ppu.drawScanline(); // Transitioning to a Hblank - bus.io.dispstat.hblank.set(); + bus.ppu.dispstat.hblank.set(); self.push(.HBlank, self.tick + (68 * 4)); }, .VBlank => {