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