DMA: Refactoring + improvements/fixes

This commit is contained in:
Sour 2019-02-15 00:08:50 -05:00
parent 574a9a6a69
commit 0f657ccf63
9 changed files with 198 additions and 56 deletions

View file

@ -57,7 +57,10 @@ void Console::LoadRom(VirtualFile romFile, VirtualFile patchFile)
shared_ptr<BaseCartridge> cart = BaseCartridge::CreateCartridge(romFile, patchFile);
if(cart) {
_ppu.reset(new Ppu(shared_from_this()));
_memoryManager.reset(new MemoryManager(cart, shared_from_this()));
_memoryManager.reset(new MemoryManager());
_memoryManager->Initialize(cart, shared_from_this());
_cpu.reset(new Cpu(_memoryManager));
_debugger.reset(new Debugger(_cpu, _ppu, _memoryManager));
}

View file

@ -53,6 +53,7 @@
<ClInclude Include="DebugHud.h" />
<ClInclude Include="DefaultVideoFilter.h" />
<ClInclude Include="DisassemblyInfo.h" />
<ClInclude Include="DmaController.h" />
<ClInclude Include="DrawCommand.h" />
<ClInclude Include="DrawLineCommand.h" />
<ClInclude Include="DrawPixelCommand.h" />
@ -88,6 +89,7 @@
<ClCompile Include="DebugHud.cpp" />
<ClCompile Include="DefaultVideoFilter.cpp" />
<ClCompile Include="DisassemblyInfo.cpp" />
<ClCompile Include="DmaController.cpp" />
<ClCompile Include="KeyManager.cpp" />
<ClCompile Include="MessageManager.cpp" />
<ClCompile Include="Ppu.cpp" />

View file

@ -98,6 +98,9 @@
<ClInclude Include="DrawStringCommand.h">
<Filter>Video\DebugHud</Filter>
</ClInclude>
<ClInclude Include="DmaController.h">
<Filter>SNES</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="stdafx.cpp" />
@ -149,6 +152,9 @@
<ClCompile Include="DebugHud.cpp">
<Filter>Video\DebugHud</Filter>
</ClCompile>
<ClCompile Include="DmaController.cpp">
<Filter>SNES</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Filter Include="SNES">

View file

@ -93,5 +93,7 @@ enum class MemoryOperationType
ExecOpCode = 2,
ExecOperand = 3,
DummyRead = 5,
DummyWrite = 6
DummyWrite = 6,
DmaRead = 7,
DmaWrite = 8
};

110
Core/DmaController.cpp Normal file
View file

