From e56eac186225c733055d0f33242d816764527b1f Mon Sep 17 00:00:00 2001 From: "Jake.Stine" Date: Fri, 20 Feb 2009 04:36:55 +0000 Subject: [PATCH] Fixed two bugs in the savestates. Older savestate versions will work now, as they should. Added a queued frame counter to the MTGS to help keep keyboard input in sync with video output, which is needed now thanks to the INTC speedhack making the menus of some games run really really fast. ;) Spiffed up the about box a wee bit. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@546 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/GS.cpp | 16 ++++------------ pcsx2/GS.h | 13 ++++++++++++- pcsx2/IPU/IPU.cpp | 13 +++++++++++-- pcsx2/IPU/IPU.h | 2 +- pcsx2/MTGS.cpp | 29 ++++++++++++++++++++++++++++- pcsx2/VifDma.cpp | 24 +++++++++++++++--------- pcsx2/windows/AboutDlg.cpp | 6 +++--- pcsx2/windows/WinMain.cpp | 8 ++------ pcsx2/windows/pcsx2.rc | 20 +++++++++++--------- 9 files changed, 87 insertions(+), 44 deletions(-) diff --git a/pcsx2/GS.cpp b/pcsx2/GS.cpp index 1b02c041e..50b977469 100644 --- a/pcsx2/GS.cpp +++ b/pcsx2/GS.cpp @@ -195,10 +195,6 @@ s32 gsOpen() { if( m_gsOpened ) return 0; - // mtgs overrides these as necessary... - GSsetBaseMem( PS2MEM_GS ); - GSirqCallback( gsIrq ); - //video // Only bind the gsIrq if we're not running the MTGS. // The MTGS simulates its own gsIrq in order to maintain proper sync. @@ -209,6 +205,9 @@ s32 gsOpen() // MTGS failed to init or is disabled. Try the GS instead! // ... and set the memptr again just in case (for switching between GS/MTGS on the fly) + GSsetBaseMem( PS2MEM_GS ); + GSirqCallback( gsIrq ); + m_gsOpened = !GSopen((void *)&pDsp, "PCSX2", 0); } @@ -769,14 +768,7 @@ void gsPostVsyncEnd( bool updategs ) *(u32*)(PS2MEM_GS+0x1000) ^= 0x2000; // swap the vsync field if( mtgsThread != NULL ) - { - mtgsThread->SendSimplePacket( GS_RINGTYPE_VSYNC, - (*(u32*)(PS2MEM_GS+0x1000)&0x2000), updategs, 0); - - // No need to freeze MMX/XMM registers here since this - // code is always called from the context of a BranchTest. - mtgsThread->SetEvent(); - } + mtgsThread->PostVsyncEnd( updategs ); else { GSvsync((*(u32*)(PS2MEM_GS+0x1000)&0x2000)); diff --git a/pcsx2/GS.h b/pcsx2/GS.h index 13406868e..d5eb2a542 100644 --- a/pcsx2/GS.h +++ b/pcsx2/GS.h @@ -171,6 +171,15 @@ protected: int m_CopyDataTally; volatile u32 m_RingBufferIsBusy; + // Counts the number of vsync frames queued in the MTGS ringbuffer. This is used to + // throttle the number of frames allowed to be rendered ahead of time for games that + // run very fast and have little or no ringbuffer overhead (typically opening menus) + volatile u32 m_QueuedFrames; + + // Protection lock for the frame queue counter -- needed because we can't safely + // AtomicExchange from two threads. + Threading::MutexLock m_lock_FrameQueueCounter; + // These vars maintain instance data for sending Data Packets. // Only one data packet can be constructed and uploaded at a time. @@ -188,7 +197,7 @@ protected: SafeAlignedArray m_RingBuffer; // mtgs needs its own memory space separate from the PS2. The PS2 memory is in - // synch with the EE while this stays in sync with the GS (ie, it lags behind) + // sync with the EE while this stays in sync with the GS (ie, it lags behind) u8* const m_gsMem; public: @@ -216,6 +225,8 @@ public: void Freeze( SaveState& state ); void SetEvent(); + void PostVsyncEnd( bool updategs ); + uptr FnPtr_SimplePacket() const { #ifndef __LINUX__ diff --git a/pcsx2/IPU/IPU.cpp b/pcsx2/IPU/IPU.cpp index adb50929b..5193e82c9 100644 --- a/pcsx2/IPU/IPU.cpp +++ b/pcsx2/IPU/IPU.cpp @@ -62,6 +62,10 @@ using namespace std; // for min / max #define IPU_DMA_FIREINT1 64 #define IPU_DMA_VIFSTALL 128 +// FIXME - g_nIPU0Data and Pointer are not saved in the savestate, which breaks savestates for some +// FMVs at random (if they get saved during the half frame of a 30fps rate). The fix is complicated +// since coroutine is such a pita. (air) + static int g_nDMATransfer = 0; int g_nIPU0Data = 0; // data left to transfer u8* g_pIPU0Pointer = NULL; @@ -165,7 +169,12 @@ void ipuShutdown() void SaveState::ipuFreeze() { IPUProcessInterrupt(); - FreezeMem(ipuRegs, sizeof(IPUregisters)); + if( GetVersion() < 0x14 ) + { + // old versions saved the IPU regs, but they're already saved as part of HW! + FreezeMem(ipuRegs, sizeof(IPUregisters)); + } + Freeze(g_nDMATransfer); Freeze(FIreadpos); Freeze(FIwritepos); @@ -1574,7 +1583,7 @@ int IPU1dma() } -int FIFOfrom_write(u32 *value,int size) +int FIFOfrom_write(const u32 *value,int size) { int transsize; int firsttrans; diff --git a/pcsx2/IPU/IPU.h b/pcsx2/IPU/IPU.h index 0e3677537..e2d5f85b1 100644 --- a/pcsx2/IPU/IPU.h +++ b/pcsx2/IPU/IPU.h @@ -256,7 +256,7 @@ extern u8 __fastcall getBits8(u8 *address, u32 advance); extern int __fastcall getBits(u8 *address, u32 size, u32 advance); // returns number of qw read -int FIFOfrom_write(u32 * value, int size); +int FIFOfrom_write(const u32 * value, int size); void FIFOfrom_read(void *value,int size); int FIFOto_read(void *value); int FIFOto_write(u32* pMem, int size); diff --git a/pcsx2/MTGS.cpp b/pcsx2/MTGS.cpp index de3e9a0af..b8f8b061d 100644 --- a/pcsx2/MTGS.cpp +++ b/pcsx2/MTGS.cpp @@ -198,6 +198,8 @@ mtgsThreadObject::mtgsThreadObject() : , m_CopyCommandTally( 0 ) , m_CopyDataTally( 0 ) , m_RingBufferIsBusy( 0 ) +, m_QueuedFrames( 0 ) +, m_lock_FrameQueueCounter() , m_packet_size( 0 ) , m_packet_ringpos( 0 ) @@ -436,6 +438,26 @@ __forceinline u32 mtgsThreadObject::_gifTransferDummy( GIF_PATH pathidx, const u return size; } +void mtgsThreadObject::PostVsyncEnd( bool updategs ) +{ + while( m_QueuedFrames > 8 ) + { + Sleep( 2 ); // Sleep off quite a bit of time, since we're obviously *waaay* ahead. + SpinWait(); + } + + m_lock_FrameQueueCounter.Lock(); + m_QueuedFrames++; + m_lock_FrameQueueCounter.Unlock(); + + SendSimplePacket( GS_RINGTYPE_VSYNC, + (*(u32*)(PS2MEM_GS+0x1000)&0x2000), updategs, 0); + + // No need to freeze MMX/XMM registers here since this + // code is always called from the context of a BranchTest. + SetEvent(); +} + struct PacketTagType { u32 command; @@ -448,6 +470,7 @@ int mtgsThreadObject::Callback() memcpy_aligned( m_gsMem, PS2MEM_GS, sizeof(m_gsMem) ); GSsetBaseMem( m_gsMem ); + GSirqCallback( NULL ); m_returncode = GSopen((void *)&pDsp, "PCSX2", 1); @@ -534,9 +557,13 @@ int mtgsThreadObject::Callback() case GS_RINGTYPE_VSYNC: { GSvsync(tag.data[0]); - gsFrameSkip( !tag.data[1] ); + m_lock_FrameQueueCounter.Lock(); + m_QueuedFrames--; + jASSUME( m_QueuedFrames >= 0 ); + m_lock_FrameQueueCounter.Unlock(); + if( PAD1update != NULL ) PAD1update(0); if( PAD2update != NULL ) PAD2update(1); } diff --git a/pcsx2/VifDma.cpp b/pcsx2/VifDma.cpp index 61e3e6c9e..66277ac17 100644 --- a/pcsx2/VifDma.cpp +++ b/pcsx2/VifDma.cpp @@ -1338,15 +1338,21 @@ void vif0Reset() { void SaveState::vif0Freeze() { // Dunno if this one is needed, but whatever, it's small. :) - Freeze( g_vifCycles ); + if( GetVersion() >= 0x14 ) + Freeze( g_vifCycles ); Freeze( vif0 ); if( GetVersion() >= 0x14 ) { - Freeze( g_vif1HasMask3 ); - Freeze( g_vif1Masks ); - Freeze( g_vifRow1 ); - Freeze( g_vifCol1 ); + Freeze( g_vif0HasMask3 ); + Freeze( g_vif0Masks ); + Freeze( g_vifRow0 ); + Freeze( g_vifCol0 ); + } + else if( IsLoading() ) + { + // Hack to "help" old savestates recover... + SetNewMask(g_vif0Masks, g_vif0HasMask3, vif0Regs->mask, ~vif0Regs->mask); } } @@ -2264,9 +2270,9 @@ void SaveState::vif1Freeze() Freeze( g_vifRow1 ); Freeze( g_vifCol1 ); } - - /*if( IsLoading() ){ + else if( IsLoading() ) + { SetNewMask(g_vif1Masks, g_vif1HasMask3, vif1Regs->mask, ~vif1Regs->mask); - if(vif1ch->chcr & 0x100)vif1.done = 0; - }*/ + //if(vif1ch->chcr & 0x100) vif1.done = 0; + } } diff --git a/pcsx2/windows/AboutDlg.cpp b/pcsx2/windows/AboutDlg.cpp index 22b32ff65..079f1bd58 100644 --- a/pcsx2/windows/AboutDlg.cpp +++ b/pcsx2/windows/AboutDlg.cpp @@ -32,12 +32,12 @@ LRESULT WINAPI AboutDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) switch(uMsg) { case WM_INITDIALOG: - hBMP = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(SPLASH_LOGO)); + //hBMP = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(SPLASH_LOGO)); hSilverBMP = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_PS2SILVER)); - hW = CreateWindow("STATIC", "", WS_VISIBLE | WS_CHILD | SS_BITMAP, + /*hW = CreateWindow("STATIC", "", WS_VISIBLE | WS_CHILD | SS_BITMAP, 230, 10, 211, 110, hDlg, (HMENU)IDC_STATIC, GetModuleHandle(NULL), NULL); - SendMessage(hW, STM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)hBMP); + SendMessage(hW, STM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)hBMP);*/ SetWindowText(hDlg, _("About PCSX2")); diff --git a/pcsx2/windows/WinMain.cpp b/pcsx2/windows/WinMain.cpp index 6cf76922d..cfb888291 100644 --- a/pcsx2/windows/WinMain.cpp +++ b/pcsx2/windows/WinMain.cpp @@ -1071,15 +1071,11 @@ void CreateMainWindow(int nCmdShow) { RegisterClass(&wc); GetObject(hbitmap_background, sizeof(bm), &bm); - { - const char* pvm = "VTLB"; - #ifdef PCSX2_DEVBUILD - sprintf(buf, _("PCSX2 %s - %s Compile Date - %s %s"), PCSX2_VERSION, pvm, COMPILEDATE, COMPILER); + sprintf(buf, _("PCSX2 %s - Compile Date - %s %s"), PCSX2_VERSION, COMPILEDATE, COMPILER); #else - sprintf(buf, _("PCSX2 %s - %s"), PCSX2_VERSION, pvm); + sprintf(buf, _("PCSX2 %s"), PCSX2_VERSION); #endif - } hWnd = CreateWindow( "PCSX2 Main", diff --git a/pcsx2/windows/pcsx2.rc b/pcsx2/windows/pcsx2.rc index 3cb717913..9b2a242d8 100644 --- a/pcsx2/windows/pcsx2.rc +++ b/pcsx2/windows/pcsx2.rc @@ -8,6 +8,7 @@ // Generated from the TEXTINCLUDE 2 resource. // #include "afxresmw.h" + ///////////////////////////////////////////////////////////////////////////// #undef APSTUDIO_READONLY_SYMBOLS @@ -1074,18 +1075,19 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK // Dialog // -ABOUT_DIALOG DIALOGEX 0, 0, 431, 302 -STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +ABOUT_DIALOG DIALOGEX 0, 0, 431, 294 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_ACCEPTFILES CAPTION "About PCSX2" -FONT 8, "Microsoft Sans Serif", 400, 0, 0x0 +FONT 8, "MS Shell Dlg", 400, 0, 0x0 BEGIN - DEFPUSHBUTTON "OK",IDOK,205,282,50,14 + DEFPUSHBUTTON "OK",IDOK,205,273,50,14 CTEXT "PCSX2, a PS2 Emulator...",IDC_PCSX_ABOUT_AUTHORS,9,10,135,127,0,WS_EX_TRANSPARENT - CTEXT "Greets to...",IDC_PCSX_ABOUT_GREETS,89,182,311,77 - GROUPBOX "",IDC_STATIC,5,3,145,138 - GROUPBOX "",IDC_STATIC,77,173,333,91 - CONTROL 132,IDC_PS2SILVER_RECT,"Static",SS_BITMAP,2,183,70,74 + CTEXT "Greets to...",IDC_PCSX_ABOUT_GREETS,94,178,319,77 + GROUPBOX "",IDC_STATIC,5,3,145,141 + GROUPBOX "",IDC_STATIC,87,169,333,91 + CONTROL 132,IDC_PS2SILVER_RECT,"Static",SS_BITMAP | SS_SUNKEN,10,179,71,75 + CONTROL 113,IDC_STATIC,"Static",SS_BITMAP,162,7,259,137,WS_EX_CLIENTEDGE END IDD_HACKS DIALOGEX 0, 0, 335, 263 @@ -1129,7 +1131,7 @@ BEGIN ABOUT_DIALOG, DIALOG BEGIN RIGHTMARGIN, 429 - BOTTOMMARGIN, 296 + BOTTOMMARGIN, 288 END IDD_HACKS, DIALOG