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