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

Annotation of /trunk/pcsx2/Sif1.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 31 - (hide annotations) (download)
Tue Sep 7 03:24:11 2010 UTC (9 years, 9 months ago) by william
File size: 7909 byte(s)
committing r3113 initial commit again...
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 sif1;
24    
25     static bool done = false;
26    
27     static __forceinline void Sif1Init()
28     {
29     SIF_LOG("SIF1 DMA start...");
30     done = false;
31     sif1.ee.cycles = 0;
32     sif1.iop.cycles = 0;
33     }
34    
35     // Write from the EE to Fifo.
36     static __forceinline bool WriteEEtoFifo()
37     {
38     // There's some data ready to transfer into the fifo..
39    
40     SIF_LOG("Sif 1: Write EE to Fifo");
41     const int writeSize = min((s32)sif1dma->qwc, sif1.fifo.free() >> 2);
42    
43     tDMA_TAG *ptag;
44    
45     ptag = sif1dma->getAddr(sif1dma->madr, DMAC_SIF1, false);
46     if (ptag == NULL)
47     {
48     DevCon.Warning("Write EE to Fifo: ptag == NULL");
49     return false;
50     }
51    
52     sif1.fifo.write((u32*)ptag, writeSize << 2);
53    
54     sif1dma->madr += writeSize << 4;
55     sif1.ee.cycles += writeSize; // fixme : BIAS is factored in above
56     sif1dma->qwc -= writeSize;
57    
58     return true;
59     }
60    
61     // Read from the fifo and write to IOP
62     static __forceinline bool WriteFifoToIOP()
63     {
64     // If we're reading something, continue to do so.
65    
66     SIF_LOG("Sif1: Write Fifo to IOP");
67     const int readSize = min (sif1.iop.counter, sif1.fifo.size);
68    
69     SIF_LOG("Sif 1 IOP doing transfer %04X to %08X", readSize, HW_DMA10_MADR);
70    
71     sif1.fifo.read((u32*)iopPhysMem(hw_dma(10).madr), readSize);
72     psxCpu->Clear(hw_dma(10).madr, readSize);
73     hw_dma(10).madr += readSize << 2;
74     sif1.iop.cycles += readSize >> 2; // fixme: should be >> 4
75     sif1.iop.counter -= readSize;
76    
77     return true;
78     }
79    
80     // Get a tag and process it.
81     static __forceinline bool ProcessEETag()
82     {
83     // Chain mode
84     tDMA_TAG *ptag;
85     SIF_LOG("Sif1: ProcessEETag");
86    
87     // Process DMA tag at sif1dma->tadr
88     ptag = sif1dma->DMAtransfer(sif1dma->tadr, DMAC_SIF1);
89     if (ptag == NULL)
90     {
91     Console.WriteLn("Sif1 ProcessEETag: ptag = NULL");
92     return false;
93     }
94    
95     if (sif1dma->chcr.TTE)
96     {
97     Console.WriteLn("SIF1 TTE");
98     sif1.fifo.write((u32*)ptag + 2, 2);
99     }
100    
101     if (sif1dma->chcr.TIE && ptag->IRQ)
102     {
103     Console.WriteLn("SIF1 TIE");
104     sif1.ee.end = true;
105     }
106    
107     SIF_LOG(wxString(ptag->tag_to_str()).To8BitData());
108     switch (ptag->ID)
109     {
110     case TAG_REFE:
111     sif1.ee.end = true;
112     sif1dma->madr = ptag[1]._u32;
113     sif1dma->tadr += 16;
114     break;
115    
116     case TAG_CNT:
117     sif1dma->madr = sif1dma->tadr + 16;
118     sif1dma->tadr = sif1dma->madr + (sif1dma->qwc << 4);
119     break;
120    
121     case TAG_NEXT:
122     sif1dma->madr = sif1dma->tadr + 16;
123     sif1dma->tadr = ptag[1]._u32;
124     break;
125    
126     case TAG_REF:
127     case TAG_REFS:
128     sif1dma->madr = ptag[1]._u32;
129     sif1dma->tadr += 16;
130     break;
131    
132     case TAG_END:
133     sif1.ee.end = true;
134     sif1dma->madr = sif1dma->tadr + 16;
135     sif1dma->tadr = sif1dma->madr + (sif1dma->qwc << 4);
136     break;
137    
138     default:
139     Console.WriteLn("Bad addr1 source chain");
140     }
141     return true;
142     }
143    
144     // Write fifo to data, and put it in IOP.
145     static __forceinline bool SIFIOPReadTag()
146     {
147     // Read a tag.
148     sif1.fifo.read((u32*)&sif1.iop.data, 4);
149     //sif1words = (sif1words + 3) & 0xfffffffc; // Round up to nearest 4.
150     SIF_LOG("SIF 1 IOP: dest chain tag madr:%08X wc:%04X id:%X irq:%d",
151     sif1data & 0xffffff, sif1words, sif1tag.ID, sif1tag.IRQ);
152    
153     // Only use the first 24 bits.
154     hw_dma(10).madr = sif1data & 0xffffff;
155    
156     sif1.iop.counter = sif1words;
157     if (sif1tag.IRQ || (sif1tag.ID & 4)) sif1.iop.end = true;
158    
159     return true;
160     }
161    
162     // Stop processing EE, and signal an interrupt.
163     static __forceinline void EndEE()
164     {
165     sif1.ee.end = false;
166     sif1.ee.busy = false;
167     SIF_LOG("Sif 1: End EE");
168    
169     // Voodoocycles : Okami wants around 100 cycles when booting up
170     // Other games reach like 50k cycles here, but the EE will long have given up by then and just retry.
171     // (Cause of double interrupts on the EE)
172     if (sif1.ee.cycles == 0)
173     {
174     SIF_LOG("SIF1 EE: cycles = 0");
175     sif1.ee.cycles = 1;
176     }
177    
178    
179     CPU_INT(DMAC_SIF1, min((int)(sif1.ee.cycles*BIAS), 384));
180     }
181    
182     // Stop processing IOP, and signal an interrupt.
183     static __forceinline void EndIOP()
184     {
185     sif1data = 0;
186     sif1.iop.end = false;
187     sif1.iop.busy = false;
188     SIF_LOG("Sif 1: End IOP");
189    
190     //Fixme ( voodoocycles ):
191     //The *24 are needed for ecco the dolphin (CDVD hangs) and silver surfer (Pad not detected)
192     //Greater than *35 break rebooting when trying to play Tekken5 arcade history
193     //Total cycles over 1024 makes SIF too slow to keep up the sound stream in so3...
194     if (sif1.iop.cycles == 0)
195     {
196     DevCon.Warning("SIF1 IOP: cycles = 0");
197     sif1.iop.cycles = 1;
198     }
199     // iop is 1/8th the clock rate of the EE and psxcycles is in words (not quadwords)
200     PSX_INT(IopEvt_SIF1, min((sif1.iop.cycles * 26), 1024));
201     }
202    
203     // Handle the EE transfer.
204     static __forceinline void HandleEETransfer()
205     {
206     if(sif1dma->chcr.STR == false)
207     {
208     DevCon.Warning("Replacement for irq prevention hack EE SIF1");
209     sif1.ee.end = false;
210     sif1.ee.busy = false;
211     return;
212     }
213     if (dmacRegs->ctrl.STD == STD_SIF1)
214     {
215     DevCon.Warning("SIF1 stall control"); // STD == fromSIF1
216     }
217    
218     /*if (sif1dma->qwc == 0)
219     if (sif1dma->chcr.MOD == NORMAL_MODE)
220     if (!sif1.ee.end){
221     DevCon.Warning("sif1 irq prevented CHCR %x QWC %x", sif1dma->chcr, sif1dma->qwc);
222     done = true;
223     return;
224     }*/
225    
226     // If there's no more to transfer.
227     if (sif1dma->qwc <= 0)
228     {
229     // If NORMAL mode or end of CHAIN then stop DMA.
230     if ((sif1dma->chcr.MOD == NORMAL_MODE) || sif1.ee.end)
231     {
232     done = true;
233     EndEE();
234     }
235     else
236     {
237     done = false;
238     if (!ProcessEETag()) return;
239     }
240     }
241     else
242     {
243     if (sif1.fifo.free() > 0)
244     {
245     WriteEEtoFifo();
246     }
247     }
248     }
249    
250     // Handle the IOP transfer.
251     static __forceinline void HandleIOPTransfer()
252     {
253     if (sif1.iop.counter > 0)
254     {
255     if (sif1.fifo.size > 0)
256     {
257     WriteFifoToIOP();
258     }
259     }
260    
261     if (sif1.iop.counter <= 0)
262     {
263     if (sif1.iop.end)
264     {
265     done = true;
266     EndIOP();
267     }
268     else if (sif1.fifo.size >= 4)
269     {
270    
271     done = false;
272     SIFIOPReadTag();
273     }
274     }
275     }
276    
277     static __forceinline void Sif1End()
278     {
279     SIF_LOG("SIF1 DMA end...");
280     }
281    
282     // Transfer EE to IOP, putting data in the fifo as an intermediate step.
283     __forceinline void SIF1Dma()
284     {
285     int BusyCheck = 0;
286     Sif1Init();
287    
288     do
289     {
290     //I realise this is very hacky in a way but its an easy way of checking if both are doing something
291     BusyCheck = 0;
292    
293     if (sif1.ee.busy)
294     {
295     if(sif1.fifo.free() > 0) BusyCheck++;
296     HandleEETransfer();
297     }
298    
299     if (sif1.iop.busy)
300     {
301     if(sif1.fifo.size >= 4) BusyCheck++;
302     HandleIOPTransfer();
303     }
304    
305     } while (!done && BusyCheck > 0);
306    
307     Sif1End();
308     }
309    
310     __forceinline void sif1Interrupt()
311     {
312     HW_DMA10_CHCR &= ~0x01000000; //reset TR flag
313     psxDmaInterrupt2(3);
314     }
315    
316     __forceinline void EEsif1Interrupt()
317     {
318     hwDmacIrq(DMAC_SIF1);
319     sif1dma->chcr.STR = false;
320     }
321    
322     // Do almost exactly the same thing as psxDma10 in IopDma.cpp.
323     // Main difference is this checks for iop, where psxDma10 checks for ee.
324     __forceinline void dmaSIF1()
325     {
326     SIF_LOG(wxString(L"dmaSIF1" + sif1dma->cmqt_to_str()).To8BitData());
327    
328     if (sif1.fifo.readPos != sif1.fifo.writePos)
329     {
330     SIF_LOG("warning, sif1.fifoReadPos != sif1.fifoWritePos");
331     }
332    
333     if(sif1dma->chcr.MOD == CHAIN_MODE && sif1dma->qwc > 0) DevCon.Warning(L"SIF1 QWC on Chain CHCR " + sif1dma->chcr.desc());
334    
335     psHu32(SBUS_F240) |= 0x4000;
336     sif1.ee.busy = true;
337    
338     if (sif1.iop.busy)
339     {
340     XMMRegisters::Freeze();
341     SIF1Dma();
342     psHu32(SBUS_F240) &= ~0x40;
343     psHu32(SBUS_F240) &= ~0x100;
344     psHu32(SBUS_F240) &= ~0x4000;
345     XMMRegisters::Thaw();
346     }
347     }

  ViewVC Help
Powered by ViewVC 1.1.22