Compare commits
14 Commits
acdb270793
...
23f5d676d4
Author | SHA1 | Date |
---|---|---|
Rekai Nyangadzayi Musuka | 23f5d676d4 | |
Rekai Nyangadzayi Musuka | 4ccacb0754 | |
Rekai Nyangadzayi Musuka | e67dc9b7de | |
Rekai Nyangadzayi Musuka | f9ca005faf | |
Rekai Nyangadzayi Musuka | 11b905dc82 | |
Rekai Nyangadzayi Musuka | 5d3435757c | |
Rekai Nyangadzayi Musuka | d705137f24 | |
Rekai Nyangadzayi Musuka | 2c6fe879ad | |
Rekai Nyangadzayi Musuka | 24905e8096 | |
Rekai Nyangadzayi Musuka | cab7816ce5 | |
Rekai Nyangadzayi Musuka | 6b6614cfa7 | |
Rekai Nyangadzayi Musuka | 106a3f8b4d | |
Rekai Nyangadzayi Musuka | 918df2743e | |
Rekai Nyangadzayi Musuka | 78c5160897 |
|
@ -1 +1 @@
|
||||||
Subproject commit 2fbd4b228516bf08348a3173f1446c7e8d75540a
|
Subproject commit 00b43568854f14e3bab340a4e062776ecb44a727
|
|
@ -1 +1 @@
|
||||||
Subproject commit 8a38c14266d1d00e0c3aee16b2e2b69675209147
|
Subproject commit a1b01ffeab452790790034b8a0e97aa30bbeb800
|
|
@ -197,29 +197,8 @@ 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);
|
||||||
|
|
||||||
|
@ -231,18 +210,29 @@ fn dbgSlowRead(self: *const Self, comptime T: type, unaligned_address: u32) T {
|
||||||
|
|
||||||
break :blk self.openBus(T, address);
|
break :blk self.openBus(T, address);
|
||||||
},
|
},
|
||||||
0x02 => unreachable, // handled by fastmem
|
0x02 => self.ewram.read(T, address),
|
||||||
0x03 => unreachable, // handled by fastmem
|
0x03 => self.iwram.read(T, address),
|
||||||
0x04 => self.readIo(T, address),
|
0x04 => self.readIo(T, address),
|
||||||
|
|
||||||
// Internal Display Memory
|
// Internal Display Memory
|
||||||
0x05 => unreachable, // handled by fastmem
|
0x05 => self.ppu.palette.read(T, address),
|
||||||
0x06 => unreachable, // handled by fastmem
|
0x06 => self.ppu.vram.read(T, address),
|
||||||
0x07 => unreachable, // handled by fastmem
|
0x07 => self.ppu.oam.read(T, address),
|
||||||
|
|
||||||
// External Memory (Game Pak)
|
// External Memory (Game Pak)
|
||||||
0x08...0x0D => self.pak.dbgRead(T, address),
|
0x08...0x0D => self.pak.dbgRead(T, address),
|
||||||
0x0E...0x0F => self.readBackup(T, unaligned_address),
|
0x0E...0x0F => blk: {
|
||||||
|
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),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -362,12 +352,7 @@ 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 => self.readBackup(T, unaligned_address),
|
0x0E...0x0F => blk: {
|
||||||
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 value = self.pak.backup.read(unaligned_address);
|
||||||
|
|
||||||
const multiplier = switch (T) {
|
const multiplier = switch (T) {
|
||||||
|
@ -377,7 +362,10 @@ fn readBackup(self: *const Self, comptime T: type, unaligned_address: u32) T {
|
||||||
else => @compileError("Backup: Unsupported read width"),
|
else => @compileError("Backup: Unsupported read width"),
|
||||||
};
|
};
|
||||||
|
|
||||||
return @as(T, value) * multiplier;
|
break :blk @as(T, value) * multiplier;
|
||||||
|
},
|
||||||
|
else => self.openBus(T, address),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
||||||
|
|
|
@ -94,9 +94,10 @@ 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 (!new.direction.read()) {
|
if (self.sweep.direction.read() and !new.direction.read()) {
|
||||||
// If at least one (1) sweep calculation has been made with
|
// Sweep Negate bit has been cleared
|
||||||
// the negate bit set (since last trigger), disable the channel
|
// If At least 1 Sweep Calculation has been made since
|
||||||
|
// 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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@ 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);
|
||||||
|
@ -51,10 +52,7 @@ 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) blk: {
|
const freq = if (decrease) shadow - shadow_shifted else shadow + shadow_shifted;
|
||||||
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;
|
||||||
|
|
Loading…
Reference in New Issue