HDMA: Set DoTransfer flag to true for all 8 HDMA channels during init if at least 1 HDMA channel is active (Fixed "Ladida_lol" test)

This commit is contained in:
Sour 2019-04-11 19:55:06 -04:00
parent 9d90fb9e52
commit 7bb0910607

View file

@ -98,17 +98,25 @@ void DmaController::RunDma(DmaChannelConfig &channel)
void DmaController::InitHdmaChannels() void DmaController::InitHdmaChannels()
{ {
if(_hdmaChannels) { for(int i = 0; i < 8; i++) {
//Reset internal flags on every frame, whether or not the channels are enabled
_channel[i].HdmaFinished = false;
_channel[i].DoTransfer = false; //not resetting this causes graphical glitches in some games (Aladdin, Super Ghouls and Ghosts)
}
if(!_hdmaChannels) {
//No channels are enabled, no more processing needs to be done
return;
}
//"The overhead is ~18 master cycles" //"The overhead is ~18 master cycles"
_memoryManager->IncrementMasterClockValue<18>(); _memoryManager->IncrementMasterClockValue<18>();
}
for(int i = 0; i < 8; i++) { for(int i = 0; i < 8; i++) {
DmaChannelConfig &ch = _channel[i]; DmaChannelConfig &ch = _channel[i];
//Reset internal flags on every frame //Set DoTransfer to true for all channels if any HDMA channel is enabled
ch.HdmaFinished = false; ch.DoTransfer = true;
ch.DoTransfer = false; //not resetting this causes graphical glitches in some games (Aladdin, Super Ghouls and Ghosts)
if(_hdmaChannels & (1 << i)) { if(_hdmaChannels & (1 << i)) {
//"1. Copy AAddress into Address." //"1. Copy AAddress into Address."
@ -134,9 +142,6 @@ void DmaController::InitHdmaChannels()
//"plus 8 master cycles for each channel set for direct HDMA" //"plus 8 master cycles for each channel set for direct HDMA"
_memoryManager->IncrementMasterClockValue<4>(); _memoryManager->IncrementMasterClockValue<4>();
} }
//4. Set DoTransfer to true.
ch.DoTransfer = true;
} }
} }
} }
@ -175,8 +180,10 @@ void DmaController::RunHdmaTransfer(DmaChannelConfig &channel)
void DmaController::ProcessHdmaChannels() void DmaController::ProcessHdmaChannels()
{ {
bool needOverhead = true; if(!_hdmaChannels) {
if(_hdmaChannels) { return;
}
_hdmaPending = true; _hdmaPending = true;
for(int i = 0; i < 8; i++) { for(int i = 0; i < 8; i++) {
@ -185,6 +192,8 @@ void DmaController::ProcessHdmaChannels()
} }
} }
//Run all the DMA transfers for each channel first, before fetching data for the next scanline
bool needOverhead = true;
for(int i = 0; i < 8; i++) { for(int i = 0; i < 8; i++) {
DmaChannelConfig &ch = _channel[i]; DmaChannelConfig &ch = _channel[i];
if((_hdmaChannels & (1 << i)) == 0 || ch.HdmaFinished) { if((_hdmaChannels & (1 << i)) == 0 || ch.HdmaFinished) {
@ -205,6 +214,14 @@ void DmaController::ProcessHdmaChannels()
//2. For the number of bytes (1, 2, or 4) required for this Transfer Mode... //2. For the number of bytes (1, 2, or 4) required for this Transfer Mode...
RunHdmaTransfer(ch); RunHdmaTransfer(ch);
} }
}
//Update the channel's state & fetch data for the next scanline
for(int i = 0; i < 8; i++) {
DmaChannelConfig &ch = _channel[i];
if((_hdmaChannels & (1 << i)) == 0 || ch.HdmaFinished) {
continue;
}
//3. Decrement $43xA. //3. Decrement $43xA.
ch.HdmaLineCounterAndRepeat--; ch.HdmaLineCounterAndRepeat--;
@ -246,7 +263,6 @@ void DmaController::ProcessHdmaChannels()
//When DMA runs, the next instruction will not check the NMI/IRQ flags, which allows 2 instructions to run after DMA //When DMA runs, the next instruction will not check the NMI/IRQ flags, which allows 2 instructions to run after DMA
_nmiIrqDelayCounter = 2; _nmiIrqDelayCounter = 2;
}
} }
void DmaController::Write(uint16_t addr, uint8_t value) void DmaController::Write(uint16_t addr, uint8_t value)