| 1 | #include "cpu.hpp" |
| 2 | #include "ppu.hpp" |
| 3 | #include "mappers/mapper4.hpp" |
| 4 | |
| 5 | |
| 6 | void Mapper4::apply() |
| 7 | { |
| 8 | map_prg<8>(1, regs[7]); |
| 9 | |
| 10 | // PRG Mode 0: |
| 11 | if (!(reg8000 & (1 << 6))) |
| 12 | { |
| 13 | map_prg<8>(0, regs[6]); |
| 14 | map_prg<8>(2, -2); |
| 15 | } |
| 16 | // PRG Mode 1: |
| 17 | else |
| 18 | { |
| 19 | map_prg<8>(0, -2); |
| 20 | map_prg<8>(2, regs[6]); |
| 21 | } |
| 22 | |
| 23 | // CHR Mode 0: |
| 24 | if (!(reg8000 & (1 << 7))) |
| 25 | { |
| 26 | map_chr<2>(0, regs[0] >> 1); |
| 27 | map_chr<2>(1, regs[1] >> 1); |
| 28 | for (int i = 0; i < 4; i++) |
| 29 | map_chr<1>(4 + i, regs[2 + i]); |
| 30 | } |
| 31 | // CHR Mode 1: |
| 32 | else |
| 33 | { |
| 34 | for (int i = 0; i < 4; i++) |
| 35 | map_chr<1>(i, regs[2 + i]); |
| 36 | map_chr<2>(2, regs[0] >> 1); |
| 37 | map_chr<2>(3, regs[1] >> 1); |
| 38 | } |
| 39 | |
| 40 | set_mirroring(horizMirroring ? PPU::HORIZONTAL : PPU::VERTICAL); |
| 41 | } |
| 42 | |
| 43 | u8 Mapper4::write(u16 addr, u8 v) |
| 44 | { |
| 45 | if (addr < 0x8000) |
| 46 | prgRam[addr - 0x6000] = v; |
| 47 | else if (addr & 0x8000) |
| 48 | { |
| 49 | switch (addr & 0xE001) |
| 50 | { |
| 51 | case 0x8000: reg8000 = v; break; |
| 52 | case 0x8001: regs[reg8000 & 0b111] = v; break; |
| 53 | case 0xA000: horizMirroring = v & 1; break; |
| 54 | case 0xC000: irqPeriod = v; break; |
| 55 | case 0xC001: irqCounter = 0; break; |
| 56 | case 0xE000: CPU::set_irq(irqEnabled = false); break; |
| 57 | case 0xE001: irqEnabled = true; break; |
| 58 | } |
| 59 | apply(); |
| 60 | } |
| 61 | return v; |
| 62 | } |
| 63 | |
| 64 | u8 Mapper4::chr_write(u16 addr, u8 v) |
| 65 | { |
| 66 | return chr[addr] = v; |
| 67 | } |
| 68 | |
| 69 | void Mapper4::signal_scanline() |
| 70 | { |
| 71 | if (irqCounter == 0) |
| 72 | irqCounter = irqPeriod; |
| 73 | else |
| 74 | irqCounter--; |
| 75 | |
| 76 | if (irqEnabled and irqCounter == 0) |
| 77 | CPU::set_irq(); |
| 78 | } |
| 79 | |