add nes cartridge subsystem and 41 ines mapper variants

This commit is contained in:
2026-08-14 06:48:16 +02:00
parent 42f20478bd
commit 04fb7bcc1f
41 changed files with 5042 additions and 0 deletions
+113
View File
@@ -0,0 +1,113 @@
const types = @import("types.zig");
const Mirroring = types.Mirroring;
const Mmc3 = @import("mmc3.zig");
const Mapper119 = @This();
mmc3: Mmc3,
pub fn init(
prg_size: usize,
chr_size: usize,
) Mapper119 {
return .{
.mmc3 = Mmc3.init(prg_size, chr_size),
};
}
pub fn cpuMapRead(
self: *const Mapper119,
address: u16,
) ?usize {
return self.mmc3.cpuMapRead(address);
}
pub fn cpuWrite(
self: *Mapper119,
address: u16,
value: u8,
) void {
self.mmc3.cpuWrite(address, value);
}
pub fn ppuMapRead(
self: *Mapper119,
address: u16,
) ?usize {
if (address >= 0x2000) return null;
const bank_val = self.getChrBankValue(address);
const offset = (address % 0x0400);
if ((bank_val & 0x40) != 0) {
// Bit 6 is set -> Route to CHR RAM
const ram_bank = @as(usize, bank_val & 7);
return 0x80000000 | (ram_bank * 0x0400 + offset);
} else {
// Route to CHR ROM
return self.mmc3.ppuMapRead(address);
}
}
pub fn ppuMapWrite(
self: *const Mapper119,
address: u16,
) ?usize {
if (address >= 0x2000) return null;
const bank_val = self.getChrBankValue(address);
const offset = (address % 0x0400);
if ((bank_val & 0x40) != 0) {
// Bit 6 is set -> Route write to CHR RAM
const ram_bank = @as(usize, bank_val & 7);
return 0x80000000 | (ram_bank * 0x0400 + offset);
} else {
return self.mmc3.ppuMapWrite(address);
}
}
fn getChrBankValue(self: *const Mapper119, address: u16) u8 {
const chr_mode = (self.mmc3.bank_select & 0x80) != 0;
const addr_k = address / 0x0400;
if (!chr_mode) {
return switch (addr_k) {
0, 1 => (self.mmc3.bank_registers[0] & 0xfe) + @as(u8, @intCast(addr_k & 1)),
2, 3 => (self.mmc3.bank_registers[1] & 0xfe) + @as(u8, @intCast(addr_k & 1)),
4 => self.mmc3.bank_registers[2],
5 => self.mmc3.bank_registers[3],
6 => self.mmc3.bank_registers[4],
7 => self.mmc3.bank_registers[5],
else => unreachable,
};
} else {
return switch (addr_k) {
0 => self.mmc3.bank_registers[2],
1 => self.mmc3.bank_registers[3],
2 => self.mmc3.bank_registers[4],
3 => self.mmc3.bank_registers[5],
4, 5 => (self.mmc3.bank_registers[0] & 0xfe) + @as(u8, @intCast(addr_k & 1)),
6, 7 => (self.mmc3.bank_registers[1] & 0xfe) + @as(u8, @intCast(addr_k & 1)),
else => unreachable,
};
}
}
pub fn mirroring(
self: *const Mapper119,
) Mirroring {
return self.mmc3.mirroring();
}
pub fn irqAsserted(
self: *const Mapper119,
) bool {
return self.mmc3.irqAsserted();
}
pub fn handleScanline(
self: *Mapper119,
) void {
self.mmc3.handleScanline();
}