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);
|
shared_ptr<BaseCartridge> cart = BaseCartridge::CreateCartridge(romFile, patchFile);
|
||||||
if(cart) {
|
if(cart) {
|
||||||
_ppu.reset(new Ppu(shared_from_this()));
|
_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));
|
_cpu.reset(new Cpu(_memoryManager));
|
||||||
_debugger.reset(new Debugger(_cpu, _ppu, _memoryManager));
|
_debugger.reset(new Debugger(_cpu, _ppu, _memoryManager));
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,7 @@
|
||||||
<ClInclude Include="DebugHud.h" />
|
<ClInclude Include="DebugHud.h" />
|
||||||
<ClInclude Include="DefaultVideoFilter.h" />
|
<ClInclude Include="DefaultVideoFilter.h" />
|
||||||
<ClInclude Include="DisassemblyInfo.h" />
|
<ClInclude Include="DisassemblyInfo.h" />
|
||||||
|
<ClInclude Include="DmaController.h" />
|
||||||
<ClInclude Include="DrawCommand.h" />
|
<ClInclude Include="DrawCommand.h" />
|
||||||
<ClInclude Include="DrawLineCommand.h" />
|
<ClInclude Include="DrawLineCommand.h" />
|
||||||
<ClInclude Include="DrawPixelCommand.h" />
|
<ClInclude Include="DrawPixelCommand.h" />
|
||||||
|
@ -88,6 +89,7 @@
|
||||||
<ClCompile Include="DebugHud.cpp" />
|
<ClCompile Include="DebugHud.cpp" />
|
||||||
<ClCompile Include="DefaultVideoFilter.cpp" />
|
<ClCompile Include="DefaultVideoFilter.cpp" />
|
||||||
<ClCompile Include="DisassemblyInfo.cpp" />
|
<ClCompile Include="DisassemblyInfo.cpp" />
|
||||||
|
<ClCompile Include="DmaController.cpp" />
|
||||||
<ClCompile Include="KeyManager.cpp" />
|
<ClCompile Include="KeyManager.cpp" />
|
||||||
<ClCompile Include="MessageManager.cpp" />
|
<ClCompile Include="MessageManager.cpp" />
|
||||||
<ClCompile Include="Ppu.cpp" />
|
<ClCompile Include="Ppu.cpp" />
|
||||||
|
|
|
@ -98,6 +98,9 @@
|
||||||
<ClInclude Include="DrawStringCommand.h">
|
<ClInclude Include="DrawStringCommand.h">
|
||||||
<Filter>Video\DebugHud</Filter>
|
<Filter>Video\DebugHud</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="DmaController.h">
|
||||||
|
<Filter>SNES</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="stdafx.cpp" />
|
<ClCompile Include="stdafx.cpp" />
|
||||||
|
@ -149,6 +152,9 @@
|
||||||
<ClCompile Include="DebugHud.cpp">
|
<ClCompile Include="DebugHud.cpp">
|
||||||
<Filter>Video\DebugHud</Filter>
|
<Filter>Video\DebugHud</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="DmaController.cpp">
|
||||||
|
<Filter>SNES</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Filter Include="SNES">
|
<Filter Include="SNES">
|
||||||
|
|
|
@ -93,5 +93,7 @@ enum class MemoryOperationType
|
||||||
ExecOpCode = 2,
|
ExecOpCode = 2,
|
||||||
ExecOperand = 3,
|
ExecOperand = 3,
|
||||||
DummyRead = 5,
|
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 "stdafx.h"
|
||||||
#include "Console.h"
|
#include "Console.h"
|
||||||
#include "Ppu.h"
|
#include "Ppu.h"
|
||||||
|
#include "DmaController.h"
|
||||||
#include "../Utilities/HexUtilities.h"
|
#include "../Utilities/HexUtilities.h"
|
||||||
#include "../Utilities/VirtualFile.h"
|
#include "../Utilities/VirtualFile.h"
|
||||||
|
|
||||||
|
@ -56,21 +57,26 @@ class CpuRegisterHandler : public IMemoryHandler
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
shared_ptr<Ppu> _ppu;
|
shared_ptr<Ppu> _ppu;
|
||||||
|
shared_ptr<MemoryManager> _memoryManager;
|
||||||
|
unique_ptr<DmaController> _dmaController;
|
||||||
|
|
||||||
public:
|
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
|
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
|
void Write(uint32_t addr, uint8_t value) override
|
||||||
{
|
{
|
||||||
_ppu->Write(addr, value);
|
_ppu->Write(addr & 0xFFFF, value);
|
||||||
|
_dmaController->Write(addr & 0xFFFF, value);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -107,12 +113,16 @@ private:
|
||||||
shared_ptr<BaseCartridge> _cart;
|
shared_ptr<BaseCartridge> _cart;
|
||||||
shared_ptr<CpuRegisterHandler> _cpuRegisterHandler;
|
shared_ptr<CpuRegisterHandler> _cpuRegisterHandler;
|
||||||
shared_ptr<Ppu> _ppu;
|
shared_ptr<Ppu> _ppu;
|
||||||
|
|
||||||
|
unique_ptr<DmaController> _dmaController;
|
||||||
|
|
||||||
|
uint32_t _wramPosition;
|
||||||
|
|
||||||
uint64_t _masterClock;
|
uint64_t _masterClock;
|
||||||
uint64_t _lastMasterClock;
|
uint64_t _lastMasterClock;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MemoryManager(shared_ptr<BaseCartridge> cart, shared_ptr<Console> console)
|
void Initialize(shared_ptr<BaseCartridge> cart, shared_ptr<Console> console)
|
||||||
{
|
{
|
||||||
_lastMasterClock = 0;
|
_lastMasterClock = 0;
|
||||||
_masterClock = 0;
|
_masterClock = 0;
|
||||||
|
@ -120,11 +130,11 @@ public:
|
||||||
_cart = cart;
|
_cart = cart;
|
||||||
_ppu = console->GetPpu();
|
_ppu = console->GetPpu();
|
||||||
|
|
||||||
_cpuRegisterHandler.reset(new CpuRegisterHandler(_ppu));
|
_cpuRegisterHandler.reset(new CpuRegisterHandler(console));
|
||||||
|
|
||||||
memset(_handlers, 0, sizeof(_handlers));
|
memset(_handlers, 0, sizeof(_handlers));
|
||||||
_workRam = new uint8_t[128 * 1024];
|
_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) {
|
for(uint32_t i = 0; i < 128 * 1024; i += 0x1000) {
|
||||||
_workRamHandlers.push_back(unique_ptr<WorkRamHandler>(new WorkRamHandler(_workRam + i)));
|
_workRamHandlers.push_back(unique_ptr<WorkRamHandler>(new WorkRamHandler(_workRam + i)));
|
||||||
|
@ -234,6 +244,25 @@ public:
|
||||||
{
|
{
|
||||||
IncrementMasterClock(addr);
|
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);
|
_console->ProcessCpuWrite(addr, value, type);
|
||||||
if(_handlers[addr >> 12]) {
|
if(_handlers[addr >> 12]) {
|
||||||
return _handlers[addr >> 12]->Write(addr, value);
|
return _handlers[addr >> 12]->Write(addr, value);
|
||||||
|
|
49
Core/Ppu.cpp
49
Core/Ppu.cpp
|
@ -86,7 +86,9 @@ void Ppu::SendFrame()
|
||||||
color >>= 1;
|
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;
|
_currentBuffer[(y * 8 + i) * 256 + x * 8 + j] = paletteColor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -106,9 +108,9 @@ uint8_t Ppu::Read(uint16_t addr)
|
||||||
|
|
||||||
case 0x4212:
|
case 0x4212:
|
||||||
return (
|
return (
|
||||||
(_scanline >= 225 ? 0x80 : 0) ||
|
(_scanline >= 225 ? 0x80 : 0) |
|
||||||
((_cycle >= 0x121 || _cycle <= 0x15) ? 0x40 : 0)
|
((_cycle >= 0x121 || _cycle <= 0x15) ? 0x40 : 0)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -184,46 +186,5 @@ void Ppu::Write(uint32_t addr, uint8_t value)
|
||||||
_enableNmi = (value & 0x80) != 0;
|
_enableNmi = (value & 0x80) != 0;
|
||||||
break;
|
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];
|
LayerConfig _layerConfig[4];
|
||||||
|
|
||||||
uint8_t _dmaDest = 0;
|
|
||||||
uint32_t _dmaSource = 0;
|
|
||||||
uint16_t _dmaSize = 0;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Ppu(shared_ptr<Console> console);
|
Ppu(shared_ptr<Console> console);
|
||||||
|
|
Loading…
Add table
Reference in a new issue