1#include "cpu.hpp"
2#include "ppu.hpp"
3#include "mappers/mapper4.hpp"
4
5
6void 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
43u8 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
64u8 Mapper4::chr_write(u16 addr, u8 v)
65{
66 return chr[addr] = v;
67}
68
69void 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