add nes cartridge subsystem and 41 ines mapper variants
This commit is contained in:
@@ -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();
|
||||
}
|
||||
Reference in New Issue
Block a user