#pragma once #include "stdafx.h" #include "Snapshotable.h" #include "IMemoryHandler.h" #include "DebuggerTypes.h" #include "Debugger.h" #include "Types.h" #include "IBattery.h" #include "RomData.h" #include "Console.h" class BaseControlDevice; class BaseMapper : public IMemoryHandler, public Snapshotable, public INotificationListener, public IBattery { private: MirroringType _mirroringType; string _batteryFilename; uint16_t InternalGetPrgPageSize(); uint16_t InternalGetSaveRamPageSize(); uint16_t InternalGetWorkRamPageSize(); uint16_t InternalGetChrPageSize(); uint16_t InternalGetChrRamPageSize(); bool ValidateAddressRange(uint16_t startAddr, uint16_t endAddr); uint8_t *_nametableRam = nullptr; uint8_t _nametableCount = 2; bool _onlyChrRam = false; bool _hasBusConflicts = false; bool _allowRegisterRead = false; bool _isReadRegisterAddr[0x10000]; bool _isWriteRegisterAddr[0x10000]; MemoryAccessType _prgMemoryAccess[0x100]; uint8_t* _prgPages[0x100]; MemoryAccessType _chrMemoryAccess[0x100]; uint8_t* _chrPages[0x100]; int32_t _prgMemoryOffset[0x100]; PrgMemoryType _prgMemoryType[0x100]; int32_t _chrMemoryOffset[0x100]; ChrMemoryType _chrMemoryType[0x100]; vector _originalPrgRom; vector _originalChrRom; protected: RomInfo _romInfo; shared_ptr _mapperControlDevice; shared_ptr _console; uint8_t* _prgRom = nullptr; uint8_t* _chrRom = nullptr; uint8_t* _chrRam = nullptr; uint32_t _prgSize = 0; uint32_t _chrRomSize = 0; uint32_t _chrRamSize = 0; uint8_t* _saveRam = nullptr; uint32_t _saveRamSize = 0; uint32_t _workRamSize = 0; uint8_t* _workRam = nullptr; bool _hasChrBattery = false; int16_t _vramOpenBusValue = -1; virtual void InitMapper() = 0; virtual void InitMapper(RomData &romData); virtual uint16_t GetPRGPageSize() = 0; virtual uint16_t GetCHRPageSize() = 0; bool IsNes20(); virtual uint16_t GetChrRamPageSize() { return 0x2000; } //Save ram is battery backed and saved to disk virtual uint32_t GetSaveRamSize() { return HasBattery() ? 0x2000 : 0; } virtual uint32_t GetSaveRamPageSize() { return 0x2000; } virtual bool ForceChrBattery() { return false; } virtual bool ForceSaveRamSize() { return false; } virtual bool ForceWorkRamSize() { return false; } virtual uint32_t GetChrRamSize() { return 0x0000; } //Work ram is NOT saved - aka Expansion ram, etc. virtual uint32_t GetWorkRamSize() { return HasBattery() ? 0 : 0x2000; } virtual uint32_t GetWorkRamPageSize() { return 0x2000; } virtual uint16_t RegisterStartAddress() { return 0x8000; } virtual uint16_t RegisterEndAddress() { return 0xFFFF; } virtual bool AllowRegisterRead() { return false; } virtual uint32_t GetDipSwitchCount() { return 0; } virtual bool HasBusConflicts() { return false; } uint8_t InternalReadRam(uint16_t addr); virtual void WriteRegister(uint16_t addr, uint8_t value); virtual uint8_t ReadRegister(uint16_t addr); void SelectPrgPage4x(uint16_t slot, uint16_t page, PrgMemoryType memoryType = PrgMemoryType::PrgRom); void SelectPrgPage2x(uint16_t slot, uint16_t page, PrgMemoryType memoryType = PrgMemoryType::PrgRom); virtual void SelectPRGPage(uint16_t slot, uint16_t page, PrgMemoryType memoryType = PrgMemoryType::PrgRom); void SetCpuMemoryMapping(uint16_t startAddr, uint16_t endAddr, int16_t pageNumber, PrgMemoryType type, int8_t accessType = -1); void SetCpuMemoryMapping(uint16_t startAddr, uint16_t endAddr, PrgMemoryType type, uint32_t sourceOffset, int8_t accessType); void SetCpuMemoryMapping(uint16_t startAddr, uint16_t endAddr, uint8_t *source, int8_t accessType = -1); void RemoveCpuMemoryMapping(uint16_t startAddr, uint16_t endAddr); virtual void SelectChrPage8x(uint16_t slot, uint16_t page, ChrMemoryType memoryType = ChrMemoryType::Default); virtual void SelectChrPage4x(uint16_t slot, uint16_t page, ChrMemoryType memoryType = ChrMemoryType::Default); virtual void SelectChrPage2x(uint16_t slot, uint16_t page, ChrMemoryType memoryType = ChrMemoryType::Default); virtual void SelectCHRPage(uint16_t slot, uint16_t page, ChrMemoryType memoryType = ChrMemoryType::Default); void SetPpuMemoryMapping(uint16_t startAddr, uint16_t endAddr, uint16_t pageNumber, ChrMemoryType type = ChrMemoryType::Default, int8_t accessType = -1); void SetPpuMemoryMapping(uint16_t startAddr, uint16_t endAddr, ChrMemoryType type, uint32_t sourceOffset, int8_t accessType); void SetPpuMemoryMapping(uint16_t startAddr, uint16_t endAddr, uint8_t* sourceMemory, int8_t accessType = -1); void RemovePpuMemoryMapping(uint16_t startAddr, uint16_t endAddr); bool HasBattery(); virtual void LoadBattery(); string GetBatteryFilename(); uint32_t GetPRGPageCount(); uint32_t GetCHRPageCount(); uint8_t GetPowerOnByte(uint8_t defaultValue = 0); uint32_t GetDipSwitches(); void SetupDefaultWorkRam(); void RestoreOriginalPrgRam(); void InitializeChrRam(int32_t chrRamSize = -1); void AddRegisterRange(uint16_t startAddr, uint16_t endAddr, MemoryOperation operation = MemoryOperation::Any); void RemoveRegisterRange(uint16_t startAddr, uint16_t endAddr, MemoryOperation operation = MemoryOperation::Any); virtual void StreamState(bool saving) override; void RestorePrgChrState(); uint8_t* GetNametable(uint8_t nametableIndex); void SetNametable(uint8_t index, uint8_t nametableIndex); void SetNametables(uint8_t nametable1Index, uint8_t nametable2Index, uint8_t nametable3Index, uint8_t nametable4Index); void SetMirroringType(MirroringType type); MirroringType GetMirroringType(); public: static constexpr uint32_t NametableCount = 0x10; static constexpr uint32_t NametableSize = 0x400; void Initialize(RomData &romData); virtual ~BaseMapper(); virtual void Reset(bool softReset); virtual ConsoleFeatures GetAvailableFeatures(); virtual void SetNesModel(NesModel model) { } virtual void ProcessCpuClock() { } virtual void NotifyVRAMAddressChange(uint16_t addr); void ProcessNotification(ConsoleNotificationType type, void* parameter) override; virtual void GetMemoryRanges(MemoryRanges &ranges) override; void ApplyCheats(); virtual void SaveBattery() override; void SetConsole(shared_ptr console); shared_ptr GetMapperControlDevice(); RomInfo GetRomInfo(); uint32_t GetMapperDipSwitchCount(); __forceinline uint8_t ReadRAM(uint16_t addr) override; uint8_t PeekRAM(uint16_t addr) override; uint8_t DebugReadRAM(uint16_t addr); virtual void WriteRAM(uint16_t addr, uint8_t value) override; void DebugWriteRAM(uint16_t addr, uint8_t value); void WritePrgRam(uint16_t addr, uint8_t value); __forceinline uint8_t InternalReadVRAM(uint16_t addr); __forceinline virtual uint8_t MapperReadVRAM(uint16_t addr, MemoryOperationType operationType); __forceinline uint8_t ReadVRAM(uint16_t addr, MemoryOperationType type = MemoryOperationType::PpuRenderingRead) { uint8_t value = MapperReadVRAM(addr, type); _console->DebugProcessVramReadOperation(type, addr, value); return value; } void DebugWriteVRAM(uint16_t addr, uint8_t value, bool disableSideEffects = true); void WriteVRAM(uint16_t addr, uint8_t value); uint8_t DebugReadVRAM(uint16_t addr, bool disableSideEffects = true); void CopyChrTile(uint32_t address, uint8_t *dest); //Debugger Helper Functions bool HasChrRam(); bool HasChrRom(); CartridgeState GetState(); uint8_t* GetPrgRom(); uint8_t* GetWorkRam(); uint8_t* GetSaveRam(); uint8_t GetMemoryValue(DebugMemoryType memoryType, uint32_t address); void SetMemoryValue(DebugMemoryType memoryType, uint32_t address, uint8_t value); uint32_t GetMemorySize(DebugMemoryType type); uint32_t CopyMemory(DebugMemoryType type, uint8_t* buffer); void WriteMemory(DebugMemoryType type, uint8_t* buffer, int32_t length); void GetAbsoluteAddressAndType(uint32_t relativeAddr, AddressTypeInfo *info); void GetPpuAbsoluteAddressAndType(uint32_t relativeAddr, PpuAddressTypeInfo *info); int32_t ToAbsoluteAddress(uint16_t addr); int32_t ToAbsoluteSaveRamAddress(uint16_t addr); int32_t ToAbsoluteWorkRamAddress(uint16_t addr); int32_t ToAbsoluteChrAddress(uint16_t addr); int32_t ToAbsoluteChrRamAddress(uint16_t addr); int32_t ToAbsoluteChrRomAddress(uint16_t addr); int32_t FromAbsoluteChrAddress(uint32_t addr); int32_t FromAbsoluteAddress(uint32_t addr, AddressType type = AddressType::PrgRom); int32_t FromAbsolutePpuAddress(uint32_t addr, PpuAddressType type); bool IsWriteRegister(uint16_t addr); bool IsReadRegister(uint16_t addr); void GetRomFileData(vector &out, bool asIpsFile, uint8_t* header); vector GetPrgChrCopy(); void RestorePrgChrBackup(vector& backupData); void RevertPrgChrChanges(); bool HasPrgChrChanges(); };