1+ #pragma once
2+ #include " stdafx.h"
3+ #include " BaseMapper.h"
4+ #include " CPU.h"
5+ #include " A12Watcher.h"
6+
7+ class Mapper413 : public BaseMapper
8+ {
9+ private:
10+ uint32_t _serialAddress;
11+ uint8_t _serialControl;
12+
13+ uint8_t _irqCounter;
14+ uint8_t _irqReloadValue;
15+ bool _irqEnabled;
16+
17+ A12Watcher _a12Watcher;
18+
19+ protected:
20+ virtual uint16_t GetPRGPageSize () override { return 0x1000 ; }
21+ virtual uint16_t GetCHRPageSize () override { return 0x1000 ; }
22+ virtual bool AllowRegisterRead () override { return true ; }
23+
24+ void InitMapper () override
25+ {
26+ _serialAddress = 0 ;
27+ _serialControl = 0 ;
28+
29+ _irqCounter = 0 ;
30+ _irqReloadValue = 0 ;
31+ _irqEnabled = false ;
32+
33+ SetCpuMemoryMapping (0x5000 , 0x5FFF , 1 , PrgMemoryType::PrgRom);
34+ SetCpuMemoryMapping (0x6000 , 0x6FFF , 0 , PrgMemoryType::PrgRom);
35+ SetCpuMemoryMapping (0x7000 , 0x7FFF , 1 , PrgMemoryType::PrgRom);
36+
37+ SelectPrgPage2x (0 , 0 );
38+ SelectPrgPage2x (1 , 0 );
39+ SelectPRGPage (5 , 0x07 );
40+ SelectPRGPage (6 , 0x08 );
41+ SelectPRGPage (7 , 0x09 );
42+
43+ SelectCHRPage (0 , 0 );
44+ SelectCHRPage (1 , -3 );
45+
46+ AddRegisterRange (0x4800 , 0x4FFF , MemoryOperation::Read);
47+ RemoveRegisterRange (0x8000 , 0xBFFF , MemoryOperation::Read);
48+ RemoveRegisterRange (0xD000 , 0xFFFF , MemoryOperation::Read);
49+ }
50+
51+ void StreamState (bool saving) override
52+ {
53+ BaseMapper::StreamState (saving);
54+ Stream (_serialAddress, _serialControl,
55+ _irqCounter, _irqReloadValue, _irqEnabled);
56+ }
57+
58+ void NotifyVRAMAddressChange (uint16_t addr) override
59+ {
60+ switch (_a12Watcher.UpdateVramAddress (addr, _console->GetPpu ()->GetFrameCycle ())) {
61+ case A12StateChange::None:
62+ case A12StateChange::Fall:
63+ break ;
64+
65+ case A12StateChange::Rise:
66+ if (_irqCounter == 0 ) {
67+ _irqCounter = _irqReloadValue;
68+ } else {
69+ _irqCounter--;
70+ }
71+ if (_irqCounter == 0 && _irqEnabled) {
72+ _console->GetCpu ()->SetIrqSource (IRQSource::External);
73+ }
74+ }
75+ }
76+
77+ uint8_t ReadRegister (uint16_t addr) override
78+ {
79+ if (_serialControl & 0x02 ) {
80+ return (_miscRom[_serialAddress++ & (_miscRomSize - 1 )]);
81+ } else {
82+ return (_miscRom[_serialAddress & (_miscRomSize - 1 )]);
83+ }
84+ }
85+
86+ void WriteRegister (uint16_t addr, uint8_t value) override
87+ {
88+ switch (addr & 0xF000 ) {
89+ case 0x8000 :
90+ _irqReloadValue = value;
91+ break ;
92+
93+ case 0x9000 :
94+ _irqCounter = 0 ;
95+ break ;
96+
97+ case 0xA000 :
98+ case 0xB000 :
99+ _irqEnabled = (addr & 0x1000 ) != 0 ;
100+ if (_irqEnabled == 0 ) {
101+ _console->GetCpu ()->ClearIrqSource (IRQSource::External);
102+ }
103+ break ;
104+
105+ case 0xC000 :
106+ _serialAddress = (_serialAddress << 1 ) | (value >> 7 );
107+ break ;
108+
109+ case 0xD000 :
110+ _serialControl = value;
111+ break ;
112+
113+ case 0xE000 :
114+ case 0xF000 :
115+ switch (value >> 6 ) {
116+ case 0 :
117+ value <<= 1 ;
118+ SetCpuMemoryMapping (0x6000 , 0x7FFF , value, PrgMemoryType::PrgRom);
119+ break ;
120+
121+ case 1 :
122+ value <<= 1 ;
123+ SelectPRGPage (0 , value);
124+ SelectPRGPage (1 , value + 1 );
125+ break ;
126+
127+ case 2 :
128+ value <<= 1 ;
129+ SelectPRGPage (2 , value);
130+ SelectPRGPage (3 , value + 1 );
131+ break ;
132+
133+ case 3 :
134+ SelectCHRPage (0 , value);
135+ break ;
136+ }
137+ break ;
138+ }
139+ }
140+ };
0 commit comments