1 #pragma once
2 
3 #include "stdafx.h"
4 #include "Snapshotable.h"
5 #include "IMemoryHandler.h"
6 #include "DebuggerTypes.h"
7 #include "Debugger.h"
8 #include "Types.h"
9 #include "IBattery.h"
10 #include "RomData.h"
11 #include "Console.h"
12 
13 class BaseControlDevice;
14 
15 class BaseMapper : public IMemoryHandler, public Snapshotable, public INotificationListener, public IBattery
16 {
17 private:
18 	MirroringType _mirroringType;
19 	string _batteryFilename;
20 
21 	uint16_t InternalGetPrgPageSize();
22 	uint16_t InternalGetSaveRamPageSize();
23 	uint16_t InternalGetWorkRamPageSize();
24 	uint16_t InternalGetChrPageSize();
25 	uint16_t InternalGetChrRamPageSize();
26 	bool ValidateAddressRange(uint16_t startAddr, uint16_t endAddr);
27 
28 	uint8_t *_nametableRam = nullptr;
29 	uint8_t _nametableCount = 2;
30 
31 	bool _onlyChrRam = false;
32 	bool _hasBusConflicts = false;
33 
34 	bool _allowRegisterRead = false;
35 	bool _isReadRegisterAddr[0x10000];
36 	bool _isWriteRegisterAddr[0x10000];
37 
38 	MemoryAccessType _prgMemoryAccess[0x100];
39 	uint8_t* _prgPages[0x100];
40 
41 	MemoryAccessType _chrMemoryAccess[0x100];
42 	uint8_t* _chrPages[0x100];
43 
44 	int32_t _prgMemoryOffset[0x100];
45 	PrgMemoryType _prgMemoryType[0x100];
46 
47 	int32_t _chrMemoryOffset[0x100];
48 	ChrMemoryType _chrMemoryType[0x100];
49 
50 	vector<uint8_t> _originalPrgRom;
51 	vector<uint8_t> _originalChrRom;
52 
53 protected:
54 	RomInfo _romInfo;
55 
56 	shared_ptr<BaseControlDevice> _mapperControlDevice;
57 	shared_ptr<Console> _console;
58 
59 	uint8_t* _prgRom = nullptr;
60 	uint8_t* _chrRom = nullptr;
61 	uint8_t* _chrRam = nullptr;
62 	uint32_t _prgSize = 0;
63 	uint32_t _chrRomSize = 0;
64 	uint32_t _chrRamSize = 0;
65 
66 	uint8_t* _saveRam = nullptr;
67 	uint32_t _saveRamSize = 0;
68 	uint32_t _workRamSize = 0;
69 	uint8_t* _workRam = nullptr;
70 	bool _hasChrBattery = false;
71 	int16_t _vramOpenBusValue = -1;
72 
73 	virtual void InitMapper() = 0;
74 	virtual void InitMapper(RomData &romData);
75 	virtual uint16_t GetPRGPageSize() = 0;
76 	virtual uint16_t GetCHRPageSize() = 0;
77 
78 	bool IsNes20();
79 
GetChrRamPageSize()80 	virtual uint16_t GetChrRamPageSize() { return 0x2000; }
81 
82 	//Save ram is battery backed and saved to disk
GetSaveRamSize()83 	virtual uint32_t GetSaveRamSize() { return HasBattery() ? 0x2000 : 0; }
GetSaveRamPageSize()84 	virtual uint32_t GetSaveRamPageSize() { return 0x2000; }
ForceChrBattery()85 	virtual bool ForceChrBattery() { return false; }
86 
ForceSaveRamSize()87 	virtual bool ForceSaveRamSize() { return false; }
ForceWorkRamSize()88 	virtual bool ForceWorkRamSize() { return false; }
89 
GetChrRamSize()90 	virtual uint32_t GetChrRamSize() { return 0x0000; }
91 
92 	//Work ram is NOT saved - aka Expansion ram, etc.
GetWorkRamSize()93 	virtual uint32_t GetWorkRamSize() { return HasBattery() ? 0 : 0x2000; }
GetWorkRamPageSize()94 	virtual uint32_t GetWorkRamPageSize() { return 0x2000; }
95 
RegisterStartAddress()96 	virtual uint16_t RegisterStartAddress() { return 0x8000; }
RegisterEndAddress()97 	virtual uint16_t RegisterEndAddress() { return 0xFFFF; }
AllowRegisterRead()98 	virtual bool AllowRegisterRead() { return false; }
99 
GetDipSwitchCount()100 	virtual uint32_t GetDipSwitchCount() { return 0; }
101 
HasBusConflicts()102 	virtual bool HasBusConflicts() { return false; }
103 
104 	uint8_t InternalReadRam(uint16_t addr);
105 
106 	virtual void WriteRegister(uint16_t addr, uint8_t value);
107 	virtual uint8_t ReadRegister(uint16_t addr);
108 
109 	void SelectPrgPage4x(uint16_t slot, uint16_t page, PrgMemoryType memoryType = PrgMemoryType::PrgRom);
110 	void SelectPrgPage2x(uint16_t slot, uint16_t page, PrgMemoryType memoryType = PrgMemoryType::PrgRom);
111 	virtual void SelectPRGPage(uint16_t slot, uint16_t page, PrgMemoryType memoryType = PrgMemoryType::PrgRom);
112 	void SetCpuMemoryMapping(uint16_t startAddr, uint16_t endAddr, int16_t pageNumber, PrgMemoryType type, int8_t accessType = -1);
113 	void SetCpuMemoryMapping(uint16_t startAddr, uint16_t endAddr, PrgMemoryType type, uint32_t sourceOffset, int8_t accessType);
114 	void SetCpuMemoryMapping(uint16_t startAddr, uint16_t endAddr, uint8_t *source, int8_t accessType = -1);
115 	void RemoveCpuMemoryMapping(uint16_t startAddr, uint16_t endAddr);
116 
117 	virtual void SelectChrPage8x(uint16_t slot, uint16_t page, ChrMemoryType memoryType = ChrMemoryType::Default);
118 	virtual void SelectChrPage4x(uint16_t slot, uint16_t page, ChrMemoryType memoryType = ChrMemoryType::Default);
119 	virtual void SelectChrPage2x(uint16_t slot, uint16_t page, ChrMemoryType memoryType = ChrMemoryType::Default);
120 	virtual void SelectCHRPage(uint16_t slot, uint16_t page, ChrMemoryType memoryType = ChrMemoryType::Default);
121 	void SetPpuMemoryMapping(uint16_t startAddr, uint16_t endAddr, uint16_t pageNumber, ChrMemoryType type = ChrMemoryType::Default, int8_t accessType = -1);
122 	void SetPpuMemoryMapping(uint16_t startAddr, uint16_t endAddr, ChrMemoryType type, uint32_t sourceOffset, int8_t accessType);
123 	void SetPpuMemoryMapping(uint16_t startAddr, uint16_t endAddr, uint8_t* sourceMemory, int8_t accessType = -1);
124 	void RemovePpuMemoryMapping(uint16_t startAddr, uint16_t endAddr);
125 
126 	bool HasBattery();
127 	virtual void LoadBattery();
128 	string GetBatteryFilename();
129 
130 	uint32_t GetPRGPageCount();
131 	uint32_t GetCHRPageCount();
132 
133 	uint8_t GetPowerOnByte(uint8_t defaultValue = 0);
134 	uint32_t GetDipSwitches();
135 
136 	void SetupDefaultWorkRam();
137 
138 	void RestoreOriginalPrgRam();
139 	void InitializeChrRam(int32_t chrRamSize = -1);
140 
141 	void AddRegisterRange(uint16_t startAddr, uint16_t endAddr, MemoryOperation operation = MemoryOperation::Any);
142 	void RemoveRegisterRange(uint16_t startAddr, uint16_t endAddr, MemoryOperation operation = MemoryOperation::Any);
143 
144 	virtual void StreamState(bool saving) override;
145 
146 	void RestorePrgChrState();
147 
148 	uint8_t* GetNametable(uint8_t nametableIndex);
149 	void SetNametable(uint8_t index, uint8_t nametableIndex);
150 	void SetNametables(uint8_t nametable1Index, uint8_t nametable2Index, uint8_t nametable3Index, uint8_t nametable4Index);
151 	void SetMirroringType(MirroringType type);
152 	MirroringType GetMirroringType();
153 
154 public:
155 	static constexpr uint32_t NametableCount = 0x10;
156 	static constexpr uint32_t NametableSize = 0x400;
157 
158 	void Initialize(RomData &romData);
159 
160 	virtual ~BaseMapper();
161 	virtual void Reset(bool softReset);
162 
163 	virtual ConsoleFeatures GetAvailableFeatures();
164 
SetNesModel(NesModel model)165 	virtual void SetNesModel(NesModel model) { }
ProcessCpuClock()166 	virtual void ProcessCpuClock() { }
167 	virtual void NotifyVRAMAddressChange(uint16_t addr);
168 	void ProcessNotification(ConsoleNotificationType type, void* parameter) override;
169 	virtual void GetMemoryRanges(MemoryRanges &ranges) override;
170 
171 	void ApplyCheats();
172 
173 	virtual void SaveBattery() override;
174 
175 	void SetConsole(shared_ptr<Console> console);
176 
177 	shared_ptr<BaseControlDevice> GetMapperControlDevice();
178 	RomInfo GetRomInfo();
179 	uint32_t GetMapperDipSwitchCount();
180 
181 	__forceinline uint8_t ReadRAM(uint16_t addr) override;
182 	uint8_t PeekRAM(uint16_t addr) override;
183 	uint8_t DebugReadRAM(uint16_t addr);
184 	virtual void WriteRAM(uint16_t addr, uint8_t value) override;
185 	void DebugWriteRAM(uint16_t addr, uint8_t value);
186 	void WritePrgRam(uint16_t addr, uint8_t value);
187 
188 	__forceinline uint8_t InternalReadVRAM(uint16_t addr);
189 	__forceinline virtual uint8_t MapperReadVRAM(uint16_t addr, MemoryOperationType operationType);
190 
191 	__forceinline uint8_t ReadVRAM(uint16_t addr, MemoryOperationType type = MemoryOperationType::PpuRenderingRead)
192 	{
193 		uint8_t value = MapperReadVRAM(addr, type);
194 		_console->DebugProcessVramReadOperation(type, addr, value);
195 		return value;
196 	}
197 
198 	void DebugWriteVRAM(uint16_t addr, uint8_t value, bool disableSideEffects = true);
199 	void WriteVRAM(uint16_t addr, uint8_t value);
200 
201 	uint8_t DebugReadVRAM(uint16_t addr, bool disableSideEffects = true);
202 
203 	void CopyChrTile(uint32_t address, uint8_t *dest);
204 
205 	//Debugger Helper Functions
206 	bool HasChrRam();
207 	bool HasChrRom();
208 
209 	CartridgeState GetState();
210 	uint8_t* GetPrgRom();
211 	uint8_t* GetWorkRam();
212 	uint8_t* GetSaveRam();
213 
214 	uint8_t GetMemoryValue(DebugMemoryType memoryType, uint32_t address);
215 	void SetMemoryValue(DebugMemoryType memoryType, uint32_t address, uint8_t value);
216 	uint32_t GetMemorySize(DebugMemoryType type);
217 
218 	uint32_t CopyMemory(DebugMemoryType type, uint8_t* buffer);
219 	void WriteMemory(DebugMemoryType type, uint8_t* buffer, int32_t length);
220 
221 	void GetAbsoluteAddressAndType(uint32_t relativeAddr, AddressTypeInfo *info);
222 	void GetPpuAbsoluteAddressAndType(uint32_t relativeAddr, PpuAddressTypeInfo *info);
223 	int32_t ToAbsoluteAddress(uint16_t addr);
224 	int32_t ToAbsoluteSaveRamAddress(uint16_t addr);
225 	int32_t ToAbsoluteWorkRamAddress(uint16_t addr);
226 	int32_t ToAbsoluteChrAddress(uint16_t addr);
227 	int32_t ToAbsoluteChrRamAddress(uint16_t addr);
228 	int32_t ToAbsoluteChrRomAddress(uint16_t addr);
229 	int32_t FromAbsoluteChrAddress(uint32_t addr);
230 	int32_t FromAbsoluteAddress(uint32_t addr, AddressType type = AddressType::PrgRom);
231 	int32_t FromAbsolutePpuAddress(uint32_t addr, PpuAddressType type);
232 
233 	bool IsWriteRegister(uint16_t addr);
234 	bool IsReadRegister(uint16_t addr);
235 
236 	void GetRomFileData(vector<uint8_t> &out, bool asIpsFile, uint8_t* header);
237 
238 	vector<uint8_t> GetPrgChrCopy();
239 	void RestorePrgChrBackup(vector<uint8_t>& backupData);
240 	void RevertPrgChrChanges();
241 	bool HasPrgChrChanges();
242 };