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

Diff of /trunk/pcsx2/Counters.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 273 by william, Fri Nov 12 01:10:22 2010 UTC
# Line 15  Line 15 
15    
16    
17  #include "PrecompiledHeader.h"  #include "PrecompiledHeader.h"
 #include "Common.h"  
18    
19  #include <time.h>  #include <time.h>
20  #include <cmath>  #include <cmath>
21    
22    #include "Common.h"
23  #include "R3000A.h"  #include "R3000A.h"
24  #include "Counters.h"  #include "Counters.h"
25  #include "IopCounters.h"  #include "IopCounters.h"
# Line 27  Line 27 
27  #include "GS.h"  #include "GS.h"
28  #include "VUmicro.h"  #include "VUmicro.h"
29    
30    #include "ps2/HwInternal.h"
31    
32  using namespace Threading;  using namespace Threading;
33    
34  extern u8 psxhblankgate;  extern u8 psxhblankgate;
# Line 45  SyncCounter vsyncCounter; Line 47  SyncCounter vsyncCounter;
47  u32 nextsCounter;       // records the cpuRegs.cycle value of the last call to rcntUpdate()  u32 nextsCounter;       // records the cpuRegs.cycle value of the last call to rcntUpdate()
48  s32 nextCounter;        // delta from nextsCounter, in cycles, until the next rcntUpdate()  s32 nextCounter;        // delta from nextsCounter, in cycles, until the next rcntUpdate()
49    
50    // Forward declarations needed because C/C++ both are wimpy single-pass compilers.
51    
52    static void rcntStartGate(bool mode, u32 sCycle);
53    static void rcntEndGate(bool mode, u32 sCycle);
54    static void rcntWcount(int index, u32 value);
55    static void rcntWmode(int index, u32 value);
56    static void rcntWtarget(int index, u32 value);
57    static void rcntWhold(int index, u32 value);
58    
59    
60  void rcntReset(int index) {  void rcntReset(int index) {
61          counters[index].count = 0;          counters[index].count = 0;
# Line 54  void rcntReset(int index) { Line 65  void rcntReset(int index) {
65  // Updates the state of the nextCounter value (if needed) to serve  // Updates the state of the nextCounter value (if needed) to serve
66  // any pending events for the given counter.  // any pending events for the given counter.
67  // Call this method after any modifications to the state of a counter.  // Call this method after any modifications to the state of a counter.
68  static __forceinline void _rcntSet( int cntidx )  static __fi void _rcntSet( int cntidx )
69  {  {
70          s32 c;          s32 c;
71          jASSUME( cntidx <= 4 );         // rcntSet isn't valid for h/vsync counters.          jASSUME( cntidx <= 4 );         // rcntSet isn't valid for h/vsync counters.
# Line 82  static __forceinline void _rcntSet( int Line 93  static __forceinline void _rcntSet( int
93          if (c < nextCounter)          if (c < nextCounter)
94          {          {
95                  nextCounter = c;                  nextCounter = c;
96                  cpuSetNextBranch( nextsCounter, nextCounter );  //Need to update on counter resets/target changes                  cpuSetNextEvent( nextsCounter, nextCounter );   //Need to update on counter resets/target changes
97          }          }
98    
99          // Ignore target diff if target is currently disabled.          // Ignore target diff if target is currently disabled.
# Line 100  static __forceinline void _rcntSet( int Line 111  static __forceinline void _rcntSet( int
111                  if (c < nextCounter)                  if (c < nextCounter)
112                  {                  {
113                          nextCounter = c;                          nextCounter = c;
114                          cpuSetNextBranch( nextsCounter, nextCounter );  //Need to update on counter resets/target changes                          cpuSetNextEvent( nextsCounter, nextCounter );   //Need to update on counter resets/target changes
115                  }                  }
116          }          }
117  }  }
118    
119    
120  static __forceinline void cpuRcntSet()  static __fi void cpuRcntSet()
121  {  {
122          int i;          int i;
123    
# Line 222  static void vSyncInfoCalc( vSyncTimingIn Line 233  static void vSyncInfoCalc( vSyncTimingIn
233    
234  u32 UpdateVSyncRate()  u32 UpdateVSyncRate()
235  {  {
         Registers::Freeze();  
   
236          // Notice:  (and I probably repeat this elsewhere, but it's worth repeating)          // Notice:  (and I probably repeat this elsewhere, but it's worth repeating)
237          //  The PS2's vsync timer is an *independent* crystal that is fixed to either 59.94 (NTSC)          //  The PS2's vsync timer is an *independent* crystal that is fixed to either 59.94 (NTSC)
238          //  or 50.0 (PAL) Hz.  It has *nothing* to do with real TV timings or the real vsync of          //  or 50.0 (PAL) Hz.  It has *nothing* to do with real TV timings or the real vsync of
# Line 277  u32 UpdateVSyncRate() Line 286  u32 UpdateVSyncRate()
286    
287          m_iStart = GetCPUTicks();          m_iStart = GetCPUTicks();
288    
         Registers::Thaw();  
   
289          return (u32)m_iTicks;          return (u32)m_iTicks;
290  }  }
291    
# Line 290  void frameLimitReset() Line 297  void frameLimitReset()
297  // Framelimiter - Measures the delta time between calls and stalls until a  // Framelimiter - Measures the delta time between calls and stalls until a
298  // certain amount of time passes if such time hasn't passed yet.  // certain amount of time passes if such time hasn't passed yet.
299  // See the GS FrameSkip function for details on why this is here and not in the GS.  // See the GS FrameSkip function for details on why this is here and not in the GS.
300  static __forceinline void frameLimit()  static __fi void frameLimit()
301  {  {
302          // 999 means the user would rather just have framelimiting turned off...          // 999 means the user would rather just have framelimiting turned off...
303          if( !EmuConfig.GS.FrameLimitEnable ) return;          if( !EmuConfig.GS.FrameLimitEnable ) return;
# Line 335  static __forceinline void frameLimit() Line 342  static __forceinline void frameLimit()
342          // starting this frame, it'll just sleep longer the next to make up for it. :)          // starting this frame, it'll just sleep longer the next to make up for it. :)
343  }  }
344    
345  static __forceinline void VSyncStart(u32 sCycle)  static __fi void VSyncStart(u32 sCycle)
346  {  {
         Cpu->CheckExecutionState();  
347          GetCoreThread().VsyncInThread();          GetCoreThread().VsyncInThread();
348            Cpu->CheckExecutionState();
349    
350          EECNT_LOG( "/////////  EE COUNTER VSYNC START (frame: %6d)  \\\\\\\\\\\\\\\\\\\\ ", g_FrameCount );          if(EmuConfig.Trace.Enabled && EmuConfig.Trace.EE.m_EnableAll)
351                    SysTrace.EE.Counters.Write( "    ================  EE COUNTER VSYNC START (frame: %d)  ================", g_FrameCount );
352    
353          // EE Profiling and Debug code.          // EE Profiling and Debug code.
354          // FIXME: should probably be moved to VsyncInThread, and handled          // FIXME: should probably be moved to VsyncInThread, and handled
# Line 350  static __forceinline void VSyncStart(u32 Line 358  static __forceinline void VSyncStart(u32
358          CpuVU0->Vsync();          CpuVU0->Vsync();
359          CpuVU1->Vsync();          CpuVU1->Vsync();
360    
361          if ((CSRw & 0x8))          if (!CSRreg.VSINT)
362          {          {
363                    CSRreg.VSINT = true;
364                  if (!(GSIMR&0x800))                  if (!(GSIMR&0x800))
365                  {                  {
366                          gsIrq();                          gsIrq();
367                  }                  }
                 GSCSRr|= 0x8;  
368          }          }
369    
370          hwIntcIrq(INTC_VBLANK_S);          hwIntcIrq(INTC_VBLANK_S);
# Line 384  static __forceinline void VSyncStart(u32 Line 392  static __forceinline void VSyncStart(u32
392          // Should no longer be required (Refraction)          // Should no longer be required (Refraction)
393  }  }
394    
395  static __forceinline void VSyncEnd(u32 sCycle)  static __fi void VSyncEnd(u32 sCycle)
396  {  {
397          EECNT_LOG( "/////////  EE COUNTER VSYNC END (frame: %d)  \\\\\\\\\\\\\\\\\\\\", g_FrameCount );          if(EmuConfig.Trace.Enabled && EmuConfig.Trace.EE.m_EnableAll)
398                    SysTrace.EE.Counters.Write( "    ================  EE COUNTER VSYNC END (frame: %d)  ================", g_FrameCount );
399    
400          g_FrameCount++;          g_FrameCount++;
401    
# Line 408  static u32 hsc=0; Line 417  static u32 hsc=0;
417  static int vblankinc = 0;  static int vblankinc = 0;
418  #endif  #endif
419    
420  __forceinline void rcntUpdate_hScanline()  __fi void rcntUpdate_hScanline()
421  {  {
422          if( !cpuTestCycle( hsyncCounter.sCycle, hsyncCounter.CycleT ) ) return;          if( !cpuTestCycle( hsyncCounter.sCycle, hsyncCounter.CycleT ) ) return;
423    
424          //iopBranchAction = 1;          //iopEventAction = 1;
425          if (hsyncCounter.Mode & MODE_HBLANK) { //HBLANK Start          if (hsyncCounter.Mode & MODE_HBLANK) { //HBLANK Start
426                  rcntStartGate(false, hsyncCounter.sCycle);                  rcntStartGate(false, hsyncCounter.sCycle);
427                  psxCheckStartGate16(0);                  psxCheckStartGate16(0);
# Line 423  __forceinline void rcntUpdate_hScanline( Line 432  __forceinline void rcntUpdate_hScanline(
432                  hsyncCounter.Mode = MODE_HRENDER;                  hsyncCounter.Mode = MODE_HRENDER;
433          }          }
434          else { //HBLANK END / HRENDER Begin          else { //HBLANK END / HRENDER Begin
435                  if (CSRw & 0x4)                  if (!CSRreg.HSINT)
436                  {                  {
437                            CSRreg.HSINT = true;
438                          if (!(GSIMR&0x400))                          if (!(GSIMR&0x400))
439                          {                          {
440                                  gsIrq();                                  gsIrq();
441                          }                          }
                         GSCSRr |= 4; // signal  
442                  }                  }
443                  if (gates) rcntEndGate(false, hsyncCounter.sCycle);                  if (gates) rcntEndGate(false, hsyncCounter.sCycle);
444                  if (psxhblankgate) psxCheckEndGate16(0);                  if (psxhblankgate) psxCheckEndGate16(0);
# Line 445  __forceinline void rcntUpdate_hScanline( Line 454  __forceinline void rcntUpdate_hScanline(
454          }          }
455  }  }
456    
457  __forceinline void rcntUpdate_vSync()  __fi void rcntUpdate_vSync()
458  {  {
459          s32 diff = (cpuRegs.cycle - vsyncCounter.sCycle);          s32 diff = (cpuRegs.cycle - vsyncCounter.sCycle);
460          if( diff < vsyncCounter.CycleT ) return;          if( diff < vsyncCounter.CycleT ) return;
# Line 482  __forceinline void rcntUpdate_vSync() Line 491  __forceinline void rcntUpdate_vSync()
491          }          }
492  }  }
493    
494  static __forceinline void _cpuTestTarget( int i )  static __fi void _cpuTestTarget( int i )
495  {  {
496          if (counters[i].count < counters[i].target) return;          if (counters[i].count < counters[i].target) return;
497    
# Line 501  static __forceinline void _cpuTestTarget Line 510  static __forceinline void _cpuTestTarget
510          else counters[i].target |= EECNT_FUTURE_TARGET;          else counters[i].target |= EECNT_FUTURE_TARGET;
511  }  }
512    
513  static __forceinline void _cpuTestOverflow( int i )  static __fi void _cpuTestOverflow( int i )
514  {  {
515          if (counters[i].count <= 0xffff) return;          if (counters[i].count <= 0xffff) return;
516    
# Line 520  static __forceinline void _cpuTestOverfl Line 529  static __forceinline void _cpuTestOverfl
529  // forceinline note: this method is called from two locations, but one  // forceinline note: this method is called from two locations, but one
530  // of them is the interpreter, which doesn't count. ;)  So might as  // of them is the interpreter, which doesn't count. ;)  So might as
531  // well forceinline it!  // well forceinline it!
532  __forceinline void rcntUpdate()  __fi void rcntUpdate()
533  {  {
534          rcntUpdate_vSync();          rcntUpdate_vSync();
535    
# Line 554  __forceinline void rcntUpdate() Line 563  __forceinline void rcntUpdate()
563          cpuRcntSet();          cpuRcntSet();
564  }  }
565    
566  static __forceinline void _rcntSetGate( int index )  static __fi void _rcntSetGate( int index )
567  {  {
568          if (counters[index].mode.EnableGate)          if (counters[index].mode.EnableGate)
569          {          {
# Line 579  static __forceinline void _rcntSetGate( Line 588  static __forceinline void _rcntSetGate(
588  }  }
589    
590  // mode - 0 means hblank source, 8 means vblank source.  // mode - 0 means hblank source, 8 means vblank source.
591  __forceinline void rcntStartGate(bool isVblank, u32 sCycle)  static __fi void rcntStartGate(bool isVblank, u32 sCycle)
592  {  {
593          int i;          int i;
594    
# Line 640  __forceinline void rcntStartGate(bool is Line 649  __forceinline void rcntStartGate(bool is
649  }  }
650    
651  // mode - 0 means hblank signal, 8 means vblank signal.  // mode - 0 means hblank signal, 8 means vblank signal.
652  __forceinline void rcntEndGate(bool isVblank , u32 sCycle)  static __fi void rcntEndGate(bool isVblank , u32 sCycle)
653  {  {
654          int i;          int i;
655    
# Line 681  __forceinline void rcntEndGate(bool isVb Line 690  __forceinline void rcntEndGate(bool isVb
690          // rcntUpdate, since we're being called from there anyway.          // rcntUpdate, since we're being called from there anyway.
691  }  }
692    
693  __forceinline void rcntWmode(int index, u32 value)  static __fi u32 rcntCycle(int index)
694    {
695            if (counters[index].mode.IsCounting && (counters[index].mode.ClockSource != 0x3))
696                    return counters[index].count + ((cpuRegs.cycle - counters[index].sCycleT) / counters[index].rate);
697            else
698                    return counters[index].count;
699    }
700    
701    static __fi void rcntWmode(int index, u32 value)
702  {  {
703          if(counters[index].mode.IsCounting) {          if(counters[index].mode.IsCounting) {
704                  if(counters[index].mode.ClockSource != 0x3) {                  if(counters[index].mode.ClockSource != 0x3) {
# Line 715  __forceinline void rcntWmode(int index, Line 732  __forceinline void rcntWmode(int index,
732          _rcntSet( index );          _rcntSet( index );
733  }  }
734    
735  __forceinline void rcntWcount(int index, u32 value)  static __fi void rcntWcount(int index, u32 value)
736  {  {
737          EECNT_LOG("EE Counter[%d] writeCount = %x,   oldcount=%x, target=%x", index, value, counters[index].count, counters[index].target );          EECNT_LOG("EE Counter[%d] writeCount = %x,   oldcount=%x, target=%x", index, value, counters[index].count, counters[index].target );
738    
# Line 741  __forceinline void rcntWcount(int index, Line 758  __forceinline void rcntWcount(int index,
758          _rcntSet( index );          _rcntSet( index );
759  }  }
760    
761  __forceinline void rcntWtarget(int index, u32 value)  static __fi void rcntWtarget(int index, u32 value)
762  {  {
763          EECNT_LOG("EE Counter[%d] writeTarget = %x", index, value);          EECNT_LOG("EE Counter[%d] writeTarget = %x", index, value);
764    
# Line 770  __forceinline void rcntWtarget(int index Line 787  __forceinline void rcntWtarget(int index
787          _rcntSet( index );          _rcntSet( index );
788  }  }
789    
790  __forceinline void rcntWhold(int index, u32 value)  static __fi void rcntWhold(int index, u32 value)
791  {  {
792          EECNT_LOG("EE Counter[%d] Hold Write = %x", index, value);          EECNT_LOG("EE Counter[%d] Hold Write = %x", index, value);
793          counters[index].hold = value;          counters[index].hold = value;
794  }  }
795    
796  __forceinline u32 rcntRcount(int index)  __fi u32 rcntRcount(int index)
797  {  {
798          u32 ret;          u32 ret;
799    
# Line 791  __forceinline u32 rcntRcount(int index) Line 808  __forceinline u32 rcntRcount(int index)
808          return ret;          return ret;
809  }  }
810    
811  __forceinline u32 rcntCycle(int index)  template< uint page >
812    __fi u16 rcntRead32( u32 mem )
813  {  {
814          if (counters[index].mode.IsCounting && (counters[index].mode.ClockSource != 0x3))          // Important DevNote:
815                  return counters[index].count + ((cpuRegs.cycle - counters[index].sCycleT) / counters[index].rate);          // Yes this uses a u16 return value on purpose!  The upper bits 16 of the counter registers
816          else          // are all fixed to 0, so we always truncate everything in these two pages using a u16
817                  return counters[index].count;          // return value! --air
818    
819            iswitch( mem ) {
820            icase(RCNT0_COUNT)      return (u16)rcntRcount(0);
821            icase(RCNT0_MODE)       return (u16)counters[0].modeval;
822            icase(RCNT0_TARGET)     return (u16)counters[0].target;
823            icase(RCNT0_HOLD)       return (u16)counters[0].hold;
824    
825            icase(RCNT1_COUNT)      return (u16)rcntRcount(1);
826            icase(RCNT1_MODE)       return (u16)counters[1].modeval;
827            icase(RCNT1_TARGET)     return (u16)counters[1].target;
828            icase(RCNT1_HOLD)       return (u16)counters[1].hold;
829    
830            icase(RCNT2_COUNT)      return (u16)rcntRcount(2);
831            icase(RCNT2_MODE)       return (u16)counters[2].modeval;
832            icase(RCNT2_TARGET)     return (u16)counters[2].target;
833    
834            icase(RCNT3_COUNT)      return (u16)rcntRcount(3);
835            icase(RCNT3_MODE)       return (u16)counters[3].modeval;
836            icase(RCNT3_TARGET)     return (u16)counters[3].target;
837            }
838            
839            return psHu16(mem);
840  }  }
841    
842    template< uint page >
843    __fi bool rcntWrite32( u32 mem, mem32_t& value )
844    {
845            pxAssume( mem >= RCNT0_COUNT && mem < 0x10002000 );
846    
847            // [TODO] : counters should actually just use the EE's hw register space for storing
848            // count, mode, target, and hold. This will allow for a simplified handler for register
849            // reads.
850    
851            iswitch( mem ) {
852            icase(RCNT0_COUNT)      return rcntWcount(0, value),    false;
853            icase(RCNT0_MODE)       return rcntWmode(0, value),             false;
854            icase(RCNT0_TARGET)     return rcntWtarget(0, value),   false;
855            icase(RCNT0_HOLD)       return rcntWhold(0, value),             false;
856    
857            icase(RCNT1_COUNT)      return rcntWcount(1, value),    false;
858            icase(RCNT1_MODE)       return rcntWmode(1, value),             false;
859            icase(RCNT1_TARGET)     return rcntWtarget(1, value),   false;
860            icase(RCNT1_HOLD)       return rcntWhold(1, value),             false;
861    
862            icase(RCNT2_COUNT)      return rcntWcount(2, value),    false;
863            icase(RCNT2_MODE)       return rcntWmode(2, value),             false;
864            icase(RCNT2_TARGET)     return rcntWtarget(2, value),   false;
865    
866            icase(RCNT3_COUNT)      return rcntWcount(3, value),    false;
867            icase(RCNT3_MODE)       return rcntWmode(3, value),             false;
868            icase(RCNT3_TARGET)     return rcntWtarget(3, value),   false;
869            }
870    
871            // unhandled .. do memory writeback.
872            return true;
873    }
874    
875    template u16 rcntRead32<0x00>( u32 mem );
876    template u16 rcntRead32<0x01>( u32 mem );
877    
878    template bool rcntWrite32<0x00>( u32 mem, mem32_t& value );
879    template bool rcntWrite32<0x01>( u32 mem, mem32_t& value );
880    
881  void SaveStateBase::rcntFreeze()  void SaveStateBase::rcntFreeze()
882  {  {
883          Freeze( counters );          Freeze( counters );
# Line 809  void SaveStateBase::rcntFreeze() Line 888  void SaveStateBase::rcntFreeze()
888    
889          if( IsLoading() )          if( IsLoading() )
890          {          {
                 UpdateVSyncRate();  
   
891                  // make sure the gate flags are set based on the counter modes...                  // make sure the gate flags are set based on the counter modes...
892                  for( int i=0; i<4; i++ )                  for( int i=0; i<4; i++ )
893                          _rcntSetGate( i );                          _rcntSetGate( i );
894    
895                  iopBranchAction = 1;    // probably not needed but won't hurt anything either.                  iopEventAction = 1;     // probably not needed but won't hurt anything either.
896          }          }
897  }  }

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

  ViewVC Help
Powered by ViewVC 1.1.22