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

Diff of /trunk/pcsx2/R5900.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 26  Line 26 
26  #include "R5900Exceptions.h"  #include "R5900Exceptions.h"
27    
28  #include "Hardware.h"  #include "Hardware.h"
29    #include "IPU/IPUdma.h"
30    
31  #include "Elfheader.h"  #include "Elfheader.h"
32  #include "CDVD/CDVD.h"  #include "CDVD/CDVD.h"
33  #include "Patch.h"  #include "Patch.h"
34  #include "DataBase_Loader.h"  #include "GameDatabase.h"
35  #include "SamplProf.h"  #include "SamplProf.h"
36    
37  using namespace R5900;  // for R5900 disasm tools  using namespace R5900;  // for R5900 disasm tools
# Line 50  static const uint eeWaitCycles = 3072; Line 51  static const uint eeWaitCycles = 3072;
51    
52  bool eeEventTestIsActive = false;  bool eeEventTestIsActive = false;
53    
 R5900Exception::BaseExcept::~BaseExcept() throw (){}  
   
   
54  void cpuReset()  void cpuReset()
55  {  {
56          if( GetMTGS().IsOpen() )          if( GetMTGS().IsOpen() )
# Line 73  void cpuReset() Line 71  void cpuReset()
71          fpuRegs.fprc[0]                 = 0x00002e00; // fpu Revision..          fpuRegs.fprc[0]                 = 0x00002e00; // fpu Revision..
72          fpuRegs.fprc[31]                = 0x01000001; // fpu Status/Control          fpuRegs.fprc[31]                = 0x01000001; // fpu Status/Control
73    
74          g_nextBranchCycle = cpuRegs.cycle + 4;          g_nextEventCycle = cpuRegs.cycle + 4;
75          EEsCycle = 0;          EEsCycle = 0;
76          EEoCycle = cpuRegs.cycle;          EEoCycle = cpuRegs.cycle;
77    
# Line 88  void cpuReset() Line 86  void cpuReset()
86          g_SkipBiosHack = EmuConfig.UseBOOT2Injection;          g_SkipBiosHack = EmuConfig.UseBOOT2Injection;
87    
88          ElfCRC = 0;          ElfCRC = 0;
89          DiscID = L"";          DiscSerial = L"";
90          ElfEntry = -1;          ElfEntry = -1;
91    
92            // FIXME: LastELF should be reset on media changes as well as on CPU resets, in
93            // the very unlikely case that a user swaps to another media source that "looks"
94            // the same (identical ELF names) but is actually different (devs actually could
95            // run into this while testing minor binary hacked changes to ISO images, which
96            // is why I found out about this) --air
97          LastELF = L"";          LastELF = L"";
98  }  }
99    
100  __releaseinline void cpuException(u32 code, u32 bd)  __ri void cpuException(u32 code, u32 bd)
101  {  {
102          bool errLevel2, checkStatus;          bool errLevel2, checkStatus;
103          u32 offset;          u32 offset;
# Line 126  __releaseinline void cpuException(u32 co Line 130  __releaseinline void cpuException(u32 co
130                          //Reset / NMI                          //Reset / NMI
131                          cpuRegs.pc = 0xBFC00000;                          cpuRegs.pc = 0xBFC00000;
132                          Console.Warning("Reset request");                          Console.Warning("Reset request");
133                          UpdateCP0Status();                          cpuUpdateOperationMode();
134                          return;                          return;
135                  }                  }
136                  else if((code & 0x38000) == 0x10000)                  else if((code & 0x38000) == 0x10000)
# Line 163  __releaseinline void cpuException(u32 co Line 167  __releaseinline void cpuException(u32 co
167          else          else
168                  cpuRegs.pc = 0xBFC00200 + offset;                  cpuRegs.pc = 0xBFC00200 + offset;
169    
170          UpdateCP0Status();          cpuUpdateOperationMode();
171  }  }
172    
173  void cpuTlbMiss(u32 addr, u32 bd, u32 excode)  void cpuTlbMiss(u32 addr, u32 bd, u32 excode)
# Line 192  void cpuTlbMiss(u32 addr, u32 bd, u32 ex Line 196  void cpuTlbMiss(u32 addr, u32 bd, u32 ex
196          }          }
197    
198          cpuRegs.CP0.n.Status.b.EXL = 1;          cpuRegs.CP0.n.Status.b.EXL = 1;
199          UpdateCP0Status();          cpuUpdateOperationMode();
200  //      Log=1; varLog|= 0x40000000;  //      Log=1; varLog|= 0x40000000;
201  }  }
202    
# Line 204  void cpuTlbMissW(u32 addr, u32 bd) { Line 208  void cpuTlbMissW(u32 addr, u32 bd) {
208          cpuTlbMiss(addr, bd, EXC_CODE_TLBS);          cpuTlbMiss(addr, bd, EXC_CODE_TLBS);
209  }  }
210    
 __forceinline void _cpuTestMissingINTC() {  
         if (cpuRegs.CP0.n.Status.val & 0x400 &&  
                 psHu32(INTC_STAT) & psHu32(INTC_MASK)) {  
                 if ((cpuRegs.interrupt & (1 << 30)) == 0) {  
                         Console.Error("*PCSX2*: Error, missing INTC Interrupt");  
                 }  
         }  
 }  
   
 __forceinline void _cpuTestMissingDMAC() {  
         if (cpuRegs.CP0.n.Status.val & 0x800 &&  
                 (psHu16(0xe012) & psHu16(0xe010) ||  
                  psHu16(0xe010) & 0x8000)) {  
                 if ((cpuRegs.interrupt & (1 << 31)) == 0) {  
                         Console.Error("*PCSX2*: Error, missing DMAC Interrupt");  
                 }  
         }  
 }  
   
 void cpuTestMissingHwInts() {  
         if ((cpuRegs.CP0.n.Status.val & 0x10007) == 0x10001) {  
                 _cpuTestMissingINTC();  
                 _cpuTestMissingDMAC();  
 //              _cpuTestTIMR();  
         }  
 }  
   
