Compare commits

...

2 Commits

Author SHA1 Message Date
Rekai Nyangadzayi Musuka f55b733646 fix: pass more test roms 2023-12-27 16:29:23 -06:00
Rekai Nyangadzayi Musuka 51076597e8 feat: implement Oam buffer 2023-12-27 16:02:39 -06:00
5 changed files with 52 additions and 3 deletions

View File

@ -77,11 +77,12 @@ fn _read(self: *@This(), comptime T: type, comptime mode: Mode, address: u32) T
} }
return switch (aligned_addr) { return switch (aligned_addr) {
0x0200_0000...0x02FF_FFFF => readInt(T, self.main[aligned_addr & 0x003F_FFFF ..][0..byte_count]), 0x0200_0000...0x02FF_FFFF => readInt(T, self.main[aligned_addr & (4 * MiB - 1) ..][0..byte_count]),
0x0300_0000...0x03FF_FFFF => self.wram.read(T, .nds9, aligned_addr), 0x0300_0000...0x03FF_FFFF => self.wram.read(T, .nds9, aligned_addr),
0x0400_0000...0x04FF_FFFF => io.read(self, T, aligned_addr), 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)]), 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), 0x0600_0000...0x06FF_FFFF => self.ppu.vram.read(T, .nds9, aligned_addr),
0x0700_0000...0x07FF_FFFF => readInt(T, self.ppu.oam.buf[aligned_addr & (2 * KiB - 1) ..][0..byte_count]),
0xFFFF_0000...0xFFFF_FFFF => self.bios.read(T, address), 0xFFFF_0000...0xFFFF_FFFF => self.bios.read(T, address),
else => warn("unexpected: read(T: {}, addr: 0x{X:0>8}) {} ", .{ T, address, T }), 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) { 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), 0x0300_0000...0x03FF_FFFF => self.wram.write(T, .nds9, aligned_addr, value),
0x0400_0000...0x04FF_FFFF => io.write(self, T, 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), 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), 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), 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 }), else => log.warn("unexpected: write(T: {}, addr: 0x{X:0>8}, value: 0x{X:0>8})", .{ T, address, value }),
} }

View File

