Compare commits
No commits in common. "5dbd681ba15ca969cb3dcbb90e07133c248b5f1b" and "6518fcc68b67146cf5bb8a099a4a7c67327ff6b1" have entirely different histories.
5dbd681ba1
...
6518fcc68b
|
@ -1 +1 @@
|
||||||
Subproject commit a3eefa643268617d10e47ca972c4ba5bd05f131e
|
Subproject commit 30cf951d2a4ccba3ff7ce70ceeae44780af5f1a1
|
|
@ -70,25 +70,6 @@ const arm9_clock = bus_clock * 2;
|
||||||
|
|
||||||
pub fn runFrame(nds7_group: nds7.Group, nds9_group: nds9.Group) void {
|
pub fn runFrame(nds7_group: nds7.Group, nds9_group: nds9.Group) void {
|
||||||
// TODO: might be more efficient to run them both in the same loop?
|
// TODO: might be more efficient to run them both in the same loop?
|
||||||
{
|
|
||||||
const scheduler = nds9_group.scheduler;
|
|
||||||
|
|
||||||
const cycles_per_dot = arm9_clock / dot_clock + 1;
|
|
||||||
comptime std.debug.assert(cycles_per_dot == 12);
|
|
||||||
|
|
||||||
const cycles_per_frame = 355 * 263 * cycles_per_dot;
|
|
||||||
const frame_end = scheduler.tick + cycles_per_frame;
|
|
||||||
|
|
||||||
const cpu = nds9_group.cpu;
|
|
||||||
const bus = nds9_group.bus;
|
|
||||||
|
|
||||||
while (scheduler.tick < frame_end) {
|
|
||||||
cpu.step();
|
|
||||||
|
|
||||||
if (scheduler.tick >= scheduler.next()) scheduler.handle(bus);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
const scheduler = nds7_group.scheduler;
|
const scheduler = nds7_group.scheduler;
|
||||||
|
|
||||||
|
@ -107,6 +88,25 @@ pub fn runFrame(nds7_group: nds7.Group, nds9_group: nds9.Group) void {
|
||||||
if (scheduler.tick >= scheduler.next()) scheduler.handle(bus);
|
if (scheduler.tick >= scheduler.next()) scheduler.handle(bus);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const scheduler = nds9_group.scheduler;
|
||||||
|
|
||||||
|
const cycles_per_dot = arm9_clock / dot_clock + 1;
|
||||||
|
comptime std.debug.assert(cycles_per_dot == 12);
|
||||||
|
|
||||||
|
const cycles_per_frame = 355 * 263 * cycles_per_dot;
|
||||||
|
const frame_end = scheduler.tick + cycles_per_frame;
|
||||||
|
|
||||||
|
const cpu = nds9_group.cpu;
|
||||||
|
const bus = nds9_group.bus;
|
||||||
|
|
||||||
|
while (scheduler.tick < frame_end) {
|
||||||
|
cpu.step();
|
||||||
|
|
||||||
|
if (scheduler.tick >= scheduler.next()) scheduler.handle(bus);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Perf win to allocating on the stack instead?
|
// FIXME: Perf win to allocating on the stack instead?
|
||||||
|
|
126
src/core/io.zig
126
src/core/io.zig
|
@ -22,8 +22,21 @@ pub const Io = struct {
|
||||||
/// Caller must cast the `u32` to either `nds7.IntRequest` or `nds9.IntRequest`
|
/// Caller must cast the `u32` to either `nds7.IntRequest` or `nds9.IntRequest`
|
||||||
irq: u32 = 0x0000_0000,
|
irq: u32 = 0x0000_0000,
|
||||||
|
|
||||||
/// Inter Process Communication FIFO
|
/// IPC Synchronize
|
||||||
ipc_fifo: IpcFifo = .{},
|
/// Read/Write
|
||||||
|
ipc_sync: IpcSync = .{ .raw = 0x0000_0000 },
|
||||||
|
|
||||||
|
/// IPC Fifo Control
|
||||||
|
/// Read/Write
|
||||||
|
ipc_fifo_cnt: IpcFifoCnt = .{ .raw = 0x0000_0000 },
|
||||||
|
|
||||||
|
/// IPC Send FIFO
|
||||||
|
/// Write-Only
|
||||||
|
ipc_fifo_send: u32 = 0x0000_0000,
|
||||||
|
|
||||||
|
/// IPC Receive FIFO
|
||||||
|
/// Read-Only
|
||||||
|
ipc_fifo_recv: u32 = 0x0000_0000,
|
||||||
|
|
||||||
/// Post Boot Flag
|
/// Post Boot Flag
|
||||||
/// Read/Write
|
/// Read/Write
|
||||||
|
@ -108,54 +121,6 @@ pub inline fn writeToAddressOffset(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const IpcFifo = struct {
|
|
||||||
const Sync = IpcSync;
|
|
||||||
const Control = IpcFifoCnt;
|
|
||||||
|
|
||||||
/// IPC Synchronize
|
|
||||||
/// Read/Write
|
|
||||||
sync: Sync = .{ .raw = 0x0000_0000 },
|
|
||||||
|
|
||||||
/// IPC Fifo Control
|
|
||||||
/// Read/Write
|
|
||||||
cnt: Control = .{ .raw = 0x0000_0000 },
|
|
||||||
|
|
||||||
fifo: [2]Fifo = .{ Fifo{}, Fifo{} },
|
|
||||||
|
|
||||||
const Source = enum { arm7, arm9 };
|
|
||||||
|
|
||||||
/// IPC Send FIFO
|
|
||||||
/// Write-Only
|
|
||||||
pub fn send(self: *@This(), comptime src: Source, value: u32) !void {
|
|
||||||
const idx = switch (src) {
|
|
||||||
.arm7 => 0,
|
|
||||||
.arm9 => 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!self.cnt.enable_fifos.read()) return;
|
|
||||||
|
|
||||||
try self.fifo[idx].push(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// IPC Receive FIFO
|
|
||||||
/// Read-Only
|
|
||||||
pub fn recv(self: *@This(), comptime src: Source) u32 {
|
|
||||||
const idx = switch (src) {
|
|
||||||
.arm7 => 1, // switched around on purpose
|
|
||||||
.arm9 => 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
const enabled = self.cnt.enable_fifos.read();
|
|
||||||
const val_opt = if (enabled) self.fifo[idx].pop() else self.fifo[idx].peek();
|
|
||||||
|
|
||||||
return val_opt orelse blk: {
|
|
||||||
self.cnt.send_fifo_empty.set();
|
|
||||||
|
|
||||||
break :blk 0x0000_0000;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const IpcSync = extern union {
|
const IpcSync = extern union {
|
||||||
/// Data input to IPCSYNC Bit 8->11 of remote CPU
|
/// Data input to IPCSYNC Bit 8->11 of remote CPU
|
||||||
/// Read-Only
|
/// Read-Only
|
||||||
|
@ -222,64 +187,3 @@ pub const nds9 = struct {
|
||||||
|
|
||||||
pub const PostFlag = enum(u8) { in_progress = 0, completed };
|
pub const PostFlag = enum(u8) { in_progress = 0, completed };
|
||||||
};
|
};
|
||||||
|
|
||||||
const Fifo = struct {
|
|
||||||
const Index = u8;
|
|
||||||
const Error = error{full};
|
|
||||||
const len = 0x10;
|
|
||||||
|
|
||||||
read_idx: Index = 0,
|
|
||||||
write_idx: Index = 0,
|
|
||||||
|
|
||||||
buf: [len]u32 = [_]u32{undefined} ** len,
|
|
||||||
|
|
||||||
comptime {
|
|
||||||
const max_capacity = (@as(Index, 1) << @typeInfo(Index).Int.bits - 1) - 1; // half the range of index type
|
|
||||||
|
|
||||||
std.debug.assert(std.math.isPowerOfTwo(len));
|
|
||||||
std.debug.assert(len <= max_capacity);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn reset(self: *@This()) void {
|
|
||||||
self.read_idx = 0;
|
|
||||||
self.write_idx = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn push(self: *@This(), value: u32) Error!void {
|
|
||||||
if (self.isFull()) return Error.full;
|
|
||||||
defer self.write_idx += 1;
|
|
||||||
|
|
||||||
self.buf[self.mask(self.write_idx)] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn pop(self: *@This()) ?u32 {
|
|
||||||
if (self.isEmpty()) return null;
|
|
||||||
defer self.read_idx += 1;
|
|
||||||
|
|
||||||
return self.buf[self.mask(self.read_idx)];
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn peek(self: *const @This()) ?u32 {
|
|
||||||
if (self.isEmpty()) return null;
|
|
||||||
|
|
||||||
return self.buf[self.mask(self.read_idx)];
|
|
||||||
}
|
|
||||||
|
|
||||||
fn _len(self: *const @This()) Index {
|
|
||||||
return self.write_idx - self.read_idx;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn isFull(self: *const @This()) bool {
|
|
||||||
return self._len() == self.buf.len;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn isEmpty(self: *const @This()) bool {
|
|
||||||
return self.read_idx == self.write_idx;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline fn mask(self: *const @This(), idx: Index) Index {
|
|
||||||
const _mask: Index = @intCast(self.buf.len - 1);
|
|
||||||
|
|
||||||
return idx & _mask;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
|
@ -20,21 +20,21 @@ pub const Io = struct {
|
||||||
|
|
||||||
pub fn read(bus: *const Bus, comptime T: type, address: u32) T {
|
pub fn read(bus: *const Bus, comptime T: type, address: u32) T {
|
||||||
return switch (T) {
|
return switch (T) {
|
||||||
u32 => switch (address) {
|
// zig fmt: off
|
||||||
0x0400_0208 => @intFromBool(bus.io.shared.ime),
|
u32 =>
|
||||||
0x0400_0210 => bus.io.shared.ie,
|
@as(T, read(bus, u8, address + 3)) << 24
|
||||||
0x0400_0214 => bus.io.shared.irq,
|
| @as(T, read(bus, u8, address + 2)) << 16
|
||||||
|
| @as(T, read(bus, u8, address + 1)) << 8
|
||||||
0x0410_0000 => bus.io.shared.ipc_fifo.recv(.arm7),
|
| read(bus, u8, address + 0) << 0,
|
||||||
else => warn("unexpected: read(T: {}, addr: 0x{X:0>8}) {} ", .{ T, address, T }),
|
// zig fmt: on
|
||||||
},
|
u16 => @as(T, read(bus, u8, address + 1)) << 8 | read(bus, u8, address),
|
||||||
u16 => switch (address) {
|
|
||||||
0x0400_0180 => @truncate(bus.io.shared.ipc_fifo.sync.raw),
|
|
||||||
0x0400_0184 => @truncate(bus.io.shared.ipc_fifo.cnt.raw),
|
|
||||||
else => warn("unexpected: read(T: {}, addr: 0x{X:0>8}) {} ", .{ T, address, T }),
|
|
||||||
},
|
|
||||||
u8 => switch (address) {
|
u8 => switch (address) {
|
||||||
else => warn("unexpected: read(T: {}, addr: 0x{X:0>8}) {} ", .{ T, address, T }),
|
0x0400_0180...0x0400_0183 => valueAtAddressOffset(u32, address, bus.io.shared.ipc_sync.raw),
|
||||||
|
0x0400_0184...0x0400_0187 => valueAtAddressOffset(u32, address, bus.io.shared.ipc_fifo_cnt.raw),
|
||||||
|
|
||||||
|
0x0400_0208...0x0400_020B => valueAtAddressOffset(u32, address, @intFromBool(bus.io.shared.ime)),
|
||||||
|
|
||||||
|
else => warn("unexpected read: 0x{X:0>8}", .{address}),
|
||||||
},
|
},
|
||||||
else => @compileError(T ++ " is an unsupported bus read type"),
|
else => @compileError(T ++ " is an unsupported bus read type"),
|
||||||
};
|
};
|
||||||
|
@ -42,26 +42,24 @@ pub fn read(bus: *const Bus, comptime T: type, address: u32) T {
|
||||||
|
|
||||||
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 => {
|
||||||
0x0400_0208 => bus.io.shared.ime = value & 1 == 1,
|
write(bus, u8, address + 3, @as(u8, @truncate(value >> 24)));
|
||||||
0x0400_0210 => bus.io.shared.ie = value,
|
write(bus, u8, address + 2, @as(u8, @truncate(value >> 16)));
|
||||||
0x0400_0214 => bus.io.shared.irq = value,
|
write(bus, u8, address + 1, @as(u8, @truncate(value >> 8)));
|
||||||
|
write(bus, u8, address + 0, @as(u8, @truncate(value >> 0)));
|
||||||
0x0400_0188 => bus.io.shared.ipc_fifo.send(.arm7, value) catch |e| std.debug.panic("FIFO error: {}", .{e}),
|
|
||||||
else => log.warn("unexpected: write(T: {}, addr: 0x{X:0>8}, value: 0x{X:0>8})", .{ T, address, value }),
|
|
||||||
},
|
},
|
||||||
u16 => switch (address) {
|
u16 => {
|
||||||
0x0400_0180 => bus.io.shared.ipc_fifo.sync.raw = blk: {
|
write(bus, u8, address + 1, @as(u8, @truncate(value >> 8)));
|
||||||
const ret = value & ~@as(u16, 0xF) | (bus.io.shared.ipc_fifo.sync.raw & 0xF);
|
write(bus, u8, address + 0, @as(u8, @truncate(value >> 0)));
|
||||||
log.debug("IPCFIFOSYNC <- 0x{X:0>8}", .{ret});
|
|
||||||
|
|
||||||
break :blk ret;
|
|
||||||
},
|
|
||||||
0x0400_0184 => bus.io.shared.ipc_fifo.cnt.raw = value,
|
|
||||||
else => log.warn("unexpected: write(T: {}, addr: 0x{X:0>8}, value: 0x{X:0>8})", .{ T, address, value }),
|
|
||||||
},
|
},
|
||||||
u8 => switch (address) {
|
u8 => switch (address) {
|
||||||
else => log.warn("unexpected: write(T: {}, addr: 0x{X:0>8}, value: 0x{X:0>8})", .{ T, address, value }),
|
0x0400_0180...0x0400_0183 => writeToAddressOffset(&bus.io.shared.ipc_sync.raw, address, value),
|
||||||
|
0x0400_0184...0x0400_0187 => writeToAddressOffset(&bus.io.shared.ipc_fifo_cnt.raw, address, value),
|
||||||
|
|
||||||
|
0x0400_0208 => bus.io.shared.ime = value & 1 == 1,
|
||||||
|
0x0400_0209...0x0400_020B => {}, // unused bytes from IME
|
||||||
|
|
||||||
|
else => log.warn("unexpected write: 0x{X:}u8 -> 0x{X:0>8}", .{ value, address }),
|
||||||
},
|
},
|
||||||
else => @compileError(T ++ " is an unsupported bus write type"),
|
else => @compileError(T ++ " is an unsupported bus write type"),
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,24 +27,26 @@ pub const Io = struct {
|
||||||
|
|
||||||
pub fn read(bus: *const Bus, comptime T: type, address: u32) T {
|
pub fn read(bus: *const Bus, comptime T: type, address: u32) T {
|
||||||
return switch (T) {
|
return switch (T) {
|
||||||
u32 => switch (address) {
|
// zig fmt: off
|
||||||
0x0400_0208 => @intFromBool(bus.io.shared.ime),
|
u32 =>
|
||||||
0x0400_0210 => bus.io.shared.ie,
|
@as(T, read(bus, u8, address + 3)) << 24
|
||||||
0x0400_0214 => bus.io.shared.irq,
|
| @as(T, read(bus, u8, address + 2)) << 16
|
||||||
|
| @as(T, read(bus, u8, address + 1)) << 8
|
||||||
0x0410_0000 => bus.io.shared.ipc_fifo.recv(.arm9),
|
| read(bus, u8, address + 0) << 0,
|
||||||
else => warn("unexpected: read(T: {}, addr: 0x{X:0>8}) {} ", .{ T, address, T }),
|
// zig fmt: on
|
||||||
},
|
u16 => @as(T, read(bus, u8, address + 1)) << 8 | read(bus, u8, address),
|
||||||
u16 => switch (address) {
|
|
||||||
0x0400_0004 => bus.ppu.io.dispstat.raw,
|
|
||||||
0x0400_0130 => bus.io.keyinput.load(.Monotonic),
|
|
||||||
|
|
||||||
0x0400_0180 => @truncate(bus.io.shared.ipc_fifo.sync.raw),
|
|
||||||
0x0400_0184 => @truncate(bus.io.shared.ipc_fifo.cnt.raw),
|
|
||||||
else => warn("unexpected: read(T: {}, addr: 0x{X:0>8}) {} ", .{ T, address, T }),
|
|
||||||
},
|
|
||||||
u8 => switch (address) {
|
u8 => switch (address) {
|
||||||
else => warn("unexpected: read(T: {}, addr: 0x{X:0>8}) {} ", .{ T, address, T }),
|
0x0400_0000...0x0400_0003 => valueAtAddressOffset(u32, address, bus.ppu.io.dispcnt_a.raw),
|
||||||
|
0x0400_0004...0x0400_0005 => valueAtAddressOffset(u16, address, bus.ppu.io.dispstat.raw),
|
||||||
|
|
||||||
|
0x0400_0130...0x0400_0131 => valueAtAddressOffset(u16, address, bus.io.keyinput.load(.Monotonic)),
|
||||||
|
0x0400_0180...0x0400_0183 => valueAtAddressOffset(u32, address, bus.io.shared.ipc_sync.raw),
|
||||||
|
0x0400_0184...0x0400_0187 => valueAtAddressOffset(u32, address, bus.io.shared.ipc_fifo_cnt.raw),
|
||||||
|
|
||||||
|
0x0400_0208...0x0400_020B => valueAtAddressOffset(u32, address, @intFromBool(bus.io.shared.ime)),
|
||||||
|
|
||||||
|
0x0400_0304...0x0400_0307 => valueAtAddressOffset(u32, address, bus.io.powcnt.raw),
|
||||||
|
else => warn("unexpected read: 0x{X:0>8}", .{address}),
|
||||||
},
|
},
|
||||||
else => @compileError(T ++ " is an unsupported bus read type"),
|
else => @compileError(T ++ " is an unsupported bus read type"),
|
||||||
};
|
};
|
||||||
|
@ -52,51 +54,32 @@ pub fn read(bus: *const Bus, comptime T: type, address: u32) T {
|
||||||
|
|
||||||
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 => {
|
||||||
0x0400_0000 => bus.ppu.io.dispcnt_a.raw = value,
|
write(bus, u8, address + 3, @as(u8, @truncate(value >> 24)));
|
||||||
0x0400_0180 => bus.io.shared.ipc_fifo.sync.raw = blk: {
|
write(bus, u8, address + 2, @as(u8, @truncate(value >> 16)));
|
||||||
const ret = value & ~@as(u32, 0xF) | (bus.io.shared.ipc_fifo.sync.raw & 0xF);
|
write(bus, u8, address + 1, @as(u8, @truncate(value >> 8)));
|
||||||
log.debug("IPCFIFOSYNC <- 0x{X:0>8}", .{ret});
|
write(bus, u8, address + 0, @as(u8, @truncate(value >> 0)));
|
||||||
|
|
||||||
break :blk ret;
|
|
||||||
},
|
},
|
||||||
0x0400_0184 => bus.io.shared.ipc_fifo.cnt.raw = value,
|
u16 => {
|
||||||
0x0400_0188 => bus.io.shared.ipc_fifo.send(.arm9, value) catch |e| std.debug.panic("IPC FIFO Error: {}", .{e}),
|
write(bus, u8, address + 1, @as(u8, @truncate(value >> 8)));
|
||||||
|
write(bus, u8, address + 0, @as(u8, @truncate(value >> 0)));
|
||||||
0x0400_0240 => {
|
|
||||||
bus.ppu.io.vramcnt_a.raw = @truncate(value >> 0); // 0x0400_0240
|
|
||||||
bus.ppu.io.vramcnt_b.raw = @truncate(value >> 8); // 0x0400_0241
|
|
||||||
bus.ppu.io.vramcnt_c.raw = @truncate(value >> 16); // 0x0400_0242
|
|
||||||
bus.ppu.io.vramcnt_d.raw = @truncate(value >> 24); // 0x0400_0243
|
|
||||||
},
|
|
||||||
|
|
||||||
0x0400_0208 => bus.io.shared.ime = value & 1 == 1,
|
|
||||||
0x0400_0210 => bus.io.shared.ie = value,
|
|
||||||
0x0400_0214 => bus.io.shared.irq = value,
|
|
||||||
|
|
||||||
0x0400_0304 => bus.io.powcnt.raw = value,
|
|
||||||
|
|
||||||
else => log.warn("unexpected: write(T: {}, addr: 0x{X:0>8}, value: 0x{X:0>8})", .{ T, address, value }),
|
|
||||||
},
|
|
||||||
u16 => switch (address) {
|
|
||||||
0x0400_0180 => bus.io.shared.ipc_fifo.sync.raw = blk: {
|
|
||||||
const ret = value & ~@as(u16, 0xF) | (bus.io.shared.ipc_fifo.sync.raw & 0xF);
|
|
||||||
log.debug("IPCFIFOSYNC <- 0x{X:0>8}", .{ret});
|
|
||||||
|
|
||||||
break :blk ret;
|
|
||||||
},
|
|
||||||
0x0400_0184 => bus.io.shared.ipc_fifo.cnt.raw = value,
|
|
||||||
0x0400_0208 => bus.io.shared.ime = value & 1 == 1,
|
|
||||||
|
|
||||||
else => log.warn("unexpected: write(T: {}, addr: 0x{X:0>8}, value: 0x{X:0>8})", .{ T, address, value }),
|
|
||||||
},
|
},
|
||||||
u8 => switch (address) {
|
u8 => switch (address) {
|
||||||
|
0x0400_0000...0x0400_0003 => writeToAddressOffset(&bus.ppu.io.dispcnt_a.raw, address, value),
|
||||||
|
|
||||||
|
0x0400_0180...0x0400_0183 => writeToAddressOffset(&bus.io.shared.ipc_sync.raw, address, value),
|
||||||
|
0x0400_0184...0x0400_0187 => writeToAddressOffset(&bus.io.shared.ipc_fifo_cnt.raw, address, value),
|
||||||
|
|
||||||
|
0x0400_0208 => bus.io.shared.ime = value & 1 == 1,
|
||||||
|
0x0400_0209...0x0400_020B => {}, // unused bytes from IME
|
||||||
|
|
||||||
0x0400_0240 => bus.ppu.io.vramcnt_a.raw = value,
|
0x0400_0240 => bus.ppu.io.vramcnt_a.raw = value,
|
||||||
0x0400_0241 => bus.ppu.io.vramcnt_b.raw = value,
|
0x0400_0241 => bus.ppu.io.vramcnt_b.raw = value,
|
||||||
0x0400_0242 => bus.ppu.io.vramcnt_c.raw = value,
|
0x0400_0242 => bus.ppu.io.vramcnt_c.raw = value,
|
||||||
0x0400_0243 => bus.ppu.io.vramcnt_d.raw = value,
|
0x0400_0243 => bus.ppu.io.vramcnt_d.raw = value,
|
||||||
|
|
||||||
else => log.warn("unexpected: write(T: {}, addr: 0x{X:0>8}, value: 0x{X:0>8})", .{ T, address, value }),
|
0x0400_0304...0x0400_0307 => writeToAddressOffset(&bus.io.powcnt.raw, address, value),
|
||||||
|
else => log.warn("unexpected write: 0x{X:}u8 -> 0x{X:0>8}", .{ value, address }),
|
||||||
},
|
},
|
||||||
else => @compileError(T ++ " is an unsupported bus write type"),
|
else => @compileError(T ++ " is an unsupported bus write type"),
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue