diff --git a/pcsx2/GS.cpp b/pcsx2/GS.cpp index 1b02c041ec..50b977469b 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 13406868e6..d5eb2a542d 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 adb50929b4..5193e82c99 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 0e3677537d..e2d5f85b1a 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 de3e9a0af3..b8f8b061dd 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 61e3e6c9ee..66277ac179 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 22b32ff651..079f1bd581 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 6cf76922d8..cfb888291b 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 3cb717913e..9b2a242d83 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