pcsx2/pcsx2/GSState.cpp

270 lines
5.9 KiB
C++

/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2010 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
#include <list>
#include <memory>
#include "GS.h"
#ifdef PCSX2_DEVBUILD
// GS Playback
int g_SaveGSStream = 0; // save GS stream; 1 - prepare, 2 - save
int g_nLeftGSFrames = 0; // when saving, number of frames left
static std::unique_ptr<memSavingState> g_fGSSave;
// fixme - need to take this concept and make it MTGS friendly.
#ifdef _STGS_GSSTATE_CODE
void GSGIFTRANSFER1(u32 *pMem, u32 addr) {
if( g_SaveGSStream == 2) {
u32 type = GSRUN_TRANS1;
u32 size = (0x4000-(addr))/16;
g_fGSSave->Freeze( type );
g_fGSSave->Freeze( size );
g_fGSSave->FreezeMem( ((u8*)pMem)+(addr), size*16 );
}
GSgifTransfer1(pMem, addr);
}
void GSGIFTRANSFER2(u32 *pMem, u32 size) {
if( g_SaveGSStream == 2) {
u32 type = GSRUN_TRANS2;
u32 _size = size;
g_fGSSave->Freeze( type );
g_fGSSave->Freeze( size );
g_fGSSave->FreezeMem( pMem, _size*16 );
}
GSgifTransfer2(pMem, size);
}
void GSGIFTRANSFER3(u32 *pMem, u32 size) {
if( g_SaveGSStream == 2 ) {
u32 type = GSRUN_TRANS3;
u32 _size = size;
g_fGSSave->Freeze( type );
g_fGSSave->Freeze( size );
g_fGSSave->FreezeMem( pMem, _size*16 );
}
GSgifTransfer3(pMem, size);
}
__fi void GSVSYNC(void) {
if( g_SaveGSStream == 2 ) {
u32 type = GSRUN_VSYNC;
g_fGSSave->Freeze( type );
}
}
#endif
/*void SaveGSState(const wxString& file)
{
if( g_SaveGSStream ) return;
Console.WriteLn( "Saving GS State..." );
Console.WriteLn( L"\t%s", file.c_str() );
SafeArray<u8> buf;
g_fGSSave = std::unique_ptr<memSavingState>(new memSavingState( buf ));
g_SaveGSStream = 1;
g_nLeftGSFrames = 2;
g_fGSSave->Freeze( g_nLeftGSFrames );
}
void LoadGSState(const wxString& file)
{
int ret;
Console.WriteLn( "Loading GS State..." );
wxString src( file );
//if( !wxFileName::FileExists( src ) )
// src = Path::Combine( g_Conf->Folders.Savestates, src );
if( !wxFileName::FileExists( src ) )
return;
SafeArray<u8> buf;
memLoadingState f( buf );
// Always set gsIrq callback -- GS States are always exclusionary of MTGS mode
GSirqCallback( gsIrq );
ret = GSopen(&pDsp, "PCSX2", 0);
if (ret != 0)
throw Exception::PluginOpenError( PluginId_GS );
ret = PADopen((void *)&pDsp);
f.Freeze(g_nLeftGSFrames);
f.gsFreeze();
GetPluginManager().Freeze( PluginId_GS, f );
RunGSState( f );
GetCorePlugins().Close( PluginId_GS );
GetCorePlugins().Close( PluginId_PAD );
}
struct GSStatePacket
{
u32 type;
std::vector<u8> mem;
};
// runs the GS
// (this should really be part of the AppGui)
void RunGSState( memLoadingState& f )
{
u32 newfield;
std::list< GSStatePacket > packets;
while( !f.IsFinished() )
{
int type, size;
f.Freeze( type );
if( type != GSRUN_VSYNC ) f.Freeze( size );
packets.push_back(GSStatePacket());
GSStatePacket& p = packets.back();
p.type = type;
if( type != GSRUN_VSYNC ) {
p.mem.resize(size*16);
f.FreezeMem( &p.mem[0], size*16 );
}
}
std::list<GSStatePacket>::iterator it = packets.begin();
g_SaveGSStream = 3;
// first extract the data
while(1) {
switch(it->type) {
case GSRUN_TRANS1:
GSgifTransfer1((u32*)&it->mem[0], 0);
break;
case GSRUN_TRANS2:
GSgifTransfer2((u32*)&it->mem[0], it->mem.size()/16);
break;
case GSRUN_TRANS3:
GSgifTransfer3((u32*)&it->mem[0], it->mem.size()/16);
break;
case GSRUN_VSYNC:
// flip
newfield = (*(u32*)(PS2MEM_GS+0x1000)&0x2000) ? 0 : 0x2000;
*(u32*)(PS2MEM_GS+0x1000) = (*(u32*)(PS2MEM_GS+0x1000) & ~(1<<13)) | newfield;
GSvsync(newfield);
// fixme : Process pending app messages here.
//SysUpdate();
if( g_SaveGSStream != 3 )
return;
break;
jNO_DEFAULT
}
++it;
if( it == packets.end() )
it = packets.begin();
}
}*/
#endif
//////////////////////////////////////////////////////////////////////////////////////////
//
void vSyncDebugStuff( uint frame )
{
#ifdef OLD_TESTBUILD_STUFF
if( g_TestRun.enabled && g_TestRun.frame > 0 ) {
if( frame > g_TestRun.frame ) {
// take a snapshot
if( g_TestRun.pimagename != NULL && GSmakeSnapshot2 != NULL ) {
if( g_TestRun.snapdone ) {
g_TestRun.curimage++;
g_TestRun.snapdone = 0;
g_TestRun.frame += 20;
if( g_TestRun.curimage >= g_TestRun.numimages ) {
// exit
g_EmuThread->Cancel();
}
}
else {
// query for the image
GSmakeSnapshot2(g_TestRun.pimagename, &g_TestRun.snapdone, g_TestRun.jpgcapture);
}
}
else {
// exit
g_EmuThread->Cancel();
}
}
}
GSVSYNC();
if( g_SaveGSStream == 1 ) {
freezeData fP;
g_SaveGSStream = 2;
g_fGSSave->gsFreeze();
if (GSfreeze(FREEZE_SIZE, &fP) == -1) {
safe_delete( g_fGSSave );
g_SaveGSStream = 0;
}
else {
fP.data = (s8*)malloc(fP.size);
if (fP.data == NULL) {
safe_delete( g_fGSSave );
g_SaveGSStream = 0;
}
else {
if (GSfreeze(FREEZE_SAVE, &fP) == -1) {
safe_delete( g_fGSSave );
g_SaveGSStream = 0;
}
else {
g_fGSSave->Freeze( fP.size );
if (fP.size) {
g_fGSSave->FreezeMem( fP.data, fP.size );
free(fP.data);
}
}
}
}
}
else if( g_SaveGSStream == 2 ) {
if( --g_nLeftGSFrames <= 0 ) {
safe_delete( g_fGSSave );
g_SaveGSStream = 0;
Console.WriteLn("Done saving GS stream");
}
}
#endif
}