@ -0,0 +1,110 @@
#include "stdafx.h"
#include "DmaController.h"
#include "MemoryManager.h"
DmaController::DmaController(shared_ptr<MemoryManager> memoryManager)
{
_memoryManager = memoryManager;
}
void DmaController::RunDma(DmaChannelConfig &channel)
{
//"Note, however, that writing $0000 to this register actually results in a transfer of $10000 bytes, not 0."
uint32_t transferSize = channel.TransferSize ? channel.TransferSize : 0x10000;
uint8_t offset = 0;
if(channel.InvertDirection) {
for(uint32_t i = 0; i < transferSize; i++) {
uint8_t valToWrite = _memoryManager->Read(0x2100 | channel.DestAddress + offset, MemoryOperationType::DmaRead);
_memoryManager->Write(channel.SrcAddress, valToWrite, MemoryOperationType::DmaWrite);
if(!channel.FixedTransfer) {
channel.SrcAddress += channel.Decrement ? -1 : 1;
}
}
} else {
for(uint32_t i = 0; i < transferSize; i++) {
uint8_t valToWrite = _memoryManager->Read(channel.SrcAddress, MemoryOperationType::DmaRead);
_memoryManager->Write(0x2100 | channel.DestAddress + offset, valToWrite, MemoryOperationType::DmaWrite);
if(channel.TransferMode == 1) {
offset = (offset + 1) & 0x01;
}
if(!channel.FixedTransfer) {
channel.SrcAddress += channel.Decrement ? -1 : 1;
}
}
}
}
void DmaController::Write(uint16_t addr, uint8_t value)
{
switch(addr) {
case 0x420B:
//MDMAEN - DMA Enable
for(int i = 0; i < 8; i++) {
if(value & (1 << i)) {
RunDma(_channel[i]);
}
}
break;
case 0x4300: case 0x4310: case 0x4320: case 0x4330: case 0x4340: case 0x4350: case 0x4360: case 0x4370:
{
//DMAPx - DMA Control for Channel x
DmaChannelConfig &channel = _channel[(addr & 0x70) >> 4];
channel.InvertDirection = (value & 0x80) != 0;
channel.HdmaPointers = (value & 0x40) != 0;
channel.Decrement = (value & 0x10) != 0;
channel.FixedTransfer = (value & 0x08) != 0;
channel.TransferMode = value & 0x07;
break;
}
case 0x4301: case 0x4311: case 0x4321: case 0x4331: case 0x4341: case 0x4351: case 0x4361: case 0x4371:
{
//BBADx - DMA Destination Register for Channel x
DmaChannelConfig &channel = _channel[(addr & 0x70) >> 4];
channel.DestAddress = value;
break;
}
case 0x4305: case 0x4315: case 0x4325: case 0x4335: case 0x4345: case 0x4355: case 0x4365: case 0x4375:
{
//DASxL - DMA Size / HDMA Indirect Address low byte(x = 0 - 7)
DmaChannelConfig &channel = _channel[(addr & 0x70) >> 4];
channel.TransferSize = (channel.TransferSize & 0xFF00) | value;
break;
}
case 0x4306: case 0x4316: case 0x4326: case 0x4336: case 0x4346: case 0x4356: case 0x4366: case 0x4376:
{
//DASxL - DMA Size / HDMA Indirect Address low byte(x = 0 - 7)
DmaChannelConfig &channel = _channel[(addr & 0x70) >> 4];
channel.TransferSize = (channel.TransferSize & 0xFF) | (value << 8);
break;
}
case 0x4302: case 0x4312: case 0x4322: case 0x4332: case 0x4342: case 0x4352: case 0x4362: case 0x4372:
{
DmaChannelConfig &channel = _channel[(addr & 0x70) >> 4];
channel.SrcAddress = (channel.SrcAddress & 0xFFFF00) | value;
break;
}
case 0x4303: case 0x4313: case 0x4323: case 0x4333: case 0x4343: case 0x4353: case 0x4363: case 0x4373:
{
DmaChannelConfig &channel = _channel[(addr & 0x70) >> 4];
channel.SrcAddress = (channel.SrcAddress & 0xFF00FF) | (value << 8);
break;
}
case 0x4304: case 0x4314: case 0x4324: case 0x4334: case 0x4344: case 0x4354: case 0x4364: case 0x4374:
{
DmaChannelConfig &channel = _channel[(addr & 0x70) >> 4];
channel.SrcAddress = (channel.SrcAddress & 0x00FFFF) | (value << 16);
break;
}
}
}

32
Core/DmaController.h Normal file
View file

@ -0,0 +1,32 @@
#pragma once
#include "stdafx.h"
#include "CpuTypes.h"
class MemoryManager;
struct DmaChannelConfig
{
bool InvertDirection;
bool Decrement;
bool FixedTransfer;
bool HdmaPointers;
uint8_t TransferMode;
uint32_t SrcAddress;
uint8_t DestAddress;
uint16_t TransferSize;
};
class DmaController
{
private:
DmaChannelConfig _channel[8] = {};
shared_ptr<MemoryManager> _memoryManager;
public:
DmaController(shared_ptr<MemoryManager> memoryManager);
void RunDma(DmaChannelConfig & channel);
void Write(uint16_t addr, uint8_t value);
};

View file

