/[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 62 by william, Tue Sep 7 11:08: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 );          EECNT_LOG( "/////////  EE COUNTER VSYNC START (frame: %6d)  \\\\\\\\\\\\\\\\\\\\ ", g_FrameCount );
351    
# Line 350  static __forceinline void VSyncStart(u32 Line 357  static __forceinline void VSyncStart(u32
357          CpuVU0->Vsync();          CpuVU0->Vsync();
358          CpuVU1->Vsync();          CpuVU1->Vsync();
359    
360          if ((CSRw & 0x8))          if (!CSRreg.VSINT)
361          {          {
362                    CSRreg.VSINT = true;
363                  if (!(GSIMR&0x800))                  if (!(GSIMR&0x800))
364                  {                  {
365                          gsIrq();                          gsIrq();
366                  }                  }
                 GSCSRr|= 0x8;  
367          }          }
368    
369          hwIntcIrq(INTC_VBLANK_S);          hwIntcIrq(INTC_VBLANK_S);
# Line 384  static __forceinline void VSyncStart(u32 Line 391  static __forceinline void VSyncStart(u32
391          // Should no longer be required (Refraction)          // Should no longer be required (Refraction)
392  }  }
393    
394  static __forceinline void VSyncEnd(u32 sCycle)  static __fi void VSyncEnd(u32 sCycle)
395  {  {
396          EECNT_LOG( "/////////  EE COUNTER VSYNC END (frame: %d)  \\\\\\\\\\\\\\\\\\\\", g_FrameCount );          EECNT_LOG( "/////////  EE COUNTER VSYNC END (frame: %d)  \\\\\\\\\\\\\\\\\\\\", g_FrameCount );
397    
# Line 408  static u32 hsc=0; Line 415  static u32 hsc=0;
415  static int vblankinc = 0;  static int vblankinc = 0;
416  #endif  #endif
417    
418  __forceinline void rcntUpdate_hScanline()  __fi void rcntUpdate_hScanline()
419  {  {
420          if( !cpuTestCycle( hsyncCounter.sCycle, hsyncCounter.CycleT ) ) return;          if( !cpuTestCycle( hsyncCounter.sCycle, hsyncCounter.CycleT ) ) return;
421    
422          //iopBranchAction = 1;          //iopEventAction = 1;
423          if (hsyncCounter.Mode & MODE_HBLANK) { //HBLANK Start          if (hsyncCounter.Mode & MODE_HBLANK) { //HBLANK Start
424                  rcntStartGate(false, hsyncCounter.sCycle);                  rcntStartGate(false, hsyncCounter.sCycle);
425                  psxCheckStartGate16(0);                  psxCheckStartGate16(0);
# Line 423  __forceinline void rcntUpdate_hScanline( Line 430  __forceinline void rcntUpdate_hScanline(
430                  hsyncCounter.Mode = MODE_HRENDER;                  hsyncCounter.Mode = MODE_HRENDER;
431          }          }
432          else { //HBLANK END / HRENDER Begin          else { //HBLANK END / HRENDER Begin
433                  if (CSRw & 0x4)                  if (!CSRreg.HSINT)
434                  {                  {
435                            CSRreg.HSINT = true;
436                          if (!(GSIMR&0x400))                          if (!(GSIMR&0x400))
437                          {                          {
438                                  gsIrq();                                  gsIrq();
439                          }                          }
                         GSCSRr |= 4; // signal  
440                  }                  }
441                  if (gates) rcntEndGate(false, hsyncCounter.sCycle);                  if (gates) rcntEndGate(false, hsyncCounter.sCycle);
442                  if (psxhblankgate) psxCheckEndGate16(0);                  if (psxhblankgate) psxCheckEndGate16(0);
# Line 445  __forceinline void rcntUpdate_hScanline( Line 452  __forceinline void rcntUpdate_hScanline(
452          }          }
453  }  }
454    
455  __forceinline void rcntUpdate_vSync()  __fi void rcntUpdate_vSync()
456  {  {
457          s32 diff = (cpuRegs.cycle - vsyncCounter.sCycle);          s32 diff = (cpuRegs.cycle - vsyncCounter.sCycle);
458          if( diff < vsyncCounter.CycleT ) return;          if( diff < vsyncCounter.CycleT ) return;
# Line 482  __forceinline void rcntUpdate_vSync() Line 489  __forceinline void rcntUpdate_vSync()
489          }          }
490  }  }
491    
492  static __forceinline void _cpuTestTarget( int i )  static __fi void _cpuTestTarget( int i )
493  {  {
494          if (counters[i].count < counters[i].target) return;          if (counters[i].count < counters[i].target) return;
495    
# Line 501  static __forceinline void _cpuTestTarget Line 508  static __forceinline void _cpuTestTarget
508          else counters[i].target |= EECNT_FUTURE_TARGET;          else counters[i].target |= EECNT_FUTURE_TARGET;
509  }  }
510    
511  static __forceinline void _cpuTestOverflow( int i )  static __fi void _cpuTestOverflow( int i )
512  {  {
513          if (counters[i].count <= 0xffff) return;          if (counters[i].count <= 0xffff) return;
514    
# Line 520  static __forceinline void _cpuTestOverfl Line 527  static __forceinline void _cpuTestOverfl
527  // forceinline note: this method is called from two locations, but one  // forceinline note: this method is called from two locations, but one
528  // of them is the interpreter, which doesn't count. ;)  So might as  // of them is the interpreter, which doesn't count. ;)  So might as
529  // well forceinline it!  // well forceinline it!
530  __forceinline void rcntUpdate()  __fi void rcntUpdate()
531  {  {
532          rcntUpdate_vSync();          rcntUpdate_vSync();
533    
# Line 554  __forceinline void rcntUpdate() Line 561  __forceinline void rcntUpdate()
561          cpuRcntSet();          cpuRcntSet();
562  }  }
563    
564  static __forceinline void _rcntSetGate( int index )  static __fi void _rcntSetGate( int index )
565  {  {
566          if (counters[index].mode.EnableGate)          if (counters[index].mode.EnableGate)
567          {          {
# Line 579  static __forceinline void _rcntSetGate( Line 586  static __forceinline void _rcntSetGate(
586  }  }
587    
588  // mode - 0 means hblank source, 8 means vblank source.  // mode - 0 means hblank source, 8 means vblank source.
589  __forceinline void rcntStartGate(bool isVblank, u32 sCycle)  static __fi void rcntStartGate(bool isVblank, u32 sCycle)
590  {  {
591          int i;          int i;
592    
# Line 640  __forceinline void rcntStartGate(bool is Line 647  __forceinline void rcntStartGate(bool is
647  }  }
648    
649  // mode - 0 means hblank signal, 8 means vblank signal.  // mode - 0 means hblank signal, 8 means vblank signal.
650  __forceinline void rcntEndGate(bool isVblank , u32 sCycle)  static __fi void rcntEndGate(bool isVblank , u32 sCycle)
651  {  {
652          int i;          int i;
653    
# Line 681  __forceinline void rcntEndGate(bool isVb Line 688  __forceinline void rcntEndGate(bool isVb
688          // rcntUpdate, since we're being called from there anyway.          // rcntUpdate, since we're being called from there anyway.
689  }  }
690    
691  __forceinline void rcntWmode(int index, u32 value)  static __fi u32 rcntCycle(int index)
692    {
693            if (counters[index].mode.IsCounting && (counters[index].mode.ClockSource != 0x3))
694                    return counters[index].count + ((cpuRegs.cycle - counters[index].sCycleT) / counters[index].rate);
695            else
696                    return counters[index].count;
697    }
698    
699    static __fi void rcntWmode(int index, u32 value)
700  {  {
701          if(counters[index].mode.IsCounting) {          if(counters[index].mode.IsCounting) {
702                  if(counters[index].mode.ClockSource != 0x3) {                  if(counters[index].mode.ClockSource != 0x3) {
# Line 715  __forceinline void rcntWmode(int index, Line 730  __forceinline void rcntWmode(int index,
730          _rcntSet( index );          _rcntSet( index );
731  }  }
732    
733  __forceinline void rcntWcount(int index, u32 value)  static __fi void rcntWcount(int index, u32 value)
734  {  {
735          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 );
736    
# Line 741  __forceinline void rcntWcount(int index, Line 756  __forceinline void rcntWcount(int index,
756          _rcntSet( index );          _rcntSet( index );
757  }  }
758    
759  __forceinline void rcntWtarget(int index, u32 value)  static __fi void rcntWtarget(int index, u32 value)
760  {  {
761          EECNT_LOG("EE Counter[%d] writeTarget = %x", index, value);          EECNT_LOG("EE Counter[%d] writeTarget = %x", index, value);
762    
# Line 770  __forceinline void rcntWtarget(int index Line 785  __forceinline void rcntWtarget(int index
785          _rcntSet( index );          _rcntSet( index );
786  }  }
787    
788  __forceinline void rcntWhold(int index, u32 value)  static __fi void rcntWhold(int index, u32 value)
789  {  {
790          EECNT_LOG("EE Counter[%d] Hold Write = %x", index, value);          EECNT_LOG("EE Counter[%d] Hold Write = %x", index, value);
791          counters[index].hold = value;          counters[index].hold = value;
792  }  }
793    
794  __forceinline u32 rcntRcount(int index)  __fi u32 rcntRcount(int index)
795  {  {
796          u32 ret;          u32 ret;
797    
# Line 791  __forceinline u32 rcntRcount(int index) Line 806  __forceinline u32 rcntRcount(int index)
806          return ret;          return ret;
807  }  }
808    
809  __forceinline u32 rcntCycle(int index)  template< uint page >
810    __fi u16 rcntRead32( u32 mem )
811  {  {
812          if (counters[index].mode.IsCounting && (counters[index].mode.ClockSource != 0x3))          // Important DevNote:
813                  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
814          else          // are all fixed to 0, so we always truncate everything in these two pages using a u16
815                  return counters[index].count;          // return value! --air
816    
817            iswitch( mem ) {
818            icase(RCNT0_COUNT)      return (u16)rcntRcount(0);
819            icase(RCNT0_MODE)       return (u16)counters[0].modeval;
820            icase(RCNT0_TARGET)     return (u16)counters[0].target;
821            icase(RCNT0_HOLD)       return (u16)counters[0].hold;
822    
823            icase(RCNT1_COUNT)      return (u16)rcntRcount(1);
824            icase(RCNT1_MODE)       return (u16)counters[1].modeval;
825            icase(RCNT1_TARGET)     return (u16)counters[1].target;
826            icase(RCNT1_HOLD)       return (u16)counters[1].hold;
827    
828            icase(RCNT2_COUNT)      return (u16)rcntRcount(2);
829            icase(RCNT2_MODE)       return (u16)counters[2].modeval;
830            icase(RCNT2_TARGET)     return (u16)counters[2].target;
831    
832            icase(RCNT3_COUNT)      return (u16)rcntRcount(3);
833            icase(RCNT3_MODE)       return (u16)counters[3].modeval;
834            icase(RCNT3_TARGET)     return (u16)counters[3].target;
835            }
836            
837            return psHu16(mem);
838  }  }
839    
840    template< uint page >
841    __fi bool rcntWrite32( u32 mem, mem32_t& value )
842    {
843            pxAssume( mem >= RCNT0_COUNT && mem < 0x10002000 );
844    
845            // [TODO] : counters should actually just use the EE's hw register space for storing
846            // count, mode, target, and hold. This will allow for a simplified handler for register
847            // reads.
848    
849            iswitch( mem ) {
850            icase(RCNT0_COUNT)      return rcntWcount(0, value),    false;
851            icase(RCNT0_MODE)       return rcntWmode(0, value),             false;
852            icase(RCNT0_TARGET)     return rcntWtarget(0, value),   false;
853            icase(RCNT0_HOLD)       return rcntWhold(0, value),             false;
854    
855            icase(RCNT1_COUNT)      return rcntWcount(1, value),    false;
856            icase(RCNT1_MODE)       return rcntWmode(1, value),             false;
857            icase(RCNT1_TARGET)     return rcntWtarget(1, value),   false;
858            icase(RCNT1_HOLD)       return rcntWhold(1, value),             false;
859    
860            icase(RCNT2_COUNT)      return rcntWcount(2, value),    false;
861            icase(RCNT2_MODE)       return rcntWmode(2, value),             false;
862            icase(RCNT2_TARGET)     return rcntWtarget(2, value),   false;
863    
864            icase(RCNT3_COUNT)      return rcntWcount(3, value),    false;
865            icase(RCNT3_MODE)       return rcntWmode(3, value),             false;
866            icase(RCNT3_TARGET)     return rcntWtarget(3, value),   false;
867            }
868    
869            // unhandled .. do memory writeback.
870            return true;
871    }
872    
873    template u16 rcntRead32<0x00>( u32 mem );
874    template u16 rcntRead32<0x01>( u32 mem );
875    
876    template bool rcntWrite32<0x00>( u32 mem, mem32_t& value );
877    template bool rcntWrite32<0x01>( u32 mem, mem32_t& value );
878    
879  void SaveStateBase::rcntFreeze()  void SaveStateBase::rcntFreeze()
880  {  {
881          Freeze( counters );          Freeze( counters );
# Line 809  void SaveStateBase::rcntFreeze() Line 886  void SaveStateBase::rcntFreeze()
886    
887          if( IsLoading() )          if( IsLoading() )
888          {          {
                 UpdateVSyncRate();  
   
889                  // make sure the gate flags are set based on the counter modes...                  // make sure the gate flags are set based on the counter modes...
890                  for( int i=0; i<4; i++ )                  for( int i=0; i<4; i++ )
891                          _rcntSetGate( i );                          _rcntSetGate( i );
892    
893                  iopBranchAction = 1;    // probably not needed but won't hurt anything either.                  iopEventAction = 1;     // probably not needed but won't hurt anything either.
894          }          }
895  }  }

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

  ViewVC Help
Powered by ViewVC 1.1.22