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

Annotation of /trunk/pcsx2/Sif0.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 62 - (hide annotations) (download)
Tue Sep 7 11:08:22 2010 UTC (10 years, 2 months ago) by william
File size: 9018 byte(s)
Auto Commited Import of: pcsx2-0.9.7-r3738-debug in ./trunk
1 william 31 /* 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    
18     #define _PC_ // disables MIPS opcode macros.
19    
20     #include "IopCommon.h"
21     #include "Sif.h"
22    
23     _sif sif0;
24    
25     static bool done = false;
26    
27 william 62 static __fi void Sif0Init()
28 william 31 {
29     SIF_LOG("SIF0 DMA start...");
30     done = false;
31     sif0.ee.cycles = 0;
32     sif0.iop.cycles = 0;
33     }
34    
35     // Write from Fifo to EE.
36 william 62 static __fi bool WriteFifoToEE()
37 william 31 {
38 william 62 const int readSize = min((s32)sif0dma.qwc, sif0.fifo.size >> 2);
39 william 31
40     tDMA_TAG *ptag;
41    
42 william 62 //SIF_LOG(" EE SIF doing transfer %04Xqw to %08X", readSize, sif0dma.madr);
43     SIF_LOG("Write Fifo to EE: ----------- %lX of %lX", readSize << 2, sif0dma.qwc << 2);
44 william 31
45 william 62 ptag = sif0dma.getAddr(sif0dma.madr, DMAC_SIF0, true);
46 william 31 if (ptag == NULL)
47     {
48     DevCon.Warning("Write Fifo to EE: ptag == NULL");
49     return false;
50     }
51    
52     sif0.fifo.read((u32*)ptag, readSize << 2);
53    
54     // Clearing handled by vtlb memory protection and manual blocks.
55 william 62 //Cpu->Clear(sif0dma.madr, readSize*4);
56 william 31
57 william 62 sif0dma.madr += readSize << 4;
58 william 31 sif0.ee.cycles += readSize; // fixme : BIAS is factored in above
59 william 62 sif0dma.qwc -= readSize;
60 william 31
61     return true;
62     }
63    
64     // Write IOP to Fifo.
65 william 62 static __fi bool WriteIOPtoFifo()
66 william 31 {
67     // There's some data ready to transfer into the fifo..
68     const int writeSize = min(sif0.iop.counter, sif0.fifo.free());
69    
70     SIF_LOG("Write IOP to Fifo: +++++++++++ %lX of %lX", writeSize, sif0.iop.counter);
71    
72     sif0.fifo.write((u32*)iopPhysMem(hw_dma(9).madr), writeSize);
73     hw_dma(9).madr += writeSize << 2;
74    
75     // iop is 1/8th the clock rate of the EE and psxcycles is in words (not quadwords).
76 william 62 sif0.iop.cycles += (writeSize >> 2)/* * BIAS*/; // fixme : should be >> 4
77 william 31 sif0.iop.counter -= writeSize;
78    
79     return true;
80     }
81    
82     // Read Fifo into an ee tag, transfer it to sif0dma, and process it.
83 william 62 static __fi bool ProcessEETag()
84 william 31 {
85     static __aligned16 u32 tag[4];
86    
87     sif0.fifo.read((u32*)&tag[0], 4); // Tag
88     SIF_LOG("SIF0 EE read tag: %x %x %x %x", tag[0], tag[1], tag[2], tag[3]);
89    
90 william 62 sif0dma.unsafeTransfer(((tDMA_TAG*)(tag)));
91     sif0dma.madr = tag[1];
92 william 31 tDMA_TAG ptag(tag[0]);
93    
94     SIF_LOG("SIF0 EE dest chain tag madr:%08X qwc:%04X id:%X irq:%d(%08X_%08X)",
95 william 62 sif0dma.madr, sif0dma.qwc, ptag.ID, ptag.IRQ, tag[1], tag[0]);
96 william 31
97 william 62 if (sif0dma.chcr.TIE && ptag.IRQ)
98 william 31 {
99     //Console.WriteLn("SIF0 TIE");
100     sif0.ee.end = true;
101     }
102    
103     switch (ptag.ID)
104     {
105     case TAG_REFE:
106     sif0.ee.end = true;
107 william 62 if (dmacRegs.ctrl.STS != NO_STS)
108     dmacRegs.stadr.ADDR = sif0dma.madr + (sif0dma.qwc * 16);
109 william 31 break;
110    
111     case TAG_REFS:
112 william 62 if (dmacRegs.ctrl.STS != NO_STS)
113     dmacRegs.stadr.ADDR = sif0dma.madr + (sif0dma.qwc * 16);
114 william 31 break;
115    
116     case TAG_END:
117     sif0.ee.end = true;
118     break;
119     }
120     return true;
121     }
122    
123     // Read Fifo into an iop tag, and transfer it to hw_dma(9). And presumably process it.
124 william 62 static __fi bool ProcessIOPTag()
125 william 31 {
126     // Process DMA tag at hw_dma(9).tadr
127     sif0.iop.data = *(sifData *)iopPhysMem(hw_dma(9).tadr);
128     sif0.iop.data.words = (sif0.iop.data.words + 3) & 0xfffffffc; // Round up to nearest 4.
129     sif0.fifo.write((u32*)iopPhysMem(hw_dma(9).tadr + 8), 4);
130    
131     hw_dma(9).tadr += 16; ///hw_dma(9).madr + 16 + sif0.sifData.words << 2;
132    
133     // We're only copying the first 24 bits.
134     hw_dma(9).madr = sif0data & 0xFFFFFF;
135     sif0.iop.counter = sif0words;
136    
137     if (sif0tag.IRQ || (sif0tag.ID & 4)) sif0.iop.end = true;
138     SIF_LOG("SIF0 IOP Tag: madr=%lx, tadr=%lx, counter=%lx (%08X_%08X)", hw_dma(9).madr, hw_dma(9).tadr, sif0.iop.counter, sif0words, sif0data);
139    
140     return true;
141     }
142    
143     // Stop transferring ee, and signal an interrupt.
144 william 62 static __fi void EndEE()
145 william 31 {
146     SIF_LOG("Sif0: End EE");
147     sif0.ee.end = false;
148     sif0.ee.busy = false;
149     if (sif0.ee.cycles == 0)
150     {
151     SIF_LOG("SIF0 EE: cycles = 0");
152     sif0.ee.cycles = 1;
153     }
154    
155     CPU_INT(DMAC_SIF0, sif0.ee.cycles*BIAS);
156     }
157    
158     // Stop transferring iop, and signal an interrupt.
159 william 62 static __fi void EndIOP()
160 william 31 {
161     SIF_LOG("Sif0: End IOP");
162     sif0data = 0;
163     sif0.iop.end = false;
164     sif0.iop.busy = false;
165    
166     if (sif0.iop.cycles == 0)
167     {
168     DevCon.Warning("SIF0 IOP: cycles = 0");
169     sif0.iop.cycles = 1;
170     }
171     // iop is 1/8th the clock rate of the EE and psxcycles is in words (not quadwords)
172     // So when we're all done, the equation looks like thus:
173     //PSX_INT(IopEvt_SIF0, ( ( sif0.iop.cycles*BIAS ) / 4 ) / 8);
174     PSX_INT(IopEvt_SIF0, sif0.iop.cycles);
175     }
176    
177     // Handle the EE transfer.
178 william 62 static __fi void HandleEETransfer()
179 william 31 {
180 william 62 if(sif0dma.chcr.STR == false)
181 william 31 {
182     DevCon.Warning("Replacement for irq prevention hack EE SIF0");
183     sif0.ee.end = false;
184     sif0.ee.busy = false;
185     return;
186     }
187    
188 william 62 if (dmacRegs.ctrl.STS == STS_SIF0)
189 william 31 {
190     DevCon.Warning("SIF0 stall control");
191     }
192    
193 william 62 /*if (sif0dma.qwc == 0)
194     if (sif0dma.chcr.MOD == NORMAL_MODE)
195 william 31 if (!sif0.ee.end){
196     DevCon.Warning("sif0 irq prevented");
197     done = true;
198     return;
199     }*/
200    
201 william 62 if (sif0dma.qwc <= 0)
202 william 31 {
203 william 62 if ((sif0dma.chcr.MOD == NORMAL_MODE) || sif0.ee.end)
204 william 31 {
205     // Stop transferring ee, and signal an interrupt.
206     done = true;
207     EndEE();
208     }
209     else if (sif0.fifo.size >= 4) // Read a tag
210     {
211     // Read Fifo into an ee tag, transfer it to sif0dma
212     // and process it.
213     ProcessEETag();
214     }
215     }
216    
217 william 62 if (sif0dma.qwc > 0) // If we're writing something, continue to do so.
218 william 31 {
219     // Write from Fifo to EE.
220     if (sif0.fifo.size > 0)
221     {
222     WriteFifoToEE();
223     }
224     }
225     }
226    
227     // Handle the IOP transfer.
228     // Note: Test any changes in this function against Grandia III.
229     // What currently happens is this:
230     // SIF0 DMA start...
231     // SIF + 4 = 4 (pos=4)
232     // SIF0 IOP Tag: madr=19870, tadr=179cc, counter=8 (00000008_80019870)
233     // SIF - 4 = 0 (pos=4)
234     // SIF0 EE read tag: 90000002 935c0 0 0
235     // SIF0 EE dest chain tag madr:000935C0 qwc:0002 id:1 irq:1(000935C0_90000002)
236     // Write Fifo to EE: ----------- 0 of 8
237     // SIF - 0 = 0 (pos=4)
238     // Write IOP to Fifo: +++++++++++ 8 of 8
239     // SIF + 8 = 8 (pos=12)
240     // Write Fifo to EE: ----------- 8 of 8
241     // SIF - 8 = 0 (pos=12)
242     // Sif0: End IOP
243     // Sif0: End EE
244     // SIF0 DMA end...
245    
246     // What happens if (sif0.iop.counter > 0) is handled first is this
247    
248     // SIF0 DMA start...
249     // ...
250     // SIF + 8 = 8 (pos=12)
251     // Sif0: End IOP
252     // Write Fifo to EE: ----------- 8 of 8
253     // SIF - 8 = 0 (pos=12)
254     // SIF0 DMA end...
255    
256 william 62 static __fi void HandleIOPTransfer()
257 william 31 {
258     if (sif0.iop.counter <= 0) // If there's no more to transfer
259     {
260     if (sif0.iop.end)
261     {
262     // Stop transferring iop, and signal an interrupt.
263     done = true;
264     EndIOP();
265     }
266     else
267     {
268     // Read Fifo into an iop tag, and transfer it to hw_dma(9).
269     // And presumably process it.
270     ProcessIOPTag();
271     }
272     }
273     else
274     {
275     // Write IOP to Fifo.
276     if (sif0.fifo.free() > 0)
277     {
278     WriteIOPtoFifo();
279     }
280     }
281     }
282    
283 william 62 static __fi void Sif0End()
284 william 31 {
285     SIF_LOG("SIF0 DMA end...");
286     }
287    
288     // Transfer IOP to EE, putting data in the fifo as an intermediate step.
289 william 62 __fi void SIF0Dma()
290 william 31 {
291     int BusyCheck = 0;
292     Sif0Init();
293    
294     do
295     {
296     //I realise this is very hacky in a way but its an easy way of checking if both are doing something
297     BusyCheck = 0;
298    
299     if (sif0.iop.busy)
300     {
301 william 62 if(sif0.fifo.free() > 0 || (sif0.iop.end == true && sif0.iop.counter == 0))
302     {
303     BusyCheck++;
304     HandleIOPTransfer();
305     }
306 william 31 }
307     if (sif0.ee.busy)
308     {
309 william 62 if(sif0.fifo.size >= 4 || (sif0.ee.end == true && sif0dma.qwc == 0))
310     {
311     BusyCheck++;
312     HandleEETransfer();
313     }
314 william 31 }
315 william 62 } while (/*!done && */BusyCheck > 0); // Substituting (sif0.ee.busy || sif0.iop.busy) breaks things.
316 william 31
317     Sif0End();
318     }
319    
320 william 62 __fi void sif0Interrupt()
321 william 31 {
322     HW_DMA9_CHCR &= ~0x01000000;
323     psxDmaInterrupt2(2);
324     }
325    
326 william 62 __fi void EEsif0Interrupt()
327 william 31 {
328     hwDmacIrq(DMAC_SIF0);
329 william 62 sif0dma.chcr.STR = false;
330 william 31 }
331    
332 william 62 __fi void dmaSIF0()
333 william 31 {
334 william 62 SIF_LOG(wxString(L"dmaSIF0" + sif0dma.cmqt_to_str()).To8BitData());
335 william 31
336     if (sif0.fifo.readPos != sif0.fifo.writePos)
337     {
338     SIF_LOG("warning, sif0.fifoReadPos != sif0.fifoWritePos");
339     }
340    
341 william 62 //if(sif0dma.chcr.MOD == CHAIN_MODE && sif0dma.qwc > 0) DevCon.Warning(L"SIF0 QWC on Chain CHCR " + sif0dma.chcr.desc());
342 william 31 psHu32(SBUS_F240) |= 0x2000;
343     sif0.ee.busy = true;
344    
345 william 62 // Okay, this here is needed currently (r3644).
346     // FFX battles in the thunder plains map die otherwise, Phantasy Star 4 as well
347     // These 2 games could be made playable again by increasing the time the EE or the IOP run,
348     // showing that this is very timing sensible.
349     // Doing this DMA unfortunately brings back an old warning in Legend of Legaia though, but it still works.
350 william 31 if (sif0.iop.busy)
351     {
352 william 62 //hwIntcIrq(INTC_SBUS); // not sure, so let's not
353 william 31 SIF0Dma();
354 william 62 // Do we really want to mess with the SIF flags like that? Nah.
355     //psHu32(SBUS_F240) &= ~0x20;
356     //psHu32(SBUS_F240) &= ~0x2000;
357 william 31 }
358     }

  ViewVC Help
Powered by ViewVC 1.1.22