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; }