Files
6soz/src/system/nes/mapper/mapper76.zig
T

92 lines
2.1 KiB
Zig

const types = @import("types.zig");
const Mirroring = types.Mirroring;
const Mapper76 = @This();
bank_select: u8 = 0,
bank_registers: [8]u8 = [_]u8{0} ** 8,
prg_bank_count: usize,
chr_bank_count: usize,
fixed_mirroring: Mirroring,
pub fn init(
prg_size: usize,
chr_size: usize,
mirroring_mode: Mirroring,
) Mapper76 {
return .{
.prg_bank_count = prg_size / 0x2000,
.chr_bank_count = if (chr_size > 0) chr_size / 0x0800 else 1,
.fixed_mirroring = mirroring_mode,
};
}
pub fn cpuMapRead(
self: *const Mapper76,
address: u16,
) ?usize {
if (address < 0x8000) return null;
const offset = @as(usize, address & 0x1fff);
const last_bank = self.prg_bank_count - 1;
const second_last_bank = self.prg_bank_count - 2;
const r6 = @as(usize, self.bank_registers[6]) % self.prg_bank_count;
const r7 = @as(usize, self.bank_registers[7]) % self.prg_bank_count;
switch ((address - 0x8000) / 0x2000) {
0 => return r6 * 0x2000 + offset,
1 => return r7 * 0x2000 + offset,
2 => return second_last_bank * 0x2000 + offset,
3 => return last_bank * 0x2000 + offset,
else => unreachable,
}
}
pub fn cpuWrite(
self: *Mapper76,
address: u16,
value: u8,
) void {
if (address < 0x8000) return;
if ((address & 1) == 0) {
self.bank_select = value & 0x07;
} else {
self.bank_registers[self.bank_select] = value;
}
}
pub fn ppuMapRead(
self: *const Mapper76,
address: u16,
) ?usize {
if (address >= 0x2000) return null;
const offset = @as(usize, address & 0x07ff);
const slot = address / 0x0800;
const reg_idx = @as(usize, 2 + slot);
const bank = (@as(usize, self.bank_registers[reg_idx])) % self.chr_bank_count;
return bank * 0x0800 + offset;
}
pub fn ppuMapWrite(
self: *const Mapper76,
address: u16,
) ?usize {
return self.ppuMapRead(address);
}
pub fn mirroring(
self: *const Mapper76,
) Mirroring {
return self.fixed_mirroring;
}
pub fn irqAsserted(
_: *const Mapper76,
) bool {
return false;
}