MCPcopy Create free account
hub / github.com/PCSX2/pcsx2 / DmaExec

Function DmaExec

pcsx2/Dmac.cpp:213–282  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

211}
212
213static __ri void DmaExec( void (*func)(), u32 mem, u32 value )
214{
215 DMACh& reg = (DMACh&)psHu32(mem);
216 tDMA_CHCR chcr(value);
217
218 //It's invalid for the hardware to write a DMA while it is active, not without Suspending the DMAC
219 if (reg.chcr.STR)
220 {
221 const uint channel = ChannelNumber(mem);
222
223 //As the manual states "Fields other than STR can only be written to when the DMA is stopped"
224 //Also "The DMA may not stop properly just by writing 0 to STR"
225 //So the presumption is that STR can be written to (ala force stop the DMA) but nothing else
226 //If the developer wishes to alter any of the other fields, it must be done AFTER the STR has been written,
227 //it will not work before or during this event.
228 if(chcr.STR == 0)
229 {
230 //DevCon.Warning(L"32bit Force Stopping %s (Current CHCR %x) while DMA active", ChcrName(mem), reg.chcr._u32, chcr._u32);
231 reg.chcr.STR = 0;
232 //We need to clear any existing DMA loops that are in progress else they will continue!
233
234 if(channel == 1)
235 {
236 cpuClearInt( 10 );
237 QueuedDMA._u16 &= ~(1 << 10); //Clear any queued DMA requests for this channel
238 }
239 else if (channel == 2)
240 {
241 cpuClearInt( 11 );
242 QueuedDMA._u16 &= ~(1 << 11); //Clear any queued DMA requests for this channel
243 }
244
245 cpuClearInt( channel );
246 QueuedDMA._u16 &= ~(1 << channel); //Clear any queued DMA requests for this channel
247 }
248 //else DevCon.Warning(L"32bit Attempted to change %s CHCR (Currently %x) with %x while DMA active, ignoring QWC = %x", ChcrName(mem), reg.chcr._u32, chcr._u32, reg.qwc);
249 return;
250 }
251
252 //if(reg.chcr.TAG != chcr.TAG && chcr.MOD == CHAIN_MODE) DevCon.Warning(L"32bit CHCR Tag on %s changed to %x from %x QWC = %x Channel Not Active", ChcrName(mem), chcr.TAG, reg.chcr.TAG, reg.qwc);
253
254 reg.chcr.set(value);
255
256 //Final Fantasy XII sets the DMA Mode to 3 which doesn't exist. On some channels (like SPR) this will break logic completely. so lets assume they mean chain.
257 if (reg.chcr.MOD == 0x3)
258 {
259 static bool warned; //Check if the warning has already been output to console, to prevent constant spam.
260 if (!warned)
261 {
262 DevCon.Warning("%s CHCR.MOD set to 3, assuming 1 (chain)", ChcrName(mem));
263 warned = true;
264 }
265 reg.chcr.MOD = 0x1;
266 }
267
268 // As tested on hardware, if NORMAL mode is started with 0 QWC it will actually transfer 1 QWC then underflows and transfer another 0xFFFF QWC's
269 // The easiest way to handle this is to just say 0x10000 QWC
270 if (reg.chcr.STR && !reg.chcr.MOD && reg.qwc == 0)

Callers 2

dmacWrite32Function · 0.85
_HwWrite_16or32_Page1Function · 0.85

Calls 5

ChannelNumberFunction · 0.85
cpuClearIntFunction · 0.85
ChcrNameFunction · 0.85
setMethod · 0.45
WarningMethod · 0.45

Tested by

no test coverage detected