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
This commit is contained in:
Jake.Stine 2009-02-20 04:36:55 +00:00
parent f412c38547
commit e56eac1862
9 changed files with 87 additions and 44 deletions

View File

@ -195,10 +195,6 @@ s32 gsOpen()
{ {
if( m_gsOpened ) return 0; if( m_gsOpened ) return 0;
// mtgs overrides these as necessary...
GSsetBaseMem( PS2MEM_GS );
GSirqCallback( gsIrq );
//video //video
// Only bind the gsIrq if we're not running the MTGS. // Only bind the gsIrq if we're not running the MTGS.
// The MTGS simulates its own gsIrq in order to maintain proper sync. // 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! // 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) // ... 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); m_gsOpened = !GSopen((void *)&pDsp, "PCSX2", 0);
} }
@ -769,14 +768,7 @@ void gsPostVsyncEnd( bool updategs )
*(u32*)(PS2MEM_GS+0x1000) ^= 0x2000; // swap the vsync field *(u32*)(PS2MEM_GS+0x1000) ^= 0x2000; // swap the vsync field
if( mtgsThread != NULL ) if( mtgsThread != NULL )
{ mtgsThread->PostVsyncEnd( updategs );
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();
}
else else
{ {
GSvsync((*(u32*)(PS2MEM_GS+0x1000)&0x2000)); GSvsync((*(u32*)(PS2MEM_GS+0x1000)&0x2000));

View File

@ -171,6 +171,15 @@ protected:
int m_CopyDataTally; int m_CopyDataTally;
volatile u32 m_RingBufferIsBusy; 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. // These vars maintain instance data for sending Data Packets.
// Only one data packet can be constructed and uploaded at a time. // Only one data packet can be constructed and uploaded at a time.
@ -188,7 +197,7 @@ protected:
SafeAlignedArray<u128,16> m_RingBuffer; SafeAlignedArray<u128,16> m_RingBuffer;
// mtgs needs its own memory space separate from the PS2. The PS2 memory is in // 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; u8* const m_gsMem;
public: public:
@ -216,6 +225,8 @@ public:
void Freeze( SaveState& state ); void Freeze( SaveState& state );
void SetEvent(); void SetEvent();
void PostVsyncEnd( bool updategs );
uptr FnPtr_SimplePacket() const uptr FnPtr_SimplePacket() const
{ {
#ifndef __LINUX__ #ifndef __LINUX__

View File

@ -62,6 +62,10 @@ using namespace std; // for min / max
#define IPU_DMA_FIREINT1 64 #define IPU_DMA_FIREINT1 64
#define IPU_DMA_VIFSTALL 128 #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; static int g_nDMATransfer = 0;
int g_nIPU0Data = 0; // data left to transfer int g_nIPU0Data = 0; // data left to transfer
u8* g_pIPU0Pointer = NULL; u8* g_pIPU0Pointer = NULL;
@ -165,7 +169,12 @@ void ipuShutdown()
void SaveState::ipuFreeze() { void SaveState::ipuFreeze() {
IPUProcessInterrupt(); 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(g_nDMATransfer);
Freeze(FIreadpos); Freeze(FIreadpos);
Freeze(FIwritepos); 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 transsize;
int firsttrans; int firsttrans;

View File

@ -256,7 +256,7 @@ extern u8 __fastcall getBits8(u8 *address, u32 advance);
extern int __fastcall getBits(u8 *address, u32 size, u32 advance); extern int __fastcall getBits(u8 *address, u32 size, u32 advance);
// returns number of qw read // 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); void FIFOfrom_read(void *value,int size);
int FIFOto_read(void *value); int FIFOto_read(void *value);
int FIFOto_write(u32* pMem, int size); int FIFOto_write(u32* pMem, int size);

View File

@ -198,6 +198,8 @@ mtgsThreadObject::mtgsThreadObject() :
, m_CopyCommandTally( 0 ) , m_CopyCommandTally( 0 )
, m_CopyDataTally( 0 ) , m_CopyDataTally( 0 )
, m_RingBufferIsBusy( 0 ) , m_RingBufferIsBusy( 0 )
, m_QueuedFrames( 0 )
, m_lock_FrameQueueCounter()
, m_packet_size( 0 ) , m_packet_size( 0 )
, m_packet_ringpos( 0 ) , m_packet_ringpos( 0 )
@ -436,6 +438,26 @@ __forceinline u32 mtgsThreadObject::_gifTransferDummy( GIF_PATH pathidx, const u
return size; 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 struct PacketTagType
{ {
u32 command; u32 command;
@ -448,6 +470,7 @@ int mtgsThreadObject::Callback()
memcpy_aligned( m_gsMem, PS2MEM_GS, sizeof(m_gsMem) ); memcpy_aligned( m_gsMem, PS2MEM_GS, sizeof(m_gsMem) );
GSsetBaseMem( m_gsMem ); GSsetBaseMem( m_gsMem );
GSirqCallback( NULL );
m_returncode = GSopen((void *)&pDsp, "PCSX2", 1); m_returncode = GSopen((void *)&pDsp, "PCSX2", 1);
@ -534,9 +557,13 @@ int mtgsThreadObject::Callback()
case GS_RINGTYPE_VSYNC: case GS_RINGTYPE_VSYNC:
{ {
GSvsync(tag.data[0]); GSvsync(tag.data[0]);
gsFrameSkip( !tag.data[1] ); gsFrameSkip( !tag.data[1] );
m_lock_FrameQueueCounter.Lock();
m_QueuedFrames--;
jASSUME( m_QueuedFrames >= 0 );
m_lock_FrameQueueCounter.Unlock();
if( PAD1update != NULL ) PAD1update(0); if( PAD1update != NULL ) PAD1update(0);
if( PAD2update != NULL ) PAD2update(1); if( PAD2update != NULL ) PAD2update(1);
} }

View File

@ -1338,15 +1338,21 @@ void vif0Reset() {
void SaveState::vif0Freeze() void SaveState::vif0Freeze()
{ {
// Dunno if this one is needed, but whatever, it's small. :) // Dunno if this one is needed, but whatever, it's small. :)
Freeze( g_vifCycles ); if( GetVersion() >= 0x14 )
Freeze( g_vifCycles );
Freeze( vif0 ); Freeze( vif0 );
if( GetVersion() >= 0x14 ) if( GetVersion() >= 0x14 )
{ {
Freeze( g_vif1HasMask3 ); Freeze( g_vif0HasMask3 );
Freeze( g_vif1Masks ); Freeze( g_vif0Masks );
Freeze( g_vifRow1 ); Freeze( g_vifRow0 );
Freeze( g_vifCol1 ); 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_vifRow1 );
Freeze( g_vifCol1 ); Freeze( g_vifCol1 );
} }
else if( IsLoading() )
/*if( IsLoading() ){ {
SetNewMask(g_vif1Masks, g_vif1HasMask3, vif1Regs->mask, ~vif1Regs->mask); SetNewMask(g_vif1Masks, g_vif1HasMask3, vif1Regs->mask, ~vif1Regs->mask);
if(vif1ch->chcr & 0x100)vif1.done = 0; //if(vif1ch->chcr & 0x100) vif1.done = 0;
}*/ }
} }

View File

@ -32,12 +32,12 @@ LRESULT WINAPI AboutDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
switch(uMsg) switch(uMsg)
{ {
case WM_INITDIALOG: case WM_INITDIALOG:
hBMP = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(SPLASH_LOGO)); //hBMP = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(SPLASH_LOGO));
hSilverBMP = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_PS2SILVER)); 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); 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")); SetWindowText(hDlg, _("About PCSX2"));

View File

@ -1071,15 +1071,11 @@ void CreateMainWindow(int nCmdShow) {
RegisterClass(&wc); RegisterClass(&wc);
GetObject(hbitmap_background, sizeof(bm), &bm); GetObject(hbitmap_background, sizeof(bm), &bm);
{
const char* pvm = "VTLB";
#ifdef PCSX2_DEVBUILD #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 #else
sprintf(buf, _("PCSX2 %s - %s"), PCSX2_VERSION, pvm); sprintf(buf, _("PCSX2 %s"), PCSX2_VERSION);
#endif #endif
}
hWnd = CreateWindow( hWnd = CreateWindow(
"PCSX2 Main", "PCSX2 Main",

View File

@ -8,6 +8,7 @@
// Generated from the TEXTINCLUDE 2 resource. // Generated from the TEXTINCLUDE 2 resource.
// //
#include "afxresmw.h" #include "afxresmw.h"
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS #undef APSTUDIO_READONLY_SYMBOLS
@ -1074,18 +1075,19 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
// Dialog // Dialog
// //
ABOUT_DIALOG DIALOGEX 0, 0, 431, 302 ABOUT_DIALOG DIALOGEX 0, 0, 431, 294
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_ACCEPTFILES EXSTYLE WS_EX_ACCEPTFILES
CAPTION "About PCSX2" CAPTION "About PCSX2"
FONT 8, "Microsoft Sans Serif", 400, 0, 0x0 FONT 8, "MS Shell Dlg", 400, 0, 0x0
BEGIN 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 "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 CTEXT "Greets to...",IDC_PCSX_ABOUT_GREETS,94,178,319,77
GROUPBOX "",IDC_STATIC,5,3,145,138 GROUPBOX "",IDC_STATIC,5,3,145,141
GROUPBOX "",IDC_STATIC,77,173,333,91 GROUPBOX "",IDC_STATIC,87,169,333,91
CONTROL 132,IDC_PS2SILVER_RECT,"Static",SS_BITMAP,2,183,70,74 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 END
IDD_HACKS DIALOGEX 0, 0, 335, 263 IDD_HACKS DIALOGEX 0, 0, 335, 263
@ -1129,7 +1131,7 @@ BEGIN
ABOUT_DIALOG, DIALOG ABOUT_DIALOG, DIALOG
BEGIN BEGIN
RIGHTMARGIN, 429 RIGHTMARGIN, 429
BOTTOMMARGIN, 296 BOTTOMMARGIN, 288
END END
IDD_HACKS, DIALOG IDD_HACKS, DIALOG