/[pcsx2_0.9.7]/trunk/pcsx2/IopDma.cpp
ViewVC logotype

Contents of /trunk/pcsx2/IopDma.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 62 - (show annotations) (download)
Tue Sep 7 11:08:22 2010 UTC (10 years, 2 months ago) by william
File size: 18464 byte(s)
Auto Commited Import of: pcsx2-0.9.7-r3738-debug in ./trunk
1 /* PCSX2 - PS2 Emulator for PCs
2 * Copyright (C) 2002-2010 PCSX2 Dev Team
3 *
4 * PCSX2 is free software: you can redistribute it and/or modify it under the terms
5 * of the GNU Lesser General Public License as published by the Free Software Found-
6 * ation, either version 3 of the License, or (at your option) any later version.
7 *
8 * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
9 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
10 * PURPOSE. See the GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License along with PCSX2.
13 * If not, see <http://www.gnu.org/licenses/>.
14 */
15
16 #include "PrecompiledHeader.h"
17 #include "IopCommon.h"
18
19 #include "Sif.h"
20
21 using namespace R3000A;
22
23 // Dma0/1 in Mdec.c
24 // Dma3 in CdRom.c
25 // Dma8 in PsxSpd.c
26 // Dma11/12 in PsxSio2.c
27
28 #ifndef ENABLE_NEW_IOPDMA_SPU2
29 static void __fastcall psxDmaGeneric(u32 madr, u32 bcr, u32 chcr, u32 spuCore, _SPU2writeDMA4Mem spu2WriteFunc, _SPU2readDMA4Mem spu2ReadFunc)
30 {
31 const char dmaNum = spuCore ? '7' : '4';
32
33 /*if (chcr & 0x400) DevCon.Status("SPU 2 DMA %c linked list chain mode! chcr = %x madr = %x bcr = %x\n", dmaNum, chcr, madr, bcr);
34 if (chcr & 0x40000000) DevCon.Warning("SPU 2 DMA %c Unusual bit set on 'to' direction chcr = %x madr = %x bcr = %x\n", dmaNum, chcr, madr, bcr);
35 if ((chcr & 0x1) == 0) DevCon.Status("SPU 2 DMA %c loading from spu2 memory chcr = %x madr = %x bcr = %x\n", dmaNum, chcr, madr, bcr);*/
36
37 const int size = (bcr >> 16) * (bcr & 0xFFFF);
38
39 // Update the spu2 to the current cycle before initiating the DMA
40
41 if (SPU2async)
42 {
43 SPU2async(psxRegs.cycle - psxCounters[6].sCycleT);
44 //Console.Status("cycles sent to SPU2 %x\n", psxRegs.cycle - psxCounters[6].sCycleT);
45
46 psxCounters[6].sCycleT = psxRegs.cycle;
47 psxCounters[6].CycleT = size * 3;
48
49 psxNextCounter -= (psxRegs.cycle - psxNextsCounter);
50 psxNextsCounter = psxRegs.cycle;
51 if (psxCounters[6].CycleT < psxNextCounter)
52 psxNextCounter = psxCounters[6].CycleT;
53
54 if((g_iopNextEventCycle - psxNextsCounter) > (u32)psxNextCounter)
55 {
56 //DevCon.Warning("SPU2async Setting new counter branch, old %x new %x ((%x - %x = %x) > %x delta)", g_iopNextEventCycle, psxNextsCounter + psxNextCounter, g_iopNextEventCycle, psxNextsCounter, (g_iopNextEventCycle - psxNextsCounter), psxNextCounter);
57 g_iopNextEventCycle = psxNextsCounter + psxNextCounter;
58 }
59 }
60
61 switch (chcr)
62 {
63 case 0x01000201: //cpu to spu2 transfer
64 PSXDMA_LOG("*** DMA %c - mem2spu *** %x addr = %x size = %x", dmaNum, chcr, madr, bcr);
65 spu2WriteFunc((u16 *)iopPhysMem(madr), size*2);
66 break;
67
68 case 0x01000200: //spu2 to cpu transfer
69 PSXDMA_LOG("*** DMA %c - spu2mem *** %x addr = %x size = %x", dmaNum, chcr, madr, bcr);
70 spu2ReadFunc((u16 *)iopPhysMem(madr), size*2);
71 psxCpu->Clear(spuCore ? HW_DMA7_MADR : HW_DMA4_MADR, size);
72 break;
73
74 default:
75 Console.Error("*** DMA %c - SPU unknown *** %x addr = %x size = %x", dmaNum, chcr, madr, bcr);
76 break;
77 }
78 }
79
80 void psxDma4(u32 madr, u32 bcr, u32 chcr) // SPU2's Core 0
81 {
82 psxDmaGeneric(madr, bcr, chcr, 0, SPU2writeDMA4Mem, SPU2readDMA4Mem);
83 }
84
85 int psxDma4Interrupt()
86 {
87 #ifdef SPU2IRQTEST
88 Console.Warning("psxDma4Interrupt()");
89 #endif
90 HW_DMA4_CHCR &= ~0x01000000;
91 psxDmaInterrupt(4);
92 iopIntcIrq(9);
93 return 1;
94 }
95
96 void spu2DMA4Irq()
97 {
98 #ifdef SPU2IRQTEST
99 Console.Warning("spu2DMA4Irq()");
100 #endif
101 SPU2interruptDMA4();
102 HW_DMA4_CHCR &= ~0x01000000;
103 psxDmaInterrupt(4);
104 }
105
106 void psxDma7(u32 madr, u32 bcr, u32 chcr) // SPU2's Core 1
107 {
108 psxDmaGeneric(madr, bcr, chcr, 1, SPU2writeDMA7Mem, SPU2readDMA7Mem);
109 }
110
111 int psxDma7Interrupt()
112 {
113 #ifdef SPU2IRQTEST
114 Console.Warning("psxDma7Interrupt()");
115 #endif
116 HW_DMA7_CHCR &= ~0x01000000;
117 psxDmaInterrupt2(0);
118 return 1;
119
120 }
121
122 void spu2DMA7Irq()
123 {
124 #ifdef SPU2IRQTEST
125 Console.Warning("spu2DMA7Irq()");
126 #endif
127 SPU2interruptDMA7();
128 HW_DMA7_CHCR &= ~0x01000000;
129 psxDmaInterrupt2(0);
130 }
131
132 #endif
133
134 #ifndef DISABLE_PSX_GPU_DMAS
135 void psxDma2(u32 madr, u32 bcr, u32 chcr) // GPU
136 {
137 HW_DMA2_CHCR &= ~0x01000000;
138 psxDmaInterrupt(2);
139 }
140
141 void psxDma6(u32 madr, u32 bcr, u32 chcr)
142 {
143 u32 *mem = (u32 *)iopPhysMem(madr);
144
145 PSXDMA_LOG("*** DMA 6 - OT *** %lx addr = %lx size = %lx", chcr, madr, bcr);
146
147 if (chcr == 0x11000002)
148 {
149 while (bcr--)
150 {
151 *mem-- = (madr - 4) & 0xffffff;
152 madr -= 4;
153 }
154 mem++;
155 *mem = 0xffffff;
156 }
157 else
158 {
159 // Unknown option
160 PSXDMA_LOG("*** DMA 6 - OT unknown *** %lx addr = %lx size = %lx", chcr, madr, bcr);
161 }
162 HW_DMA6_CHCR &= ~0x01000000;
163 psxDmaInterrupt(6);
164 }
165 #endif
166
167 #ifndef ENABLE_NEW_IOPDMA_DEV9
168 void psxDma8(u32 madr, u32 bcr, u32 chcr)
169 {
170 const int size = (bcr >> 16) * (bcr & 0xFFFF) * 8;
171
172 switch (chcr & 0x01000201)
173 {
174 case 0x01000201: //cpu to dev9 transfer
175 PSXDMA_LOG("*** DMA 8 - DEV9 mem2dev9 *** %lx addr = %lx size = %lx", chcr, madr, bcr);
176 DEV9writeDMA8Mem((u32*)iopPhysMem(madr), size);
177 break;
178
179 case 0x01000200: //dev9 to cpu transfer
180 PSXDMA_LOG("*** DMA 8 - DEV9 dev9mem *** %lx addr = %lx size = %lx", chcr, madr, bcr);
181 DEV9readDMA8Mem((u32*)iopPhysMem(madr), size);
182 break;
183
184 default:
185 PSXDMA_LOG("*** DMA 8 - DEV9 unknown *** %lx addr = %lx size = %lx", chcr, madr, bcr);
186 break;
187 }
188 HW_DMA8_CHCR &= ~0x01000000;
189 psxDmaInterrupt2(1);
190 }
191 #endif
192
193 void psxDma9(u32 madr, u32 bcr, u32 chcr)
194 {
195 SIF_LOG("IOP: dmaSIF0 chcr = %lx, madr = %lx, bcr = %lx, tadr = %lx", chcr, madr, bcr, HW_DMA9_TADR);
196
197 sif0.iop.busy = true;
198 psHu32(SBUS_F240) |= 0x2000;
199
200 /*if (sif0.ee.busy)
201 {*/
202 SIF0Dma();
203 psHu32(SBUS_F240) &= ~0x20;
204 psHu32(SBUS_F240) &= ~0x2000;
205 //}
206 }
207
208 void psxDma10(u32 madr, u32 bcr, u32 chcr)
209 {
210 SIF_LOG("IOP: dmaSIF1 chcr = %lx, madr = %lx, bcr = %lx", chcr, madr, bcr);
211
212 sif1.iop.busy = true;
213 psHu32(SBUS_F240) |= 0x4000;
214
215 /*if (sif1.ee.busy)
216 {*/
217 SIF1Dma();
218 psHu32(SBUS_F240) &= ~0x40;
219 psHu32(SBUS_F240) &= ~0x100;
220 psHu32(SBUS_F240) &= ~0x4000;
221 //}
222 }
223
224 /* psxDma11 & psxDma 12 are in IopSio2.cpp, along with the appropriate interrupt functions. */
225
226 //////////////////////////////////////////////////////////////////////////////////////////////
227 //
228 // Gigaherz's "Improved DMA Handling" Engine WIP...
229 //
230
231 #ifdef ENABLE_NEW_IOPDMA
232
233 //////////////////////////////////////////////////////////////////////////////////////////////
234 // Local Declarations
235
236 // in IopSio2.cpp
237 extern s32 CALLBACK sio2DmaStart(s32 channel, u32 madr, u32 bcr, u32 chcr);
238 extern s32 CALLBACK sio2DmaRead(s32 channel, u32* data, u32 bytesLeft, u32* bytesProcessed);
239 extern s32 CALLBACK sio2DmaWrite(s32 channel, u32* data, u32 bytesLeft, u32* bytesProcessed);
240 extern void CALLBACK sio2DmaInterrupt(s32 channel);
241
242 // implemented below
243 s32 CALLBACK errDmaWrite(s32 channel, u32* data, u32 bytesLeft, u32* bytesProcessed);
244 s32 CALLBACK errDmaRead(s32 channel, u32* data, u32 bytesLeft, u32* bytesProcessed);
245
246 // pointer types
247 typedef s32 (CALLBACK * DmaHandler)(s32 channel, u32* data, u32 bytesLeft, u32* bytesProcessed);
248 typedef void (CALLBACK * DmaIHandler)(s32 channel);
249 typedef s32 (CALLBACK * DmaSHandler)(s32 channel, u32 madr, u32 bcr, u32 chcr);
250
251 // constants
252 struct DmaHandlerInfo
253 {
254 const char* Name;
255
256 // doubles as a "disable" flag
257 u32 DirectionFlags;
258 u32 DmacRegisterBase;
259 DmaHandler Read;
260 DmaHandler Write;
261 DmaIHandler Interrupt;
262 DmaSHandler Start;
263
264 __fi u32& REG_MADR(void) const { return psxHu32(DmacRegisterBase + 0x0); }
265 __fi u32& REG_BCR(void) const { return psxHu32(DmacRegisterBase + 0x4); }
266 __fi u32& REG_CHCR(void) const { return psxHu32(DmacRegisterBase + 0x8); }
267 __fi u32& REG_TADR(void) const { return psxHu32(DmacRegisterBase + 0xC); }
268 };
269
270 #define MEM_BASE1 0x1f801080
271 #define MEM_BASE2 0x1f801500
272
273 #define CHANNEL_BASE1(ch) (MEM_BASE1 + ((ch)<<4))
274 #define CHANNEL_BASE2(ch) (MEM_BASE2 + ((ch)<<4))
275
276 // channel disabled
277 #define _D__ 0
278 #define _D_W 1
279 #define _DR_ 2
280 #define _DRW 3
281 // channel enabled
282 #define _E__ 4
283 #define _E_W 5
284 #define _ER_ 6
285 #define _ERW 7
286
287 //////////////////////////////////////////////////////////////////////////////////////////////
288 // Plugin interface accessors
289
290 #ifdef ENABLE_NEW_IOPDMA_SPU2
291 s32 CALLBACK spu2DmaRead (s32 channel, u32* data, u32 bytesLeft, u32* bytesProcessed) { return SPU2dmaRead(channel,data,bytesLeft,bytesProcessed); }
292 s32 CALLBACK spu2DmaWrite (s32 channel, u32* data, u32 bytesLeft, u32* bytesProcessed) { return SPU2dmaWrite(channel,data,bytesLeft,bytesProcessed); }
293 void CALLBACK spu2DmaInterrupt (s32 channel) { SPU2dmaInterrupt(channel); }
294 #else
295 s32 CALLBACK spu2DmaRead (s32 channel, u32* data, u32 bytesLeft, u32* bytesProcessed) { *bytesProcessed=0; return 0; }
296 s32 CALLBACK spu2DmaWrite (s32 channel, u32* data, u32 bytesLeft, u32* bytesProcessed) { *bytesProcessed=0; return 0; }
297 void CALLBACK spu2DmaInterrupt (s32 channel) { }
298 #endif
299 #ifdef ENABLE_NEW_IOPDMA_DEV9
300 s32 CALLBACK dev9DmaRead (s32 channel, u32* data, u32 bytesLeft, u32* bytesProcessed) { return DEV9dmaRead(channel,data,bytesLeft,bytesProcessed); }
301 s32 CALLBACK dev9DmaWrite (s32 channel, u32* data, u32 bytesLeft, u32* bytesProcessed) { return DEV9dmaWrite(channel,data,bytesLeft,bytesProcessed); }
302 void CALLBACK dev9DmaInterrupt (s32 channel) { DEV9dmaInterrupt(channel); }
303 #else
304 s32 CALLBACK dev9DmaRead (s32 channel, u32* data, u32 bytesLeft, u32* bytesProcessed) { *bytesProcessed=0; return 0; }
305 s32 CALLBACK dev9DmaWrite (s32 channel, u32* data, u32 bytesLeft, u32* bytesProcessed) { *bytesProcessed=0; return 0; }
306 void CALLBACK dev9DmaInterrupt (s32 channel) { }
307 #endif
308
309 //////////////////////////////////////////////////////////////////////////////////////////////
310 // Dma channel definitions
311
312 const DmaHandlerInfo IopDmaHandlers[DMA_CHANNEL_MAX] =
313 {
314 // First DMAC, same as PS1
315 {"Ps1 Mdec in", _D__}, //0
316 {"Ps1 Mdec out", _D__}, //1
317 {"Ps1 Gpu", _D__}, //2
318 #ifdef ENABLE_NEW_IOPDMA_CDVD
319 {"CDVD", _ER_, CHANNEL_BASE1(3), cdvdDmaRead, errDmaWrite, cdvdDmaInterrupt}, //3: CDVD
320 #else
321 {"CDVD", _D__}, //3: CDVD
322 #endif
323 #ifdef ENABLE_NEW_IOPDMA_SPU2
324 {"SPU2 Core0", _ERW, CHANNEL_BASE1(4), spu2DmaRead, spu2DmaWrite, spu2DmaInterrupt}, //4: Spu/Spu2 Core0
325 #else
326 {"SPU2 Core0", _D__}, //4: Spu/Spu2 Core0
327 #endif
328 {"Ps1 PIO", _D__}, //5: PIO
329 {"Ps1 OTC", _D__}, //6: "reverse clear OT" - PSX GPU related
330
331 // Second DMAC, new in PS2 IOP
332 #ifdef ENABLE_NEW_IOPDMA_SPU2
333 {"SPU2 Core1", _ERW, CHANNEL_BASE2(0), spu2DmaRead, spu2DmaWrite, spu2DmaInterrupt}, //7: Spu2 Core1
334 #else
335 {"SPU2 Core1", _D__}, //7: Spu2 Core1
336 #endif
337 #ifdef ENABLE_NEW_IOPDMA_DEV9
338 {"Dev9", _ERW, CHANNEL_BASE2(1), dev9DmaRead, dev9DmaWrite, dev9DmaInterrupt}, //8: Dev9
339 #else
340 {"Dev9", _D__}, //8: Dev9
341 #endif
342 #ifdef ENABLE_NEW_IOPDMA_SIF
343 {"Sif0", _ERW, CHANNEL_BASE2(2), sif0DmaRead, sif0DmaWrite, sif0DmaInterrupt}, //9: SIF0
344 {"Sif1", _ERW, CHANNEL_BASE2(3), sif1DmaRead, sif1DmaWrite, sif1DmaInterrupt}, //10: SIF1
345 #else
346 {"Sif0", _D__}, //9: SIF0
347 {"Sif1", _D__}, //10: SIF1
348 #endif
349 #ifdef ENABLE_NEW_IOPDMA_SIO
350 {"Sio2 (writes)", _E_W, CHANNEL_BASE2(4), errDmaRead, sio2DmaWrite, sio2DmaInterrupt, sio2DmaStart}, //11: Sio2
351 {"Sio2 (reads)", _ER_, CHANNEL_BASE2(5), sio2DmaRead, errDmaWrite, sio2DmaInterrupt, sio2DmaStart}, //12: Sio2
352 #else
353 {"Sio2 (writes)", _D__}, //11: Sio2
354 {"Sio2 (reads)", _D__}, //12: Sio2
355 #endif
356 {"?", _D__}, //13
357 // if each dmac has 7 channels, the list would end here, but I'm not sure :p
358 };
359
360 // runtime variables
361 struct DmaChannelInfo
362 {
363 s32 ByteCount;
364 s32 NextUpdate;
365 } IopDmaChannels[DMA_CHANNEL_MAX] = {0};
366
367
368 //////////////////////////////////////////////////////////////////////////////////////////////
369 // Tool functions
370 void SetDmaUpdateTarget(u32 delay)
371 {
372 psxCounters[8].CycleT = delay;
373 if (delay < psxNextCounter)
374 psxNextCounter = delay;
375 }
376
377 void RaiseDmaIrq(u32 channel)
378 {
379 if(channel<7)
380 psxDmaInterrupt(channel);
381 else
382 psxDmaInterrupt2(channel-7);
383 }
384
385 //////////////////////////////////////////////////////////////////////////////////////////////
386 // IopDmaStart: Called from IopHwWrite to test and possibly start a dma transfer
387
388 void IopDmaStart(int channel)
389 {
390 if(!(IopDmaHandlers[channel].DirectionFlags&_E__))
391 return;
392
393 int chcr = IopDmaHandlers[channel].REG_CHCR();
394
395 int pcr = (channel>=7)?(HW_DMA_PCR2 & (8 << ((channel-7) * 4))):(HW_DMA_PCR & (8 << (channel * 4)));
396
397 if ( !(chcr & 0x01000000) || !pcr)
398 return;
399
400 // I dont' really understand this, but it's used above. Is this BYTES OR WHAT?
401 int bcr = IopDmaHandlers[channel].REG_BCR();
402 int bcr_size = (bcr & 0xFFFF);
403 int bcr_count = (bcr >> 16);
404 int size = 4* bcr_count * bcr_size;
405
406 int dirf = IopDmaHandlers[channel].DirectionFlags&3;
407
408 if(dirf != 3)
409 {
410 bool ok = (chcr & DMA_CTRL_DIRECTION)? (dirf==_D_W) : (dirf==_DR_);
411 if(!ok)
412 {
413 // hack?!
414 IopDmaHandlers[channel].REG_CHCR() &= ~DMA_CTRL_ACTIVE;
415 return;
416 }
417 }
418
419 if(IopDmaHandlers[channel].Start)
420 {
421 int ret = IopDmaHandlers[channel].Start(channel,
422 IopDmaHandlers[channel].REG_MADR(),
423 IopDmaHandlers[channel].REG_BCR(),
424 IopDmaHandlers[channel].REG_CHCR());
425 if(ret < 0)
426 {
427 IopDmaHandlers[channel].REG_CHCR() &= ~DMA_CTRL_ACTIVE;
428 return;
429 }
430 }
431
432 //Console.WriteLn(Color_StrongOrange,"Starting NewDMA ch=%d, size=%d(0x%08x), dir=%d", channel, size, bcr, chcr&DMA_CTRL_DIRECTION);
433
434 IopDmaHandlers[channel].REG_CHCR() |= DMA_CTRL_ACTIVE;
435 IopDmaChannels[channel].ByteCount = size;
436 IopDmaChannels[channel].NextUpdate = 0;
437
438 //SetDmaUpdateTarget(1);
439 {
440 const s32 difference = psxRegs.cycle - psxCounters[8].sCycleT;
441
442 psxCounters[8].sCycleT = psxRegs.cycle;
443 psxCounters[8].CycleT = psxCounters[8].rate;
444 IopDmaUpdate(difference);
445
446 s32 c = psxCounters[8].CycleT;
447 if (c < psxNextCounter) psxNextCounter = c;
448 }
449 }
450
451 //////////////////////////////////////////////////////////////////////////////////////////////
452 // IopDmaProcessChannel: Called from IopDmaUpdate (below) to process a dma channel
453
454 template<int channel>
455 static void __ri IopDmaProcessChannel(int elapsed, int& MinDelay)
456 {
457 // Hopefully the compiler would be able to optimize the whole function away if this doesn't pass.
458 if(!(IopDmaHandlers[channel].DirectionFlags&_E__))
459 return;
460
461 DmaChannelInfo *ch = IopDmaChannels + channel;
462 const DmaHandlerInfo *hh = IopDmaHandlers + channel;
463
464 if (hh->REG_CHCR()&DMA_CTRL_ACTIVE)
465 {
466 ch->NextUpdate -= elapsed;
467 if (ch->NextUpdate <= 0) // Refresh target passed
468 {
469 if (ch->ByteCount <= 0) // No more data left, finish dma
470 {
471 ch->NextUpdate = 0x7fffffff;
472
473 hh->REG_CHCR() &= ~DMA_CTRL_ACTIVE;
474 RaiseDmaIrq(channel);
475 hh->Interrupt(channel);
476 }
477 else // let the handlers transfer more data
478 {
479 int chcr = hh->REG_CHCR();
480
481 DmaHandler handler = (chcr & DMA_CTRL_DIRECTION) ? hh->Write : hh->Read;
482
483 u32 ProcessedBytes = 0;
484 s32 RequestedDelay = (handler) ? handler(channel, (u32*)iopPhysMem(hh->REG_MADR()), ch->ByteCount, &ProcessedBytes) : 0;
485
486 if(ProcessedBytes>0 && (!(chcr & DMA_CTRL_DIRECTION)))
487 {
488 psxCpu->Clear(hh->REG_MADR(), ProcessedBytes/4);
489 }
490
491 int NextUpdateDelay = 100;
492 if (RequestedDelay < 0) // error code
493 {
494 // TODO: ... What to do if the handler gives an error code? :P
495 DevCon.Warning("ERROR on channel %d",channel);
496 hh->REG_CHCR() &= ~DMA_CTRL_ACTIVE;
497 RaiseDmaIrq(channel);
498 hh->Interrupt(channel);
499 }
500 else if (ProcessedBytes > 0) // if not an error, continue transfer
501 {
502 //DevCon.WriteLn("Transfer channel %d, ProcessedBytes = %d",i,ProcessedBytes);
503 hh->REG_MADR()+= ProcessedBytes;
504 ch->ByteCount -= ProcessedBytes;
505
506 NextUpdateDelay = ProcessedBytes/2; // / ch->Width;
507 }
508 else if(RequestedDelay==0)
509 DevCon.Warning("What now? :p"); // its ok as long as there's a delay requeste, autodma requires this.
510
511 if (RequestedDelay != 0) NextUpdateDelay = RequestedDelay;
512
513 // SPU2 adma early interrupts. PCSX2 likes those better currently.
514 if((channel==4 || channel==7) && (ch->ByteCount<=0) && (ProcessedBytes <= 1024))
515 {
516 ch->NextUpdate = 0;
517 }
518 else
519 ch->NextUpdate += NextUpdateDelay;
520
521 //ch->NextUpdate += NextUpdateDelay;
522 }
523 }
524
525 int nTarget = ch->NextUpdate;
526 if(nTarget < 0) nTarget = 0;
527
528 if (nTarget<MinDelay)
529 MinDelay = nTarget;
530 }
531 }
532
533 //////////////////////////////////////////////////////////////////////////////////////////////
534 // IopDmaProcessChannel: Called regularly to update the active channels
535
536 void IopDmaUpdate(u32 elapsed)
537 {
538 s32 MinDelay=0;
539
540 do {
541 MinDelay = 0x7FFFFFFF; // max possible value
542
543 // Unrolled
544 //IopDmaProcessChannel<0>(elapsed, MinDelay);
545 //IopDmaProcessChannel<1>(elapsed, MinDelay);
546 //IopDmaProcessChannel<2>(elapsed, MinDelay);
547 IopDmaProcessChannel<3>(elapsed, MinDelay);
548 IopDmaProcessChannel<4>(elapsed, MinDelay);
549 //IopDmaProcessChannel<5>(elapsed, MinDelay);
550 //IopDmaProcessChannel<6>(elapsed, MinDelay);
551 IopDmaProcessChannel<7>(elapsed, MinDelay);
552 IopDmaProcessChannel<8>(elapsed, MinDelay);
553 IopDmaProcessChannel<9>(elapsed, MinDelay);
554 IopDmaProcessChannel<10>(elapsed, MinDelay);
555 IopDmaProcessChannel<11>(elapsed, MinDelay);
556 IopDmaProcessChannel<12>(elapsed, MinDelay);
557 //IopDmaProcessChannel<13>(elapsed, MinDelay);
558
559 // reset elapsed time in case we loop
560 elapsed=0;
561 }
562 while(MinDelay <= 0);
563
564 if(MinDelay<0x7FFFFFFF)
565 {
566 // tell the iop when to call this function again
567 SetDmaUpdateTarget(MinDelay);
568 }
569 else
570 {
571 // bogus value so the function gets called again, not sure if it's necessary anymore
572 SetDmaUpdateTarget(10000);
573 }
574 }
575
576 //////////////////////////////////////////////////////////////////////////////////////////////
577 // Error functions: dummy functions for unsupported dma "directions"
578
579 s32 CALLBACK errDmaRead(s32 channel, u32* data, u32 bytesLeft, u32* bytesProcessed)
580 {
581 Console.Error("ERROR: Tried to read using DMA %d (%s). Ignoring.", channel, IopDmaHandlers[channel]);
582
583 *bytesProcessed = bytesLeft;
584 return 0;
585 }
586
587 s32 CALLBACK errDmaWrite(s32 channel, u32* data, u32 bytesLeft, u32* bytesProcessed)
588 {
589 Console.Error("ERROR: Tried to write using DMA %d (%s). Ignoring.", channel, IopDmaHandlers[channel]);
590
591 *bytesProcessed = bytesLeft;
592 return 0;
593 }
594
595 void SaveStateBase::iopDmacFreeze()
596 {
597 FreezeTag("iopDmac");
598
599 Freeze(IopDmaChannels);
600
601 if( IsLoading() )
602 {
603 SetDmaUpdateTarget(10000); // Might be needed to kickstart the main updater :p
604 }
605 }
606
607 #endif

  ViewVC Help
Powered by ViewVC 1.1.22