@ -2,6 +2,7 @@
#include "stdafx.h"
#include "Console.h"
#include "Ppu.h"
#include "DmaController.h"
#include "../Utilities/HexUtilities.h"
#include "../Utilities/VirtualFile.h"
@ -56,21 +57,26 @@ class CpuRegisterHandler : public IMemoryHandler
{
private:
shared_ptr<Ppu> _ppu;
shared_ptr<MemoryManager> _memoryManager;
unique_ptr<DmaController> _dmaController;
public:
CpuRegisterHandler(shared_ptr<Ppu> ppu)
CpuRegisterHandler(shared_ptr<Console> console)
{
_ppu = ppu;
_ppu = console->GetPpu();
_memoryManager = console->GetMemoryManager();
_dmaController.reset(new DmaController(_memoryManager));
}
uint8_t Read(uint32_t addr) override
{
return _ppu->Read(addr);
return _ppu->Read(addr & 0xFFFF);
}
void Write(uint32_t addr, uint8_t value) override
{
_ppu->Write(addr, value);
_ppu->Write(addr & 0xFFFF, value);
_dmaController->Write(addr & 0xFFFF, value);
}
};
@ -108,11 +114,15 @@ private:
shared_ptr<CpuRegisterHandler> _cpuRegisterHandler;
shared_ptr<Ppu> _ppu;
unique_ptr<DmaController> _dmaController;
uint32_t _wramPosition;
uint64_t _masterClock;
uint64_t _lastMasterClock;
public:
MemoryManager(shared_ptr<BaseCartridge> cart, shared_ptr<Console> console)
void Initialize(shared_ptr<BaseCartridge> cart, shared_ptr<Console> console)
{
_lastMasterClock = 0;
_masterClock = 0;
@ -120,11 +130,11 @@ public:
_cart = cart;
_ppu = console->GetPpu();
_cpuRegisterHandler.reset(new CpuRegisterHandler(_ppu));
_cpuRegisterHandler.reset(new CpuRegisterHandler(console));
memset(_handlers, 0, sizeof(_handlers));
_workRam = new uint8_t[128 * 1024];
memset(_workRam, 0, 128 * 1024);
//memset(_workRam, 0, 128 * 1024);
for(uint32_t i = 0; i < 128 * 1024; i += 0x1000) {
_workRamHandlers.push_back(unique_ptr<WorkRamHandler>(new WorkRamHandler(_workRam + i)));
@ -234,6 +244,25 @@ public:
{
IncrementMasterClock(addr);
switch(addr & 0xFFFF) {
case 0x2180:
_workRam[_wramPosition] = value;
_wramPosition++;
break;
case 0x2181:
_wramPosition = (_wramPosition & 0x1FF00) | value;
break;
case 0x2182:
_wramPosition = (_wramPosition & 0x100FF) | (value << 8);
break;
case 0x2183:
_wramPosition = (_wramPosition & 0xFFFF) | ((value & 0x01) << 16);
break;
}
_console->ProcessCpuWrite(addr, value, type);
if(_handlers[addr >> 12]) {
return _handlers[addr >> 12]->Write(addr, value);

View file

@ -86,7 +86,9 @@ void Ppu::SendFrame()
color >>= 1;
}
uint16_t paletteColor = _cgram[(palette * 4 + color) * 2] | (_cgram[(palette * 4 + color) * 2 + 1] << 8);
uint16_t paletteRamOffset = color == 0 ? 0 : ((palette * 4 + color) * 2);
uint16_t paletteColor = _cgram[paletteRamOffset] | (_cgram[paletteRamOffset + 1] << 8);
_currentBuffer[(y * 8 + i) * 256 + x * 8 + j] = paletteColor;
}
}
@ -106,7 +108,7 @@ uint8_t Ppu::Read(uint16_t addr)
case 0x4212:
return (
(_scanline >= 225 ? 0x80 : 0) ||
(_scanline >= 225 ? 0x80 : 0) |
((_cycle >= 0x121 || _cycle <= 0x15) ? 0x40 : 0)
);
}
@ -184,46 +186,5 @@ void Ppu::Write(uint32_t addr, uint8_t value)
_enableNmi = (value & 0x80) != 0;
break;
case 0x420B:
//MDMAEN - DMA Enable
if(value & 0x01) {
for(int i = 0; i < _dmaSize; i++) {
uint8_t valToWrite = _console->GetMemoryManager()->Read(_dmaSource, MemoryOperationType::Read);
_console->GetMemoryManager()->Write(0x2100 | _dmaDest, valToWrite, MemoryOperationType::Write);
_dmaSource++;
}
}
break;
case 0x4300:
//DMAPx - DMA Control for Channel x
break;
case 0x4301:
//BBADx - DMA Destination Register for Channel x
_dmaDest = value;
break;
case 0x4305:
//DASxL - DMA Size / HDMA Indirect Address low byte(x = 0 - 7)
_dmaSize = (_dmaSize & 0xFF00) | value;
break;
case 0x4306:
//DASxL - DMA Size / HDMA Indirect Address low byte(x = 0 - 7)
_dmaSize = (_dmaSize & 0xFF) | (value << 8);
break;
case 0x4302:
_dmaSource = (_dmaSource & 0xFFFF00) | value;
break;
case 0x4303:
_dmaSource = (_dmaSource & 0xFF00FF) | (value << 8);
break;
case 0x4304:
_dmaSource = (_dmaSource & 0x00FFFF) | (value << 16);
break;
}
}

View file

@ -29,9 +29,6 @@ private:
LayerConfig _layerConfig[4];
uint8_t _dmaDest = 0;
uint32_t _dmaSource = 0;
uint16_t _dmaSize = 0;
public:
Ppu(shared_ptr<Console> console);