110 lines
3.5 KiB
C++
110 lines
3.5 KiB
C++
#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;
|
|
}
|
|
}
|
|
}
|