DMA: Refactoring + improvements/fixes
This commit is contained in:
parent
574a9a6a69
commit
0f657ccf63
9 changed files with 198 additions and 56 deletions
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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
110
Core/DmaController.cpp
Normal 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
32
Core/DmaController.h
Normal 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);
|
||||
};
|
|
@ -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);
|
||||
|
|
47
Core/Ppu.cpp
47
Core/Ppu.cpp
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue