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

Diff of /trunk/pcsx2/Gif.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 31 by william, Tue Sep 7 03:24:11 2010 UTC revision 62 by william, Tue Sep 7 11:08:22 2010 UTC
# Line 35  static u32 gscycles = 0, prevcycles = 0, Line 35  static u32 gscycles = 0, prevcycles = 0,
35  static u32 gifqwc = 0;  static u32 gifqwc = 0;
36  static bool gifmfifoirq = false;  static bool gifmfifoirq = false;
37    
38  static __forceinline void clearFIFOstuff(bool full)  //Just some temporary bits to store Path1 transfers if another is in progress.
39  {  __aligned16 u8 Path1Buffer[0x1000000];
40          GSCSRr &= ~0xC000;  //Clear FIFO stuff  u32 Path1WritePos = 0;
41    u32 Path1ReadPos = 0;
42    
43    static __fi void clearFIFOstuff(bool full)
44    {
45          if (full)          if (full)
46                  GSCSRr |= 0x8000;   //FIFO full                  CSRreg.FIFO = CSR_FIFO_FULL;
47          else          else
48                  GSCSRr |= 0x4000;  //FIFO empty                  CSRreg.FIFO = CSR_FIFO_EMPTY;
49  }  }
50    
51  __forceinline void gsInterrupt()  void gsPath1Interrupt()
52    {
53            //DevCon.Warning("Path1 flush W %x, R %x", Path1WritePos, Path1ReadPos);
54    
55            
56    
57            if((gifRegs.stat.APATH <= GIF_APATH1 || (gifRegs.stat.IP3 == true && gifRegs.stat.APATH == GIF_APATH3)) && Path1WritePos > 0 && !gifRegs.stat.PSE)
58            {
59                    gifRegs.stat.P1Q = false;
60    
61                    if (uint size = (Path1WritePos - Path1ReadPos))
62                    {
63                            GetMTGS().PrepDataPacket(GIF_PATH_1, size);
64                            //DevCon.Warning("Flush Size = %x", size);
65                            while(size > 0)
66                            {
67                                    uint count = GIFPath_CopyTag(GIF_PATH_1, ((u128*)Path1Buffer) + Path1ReadPos, size);
68                                    Path1ReadPos += count;
69                                    size -= count;
70    
71                                    if(GSTransferStatus.PTH1 == STOPPED_MODE)
72                                    {      
73                                            gifRegs.stat.OPH = false;
74                                            gifRegs.stat.APATH = GIF_APATH_IDLE;
75                                    }
76                            }
77                            GetMTGS().SendDataPacket();
78    
79                            if(Path1ReadPos == Path1WritePos)
80                            {
81                                    Path1WritePos = Path1ReadPos = 0;
82                            }
83                    }
84            }
85            else
86            {
87                    if(gifRegs.stat.PSE) DevCon.Warning("Path1 paused by GIF_CTRL");
88                    DevCon.Warning("Looping??? IP3 %x APATH %x OPH %x", gifRegs.stat.IP3, gifRegs.stat.APATH, gifRegs.stat.OPH);
89                    //if(!(cpuRegs.interrupt & (1<<28)) && Path1WritePos > 0)CPU_INT(28, 128);
90            }
91            
92    }
93    
94    extern bool SIGNAL_IMR_Pending;
95    
96    __fi void gsInterrupt()
97  {  {
98          GIF_LOG("gsInterrupt: %8.8x", cpuRegs.cycle);          GIF_LOG("gsInterrupt: %8.8x", cpuRegs.cycle);
99    
100          if (!(gif->chcr.STR))          if(SIGNAL_IMR_Pending == true)
101          {          {
102                  //Console.WriteLn("Eh? why are you still interrupting! chcr %x, qwc %x, done = %x", gif->chcr._u32, gif->qwc, done);                  //DevCon.Warning("Path 3 Paused");
103                    CPU_INT(DMAC_GIF, 128);
104                  return;                  return;
105          }          }
106    
107            if(GSTransferStatus.PTH3 >= PENDINGSTOP_MODE && gifRegs.stat.APATH == GIF_APATH3 )
108            {
109                    gifRegs.stat.OPH = false;
110                    GSTransferStatus.PTH3 = STOPPED_MODE;
111                    gifRegs.stat.APATH = GIF_APATH_IDLE;
112                    if(gifRegs.stat.P1Q) gsPath1Interrupt();
113            }
114            
115    
116          if (GSTransferStatus.PTH3 == STOPPED_MODE)          if (!(gifch.chcr.STR))
117          {          {
118              gifRegs->stat.clear_flags(GIF_STAT_APATH3);                  //Console.WriteLn("Eh? why are you still interrupting! chcr %x, qwc %x, done = %x", gifch.chcr._u32, gifch.qwc, done);
119                    return;
120          }          }
121    
122          if ((gif->qwc > 0) || (!gspath3done))  
123            if ((gifch.qwc > 0) || (!gspath3done))
124          {          {
125                  if (!dmacRegs->ctrl.DMAE)                  if (!dmacRegs.ctrl.DMAE)
126                  {                  {
127                          Console.Warning("gs dma masked, re-scheduling...");                          Console.Warning("gs dma masked, re-scheduling...");
128                          // re-raise the int shortly in the future                          // re-raise the int shortly in the future
# Line 77  __forceinline void gsInterrupt() Line 136  __forceinline void gsInterrupt()
136    
137          gspath3done = false;          gspath3done = false;
138          gscycles = 0;          gscycles = 0;
139          gif->chcr.STR = false;          gifch.chcr.STR = false;
         vif1Regs->stat.VGW = false;  
         if(GSTransferStatus.PTH3 == 3) GSTransferStatus.PTH3 = STOPPED_MODE;  
         gifRegs->stat.clear_flags(GIF_STAT_APATH3 | GIF_STAT_FQC);  
140    
141            ////
142            /*gifRegs.stat.OPH = false;
143            GSTransferStatus.PTH3 = STOPPED_MODE;
144            gifRegs.stat.APATH = GIF_APATH_IDLE;*/
145            ////
146            gifRegs.stat.clear_flags(GIF_STAT_FQC);
147          clearFIFOstuff(false);          clearFIFOstuff(false);
148          hwDmacIrq(DMAC_GIF);          hwDmacIrq(DMAC_GIF);
149          GIF_LOG("GIF DMA end");          //DevCon.Warning("GIF DMA end");
150  }  }
151    
152  static u32 WRITERING_DMA(u32 *pMem, u32 qwc)  static u32 WRITERING_DMA(u32 *pMem, u32 qwc)
153  {  {
154          int size   = GetMTGS().PrepDataPacket(GIF_PATH_3, pMem, qwc);          GetMTGS().PrepDataPacket(GIF_PATH_3, qwc);
155          u8* pgsmem = GetMTGS().GetDataPacketPtr();          uint size = GIFPath_CopyTag(GIF_PATH_3, (u128*)pMem, qwc );
   
         memcpy_aligned(pgsmem, pMem, size<<4);  
   
156          GetMTGS().SendDataPacket();          GetMTGS().SendDataPacket();
157          return size;          return size;
158  }  }
# Line 107  int  _GIFchain() Line 166  int  _GIFchain()
166  {  {
167          tDMA_TAG *pMem;          tDMA_TAG *pMem;
168    
169          pMem = dmaGetAddr(gif->madr, false);          pMem = dmaGetAddr(gifch.madr, false);
170          if (pMem == NULL)          if (pMem == NULL)
171          {          {
172                  // reset path3, fixes dark cloud 2                  // reset path3, fixes dark cloud 2
173                  GIFPath_Clear( GIF_PATH_3 );                  GIFPath_Clear( GIF_PATH_3 );
174    
175                  //must increment madr and clear qwc, else it loops                  //must increment madr and clear qwc, else it loops
176                  gif->madr += gif->qwc * 16;                  gifch.madr += gifch.qwc * 16;
177                  gif->qwc = 0;                  gifch.qwc = 0;
178                  Console.Warning( "Hackfix - NULL GIFchain" );                  Console.Warning( "Hackfix - NULL GIFchain" );
179                  return -1;                  return -1;
180          }          }
181    
182          return WRITERING_DMA(pMem, gif->qwc);          return WRITERING_DMA(pMem, gifch.qwc);
183  }  }
184    
185  static __forceinline void GIFchain()  static __fi void GIFchain()
186  {  {
         Registers::Freeze();  
187          // qwc check now done outside this function          // qwc check now done outside this function
188          // Voodoocycles          // Voodoocycles
189          // >> 2 so Drakan and Tekken 5 don't mess up in some PATH3 transfer. Cycles to interrupt were getting huge..          // >> 2 so Drakan and Tekken 5 don't mess up in some PATH3 transfer. Cycles to interrupt were getting huge..
190          /*if (gif->qwc)*/ gscycles+= ( _GIFchain() >> 2 ); /* guessing */          /*if (gifch.qwc)*/ gscycles+= ( _GIFchain() * BIAS); /* guessing */
         Registers::Thaw();  
191  }  }
192    
193  static __forceinline bool checkTieBit(tDMA_TAG* &ptag)  static __fi bool checkTieBit(tDMA_TAG* &ptag)
194  {  {
195          if (gif->chcr.TIE && ptag->IRQ)          if (gifch.chcr.TIE && ptag->IRQ)
196          {          {
197                  GIF_LOG("dmaIrq Set");                  GIF_LOG("dmaIrq Set");
198                  gspath3done = true;                  gspath3done = true;
# Line 145  static __forceinline bool checkTieBit(tD Line 202  static __forceinline bool checkTieBit(tD
202          return false;          return false;
203  }  }
204    
205  static __forceinline tDMA_TAG* ReadTag()  static __fi tDMA_TAG* ReadTag()
206  {  {
207          tDMA_TAG* ptag = dmaGetAddr(gif->tadr, false);  //Set memory pointer to TADR          tDMA_TAG* ptag = dmaGetAddr(gifch.tadr, false);  //Set memory pointer to TADR
208    
209          if (!(gif->transfer("Gif", ptag))) return NULL;          if (!(gifch.transfer("Gif", ptag))) return NULL;
210    
211          gif->madr = ptag[1]._u32;                                   //MADR = ADDR field + SPR          gifch.madr = ptag[1]._u32;                                  //MADR = ADDR field + SPR
212          gscycles += 2; // Add 1 cycles from the QW read for the tag          gscycles += 2; // Add 1 cycles from the QW read for the tag
213    
214          gspath3done = hwDmacSrcChainWithStack(gif, ptag->ID);          gspath3done = hwDmacSrcChainWithStack(gifch, ptag->ID);
215          return ptag;          return ptag;
216  }  }
217    
218  static __forceinline tDMA_TAG* ReadTag2()  static __fi tDMA_TAG* ReadTag2()
219  {  {
220          tDMA_TAG* ptag = dmaGetAddr(gif->tadr, false);  //Set memory pointer to TADR          tDMA_TAG* ptag = dmaGetAddr(gifch.tadr, false);  //Set memory pointer to TADR
221    
222      gif->unsafeTransfer(ptag);      gifch.unsafeTransfer(ptag);
223          gif->madr = ptag[1]._u32;          gifch.madr = ptag[1]._u32;
224    
225          gspath3done = hwDmacSrcChainWithStack(gif, ptag->ID);          gspath3done = hwDmacSrcChainWithStack(gifch, ptag->ID);
226          return ptag;          return ptag;
227  }  }
228    
229    bool CheckPaths(int Channel)
230    {
231            if(GSTransferStatus.PTH3 <= IMAGE_MODE && gifRegs.mode.IMT)
232            {
233                    if((gifRegs.stat.P1Q == true || gifRegs.stat.P2Q == true) || (gifRegs.stat.APATH > GIF_APATH_IDLE && gifRegs.stat.APATH < GIF_APATH3))
234                    {
235                            if((vif1.cmd & 0x7f) != 0x51 || gifRegs.stat.P1Q == true)
236                            {
237                                            gifRegs.stat.IP3 = true;
238                                            if(gifRegs.stat.P1Q) gsPath1Interrupt();
239                                            CPU_INT(DMAC_GIF, 16);
240                                            return false;
241                            }
242                    }
243            }
244            else if((GSTransferStatus.PTH3 == IDLE_MODE)|| (GSTransferStatus.PTH3 == STOPPED_MODE))
245            {
246                    //This should cover both scenarios, as DIRECTHL doesn't gain priority when image mode is running (PENDINGIMAGE_MODE == fininshed).
247                    if((gifRegs.stat.P1Q == true || gifRegs.stat.P2Q == true) || (gifRegs.stat.APATH > GIF_APATH_IDLE && gifRegs.stat.APATH < GIF_APATH3))
248                    {
249                            gifRegs.stat.IP3 = true;
250                            CPU_INT(DMAC_GIF, 16);
251                            return false;
252                    }
253            }
254            
255            gifRegs.stat.IP3 = false;
256            return true;
257    }
258    
259  void GIFdma()  void GIFdma()
260  {  {
261          tDMA_TAG *ptag;          tDMA_TAG *ptag;
262    
263          gscycles = prevcycles;          gscycles = prevcycles;
264    
265          if (gifRegs->ctrl.PSE)  // temporarily stop          if (gifRegs.ctrl.PSE)  // temporarily stop
266          {          {
267                  Console.WriteLn("Gif dma temp paused?");                  Console.WriteLn("Gif dma temp paused? (non MFIFO GIF)");
268                    CPU_INT(DMAC_GIF, 16);
269                  return;                  return;
270          }          }
271    
272          if ((dmacRegs->ctrl.STD == STD_GIF) && (prevcycles != 0))          if ((dmacRegs.ctrl.STD == STD_GIF) && (prevcycles != 0))
273          {          {
274                  Console.WriteLn("GS Stall Control Source = %x, Drain = %x\n MADR = %x, STADR = %x", (psHu32(0xe000) >> 4) & 0x3, (psHu32(0xe000) >> 6) & 0x3, gif->madr, psHu32(DMAC_STADR));                  //Console.WriteLn("GS Stall Control Source = %x, Drain = %x\n MADR = %x, STADR = %x", (psHu32(0xe000) >> 4) & 0x3, (psHu32(0xe000) >> 6) & 0x3, gifch.madr, psHu32(DMAC_STADR));
275    
276                  if ((gif->madr + (gif->qwc * 16)) > dmacRegs->stadr.ADDR)                  if ((gifch.madr + (gifch.qwc * 16)) > dmacRegs.stadr.ADDR)
277                  {                  {
278                          CPU_INT(DMAC_GIF, 4);                          CPU_INT(DMAC_GIF, 4);
279                          gscycles = 0;                          gscycles = 0;
# Line 193  void GIFdma() Line 281  void GIFdma()
281                  }                  }
282    
283                  prevcycles = 0;                  prevcycles = 0;
284                  gif->qwc = 0;                  gifch.qwc = 0;
285          }          }
286    
287          clearFIFOstuff(true);          clearFIFOstuff(true);
288          gifRegs->stat.FQC = min((u16)0x10, gif->qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]          gifRegs.stat.FQC = min((u16)0x10, gifch.qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]
289    
290          //Path2 gets priority in intermittent mode          
291          if (GSTransferStatus.PTH1 != STOPPED_MODE || GSTransferStatus.PTH2 != STOPPED_MODE)          if (vif1Regs.mskpath3 || gifRegs.mode.M3R)
292          {          {
293              // We are in image mode doing DIRECTHL, Path 1 is in queue, and in intermittant mode.                  if (gifch.qwc == 0)
                 //GIF_LOG("Waiting VU %x, PATH2 %x, GIFMODE %x Progress %x", gifRegs->stat.P1Q, (vif1.cmd & 0x7f), gifRegs->mode._u32, GSTransferStatus.PTH3);  
                 gifRegs->stat.set_flags(GIF_STAT_P3Q);  
                 CPU_INT(DMAC_GIF, 16);  
                 return;  
         }  
         gifRegs->stat.clear_flags(GIF_STAT_P3Q);  
         gifRegs->stat.APATH = GIF_APATH3;  
   
         if (vif1Regs->mskpath3 || gifRegs->mode.M3R)  
         {  
                 if (gif->qwc == 0)  
294                  {                  {
295                          if ((gif->chcr.MOD == CHAIN_MODE) && gif->chcr.STR)                          if ((gifch.chcr.MOD == CHAIN_MODE) && gifch.chcr.STR)
296                          {                          {
297                                    //DevCon.Warning("GIF Reading Tag Masked MSK = %x", vif1Regs.mskpath3);
298                              ptag = ReadTag();                              ptag = ReadTag();
299                                  gifRegs->stat.FQC = min((u16)0x10, gif->qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]                                  gifRegs.stat.FQC = min((u16)0x10, gifch.qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]
300                                  if (ptag == NULL) return;                                  if (ptag == NULL) return;
301                                  GIF_LOG("PTH3 MASK gifdmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx tadr=%lx", ptag[1]._u32, ptag[0]._u32, gif->qwc, ptag->ID, gif->madr, gif->tadr);                                  GIF_LOG("PTH3 MASK gifdmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx tadr=%lx", ptag[1]._u32, ptag[0]._u32, gifch.qwc, ptag->ID, gifch.madr, gifch.tadr);
302    
303                                  //Check TIE bit of CHCR and IRQ bit of tag                                  //Check TIE bit of CHCR and IRQ bit of tag
304                                  if (checkTieBit(ptag))  GIF_LOG("PATH3 MSK dmaIrq Set");                                  if (checkTieBit(ptag))  GIF_LOG("PATH3 MSK dmaIrq Set");
305                          }                          }
306                  }                  }
307                    
308    
309                  if (GSTransferStatus.PTH3 == STOPPED_MODE) /*|| (vif1Regs->stat._u32 |= VIF1_STAT_VGW) == 0*/                  if (GSTransferStatus.PTH3 == IDLE_MODE)
310                  {                  {
311                          GIF_LOG("PTH3 MASK Paused by VIF");                          GIF_LOG("PTH3 MASK Paused by VIF QWC %x", gifch.qwc);
312                          vif1Regs->stat.VGW = false;                          
313                          if (gif->qwc == 0) CPU_INT(DMAC_GIF, 16);                          //DevCon.Warning("GIF Paused by Mask MSK = %x", vif1Regs.mskpath3);
314                            
315                            if(gifch.qwc == 0) gsInterrupt();
316                            else gifRegs.stat.set_flags(GIF_STAT_P3Q);
317                          return;                          return;
318                  }                  }
319                  gifRegs->stat.FQC = min((u16)0x10, gif->qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]                  
320    
321                    
322                    gifRegs.stat.FQC = min((u16)0x10, gifch.qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]
323                  //Check with Path3 masking games                  //Check with Path3 masking games
324                  if (gif->qwc > 0) {                  if (gifch.qwc > 0) {
325                            gifRegs.stat.set_flags(GIF_STAT_P3Q);
326                            if(CheckPaths(DMAC_GIF) == false) return;
327                            gifRegs.stat.clear_flags(GIF_STAT_P3Q);
328                          GIF_LOG("PTH3 MASK Transferring");                          GIF_LOG("PTH3 MASK Transferring");
329                          GIFchain();                                                              GIFchain();                    
330                            /*if(GSTransferStatus.PTH3 == PENDINGSTOP_MODE && gifRegs.stat.APATH == GIF_APATH_IDLE)
331                            {
332                                    GSTransferStatus.PTH3 = STOPPED_MODE;
333                            }*/
334                  }//else DevCon.WriteLn("GIFdma() case 1, but qwc = 0!"); //Don't do 0 GIFchain and then return                  }//else DevCon.WriteLn("GIFdma() case 1, but qwc = 0!"); //Don't do 0 GIFchain and then return
335                  CPU_INT(DMAC_GIF, gscycles * BIAS);                      CPU_INT(DMAC_GIF, gscycles);    
336                  return;                  return;
337                                    
338          }          }
339            
340          // Transfer Dn_QWC from Dn_MADR to GIF          // Transfer Dn_QWC from Dn_MADR to GIF
341          if ((gif->chcr.MOD == NORMAL_MODE) || (gif->qwc > 0)) // Normal Mode          if ((gifch.chcr.MOD == NORMAL_MODE) || (gifch.qwc > 0)) // Normal Mode
342          {          {
343    
344                  if ((dmacRegs->ctrl.STD == STD_GIF) && (gif->chcr.MOD == NORMAL_MODE))                  if ((dmacRegs.ctrl.STD == STD_GIF) && (gifch.chcr.MOD == NORMAL_MODE))
345                  {                  {
346                          Console.WriteLn("DMA Stall Control on GIF normal");                          //Console.WriteLn("DMA Stall Control on GIF normal");
347                  }                  }
348                  gifRegs->stat.FQC = min((u16)0x10, gif->qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]                  gifRegs.stat.FQC = min((u16)0x10, gifch.qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]
349                  //Check with Path3 masking games                  //Check with Path3 masking games
350                  if (gif->qwc > 0) {                  //DevCon.Warning("GIF Transferring Normal/ChainQWC MSK = %x", vif1Regs.mskpath3);
351                    
352                    
353                    
354                    if (gifch.qwc > 0) {
355                            gifRegs.stat.set_flags(GIF_STAT_P3Q);
356                            if(CheckPaths(DMAC_GIF) == false) return;
357                            gifRegs.stat.clear_flags(GIF_STAT_P3Q);
358                          GIFchain();     //Transfers the data set by the switch                          GIFchain();     //Transfers the data set by the switch
359                          CPU_INT(DMAC_GIF, gscycles * BIAS);                          CPU_INT(DMAC_GIF, gscycles);
360                          return;                          return;
361                  } else { //Else it really is a normal transfer and we want to quit, else it gets confused with chains                  } else DevCon.Warning("GIF Normalmode or QWC going to invalid case? CHCR %x", gifch.chcr._u32);
                         gspath3done = 1;  
                 }  
362    
363                  //else DevCon.WriteLn("GIFdma() case 2, but qwc = 0!"); //Don't do 0 GIFchain and then return, fixes Dual Hearts                  //else DevCon.WriteLn("GIFdma() case 2, but qwc = 0!"); //Don't do 0 GIFchain and then return, fixes Dual Hearts
364          }          }
365    
366          if ((gif->chcr.MOD == CHAIN_MODE) && (!gspath3done)) // Chain Mode          if ((gifch.chcr.MOD == CHAIN_MODE) && (!gspath3done)) // Chain Mode
367          {          {
368          ptag = ReadTag();          ptag = ReadTag();
369          if (ptag == NULL) return;          if (ptag == NULL) return;
370                  GIF_LOG("gifdmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx tadr=%lx", ptag[1]._u32, ptag[0]._u32, gif->qwc, ptag->ID, gif->madr, gif->tadr);                  //DevCon.Warning("GIF Reading Tag MSK = %x", vif1Regs.mskpath3);
371                  gifRegs->stat.FQC = min((u16)0x10, gif->qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]                  GIF_LOG("gifdmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx tadr=%lx", ptag[1]._u32, ptag[0]._u32, gifch.qwc, ptag->ID, gifch.madr, gifch.tadr);
372                  if (dmacRegs->ctrl.STD == STD_GIF)                  gifRegs.stat.FQC = min((u16)0x10, gifch.qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]
373                    if (dmacRegs.ctrl.STD == STD_GIF)
374                  {                  {
375                          // there are still bugs, need to also check if gif->madr +16*qwc >= stadr, if not, stall                          // there are still bugs, need to also check if gifch.madr +16*qwc >= stadr, if not, stall
376                          if (!gspath3done && ((gif->madr + (gif->qwc * 16)) > dmacRegs->stadr.ADDR) && (ptag->ID == TAG_REFS))                          if (!gspath3done && ((gifch.madr + (gifch.qwc * 16)) > dmacRegs.stadr.ADDR) && (ptag->ID == TAG_REFS))
377                          {                          {
378                                  // stalled.                                  // stalled.
379                                  // We really need to test this. Pay attention to prevcycles, as it used to trigger GIFchains in the code above. (rama)                                  // We really need to test this. Pay attention to prevcycles, as it used to trigger GIFchains in the code above. (rama)
380                                  Console.WriteLn("GS Stall Control start Source = %x, Drain = %x\n MADR = %x, STADR = %x", (psHu32(0xe000) >> 4) & 0x3, (psHu32(0xe000) >> 6) & 0x3,gif->madr, psHu32(DMAC_STADR));                                  //Console.WriteLn("GS Stall Control start Source = %x, Drain = %x\n MADR = %x, STADR = %x", (psHu32(0xe000) >> 4) & 0x3, (psHu32(0xe000) >> 6) & 0x3,gifch.madr, psHu32(DMAC_STADR));
381                                  prevcycles = gscycles;                                  prevcycles = gscycles;
382                                  //gif->tadr -= 16;                                  //gifch.tadr -= 16;
383                                    // Quake III revolution wants to see tadr move.
384                                    // Simple Media System (homebrew) as well.
385                                    // -16 also seems right (it shifts the bg image right if anything else).
386                                    gifch.tadr -= 16;
387                                    // Next line also needs to be here, according to ref
388                                    gifch.qwc = 0;
389                                  hwDmacIrq(DMAC_STALL_SIS);                                  hwDmacIrq(DMAC_STALL_SIS);
390                                  CPU_INT(DMAC_GIF, gscycles);                                  CPU_INT(DMAC_GIF, gscycles);
391                                  gscycles = 0;                                  gscycles = 0;
# Line 290  void GIFdma() Line 394  void GIFdma()
394                  }                  }
395    
396                  checkTieBit(ptag);                  checkTieBit(ptag);
397                    /*if(gifch.qwc == 0)
398                    {
399                            gsInterrupt();
400                            return;
401                    }*/
402          }          }
403    
404          prevcycles = 0;          prevcycles = 0;
405            CPU_INT(DMAC_GIF, gscycles);
406          if ((!gspath3done) && (gif->qwc == 0))          gifRegs.stat.FQC = min((u16)0x10, gifch.qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // OPH=1 | APATH=3]
         {  
                 ptag = dmaGetAddr(gif->tadr, false);  //Set memory pointer to TADR  
         gif->unsafeTransfer(ptag);  
                 gif->madr = ptag[1]._u32;  
   
                 gspath3done = hwDmacSrcChainWithStack(gif, ptag->ID);  
   
                 checkTieBit(ptag);  
   
                 GIF_LOG("gifdmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx tadr=%lx", ptag[1]._u32, ptag[0]._u32, gif->qwc, ptag->ID, gif->madr, gif->tadr);  
                 CPU_INT(DMAC_GIF, gscycles * BIAS);  
         }  
         else  
         {  
                 CPU_INT(DMAC_GIF, gscycles * BIAS);  
                 gscycles = 0;  
         }  
         gifRegs->stat.FQC = min((u16)0x10, gif->qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]  
407  }  }
408    
409  void dmaGIF()  void dmaGIF()
410  {  {
411           //We used to add wait time for the buffer to fill here, fixing some timing problems in path 3 masking           //We used to add wait time for the buffer to fill here, fixing some timing problems in path 3 masking
412          //It takes the time of 24 QW for the BUS to become ready - The Punisher And Streetball          //It takes the time of 24 QW for the BUS to become ready - The Punisher And Streetball
413          GIF_LOG("dmaGIFstart chcr = %lx, madr = %lx, qwc  = %lx\n tadr = %lx, asr0 = %lx, asr1 = %lx", gif->chcr._u32, gif->madr, gif->qwc, gif->tadr, gif->asr0, gif->asr1);          //DevCon.Warning("dmaGIFstart chcr = %lx, madr = %lx, qwc  = %lx\n tadr = %lx, asr0 = %lx, asr1 = %lx", gifch.chcr._u32, gifch.madr, gifch.qwc, gifch.tadr, gifch.asr0, gifch.asr1);
414    
         //GSTransferStatus.PTH3 = STOPPED_MODE;  
415          gspath3done = false; // For some reason this doesn't clear? So when the system starts the thread, we will clear it :)          gspath3done = false; // For some reason this doesn't clear? So when the system starts the thread, we will clear it :)
416    
417          gifRegs->stat.P3Q = true;          gifRegs.stat.FQC |= 0x10; // hack ;)
         gifRegs->stat.FQC |= 0x10; // hack ;)  
418    
419            if (gifch.chcr.MOD == NORMAL_MODE) { //Else it really is a normal transfer and we want to quit, else it gets confused with chains
420                    gspath3done = true;
421            }
422          clearFIFOstuff(true);          clearFIFOstuff(true);
423    
424          if (dmacRegs->ctrl.MFD == MFD_GIF)  // GIF MFIFO          if(gifch.chcr.MOD == CHAIN_MODE && gifch.qwc > 0)
425          {          {
426                  //Console.WriteLn("GIF MFIFO");                  //DevCon.Warning(L"GIF QWC on Chain " + gifch.chcr.desc());
427                  gifMFIFOInterrupt();                  if ((gifch.chcr.tag().ID == TAG_REFE) || (gifch.chcr.tag().ID == TAG_END))
428                  return;                  {
429                            gspath3done = true;
430                    }
431          }          }
432    
433          if ((gif->qwc == 0) && (gif->chcr.MOD != NORMAL_MODE))          if (dmacRegs.ctrl.MFD == MFD_GIF)  // GIF MFIFO
434          {          {
435                  tDMA_TAG* ptag = ReadTag2();                  //Console.WriteLn("GIF MFIFO");
436                  GIF_LOG("gifdmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx tadr=%lx", ptag[1]._u32, ptag[0]._u32, gif->qwc, ptag->ID, gif->madr, gif->tadr);                  gifMFIFOInterrupt();
   
                 checkTieBit(ptag);  
                 GIFdma();  
437                  return;                  return;
438          }          }      
   
         //Halflife sets a QWC amount in chain mode, no tadr set.  
         if (gif->qwc > 0) gspath3done = true;  
         if(gif->chcr.MOD == CHAIN_MODE && gif->qwc > 0) DevCon.Warning(L"GIF QWC on Chain " + gif->chcr.desc());  
439    
440          GIFdma();          GIFdma();
441  }  }
442    
443  // called from only one location, so forceinline it:  // called from only one location, so forceinline it:
444  static __forceinline bool mfifoGIFrbTransfer()  static __fi bool mfifoGIFrbTransfer()
445  {  {
446          u32 mfifoqwc = min(gifqwc, (u32)gif->qwc);          u32 mfifoqwc = min(gifqwc, (u32)gifch.qwc);
447          u32 *src;          u32 *src;
448    
449            GetMTGS().PrepDataPacket(GIF_PATH_3, mfifoqwc);
450    
451            // TODO (minor optimization): The new GIFpath parser can do rather efficient wrapping of
452            // its own internally now. We just need to groom a version of it that can wrap around MFIFO
453            // memory similarly to how it wraps VU1 memory on PATH1.
454    
455          /* Check if the transfer should wrap around the ring buffer */          /* Check if the transfer should wrap around the ring buffer */
456          if ((gif->madr + mfifoqwc * 16) > (dmacRegs->rbor.ADDR + dmacRegs->rbsr.RMSK + 16))          if ((gifch.madr + mfifoqwc * 16) > (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16))
457          {          {
458                  uint s1 = ((dmacRegs->rbor.ADDR + dmacRegs->rbsr.RMSK + 16) - gif->madr) >> 4;                  uint s1 = ((dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16) - gifch.madr) >> 4;
459                  uint s2 = (mfifoqwc - s1);                  uint s2 = (mfifoqwc - s1);
                 // fixme - I don't think these should use WRITERING_DMA, since our source  
                 // isn't the DmaGetAddr(gif->madr) address that WRITERING_DMA expects.  
460    
461                  /* it does (wrap around), so first copy 's1' bytes from 'addr' to 'data' */                  /* it does (wrap around), so first copy 's1' bytes from 'addr' to 'data' */
462                  src = (u32*)PSM(gif->madr);                  /* and second copy 's2' bytes from 'maddr' to '&data[s1]' */
463    
464                    src = (u32*)PSM(gifch.madr);
465                  if (src == NULL) return false;                  if (src == NULL) return false;
466                  s1 = WRITERING_DMA(src, s1);                  uint copied = GIFPath_CopyTag(GIF_PATH_3, (u128*)src, s1);
467    
468                  if (s1 == (mfifoqwc - s2))                  if (copied == s1)       // but only copy second if first didn't abort prematurely for some reason.
469                  {                  {
470                          /* and second copy 's2' bytes from 'maddr' to '&data[s1]' */                          src = (u32*)PSM(dmacRegs.rbor.ADDR);
                         src = (u32*)PSM(dmacRegs->rbor.ADDR);  
471                          if (src == NULL) return false;                          if (src == NULL) return false;
472                          s2 = WRITERING_DMA(src, s2);                          copied += GIFPath_CopyTag(GIF_PATH_3, (u128*)src, s2);
                 }  
                 else  
                 {  
                         s2 = 0;  
473                  }                  }
474    
475                  mfifoqwc = s1 + s2;                  mfifoqwc = copied;
476          }          }
477          else          else
478          {          {
479                  /* it doesn't, so just transfer 'qwc*16' words from 'gif->madr' to GS */                  /* it doesn't, so just transfer 'qwc*16' words from 'gifch.madr' to GS */
480                  src = (u32*)PSM(gif->madr);                  src = (u32*)PSM(gifch.madr);
481                  if (src == NULL) return false;                  if (src == NULL) return false;
482                  mfifoqwc = WRITERING_DMA(src, mfifoqwc);                  mfifoqwc = GIFPath_CopyTag(GIF_PATH_3, (u128*)src, mfifoqwc);
483                  gif->madr = dmacRegs->rbor.ADDR + (gif->madr & dmacRegs->rbsr.RMSK);                  gifch.madr = dmacRegs.rbor.ADDR + (gifch.madr & dmacRegs.rbsr.RMSK);
484          }          }
485    
486            GetMTGS().SendDataPacket();
487          gifqwc -= mfifoqwc;          gifqwc -= mfifoqwc;
488    
489          return true;          return true;
490  }  }
491    
492  // called from only one location, so forceinline it:  // called from only one location, so forceinline it:
493  static __forceinline bool mfifoGIFchain()  static __fi bool mfifoGIFchain()
494  {  {
495          /* Is QWC = 0? if so there is nothing to transfer */          /* Is QWC = 0? if so there is nothing to transfer */
496          if (gif->qwc == 0) return true;          if (gifch.qwc == 0) return true;
497    
498          if (gif->madr >= dmacRegs->rbor.ADDR &&          if (gifch.madr >= dmacRegs.rbor.ADDR &&
499                  gif->madr <= (dmacRegs->rbor.ADDR + dmacRegs->rbsr.RMSK))                  gifch.madr <= (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK))
500          {          {
501                  if (!mfifoGIFrbTransfer()) return false;                  if (!mfifoGIFrbTransfer()) return false;
502          }          }
# Line 415  static __forceinline bool mfifoGIFchain( Line 504  static __forceinline bool mfifoGIFchain(
504          {          {
505                  int mfifoqwc;                  int mfifoqwc;
506    
507                  tDMA_TAG *pMem = dmaGetAddr(gif->madr, false);                  tDMA_TAG *pMem = dmaGetAddr(gifch.madr, false);
508                  if (pMem == NULL) return false;                  if (pMem == NULL) return false;
509    
510                  mfifoqwc = WRITERING_DMA(pMem, gif->qwc);                  mfifoqwc = WRITERING_DMA(pMem, gifch.qwc);
511                  mfifocycles += (mfifoqwc) * 2; /* guessing */                  mfifocycles += (mfifoqwc) * 2; /* guessing */
512          }          }
513    
# Line 427  static __forceinline bool mfifoGIFchain( Line 516  static __forceinline bool mfifoGIFchain(
516    
517  static u32 qwctag(u32 mask)  static u32 qwctag(u32 mask)
518  {  {
519          return (dmacRegs->rbor.ADDR + (mask & dmacRegs->rbsr.RMSK));          return (dmacRegs.rbor.ADDR + (mask & dmacRegs.rbsr.RMSK));
520  }  }
521    
522  void mfifoGIFtransfer(int qwc)  void mfifoGIFtransfer(int qwc)
# Line 447  void mfifoGIFtransfer(int qwc) Line 536  void mfifoGIFtransfer(int qwc)
536                  gifempty = false;                  gifempty = false;
537          }          }
538    
539          GIF_LOG("mfifoGIFtransfer %x madr %x, tadr %x", gif->chcr._u32, gif->madr, gif->tadr);          if (gifRegs.ctrl.PSE)  // temporarily stop
540            {
541                    Console.WriteLn("Gif dma temp paused?");
542                    CPU_INT(DMAC_MFIFO_GIF, 16);
543                    return;
544            }
545    
546          if (gif->qwc == 0)          if (gifch.qwc == 0)
547          {          {
548                  if (gif->tadr == spr0->madr)                  if (gifch.tadr == spr0ch.madr)
549                  {                  {
550                          //if( gifqwc > 1 ) DevCon.WriteLn("gif mfifo tadr==madr but qwc = %d", gifqwc);                          //if( gifqwc > 1 ) DevCon.WriteLn("gif mfifo tadr==madr but qwc = %d", gifqwc);
551                          hwDmacIrq(DMAC_MFIFO_EMPTY);                          hwDmacIrq(DMAC_MFIFO_EMPTY);
# Line 460  void mfifoGIFtransfer(int qwc) Line 554  void mfifoGIFtransfer(int qwc)
554                          return;                          return;
555                  }                  }
556    
557                  gif->tadr = qwctag(gif->tadr);                  gifch.tadr = qwctag(gifch.tadr);
558    
559                  ptag = dmaGetAddr(gif->tadr, false);                  ptag = dmaGetAddr(gifch.tadr, false);
560                  gif->unsafeTransfer(ptag);                  gifch.unsafeTransfer(ptag);
561                  gif->madr = ptag[1]._u32;                  gifch.madr = ptag[1]._u32;
562    
563                  mfifocycles += 2;                  mfifocycles += 2;
564    
565                  GIF_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx mfifo qwc = %x spr0 madr = %x",                  GIF_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx mfifo qwc = %x spr0 madr = %x",
566                                  ptag[1]._u32, ptag[0]._u32, gif->qwc, ptag->ID, gif->madr, gif->tadr, gifqwc, spr0->madr);                                  ptag[1]._u32, ptag[0]._u32, gifch.qwc, ptag->ID, gifch.madr, gifch.tadr, gifqwc, spr0ch.madr);
567    
568                  gifqwc--;                  gifqwc--;
569    
570                  switch (ptag->ID)                  switch (ptag->ID)
571                  {                  {
572                          case TAG_REFE: // Refe - Transfer Packet According to ADDR field                          case TAG_REFE:          // Refe - Transfer Packet According to ADDR field
573                                  gif->tadr = qwctag(gif->tadr + 16);                                  gifch.tadr = qwctag(gifch.tadr + 16);
574                                  gifstate = GIF_STATE_DONE;                                                                              //End Transfer                                  gifstate = GIF_STATE_DONE;                                                                              //End Transfer
575                                  break;                                  break;
576    
577                          case TAG_CNT: // CNT - Transfer QWC following the tag.                          case TAG_CNT:           // CNT - Transfer QWC following the tag.
578                                  gif->madr = qwctag(gif->tadr + 16);                                             //Set MADR to QW after Tag                                  gifch.madr = qwctag(gifch.tadr + 16);                                           //Set MADR to QW after Tag
579                                  gif->tadr = qwctag(gif->madr + (gif->qwc << 4));                        //Set TADR to QW following the data                                  gifch.tadr = qwctag(gifch.madr + (gifch.qwc << 4));             //Set TADR to QW following the data
580                                  gifstate = GIF_STATE_READY;                                  gifstate = GIF_STATE_READY;
581                                  break;                                  break;
582    
583                          case TAG_NEXT: // Next - Transfer QWC following tag. TADR = ADDR                          case TAG_NEXT:          // Next - Transfer QWC following tag. TADR = ADDR
584                          {                          {
585                                  u32 temp = gif->madr;                                                           //Temporarily Store ADDR                                  u32 temp = gifch.madr;                                                                  //Temporarily Store ADDR
586                                  gif->madr = qwctag(gif->tadr + 16);                                       //Set MADR to QW following the tag                                  gifch.madr = qwctag(gifch.tadr + 16);                                           //Set MADR to QW following the tag
587                                  gif->tadr = temp;                                                               //Copy temporarily stored ADDR to Tag                                  gifch.tadr = temp;                                                                              //Copy temporarily stored ADDR to Tag
588                                  gifstate = GIF_STATE_READY;                                  gifstate = GIF_STATE_READY;
589                                  break;                                  break;
590                          }                          }
591    
592                          case TAG_REF: // Ref - Transfer QWC from ADDR field                          case TAG_REF:           // Ref - Transfer QWC from ADDR field
593                          case TAG_REFS: // Refs - Transfer QWC from ADDR field (Stall Control)                          case TAG_REFS:          // Refs - Transfer QWC from ADDR field (Stall Control)
594                                  gif->tadr = qwctag(gif->tadr + 16);                                                     //Set TADR to next tag                                  gifch.tadr = qwctag(gifch.tadr + 16);                                                   //Set TADR to next tag
595                                  gifstate = GIF_STATE_READY;                                  gifstate = GIF_STATE_READY;
596                                  break;                                  break;
597    
598                          case TAG_END: // End - Transfer QWC following the tag                          case TAG_END:           // End - Transfer QWC following the tag
599                                  gif->madr = qwctag(gif->tadr + 16);             //Set MADR to data following the tag                                  gifch.madr = qwctag(gifch.tadr + 16);                                   //Set MADR to data following the tag
600                                  gif->tadr = qwctag(gif->madr + (gif->qwc << 4));                        //Set TADR to QW following the data                                  gifch.tadr = qwctag(gifch.madr + (gifch.qwc << 4));     //Set TADR to QW following the data
601                                  gifstate = GIF_STATE_DONE;                                              //End Transfer                                  gifstate = GIF_STATE_DONE;                                                      //End Transfer
602                                  break;                                  break;
603                          }                          }
604    
605                  if ((gif->chcr.TIE) && (ptag->IRQ))                  if ((gifch.chcr.TIE) && (ptag->IRQ))
606                  {                  {
607                          SPR_LOG("dmaIrq Set");                          SPR_LOG("dmaIrq Set");
608                          gifstate = GIF_STATE_DONE;                          gifstate = GIF_STATE_DONE;
# Line 516  void mfifoGIFtransfer(int qwc) Line 610  void mfifoGIFtransfer(int qwc)
610                  }                  }
611           }           }
612    
         Registers::Freeze();  
613          if (!mfifoGIFchain())          if (!mfifoGIFchain())
614          {          {
615                  Console.WriteLn("GIF dmaChain error size=%d, madr=%lx, tadr=%lx", gif->qwc, gif->madr, gif->tadr);                  Console.WriteLn("GIF dmaChain error size=%d, madr=%lx, tadr=%lx", gifch.qwc, gifch.madr, gifch.tadr);
616                  gifstate = GIF_STATE_STALL;                  gifstate = GIF_STATE_STALL;
617          }          }
         Registers::Thaw();  
618    
619          if ((gif->qwc == 0) && (gifstate & GIF_STATE_DONE)) gifstate = GIF_STATE_STALL;          if ((gifch.qwc == 0) && (gifstate & GIF_STATE_DONE)) gifstate = GIF_STATE_STALL;
620          CPU_INT(11,mfifocycles);          CPU_INT(DMAC_MFIFO_GIF,mfifocycles);
621    
622          SPR_LOG("mfifoGIFtransfer end %x madr %x, tadr %x", gif->chcr._u32, gif->madr, gif->tadr);          SPR_LOG("mfifoGIFtransfer end %x madr %x, tadr %x", gifch.chcr._u32, gifch.madr, gifch.tadr);
623  }  }
624    
625  void gifMFIFOInterrupt()  void gifMFIFOInterrupt()
# Line 535  void gifMFIFOInterrupt() Line 627  void gifMFIFOInterrupt()
627      //Console.WriteLn("gifMFIFOInterrupt");      //Console.WriteLn("gifMFIFOInterrupt");
628          mfifocycles = 0;          mfifocycles = 0;
629    
630          if (GSTransferStatus.PTH3 == STOPPED_MODE)          if(SIGNAL_IMR_Pending == true)
631          {          {
632               gifRegs->stat.APATH = GIF_APATH_IDLE;                  //DevCon.Warning("Path 3 Paused");
633                    CPU_INT(DMAC_MFIFO_GIF, 128);
634                    return;
635          }          }
636    
637          if ((spr0->chcr.STR) && (spr0->qwc == 0))          if(GSTransferStatus.PTH3 == STOPPED_MODE && gifRegs.stat.APATH == GIF_APATH3 )
638          {          {
639                  spr0->chcr.STR = false;                  gifRegs.stat.OPH = false;
640                  hwDmacIrq(DMAC_FROM_SPR);                  gifRegs.stat.APATH = GIF_APATH_IDLE;
641                    if(gifRegs.stat.P1Q) gsPath1Interrupt();
642          }          }
643    
644          if (!(gif->chcr.STR))          if(CheckPaths(11) == false) return;
645    
646            if (!(gifch.chcr.STR))
647          {          {
648                  Console.WriteLn("WTF GIFMFIFO");                  Console.WriteLn("WTF GIFMFIFO");
649                  cpuRegs.interrupt &= ~(1 << 11);                  cpuRegs.interrupt &= ~(1 << 11);
650                  return;                  return;
651          }          }
652    
         if ((gifRegs->stat.P1Q || (vif1.cmd & 0x7f) == 0x50) && gifRegs->mode.IMT && GSTransferStatus.PTH3 == IMAGE_MODE) //Path2 gets priority in intermittent mode  
         {  
                 //GIF_LOG("Waiting VU %x, PATH2 %x, GIFMODE %x Progress %x", psHu32(GIF_STAT) & 0x100, (vif1.cmd & 0x7f), psHu32(GIF_MODE), GSTransferStatus.PTH3);  
                 CPU_INT(11,mfifocycles);  
                 return;  
         }  
   
653          if (!(gifstate & GIF_STATE_STALL))          if (!(gifstate & GIF_STATE_STALL))
654          {          {
655                  if (gifqwc <= 0)                  if (gifqwc <= 0)
# Line 569  void gifMFIFOInterrupt() Line 659  void gifMFIFOInterrupt()
659                          gifstate |= GIF_STATE_EMPTY;                          gifstate |= GIF_STATE_EMPTY;
660                          gifempty = true;                          gifempty = true;
661    
662                          gifRegs->stat.IMT = false;                          gifRegs.stat.IMT = false;
663                          return;                          return;
664                  }                  }
665                  mfifoGIFtransfer(0);                  mfifoGIFtransfer(0);
# Line 577  void gifMFIFOInterrupt() Line 667  void gifMFIFOInterrupt()
667          }          }
668    
669  #ifdef PCSX2_DEVBUILD  #ifdef PCSX2_DEVBUILD
670          if ((gifstate & GIF_STATE_READY) || (gif->qwc > 0))          if ((gifstate & GIF_STATE_READY) || (gifch.qwc > 0))
671          {          {
672                  Console.Error("gifMFIFO Panic > Shouldn't go here!");                  Console.Error("gifMFIFO Panic > Shouldn't go here!");
673                  return;                  return;
# Line 589  void gifMFIFOInterrupt() Line 679  void gifMFIFOInterrupt()
679          gspath3done = false;          gspath3done = false;
680          gscycles = 0;          gscycles = 0;
681    
682          gifRegs->stat.clear_flags(GIF_STAT_APATH3 | GIF_STAT_P3Q | GIF_STAT_FQC); // APATH, P3Q,  FQC = 0          gifRegs.stat.clear_flags(GIF_STAT_APATH3 | GIF_STAT_P3Q | GIF_STAT_FQC); // APATH, P3Q,  FQC = 0
683    
684          vif1Regs->stat.VGW = false;          vif1Regs.stat.VGW = false;
685          gif->chcr.STR = false;          gifch.chcr.STR = false;
686          gifstate = GIF_STATE_READY;          gifstate = GIF_STATE_READY;
687          hwDmacIrq(DMAC_GIF);          hwDmacIrq(DMAC_GIF);
688          clearFIFOstuff(false);          clearFIFOstuff(false);
# Line 608  void SaveStateBase::gifFreeze() Line 698  void SaveStateBase::gifFreeze()
698          Freeze( gscycles );          Freeze( gscycles );
699          //Freeze(gifempty);          //Freeze(gifempty);
700          // Note: mfifocycles is not a persistent var, so no need to save it here.          // Note: mfifocycles is not a persistent var, so no need to save it here.
701    
702            int bufsize = Path1WritePos - Path1ReadPos;
703            Freeze(bufsize);
704    
705            if (IsSaving())
706            {
707                    // We can just load the queued Path1 data into the front of the buffer, and
708                    // reset the ReadPos and WritePos accordingly.
709                    FreezeMem(Path1Buffer, bufsize);
710                    Path1ReadPos = 0;
711                    Path1WritePos = bufsize;
712            }
713            else
714            {
715                    // Only want to save the actual Path1 data between readpos and writepos.  The
716                    // rest of the buffer is just unused-ness!
717                    FreezeMem(&Path1Buffer[Path1ReadPos], bufsize);
718            }
719  }  }

Legend:
Removed from v.31  
changed lines
  Added in v.62

  ViewVC Help
Powered by ViewVC 1.1.22