211  // sets a branch test to occur some time from an arbitrary starting point.  // sets a branch test to occur some time from an arbitrary starting point.
212  __forceinline void cpuSetNextBranch( u32 startCycle, s32 delta )  __fi void cpuSetNextEvent( u32 startCycle, s32 delta )
213  {  {
214          // typecast the conditional to signed so that things don't blow up          // typecast the conditional to signed so that things don't blow up
215          // if startCycle is greater than our next branch cycle.          // if startCycle is greater than our next branch cycle.
216    
217          if( (int)(g_nextBranchCycle - startCycle) > delta )          if( (int)(g_nextEventCycle - startCycle) > delta )
218          {          {
219                  g_nextBranchCycle = startCycle + delta;                  g_nextEventCycle = startCycle + delta;
220          }          }
221  }  }
222    
223  // sets a branch to occur some time from the current cycle  // sets a branch to occur some time from the current cycle
224  __forceinline void cpuSetNextBranchDelta( s32 delta )  __fi void cpuSetNextEventDelta( s32 delta )
225  {  {
226          cpuSetNextBranch( cpuRegs.cycle, delta );          cpuSetNextEvent( cpuRegs.cycle, delta );
227  }  }
228    
229  // tests the cpu cycle agaisnt the given start and delta values.  // tests the cpu cycle against the given start and delta values.
230  // Returns true if the delta time has passed.  // Returns true if the delta time has passed.
231  __forceinline int cpuTestCycle( u32 startCycle, s32 delta )  __fi int cpuTestCycle( u32 startCycle, s32 delta )
232  {  {
233          // typecast the conditional to signed so that things don't explode          // typecast the conditional to signed so that things don't explode
234          // if the startCycle is ahead of our current cpu cycle.          // if the startCycle is ahead of our current cpu cycle.
# Line 260  __forceinline int cpuTestCycle( u32 star Line 237  __forceinline int cpuTestCycle( u32 star
237  }  }
238    
239  // tells the EE to run the branch test the next time it gets a chance.  // tells the EE to run the branch test the next time it gets a chance.
240  __forceinline void cpuSetBranch()  __fi void cpuSetEvent()
241  {  {
242          g_nextBranchCycle = cpuRegs.cycle;          g_nextEventCycle = cpuRegs.cycle;
243  }  }
244    
245  __forceinline void cpuClearInt( uint i )  __fi void cpuClearInt( uint i )
246  {  {
247          jASSUME( i < 32 );          jASSUME( i < 32 );
248          cpuRegs.interrupt &= ~(1 << i);          cpuRegs.interrupt &= ~(1 << i);
249  }  }
250    
251  static __forceinline void TESTINT( u8 n, void (*callback)() )  static __fi void TESTINT( u8 n, void (*callback)() )
252  {  {
253          if( !(cpuRegs.interrupt & (1 << n)) ) return;          if( !(cpuRegs.interrupt & (1 << n)) ) return;
254    
# Line 281  static __forceinline void TESTINT( u8 n, Line 258  static __forceinline void TESTINT( u8 n,
258                  callback();                  callback();
259          }          }
260          else          else
261                  cpuSetNextBranch( cpuRegs.sCycle[n], cpuRegs.eCycle[n] );                  cpuSetNextEvent( cpuRegs.sCycle[n], cpuRegs.eCycle[n] );
262  }  }
263    
264  static __forceinline void _cpuTestInterrupts()  // [TODO] move this function to LegacyDmac.cpp, and remove most of the DMAC-related headers from
265    // being included into R5900.cpp.
266    static __fi void _cpuTestInterrupts()
267  {  {
268          if (!dmacRegs->ctrl.DMAE || psHu8(DMAC_ENABLER+2) == 1)          if (!dmacRegs.ctrl.DMAE || (psHu8(DMAC_ENABLER+2) & 1))
269          {          {
270                  //Console.Write("DMAC Disabled or suspended");                  //Console.Write("DMAC Disabled or suspended");
271                  return;                  return;
# Line 294  static __forceinline void _cpuTestInterr Line 273  static __forceinline void _cpuTestInterr
273          /* These are 'pcsx2 interrupts', they handle asynchronous stuff          /* These are 'pcsx2 interrupts', they handle asynchronous stuff
274             that depends on the cycle timings */             that depends on the cycle timings */
275    
276          TESTINT(1, vif1Interrupt);          TESTINT(DMAC_VIF1,              vif1Interrupt);
277          TESTINT(2, gsInterrupt);          TESTINT(DMAC_GIF,               gsInterrupt);  
278          TESTINT(5, EEsif0Interrupt);          TESTINT(DMAC_SIF0,              EEsif0Interrupt);
279          TESTINT(6, EEsif1Interrupt);          TESTINT(DMAC_SIF1,              EEsif1Interrupt);
280    
281          // Profile-guided Optimization (sorta)          // Profile-guided Optimization (sorta)
282          // The following ints are rarely called.  Encasing them in a conditional          // The following ints are rarely called.  Encasing them in a conditional
# Line 305  static __forceinline void _cpuTestInterr Line 284  static __forceinline void _cpuTestInterr
284    
285          if( cpuRegs.interrupt & 0xF19 ) // Bits 0 3 4 8 9 10 11 ( 111100011001 )          if( cpuRegs.interrupt & 0xF19 ) // Bits 0 3 4 8 9 10 11 ( 111100011001 )
286          {          {
287                  TESTINT(0, vif0Interrupt);                  TESTINT(DMAC_VIF0,              vif0Interrupt);
288    
289                  TESTINT(3, ipu0Interrupt);                  TESTINT(DMAC_FROM_IPU,  ipu0Interrupt);
290                  TESTINT(4, ipu1Interrupt);                  TESTINT(DMAC_TO_IPU,    ipu1Interrupt);
291    
292                  TESTINT(8, SPRFROMinterrupt);                  TESTINT(DMAC_FROM_SPR,  SPRFROMinterrupt);
293                  TESTINT(9, SPRTOinterrupt);                  TESTINT(DMAC_TO_SPR,    SPRTOinterrupt);
294    
295                  TESTINT(10, vifMFIFOInterrupt);                  TESTINT(DMAC_MFIFO_VIF, vifMFIFOInterrupt);
296                  TESTINT(11, gifMFIFOInterrupt);                  TESTINT(DMAC_MFIFO_GIF, gifMFIFOInterrupt);
297          }          }
298  }  }
299    
300  static __forceinline void _cpuTestTIMR()  static __fi void _cpuTestTIMR()
301  {  {
302          cpuRegs.CP0.n.Count += cpuRegs.cycle-s_iLastCOP0Cycle;          cpuRegs.CP0.n.Count += cpuRegs.cycle-s_iLastCOP0Cycle;
303          s_iLastCOP0Cycle = cpuRegs.cycle;          s_iLastCOP0Cycle = cpuRegs.cycle;
304    
305          // fixme: this looks like a hack to make up for the fact that the TIMR          // fixme: this looks like a hack to make up for the fact that the TIMR
306          // doesn't yet have a proper mechanism for setting itself up on a nextBranchCycle.          // doesn't yet have a proper mechanism for setting itself up on a nextEventCycle.
307          // A proper fix would schedule the TIMR to trigger at a specific cycle anytime          // A proper fix would schedule the TIMR to trigger at a specific cycle anytime
308          // the Count or Compare registers are modified.          // the Count or Compare registers are modified.
309    
# Line 336  static __forceinline void _cpuTestTIMR() Line 315  static __forceinline void _cpuTestTIMR()
315          }          }
316  }  }
317    
318  static __forceinline void _cpuTestPERF()  static __fi void _cpuTestPERF()
319  {  {
320          // Perfs are updated when read by games (COP0's MFC0/MTC0 instructions), so we need          // Perfs are updated when read by games (COP0's MFC0/MTC0 instructions), so we need
321          // only update them at semi-regular intervals to keep cpuRegs.cycle from wrapping          // only update them at semi-regular intervals to keep cpuRegs.cycle from wrapping
# Line 351  static __forceinline void _cpuTestPERF() Line 330  static __forceinline void _cpuTestPERF()
330  // them out.  Exceptions while the exception handler is active (EIE), or exceptions of any  // them out.  Exceptions while the exception handler is active (EIE), or exceptions of any
331  // level other than 0 are ignored here.  // level other than 0 are ignored here.
332    
333  static bool cpuIntsEnabled()  static bool cpuIntsEnabled(int Interrupt)
334  {  {
335          return cpuRegs.CP0.n.Status.b.EIE && cpuRegs.CP0.n.Status.b.IE &&          bool IntType = !!(cpuRegs.CP0.n.Status.val & Interrupt); //Choose either INTC or DMAC, depending on what called it
336    
337            return IntType && cpuRegs.CP0.n.Status.b.EIE && cpuRegs.CP0.n.Status.b.IE &&
338                  !cpuRegs.CP0.n.Status.b.EXL && (cpuRegs.CP0.n.Status.b.ERL == 0);                  !cpuRegs.CP0.n.Status.b.EXL && (cpuRegs.CP0.n.Status.b.ERL == 0);
339  }  }
340    
341  // if cpuRegs.cycle is greater than this cycle, should check cpuBranchTest for updates  // if cpuRegs.cycle is greater than this cycle, should check cpuEventTest for updates
342  u32 g_nextBranchCycle = 0;  u32 g_nextEventCycle = 0;
343    
344  // Shared portion of the branch test, called from both the Interpreter  // Shared portion of the branch test, called from both the Interpreter
345  // and the recompiler.  (moved here to help alleviate redundant code)  // and the recompiler.  (moved here to help alleviate redundant code)
346  __forceinline void _cpuBranchTest_Shared()  __fi void _cpuEventTest_Shared()
347  {  {
348          eeEventTestIsActive = true;          ScopedBool etest(eeEventTestIsActive);
349          g_nextBranchCycle = cpuRegs.cycle + eeWaitCycles;          g_nextEventCycle = cpuRegs.cycle + eeWaitCycles;
350    
351            // ---- INTC / DMAC (CPU-level Exceptions) -----------------
352            // Done first because exceptions raised during event tests need to be postponed a few
353            // cycles (fixes Grandia II [PAL], which does a spin loop on a vsync and expects to
354            // be able to read the value before the exception handler clears it).
355    
356            uint mask = intcInterrupt() | dmacInterrupt();
357            if (cpuIntsEnabled(mask)) cpuException(mask, cpuRegs.branch);
358    
359    
360          // ---- Counters -------------          // ---- Counters -------------
361          // Important: the vsync counter must be the first to be checked.  It includes emulation          // Important: the vsync counter must be the first to be checked.  It includes emulation
362          // escape/suspend hooks, and it's really a good idea to suspend/resume emulation before          // escape/suspend hooks, and it's really a good idea to suspend/resume emulation before
363          // doing any actual meaninful branchtest logic.          // doing any actual meaningful branchtest logic.
364    
365          if( cpuTestCycle( nextsCounter, nextCounter ) )          if( cpuTestCycle( nextsCounter, nextCounter ) )
366          {          {
# Line 383  __forceinline void _cpuBranchTest_Shared Line 373  __forceinline void _cpuBranchTest_Shared
373          _cpuTestTIMR();          _cpuTestTIMR();
374    
375          // ---- Interrupts -------------          // ---- Interrupts -------------
376          // Handles all interrupts except 30 and 31, which are handled later.          // These are basically just DMAC-related events, which also piggy-back the same bits as
377            // the PS2's own DMA channel IRQs and IRQ Masks.
378    
379          if( cpuRegs.interrupt & ~(3<<30) )          _cpuTestInterrupts();
                 _cpuTestInterrupts();  
380    
381          // ---- IOP -------------          // ---- IOP -------------
382          // * It's important to run a psxBranchTest before calling ExecuteBlock. This          // * It's important to run a iopEventTest before calling ExecuteBlock. This
383          //   is because the IOP does not always perform branch tests before returning          //   is because the IOP does not always perform branch tests before returning
384          //   (during the prev branch) and also so it can act on the state the EE has          //   (during the prev branch) and also so it can act on the state the EE has
385          //   given it before executing any code.          //   given it before executing any code.
386          //          //
387          // * The IOP cannot always be run.  If we run IOP code every time through the          // * The IOP cannot always be run.  If we run IOP code every time through the
388          //   cpuBranchTest, the IOP generally starts to run way ahead of the EE.          //   cpuEventTest, the IOP generally starts to run way ahead of the EE.
389    
390          EEsCycle += cpuRegs.cycle - EEoCycle;          EEsCycle += cpuRegs.cycle - EEoCycle;
391          EEoCycle = cpuRegs.cycle;          EEoCycle = cpuRegs.cycle;
392    
393          if( EEsCycle > 0 )          if( EEsCycle > 0 )
394                  iopBranchAction = true;                  iopEventAction = true;
395    
396          psxBranchTest();          iopEventTest();
397    
398          if( iopBranchAction )          if( iopEventAction )
399          {          {
400                  //if( EEsCycle < -450 )                  //if( EEsCycle < -450 )
401                  //      Console.WriteLn( " IOP ahead by: %d cycles", -EEsCycle );                  //      Console.WriteLn( " IOP ahead by: %d cycles", -EEsCycle );
402    
403                  // Experimental and Probably Unnecessry Logic -->                  EEsCycle = psxCpu->ExecuteBlock( EEsCycle );
                 // Check if the EE already has an exception pending, and if so we shouldn't  
                 // waste too much time updating the IOP.  Theory being that the EE and IOP should  
                 // run closely in sync during raised exception events.  But in practice it didn't  
                 // seem to make much of a difference.  
   
                 // Note: The IOP is very good about chaining blocks together so it tends to  
                 // run lots of cycles, even with only 32 (4 IOP) cycles specified here.  That's  
                 // probably why it doesn't improve sync much.  
   
                 /*bool eeExceptPending = cpuIntsEnabled() &&  
                         //( cpuRegs.CP0.n.Status.b.EIE && cpuRegs.CP0.n.Status.b.IE && (cpuRegs.CP0.n.Status.b.ERL == 0) ) &&  
                         //( (cpuRegs.CP0.n.Status.val & 0x10007) == 0x10001 ) &&  
                         ( (cpuRegs.interrupt & (3<<30)) != 0 );  
404    
405                  if( eeExceptPending )                  iopEventAction = false;
                 {  
                         // ExecuteBlock returns a negative value, so subtract it from the cycle count  
                         // specified to get the total cycles processed! :D  
                         int cycleCount = std::min( EEsCycle, (s32)(eeWaitCycles>>4) );  
                         int cyclesRun = cycleCount - psxCpu->ExecuteBlock( cycleCount );  
                         EEsCycle -= cyclesRun;  
                         //Console.Warning( "IOP Exception-Pending Execution -- EEsCycle: %d", EEsCycle );  
                 }  
                 else*/  
                 {  
                         EEsCycle = psxCpu->ExecuteBlock( EEsCycle );  
                 }  
   
                 iopBranchAction = false;  
406          }          }
407    
408          // ---- VU0 -------------          // ---- VU0 -------------
409          // We're in a BranchTest.  All dynarec registers are flushed          // We're in a EventTest.  All dynarec registers are flushed
410          // so there is no need to freeze registers here.          // so there is no need to freeze registers here.
411          CpuVU0->ExecuteBlock();          CpuVU0->ExecuteBlock();
412    
# Line 458  __forceinline void _cpuBranchTest_Shared Line 421  __forceinline void _cpuBranchTest_Shared
421                  // EE's running way ahead of the IOP still, so we should branch quickly to give the                  // EE's running way ahead of the IOP still, so we should branch quickly to give the
422                  // IOP extra timeslices in short order.                  // IOP extra timeslices in short order.
423    
424                  cpuSetNextBranchDelta( 48 );                  cpuSetNextEventDelta( 48 );
425                  //Console.Warning( "EE ahead of the IOP -- Rapid Branch!  %d", EEsCycle );                  //Console.Warning( "EE ahead of the IOP -- Rapid Event!  %d", EEsCycle );
426          }          }
427    
428          // The IOP could be running ahead/behind of us, so adjust the iop's next branch by its          // The IOP could be running ahead/behind of us, so adjust the iop's next branch by its
429          // relative position to the EE (via EEsCycle)          // relative position to the EE (via EEsCycle)
430          cpuSetNextBranchDelta( ((g_psxNextBranchCycle-psxRegs.cycle)*8) - EEsCycle );          cpuSetNextEventDelta( ((g_iopNextEventCycle-psxRegs.cycle)*8) - EEsCycle );
431    
432          // Apply the hsync counter's nextCycle          // Apply the hsync counter's nextCycle
433          cpuSetNextBranch( hsyncCounter.sCycle, hsyncCounter.CycleT );          cpuSetNextEvent( hsyncCounter.sCycle, hsyncCounter.CycleT );
434    
435          // Apply vsync and other counter nextCycles          // Apply vsync and other counter nextCycles
436          cpuSetNextBranch( nextsCounter, nextCounter );          cpuSetNextEvent( nextsCounter, nextCounter );
   
         eeEventTestIsActive = false;  
   
         // ---- INTC / DMAC Exceptions -----------------  
         // Raise the INTC and DMAC interrupts here, which usually throw exceptions.  
         // This should be done last since the IOP and the VU0 can raise several EE  
         // exceptions.  
   
         //if ((cpuRegs.CP0.n.Status.val & 0x10007) == 0x10001)  
         if( cpuIntsEnabled() )  
         {  
                 TESTINT(30, intcInterrupt);  
                 TESTINT(31, dmacInterrupt);  
         }  
437  }  }
438    
439  __releaseinline void cpuTestINTCInts()  __ri void cpuTestINTCInts()
440  {  {
441          if( cpuRegs.interrupt & (1 << 30) ) return;          // Check the COP0's Status register for general interrupt disables, and the 0x400
442          //if( (cpuRegs.CP0.n.Status.val & 0x10407) != 0x10401 ) return;          // bit (which is INTC master toggle).
443          if( !cpuIntsEnabled() ) return;          if( !cpuIntsEnabled(0x400) ) return;
         if( (psHu32(INTC_STAT) & psHu32(INTC_MASK)) == 0 ) return;  
444    
445          cpuRegs.interrupt|= 1 << 30;          if( (psHu32(INTC_STAT) & psHu32(INTC_MASK)) == 0 ) return;
         cpuRegs.sCycle[30] = cpuRegs.cycle;  
         cpuRegs.eCycle[30] = 4;  //Needs to be 4 to account for bus delays/pipelines etc  
446    
447          // only set the next branch delta if the exception won't be handled for          cpuSetNextEventDelta( 4 );
448          // the current branch...          if(eeEventTestIsActive && (iopCycleEE > 0))
         if( !eeEventTestIsActive )  
                 cpuSetNextBranchDelta( 4 );  
         else if(psxCycleEE > 0)  
449          {          {
450                  psxBreak += psxCycleEE;         // record the number of cycles the IOP didn't run.                  iopBreak += iopCycleEE;         // record the number of cycles the IOP didn't run.
451                  psxCycleEE = 0;                  iopCycleEE = 0;
452          }          }
453  }  }
454    
455  __forceinline void cpuTestDMACInts()  __fi void cpuTestDMACInts()
456  {  {
457          if ( cpuRegs.interrupt & (1 << 31) ) return;          // Check the COP0's Status register for general interrupt disables, and the 0x800
458          if ((cpuRegs.CP0.n.Status.val & 0x10807) != 0x10801) return;          // bit (which is the DMAC master toggle).
459            if( !cpuIntsEnabled(0x800) ) return;
460    
461          if ( ( (psHu16(0xe012) & psHu16(0xe010)) == 0) &&          if ( ( (psHu16(0xe012) & psHu16(0xe010)) == 0) &&
462                   ( (psHu16(0xe010) & 0x8000) == 0) ) return;                   ( (psHu16(0xe010) & 0x8000) == 0) ) return;
463    
464          cpuRegs.interrupt|= 1 << 31;          cpuSetNextEventDelta( 4 );
465          cpuRegs.sCycle[31] = cpuRegs.cycle;          if(eeEventTestIsActive && (iopCycleEE > 0))
         cpuRegs.eCycle[31] = 4;  //Needs to be 4 to account for bus delays/pipelines etc  
   
         // only set the next branch delta if the exception won't be handled for  
         // the current branch...  
         if( !eeEventTestIsActive )  
                 cpuSetNextBranchDelta( 4 );  
         else if(psxCycleEE > 0)  
466          {          {
467                  psxBreak += psxCycleEE;         // record the number of cycles the IOP didn't run.                  iopBreak += iopCycleEE;         // record the number of cycles the IOP didn't run.
468                  psxCycleEE = 0;                  iopCycleEE = 0;
469          }          }
470  }  }
471    
472  __forceinline void cpuTestTIMRInts() {  __fi void cpuTestTIMRInts() {
473          if ((cpuRegs.CP0.n.Status.val & 0x10007) == 0x10001) {          if ((cpuRegs.CP0.n.Status.val & 0x10007) == 0x10001) {
474                  _cpuTestPERF();                  _cpuTestPERF();
475                  _cpuTestTIMR();                  _cpuTestTIMR();
476          }          }
477  }  }
478    
479  __forceinline void cpuTestHwInts() {  __fi void cpuTestHwInts() {
480          cpuTestINTCInts();          cpuTestINTCInts();
481          cpuTestDMACInts();          cpuTestDMACInts();
482          cpuTestTIMRInts();          cpuTestTIMRInts();
483  }  }
484    
485  __forceinline void CPU_INT( u32 n, s32 ecycle)  __fi void CPU_INT( EE_EventType n, s32 ecycle)
486  {  {
487          if( n != 2 && cpuRegs.interrupt & (1<<n) ){ //2 is Gif, and every path 3 masking game triggers this :/          if( n != 2 && cpuRegs.interrupt & (1<<n) ){ //2 is Gif, and every path 3 masking game triggers this :/
488                  DevCon.Warning( "***** EE > Twice-thrown int on IRQ %d", n );                  DevCon.Warning( "***** EE > Twice-thrown int on IRQ %d", n );
489          }          }
490    
491          // EE events happen 1 cycle in the future instead of whatever was requested.          // EE events happen 8 cycles in the future instead of whatever was requested.
492          // This can be used on games with PATH3 masking issues for example, or when          // This can be used on games with PATH3 masking issues for example, or when
493          // some FMV look bad.          // some FMV look bad.
494          if(CHECK_EETIMINGHACK) ecycle = 1;          if(CHECK_EETIMINGHACK) ecycle = 8;
495    
496          cpuRegs.interrupt|= 1 << n;          cpuRegs.interrupt|= 1 << n;
497          cpuRegs.sCycle[n] = cpuRegs.cycle;          cpuRegs.sCycle[n] = cpuRegs.cycle;
# Line 562  __forceinline void CPU_INT( u32 n, s32 e Line 499  __forceinline void CPU_INT( u32 n, s32 e
499    
500          // Interrupt is happening soon: make sure both EE and IOP are aware.          // Interrupt is happening soon: make sure both EE and IOP are aware.
501    
502          if( ecycle <= 28 && psxCycleEE > 0 )          if( ecycle <= 28 && iopCycleEE > 0 )
503          {          {
504                  // If running in the IOP, force it to break immediately into the EE.                  // If running in the IOP, force it to break immediately into the EE.
505                  // the EE's branch test is due to run.                  // the EE's branch test is due to run.
506    
507                  psxBreak += psxCycleEE;         // record the number of cycles the IOP didn't run.                  iopBreak += iopCycleEE;         // record the number of cycles the IOP didn't run.
508                  psxCycleEE = 0;                  iopCycleEE = 0;
509          }          }
510    
511          cpuSetNextBranchDelta( cpuRegs.eCycle[n] );          cpuSetNextEventDelta( cpuRegs.eCycle[n] );
512  }  }
513    
514    // Called from recompilers; __fastcall define is mandatory.
515  void __fastcall eeGameStarting()  void __fastcall eeGameStarting()
516  {  {
517          if (!g_GameStarted && ElfCRC) {          if (!g_GameStarted)
518                  wxString gameCRC( wxsFormat( L"%8.8x", ElfCRC ) );          {
519                  wxString gameName   = L"Unknown Game (\?\?\?)";                  //Console.WriteLn( Color_Green, "(R5900) ELF Entry point! [addr=0x%08X]", ElfEntry );
                 wxString gameSerial = L" [" + DiscID  + L"]";  
                 wxString gameCompat = L" [Status = Unknown]";  
                 wxString gamePatch  = L"";  
                 wxString gameFixes  = L"";  
                 wxString gameCheats = L"";  
   
                 if (GameDB && GameDB->gameLoaded()) {  
                         int compat = GameDB->getInt("Compat");  
                         gameName   = GameDB->getStringWX("Name");  
                         gameName  += L" (" + GameDB->getStringWX("Region") + L")";  
                         gameCompat = L" [Status = "+compatToStringWX(compat)+L"]";  
                 }  
                   
                 if (EmuConfig.EnablePatches) {  
                         int patches = InitPatches(gameCRC);  
                         if (patches) {  
                                 wxString pString( wxsFormat( L"%d", patches ) );  
                                 gamePatch = L" [Patches = " + pString + L"]";  
                         }  
                         int fixes = loadGameSettings(GameDB);  
                         if (fixes) {  
                                 wxString pString( wxsFormat( L"%d", fixes ) );  
                                 gameFixes = L" [Fixes = " + pString + L"]";  
                         }  
                 }  
   
                 if (EmuConfig.EnableCheats) {  
                         int cheats = InitCheats(gameCRC);  
                         if (cheats) {  
                                 wxString cString( wxsFormat( L"%d", cheats ) );  
                                 gameCheats = L" [Cheats = " + cString + L"]";  
                         }  
                 }  
   
                 Console.SetTitle(gameName+gameSerial+gameCompat+gameFixes+gamePatch+gameCheats);  
                   
                 GetMTGS().SendGameCRC(ElfCRC);  
520                  g_GameStarted = true;                  g_GameStarted = true;
521                                    GetCoreThread().GameStartingInThread();
                 if (0) ProfilerSetEnabled(true);  
         }  
522    
523          if (EmuConfig.EnablePatches) ApplyPatch(0);                  // GameStartingInThread may issue a reset of the cpu and/or recompilers.  Check for and
524          if (EmuConfig.EnableCheats)  ApplyCheat(0);                  // handle such things here:
525                    Cpu->CheckExecutionState();
526            }
527            else
528            {
529                    Console.WriteLn( Color_Green, "(R5900) Re-executed ELF Entry point (ignored) [addr=0x%08X]", ElfEntry );
530            }
531  }  }
532    
533    // Called from recompilers; __fastcall define is mandatory.
534  void __fastcall eeloadReplaceOSDSYS()  void __fastcall eeloadReplaceOSDSYS()
535  {  {
536          g_SkipBiosHack = false;          g_SkipBiosHack = false;
# Line 636  void __fastcall eeloadReplaceOSDSYS() Line 542  void __fastcall eeloadReplaceOSDSYS()
542          else          else
543                  cdvdReloadElfInfo();                  cdvdReloadElfInfo();
544    
545          // didn't recognise an ELF          // didn't recognize an ELF
546          if (ElfEntry == -1) {          if (ElfEntry == -1) {
547                  eeGameStarting();                  eeGameStarting();
548                  return;                  return;
# Line 665  void __fastcall eeloadReplaceOSDSYS() Line 571  void __fastcall eeloadReplaceOSDSYS()
571          }          }
572          pxAssert(osdsys_p);          pxAssert(osdsys_p);
573    
574          string elfname;          std::string elfname;
575    
576          if (!elf_override.IsEmpty())          if (!elf_override.IsEmpty())
577          {          {

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

  ViewVC Help
Powered by ViewVC 1.1.22