diff --git a/Core/DebugTypes.h b/Core/DebugTypes.h index 5a585b0..1d9613c 100644 --- a/Core/DebugTypes.h +++ b/Core/DebugTypes.h @@ -18,6 +18,7 @@ enum class SnesMemoryType VideoRam, SpriteRam, CGRam, + Register }; struct AddressInfo diff --git a/Core/DmaController.cpp b/Core/DmaController.cpp index 1e445f3..0b4b263 100644 --- a/Core/DmaController.cpp +++ b/Core/DmaController.cpp @@ -8,6 +8,28 @@ DmaController::DmaController(MemoryManager *memoryManager) _memoryManager = memoryManager; } +void DmaController::CopyDmaByte(uint32_t addressBusA, uint16_t addressBusB, bool fromBtoA) +{ + if(fromBtoA) { + if(addressBusB != 0x2180 || !_memoryManager->IsWorkRam(addressBusA)) { + uint8_t valToWrite = _memoryManager->ReadDma(addressBusB); + _memoryManager->WriteDma(addressBusA, valToWrite); + } else { + //$2180->WRAM do cause a write to occur (but no read), but the value written is invalid + _memoryManager->IncrementMasterClockValue<4>(); + _memoryManager->WriteDma(addressBusA, 0xFF); + } + } else { + if(addressBusB != 0x2180 || !_memoryManager->IsWorkRam(addressBusA)) { + uint8_t valToWrite = _memoryManager->ReadDma(addressBusA); + _memoryManager->WriteDma(addressBusB, valToWrite); + } else { + //WRAM->$2180 does not cause a write to occur + _memoryManager->IncrementMasterClockValue<8>(); + } + } +} + void DmaController::RunSingleTransfer(DmaChannelConfig &channel) { const uint8_t *transferOffsets = _transferOffset[channel.TransferMode]; @@ -15,13 +37,11 @@ void DmaController::RunSingleTransfer(DmaChannelConfig &channel) uint8_t i = 0; do { - if(channel.InvertDirection) { - uint8_t valToWrite = _memoryManager->ReadDma(0x2100 | channel.DestAddress + transferOffsets[i]); - _memoryManager->WriteDma((channel.SrcBank << 16) | channel.SrcAddress, valToWrite); - } else { - uint8_t valToWrite = _memoryManager->ReadDma((channel.SrcBank << 16) | channel.SrcAddress); - _memoryManager->WriteDma(0x2100 | channel.DestAddress + transferOffsets[i], valToWrite); - } + CopyDmaByte( + (channel.SrcBank << 16) | channel.SrcAddress, + 0x2100 | channel.DestAddress + transferOffsets[i], + channel.InvertDirection + ); if(!channel.FixedTransfer) { channel.SrcAddress += channel.Decrement ? -1 : 1; @@ -105,13 +125,11 @@ void DmaController::RunHdmaTransfer(DmaChannelConfig &channel) uint8_t i = 0; do { - if(channel.InvertDirection) { - uint8_t valToWrite = _memoryManager->ReadDma(0x2100 | channel.DestAddress + transferOffsets[i]); - _memoryManager->WriteDma(srcAddress, valToWrite); - } else { - uint8_t valToWrite = _memoryManager->ReadDma(srcAddress); - _memoryManager->WriteDma(0x2100 | channel.DestAddress + transferOffsets[i], valToWrite); - } + CopyDmaByte( + srcAddress, + 0x2100 | channel.DestAddress + transferOffsets[i], + channel.InvertDirection + ); srcAddress = (srcAddress + (channel.Decrement ? -1 : 1)) & 0xFFFFFF; diff --git a/Core/DmaController.h b/Core/DmaController.h index 2a3f30c..48a9d8a 100644 --- a/Core/DmaController.h +++ b/Core/DmaController.h @@ -43,13 +43,15 @@ private: DmaChannelConfig _channel[8] = {}; MemoryManager *_memoryManager; + void CopyDmaByte(uint32_t addressBusA, uint16_t addressBusB, bool fromBtoA); + void RunSingleTransfer(DmaChannelConfig &channel); void RunDma(DmaChannelConfig &channel); void RunHdmaTransfer(DmaChannelConfig &channel); public: DmaController(MemoryManager *memoryManager); - + void InitHdmaChannels(); void ProcessHdmaChannels(); diff --git a/Core/IMemoryHandler.h b/Core/IMemoryHandler.h index 32855df..9f44751 100644 --- a/Core/IMemoryHandler.h +++ b/Core/IMemoryHandler.h @@ -4,11 +4,19 @@ class IMemoryHandler { +protected: + SnesMemoryType _memoryType; + public: virtual uint8_t Read(uint32_t addr) = 0; virtual uint8_t Peek(uint32_t addr) = 0; virtual void Write(uint32_t addr, uint8_t value) = 0; + __forceinline SnesMemoryType GetMemoryType() + { + return _memoryType; + } + virtual AddressInfo GetAbsoluteAddress(uint32_t address) = 0; //virtual void GetMemoryRanges(MemoryRanges &ranges) = 0; diff --git a/Core/MemoryManager.cpp b/Core/MemoryManager.cpp index 4e6a255..958840b 100644 --- a/Core/MemoryManager.cpp +++ b/Core/MemoryManager.cpp @@ -248,6 +248,12 @@ bool MemoryManager::IsRegister(uint32_t cpuAddress) return _handlers[cpuAddress >> 12] == _registerHandlerA.get() || _handlers[cpuAddress >> 12] == _registerHandlerB.get(); } +bool MemoryManager::IsWorkRam(uint32_t cpuAddress) +{ + IMemoryHandler* handler = _handlers[cpuAddress >> 12]; + return handler && handler->GetMemoryType() == SnesMemoryType::WorkRam; +} + AddressInfo MemoryManager::GetAbsoluteAddress(uint32_t addr) { if(_handlers[addr >> 12]) { diff --git a/Core/MemoryManager.h b/Core/MemoryManager.h index 835bbf4..4209ee5 100644 --- a/Core/MemoryManager.h +++ b/Core/MemoryManager.h @@ -62,6 +62,7 @@ public: uint8_t* DebugGetWorkRam(); bool IsRegister(uint32_t cpuAddress); + bool IsWorkRam(uint32_t cpuAddress); AddressInfo GetAbsoluteAddress(uint32_t addr); int GetRelativeAddress(AddressInfo &address, int32_t cpuAddress = -1); }; diff --git a/Core/RamHandler.h b/Core/RamHandler.h index d56397b..903bc98 100644 --- a/Core/RamHandler.h +++ b/Core/RamHandler.h @@ -9,7 +9,6 @@ private: uint8_t * _ram; uint32_t _offset; uint32_t _mask; - SnesMemoryType _memoryType; public: RamHandler(uint8_t *ram, uint32_t offset, uint32_t size, SnesMemoryType memoryType) diff --git a/Core/RegisterHandlerA.h b/Core/RegisterHandlerA.h index 31c6b43..12505cf 100644 --- a/Core/RegisterHandlerA.h +++ b/Core/RegisterHandlerA.h @@ -18,6 +18,7 @@ public: _regs = regs; _dmaController = dmaController; _controlManager = controlManager; + _memoryType = SnesMemoryType::Register; } uint8_t Read(uint32_t addr) override diff --git a/Core/RegisterHandlerB.h b/Core/RegisterHandlerB.h index 383699d..f5948d4 100644 --- a/Core/RegisterHandlerB.h +++ b/Core/RegisterHandlerB.h @@ -22,6 +22,7 @@ public: _spc = spc; _workRam = workRam; _wramPosition = 0; + _memoryType = SnesMemoryType::Register; } uint8_t Read(uint32_t addr) override