diff --git a/src/core/nds9/Bus.zig b/src/core/nds9/Bus.zig index 8e6c5cf..bb5ede8 100644 --- a/src/core/nds9/Bus.zig +++ b/src/core/nds9/Bus.zig @@ -82,6 +82,7 @@ fn _read(self: *@This(), comptime T: type, comptime mode: Mode, address: u32) T 0x0400_0000...0x04FF_FFFF => io.read(self, T, aligned_addr), 0x0500_0000...0x05FF_FFFF => readInt(T, self.makeshift_palram[aligned_addr & (2 * KiB - 1) ..][0..@sizeOf(T)]), 0x0600_0000...0x06FF_FFFF => self.ppu.vram.read(T, .nds9, aligned_addr), + 0x0700_0000...0x07FF_FFFF => readInt(T, self.ppu.oam.buf[aligned_addr..][0..byte_count]), 0xFFFF_0000...0xFFFF_FFFF => self.bios.read(T, address), else => warn("unexpected: read(T: {}, addr: 0x{X:0>8}) {} ", .{ T, address, T }), }; @@ -108,11 +109,12 @@ fn _write(self: *@This(), comptime T: type, comptime mode: Mode, address: u32, v } switch (aligned_addr) { - 0x0200_0000...0x02FF_FFFF => writeInt(T, self.main[aligned_addr & 0x003F_FFFF ..][0..byte_count], value), + 0x0200_0000...0x02FF_FFFF => writeInt(T, self.main[aligned_addr & (4 * MiB - 1) ..][0..byte_count], value), 0x0300_0000...0x03FF_FFFF => self.wram.write(T, .nds9, aligned_addr, value), 0x0400_0000...0x04FF_FFFF => io.write(self, T, aligned_addr, value), 0x0500_0000...0x05FF_FFFF => writeInt(T, self.makeshift_palram[aligned_addr & (2 * KiB - 1) ..][0..@sizeOf(T)], value), 0x0600_0000...0x06FF_FFFF => self.ppu.vram.write(T, .nds9, aligned_addr, value), + 0x0700_0000...0x07FF_FFFF => writeInt(T, self.ppu.oam.buf[aligned_addr & (2 * KiB - 1) ..][0..@sizeOf(T)], value), 0xFFFF_0000...0xFFFF_FFFF => self.bios.write(T, address, value), else => log.warn("unexpected: write(T: {}, addr: 0x{X:0>8}, value: 0x{X:0>8})", .{ T, address, value }), } diff --git a/src/core/nds9/io.zig b/src/core/nds9/io.zig index 5fe34c8..c776aca 100644 --- a/src/core/nds9/io.zig +++ b/src/core/nds9/io.zig @@ -77,6 +77,8 @@ pub fn read(bus: *const Bus, comptime T: type, address: u32) T { else => warn("unexpected: read(T: {}, addr: 0x{X:0>8}) {} ", .{ T, address, T }), }, u16 => switch (address) { + 0x0400_0006 => bus.ppu.io.nds9.vcount.raw, + // DMA Transfers 0x0400_00B0...0x0400_00DE => dma.read(T, &bus.dma, address) orelse 0x0000, 0x0400_00E0...0x0400_00EE => std.mem.readIntLittle(T, bus.io.dma_fill[address & 0xF ..][0..@sizeOf(T)]), @@ -131,6 +133,14 @@ const subset = @import("../../util.zig").subset; pub fn write(bus: *Bus, comptime T: type, address: u32, value: T) void { switch (T) { u32 => switch (address) { + 0x0400_0008 => { + bus.ppu.engines[0].bg[0].cnt.raw = @truncate(value >> 0); // 0x0400_0008 + bus.ppu.engines[0].bg[1].cnt.raw = @truncate(value >> 16); // 0x0400_000A + }, + 0x0400_000C => { + bus.ppu.engines[0].bg[2].cnt.raw = @truncate(value >> 0); // 0x0400_000A + bus.ppu.engines[0].bg[3].cnt.raw = @truncate(value >> 16); // 0x0400_000C + }, // DMA Transfers 0x0400_00B0...0x0400_00DC => dma.write(T, &bus.dma, address, value), @@ -155,6 +165,16 @@ pub fn write(bus: *Bus, comptime T: type, address: u32, value: T) void { 0x0400_0210 => bus.io.ie.raw = value, 0x0400_0214 => bus.io.irq.raw &= ~value, + 0x0400_0244 => { + bus.ppu.vram.io.cnt_e.raw = @truncate(value >> 0); // 0x0400_0244 + bus.ppu.vram.io.cnt_f.raw = @truncate(value >> 8); // 0x0400_0245 + bus.ppu.vram.io.cnt_g.raw = @truncate(value >> 16); // 0x0400_0246 + bus.io.shr.wramcnt.raw = @truncate(value >> 24); // 0x0400_0247 + + bus.ppu.vram.update(); + bus.wram.update(bus.io.shr.wramcnt); + }, + 0x0400_0290, 0x0400_0294 => { bus.io.div.numerator = subset(u64, u32, address, bus.io.div.numerator, value); bus.io.div.schedule(bus.scheduler); diff --git a/src/core/ppu.zig b/src/core/ppu.zig index a273323..fbbeb29 100644 --- a/src/core/ppu.zig +++ b/src/core/ppu.zig @@ -5,6 +5,8 @@ const Scheduler = @import("Scheduler.zig"); const System = @import("emu.zig").System; const Vram = @import("ppu/Vram.zig"); +const Oam = @import("ppu/Oam.zig"); + const EngineA = @import("ppu/engine.zig").EngineA; const EngineB = @import("ppu/engine.zig").EngineB; @@ -24,6 +26,9 @@ pub const Ppu = struct { vram: *Vram, + // FIXME: do I need a pointer here? + oam: *Oam, + engines: struct { EngineA, EngineB }, io: Io = .{}, @@ -49,12 +54,19 @@ pub const Ppu = struct { .fb = try FrameBuffer.init(allocator), .engines = .{ try EngineA.init(allocator), try EngineB.init(allocator) }, .vram = vram, + .oam = blk: { + var oam = try allocator.create(Oam); + oam.init(); + + break :blk oam; + }, }; } pub fn deinit(self: @This(), allocator: Allocator) void { self.fb.deinit(allocator); inline for (self.engines) |eng| eng.deinit(allocator); + allocator.destroy(self.oam); } pub fn drawScanline(self: *@This(), bus: *System.Bus9) void { diff --git a/src/core/ppu/Oam.zig b/src/core/ppu/Oam.zig new file mode 100644 index 0000000..e177ba3 --- /dev/null +++ b/src/core/ppu/Oam.zig @@ -0,0 +1,7 @@ +const KiB = 0x400; + +buf: [2 * KiB]u8, + +pub fn init(self: *@This()) void { + @memset(self.buf[0..], 0); +}