@ -219,7 +219,7 @@ fn Controller(comptime id: u2) type {
const start_timing: Kind = @enumFromInt(new.start_timing.read()); const start_timing: Kind = @enumFromInt(new.start_timing.read());
switch (start_timing) { switch (start_timing) {
.immediate, .vblank => {}, .immediate, .vblank, .hblank => {},
else => log.err("TODO: Implement DMA({}) {s} mode", .{ id, @tagName(start_timing) }), else => log.err("TODO: Implement DMA({}) {s} mode", .{ id, @tagName(start_timing) }),
} }

View File

@ -65,6 +65,7 @@ pub fn read(bus: *const Bus, comptime T: type, address: u32) T {
0x0400_0210 => bus.io.ie.raw, 0x0400_0210 => bus.io.ie.raw,
0x0400_0214 => bus.io.irq.raw, 0x0400_0214 => bus.io.irq.raw,
0x0400_0280 => bus.io.div.cnt.raw,
0x0400_02A0, 0x0400_02A4 => @truncate(bus.io.div.result >> shift(u64, address)), 0x0400_02A0, 0x0400_02A4 => @truncate(bus.io.div.result >> shift(u64, address)),
0x0400_02A8, 0x0400_02AC => @truncate(bus.io.div.remainder >> shift(u64, address)), 0x0400_02A8, 0x0400_02AC => @truncate(bus.io.div.remainder >> shift(u64, address)),
0x0400_02B4 => @truncate(bus.io.sqrt.result), 0x0400_02B4 => @truncate(bus.io.sqrt.result),
@ -77,6 +78,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 }), else => warn("unexpected: read(T: {}, addr: 0x{X:0>8}) {} ", .{ T, address, T }),
}, },
u16 => switch (address) { u16 => switch (address) {
0x0400_0006 => bus.ppu.io.nds9.vcount.raw,
// DMA Transfers // DMA Transfers
0x0400_00B0...0x0400_00DE => dma.read(T, &bus.dma, address) orelse 0x0000, 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)]), 0x0400_00E0...0x0400_00EE => std.mem.readIntLittle(T, bus.io.dma_fill[address & 0xF ..][0..@sizeOf(T)]),
@ -131,6 +134,14 @@ const subset = @import("../../util.zig").subset;
pub fn write(bus: *Bus, comptime T: type, address: u32, value: T) void { pub fn write(bus: *Bus, comptime T: type, address: u32, value: T) void {
switch (T) { switch (T) {
u32 => switch (address) { 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 // DMA Transfers
0x0400_00B0...0x0400_00DC => dma.write(T, &bus.dma, address, value), 0x0400_00B0...0x0400_00DC => dma.write(T, &bus.dma, address, value),
@ -155,6 +166,18 @@ pub fn write(bus: *Bus, comptime T: type, address: u32, value: T) void {
0x0400_0210 => bus.io.ie.raw = value, 0x0400_0210 => bus.io.ie.raw = value,
0x0400_0214 => bus.io.irq.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_0280 => bus.io.div.cnt.raw = value,
0x0400_0290, 0x0400_0294 => { 0x0400_0290, 0x0400_0294 => {
bus.io.div.numerator = subset(u64, u32, address, bus.io.div.numerator, value); bus.io.div.numerator = subset(u64, u32, address, bus.io.div.numerator, value);
bus.io.div.schedule(bus.scheduler); bus.io.div.schedule(bus.scheduler);
@ -165,6 +188,11 @@ pub fn write(bus: *Bus, comptime T: type, address: u32, value: T) void {
bus.io.div.schedule(bus.scheduler); bus.io.div.schedule(bus.scheduler);
}, },
0x0400_02A0, 0x0400_02A4 => bus.io.div.result = subset(u64, u32, address, bus.io.div.result, value),
0x0400_02A8, 0x0400_02AC => bus.io.div.remainder = subset(u64, u32, address, bus.io.div.remainder, value),
0x0400_02B0 => bus.io.sqrt.cnt.raw = value,
0x0400_02B8, 0x0400_02BC => { 0x0400_02B8, 0x0400_02BC => {
bus.io.sqrt.param = subset(u64, u32, address, bus.io.sqrt.param, value); bus.io.sqrt.param = subset(u64, u32, address, bus.io.sqrt.param, value);
bus.io.sqrt.schedule(bus.scheduler); bus.io.sqrt.schedule(bus.scheduler);

View File

@ -5,6 +5,8 @@ const Scheduler = @import("Scheduler.zig");
const System = @import("emu.zig").System; const System = @import("emu.zig").System;
const Vram = @import("ppu/Vram.zig"); const Vram = @import("ppu/Vram.zig");
const Oam = @import("ppu/Oam.zig");
const EngineA = @import("ppu/engine.zig").EngineA; const EngineA = @import("ppu/engine.zig").EngineA;
const EngineB = @import("ppu/engine.zig").EngineB; const EngineB = @import("ppu/engine.zig").EngineB;
@ -24,6 +26,9 @@ pub const Ppu = struct {
vram: *Vram, vram: *Vram,
// FIXME: do I need a pointer here?
oam: *Oam,
engines: struct { EngineA, EngineB }, engines: struct { EngineA, EngineB },
io: Io = .{}, io: Io = .{},
@ -49,12 +54,19 @@ pub const Ppu = struct {
.fb = try FrameBuffer.init(allocator), .fb = try FrameBuffer.init(allocator),
.engines = .{ try EngineA.init(allocator), try EngineB.init(allocator) }, .engines = .{ try EngineA.init(allocator), try EngineB.init(allocator) },
.vram = vram, .vram = vram,
.oam = blk: {
var oam = try allocator.create(Oam);
oam.init();
break :blk oam;
},
}; };
} }
pub fn deinit(self: @This(), allocator: Allocator) void { pub fn deinit(self: @This(), allocator: Allocator) void {
self.fb.deinit(allocator); self.fb.deinit(allocator);
inline for (self.engines) |eng| eng.deinit(allocator); inline for (self.engines) |eng| eng.deinit(allocator);
allocator.destroy(self.oam);
} }
pub fn drawScanline(self: *@This(), bus: *System.Bus9) void { pub fn drawScanline(self: *@This(), bus: *System.Bus9) void {

7
src/core/ppu/Oam.zig Normal file
View File

@ -0,0 +1,7 @@
const KiB = 0x400;
buf: [2 * KiB]u8,
pub fn init(self: *@This()) void {
@memset(self.buf[0..], 0);
}