Compare commits

..

17 Commits

Author SHA1 Message Date
Rekai Nyangadzayi Musuka acdb270793 chore: reimplement alpha blending 2022-12-16 22:16:37 -04:00
Rekai Nyangadzayi Musuka 4ceed382ed chore(ppu): use @ptrCast in drawTextMode 2022-12-16 22:16:37 -04:00
Rekai Nyangadzayi Musuka 52ce4f3d20 chore(ppu): reimplement modes 3, 4, and 5 2022-12-16 22:16:37 -04:00
Rekai Nyangadzayi Musuka c1c8cac6e4 style(ppu): move text mode drawing to unique fn 2022-12-16 22:16:37 -04:00
Rekai Nyangadzayi Musuka be7a34f719 fix(window): proper inRange impl for window
window wrap now works (it's pretty slow though?)
2022-12-16 22:16:37 -04:00
Rekai Nyangadzayi Musuka f7a94634f9 chore: improve readability of sprite drawing code a bit 2022-12-16 22:16:37 -04:00
Rekai Nyangadzayi Musuka 7d4ab6db2c style: remove unused imports 2022-12-16 22:16:37 -04:00
Rekai Nyangadzayi Musuka 0a78587d8e chore: dont allocate not-small ?Sprite array on stack
use memset like most other allocations in this emu
2022-12-16 22:16:37 -04:00
Rekai Nyangadzayi Musuka b753ceef8e chore: move FrameBuffer struct to util.zig 2022-12-16 22:16:37 -04:00
Rekai Nyangadzayi Musuka 8963fe205b chore: move OAM, PALRAM and VRAM structs to separate files 2022-12-16 22:16:37 -04:00
Rekai Nyangadzayi Musuka e906506e16 fix: 8-bit writes to WIN PPU registers
Advance Wars depends on these registers similar to Mario Kart's 8-bit
writes to Affine Background registers:
2022-12-16 22:16:37 -04:00
Rekai Nyangadzayi Musuka 3195a45e3d chore: refactor window 2022-12-16 22:16:37 -04:00
Rekai Nyangadzayi Musuka 6aad911985 chore: crude background window impl (no affine) 2022-12-16 22:16:37 -04:00
Rekai Nyangadzayi Musuka e3b45ef794 chore: rename function (misspelt until now somehow) 2022-12-16 22:16:37 -04:00
Rekai Nyangadzayi Musuka 8e1a539e70 chore: debug read takes advantage of fastmem
deduplicate slowmem backup read handler
2022-12-15 23:18:54 -04:00
Rekai Nyangadzayi Musuka 63fa972afa chore: update dependencies
in response to zig master deprecations
2022-12-14 22:57:51 -04:00
Rekai Nyangadzayi Musuka bf95eee3f1 fix(apu): resolve bug in NR10 obscure behaviour 2022-12-05 11:08:04 -04:00
5 changed files with 51 additions and 38 deletions

@ -1 +1 @@
Subproject commit 00b43568854f14e3bab340a4e062776ecb44a727 Subproject commit 2fbd4b228516bf08348a3173f1446c7e8d75540a

@ -1 +1 @@
Subproject commit a1b01ffeab452790790034b8a0e97aa30bbeb800 Subproject commit 8a38c14266d1d00e0c3aee16b2e2b69675209147

View File

@ -197,8 +197,29 @@ fn fillTableExternalMemory(bus: *Self, addr: usize) ?*anyopaque {
return &bus.pak.buf[masked_addr]; return &bus.pak.buf[masked_addr];
} }
// TODO: Take advantage of fastmem here too?
pub fn dbgRead(self: *const Self, comptime T: type, unaligned_address: u32) T { pub fn dbgRead(self: *const Self, comptime T: type, unaligned_address: u32) T {
const bits = @typeInfo(std.math.IntFittingRange(0, page_size - 1)).Int.bits;
const page = unaligned_address >> bits;
const offset = unaligned_address & (page_size - 1);
// We're doing some serious out-of-bounds open-bus reads
if (page >= table_len) return self.openBus(T, unaligned_address);
if (self.read_table[page]) |some_ptr| {
// We have a pointer to a page, cast the pointer to it's underlying type
const Ptr = [*]const T;
const alignment = @alignOf(std.meta.Child(Ptr));
const ptr = @ptrCast(Ptr, @alignCast(alignment, some_ptr));
// Note: We don't check array length, since we force align the
// lower bits of the address as the GBA would
return ptr[forceAlign(T, offset) / @sizeOf(T)];
}
return self.dbgSlowRead(T, unaligned_address);
}
fn dbgSlowRead(self: *const Self, comptime T: type, unaligned_address: u32) T {
const page = @truncate(u8, unaligned_address >> 24); const page = @truncate(u8, unaligned_address >> 24);
const address = forceAlign(T, unaligned_address); const address = forceAlign(T, unaligned_address);
@ -210,29 +231,18 @@ pub fn dbgRead(self: *const Self, comptime T: type, unaligned_address: u32) T {
break :blk self.openBus(T, address); break :blk self.openBus(T, address);
}, },
0x02 => self.ewram.read(T, address), 0x02 => unreachable, // handled by fastmem
0x03 => self.iwram.read(T, address), 0x03 => unreachable, // handled by fastmem
0x04 => self.readIo(T, address), 0x04 => self.readIo(T, address),
// Internal Display Memory // Internal Display Memory
0x05 => self.ppu.palette.read(T, address), 0x05 => unreachable, // handled by fastmem
0x06 => self.ppu.vram.read(T, address), 0x06 => unreachable, // handled by fastmem
0x07 => self.ppu.oam.read(T, address), 0x07 => unreachable, // handled by fastmem
// External Memory (Game Pak) // External Memory (Game Pak)
0x08...0x0D => self.pak.dbgRead(T, address), 0x08...0x0D => self.pak.dbgRead(T, address),
0x0E...0x0F => blk: { 0x0E...0x0F => self.readBackup(T, unaligned_address),
const value = self.pak.backup.read(unaligned_address);
const multiplier = switch (T) {
u32 => 0x01010101,
u16 => 0x0101,
u8 => 1,
else => @compileError("Backup: Unsupported read width"),
};
break :blk @as(T, value) * multiplier;
},
else => self.openBus(T, address), else => self.openBus(T, address),
}; };
} }
@ -352,22 +362,24 @@ fn slowRead(self: *Self, comptime T: type, unaligned_address: u32) T {
// External Memory (Game Pak) // External Memory (Game Pak)
0x08...0x0D => self.pak.read(T, address), 0x08...0x0D => self.pak.read(T, address),
0x0E...0x0F => blk: { 0x0E...0x0F => self.readBackup(T, unaligned_address),
const value = self.pak.backup.read(unaligned_address);
const multiplier = switch (T) {
u32 => 0x01010101,
u16 => 0x0101,
u8 => 1,
else => @compileError("Backup: Unsupported read width"),
};
break :blk @as(T, value) * multiplier;
},
else => self.openBus(T, address), else => self.openBus(T, address),
}; };
} }
fn readBackup(self: *const Self, comptime T: type, unaligned_address: u32) T {
const value = self.pak.backup.read(unaligned_address);
const multiplier = switch (T) {
u32 => 0x01010101,
u16 => 0x0101,
u8 => 1,
else => @compileError("Backup: Unsupported read width"),
};
return @as(T, value) * multiplier;
}
pub fn write(self: *Self, comptime T: type, unaligned_address: u32, value: T) void { pub fn write(self: *Self, comptime T: type, unaligned_address: u32, value: T) void {
const bits = @typeInfo(std.math.IntFittingRange(0, page_size - 1)).Int.bits; const bits = @typeInfo(std.math.IntFittingRange(0, page_size - 1)).Int.bits;
const page = unaligned_address >> bits; const page = unaligned_address >> bits;

View File

@ -94,10 +94,9 @@ pub fn sound1CntL(self: *const Self) u8 {
pub fn setSound1CntL(self: *Self, value: u8) void { pub fn setSound1CntL(self: *Self, value: u8) void {
const new = io.Sweep{ .raw = value }; const new = io.Sweep{ .raw = value };
if (self.sweep.direction.read() and !new.direction.read()) { if (!new.direction.read()) {
// Sweep Negate bit has been cleared // If at least one (1) sweep calculation has been made with
// If At least 1 Sweep Calculation has been made since // the negate bit set (since last trigger), disable the channel
// the last trigger, the channel is immediately disabled
if (self.sweep_dev.calc_performed) self.enabled = false; if (self.sweep_dev.calc_performed) self.enabled = false;
} }

View File

@ -31,7 +31,6 @@ pub fn tick(self: *Self, ch1: *ToneSweep) void {
if (self.timer == 0) { if (self.timer == 0) {
const period = ch1.sweep.period.read(); const period = ch1.sweep.period.read();
self.timer = if (period == 0) 8 else period; self.timer = if (period == 0) 8 else period;
if (!self.calc_performed) self.calc_performed = true;
if (self.enabled and period != 0) { if (self.enabled and period != 0) {
const new_freq = self.calculate(ch1.sweep, &ch1.enabled); const new_freq = self.calculate(ch1.sweep, &ch1.enabled);
@ -52,7 +51,10 @@ pub fn calculate(self: *Self, sweep: io.Sweep, ch_enable: *bool) u12 {
const shadow_shifted = shadow >> sweep.shift.read(); const shadow_shifted = shadow >> sweep.shift.read();
const decrease = sweep.direction.read(); const decrease = sweep.direction.read();
const freq = if (decrease) shadow - shadow_shifted else shadow + shadow_shifted; const freq = if (decrease) blk: {
self.calc_performed = true;
break :blk shadow - shadow_shifted;
} else shadow + shadow_shifted;
if (freq > 0x7FF) ch_enable.* = false; if (freq > 0x7FF) ch_enable.* = false;
return freq; return freq;