mirror of https://github.com/PCSX2/pcsx2.git
Major GUI stability renovations: Pcsx2 now supports an "automagic" to-memory savestate system that allows it to recover on-the-fly from most dialog box changes (speedhacks, advanced roundmodes, and even MTGS). Use Run:Execute to resume your game right where you left off!
Fixed several memory leaks, including one that ate up about 40 megs of ram everytime you hit esc to go to the GUI. Also added quite a bit more error checking to init/deinit procedures. Run:Reset menu now *fully* resets all plugins, including the GS. Added color to the Win32 console! :) TODO: The "Configure" dialog box doesn't support the new recovery system yet, so you can't change plugin versions on the fly yet (coming soon). git-svn-id: http://pcsx2-playground.googlecode.com/svn/trunk@488 a6443dda-0b58-4228-96e9-037be469359c
This commit is contained in:
parent
9a70d486f5
commit
2d95e58bba
21
pcsx2/CDVD.c
21
pcsx2/CDVD.c
|
@ -583,7 +583,6 @@ s32 cdvdGetTrayStatus()
|
|||
}
|
||||
// Note: Is tray status being kept as a var here somewhere?
|
||||
// cdvdNewDiskCB() can update it's status as well...
|
||||
extern int needReset;
|
||||
|
||||
// Modified by (efp) - 16/01/2006
|
||||
s32 cdvdGetDiskType() {
|
||||
|
@ -596,9 +595,11 @@ s32 cdvdGetDiskType() {
|
|||
// or just throw it out. CDVDgetDiskType() sets type to "NODISC" anyway.
|
||||
|
||||
cdvd.Type = CDVDgetDiskType();
|
||||
if (cdvd.Type == CDVD_TYPE_PS2CD && needReset == 1) {
|
||||
if (cdvd.Type == CDVD_TYPE_PS2CD) // && needReset == 1)
|
||||
{
|
||||
char str[g_MaxPath];
|
||||
if (GetPS2ElfName(str) == 1) {
|
||||
if (GetPS2ElfName(str) == 1)
|
||||
{
|
||||
cdvd.Type = CDVD_TYPE_PSCD;
|
||||
} // ENDIF- Does the SYSTEM.CNF file only say "BOOT="? PS1 CD then.
|
||||
} // ENDIF- Is the type listed as a PS2 CD?
|
||||
|
@ -717,16 +718,14 @@ void cdvdReset()
|
|||
|
||||
}
|
||||
|
||||
int cdvdFreeze(gzFile f, int Mode)
|
||||
void SaveState::cdvdFreeze()
|
||||
{
|
||||
gzfreeze(&cdvd, sizeof(cdvd));
|
||||
if (Mode == FREEZE_LOAD) {
|
||||
if (cdvd.Reading) {
|
||||
cdvd.RErr = CDVDreadTrack(cdvd.Sector, cdvd.ReadMode);
|
||||
}
|
||||
}
|
||||
Freeze(cdvd);
|
||||
|
||||
return 0;
|
||||
// Make sure the Cdvd plugin has the expected track loaded into the buffer.
|
||||
|
||||
if( IsLoading() && cdvd.Reading)
|
||||
cdvd.RErr = CDVDreadTrack(cdvd.Sector, cdvd.ReadMode);
|
||||
}
|
||||
|
||||
int cdvdInterrupt() {
|
||||
|
|
|
@ -88,7 +88,6 @@ struct cdvdStruct {
|
|||
void cdvdReset();
|
||||
void cdvdVsync();
|
||||
int cdvdInterrupt();
|
||||
int cdvdFreeze(gzFile f, int Mode);
|
||||
extern void cdvdReadInterrupt();
|
||||
void cdvdNewDiskCB();
|
||||
u8 cdvdRead04(void);
|
||||
|
|
|
@ -75,8 +75,8 @@ void CDVDFS_init(){
|
|||
// CDVDFS_open
|
||||
// called by 80000001 fileio_open for devices: "cdrom:", "cdrom0:"
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
int CDVDFS_open(char *name, int mode){
|
||||
register int j;
|
||||
int CDVDFS_open(const char *name, int mode){
|
||||
int j;
|
||||
static struct TocEntry tocEntry;
|
||||
|
||||
// check if the file exists
|
||||
|
|
|
@ -30,7 +30,7 @@ extern CdRMode cdReadMode;
|
|||
|
||||
/* Filing-system exported functions */
|
||||
void CDVDFS_init();
|
||||
int CDVDFS_open(char *name, int mode);
|
||||
int CDVDFS_open(const char *name, int mode);
|
||||
int CDVDFS_lseek(int fd, int offset, int whence);
|
||||
int CDVDFS_read( int fd, char * buffer, int size );
|
||||
int CDVDFS_write( int fd, char * buffer, int size );
|
||||
|
|
|
@ -226,7 +226,7 @@ void MapTLB(int i)
|
|||
u32 saddr, eaddr;
|
||||
|
||||
#ifndef PCSX2_VIRTUAL_MEM
|
||||
DevCon::FormatLn("MAP TLB %d: %08x-> [%08x %08x] S=%d G=%d ASID=%d Mask= %03X",
|
||||
DevCon::MsgLn("MAP TLB %d: %08x-> [%08x %08x] S=%d G=%d ASID=%d Mask= %03X",
|
||||
i,tlb[i].VPN2,tlb[i].PFN0,tlb[i].PFN1,tlb[i].S,tlb[i].G,tlb[i].ASID,tlb[i].Mask);
|
||||
|
||||
if (tlb[i].S)
|
||||
|
|
|
@ -951,15 +951,15 @@ void cdrReset() {
|
|||
cdReadTime = (PSXCLK / 1757) * BIAS;
|
||||
}
|
||||
|
||||
int cdrFreeze(gzFile f, int Mode) {
|
||||
int tmp;
|
||||
void SaveState::cdrFreeze() {
|
||||
Freeze(cdr);
|
||||
|
||||
gzfreeze(&cdr, sizeof(cdr));
|
||||
// Alrighty! This code ised to, for some reason, recalculate the pTransfer value
|
||||
// even though it's being saved as part of the cdr struct. Probably a backwards
|
||||
// compat fix with an earlier save version.
|
||||
|
||||
if (Mode == 1) tmp = (int)(cdr.pTransfer - cdr.Transfer);
|
||||
gzfreeze(&tmp, 4);
|
||||
if (Mode == 0) cdr.pTransfer = cdr.Transfer + tmp;
|
||||
|
||||
return 0;
|
||||
int tmp; // = (int)(cdr.pTransfer - cdr.Transfer);
|
||||
Freeze(tmp);
|
||||
//if (Mode == 0) cdr.pTransfer = cdr.Transfer + tmp;
|
||||
}
|
||||
|
||||
|
|
|
@ -89,6 +89,5 @@ void cdrWrite0(u8 rt);
|
|||
void cdrWrite1(u8 rt);
|
||||
void cdrWrite2(u8 rt);
|
||||
void cdrWrite3(u8 rt);
|
||||
int cdrFreeze(gzFile f, int Mode);
|
||||
|
||||
#endif /* __CDROM_H__ */
|
||||
|
|
|
@ -89,7 +89,7 @@ struct TESTRUNARGS
|
|||
int numimages;
|
||||
int curimage;
|
||||
u32 autopad; // mask for auto buttons
|
||||
int efile;
|
||||
bool efile;
|
||||
int snapdone;
|
||||
|
||||
const char* ptitle;
|
||||
|
|
|
@ -237,7 +237,7 @@ u32 UpdateVSyncRate()
|
|||
if( m_iTicks != ticks )
|
||||
{
|
||||
m_iTicks = ticks;
|
||||
SysPrintf( limiterMsg, vSyncInfo.Framerate/50, vSyncInfo.Framerate%50 );
|
||||
SysPrintf( limiterMsg, vSyncInfo.Framerate/50, (vSyncInfo.Framerate*2)%100 );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -299,27 +299,27 @@ void vSyncDebugStuff() {
|
|||
freezeData fP;
|
||||
|
||||
g_SaveGSStream = 2;
|
||||
gsFreeze(g_fGSSave, 1);
|
||||
g_fGSSave->gsFreeze();
|
||||
|
||||
if (GSfreeze(FREEZE_SIZE, &fP) == -1) {
|
||||
gzclose(g_fGSSave);
|
||||
safe_delete( g_fGSSave );
|
||||
g_SaveGSStream = 0;
|
||||
}
|
||||
else {
|
||||
fP.data = (s8*)malloc(fP.size);
|
||||
if (fP.data == NULL) {
|
||||
gzclose(g_fGSSave);
|
||||
safe_delete( g_fGSSave );
|
||||
g_SaveGSStream = 0;
|
||||
}
|
||||
else {
|
||||
if (GSfreeze(FREEZE_SAVE, &fP) == -1) {
|
||||
gzclose(g_fGSSave);
|
||||
safe_delete( g_fGSSave );
|
||||
g_SaveGSStream = 0;
|
||||
}
|
||||
else {
|
||||
gzwrite(g_fGSSave, &fP.size, sizeof(fP.size));
|
||||
g_fGSSave->Freeze( fP.size );
|
||||
if (fP.size) {
|
||||
gzwrite(g_fGSSave, fP.data, fP.size);
|
||||
g_fGSSave->FreezeMem( fP.data, fP.size );
|
||||
free(fP.data);
|
||||
}
|
||||
}
|
||||
|
@ -329,10 +329,9 @@ void vSyncDebugStuff() {
|
|||
else if( g_SaveGSStream == 2 ) {
|
||||
|
||||
if( --g_nLeftGSFrames <= 0 ) {
|
||||
gzclose(g_fGSSave);
|
||||
g_fGSSave = NULL;
|
||||
safe_delete( g_fGSSave );
|
||||
g_SaveGSStream = 0;
|
||||
SysPrintf("Done saving GS stream\n");
|
||||
Console::WriteLn("Done saving GS stream");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -767,13 +766,13 @@ u32 rcntCycle(int index) {
|
|||
return counters[index].count;
|
||||
}
|
||||
|
||||
int rcntFreeze(gzFile f, int Mode) {
|
||||
void SaveState::rcntFreeze()
|
||||
{
|
||||
Freeze(counters);
|
||||
Freeze(nextCounter);
|
||||
Freeze(nextsCounter);
|
||||
|
||||
gzfreezel(counters);
|
||||
gzfreeze(&nextCounter, sizeof(nextCounter));
|
||||
gzfreeze(&nextsCounter, sizeof(nextsCounter));
|
||||
|
||||
if( Mode == 0 )
|
||||
if( !IsSaving() )
|
||||
{
|
||||
#ifdef PCSX2_VIRTUAL_MEM
|
||||
// Sanity check for loading older savestates:
|
||||
|
@ -788,10 +787,8 @@ int rcntFreeze(gzFile f, int Mode) {
|
|||
// make sure the gate flags are set based on the counter modes...
|
||||
for( int i=0; i<4; i++ )
|
||||
_rcntSetGate( i );
|
||||
}
|
||||
|
||||
iopBranchAction = 1; // probably not needed but won't hurt anything either.
|
||||
|
||||
return 0;
|
||||
iopBranchAction = 1; // probably not needed but won't hurt anything either.
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -92,7 +92,6 @@ void rcntWtarget(int index, u32 value);
|
|||
void rcntWhold(int index, u32 value);
|
||||
u32 rcntRcount(int index);
|
||||
u32 rcntCycle(int index);
|
||||
int rcntFreeze(gzFile f, int Mode);
|
||||
|
||||
u32 UpdateVSyncRate();
|
||||
|
||||
|
|
|
@ -161,11 +161,11 @@ unsigned int args_ptr; //a big value; in fact, it is an address
|
|||
//+08+4*argc the program name(first param) <--
|
||||
//+08+4*argc+strlen(argv[0]+1) the rest of params; i.e. a copy of 'args'
|
||||
// see above 'char args[256];'
|
||||
unsigned int parseCommandLine( char *filename )
|
||||
static uint parseCommandLine( const char *filename )
|
||||
{
|
||||
if ( ( args_ptr != 0xFFFFFFFF ) && ( args_ptr > 264 ) )
|
||||
{ // 4 + 4 + 256
|
||||
char * p;
|
||||
const char * p;
|
||||
int argc,
|
||||
i;
|
||||
|
||||
|
@ -245,7 +245,7 @@ unsigned int parseCommandLine( char *filename )
|
|||
}
|
||||
//---------------
|
||||
|
||||
int readFile( char *Exepath, char *ptr, u32 offset, int size ) {
|
||||
static int readFile( const char *Exepath, char *ptr, u32 offset, int size ) {
|
||||
FILE *f;
|
||||
int fi;
|
||||
|
||||
|
@ -269,7 +269,7 @@ int readFile( char *Exepath, char *ptr, u32 offset, int size ) {
|
|||
return size;
|
||||
}
|
||||
|
||||
int loadHeaders( char *Exepath ) {
|
||||
static int loadHeaders( const char *Exepath ) {
|
||||
elfHeader = (ELF_HEADER*)elfdata;
|
||||
|
||||
if ( ( elfHeader->e_shentsize != sizeof(ELF_SHR) ) && ( elfHeader->e_shnum > 0 ) ) {
|
||||
|
@ -340,7 +340,7 @@ int loadHeaders( char *Exepath ) {
|
|||
}
|
||||
|
||||
|
||||
BOOL loadProgramHeaders( char *Exepath )
|
||||
static BOOL loadProgramHeaders( const char *Exepath )
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -388,7 +388,7 @@ BOOL loadProgramHeaders( char *Exepath )
|
|||
break;
|
||||
}
|
||||
|
||||
ELF_LOG("\n");
|
||||
ELF_LOG("\n");
|
||||
ELF_LOG("offset: %08x\n",(int)elfProgH[i].p_offset);
|
||||
ELF_LOG("vaddr: %08x\n",(int)elfProgH[i].p_vaddr);
|
||||
ELF_LOG("paddr: %08x\n",elfProgH[i].p_paddr);
|
||||
|
@ -404,7 +404,7 @@ BOOL loadProgramHeaders( char *Exepath )
|
|||
}
|
||||
|
||||
|
||||
BOOL loadSectionHeaders( char * Exepath )
|
||||
static BOOL loadSectionHeaders( const char * Exepath )
|
||||
{
|
||||
int i;
|
||||
int i_st = -1;
|
||||
|
@ -504,12 +504,18 @@ BOOL loadSectionHeaders( char * Exepath )
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
int loadElfFile(char *filename) {
|
||||
int loadElfFile(const char *filename) {
|
||||
char str[256],str2[256];
|
||||
u32 crc;
|
||||
u32 i;
|
||||
|
||||
SysPrintf("loadElfFile: %s\n", filename);
|
||||
if( filename == NULL || filename[0] == 0 )
|
||||
{
|
||||
Console::Notice( "Running the PS2 BIOS...", filename );
|
||||
return -1;
|
||||
}
|
||||
|
||||
Console::MsgLn("loadElfFile: %s", filename);
|
||||
if (strnicmp( filename, "cdrom0:", strlen( "cdrom0:" ) ) &&
|
||||
strnicmp( filename, "cdrom1:", strlen( "cdrom1:" ) ) ) {
|
||||
if ( stat( filename, &sbuf ) != 0 )
|
||||
|
@ -522,7 +528,7 @@ int loadElfFile(char *filename) {
|
|||
elfsize = toc.fileSize;
|
||||
}
|
||||
|
||||
SysPrintf("loadElfFile: %d\n", elfsize);
|
||||
Console::MsgLn( Color_Green, "loadElfFile: %d", elfsize);
|
||||
elfdata = (u8*)malloc(elfsize);
|
||||
if (elfdata == NULL) return -1;
|
||||
readFile(filename, (char*)elfdata, 0, elfsize);
|
||||
|
@ -556,21 +562,21 @@ int loadElfFile(char *filename) {
|
|||
}
|
||||
ElfCRC = crc;
|
||||
|
||||
SysPrintf("loadElfFile: %s; CRC = %8.8X\n", filename, crc);
|
||||
Console::MsgLn( Color_Green, "loadElfFile: %s; CRC = %8.8X\n", filename, crc);
|
||||
|
||||
// Applying patches
|
||||
if (Config.Patch) {
|
||||
sprintf(str, "%8.8x", crc);
|
||||
|
||||
sprintf(str2,"No patch found.Game will run normally. [CRC=%8.8x]",crc);//if patches found it will overwritten :p
|
||||
sprintf(str2,"No patch found. Game will run normally. [CRC=%8.8x]",crc);//if patches found it will overwritten :p
|
||||
Console::SetTitle( str2 );
|
||||
|
||||
if(LoadPatch(str)!=0)
|
||||
{
|
||||
SysPrintf("XML Loader returned an error. Trying to load a pnach...\n");
|
||||
Console::WriteLn("XML Loader returned an error. Trying to load a pnach...");
|
||||
inifile_read(str);
|
||||
}
|
||||
else SysPrintf("XML Loading success. Will not load from pnach...\n");
|
||||
else Console::WriteLn("XML Loading success. Will not load from pnach...");
|
||||
applypatch( 0 );
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ extern char args[256]; //to be filled by GUI
|
|||
extern unsigned int args_ptr;
|
||||
|
||||
//-------------------
|
||||
int loadElfFile(char *filename);
|
||||
int loadElfFile(const char *filename);
|
||||
void LoadGameSpecificSettings();
|
||||
|
||||
extern u32 ElfCRC;
|
||||
|
|
|
@ -0,0 +1,127 @@
|
|||
/* Pcsx2 - Pc Ps2 Emulator
|
||||
* Copyright (C) 2002-2008 Pcsx2 Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef _PCSX2_EXCEPTIONS_H_
|
||||
#define _PCSX2_EXCEPTIONS_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace Exception
|
||||
{
|
||||
// This exception exception thrown any time an operation is attempted when an object
|
||||
// is in an uninitialized state.
|
||||
class InvalidOperation : public std::logic_error
|
||||
{
|
||||
public:
|
||||
virtual ~InvalidOperation() throw() {}
|
||||
explicit InvalidOperation( const std::string& msg="Attempted method call is invalid for the current object or program state." ) :
|
||||
logic_error( msg ) {}
|
||||
};
|
||||
|
||||
// This exception is thrown by the PS2 emulation (R5900, etc) when bad things happen
|
||||
// that force the emulation state to terminate. The GUI should handle them by returning
|
||||
// the user to the GUI.
|
||||
class CpuStateShutdown : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
virtual ~CpuStateShutdown() throw() {}
|
||||
explicit CpuStateShutdown( const std::string& msg="The PS2 emulated state was shut down unexpectedly." ) :
|
||||
runtime_error( msg ) {}
|
||||
};
|
||||
|
||||
// Exception thrown by SaveState class when a critical plugin or gzread
|
||||
class FreezePluginFailure : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
std::string plugin_name; // name of the plugin
|
||||
std::string freeze_action;
|
||||
|
||||
virtual ~FreezePluginFailure() throw() {}
|
||||
explicit FreezePluginFailure( const std::string& plugin, const std::string& action ) :
|
||||
runtime_error( plugin + " plugin returned an error while " + action + " the state." )
|
||||
, plugin_name( plugin )
|
||||
, freeze_action( action ){}
|
||||
};
|
||||
|
||||
class UnsupportedStateVersion : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
virtual ~UnsupportedStateVersion() throw() {}
|
||||
explicit UnsupportedStateVersion( const std::string& msg="Unknown or unsupported savestate version." ) :
|
||||
runtime_error( msg ) {}
|
||||
};
|
||||
|
||||
class PluginFailure : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
std::string plugin_name; // name of the plugin
|
||||
|
||||
virtual ~PluginFailure() throw() {}
|
||||
explicit PluginFailure( const std::string& plugin, const std::string& msg = "An error occured in the " ) :
|
||||
runtime_error( plugin + msg + " Plugin" )
|
||||
, plugin_name( plugin ) {}
|
||||
};
|
||||
|
||||
/**** BEGIN STREAMING EXCEPTIONS ****/
|
||||
|
||||
// Generic stream error. Contains the name of the stream and a message.
|
||||
// This exception is usually thrown via derrived classes, except in the (rare) case of a generic / unknown error.
|
||||
class Stream : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
std::string stream_name; // name of the stream (if applicable)
|
||||
|
||||
virtual ~Stream() throw() {}
|
||||
|
||||
// copy construct!
|
||||
Stream( const Stream& src ) :
|
||||
std::runtime_error( src.what() )
|
||||
, stream_name( src.stream_name ) {}
|
||||
|
||||
explicit Stream(
|
||||
const std::string& objname=std::string(),
|
||||
const std::string& msg="Invalid stream object" ) :
|
||||
std::runtime_error( msg + ": " + objname )
|
||||
, stream_name( objname ) {}
|
||||
};
|
||||
|
||||
// Exception thrown when a corrupted or truncated savestate is encountered.
|
||||
class BadSavedState : public Stream
|
||||
{
|
||||
public:
|
||||
virtual ~BadSavedState() throw() {}
|
||||
explicit BadSavedState(
|
||||
const std::string& objname=std::string(),
|
||||
const std::string& msg="Corrupted data or end of file encountered while loading savestate" ) :
|
||||
Stream( objname, msg ) {}
|
||||
};
|
||||
|
||||
// Exception thrown when an attempt to open a non-existant file is made.
|
||||
// (this exception can also mean file permissions are invalid)
|
||||
class FileNotFound : public Stream
|
||||
{
|
||||
public:
|
||||
virtual ~FileNotFound() throw() {}
|
||||
explicit FileNotFound(
|
||||
const std::string& objname=std::string(),
|
||||
const std::string& msg="File not found or permission denied" ) :
|
||||
Stream( objname, msg ) {}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
160
pcsx2/GS.cpp
160
pcsx2/GS.cpp
|
@ -224,15 +224,15 @@ static s32 g_pGSvSyncCount = 0;
|
|||
// GS Playback
|
||||
int g_SaveGSStream = 0; // save GS stream; 1 - prepare, 2 - save
|
||||
int g_nLeftGSFrames = 0; // when saving, number of frames left
|
||||
gzFile g_fGSSave;
|
||||
gzSavingState* g_fGSSave;
|
||||
|
||||
void GSGIFTRANSFER1(u32 *pMem, u32 addr) {
|
||||
if( g_SaveGSStream == 2) {
|
||||
u32 type = GSRUN_TRANS1;
|
||||
u32 size = (0x4000-(addr))/16;
|
||||
gzwrite(g_fGSSave, &type, sizeof(type));
|
||||
gzwrite(g_fGSSave, &size, 4);
|
||||
gzwrite(g_fGSSave, ((u8*)pMem)+(addr), size*16);
|
||||
u32 size = (0x4000-(addr))/16;
|
||||
g_fGSSave->Freeze( type );
|
||||
g_fGSSave->Freeze( size );
|
||||
g_fGSSave->FreezeMem( ((u8*)pMem)+(addr), size*16 );
|
||||
}
|
||||
GSgifTransfer1(pMem, addr);
|
||||
}
|
||||
|
@ -241,9 +241,9 @@ void GSGIFTRANSFER2(u32 *pMem, u32 size) {
|
|||
if( g_SaveGSStream == 2) {
|
||||
u32 type = GSRUN_TRANS2;
|
||||
u32 _size = size;
|
||||
gzwrite(g_fGSSave, &type, sizeof(type));
|
||||
gzwrite(g_fGSSave, &_size, 4);
|
||||
gzwrite(g_fGSSave, pMem, _size*16);
|
||||
g_fGSSave->Freeze( type );
|
||||
g_fGSSave->Freeze( size );
|
||||
g_fGSSave->FreezeMem( pMem, _size*16 );
|
||||
}
|
||||
GSgifTransfer2(pMem, size);
|
||||
}
|
||||
|
@ -252,9 +252,9 @@ void GSGIFTRANSFER3(u32 *pMem, u32 size) {
|
|||
if( g_SaveGSStream == 2 ) {
|
||||
u32 type = GSRUN_TRANS3;
|
||||
u32 _size = size;
|
||||
gzwrite(g_fGSSave, &type, sizeof(type));
|
||||
gzwrite(g_fGSSave, &_size, 4);
|
||||
gzwrite(g_fGSSave, pMem, _size*16);
|
||||
g_fGSSave->Freeze( type );
|
||||
g_fGSSave->Freeze( size );
|
||||
g_fGSSave->FreezeMem( pMem, _size*16 );
|
||||
}
|
||||
GSgifTransfer3(pMem, size);
|
||||
}
|
||||
|
@ -262,7 +262,7 @@ void GSGIFTRANSFER3(u32 *pMem, u32 size) {
|
|||
__forceinline void GSVSYNC(void) {
|
||||
if( g_SaveGSStream == 2 ) {
|
||||
u32 type = GSRUN_VSYNC;
|
||||
gzwrite(g_fGSSave, &type, sizeof(type));
|
||||
g_fGSSave->Freeze( type );
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
@ -450,9 +450,21 @@ void gsSetVideoRegionType( u32 isPal )
|
|||
|
||||
|
||||
// Initializes MultiGS ringbuffer and registers.
|
||||
// (does nothing for single threaded GS)
|
||||
// Make sure framelimiter options are in sync with the plugin's capabilities.
|
||||
void gsInit()
|
||||
{
|
||||
switch(CHECK_FRAMELIMIT)
|
||||
{
|
||||
case PCSX2_FRAMELIMIT_SKIP:
|
||||
case PCSX2_FRAMELIMIT_VUSKIP:
|
||||
if( GSsetFrameSkip == NULL )
|
||||
{
|
||||
Config.Options &= ~PCSX2_FRAMELIMIT_MASK;
|
||||
Console::WriteLn("Notice: Disabling frameskip -- GS plugin does not support it.");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if( CHECK_MULTIGS )
|
||||
{
|
||||
g_pGSRingPos = GS_RINGBUFFERBASE;
|
||||
|
@ -607,7 +619,7 @@ void GSRINGBUF_DONECOPY(const u8* mem, u32 size)
|
|||
}
|
||||
}
|
||||
|
||||
void gsShutdown()
|
||||
void gsClose()
|
||||
{
|
||||
if( CHECK_MULTIGS ) {
|
||||
|
||||
|
@ -616,7 +628,7 @@ void gsShutdown()
|
|||
// (they might be 1 byte under some compilers).
|
||||
gsHasToExit = true;
|
||||
|
||||
SysPrintf("MTGS > Closing GS thread...\n");
|
||||
Console::WriteLn( "MTGS > Closing GS thread..." );
|
||||
GS_SETEVENT();
|
||||
|
||||
if (g_hVuGsThread != NULL) thread_close( g_hVuGsThread );
|
||||
|
@ -630,6 +642,8 @@ void gsShutdown()
|
|||
}
|
||||
else
|
||||
GSclose();
|
||||
|
||||
m_gsOpened = false;
|
||||
}
|
||||
|
||||
#ifdef PCSX2_GSRING_TX_STATS
|
||||
|
@ -824,8 +838,6 @@ void GSRingBufSimplePacket(int type, int data0, int data1, int data2)
|
|||
while( future_writepos == *(volatile PU8*)&g_pGSRingPos )
|
||||
gsSetEventWait();
|
||||
|
||||
|
||||
|
||||
#ifdef RINGBUF_DEBUG_STACK
|
||||
mutex_lock( stackLock );
|
||||
ringposStack.push_front( (uptr)writepos );
|
||||
|
@ -841,7 +853,7 @@ void GSRingBufSimplePacket(int type, int data0, int data1, int data2)
|
|||
AtomicExchangePointer( g_pGSWritePos, future_writepos );
|
||||
}
|
||||
|
||||
void GSRingBufSimplePacket64(int type, u32 data0, u64 data1 )
|
||||
void GSRingBufPointerPacket(int type, u32 data0, void* data1 )
|
||||
{
|
||||
u8* writepos = g_pGSWritePos;
|
||||
const u8* future_writepos = writepos+16;
|
||||
|
@ -862,7 +874,7 @@ void GSRingBufSimplePacket64(int type, u32 data0, u64 data1 )
|
|||
|
||||
*(u32*)writepos = type;
|
||||
*(u32*)(writepos+4) = data0;
|
||||
*(u64*)(writepos+8) = data1;
|
||||
*(uptr*)(writepos+8) = (uptr)data1;
|
||||
|
||||
assert( future_writepos != *(volatile PU8*)&g_pGSRingPos );
|
||||
AtomicExchangePointer( g_pGSWritePos, future_writepos );
|
||||
|
@ -1254,9 +1266,7 @@ u32 GSgifTransferDummy(int pathidx, const u8 *pMem, u32 size)
|
|||
else if(path.tag.nloop == 0)
|
||||
{
|
||||
if(pathidx == 0 && g_FFXHack)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
eop = true;
|
||||
}
|
||||
|
@ -1270,6 +1280,9 @@ u32 GSgifTransferDummy(int pathidx, const u8 *pMem, u32 size)
|
|||
|
||||
while(size > 0)
|
||||
{
|
||||
// Register 0xe is a NOP.
|
||||
// Why were we treating it as a handler?
|
||||
|
||||
if( path.GetReg() == 0xe )
|
||||
{
|
||||
const int handler = pMem[8];
|
||||
|
@ -1285,13 +1298,11 @@ u32 GSgifTransferDummy(int pathidx, const u8 *pMem, u32 size)
|
|||
path.tag.nloop--;
|
||||
|
||||
if(path.tag.nloop == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
case GIF_FLG_REGLIST:
|
||||
|
||||
|
@ -1319,32 +1330,27 @@ u32 GSgifTransferDummy(int pathidx, const u8 *pMem, u32 size)
|
|||
}
|
||||
|
||||
if(size & 1) pMem += 8; //sizeof(GIFReg);
|
||||
|
||||
size /= 2;
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
case GIF_FLG_IMAGE2: // hmmm
|
||||
|
||||
assert(0);
|
||||
|
||||
path.tag.nloop = 0;
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
case GIF_FLG_IMAGE:
|
||||
{
|
||||
int len = (int)min(size, path.tag.nloop);
|
||||
{
|
||||
int len = (int)min(size, path.tag.nloop);
|
||||
|
||||
//ASSERT(!(len&3));
|
||||
|
||||
pMem += len * 16;
|
||||
path.tag.nloop -= len;
|
||||
size -= len;
|
||||
}
|
||||
|
||||
break;
|
||||
//ASSERT(!(len&3));
|
||||
|
||||
pMem += len * 16;
|
||||
path.tag.nloop -= len;
|
||||
size -= len;
|
||||
}
|
||||
break;
|
||||
|
||||
jNO_DEFAULT;
|
||||
|
||||
|
@ -1364,7 +1370,7 @@ u32 GSgifTransferDummy(int pathidx, const u8 *pMem, u32 size)
|
|||
if(!path.tag.eop && path.tag.nloop > 0)
|
||||
{
|
||||
path.tag.nloop = 0;
|
||||
SysPrintf( "path1 hack! " );
|
||||
Console::Write( "path1 hack! " );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2207,52 +2213,13 @@ GS_THREADPROC
|
|||
break;
|
||||
|
||||
case GS_RINGTYPE_SAVE:
|
||||
{
|
||||
gzFile f = *(gzFile*)(g_pGSRingPos+4);
|
||||
freezeData fP;
|
||||
|
||||
if (GSfreeze(FREEZE_SIZE, &fP) == -1) {
|
||||
gzclose(f);
|
||||
break;
|
||||
}
|
||||
fP.data = (s8*)malloc(fP.size);
|
||||
if (fP.data == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (GSfreeze(FREEZE_SAVE, &fP) == -1) {
|
||||
gzclose(f);
|
||||
break;
|
||||
}
|
||||
|
||||
gzwrite(f, &fP.size, sizeof(fP.size));
|
||||
if (fP.size) {
|
||||
gzwrite(f, fP.data, fP.size);
|
||||
free(fP.data);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GS_RINGTYPE_LOAD:
|
||||
{
|
||||
gzFile f = *(gzFile*)(g_pGSRingPos+4);
|
||||
freezeData fP;
|
||||
|
||||
gzread(f, &fP.size, sizeof(fP.size));
|
||||
if (fP.size) {
|
||||
fP.data = (s8*)malloc(fP.size);
|
||||
if (fP.data == NULL)
|
||||
break;
|
||||
|
||||
gzread(f, fP.data, fP.size);
|
||||
}
|
||||
if (GSfreeze(FREEZE_LOAD, &fP) == -1) {
|
||||
// failed
|
||||
}
|
||||
if (fP.size)
|
||||
free(fP.data);
|
||||
|
||||
SaveState* f = (SaveState*)(*(uptr*)(g_pGSRingPos+8));
|
||||
f->FreezePlugin( "GS", GSfreeze );
|
||||
break;
|
||||
}
|
||||
|
||||
case GS_RINGTYPE_RECORD:
|
||||
{
|
||||
int record = *(u32*)(g_pGSRingPos+4);
|
||||
|
@ -2312,25 +2279,23 @@ GS_THREADPROC
|
|||
return 0;
|
||||
}
|
||||
|
||||
int gsFreeze(gzFile f, int Mode)
|
||||
void SaveState::gsFreeze()
|
||||
{
|
||||
gzfreeze(PS2MEM_GS, 0x2000);
|
||||
gzfreeze(&CSRw, sizeof(CSRw));
|
||||
FreezeMem(PS2MEM_GS, 0x2000);
|
||||
Freeze(CSRw);
|
||||
|
||||
for(int i=0; i<3; i++ )
|
||||
{
|
||||
gzfreeze( &g_path[i].tag, sizeof( g_path[i].tag ) );
|
||||
Freeze( g_path[i].tag );
|
||||
|
||||
// Earlier versions had an extra u32 in the tag struct:
|
||||
|
||||
u32 dummy=g_path[i].nreg;
|
||||
gzfreeze( &dummy, sizeof( dummy ) );
|
||||
Freeze( dummy );
|
||||
}
|
||||
|
||||
for(int i=0; i<3; i++ )
|
||||
gzfreeze( &g_path[i].regs, sizeof( g_path[i].regs ) );
|
||||
|
||||
return 0;
|
||||
Freeze( g_path[i].regs );
|
||||
}
|
||||
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
|
@ -2342,16 +2307,17 @@ struct GSStatePacket
|
|||
};
|
||||
|
||||
// runs the GS
|
||||
void RunGSState(gzFile f)
|
||||
void RunGSState( gzLoadingState& f )
|
||||
{
|
||||
u32 newfield;
|
||||
list< GSStatePacket > packets;
|
||||
|
||||
while(!gzeof(f)) {
|
||||
while( !f.Finished() )
|
||||
{
|
||||
int type, size;
|
||||
gzread(f, &type, sizeof(type));
|
||||
f.Freeze( type );
|
||||
|
||||
if( type != GSRUN_VSYNC ) gzread(f, &size, 4);
|
||||
if( type != GSRUN_VSYNC ) f.Freeze( size );
|
||||
|
||||
packets.push_back(GSStatePacket());
|
||||
GSStatePacket& p = packets.back();
|
||||
|
@ -2360,7 +2326,7 @@ void RunGSState(gzFile f)
|
|||
|
||||
if( type != GSRUN_VSYNC ) {
|
||||
p.mem.resize(size*16);
|
||||
gzread(f, &p.mem[0], size*16);
|
||||
f.FreezeMem( &p.mem[0], size*16 );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2393,8 +2359,8 @@ void RunGSState(gzFile f)
|
|||
if( g_SaveGSStream != 3 )
|
||||
return;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
|
||||
jNO_DEFAULT
|
||||
}
|
||||
|
||||
++it;
|
||||
|
|
|
@ -76,13 +76,13 @@ enum GS_RINGTYPE
|
|||
// if returns NULL, don't copy (memory is preserved)
|
||||
u8* GSRingBufCopy(u32 size, u32 type);
|
||||
void GSRingBufSimplePacket(int type, int data0, int data1, int data2);
|
||||
void GSRingBufSimplePacket64(int type, u32 data0, u64 data1 );
|
||||
void GSRingBufPointerPacket(int type, u32 data0, void* data1 );
|
||||
|
||||
u32 GSgifTransferDummy(int path, const u8 *pMem, u32 size);
|
||||
|
||||
void gsInit();
|
||||
s32 gsOpen();
|
||||
void gsShutdown();
|
||||
void gsClose();
|
||||
void gsReset();
|
||||
void gsSetVideoRegionType( u32 isPal );
|
||||
void gsResetFrameSkip();
|
||||
|
@ -125,7 +125,6 @@ extern void gsInterrupt();
|
|||
void dmaGIF();
|
||||
void GIFdma();
|
||||
void mfifoGIFtransfer(int qwc);
|
||||
int gsFreeze(gzFile f, int Mode);
|
||||
int _GIFchain();
|
||||
void gifMFIFOInterrupt();
|
||||
|
||||
|
@ -141,11 +140,11 @@ extern u32 g_vu1SkipCount;
|
|||
|
||||
extern int g_SaveGSStream;
|
||||
extern int g_nLeftGSFrames;
|
||||
extern gzFile g_fGSSave;
|
||||
extern gzSavingState* g_fGSSave;
|
||||
|
||||
#endif
|
||||
|
||||
void RunGSState(gzFile f);
|
||||
void RunGSState(gzLoadingState& f);
|
||||
|
||||
extern void GSGIFTRANSFER1(u32 *pMem, u32 addr);
|
||||
extern void GSGIFTRANSFER2(u32 *pMem, u32 addr);
|
||||
|
|
108
pcsx2/IPU/IPU.c
108
pcsx2/IPU/IPU.c
|
@ -170,69 +170,67 @@ void ipuShutdown()
|
|||
{
|
||||
}
|
||||
|
||||
int ipuFreeze(gzFile f, int Mode) {
|
||||
// fixme - ipuFreeze looks fairly broken. Should probably take a closer look at some point.
|
||||
|
||||
void SaveState::ipuFreeze() {
|
||||
IPUProcessInterrupt();
|
||||
|
||||
gzfreeze(ipuRegs, sizeof(IPUregisters));
|
||||
gzfreeze(&g_nDMATransfer, sizeof(g_nDMATransfer));
|
||||
gzfreeze(&FIreadpos, sizeof(FIreadpos));
|
||||
gzfreeze(&FIwritepos, sizeof(FIwritepos));
|
||||
gzfreeze(fifo_input, sizeof(fifo_input));
|
||||
gzfreeze(&FOreadpos, sizeof(FOreadpos));
|
||||
gzfreeze(&FOwritepos, sizeof(FOwritepos));
|
||||
gzfreeze(fifo_output, sizeof(fifo_output));
|
||||
gzfreeze(&g_BP, sizeof(g_BP));
|
||||
gzfreeze(niq, sizeof(niq));
|
||||
gzfreeze(iq, sizeof(niq));
|
||||
gzfreeze(vqclut, sizeof(vqclut));
|
||||
gzfreeze(s_thresh, sizeof(s_thresh));
|
||||
gzfreeze(&coded_block_pattern, sizeof(coded_block_pattern));
|
||||
gzfreeze(&g_decoder, sizeof(g_decoder));
|
||||
gzfreeze(mpeg2_scan_norm, sizeof(mpeg2_scan_norm));
|
||||
gzfreeze(mpeg2_scan_alt, sizeof(mpeg2_scan_alt));
|
||||
gzfreeze(g_nCmdPos, sizeof(g_nCmdPos));
|
||||
gzfreeze(&g_nCmdIndex, sizeof(g_nCmdIndex));
|
||||
gzfreeze(&ipuCurCmd, sizeof(ipuCurCmd));
|
||||
FreezeMem(ipuRegs, sizeof(IPUregisters));
|
||||
Freeze(g_nDMATransfer);
|
||||
Freeze(FIreadpos);
|
||||
Freeze(FIwritepos);
|
||||
Freeze(fifo_input);
|
||||
Freeze(FOreadpos);
|
||||
Freeze(FOwritepos);
|
||||
Freeze(fifo_output);
|
||||
Freeze(g_BP);
|
||||
Freeze(niq);
|
||||
Freeze(iq);
|
||||
Freeze(vqclut);
|
||||
Freeze(s_thresh);
|
||||
Freeze(coded_block_pattern);
|
||||
Freeze(g_decoder);
|
||||
Freeze(mpeg2_scan_norm);
|
||||
Freeze(mpeg2_scan_alt);
|
||||
Freeze(g_nCmdPos);
|
||||
Freeze(g_nCmdIndex);
|
||||
Freeze(ipuCurCmd);
|
||||
|
||||
gzfreeze(_readbits, sizeof(_readbits));
|
||||
Freeze(_readbits);
|
||||
|
||||
if( Mode == 0 ) {
|
||||
int temp = readbits-_readbits;
|
||||
gzfreeze(&temp, sizeof(temp));
|
||||
}
|
||||
else {
|
||||
int temp;
|
||||
gzfreeze(&temp, sizeof(temp));
|
||||
int temp = readbits-_readbits;
|
||||
Freeze(temp);
|
||||
|
||||
if( IsLoading() )
|
||||
{
|
||||
readbits = _readbits;
|
||||
|
||||
//other stuff
|
||||
g_decoder.intra_quantizer_matrix =(u8*)iq;
|
||||
g_decoder.non_intra_quantizer_matrix =(u8*)niq;
|
||||
g_decoder.picture_structure = FRAME_PICTURE; //default: progressive...my guess:P
|
||||
g_decoder.mb8 =&mb8;
|
||||
g_decoder.mb16=&mb16;
|
||||
g_decoder.rgb32=&rgb32;
|
||||
g_decoder.rgb16=&rgb16;
|
||||
g_decoder.stride=16;
|
||||
|
||||
if (!mpeg2_inited){
|
||||
mpeg2_idct_init();
|
||||
convert=convert_rgb (CONVERT_RGB, 32);
|
||||
convert(16, 16, 0, NULL, &convert_init);
|
||||
memset(mb8.Y,0,sizeof(mb8.Y));
|
||||
memset(mb8.Cb,0,sizeof(mb8.Cb));
|
||||
memset(mb8.Cr,0,sizeof(mb8.Cr));
|
||||
memset(mb16.Y,0,sizeof(mb16.Y));
|
||||
memset(mb16.Cb,0,sizeof(mb16.Cb));
|
||||
memset(mb16.Cr,0,sizeof(mb16.Cr));
|
||||
mpeg2_inited=1;
|
||||
}
|
||||
}
|
||||
|
||||
//other stuff
|
||||
g_decoder.intra_quantizer_matrix =(u8*)iq;
|
||||
g_decoder.non_intra_quantizer_matrix =(u8*)niq;
|
||||
g_decoder.picture_structure = FRAME_PICTURE; //default: progressive...my guess:P
|
||||
g_decoder.mb8 =&mb8;
|
||||
g_decoder.mb16=&mb16;
|
||||
g_decoder.rgb32=&rgb32;
|
||||
g_decoder.rgb16=&rgb16;
|
||||
g_decoder.stride=16;
|
||||
|
||||
if (!mpeg2_inited){
|
||||
mpeg2_idct_init();
|
||||
convert=convert_rgb (CONVERT_RGB, 32);
|
||||
convert(16, 16, 0, NULL, &convert_init);
|
||||
memset(mb8.Y,0,sizeof(mb8.Y));
|
||||
memset(mb8.Cb,0,sizeof(mb8.Cb));
|
||||
memset(mb8.Cr,0,sizeof(mb8.Cr));
|
||||
memset(mb16.Y,0,sizeof(mb16.Y));
|
||||
memset(mb16.Cb,0,sizeof(mb16.Cb));
|
||||
memset(mb16.Cr,0,sizeof(mb16.Cr));
|
||||
mpeg2_inited=1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL ipuCanFreeze()
|
||||
bool ipuCanFreeze()
|
||||
{
|
||||
return ipuCurCmd == 0xffffffff;
|
||||
}
|
||||
|
|
|
@ -195,7 +195,7 @@ int ipuInit();
|
|||
void ipuReset();
|
||||
void ipuShutdown();
|
||||
int ipuFreeze(gzFile f, int Mode);
|
||||
BOOL ipuCanFreeze();
|
||||
bool ipuCanFreeze();
|
||||
|
||||
u32 ipuRead32(u32 mem);
|
||||
int ipuConstRead32(u32 x86reg, u32 mem);
|
||||
|
|
|
@ -833,7 +833,7 @@ int __Deci2Call(int call, u32 *addr) {
|
|||
return 1;
|
||||
|
||||
case 0x10://kputs
|
||||
SysPrintf("%s", PSM(*addr));
|
||||
Console::Msg( Color_Cyan, "%s", PSM(*addr));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -850,7 +850,7 @@ void SYSCALL() {
|
|||
else call = cpuRegs.GPR.n.v1.UC[0];
|
||||
BIOS_LOG("Bios call: %s (%x)\n", bios[call], call);
|
||||
if (call == 0x7c && cpuRegs.GPR.n.a0.UL[0] == 0x10) {
|
||||
SysPrintf("%s", PSM(PSMu32(cpuRegs.GPR.n.a1.UL[0])));
|
||||
Console::Msg( Color_Cyan, "%s", PSM(PSMu32(cpuRegs.GPR.n.a1.UL[0])));
|
||||
} else
|
||||
//if (call == 0x7c) SysPrintf("Deci2Call: %x\n", cpuRegs.GPR.n.a0.UL[0]);
|
||||
if (call == 0x7c) __Deci2Call(cpuRegs.GPR.n.a0.UL[0], (u32*)PSM(cpuRegs.GPR.n.a1.UL[0]));
|
||||
|
|
|
@ -124,6 +124,18 @@ void SignalExit(int sig) {
|
|||
|
||||
void RunExecute(int run)
|
||||
{
|
||||
// (air notes:)
|
||||
// If you want to use the new to-memory savestate feature, take a look at the new
|
||||
// RunExecute in WinMain.c, and secondly the CpuDlg.c or AdvancedDlg.cpp. The
|
||||
// objects used are MemoryAlloc, memLoadingState, and memSavingState.
|
||||
|
||||
// It's important to make sure to reset the CPU and the plugins correctly, which is
|
||||
// where the new RunExecute comes into play. It can be kind of tricky knowing
|
||||
// when to call cpuExecuteBios and loadElfFile, and with what parameters.
|
||||
|
||||
// (or, as an alternative maybe we should switch to wxWidgets and have a unified
|
||||
// cross platform gui?) - Air
|
||||
|
||||
if (needReset == TRUE)
|
||||
if (!SysReset())
|
||||
return;
|
||||
|
@ -281,31 +293,102 @@ void UpdateMenuSlots(GtkMenuItem *menuitem, gpointer user_data) {
|
|||
}
|
||||
}
|
||||
|
||||
void States_Load(int num) {
|
||||
char Text[g_MaxPath];
|
||||
int ret;
|
||||
|
||||
void States_Load(const char* file, int num = -1 )
|
||||
{
|
||||
efile = 2;
|
||||
RunExecute(0);
|
||||
try
|
||||
{
|
||||
// when we init joe it'll throw an UnsupportedStateVersion.
|
||||
// So reset the cpu afterward so that trying to load a bum save
|
||||
// doesn't fry the current emulation state.
|
||||
gzLoadingState joe( file );
|
||||
|
||||
sprintf (Text, SSTATES_DIR "/%8.8X.%3.3d", ElfCRC, num);
|
||||
ret = LoadState(Text);
|
||||
// Make sure the cpu and plugins are ready to be state-ified!
|
||||
cpuReset();
|
||||
OpenPlugins( NULL );
|
||||
|
||||
joe.FreezeAll();
|
||||
}
|
||||
catch( Exception::UnsupportedStateVersion& )
|
||||
{
|
||||
if( num != -1 )
|
||||
SysMessage( _( "Savestate slot %d is an unsupported version." ), num);
|
||||
else
|
||||
SysMessage( _( "%s : This is an unsupported savestate version." ), file);
|
||||
|
||||
// At this point the cpu hasn't been reset, so we can return
|
||||
// control to the user safely...
|
||||
|
||||
return;
|
||||
}
|
||||
catch( std::exception& ex )
|
||||
{
|
||||
if( num != -1 )
|
||||
Console::Error( _("Error occured while trying to load savestate slot %d"), num);
|
||||
else
|
||||
Console::Error( _("Error occured while trying to load savestate file: %d"), file);
|
||||
|
||||
Console::Error( ex.what() );
|
||||
|
||||
// The emulation state is ruined. Might as well give them a popup and start the gui.
|
||||
|
||||
SysMessage( _(
|
||||
"An error occured while trying to load the savestate data.\n"
|
||||
"Pcsx2 emulation state has been reset."
|
||||
) );
|
||||
|
||||
cpuShutdown();
|
||||
return;
|
||||
}
|
||||
|
||||
Cpu->Execute();
|
||||
}
|
||||
|
||||
void States_Load(int num) {
|
||||
char Text[g_MaxPath];
|
||||
|
||||
SaveState::GetFilename( Text, num );
|
||||
|
||||
struct stat buf;
|
||||
if( stat(Text, &buf ) == -1 )
|
||||
{
|
||||
Console::Notice( "Saveslot %d is empty.", num );
|
||||
return;
|
||||
}
|
||||
States_Load( Text, num );
|
||||
}
|
||||
|
||||
void States_Save( const char* file, int num = -1 );
|
||||
{
|
||||
try
|
||||
{
|
||||
gzSavingState(file).FreezeAll();
|
||||
if( num != -1 )
|
||||
Console::Notice( _( "State saved to slot %d" ), num );
|
||||
else
|
||||
Console::Notice( _( "State saved to file: %s" ), file );
|
||||
}
|
||||
catch( std::exception& ex )
|
||||
{
|
||||
if( num != -1 )
|
||||
SysMessage( _("An error occured while trying to save to slot %d"), num );
|
||||
else
|
||||
SysMessage( _("An error occured while trying to save to file: %s"), file );
|
||||
|
||||
Console::Error( _( "Save state request failed with the following error:" ) );
|
||||
Console::Error( ex.what() );
|
||||
}
|
||||
|
||||
// Do you really want the game ro resume after saving from the menu?
|
||||
// I found it annoying and removed it from the Win32 side (air)
|
||||
RunExecute(1);
|
||||
}
|
||||
|
||||
void States_Save(int num) {
|
||||
char Text[g_MaxPath];
|
||||
int ret;
|
||||
|
||||
sprintf (Text, SSTATES_DIR "/%8.8X.%3.3d", ElfCRC, num);
|
||||
ret = SaveState(Text);
|
||||
if (ret == 0)
|
||||
sprintf(Text, _("*PCSX2*: Saving State %d"), num+1);
|
||||
else
|
||||
sprintf(Text, _("*PCSX2*: Error Saving State %d"), num+1);
|
||||
|
||||
RunExecute(1);
|
||||
SaveState::GetFilename( Text, num );
|
||||
States_Save( Text, num );
|
||||
}
|
||||
|
||||
void OnStates_Load1(GtkMenuItem *menuitem, gpointer user_data) { States_Load(0); }
|
||||
|
@ -323,12 +406,7 @@ void OnLoadOther_Ok(GtkButton* button, gpointer user_data) {
|
|||
strcpy(str, File);
|
||||
gtk_widget_destroy(FileSel);
|
||||
|
||||
efile = 2;
|
||||
RunExecute(0);
|
||||
|
||||
ret = LoadState(str);
|
||||
|
||||
Cpu->Execute();
|
||||
States_Load( str );
|
||||
}
|
||||
|
||||
void OnLoadOther_Cancel(GtkButton* button, gpointer user_data) {
|
||||
|
@ -367,11 +445,8 @@ void OnSaveOther_Ok(GtkButton* button, gpointer user_data) {
|
|||
File = (gchar*)gtk_file_selection_get_filename(GTK_FILE_SELECTION(FileSel));
|
||||
strcpy(str, File);
|
||||
gtk_widget_destroy(FileSel);
|
||||
RunExecute(0);
|
||||
|
||||
ret = SaveState(str);
|
||||
|
||||
Cpu->Execute();
|
||||
States_Save( str );
|
||||
}
|
||||
|
||||
void OnSaveOther_Cancel(GtkButton* button, gpointer user_data) {
|
||||
|
@ -451,13 +526,6 @@ void OnCpu_Ok(GtkButton *button, gpointer user_data) {
|
|||
Config.CustomConsecutiveFrames = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(lookup_widget(CpuDlg, "FramesBeforeSkipping")));
|
||||
Config.CustomConsecutiveSkip = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(lookup_widget(CpuDlg, "FramesToSkip")));
|
||||
|
||||
if ((Config.Options&PCSX2_GSMULTITHREAD) ^ (newopts&PCSX2_GSMULTITHREAD)) {
|
||||
Config.Options = newopts;
|
||||
SaveConfig();
|
||||
SysMessage("Restart Pcsx2");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (newopts & PCSX2_EEREC ) newopts |= PCSX2_COP2REC;
|
||||
|
||||
Config.Options = newopts;
|
||||
|
@ -465,8 +533,14 @@ void OnCpu_Ok(GtkButton *button, gpointer user_data) {
|
|||
UpdateVSyncRate();
|
||||
SaveConfig();
|
||||
|
||||
cpuRestartCPU();
|
||||
|
||||
if ((Config.Options&PCSX2_GSMULTITHREAD) ^ (newopts&PCSX2_GSMULTITHREAD))
|
||||
{
|
||||
cpuShutdown();
|
||||
ResetPlugins();
|
||||
}
|
||||
|
||||
cpuReset(); // cpuReset will call cpuInit() automatically if needed.
|
||||
|
||||
gtk_widget_destroy(CpuDlg);
|
||||
if (MainWindow) gtk_widget_set_sensitive(MainWindow, TRUE);
|
||||
gtk_main_quit();
|
||||
|
|
|
@ -21,10 +21,26 @@
|
|||
#include "System.h"
|
||||
#include "Linux.h"
|
||||
|
||||
|
||||
#define COLOR_RESET "\033[0m"
|
||||
|
||||
|
||||
// Linux Note : The Linux Console is pretty simple. It just dumps to the stdio!
|
||||
// (no console open/close/title stuff tho, so those functions are dummies)
|
||||
namespace Console
|
||||
{
|
||||
static const char* tbl_color_codes[] =
|
||||
{
|
||||
"\033[30m" // black
|
||||
, "\033[31m" // red
|
||||
, "\033[32m" // green
|
||||
, "\033[33m" // yellow
|
||||
, "\033[34m" // blue
|
||||
, "\033[35m" // magenta
|
||||
, "\033[36m" // cyan
|
||||
, "\033[37m" // white!
|
||||
};
|
||||
|
||||
void SetTitle( const char* title )
|
||||
{
|
||||
}
|
||||
|
@ -63,6 +79,16 @@ namespace Console
|
|||
return false;
|
||||
}
|
||||
|
||||
void __fastcall SetColor( Colors color )
|
||||
{
|
||||
Write( tbl_color_codes[color] );
|
||||
}
|
||||
|
||||
void ClearColor()
|
||||
{
|
||||
Write( COLOR_RESET );
|
||||
}
|
||||
|
||||
__forceinline bool __fastcall WriteLn( const char* fmt )
|
||||
{
|
||||
Write( fmt );
|
||||
|
@ -70,7 +96,38 @@ namespace Console
|
|||
return false;
|
||||
}
|
||||
|
||||
bool Format( const char* fmt, ... )
|
||||
static __forceinline void __fastcall _MsgLn( Colors color, const char* fmt, va_list args )
|
||||
{
|
||||
char msg[2048];
|
||||
|
||||
vsnprintf(msg,2045,fmt,list);
|
||||
msg[2044] = '\0';
|
||||
strcat( msg, "\n" );
|
||||
SetColor( color );
|
||||
Write( msg );
|
||||
ClearColor();
|
||||
|
||||
if( emuLog != NULL )
|
||||
fflush( emuLog ); // manual flush to accompany manual newline
|
||||
}
|
||||
|
||||
bool Msg( Colors color, const char* fmt, ... )
|
||||
{
|
||||
va_list list;
|
||||
char msg[2048];
|
||||
|
||||
va_start(list,fmt);
|
||||
vsnprintf(msg,2047,fmt,list);
|
||||
msg[2047] = '\0';
|
||||
va_end(list);
|
||||
|
||||
SetColor( color );
|
||||
Write( msg );
|
||||
ClearColor();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Msg( const char* fmt, ... )
|
||||
{
|
||||
va_list list;
|
||||
char msg[2048];
|
||||
|
@ -84,7 +141,7 @@ namespace Console
|
|||
return false;
|
||||
}
|
||||
|
||||
bool FormatLn( const char* fmt, ... )
|
||||
bool MsgLn( const char* fmt, ... )
|
||||
{
|
||||
va_list list;
|
||||
char msg[2048];
|
||||
|
@ -99,5 +156,27 @@ namespace Console
|
|||
fflush( emuLog ); // manual flush to accomany manual newline
|
||||
return false;
|
||||
}
|
||||
|
||||
// Displays a message in the console with red emphasis.
|
||||
// Newline is automatically appended.
|
||||
bool Error( const char* fmt, ... )
|
||||
{
|
||||
va_list list;
|
||||
va_start(list,fmt);
|
||||
_MsgLn( Color_Red, fmt, list );
|
||||
va_end(list);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Displays a message in the console with yellow emphasis.
|
||||
// Newline is automatically appended.
|
||||
bool Notice( const char* fmt, ... )
|
||||
{
|
||||
va_list list;
|
||||
va_start(list,fmt);
|
||||
_MsgLn( Color_Yellow, fmt, list );
|
||||
va_end(list);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
namespace EE { namespace Interpreter{ namespace OpcodeImpl
|
||||
{
|
||||
|
||||
void MMI_Unknown() { SysPrintf ("Unknown MMI opcode called\n"); }
|
||||
void MMI_Unknown() { Console::Notice("Unknown MMI opcode called"); }
|
||||
|
||||
//*****************MMI OPCODES*********************************
|
||||
|
||||
|
|
242
pcsx2/Memory.c
242
pcsx2/Memory.c
|
@ -104,19 +104,37 @@ u16 ba0R16(u32 mem) {
|
|||
/////////////////////////////
|
||||
#ifdef PCSX2_VIRTUAL_MEM
|
||||
|
||||
class vm_alloc_failed_exception : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
void* requested_addr;
|
||||
int requested_size;
|
||||
void* returned_addr;
|
||||
|
||||
explicit vm_alloc_failed_exception( void* reqadr, uint reqsize, void* retadr ) :
|
||||
std::runtime_error( "virtual memory allocation failure." )
|
||||
, requested_addr( reqadr )
|
||||
, requested_size( reqsize )
|
||||
, returned_addr( retadr )
|
||||
{}
|
||||
};
|
||||
|
||||
PSMEMORYBLOCK s_psM = {0}, s_psHw = {0}, s_psS = {0}, s_psxM = {0}, s_psVuMem = {0};
|
||||
|
||||
#define PHYSICAL_ALLOC(ptr, size, block) { \
|
||||
if(SysPhysicalAlloc(size, &block) == -1 ) \
|
||||
goto eCleanupAndExit; \
|
||||
if(SysVirtualPhyAlloc((void*)ptr, size, &block) == -1) \
|
||||
goto eCleanupAndExit; \
|
||||
} \
|
||||
static void PHYSICAL_ALLOC( void* ptr, uint size, PSMEMORYBLOCK& block)
|
||||
{
|
||||
if(SysPhysicalAlloc(size, &block) == -1 )
|
||||
throw vm_alloc_failed_exception( ptr, size, NULL );
|
||||
if(SysVirtualPhyAlloc(ptr, size, &block) == -1)
|
||||
throw vm_alloc_failed_exception( ptr, size, NULL );
|
||||
}
|
||||
|
||||
static void PHYSICAL_FREE( void* ptr, uint size, PSMEMORYBLOCK& block)
|
||||
{
|
||||
SysVirtualFree(ptr, size);
|
||||
SysPhysicalFree(&block);
|
||||
}
|
||||
|
||||
#define PHYSICAL_FREE(ptr, size, block) { \
|
||||
SysVirtualFree(ptr, size); \
|
||||
SysPhysicalFree(&block); \
|
||||
} \
|
||||
|
||||
#ifdef _WIN32 // windows implementation of vm
|
||||
|
||||
|
@ -136,19 +154,19 @@ static PSMEMORYMAP initMemoryMap(uptr* aPFNs, uptr* aVFNs)
|
|||
// virtual memory blocks
|
||||
PSMEMORYMAP *memLUT = NULL;
|
||||
|
||||
#define VIRTUAL_ALLOC(base, size, Protection) { \
|
||||
LPVOID lpMemReserved = VirtualAlloc( base, size, MEM_RESERVE|MEM_COMMIT, Protection ); \
|
||||
if( lpMemReserved == NULL || base != lpMemReserved ) \
|
||||
{ \
|
||||
SysPrintf("Cannot reserve memory at 0x%8.8x(%x), error: %d.\n", base, lpMemReserved, GetLastError()); \
|
||||
goto eCleanupAndExit; \
|
||||
} \
|
||||
} \
|
||||
static void VIRTUAL_ALLOC( void* base, uint size, uint Protection)
|
||||
{
|
||||
LPVOID lpMemReserved = VirtualAlloc( base, size, MEM_RESERVE|MEM_COMMIT, Protection );
|
||||
if( base != lpMemReserved )
|
||||
throw vm_alloc_failed_exception( base, size, lpMemReserved );
|
||||
}
|
||||
|
||||
#define VIRTUAL_FREE(ptr, size) { \
|
||||
VirtualFree(ptr, size, MEM_DECOMMIT); \
|
||||
VirtualFree(ptr, 0, MEM_RELEASE); \
|
||||
} \
|
||||
static void ReserveExtraMem( void* base, uint size )
|
||||
{
|
||||
void* pExtraMem = VirtualAlloc(base, size, MEM_RESERVE|MEM_PHYSICAL, PAGE_READWRITE);
|
||||
if( pExtraMem != base )
|
||||
throw vm_alloc_failed_exception( base, size, pExtraMem);
|
||||
}
|
||||
|
||||
int memInit() {
|
||||
|
||||
|
@ -158,72 +176,81 @@ int memInit() {
|
|||
// release the previous reserved mem
|
||||
VirtualFree(PS2MEM_BASE, 0, MEM_RELEASE);
|
||||
|
||||
// allocate all virtual memory
|
||||
PHYSICAL_ALLOC(PS2MEM_BASE, 0x02000000, s_psM);
|
||||
VIRTUAL_ALLOC(PS2MEM_ROM, 0x00400000, PAGE_READONLY);
|
||||
VIRTUAL_ALLOC(PS2MEM_ROM1, 0x00040000, PAGE_READONLY);
|
||||
VIRTUAL_ALLOC(PS2MEM_ROM2, 0x00080000, PAGE_READONLY);
|
||||
VIRTUAL_ALLOC(PS2MEM_EROM, 0x001C0000, PAGE_READONLY);
|
||||
PHYSICAL_ALLOC(PS2MEM_SCRATCH, 0x00010000, s_psS);
|
||||
PHYSICAL_ALLOC(PS2MEM_HW, 0x00010000, s_psHw);
|
||||
PHYSICAL_ALLOC(PS2MEM_PSX, 0x00200000, s_psxM);
|
||||
PHYSICAL_ALLOC(PS2MEM_VU0MICRO, 0x00010000, s_psVuMem);
|
||||
try
|
||||
{
|
||||
// allocate all virtual memory
|
||||
PHYSICAL_ALLOC(PS2MEM_BASE, 0x02000000, s_psM);
|
||||
VIRTUAL_ALLOC(PS2MEM_ROM, 0x00400000, PAGE_READONLY);
|
||||
VIRTUAL_ALLOC(PS2MEM_ROM1, 0x00040000, PAGE_READONLY);
|
||||
VIRTUAL_ALLOC(PS2MEM_ROM2, 0x00080000, PAGE_READONLY);
|
||||
VIRTUAL_ALLOC(PS2MEM_EROM, 0x001C0000, PAGE_READONLY);
|
||||
PHYSICAL_ALLOC(PS2MEM_SCRATCH, 0x00010000, s_psS);
|
||||
PHYSICAL_ALLOC(PS2MEM_HW, 0x00010000, s_psHw);
|
||||
PHYSICAL_ALLOC(PS2MEM_PSX, 0x00200000, s_psxM);
|
||||
PHYSICAL_ALLOC(PS2MEM_VU0MICRO, 0x00010000, s_psVuMem);
|
||||
|
||||
VIRTUAL_ALLOC(PS2MEM_PSXHW, 0x00010000, PAGE_READWRITE);
|
||||
//VIRTUAL_ALLOC(PS2MEM_PSXHW2, 0x00010000, PAGE_READWRITE);
|
||||
VIRTUAL_ALLOC(PS2MEM_PSXHW4, 0x00010000, PAGE_NOACCESS);
|
||||
VIRTUAL_ALLOC(PS2MEM_GS, 0x00002000, PAGE_READWRITE);
|
||||
VIRTUAL_ALLOC(PS2MEM_DEV9, 0x00010000, PAGE_NOACCESS);
|
||||
VIRTUAL_ALLOC(PS2MEM_SPU2, 0x00010000, PAGE_NOACCESS);
|
||||
VIRTUAL_ALLOC(PS2MEM_SPU2_, 0x00010000, PAGE_NOACCESS);
|
||||
VIRTUAL_ALLOC(PS2MEM_PSXHW, 0x00010000, PAGE_READWRITE);
|
||||
//VIRTUAL_ALLOC(PS2MEM_PSXHW2, 0x00010000, PAGE_READWRITE);
|
||||
VIRTUAL_ALLOC(PS2MEM_PSXHW4, 0x00010000, PAGE_NOACCESS);
|
||||
VIRTUAL_ALLOC(PS2MEM_GS, 0x00002000, PAGE_READWRITE);
|
||||
VIRTUAL_ALLOC(PS2MEM_DEV9, 0x00010000, PAGE_NOACCESS);
|
||||
VIRTUAL_ALLOC(PS2MEM_SPU2, 0x00010000, PAGE_NOACCESS);
|
||||
VIRTUAL_ALLOC(PS2MEM_SPU2_, 0x00010000, PAGE_NOACCESS);
|
||||
|
||||
VIRTUAL_ALLOC(PS2MEM_B80, 0x00010000, PAGE_READWRITE);
|
||||
VIRTUAL_ALLOC(PS2MEM_BA0, 0x00010000, PAGE_READWRITE);
|
||||
VIRTUAL_ALLOC(PS2MEM_B80, 0x00010000, PAGE_READWRITE);
|
||||
VIRTUAL_ALLOC(PS2MEM_BA0, 0x00010000, PAGE_READWRITE);
|
||||
|
||||
// reserve the left over 224Mb, don't map
|
||||
pExtraMem = VirtualAlloc(PS2MEM_BASE+0x02000000, 0x0e000000, MEM_RESERVE|MEM_PHYSICAL, PAGE_READWRITE);
|
||||
if( pExtraMem != PS2MEM_BASE+0x02000000 )
|
||||
goto eCleanupAndExit;
|
||||
// reserve the left over 224Mb, don't map
|
||||
ReserveExtraMem( PS2MEM_BASE+0x02000000, 0x0e000000 );
|
||||
|
||||
// reserve left over psx mem
|
||||
pExtraMem = VirtualAlloc(PS2MEM_PSX+0x00200000, 0x00600000, MEM_RESERVE|MEM_PHYSICAL, PAGE_READWRITE);
|
||||
if( pExtraMem != PS2MEM_PSX+0x00200000 )
|
||||
goto eCleanupAndExit;
|
||||
// reserve left over psx mem
|
||||
ReserveExtraMem( PS2MEM_PSX+0x00200000, 0x00600000 );
|
||||
|
||||
// reserve gs mem
|
||||
pExtraMem = VirtualAlloc(PS2MEM_BASE+0x20000000, 0x10000000, MEM_RESERVE|MEM_PHYSICAL, PAGE_READWRITE);
|
||||
if( pExtraMem != PS2MEM_BASE+0x20000000 )
|
||||
goto eCleanupAndExit;
|
||||
|
||||
// special addrs mmap
|
||||
VIRTUAL_ALLOC(PS2MEM_BASE+0x5fff0000, 0x10000, PAGE_READWRITE);
|
||||
// reserve gs mem
|
||||
ReserveExtraMem( PS2MEM_BASE+0x20000000, 0x10000000 );
|
||||
|
||||
// special addrs mmap
|
||||
VIRTUAL_ALLOC(PS2MEM_BASE+0x5fff0000, 0x10000, PAGE_READWRITE);
|
||||
|
||||
// alloc virtual mappings
|
||||
memLUT = (PSMEMORYMAP*)_aligned_malloc(0x100000 * sizeof(PSMEMORYMAP), 16);
|
||||
memset(memLUT, 0, sizeof(PSMEMORYMAP)*0x100000);
|
||||
for (i=0; i<0x02000; i++) memLUT[i + 0x00000] = initMemoryMap(&s_psM.aPFNs[i], &s_psM.aVFNs[i]);
|
||||
for (i=2; i<0x00010; i++) memLUT[i + 0x10000] = initMemoryMap(&s_psHw.aPFNs[i], &s_psHw.aVFNs[i]);
|
||||
for (i=0; i<0x00800; i++) memLUT[i + 0x1c000] = initMemoryMap(&s_psxM.aPFNs[(i & 0x1ff)], &s_psxM.aVFNs[(i & 0x1ff)]);
|
||||
for (i=0; i<0x00004; i++) memLUT[i + 0x11000] = initMemoryMap(&s_psVuMem.aPFNs[0], &s_psVuMem.aVFNs[0]);
|
||||
for (i=0; i<0x00004; i++) memLUT[i + 0x11004] = initMemoryMap(&s_psVuMem.aPFNs[1], &s_psVuMem.aVFNs[1]);
|
||||
for (i=0; i<0x00004; i++) memLUT[i + 0x11008] = initMemoryMap(&s_psVuMem.aPFNs[4+i], &s_psVuMem.aVFNs[4+i]);
|
||||
for (i=0; i<0x00004; i++) memLUT[i + 0x1100c] = initMemoryMap(&s_psVuMem.aPFNs[8+i], &s_psVuMem.aVFNs[8+i]);
|
||||
// alloc virtual mappings
|
||||
memLUT = (PSMEMORYMAP*)_aligned_malloc(0x100000 * sizeof(PSMEMORYMAP), 16);
|
||||
if( memLUT == NULL )
|
||||
throw std::bad_alloc();
|
||||
|
||||
for (i=0; i<0x00004; i++) memLUT[i + 0x50000] = initMemoryMap(&s_psS.aPFNs[i], &s_psS.aVFNs[i]);
|
||||
memset(memLUT, 0, sizeof(PSMEMORYMAP)*0x100000);
|
||||
for (i=0; i<0x02000; i++) memLUT[i + 0x00000] = initMemoryMap(&s_psM.aPFNs[i], &s_psM.aVFNs[i]);
|
||||
for (i=2; i<0x00010; i++) memLUT[i + 0x10000] = initMemoryMap(&s_psHw.aPFNs[i], &s_psHw.aVFNs[i]);
|
||||
for (i=0; i<0x00800; i++) memLUT[i + 0x1c000] = initMemoryMap(&s_psxM.aPFNs[(i & 0x1ff)], &s_psxM.aVFNs[(i & 0x1ff)]);
|
||||
for (i=0; i<0x00004; i++) memLUT[i + 0x11000] = initMemoryMap(&s_psVuMem.aPFNs[0], &s_psVuMem.aVFNs[0]);
|
||||
for (i=0; i<0x00004; i++) memLUT[i + 0x11004] = initMemoryMap(&s_psVuMem.aPFNs[1], &s_psVuMem.aVFNs[1]);
|
||||
for (i=0; i<0x00004; i++) memLUT[i + 0x11008] = initMemoryMap(&s_psVuMem.aPFNs[4+i], &s_psVuMem.aVFNs[4+i]);
|
||||
for (i=0; i<0x00004; i++) memLUT[i + 0x1100c] = initMemoryMap(&s_psVuMem.aPFNs[8+i], &s_psVuMem.aVFNs[8+i]);
|
||||
|
||||
// map to other modes
|
||||
memcpy(memLUT+0x80000, memLUT, 0x20000*sizeof(PSMEMORYMAP));
|
||||
memcpy(memLUT+0xa0000, memLUT, 0x20000*sizeof(PSMEMORYMAP));
|
||||
for (i=0; i<0x00004; i++) memLUT[i + 0x50000] = initMemoryMap(&s_psS.aPFNs[i], &s_psS.aVFNs[i]);
|
||||
|
||||
if (psxInit() == -1)
|
||||
goto eCleanupAndExit;
|
||||
// map to other modes
|
||||
memcpy(memLUT+0x80000, memLUT, 0x20000*sizeof(PSMEMORYMAP));
|
||||
memcpy(memLUT+0xa0000, memLUT, 0x20000*sizeof(PSMEMORYMAP));
|
||||
|
||||
return 0;
|
||||
if(psxInit() == -1)
|
||||
throw std::bad_alloc( "IOP memory allocations failed" );
|
||||
|
||||
eCleanupAndExit:
|
||||
if( pExtraMem != NULL )
|
||||
VirtualFree(pExtraMem, 0x0e000000, MEM_RELEASE);
|
||||
memShutdown();
|
||||
return 0;
|
||||
}
|
||||
catch( vm_alloc_failed_exception& ex )
|
||||
{
|
||||
Console::Error( "Virtual Memory Error > Cannot reserve %dk memory block at 0x%8.8x",
|
||||
ex.requested_size / 1024, ex.requested_addr );
|
||||
|
||||
Console::Error( "\tError code: %d \tReturned address: 0x%8.8x",
|
||||
GetLastError(), ex.returned_addr);
|
||||
|
||||
memShutdown();
|
||||
}
|
||||
catch( std::exception& )
|
||||
{
|
||||
memShutdown();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -234,31 +261,34 @@ void memShutdown()
|
|||
VirtualFree(PS2MEM_BASE+0x20000000, 0, MEM_RELEASE);
|
||||
|
||||
PHYSICAL_FREE(PS2MEM_BASE, 0x02000000, s_psM);
|
||||
VIRTUAL_FREE(PS2MEM_ROM, 0x00400000);
|
||||
VIRTUAL_FREE(PS2MEM_ROM1, 0x00080000);
|
||||
VIRTUAL_FREE(PS2MEM_ROM2, 0x00080000);
|
||||
VIRTUAL_FREE(PS2MEM_EROM, 0x001C0000);
|
||||
SysMunmap(PS2MEM_ROM, 0x00400000);
|
||||
SysMunmap(PS2MEM_ROM1, 0x00080000);
|
||||
SysMunmap(PS2MEM_ROM2, 0x00080000);
|
||||
SysMunmap(PS2MEM_EROM, 0x001C0000);
|
||||
PHYSICAL_FREE(PS2MEM_SCRATCH, 0x00010000, s_psS);
|
||||
PHYSICAL_FREE(PS2MEM_HW, 0x00010000, s_psHw);
|
||||
PHYSICAL_FREE(PS2MEM_PSX, 0x00200000, s_psxM);
|
||||
PHYSICAL_FREE(PS2MEM_VU0MICRO, 0x00010000, s_psVuMem);
|
||||
|
||||
VIRTUAL_FREE(PS2MEM_VU0MICRO, 0x00010000); // allocate for all VUs
|
||||
SysMunmap(PS2MEM_VU0MICRO, 0x00010000); // allocate for all VUs
|
||||
|
||||
VIRTUAL_FREE(PS2MEM_PSXHW, 0x00010000);
|
||||
//VIRTUAL_FREE(PS2MEM_PSXHW2, 0x00010000);
|
||||
VIRTUAL_FREE(PS2MEM_PSXHW4, 0x00010000);
|
||||
VIRTUAL_FREE(PS2MEM_GS, 0x00010000);
|
||||
VIRTUAL_FREE(PS2MEM_DEV9, 0x00010000);
|
||||
VIRTUAL_FREE(PS2MEM_SPU2, 0x00010000);
|
||||
VIRTUAL_FREE(PS2MEM_SPU2_, 0x00010000);
|
||||
SysMunmap(PS2MEM_PSXHW, 0x00010000);
|
||||
//SysMunmap(PS2MEM_PSXHW2, 0x00010000);
|
||||
SysMunmap(PS2MEM_PSXHW4, 0x00010000);
|
||||
SysMunmap(PS2MEM_GS, 0x00010000);
|
||||
SysMunmap(PS2MEM_DEV9, 0x00010000);
|
||||
SysMunmap(PS2MEM_SPU2, 0x00010000);
|
||||
SysMunmap(PS2MEM_SPU2_, 0x00010000);
|
||||
|
||||
VIRTUAL_FREE(PS2MEM_B80, 0x00010000);
|
||||
VIRTUAL_FREE(PS2MEM_BA0, 0x00010000);
|
||||
SysMunmap(PS2MEM_B80, 0x00010000);
|
||||
SysMunmap(PS2MEM_BA0, 0x00010000);
|
||||
|
||||
// Special Addrs.. ?
|
||||
SysMunmap(PS2MEM_BASE+0x5fff0000, 0x10000);
|
||||
|
||||
VirtualFree(PS2MEM_VU0MICRO, 0, MEM_RELEASE);
|
||||
|
||||
_aligned_free(memLUT); memLUT = NULL;
|
||||
safe_aligned_free( memLUT );
|
||||
|
||||
// reserve mem
|
||||
VirtualAlloc(PS2MEM_BASE, 0x40000000, MEM_RESERVE, PAGE_NOACCESS);
|
||||
|
@ -386,7 +416,7 @@ int SysPageFaultExceptionFilter(EXCEPTION_POINTERS* eps)
|
|||
if( SysMapUserPhysicalPages((void*)curvaddr, 1, pmap->aPFNs, 0) )
|
||||
return EXCEPTION_CONTINUE_EXECUTION;
|
||||
|
||||
SysPrintf("Fatal error, virtual page 0x%x cannot be found %d (p:%x,v:%x)\n",
|
||||
Console::Error("Virtual Memory Error > page 0x%x cannot be found %d (p:%x,v:%x)\n",
|
||||
addr-(u32)PS2MEM_BASE, GetLastError(), pmap->aPFNs[0], curvaddr);
|
||||
}
|
||||
}
|
||||
|
@ -2438,6 +2468,7 @@ int __fastcall vuMicroRead8(u32 addr,mem8_t* data)
|
|||
*data=vu->Micro[addr];
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<int vunum>
|
||||
int __fastcall vuMicroRead16(u32 addr,mem16_t* data)
|
||||
{
|
||||
|
@ -2447,6 +2478,7 @@ int __fastcall vuMicroRead16(u32 addr,mem16_t* data)
|
|||
*data=*(u16*)&vu->Micro[addr];
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<int vunum>
|
||||
int __fastcall vuMicroRead32(u32 addr,mem32_t* data)
|
||||
{
|
||||
|
@ -2456,6 +2488,7 @@ int __fastcall vuMicroRead32(u32 addr,mem32_t* data)
|
|||
*data=*(u32*)&vu->Micro[addr];
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<int vunum>
|
||||
int __fastcall vuMicroRead64(u32 addr,mem64_t* data)
|
||||
{
|
||||
|
@ -2465,6 +2498,7 @@ int __fastcall vuMicroRead64(u32 addr,mem64_t* data)
|
|||
*data=*(u64*)&vu->Micro[addr];
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<int vunum>
|
||||
int __fastcall vuMicroRead128(u32 addr,mem128_t* data)
|
||||
{
|
||||
|
@ -2475,6 +2509,7 @@ int __fastcall vuMicroRead128(u32 addr,mem128_t* data)
|
|||
data[1]=*(u64*)&vu->Micro[addr+8];
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<int vunum>
|
||||
void __fastcall vuMicroWrite8(u32 addr,mem8_t data)
|
||||
{
|
||||
|
@ -2491,6 +2526,7 @@ void __fastcall vuMicroWrite8(u32 addr,mem8_t data)
|
|||
Cpu->ClearVU1(addr&(~7),1);
|
||||
}
|
||||
}
|
||||
|
||||
template<int vunum>
|
||||
void __fastcall vuMicroWrite16(u32 addr,mem16_t data)
|
||||
{
|
||||
|
@ -2507,6 +2543,7 @@ void __fastcall vuMicroWrite16(u32 addr,mem16_t data)
|
|||
Cpu->ClearVU1(addr&(~7),1);
|
||||
}
|
||||
}
|
||||
|
||||
template<int vunum>
|
||||
void __fastcall vuMicroWrite32(u32 addr,mem32_t data)
|
||||
{
|
||||
|
@ -2523,6 +2560,7 @@ void __fastcall vuMicroWrite32(u32 addr,mem32_t data)
|
|||
Cpu->ClearVU1(addr&(~7),1);
|
||||
}
|
||||
}
|
||||
|
||||
template<int vunum>
|
||||
void __fastcall vuMicroWrite64(u32 addr,const mem64_t* data)
|
||||
{
|
||||
|
@ -2539,6 +2577,7 @@ void __fastcall vuMicroWrite64(u32 addr,const mem64_t* data)
|
|||
Cpu->ClearVU1(addr,1);
|
||||
}
|
||||
}
|
||||
|
||||
template<int vunum>
|
||||
void __fastcall vuMicroWrite128(u32 addr,const mem128_t* data)
|
||||
{
|
||||
|
@ -2556,6 +2595,7 @@ void __fastcall vuMicroWrite128(u32 addr,const mem128_t* data)
|
|||
Cpu->ClearVU1(addr,2);
|
||||
}
|
||||
}
|
||||
|
||||
int memInit()
|
||||
{
|
||||
if (!vtlb_Init())
|
||||
|
@ -2698,6 +2738,7 @@ int memReset() {
|
|||
memset(PS2MEM_BASE, 0, 0x02000000);
|
||||
memset(PS2MEM_SCRATCH, 0, 0x00004000);
|
||||
#else
|
||||
vtlb_Reset();
|
||||
memset(psM, 0, 0x02000000);
|
||||
memset(psS, 0, 0x00004000);
|
||||
#endif
|
||||
|
@ -2705,7 +2746,7 @@ int memReset() {
|
|||
CombinePaths( Bios, Config.BiosDir, Config.Bios );
|
||||
|
||||
if (stat(Bios, &buf) == -1) {
|
||||
SysMessage(_("Unable to load bios: '%s', PCSX2 can't run without that"), Bios);
|
||||
Console::Error(_("Unable to load bios: '%s', PCSX2 can't run without that"), Bios);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2731,7 +2772,7 @@ int memReset() {
|
|||
fclose(fp);
|
||||
|
||||
BiosVersion = GetBiosVersion();
|
||||
SysPrintf("Bios Version %d.%d\n", BiosVersion >> 8, BiosVersion & 0xff);
|
||||
Console::Notice("Bios Version %d.%d\n", BiosVersion >> 8, BiosVersion & 0xff);
|
||||
|
||||
//injectIRX("host.irx"); //not fully tested; still buggy
|
||||
|
||||
|
@ -2784,6 +2825,7 @@ int mmap_GetRamPageInfo(void* ptr)
|
|||
offset>>=12;
|
||||
return (psMPWC[(offset/32)]&(1<<(offset&31)))?1:0;
|
||||
}
|
||||
|
||||
void mmap_MarkCountedRamPage(void* ptr,u32 vaddr)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
@ -2805,7 +2847,7 @@ void mmap_MarkCountedRamPage(void* ptr,u32 vaddr)
|
|||
}
|
||||
void mmap_ResetBlockTracking()
|
||||
{
|
||||
SysPrintf("vtlb/mmap: Block Tracking reseted ..\n");
|
||||
Console::WriteLn("vtlb/mmap: Block Tracking reseted ..");
|
||||
memset(psMPWC,0,sizeof(psMPWC));
|
||||
for(u32 i=0;i<(0x02000000>>12);i++)
|
||||
{
|
||||
|
@ -2822,16 +2864,16 @@ void mmap_ResetBlockTracking()
|
|||
#ifdef _WIN32
|
||||
int SysPageFaultExceptionFilter(EXCEPTION_POINTERS* eps)
|
||||
{
|
||||
struct _EXCEPTION_RECORD* ExceptionRecord = eps->ExceptionRecord;
|
||||
struct _CONTEXT* ContextRecord = eps->ContextRecord;
|
||||
const _EXCEPTION_RECORD& ExceptionRecord = *eps->ExceptionRecord;
|
||||
//const _CONTEXT& ContextRecord = *eps->ContextRecord;
|
||||
|
||||
if (eps->ExceptionRecord->ExceptionCode != EXCEPTION_ACCESS_VIOLATION)
|
||||
if (ExceptionRecord.ExceptionCode != EXCEPTION_ACCESS_VIOLATION)
|
||||
{
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
|
||||
// get bad virtual address
|
||||
u32 offset = (u8*)eps->ExceptionRecord->ExceptionInformation[1]-psM;
|
||||
u32 offset = (u8*)ExceptionRecord.ExceptionInformation[1]-psM;
|
||||
|
||||
if (offset>=0x02000000)
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
|
|
480
pcsx2/Misc.c
480
pcsx2/Misc.c
|
@ -45,11 +45,6 @@
|
|||
|
||||
#include "Paths.h"
|
||||
|
||||
u32 dwCurSaveStateVer = 0;
|
||||
extern u32 s_iLastCOP0Cycle;
|
||||
extern u32 s_iLastPERFCycle[2];
|
||||
extern int g_psxWriteOk;
|
||||
|
||||
PcsxConfig Config;
|
||||
u32 BiosVersion;
|
||||
char CdromId[12];
|
||||
|
@ -318,7 +313,7 @@ int GetPS2ElfName(char *name){
|
|||
|
||||
// check if the file exists
|
||||
if (CDVD_findfile("SYSTEM.CNF;1", &tocEntry) != TRUE){
|
||||
SysPrintf("SYSTEM.CNF not found\n");
|
||||
Console::Error("Boot Error > SYSTEM.CNF not found");
|
||||
return 0;//could not find; not a PS/PS2 cdvd
|
||||
}
|
||||
|
||||
|
@ -327,16 +322,12 @@ int GetPS2ElfName(char *name){
|
|||
CDVDFS_close(f);
|
||||
|
||||
buffer[tocEntry.fileSize]='\0';
|
||||
// SysPrintf(
|
||||
// "---------------------SYSTEM.CNF---------------------\n"
|
||||
// "%s"
|
||||
// "----------------------------------------------------\n", buffer);
|
||||
|
||||
pos=strstr(buffer, "BOOT2");
|
||||
if (pos==NULL){
|
||||
pos=strstr(buffer, "BOOT");
|
||||
if (pos==NULL) {
|
||||
SysPrintf("This is not a PS2 game!\n");
|
||||
Console::Error("Boot Error > This is not a PS2 game!");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
|
@ -359,7 +350,7 @@ int GetPS2ElfName(char *name){
|
|||
if (fp) {
|
||||
u32 addr;
|
||||
|
||||
SysPrintf("Loading System.map\n", fp);
|
||||
Console::WriteLn("Loading System.map...");
|
||||
while (!feof(fp)) {
|
||||
fseek(fp, 8, SEEK_CUR);
|
||||
buffer[0] = '0'; buffer[1] = 'x';
|
||||
|
@ -381,370 +372,78 @@ int GetPS2ElfName(char *name){
|
|||
return 2;
|
||||
}
|
||||
|
||||
// STATES
|
||||
|
||||
#define STATE_VERSION "STv6"
|
||||
const char Pcsx2Header[32] = STATE_VERSION " PCSX2 " PCSX2_VERSION;
|
||||
|
||||
#define _PS2Esave(type) \
|
||||
if (type##freeze(FREEZE_SIZE, &fP) == -1) { \
|
||||
gzclose(f); \
|
||||
return -1; \
|
||||
} \
|
||||
fP.data = (s8*)malloc(fP.size); \
|
||||
if (fP.data == NULL) return -1; \
|
||||
\
|
||||
if (type##freeze(FREEZE_SAVE, &fP) == -1) { \
|
||||
gzclose(f); \
|
||||
return -1; \
|
||||
} \
|
||||
\
|
||||
gzwrite(f, &fP.size, sizeof(fP.size)); \
|
||||
if (fP.size) { \
|
||||
gzwrite(f, fP.data, fP.size); \
|
||||
free(fP.data); \
|
||||
}
|
||||
|
||||
#define _PS2Eload(type) \
|
||||
gzread(f, &fP.size, sizeof(fP.size)); \
|
||||
if (fP.size) { \
|
||||
fP.data = (s8*)malloc(fP.size); \
|
||||
if (fP.data == NULL) return -1; \
|
||||
gzread(f, fP.data, fP.size); \
|
||||
} \
|
||||
if (type##freeze(FREEZE_LOAD, &fP) == -1) { \
|
||||
/* skip */ \
|
||||
/*if (fP.size) free(fP.data); \
|
||||
gzclose(f); \
|
||||
return -1;*/ \
|
||||
} \
|
||||
if (fP.size) free(fP.data);
|
||||
|
||||
|
||||
int SaveState(const char *file) {
|
||||
|
||||
gzFile f;
|
||||
freezeData fP;
|
||||
|
||||
gsWaitGS();
|
||||
|
||||
SysPrintf("SaveState: %s\n", file);
|
||||
f = gzopen(file, "wb");
|
||||
if (f == NULL) return -1;
|
||||
|
||||
gzwrite(f, &g_SaveVersion, 4);
|
||||
|
||||
gzwrite(f, PS2MEM_BASE, 0x02000000); // 32 MB main memory
|
||||
gzwrite(f, PS2MEM_ROM, 0x00400000); // 4 mb rom memory
|
||||
gzwrite(f, PS2MEM_ROM1,0x00040000); // 256kb rom1 memory
|
||||
gzwrite(f, PS2MEM_SCRATCH, 0x00004000); // scratch pad
|
||||
|
||||
gzwrite(f, PS2MEM_HW, 0x00010000); // hardware memory
|
||||
|
||||
gzwrite(f, (void*)&cpuRegs, sizeof(cpuRegs)); // cpu regs + COP0
|
||||
gzwrite(f, (void*)&psxRegs, sizeof(psxRegs)); // iop regs]
|
||||
gzwrite(f, (void*)&fpuRegs, sizeof(fpuRegs)); // fpu regs
|
||||
gzwrite(f, (void*)&tlb, sizeof(tlb)); // tlbs
|
||||
|
||||
gzwrite(f, &EEsCycle, sizeof(EEsCycle));
|
||||
gzwrite(f, &EEoCycle, sizeof(EEoCycle));
|
||||
gzwrite(f, &psxRegs.cycle, sizeof(u32)); // used to be IOPoCycle. This retains compatibility.
|
||||
gzwrite(f, &g_nextBranchCycle, sizeof(g_nextBranchCycle));
|
||||
gzwrite(f, &g_psxNextBranchCycle, sizeof(g_psxNextBranchCycle));
|
||||
|
||||
gzwrite(f, &s_iLastCOP0Cycle, sizeof(s_iLastCOP0Cycle));
|
||||
gzwrite(f, s_iLastPERFCycle, sizeof(u32)*2);
|
||||
gzwrite(f, &g_psxWriteOk, sizeof(g_psxWriteOk));
|
||||
|
||||
//hope didn't forgot any cpu....
|
||||
|
||||
rcntFreeze(f, 1);
|
||||
gsFreeze(f, 1);
|
||||
vu0Freeze(f, 1);
|
||||
vu1Freeze(f, 1);
|
||||
vif0Freeze(f, 1);
|
||||
vif1Freeze(f, 1);
|
||||
sifFreeze(f, 1);
|
||||
ipuFreeze(f, 1);
|
||||
|
||||
// iop now
|
||||
gzwrite(f, psxM, 0x00200000); // 2 MB main memory
|
||||
//gzwrite(f, psxP, 0x00010000); // pralell memory
|
||||
gzwrite(f, psxH, 0x00010000); // hardware memory
|
||||
//gzwrite(f, psxS, 0x00010000); // sif memory
|
||||
|
||||
sioFreeze(f, 1);
|
||||
cdrFreeze(f, 1);
|
||||
cdvdFreeze(f, 1);
|
||||
psxRcntFreeze(f, 1);
|
||||
//mdecFreeze(f, 1);
|
||||
sio2Freeze(f, 1);
|
||||
|
||||
SysPrintf("Saving GS\n");
|
||||
if( CHECK_MULTIGS ) {
|
||||
// have to call in thread, otherwise weird stuff will start happening
|
||||
u64 uf = (uptr)f;
|
||||
GSRingBufSimplePacket(GS_RINGTYPE_SAVE, (u32)(uf&0xffffffff), (u32)(uf>>32), 0);
|
||||
gsWaitGS();
|
||||
}
|
||||
else {
|
||||
_PS2Esave(GS);
|
||||
}
|
||||
SysPrintf("Saving SPU2\n");
|
||||
_PS2Esave(SPU2);
|
||||
SysPrintf("Saving DEV9\n");
|
||||
_PS2Esave(DEV9);
|
||||
SysPrintf("Saving USB\n");
|
||||
_PS2Esave(USB);
|
||||
SysPrintf("Saving ok\n");
|
||||
|
||||
gzclose(f);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern u32 dumplog;
|
||||
u32 s_vucount=0;
|
||||
|
||||
int LoadState(const char *file) {
|
||||
|
||||
gzFile f;
|
||||
freezeData fP;
|
||||
int i;
|
||||
u32 dud; // for loading unused vars.
|
||||
#ifdef PCSX2_VIRTUAL_MEM
|
||||
DWORD OldProtect;
|
||||
#endif
|
||||
|
||||
#ifdef _DEBUG
|
||||
s_vucount = 0;
|
||||
#endif
|
||||
|
||||
SysPrintf("LoadState: %s\n", file);
|
||||
f = gzopen(file, "rb");
|
||||
if (f == NULL) return -1;
|
||||
|
||||
gzread(f, &dwCurSaveStateVer, 4);
|
||||
|
||||
if( dwCurSaveStateVer != g_SaveVersion ) {
|
||||
|
||||
#ifdef PCSX2_VIRTUAL_MEM
|
||||
if( dwCurSaveStateVer >= 0x8b400000 )
|
||||
{
|
||||
gzclose(f);
|
||||
SysPrintf(
|
||||
"Savestate load aborted:\n"
|
||||
" VM edition cannot safely load savestates created by the VTLB edition.\n" );
|
||||
return 0;
|
||||
}
|
||||
// pcsx2 vm supports opening these formats
|
||||
if( dwCurSaveStateVer < 0x7a30000d) {
|
||||
gzclose(f);
|
||||
SysPrintf("Unsupported savestate version: %x.\n", dwCurSaveStateVer );
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
gzclose(f);
|
||||
SysPrintf(
|
||||
"Savestate load aborted:\n"
|
||||
" VTLB edition cannot safely load savestates created by the VM edition.\n" );
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
// stop and reset the system first
|
||||
gsWaitGS();
|
||||
|
||||
for (i=0; i<48; i++) UnmapTLB(i);
|
||||
|
||||
Cpu->Reset();
|
||||
recResetVU0();
|
||||
recResetVU1();
|
||||
psxCpu->Reset();
|
||||
|
||||
SysPrintf("Loading memory\n");
|
||||
|
||||
#ifdef PCSX2_VIRTUAL_MEM
|
||||
// make sure can write
|
||||
VirtualProtect(PS2MEM_ROM, 0x00400000, PAGE_READWRITE, &OldProtect);
|
||||
VirtualProtect(PS2MEM_ROM1, 0x00040000, PAGE_READWRITE, &OldProtect);
|
||||
VirtualProtect(PS2MEM_ROM2, 0x00080000, PAGE_READWRITE, &OldProtect);
|
||||
VirtualProtect(PS2MEM_EROM, 0x001C0000, PAGE_READWRITE, &OldProtect);
|
||||
#endif
|
||||
|
||||
gzread(f, PS2MEM_BASE, 0x02000000); // 32 MB main memory
|
||||
gzread(f, PS2MEM_ROM, 0x00400000); // 4 mb rom memory
|
||||
gzread(f, PS2MEM_ROM1,0x00040000); // 256kb rom1 memory
|
||||
gzread(f, PS2MEM_SCRATCH, 0x00004000); // scratch pad
|
||||
|
||||
#ifdef PCSX2_VIRTUAL_MEM
|
||||
VirtualProtect(PS2MEM_ROM, 0x00400000, PAGE_READONLY, &OldProtect);
|
||||
VirtualProtect(PS2MEM_ROM1, 0x00040000, PAGE_READONLY, &OldProtect);
|
||||
VirtualProtect(PS2MEM_ROM2, 0x00080000, PAGE_READONLY, &OldProtect);
|
||||
VirtualProtect(PS2MEM_EROM, 0x001C0000, PAGE_READONLY, &OldProtect);
|
||||
#endif
|
||||
|
||||
gzread(f, PS2MEM_HW, 0x00010000); // hardware memory
|
||||
|
||||
SysPrintf("Loading structs\n");
|
||||
gzread(f, (void*)&cpuRegs, sizeof(cpuRegs)); // cpu regs + COP0
|
||||
gzread(f, (void*)&psxRegs, sizeof(psxRegs)); // iop regs
|
||||
gzread(f, (void*)&fpuRegs, sizeof(fpuRegs)); // fpu regs
|
||||
gzread(f, (void*)&tlb, sizeof(tlb)); // tlbs
|
||||
gzread(f, &EEsCycle, sizeof(EEsCycle));
|
||||
gzread(f, &EEoCycle, sizeof(EEoCycle));
|
||||
gzread(f, &dud, sizeof(u32)); // was IOPoCycle
|
||||
gzread(f, &g_nextBranchCycle, sizeof(g_nextBranchCycle));
|
||||
gzread(f, &g_psxNextBranchCycle, sizeof(g_psxNextBranchCycle));
|
||||
|
||||
gzread(f, &s_iLastCOP0Cycle, sizeof(s_iLastCOP0Cycle));
|
||||
if( dwCurSaveStateVer >= 0x7a30000e ) {
|
||||
gzread(f, s_iLastPERFCycle, sizeof(u32)*2);
|
||||
}
|
||||
gzread(f, &g_psxWriteOk, sizeof(g_psxWriteOk));
|
||||
|
||||
rcntFreeze(f, 0);
|
||||
gsFreeze(f, 0);
|
||||
vu0Freeze(f, 0);
|
||||
vu1Freeze(f, 0);
|
||||
vif0Freeze(f, 0);
|
||||
vif1Freeze(f, 0);
|
||||
sifFreeze(f, 0);
|
||||
ipuFreeze(f, 0);
|
||||
|
||||
// iop now
|
||||
SysPrintf("Loading iop mem\n");
|
||||
gzread(f, psxM, 0x00200000); // 2 MB main memory
|
||||
//gzread(f, psxP, 0x00010000); // pralell memory
|
||||
gzread(f, psxH, 0x00010000); // hardware memory
|
||||
//gzread(f, psxS, 0x00010000); // sif memory
|
||||
|
||||
SysPrintf("Loading iop stuff\n");
|
||||
sioFreeze(f, 0);
|
||||
cdrFreeze(f, 0);
|
||||
cdvdFreeze(f, 0);
|
||||
psxRcntFreeze(f, 0);
|
||||
//mdecFreeze(f, 0);
|
||||
sio2Freeze(f, 0);
|
||||
|
||||
SysPrintf("Loading GS\n");
|
||||
if( CHECK_MULTIGS ) {
|
||||
// have to call in thread, otherwise weird stuff will start happening
|
||||
u64 uf = (uptr)f;
|
||||
GSRingBufSimplePacket(GS_RINGTYPE_LOAD, (u32)(uf&0xffffffff), (u32)(uf>>32), 0);
|
||||
gsWaitGS();
|
||||
}
|
||||
else {
|
||||
_PS2Eload(GS);
|
||||
}
|
||||
SysPrintf("Loading SPU2\n");
|
||||
_PS2Eload(SPU2);
|
||||
SysPrintf("Loading DEV9\n");
|
||||
_PS2Eload(DEV9);
|
||||
SysPrintf("Loading USB\n");
|
||||
_PS2Eload(USB);
|
||||
|
||||
SysPrintf("Loading ok\n");
|
||||
|
||||
gzclose(f);
|
||||
memset(pCache,0,sizeof(_cacheS)*64);
|
||||
|
||||
//dumplog |= 4;
|
||||
WriteCP0Status(cpuRegs.CP0.n.Status.val);
|
||||
for (i=0; i<48; i++) MapTLB(i);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
|
||||
int SaveGSState(const char *file)
|
||||
void SaveGSState(const char *file)
|
||||
{
|
||||
if( g_SaveGSStream ) return -1;
|
||||
if( g_SaveGSStream ) return;
|
||||
|
||||
SysPrintf("SaveGSState: %s\n", file);
|
||||
g_fGSSave = gzopen(file, "wb");
|
||||
if (g_fGSSave == NULL) return -1;
|
||||
Console::Write( "SaveGSState: " ); Console::WriteLn( file );
|
||||
g_fGSSave = new gzSavingState( file );
|
||||
|
||||
g_SaveGSStream = 1;
|
||||
g_nLeftGSFrames = 2;
|
||||
|
||||
gzwrite(g_fGSSave, &g_nLeftGSFrames, sizeof(g_nLeftGSFrames));
|
||||
|
||||
return 0;
|
||||
g_fGSSave->Freeze( g_nLeftGSFrames );
|
||||
}
|
||||
|
||||
extern uptr pDsp;
|
||||
int LoadGSState(const char *file)
|
||||
void LoadGSState(const char *file)
|
||||
{
|
||||
int ret;
|
||||
gzFile f;
|
||||
freezeData fP;
|
||||
gzLoadingState* f;
|
||||
|
||||
f = gzopen(file, "rb");
|
||||
if( f == NULL )
|
||||
Console::Write( "LoadGSState: " );
|
||||
|
||||
try
|
||||
{
|
||||
f = new gzLoadingState( file );
|
||||
Console::WriteLn( file );
|
||||
}
|
||||
catch( Exception::FileNotFound& )
|
||||
{
|
||||
// file not found? try prefixing with sstates folder:
|
||||
if( !isPathRooted( file ) )
|
||||
{
|
||||
// file not found? try prefixing with sstates folder:
|
||||
char strfile[g_MaxPath];
|
||||
CombinePaths( strfile, SSTATES_DIR, file );
|
||||
f = gzopen(strfile, "rb");
|
||||
file = strfile;
|
||||
f = new gzLoadingState( file );
|
||||
Console::WriteLn( strfile );
|
||||
|
||||
// If this load attempt fails, then let the exception bubble up to
|
||||
// the caller to deal with...
|
||||
}
|
||||
}
|
||||
|
||||
if( f == NULL ) {
|
||||
SysPrintf("Failed to find gs state\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
SysPrintf("LoadGSState: %s\n", file);
|
||||
|
||||
// Always set gsIrq callback -- GS States are always exclusionary of MTGS mode
|
||||
GSirqCallback( gsIrq );
|
||||
|
||||
ret = GSopen(&pDsp, "PCSX2", 0);
|
||||
if (ret != 0) {
|
||||
SysMessage (_("Error Opening GS Plugin"));
|
||||
return -1;
|
||||
if (ret != 0)
|
||||
{
|
||||
delete f;
|
||||
throw Exception::PluginFailure( "GS", "Error opening" );
|
||||
}
|
||||
|
||||
ret = PAD1open((void *)&pDsp);
|
||||
|
||||
gzread(f, &g_nLeftGSFrames, sizeof(g_nLeftGSFrames));
|
||||
f->Freeze(g_nLeftGSFrames);
|
||||
f->gsFreeze();
|
||||
|
||||
gsFreeze(f, 0);
|
||||
_PS2Eload(GS);
|
||||
f->FreezePlugin( "GS", GSfreeze );
|
||||
|
||||
RunGSState(f);
|
||||
gzclose(f);
|
||||
RunGSState( *f );
|
||||
|
||||
delete( f );
|
||||
|
||||
GSclose();
|
||||
PAD1close();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int CheckState(const char *file) {
|
||||
gzFile f;
|
||||
char header[32];
|
||||
|
||||
f = gzopen(file, "rb");
|
||||
if (f == NULL) return -1;
|
||||
|
||||
gzread(f, header, 32);
|
||||
|
||||
gzclose(f);
|
||||
|
||||
if (strncmp(STATE_VERSION " PCSX2", header, 10)) return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct LangDef {
|
||||
char id[8];
|
||||
char name[64];
|
||||
|
@ -805,13 +504,6 @@ char* mystrlwr( char* string )
|
|||
return string;
|
||||
}
|
||||
|
||||
static void GetSaveStateFilename( char* dest )
|
||||
{
|
||||
char elfcrcText[72];
|
||||
sprintf( elfcrcText, "%8.8X.%3.3d", ElfCRC, StatesC );
|
||||
CombinePaths( dest, SSTATES_DIR, elfcrcText );
|
||||
}
|
||||
|
||||
static void GetGSStateFilename( char* dest )
|
||||
{
|
||||
char gsText[72];
|
||||
|
@ -821,31 +513,76 @@ static void GetGSStateFilename( char* dest )
|
|||
|
||||
void ProcessFKeys(int fkey, int shift)
|
||||
{
|
||||
int ret;
|
||||
char Text[g_MaxPath];
|
||||
|
||||
assert(fkey >= 1 && fkey <= 12 );
|
||||
|
||||
switch(fkey) {
|
||||
case 1:
|
||||
GetSaveStateFilename(Text);
|
||||
ret = SaveState(Text);
|
||||
try
|
||||
{
|
||||
SaveState::GetFilename( Text, StatesC );
|
||||
gzSavingState(Text).FreezeAll();
|
||||
}
|
||||
catch( std::exception& ex )
|
||||
{
|
||||
// 99% of the time this is a file permission error and the
|
||||
// cpu state is intact so just display a passive msg to console.
|
||||
|
||||
Console::Error( _( "Error > Could not save state to slot %d" ), StatesC );
|
||||
Console::Error( ex.what() );
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if( shift )
|
||||
StatesC = (StatesC+NUM_STATES-1)%NUM_STATES;
|
||||
StatesC = (StatesC+NUM_STATES-1) % NUM_STATES;
|
||||
else
|
||||
StatesC = (StatesC+1)%NUM_STATES;
|
||||
SysPrintf("*PCSX2*: Selected State %ld\n", StatesC);
|
||||
StatesC = (StatesC+1) % NUM_STATES;
|
||||
|
||||
Console::Notice( _( " > Selected savestate slot %d" ), StatesC+1);
|
||||
|
||||
if( GSchangeSaveState != NULL ) {
|
||||
GetSaveStateFilename(Text);
|
||||
SaveState::GetFilename(Text, StatesC);
|
||||
GSchangeSaveState(StatesC, Text);
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
GetSaveStateFilename(Text);
|
||||
ret = LoadState(Text);
|
||||
break;
|
||||
try
|
||||
{
|
||||
SaveState::GetFilename( Text, StatesC );
|
||||
gzLoadingState joe(Text); // throws exception on version mismatch
|
||||
cpuReset();
|
||||
joe.FreezeAll();
|
||||
}
|
||||
catch( Exception::UnsupportedStateVersion& )
|
||||
{
|
||||
// At this point the cpu hasn't been reset, so we can return
|
||||
// control to the user safely...
|
||||
}
|
||||
catch( Exception::FileNotFound& )
|
||||
{
|
||||
Console::Notice( _("Saveslot %d cannot be loaded; slot does not exist (file not found)"), StatesC );
|
||||
}
|
||||
catch( std::runtime_error& ex )
|
||||
{
|
||||
// This is the bad one. Chances are the cpu has been reset, so emulation has
|
||||
// to be aborted. Sorry user! We'll give you some info for your trouble:
|
||||
|
||||
Console::Error( _("An error occured while trying to load saveslot %d"), StatesC );
|
||||
Console::Error( ex.what() );
|
||||
SysMessage(
|
||||
"Pcsx2 encountered an error while trying to load the savestate\n"
|
||||
"and emulation had to be aborted." );
|
||||
|
||||
cpuShutdown();
|
||||
ClosePlugins();
|
||||
|
||||
throw Exception::CpuStateShutdown(
|
||||
"Saveslot load failed; PS2 emulated state had to be shut down." ); // let the GUI handle the error "gracefully"
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
{
|
||||
|
@ -875,7 +612,7 @@ void ProcessFKeys(int fkey, int shift)
|
|||
if( GSsetFrameSkip == NULL )
|
||||
{
|
||||
newOptions &= ~PCSX2_FRAMELIMIT_MASK;
|
||||
SysPrintf("Notice: GS Plugin does not support frameskipping.\n");
|
||||
Console::Notice("Notice: GS Plugin does not support frameskipping.");
|
||||
limitMsg = "None/Normal";
|
||||
}
|
||||
else
|
||||
|
@ -890,7 +627,7 @@ void ProcessFKeys(int fkey, int shift)
|
|||
}
|
||||
AtomicExchange( Config.Options, newOptions );
|
||||
|
||||
SysPrintf("Frame Limit Mode Changed: %s\n", limitMsg );
|
||||
Console::Notice("Frame Limit Mode Changed: %s", limitMsg );
|
||||
|
||||
// [Air]: Do we really want to save runtime changes to frameskipping?
|
||||
//SaveConfig();
|
||||
|
@ -924,7 +661,7 @@ void ProcessFKeys(int fkey, int shift)
|
|||
|
||||
case 11:
|
||||
if( CHECK_MULTIGS ) {
|
||||
SysPrintf("Cannot make gsstates in MTGS mode\n");
|
||||
Console::Notice( "Cannot make gsstates in MTGS mode" );
|
||||
}
|
||||
else {
|
||||
if( strgametitle[0] != 0 ) {
|
||||
|
@ -952,7 +689,7 @@ void ProcessFKeys(int fkey, int shift)
|
|||
if( shift ) {
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
iDumpRegisters(cpuRegs.pc, 0);
|
||||
SysPrintf("hardware registers dumped EE:%x, IOP:%x\n", cpuRegs.pc, psxRegs.pc);
|
||||
Console::Notice("hardware registers dumped EE:%x, IOP:%x\n", cpuRegs.pc, psxRegs.pc);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
|
@ -1035,6 +772,37 @@ void injectIRX(const char *filename){
|
|||
rd[i].extInfoSize=0;
|
||||
}
|
||||
|
||||
MemoryAlloc::MemoryAlloc() :
|
||||
m_ptr( NULL )
|
||||
, m_alloc( 0 )
|
||||
, ChunkSize( DefaultChunkSize )
|
||||
{
|
||||
}
|
||||
|
||||
MemoryAlloc::MemoryAlloc( int initialSize ) :
|
||||
m_ptr( (u8*)malloc( initialSize ) )
|
||||
, m_alloc( initialSize )
|
||||
, ChunkSize( DefaultChunkSize )
|
||||
{
|
||||
if( m_ptr == NULL )
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
|
||||
MemoryAlloc::~MemoryAlloc()
|
||||
{
|
||||
safe_free( m_ptr );
|
||||
}
|
||||
|
||||
void MemoryAlloc::MakeRoomFor( int blockSize )
|
||||
{
|
||||
if( blockSize > m_alloc )
|
||||
{
|
||||
m_alloc += blockSize + ChunkSize;
|
||||
m_ptr = (u8*)realloc( m_ptr, m_alloc );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// [TODO] I'd like to move the following functions to their own module eventually.
|
||||
// It might even be a good idea to just go ahead and move them into Win32/Linux
|
||||
// specific files since they're all #ifdef'd that way anyways.
|
||||
|
|
26
pcsx2/Misc.h
26
pcsx2/Misc.h
|
@ -30,6 +30,7 @@
|
|||
#endif
|
||||
|
||||
#include "PS2Etypes.h"
|
||||
#include "System.h"
|
||||
|
||||
// compile-time assert
|
||||
#ifndef C_ASSERT
|
||||
|
@ -180,29 +181,10 @@ int GetPS2ElfName(char*);
|
|||
extern const char *LabelAuthors;
|
||||
extern const char *LabelGreets;
|
||||
|
||||
// --->> Savestate stuff [PathUtil.c]
|
||||
#include "SaveState.h"
|
||||
|
||||
// Savestate Versioning!
|
||||
// If you make changes to the savestate version, please increment the value below.
|
||||
|
||||
#ifdef PCSX2_VIRTUAL_MEM
|
||||
static const u32 g_SaveVersion = 0x7a300010;
|
||||
#else
|
||||
static const u32 g_SaveVersion = 0x8b400000;
|
||||
#endif
|
||||
|
||||
int SaveState(const char *file);
|
||||
int LoadState(const char *file);
|
||||
int CheckState(const char *file);
|
||||
|
||||
int SaveGSState(const char *file);
|
||||
int LoadGSState(const char *file);
|
||||
|
||||
#define gzfreeze(ptr, size) \
|
||||
if (Mode == 1) gzwrite(f, ptr, size); \
|
||||
else if (Mode == 0) gzread(f, ptr, size);
|
||||
|
||||
#define gzfreezel(ptr) gzfreeze(ptr, sizeof(ptr))
|
||||
void SaveGSState(const char *file);
|
||||
void LoadGSState(const char *file);
|
||||
|
||||
// <<--- End Savestate Stuff
|
||||
|
||||
|
|
|
@ -51,7 +51,6 @@ u32 LastType = 0;
|
|||
|
||||
int g_ZeroGSOptions=0;
|
||||
int patchnumber;
|
||||
extern int RunExe;
|
||||
|
||||
char strgametitle[256]= {0};
|
||||
|
||||
|
@ -383,10 +382,7 @@ void patchFunc_patch( char * cmd, char * param )
|
|||
pText = strtok( param, "," );
|
||||
pText = param;
|
||||
|
||||
if(RunExe == 1)
|
||||
patch[ patchnumber ].placetopatch = 1;
|
||||
else
|
||||
patch[ patchnumber ].placetopatch = strtol( pText, (char **)NULL, 0 );
|
||||
patch[ patchnumber ].placetopatch = strtol( pText, (char **)NULL, 0 );
|
||||
|
||||
pText = strtok( NULL, "," );
|
||||
inifile_trim( pText );
|
||||
|
@ -551,10 +547,7 @@ int AddPatch(int Mode, int Place, int Address, int Size, u64 data)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if(RunExe == 1)
|
||||
patch[patchnumber].placetopatch = 1;
|
||||
else
|
||||
patch[patchnumber].placetopatch = Mode;
|
||||
patch[patchnumber].placetopatch = Mode;
|
||||
|
||||
patch[patchnumber].cpu = (patch_cpu_type)Place;
|
||||
patch[patchnumber].addr=Address;
|
||||
|
|
|
@ -571,7 +571,23 @@ int LoadFWplugin(char *filename) {
|
|||
|
||||
return 0;
|
||||
}
|
||||
static int loadp=0;
|
||||
|
||||
struct PluginOpenStatusFlags
|
||||
{
|
||||
u8 GS : 1
|
||||
, CDVD : 1
|
||||
, DEV9 : 1
|
||||
, USB : 1
|
||||
, SPU2 : 1
|
||||
, PAD1 : 1
|
||||
, PAD2 : 1
|
||||
, FW : 1;
|
||||
|
||||
};
|
||||
|
||||
static PluginOpenStatusFlags OpenStatus = {0};
|
||||
|
||||
static bool loadp=false;
|
||||
|
||||
int InitPlugins() {
|
||||
int ret;
|
||||
|
@ -606,7 +622,18 @@ int InitPlugins() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
void ShutdownPlugins() {
|
||||
void ShutdownPlugins()
|
||||
{
|
||||
// GS is a special case: It needs closed first usually.
|
||||
// (the GS isn't closed during emulation pauses)
|
||||
if( OpenStatus.GS )
|
||||
{
|
||||
gsClose();
|
||||
OpenStatus.GS = false;
|
||||
}
|
||||
|
||||
ClosePlugins();
|
||||
|
||||
GSshutdown();
|
||||
PAD1shutdown();
|
||||
PAD2shutdown();
|
||||
|
@ -618,9 +645,10 @@ void ShutdownPlugins() {
|
|||
}
|
||||
|
||||
int LoadPlugins() {
|
||||
|
||||
if( loadp ) return 0;
|
||||
char Plugin[g_MaxPath];
|
||||
|
||||
|
||||
CombinePaths( Plugin, Config.PluginsDir, Config.GS );
|
||||
if (LoadGSplugin(Plugin) == -1) return -1;
|
||||
|
||||
|
@ -648,7 +676,7 @@ int LoadPlugins() {
|
|||
if( g_Error_PathTooLong ) return -1;
|
||||
if (InitPlugins() == -1) return -1;
|
||||
|
||||
loadp=1;
|
||||
loadp=true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -658,26 +686,11 @@ extern void spu2DMA4Irq();
|
|||
extern void spu2DMA7Irq();
|
||||
extern void spu2Irq();
|
||||
|
||||
struct PluginOpenStatusFlags
|
||||
{
|
||||
u8 GS : 1
|
||||
, CDVD : 1
|
||||
, DEV9 : 1
|
||||
, USB : 1
|
||||
, SPU2 : 1
|
||||
, PAD1 : 1
|
||||
, PAD2 : 1
|
||||
, FW : 1;
|
||||
|
||||
};
|
||||
|
||||
static PluginOpenStatusFlags OpenStatus;
|
||||
|
||||
int OpenPlugins(const char* pTitleFilename) {
|
||||
GSdriverInfo info;
|
||||
int ret;
|
||||
|
||||
if (loadp == 0) return -1;
|
||||
if (!loadp) return -1;
|
||||
|
||||
#ifndef _WIN32
|
||||
// change dir so that CDVD can find its config file
|
||||
|
@ -776,13 +789,16 @@ OpenError:
|
|||
#define CLOSE_PLUGIN( name ) \
|
||||
if( OpenStatus.name ) { \
|
||||
name##close(); \
|
||||
OpenStatus.name = 0; \
|
||||
OpenStatus.name = false; \
|
||||
}
|
||||
|
||||
|
||||
void ClosePlugins()
|
||||
{
|
||||
// GS plugin is special and is not closed during emulation pauses.
|
||||
// (that's because the GS is the most complicated plugin and to close it would
|
||||
// require we save the GS state -- plus, Gsdx doesn't really support being
|
||||
// closed)
|
||||
|
||||
if( OpenStatus.GS )
|
||||
gsWaitGS();
|
||||
|
@ -796,15 +812,17 @@ void ClosePlugins()
|
|||
CLOSE_PLUGIN( PAD2 );
|
||||
}
|
||||
|
||||
void ResetPlugins() {
|
||||
void ResetPlugins()
|
||||
{
|
||||
gsWaitGS();
|
||||
|
||||
ShutdownPlugins();
|
||||
InitPlugins();
|
||||
}
|
||||
|
||||
void ReleasePlugins() {
|
||||
if (loadp == 0) return;
|
||||
void ReleasePlugins()
|
||||
{
|
||||
if (!loadp) return;
|
||||
|
||||
if (GSplugin == NULL || PAD1plugin == NULL || PAD2plugin == NULL ||
|
||||
SPU2plugin == NULL || CDVDplugin == NULL || DEV9plugin == NULL ||
|
||||
|
@ -820,5 +838,5 @@ void ReleasePlugins() {
|
|||
SysCloseLibrary(DEV9plugin); DEV9plugin = NULL;
|
||||
SysCloseLibrary(USBplugin); USBplugin = NULL;
|
||||
SysCloseLibrary(FWplugin); FWplugin = NULL;
|
||||
loadp=0;
|
||||
loadp = false;
|
||||
}
|
||||
|
|
|
@ -23,10 +23,19 @@
|
|||
#define PLUGINfuncs
|
||||
#include "PS2Edefs.h"
|
||||
|
||||
// Loads plugins as specified in the Config global.
|
||||
int LoadPlugins();
|
||||
|
||||
// Unloads all plugin DLLs. To change plugins, call ReleasePlugins followed by
|
||||
// changes to Config.Plugins filenames, and then call LoadPlugins.
|
||||
void ReleasePlugins();
|
||||
|
||||
int OpenPlugins(const char* pTitleFilename);
|
||||
void ClosePlugins();
|
||||
|
||||
// Completely shuts down all plugins and re-initializes them. (clean slate)
|
||||
// Plugins are not unloaded, so changes to Config.Plugins values will not
|
||||
// take effect. Use a manual set oc alls to ReleasePlugins and LoadPlugins for that.
|
||||
void ResetPlugins();
|
||||
|
||||
#endif /* __PLUGINS_H__ */
|
||||
|
|
|
@ -252,23 +252,18 @@ _start:
|
|||
|
||||
memcpy((char*)PSXM(sp), save, 4*4);
|
||||
|
||||
SysPrintf( "%s", tmp);
|
||||
Console::Msg( Color_Cyan, "%s", tmp);
|
||||
|
||||
pc0 = ra;
|
||||
}
|
||||
|
||||
void bios_putchar () { // 3d
|
||||
char tmp[12];
|
||||
|
||||
sprintf (tmp,"%c",(char)a0);
|
||||
SysPrintf(tmp);
|
||||
|
||||
Console::Msg( Color_Cyan, "%c", a0 );
|
||||
pc0 = ra;
|
||||
}
|
||||
|
||||
void bios_puts () { // 3e/3f
|
||||
SysPrintf(Ra0);
|
||||
|
||||
Console::Msg( Color_Cyan, Ra0 );
|
||||
pc0 = ra;
|
||||
}
|
||||
|
||||
|
|
|
@ -707,11 +707,10 @@ u64 psxRcntCycles(int index)
|
|||
return (u64)(psxCounters[index].count + (u32)((psxRegs.cycle - psxCounters[index].sCycleT) / psxCounters[index].rate));
|
||||
}
|
||||
|
||||
extern u32 dwCurSaveStateVer;
|
||||
int psxRcntFreeze(gzFile f, int Mode)
|
||||
void SaveState::psxRcntFreeze()
|
||||
{
|
||||
#ifdef PCSX2_VIRTUAL_MEM
|
||||
if( Mode == 0 && (dwCurSaveStateVer < 0x7a300010) )
|
||||
if( IsLoading() && (m_version < 0x7a300010) )
|
||||
{
|
||||
// --- Reading Mode, Old Version ---
|
||||
// struct used to be 32bit count and target
|
||||
|
@ -719,18 +718,18 @@ int psxRcntFreeze(gzFile f, int Mode)
|
|||
u32 val;
|
||||
for(i = 0; i < ARRAYSIZE(psxCounters); ++i)
|
||||
{
|
||||
gzfreeze(&val,4); psxCounters[i].count = val;
|
||||
gzfreeze(&val,4); psxCounters[i].mode = val;
|
||||
gzfreeze(&val,4); psxCounters[i].target = val;
|
||||
gzfreeze((u8*)&psxCounters[i].rate, sizeof(psxCounters[i])-20);
|
||||
Freeze(val); psxCounters[i].count = val;
|
||||
Freeze(val); psxCounters[i].mode = val;
|
||||
Freeze(val); psxCounters[i].target = val;
|
||||
FreezeMem((u8*)&psxCounters[i].rate, sizeof(psxCounters[i])-20);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gzfreezel(psxCounters);
|
||||
Freeze(psxCounters);
|
||||
}
|
||||
|
||||
if( Mode == 0 && (dwCurSaveStateVer <= 0x7a300010) )
|
||||
if( IsLoading() && (m_version <= 0x7a300010) )
|
||||
{
|
||||
// This is needed to make old save states compatible.
|
||||
psxCounters[6].rate = 768*12;
|
||||
|
@ -754,10 +753,10 @@ int psxRcntFreeze(gzFile f, int Mode)
|
|||
}
|
||||
#else
|
||||
|
||||
gzfreezel(psxCounters);
|
||||
gzfreeze(&psxNextCounter, sizeof(psxNextCounter));
|
||||
gzfreeze(&psxNextsCounter, sizeof(psxNextsCounter));
|
||||
#endif
|
||||
// vTLB's new savestate version! :D
|
||||
|
||||
return 0;
|
||||
Freeze(psxCounters);
|
||||
Freeze(psxNextCounter);
|
||||
Freeze(psxNextsCounter);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -51,7 +51,6 @@ void psxRcntWtarget32(int index, u32 value);
|
|||
u16 psxRcntRcount16(int index);
|
||||
u32 psxRcntRcount32(int index);
|
||||
u64 psxRcntCycles(int index);
|
||||
int psxRcntFreeze(gzFile f, int Mode);
|
||||
|
||||
void psxVBlankStart();
|
||||
void psxVBlankEnd();
|
||||
|
|
|
@ -271,15 +271,15 @@ void zeroEx()
|
|||
}
|
||||
|
||||
if (!strncmp(lib, "loadcore", 8) && code == 6) {
|
||||
DevCon::FormatLn("loadcore RegisterLibraryEntries (%x): %8.8s", psxRegs.pc, PSXM(psxRegs.GPR.n.a0+12));
|
||||
DevCon::MsgLn("loadcore RegisterLibraryEntries (%x): %8.8s", psxRegs.pc, PSXM(psxRegs.GPR.n.a0+12));
|
||||
}
|
||||
|
||||
if (!strncmp(lib, "intrman", 7) && code == 4) {
|
||||
DevCon::FormatLn("intrman RegisterIntrHandler (%x): intr %s, handler %x", psxRegs.pc, intrname[psxRegs.GPR.n.a0], psxRegs.GPR.n.a2);
|
||||
DevCon::MsgLn("intrman RegisterIntrHandler (%x): intr %s, handler %x", psxRegs.pc, intrname[psxRegs.GPR.n.a0], psxRegs.GPR.n.a2);
|
||||
}
|
||||
|
||||
if (!strncmp(lib, "sifcmd", 6) && code == 17) {
|
||||
DevCon::FormatLn("sifcmd sceSifRegisterRpc (%x): rpc_id %x", psxRegs.pc, psxRegs.GPR.n.a1);
|
||||
DevCon::MsgLn("sifcmd sceSifRegisterRpc (%x): rpc_id %x", psxRegs.pc, psxRegs.GPR.n.a1);
|
||||
}
|
||||
|
||||
if (!strncmp(lib, "sysclib", 8))
|
||||
|
|
|
@ -429,12 +429,13 @@ void psxMemReset() {
|
|||
|
||||
void psxMemShutdown()
|
||||
{
|
||||
SysMunmap((uptr)psxM, 0x00200000); psxM = NULL;
|
||||
SysMunmap((uptr)psxP, 0x00010000); psxP = NULL;
|
||||
SysMunmap((uptr)psxH, 0x00010000); psxH = NULL;
|
||||
SysMunmap((uptr)psxS, 0x00010000); psxS = NULL;
|
||||
_aligned_free(psxMemRLUT);
|
||||
_aligned_free(psxMemWLUT);
|
||||
SafeSysMunmap(psxM, 0x00200000);
|
||||
SafeSysMunmap(psxP, 0x00010000);
|
||||
SafeSysMunmap(psxH, 0x00010000);
|
||||
SafeSysMunmap(psxS, 0x00010000);
|
||||
|
||||
safe_aligned_free(psxMemRLUT);
|
||||
safe_aligned_free(psxMemWLUT);
|
||||
}
|
||||
|
||||
u8 psxMemRead8(u32 mem) {
|
||||
|
|
|
@ -268,9 +268,7 @@ void psxDMA12Interrupt()
|
|||
psxRegs.interrupt&= ~(1 << 12);
|
||||
}
|
||||
|
||||
int sio2Freeze(gzFile f, int Mode) {
|
||||
gzfreeze(&sio2, sizeof(sio2));
|
||||
|
||||
return 0;
|
||||
void SaveState::sio2Freeze() {
|
||||
Freeze(sio2);
|
||||
}
|
||||
|
||||
|
|
|
@ -94,7 +94,6 @@ void psxDma12(u32 madr, u32 bcr, u32 chcr);
|
|||
|
||||
void psxDMA11Interrupt();
|
||||
void psxDMA12Interrupt();
|
||||
int sio2Freeze(gzFile f, int Mode);
|
||||
|
||||
#endif /* __PSXSIO2_H__ */
|
||||
|
||||
|
|
|
@ -273,14 +273,3 @@ void psxExecuteBios() {
|
|||
*/
|
||||
}
|
||||
|
||||
void psxRestartCPU()
|
||||
{
|
||||
psxCpu->Shutdown();
|
||||
psxCpu = CHECK_EEREC ? &psxRec : &psxInt;
|
||||
|
||||
if (psxCpu->Init() == -1) {
|
||||
SysClose();
|
||||
exit(1);
|
||||
}
|
||||
psxCpu->Reset();
|
||||
}
|
||||
|
|
|
@ -211,7 +211,6 @@ void psxShutdown();
|
|||
void psxException(u32 code, u32 step);
|
||||
void psxBranchTest();
|
||||
void psxExecuteBios();
|
||||
void psxRestartCPU();
|
||||
|
||||
extern s32 psxNextCounter;
|
||||
extern u32 psxNextsCounter;
|
||||
|
|
108
pcsx2/R5900.c
108
pcsx2/R5900.c
|
@ -43,23 +43,36 @@ s32 EEsCycle; // used to sync the IOP to the EE
|
|||
u32 EEoCycle;
|
||||
u32 bExecBIOS = 0; // set if the BIOS has already been executed
|
||||
|
||||
int cpuInit()
|
||||
static bool cpuIsInitialized = false;
|
||||
|
||||
#ifdef _DEBUG
|
||||
extern u32 s_vucount;
|
||||
#endif
|
||||
|
||||
bool cpuInit()
|
||||
{
|
||||
if( cpuIsInitialized ) return true;
|
||||
|
||||
cpuIsInitialized = true;
|
||||
int ret;
|
||||
|
||||
SysPrintf("PCSX2 " PCSX2_VERSION " save ver: %x\n", g_SaveVersion);
|
||||
SysPrintf("EE pc offset: 0x%x, PSX pc offset: 0x%x\n", (u32)&cpuRegs.pc - (u32)&cpuRegs, (u32)&psxRegs.pc - (u32)&psxRegs);
|
||||
Console::Notice("PCSX2 " PCSX2_VERSION " save ver: %x", g_SaveVersion);
|
||||
Console::Notice("EE pc offset: 0x%x, PSX pc offset: 0x%x", (u32)&cpuRegs.pc - (u32)&cpuRegs, (u32)&psxRegs.pc - (u32)&psxRegs);
|
||||
|
||||
cpuRegs.constzero = 0;
|
||||
cpudetectInit();
|
||||
Cpu = CHECK_EEREC ? &recCpu : &intCpu;
|
||||
|
||||
Console::SetColor( Console::Color_White );
|
||||
ret = Cpu->Init();
|
||||
Console::ClearColor();
|
||||
|
||||
if (ret == -1 && CHECK_EEREC) {
|
||||
SysMessage(_("Error initializing Recompiler, switching to Interpreter"));
|
||||
Console::WriteLn(_("Error initializing Recompiler, switching to Interpreter"));
|
||||
Config.Options &= ~(PCSX2_EEREC|PCSX2_VU1REC|PCSX2_VU0REC);
|
||||
Cpu = &intCpu;
|
||||
ret = Cpu->Init();
|
||||
if( ret == -1 ) return false;
|
||||
}
|
||||
|
||||
#ifdef PCSX2_VIRTUAL_MEM
|
||||
|
@ -77,7 +90,7 @@ int cpuInit()
|
|||
memset(&si, 0, sizeof(si));
|
||||
|
||||
if( !CreateProcess(strexe, "", NULL, NULL, FALSE, DETACHED_PROCESS|CREATE_NEW_PROCESS_GROUP, NULL, strdir, &si, &pi)) {
|
||||
_snprintf(strdir, ARRAYSIZE(strexe), "Failed to launch %s\n", strexe);
|
||||
_snprintf(strdir, ARRAYSIZE(strdir), "Failed to launch %s\n", strexe);
|
||||
MessageBox(NULL, strdir, "Failure", MB_OK);
|
||||
}
|
||||
else {
|
||||
|
@ -86,24 +99,33 @@ int cpuInit()
|
|||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
if (hwInit() == -1) return -1;
|
||||
if (vu0Init() == -1) return -1;
|
||||
if (vu1Init() == -1) return -1;
|
||||
if (hwInit() == -1) return false;
|
||||
if (vu0Init() == -1) return false;
|
||||
if (vu1Init() == -1) return false;
|
||||
#ifndef PCSX2_VIRTUAL_MEM
|
||||
if (memInit() == -1) return -1;
|
||||
if (memInit() == -1) return false;
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
return true;
|
||||
}
|
||||
|
||||
int cpuReset()
|
||||
bool cpuReset()
|
||||
{
|
||||
if( cpuIsInitialized )
|
||||
{
|
||||
for( int i=0; i<48; i++ )
|
||||
UnmapTLB(i);
|
||||
}
|
||||
|
||||
gsWaitGS(); // GS better be done before we reset the EE..
|
||||
|
||||
cpuInit();
|
||||
Cpu->Reset();
|
||||
|
||||
if( !memReset() ) return 0;
|
||||
if( !memReset() ) return false;
|
||||
|
||||
memset(&cpuRegs, 0, sizeof(cpuRegs));
|
||||
memset(&fpuRegs, 0, sizeof(fpuRegs));
|
||||
|
@ -128,12 +150,22 @@ int cpuReset()
|
|||
rcntInit();
|
||||
psxReset();
|
||||
|
||||
return 1;
|
||||
#ifdef _DEBUG
|
||||
s_vucount = 0;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void cpuShutdown()
|
||||
{
|
||||
gsShutdown(); // shut down the GS first because it's running a thread.
|
||||
if( !cpuIsInitialized ) return;
|
||||
|
||||
gsWaitGS();
|
||||
//gsShutdown(); // shut down the GS first because it's running a thread.
|
||||
|
||||
for( int i=0; i<48; i++ )
|
||||
UnmapTLB(i);
|
||||
|
||||
hwShutdown();
|
||||
// biosShutdown();
|
||||
|
@ -144,6 +176,8 @@ void cpuShutdown()
|
|||
disR5900FreeSyms();
|
||||
|
||||
Cpu->Shutdown();
|
||||
|
||||
cpuIsInitialized = false;
|
||||
}
|
||||
|
||||
void cpuException(u32 code, u32 bd) {
|
||||
|
@ -159,7 +193,7 @@ void cpuException(u32 code, u32 bd) {
|
|||
if (cpuRegs.CP0.n.Status.b.EXL == 0) {
|
||||
cpuRegs.CP0.n.Status.b.EXL = 1;
|
||||
if (bd) {
|
||||
SysPrintf("branch delay!!\n");
|
||||
Console::Notice("branch delay!!");
|
||||
cpuRegs.CP0.n.EPC = cpuRegs.pc - 4;
|
||||
cpuRegs.CP0.n.Cause |= 0x80000000;
|
||||
} else {
|
||||
|
@ -176,20 +210,20 @@ void cpuException(u32 code, u32 bd) {
|
|||
cpuRegs.pc = 0xBFC00200 + offset;
|
||||
}
|
||||
} else { //Error Level 2
|
||||
SysPrintf("FIX ME: Level 2 cpuException\n");
|
||||
Console::Error("FIX ME: Level 2 cpuException");
|
||||
if((code & 0x38000) <= 0x8000 ) { //Reset / NMI
|
||||
cpuRegs.pc = 0xBFC00000;
|
||||
SysPrintf("Reset request\n");
|
||||
Console::Notice("Reset request");
|
||||
UpdateCP0Status();
|
||||
return;
|
||||
} else if((code & 0x38000) == 0x10000) offset = 0x80; //Performance Counter
|
||||
else if((code & 0x38000) == 0x18000) offset = 0x100; //Debug
|
||||
else SysPrintf("Unknown Level 2 Exception!! Cause %x\n", code);
|
||||
else Console::Error("Unknown Level 2 Exception!! Cause %x", code);
|
||||
|
||||
if (cpuRegs.CP0.n.Status.b.EXL == 0) {
|
||||
cpuRegs.CP0.n.Status.b.EXL = 1;
|
||||
if (bd) {
|
||||
SysPrintf("branch delay!!\n");
|
||||
Console::Notice("branch delay!!");
|
||||
cpuRegs.CP0.n.EPC = cpuRegs.pc - 4;
|
||||
cpuRegs.CP0.n.Cause |= 0x80000000;
|
||||
} else {
|
||||
|
@ -198,7 +232,7 @@ void cpuException(u32 code, u32 bd) {
|
|||
}
|
||||
} else {
|
||||
offset = 0x180; //Overrride the cause
|
||||
SysPrintf("cpuException: Status.EXL = 1 cause %x\n", code);
|
||||
Console::Notice("cpuException: Status.EXL = 1 cause %x", code);
|
||||
}
|
||||
if (cpuRegs.CP0.n.Status.b.DEV == 0) {
|
||||
cpuRegs.pc = 0x80000000 + offset;
|
||||
|
@ -614,22 +648,10 @@ void cpuExecuteBios()
|
|||
if( CHECK_EEREC ) Config.Options |= PCSX2_COP2REC;
|
||||
else Config.Options &= ~PCSX2_COP2REC;
|
||||
|
||||
// remove frame skipping if GS doesn't support it
|
||||
switch(CHECK_FRAMELIMIT) {
|
||||
case PCSX2_FRAMELIMIT_SKIP:
|
||||
case PCSX2_FRAMELIMIT_VUSKIP:
|
||||
if( GSsetFrameSkip == NULL )
|
||||
{
|
||||
Config.Options &= ~PCSX2_FRAMELIMIT_MASK;
|
||||
SysPrintf("Notice: Disabling frameskip -- GS plugin does not support it.\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Set the video mode to user's default request:
|
||||
gsSetVideoRegionType( Config.PsxType & 1 );
|
||||
|
||||
SysPrintf("* PCSX2 *: ExecuteBios\n");
|
||||
Console::Notice( "* PCSX2 *: ExecuteBios" );
|
||||
|
||||
bExecBIOS = TRUE;
|
||||
while (cpuRegs.pc != 0x00200008 &&
|
||||
|
@ -655,26 +677,10 @@ void cpuExecuteBios()
|
|||
// REC_CLEARM(cpuRegs.pc);
|
||||
if( CHECK_EEREC ) Cpu->Reset();
|
||||
|
||||
SysPrintf("* PCSX2 *: ExecuteBios Complete\n");
|
||||
Console::Notice("* PCSX2 *: ExecuteBios Complete");
|
||||
GSprintf(5, "PCSX2 " PCSX2_VERSION "\nExecuteBios Complete\n");
|
||||
}
|
||||
|
||||
void cpuRestartCPU()
|
||||
{
|
||||
Cpu = CHECK_EEREC ? &recCpu : &intCpu;
|
||||
|
||||
// restart vus
|
||||
if (Cpu->Init() == -1) {
|
||||
SysClose();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
vu0Init();
|
||||
vu1Init();
|
||||
Cpu->Reset();
|
||||
psxRestartCPU();
|
||||
}
|
||||
|
||||
// for interpreter only
|
||||
void IntcpuBranchTest()
|
||||
{
|
||||
|
|
|
@ -225,8 +225,8 @@ extern PCSX2_ALIGNED16_DECL(tlbs tlb[48]);
|
|||
|
||||
#endif
|
||||
|
||||
int cpuInit();
|
||||
int cpuReset();
|
||||
bool cpuInit();
|
||||
bool cpuReset();
|
||||
void cpuShutdown();
|
||||
void cpuException(u32 code, u32 bd);
|
||||
void cpuTlbMissR(u32 addr, u32 bd);
|
||||
|
@ -238,7 +238,6 @@ extern void cpuTestINTCInts();
|
|||
extern void cpuTestDMACInts();
|
||||
extern void cpuTestTIMRInts();
|
||||
void cpuExecuteBios();
|
||||
void cpuRestartCPU();
|
||||
|
||||
u32 VirtualToPhysicalR(u32 addr);
|
||||
u32 VirtualToPhysicalW(u32 addr);
|
||||
|
|
|
@ -0,0 +1,356 @@
|
|||
/* Pcsx2 - Pc Ps2 Emulator
|
||||
* Copyright (C) 2002-2008 Pcsx2 Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include "Common.h"
|
||||
#include "PsxCommon.h"
|
||||
#include "CDVDisodrv.h"
|
||||
#include "VUmicro.h"
|
||||
|
||||
#include "VU.h"
|
||||
#include "iCore.h"
|
||||
#include "iVUzerorec.h"
|
||||
|
||||
#include "GS.h"
|
||||
#include "COP0.h"
|
||||
#include "Cache.h"
|
||||
|
||||
#include "Paths.h"
|
||||
|
||||
extern u32 s_iLastCOP0Cycle;
|
||||
extern u32 s_iLastPERFCycle[2];
|
||||
extern int g_psxWriteOk;
|
||||
|
||||
// STATES
|
||||
|
||||
static void PreLoadPrep()
|
||||
{
|
||||
#ifdef PCSX2_VIRTUAL_MEM
|
||||
DWORD OldProtect;
|
||||
// make sure can write
|
||||
VirtualProtect(PS2MEM_ROM, 0x00400000, PAGE_READWRITE, &OldProtect);
|
||||
VirtualProtect(PS2MEM_ROM1, 0x00040000, PAGE_READWRITE, &OldProtect);
|
||||
VirtualProtect(PS2MEM_ROM2, 0x00080000, PAGE_READWRITE, &OldProtect);
|
||||
VirtualProtect(PS2MEM_EROM, 0x001C0000, PAGE_READWRITE, &OldProtect);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void PostLoadPrep()
|
||||
{
|
||||
#ifdef PCSX2_VIRTUAL_MEM
|
||||
DWORD OldProtect;
|
||||
VirtualProtect(PS2MEM_ROM, 0x00400000, PAGE_READONLY, &OldProtect);
|
||||
VirtualProtect(PS2MEM_ROM1, 0x00040000, PAGE_READONLY, &OldProtect);
|
||||
VirtualProtect(PS2MEM_ROM2, 0x00080000, PAGE_READONLY, &OldProtect);
|
||||
VirtualProtect(PS2MEM_EROM, 0x001C0000, PAGE_READONLY, &OldProtect);
|
||||
#endif
|
||||
|
||||
memset(pCache,0,sizeof(_cacheS)*64);
|
||||
WriteCP0Status(cpuRegs.CP0.n.Status.val);
|
||||
for(int i=0; i<48; i++) MapTLB(i);
|
||||
}
|
||||
|
||||
void SaveState::GetFilename( char* dest, int slot )
|
||||
{
|
||||
char elfcrcText[72];
|
||||
sprintf( elfcrcText, "%8.8X.%3.3d", ElfCRC, slot );
|
||||
CombinePaths( dest, SSTATES_DIR, elfcrcText );
|
||||
}
|
||||
|
||||
SaveState::SaveState( const char* msg, const char* destination ) :
|
||||
m_version( g_SaveVersion )
|
||||
{
|
||||
Console::MsgLn( "%s %s", msg, destination );
|
||||
}
|
||||
|
||||
void SaveState::FreezeAll()
|
||||
{
|
||||
if( IsLoading() )
|
||||
PreLoadPrep();
|
||||
|
||||
FreezeMem(PS2MEM_BASE, 0x02000000); // 32 MB main memory
|
||||
FreezeMem(PS2MEM_ROM, 0x00400000); // 4 mb rom memory
|
||||
FreezeMem(PS2MEM_ROM1,0x00040000); // 256kb rom1 memory
|
||||
FreezeMem(PS2MEM_SCRATCH, 0x00004000); // scratch pad
|
||||
FreezeMem(PS2MEM_HW, 0x00010000); // hardware memory
|
||||
|
||||
Freeze(cpuRegs); // cpu regs + COP0
|
||||
Freeze(psxRegs); // iop regs
|
||||
Freeze(fpuRegs); // fpu regs
|
||||
Freeze(tlb); // tlbs
|
||||
|
||||
Freeze(EEsCycle);
|
||||
Freeze(EEoCycle);
|
||||
Freeze(psxRegs.cycle); // used to be IOPoCycle. This retains compatibility.
|
||||
Freeze(g_nextBranchCycle);
|
||||
Freeze(g_psxNextBranchCycle);
|
||||
|
||||
Freeze(s_iLastCOP0Cycle);
|
||||
if( m_version >= 0x7a30000e )
|
||||
Freeze(s_iLastPERFCycle);
|
||||
|
||||
Freeze(g_psxWriteOk);
|
||||
|
||||
//hope didn't forgot any cpu....
|
||||
|
||||
rcntFreeze();
|
||||
gsFreeze();
|
||||
vu0Freeze();
|
||||
vu1Freeze();
|
||||
vif0Freeze();
|
||||
vif1Freeze();
|
||||
sifFreeze();
|
||||
ipuFreeze();
|
||||
|
||||
// iop now
|
||||
FreezeMem(psxM, 0x00200000); // 2 MB main memory
|
||||
FreezeMem(psxH, 0x00010000); // hardware memory
|
||||
//FreezeMem(psxS, 0x00010000); // sif memory
|
||||
|
||||
sioFreeze();
|
||||
cdrFreeze();
|
||||
cdvdFreeze();
|
||||
psxRcntFreeze();
|
||||
sio2Freeze();
|
||||
|
||||
if( CHECK_MULTIGS ) {
|
||||
// have to call in thread, otherwise weird stuff will start happening
|
||||
GSRingBufPointerPacket(
|
||||
IsSaving() ? GS_RINGTYPE_SAVE : GS_RINGTYPE_LOAD, 0, this
|
||||
);
|
||||
gsWaitGS();
|
||||
}
|
||||
else {
|
||||
FreezePlugin( "GS", GSfreeze );
|
||||
}
|
||||
FreezePlugin( "SPU2", SPU2freeze );
|
||||
FreezePlugin( "DEV9", DEV9freeze );
|
||||
FreezePlugin( "USB", USBfreeze );
|
||||
|
||||
if( IsLoading() )
|
||||
PostLoadPrep();
|
||||
}
|
||||
|
||||
gzBaseStateInfo::gzBaseStateInfo( const char* msg, const char* filename ) :
|
||||
SaveState( msg, filename )
|
||||
, m_filename( filename )
|
||||
, m_file( NULL )
|
||||
{
|
||||
}
|
||||
|
||||
gzBaseStateInfo::~gzBaseStateInfo()
|
||||
{
|
||||
if( m_file != NULL )
|
||||
{
|
||||
gzclose( m_file );
|
||||
m_file = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
gzSavingState::gzSavingState( const char* filename ) :
|
||||
gzBaseStateInfo( _("Saving state to: "), filename )
|
||||
{
|
||||
m_file = gzopen(filename, "wb");
|
||||
if( m_file == NULL )
|
||||
throw Exception::FileNotFound();
|
||||
|
||||
Freeze( m_version );
|
||||
}
|
||||
|
||||
|
||||
gzLoadingState::gzLoadingState( const char* filename ) :
|
||||
gzBaseStateInfo( _("Loading state from: "), filename )
|
||||
{
|
||||
m_file = gzopen(filename, "rb");
|
||||
if( m_file == NULL )
|
||||
throw Exception::FileNotFound();
|
||||
|
||||
gzread( m_file, &m_version, 4 );
|
||||
|
||||
if( m_version != g_SaveVersion )
|
||||
{
|
||||
#ifdef PCSX2_VIRTUAL_MEM
|
||||
if( m_version >= 0x8b400000 )
|
||||
{
|
||||
Console::Error(
|
||||
"Savestate load aborted:\n"
|
||||
"\tVM edition cannot safely load savestates created by the VTLB edition."
|
||||
);
|
||||
throw Exception::UnsupportedStateVersion();
|
||||
}
|
||||
// pcsx2 vm supports opening these formats
|
||||
if( m_version < 0x7a30000d )
|
||||
{
|
||||
Console::MsgLn( "Unsupported or unrecognized savestate version: %x.", m_version );
|
||||
throw Exception::UnsupportedStateVersion();
|
||||
}
|
||||
#else
|
||||
Console::Error(
|
||||
"Savestate load aborted:\n"
|
||||
"\tVTLB edition cannot safely load savestates created by the VM edition." );
|
||||
throw Exception::UnsupportedStateVersion();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
gzLoadingState::~gzLoadingState() { }
|
||||
|
||||
|
||||
void gzSavingState::FreezeMem( void* data, int size )
|
||||
{
|
||||
gzwrite( m_file, data, size );
|
||||
}
|
||||
|
||||
void gzLoadingState::FreezeMem( void* data, int size )
|
||||
{
|
||||
gzread( m_file, data, size );
|
||||
}
|
||||
|
||||
void gzSavingState::FreezePlugin( const char* name, s32 (CALLBACK *freezer)(int mode, freezeData *data) )
|
||||
{
|
||||
Console::MsgLn( "\tSaving %s", name );
|
||||
freezeData fP = { 0, NULL };
|
||||
|
||||
if (freezer(FREEZE_SIZE, &fP) == -1)
|
||||
throw Exception::FreezePluginFailure( name, "saving" );
|
||||
|
||||
gzwrite(m_file, &fP.size, sizeof(fP.size));
|
||||
if( fP.size == 0 ) return;
|
||||
|
||||
fP.data = (s8*)malloc(fP.size);
|
||||
if (fP.data == NULL)
|
||||
throw std::bad_alloc();
|
||||
|
||||
if(freezer(FREEZE_SAVE, &fP) == -1)
|
||||
throw Exception::FreezePluginFailure( name, "saving" );
|
||||
|
||||
if (fP.size)
|
||||
{
|
||||
gzwrite(m_file, fP.data, fP.size);
|
||||
free(fP.data);
|
||||
}
|
||||
}
|
||||
|
||||
void gzLoadingState::FreezePlugin( const char* name, s32 (CALLBACK *freezer)(int mode, freezeData *data) )
|
||||
{
|
||||
freezeData fP = { 0, NULL };
|
||||
Console::MsgLn( "\tLoading %s", name );
|
||||
|
||||
gzread(m_file, &fP.size, sizeof(fP.size));
|
||||
if( fP.size == 0 ) return;
|
||||
|
||||
fP.data = (s8*)malloc(fP.size);
|
||||
if (fP.data == NULL)
|
||||
throw std::bad_alloc();
|
||||
gzread(m_file, fP.data, fP.size);
|
||||
|
||||
if( gzeof( m_file ) )
|
||||
throw Exception::BadSavedState( m_filename );
|
||||
|
||||
if(freezer(FREEZE_LOAD, &fP) == -1)
|
||||
throw Exception::FreezePluginFailure( name, "loading" );
|
||||
|
||||
if (fP.size) free(fP.data);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
memBaseStateInfo::memBaseStateInfo( MemoryAlloc& memblock, const char* msg ) :
|
||||
SaveState( msg, "Memory" )
|
||||
, m_memory( memblock )
|
||||
, m_idx( 0 )
|
||||
{
|
||||
}
|
||||
|
||||
memSavingState::memSavingState( MemoryAlloc& save_to ) : memBaseStateInfo( save_to, _("Saving state to: ") )
|
||||
{
|
||||
save_to.ChunkSize = ReallocThreshold;
|
||||
save_to.MakeRoomFor( MemoryBaseAllocSize );
|
||||
}
|
||||
|
||||
// Saving of state data to a memory buffer
|
||||
void memSavingState::FreezeMem( void* data, int size )
|
||||
{
|
||||
const int end = m_idx+size;
|
||||
m_memory.MakeRoomFor( end );
|
||||
|
||||
u8* dest = (u8*)m_memory.GetPtr();
|
||||
const u8* src = (u8*)data;
|
||||
|
||||
for( ; m_idx<end; ++m_idx, ++src )
|
||||
dest[m_idx] = *src;
|
||||
}
|
||||
|
||||
memLoadingState::memLoadingState(MemoryAlloc& load_from ) : memBaseStateInfo( load_from, _("Loading state from: ") )
|
||||
{
|
||||
}
|
||||
|
||||
memLoadingState::~memLoadingState() { }
|
||||
|
||||
// Loading of state data from a memory buffer...
|
||||
void memLoadingState::FreezeMem( void* data, int size )
|
||||
{
|
||||
const int end = m_idx+size;
|
||||
const u8* src = (u8*)m_memory.GetPtr();
|
||||
u8* dest = (u8*)data;
|
||||
|
||||
for( ; m_idx<end; ++m_idx, ++dest )
|
||||
*dest = src[m_idx];
|
||||
}
|
||||
|
||||
void memSavingState::FreezePlugin( const char* name, s32 (CALLBACK *freezer)(int mode, freezeData *data) )
|
||||
{
|
||||
freezeData fP = { 0, NULL };
|
||||
Console::MsgLn( "\tSaving %s", name );
|
||||
|
||||
if( freezer(FREEZE_SIZE, &fP) == -1 )
|
||||
throw Exception::FreezePluginFailure( name, "saving" );
|
||||
|
||||
Freeze( fP.size );
|
||||
if( fP.size == 0 ) return;
|
||||
|
||||
const int end = m_idx+fP.size;
|
||||
m_memory.MakeRoomFor( end );
|
||||
|
||||
fP.data = ((s8*)m_memory.GetPtr()) + m_idx;
|
||||
if(freezer(FREEZE_SAVE, &fP) == -1)
|
||||
throw Exception::FreezePluginFailure( name, "saving" );
|
||||
|
||||
m_idx += fP.size;
|
||||
}
|
||||
|
||||
void memLoadingState::FreezePlugin( const char* name, s32 (CALLBACK *freezer)(int mode, freezeData *data) )
|
||||
{
|
||||
freezeData fP;
|
||||
Console::MsgLn( "\tLoading %s", name );
|
||||
|
||||
Freeze( fP.size );
|
||||
if( fP.size == 0 ) return;
|
||||
|
||||
if( ( fP.size + m_idx ) > m_memory.GetSize() )
|
||||
throw Exception::BadSavedState( "memory" );
|
||||
|
||||
fP.data = ((s8*)m_memory.GetPtr()) + m_idx;
|
||||
if(freezer(FREEZE_LOAD, &fP) == -1)
|
||||
throw Exception::FreezePluginFailure( name, "loading" );
|
||||
|
||||
m_idx += fP.size;
|
||||
|
||||
if( ( fP.size + m_idx ) > m_memory.GetSize() )
|
||||
throw Exception::BadSavedState( "memory" );
|
||||
}
|
|
@ -0,0 +1,178 @@
|
|||
/* Pcsx2 - Pc Ps2 Emulator
|
||||
* Copyright (C) 2002-2008 Pcsx2 Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef _SAVESTATE_H_
|
||||
#define _SAVESTATE_H_
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
// Savestate Versioning!
|
||||
// If you make changes to the savestate version, please increment the value below.
|
||||
|
||||
#ifdef PCSX2_VIRTUAL_MEM
|
||||
static const u32 g_SaveVersion = 0x7a300010;
|
||||
#else
|
||||
static const u32 g_SaveVersion = 0x8b400000;
|
||||
#endif
|
||||
|
||||
// This class provides the base API for both loading and saving savestates.
|
||||
// Normally you'll want to use one of the four "functional" derrived classes rather
|
||||
// than this class directly: gzLoadingState, gzSavingState (gzipped disk-saved
|
||||
// states), and memLoadingState, memSavingState (uncompressed memory states).
|
||||
class SaveState
|
||||
{
|
||||
protected:
|
||||
u32 m_version; // version of the savestate being loaded.
|
||||
|
||||
public:
|
||||
SaveState( const char* msg, const char* destination );
|
||||
virtual ~SaveState() { }
|
||||
|
||||
static void GetFilename( char* dest, int slot );
|
||||
|
||||
// Gets the version of savestate that this object is acting on.
|
||||
u32 GetVersion() const { return m_version; }
|
||||
|
||||
// Loads or saves the entire emulation state.
|
||||
// Note: The Cpu state must be reset, and plugins *open*, prior to Defrosting
|
||||
// (loading) a state!
|
||||
void FreezeAll();
|
||||
|
||||
// Loads or saves an arbitrary data type. Usable on atomic types, structs, and arrays.
|
||||
// For dynamically allocated pointers use FreezeMem instead.
|
||||
template<typename T>
|
||||
void Freeze( T& data )
|
||||
{
|
||||
FreezeMem( &data, sizeof( T ) );
|
||||
}
|
||||
|
||||
// Loads or saves a plugin. Plugin name is for console logging purposes.
|
||||
virtual void FreezePlugin( const char* name, s32 (CALLBACK *freezer)(int mode, freezeData *data) )=0;
|
||||
|
||||
// Loads or saves a memory block.
|
||||
virtual void FreezeMem( void* data, int size )=0;
|
||||
|
||||
// Returns true if this object is a StateSaving type object.
|
||||
virtual bool IsSaving() const=0;
|
||||
|
||||
// Returns true if this object is a StateLoading type object.
|
||||
bool IsLoading() const { return !IsSaving(); }
|
||||
|
||||
// note: gsFreeze() needs to be public because of the GSState recorder.
|
||||
|
||||
public:
|
||||
void gsFreeze();
|
||||
|
||||
protected:
|
||||
|
||||
// Load/Save functions for the various components of our glorious emulator!
|
||||
|
||||
void rcntFreeze();
|
||||
void vu0Freeze();
|
||||
void vu1Freeze();
|
||||
void vif0Freeze();
|
||||
void vif1Freeze();
|
||||
void sifFreeze();
|
||||
void ipuFreeze();
|
||||
|
||||
void sioFreeze();
|
||||
void cdrFreeze();
|
||||
void cdvdFreeze();
|
||||
void psxRcntFreeze();
|
||||
void sio2Freeze();
|
||||
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
// Class Declarations for Savestates using zlib
|
||||
|
||||
class gzBaseStateInfo : public SaveState
|
||||
{
|
||||
protected:
|
||||
const char* m_filename;
|
||||
gzFile m_file; // used for reading/writing disk saves
|
||||
|
||||
public:
|
||||
gzBaseStateInfo( const char* msg, const char* filename );
|
||||
|
||||
virtual ~gzBaseStateInfo();
|
||||
};
|
||||
|
||||
class gzSavingState : public gzBaseStateInfo
|
||||
{
|
||||
public:
|
||||
virtual ~gzSavingState() {}
|
||||
gzSavingState( const char* filename ) ;
|
||||
|
||||
void FreezePlugin( const char* name, s32 (CALLBACK *freezer)(int mode, freezeData *data) );
|
||||
void FreezeMem( void* data, int size );
|
||||
bool IsSaving() const { return true; }
|
||||
};
|
||||
|
||||
class gzLoadingState : public gzBaseStateInfo
|
||||
{
|
||||
public:
|
||||
virtual ~gzLoadingState();
|
||||
gzLoadingState( const char* filename );
|
||||
|
||||
void FreezePlugin( const char* name, s32 (CALLBACK *freezer)(int mode, freezeData *data) );
|
||||
void FreezeMem( void* data, int size );
|
||||
bool IsSaving() const { return false; }
|
||||
bool Finished() const { return !!gzeof( m_file ); }
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class memBaseStateInfo : public SaveState
|
||||
{
|
||||
protected:
|
||||
MemoryAlloc& m_memory;
|
||||
int m_idx; // current read/write index of the allocation
|
||||
|
||||
public:
|
||||
virtual ~memBaseStateInfo() { }
|
||||
memBaseStateInfo( MemoryAlloc& memblock, const char* msg );
|
||||
};
|
||||
|
||||
class memSavingState : public memBaseStateInfo
|
||||
{
|
||||
protected:
|
||||
static const int ReallocThreshold = 0x200000; // 256k reallocation block size.
|
||||
static const int MemoryBaseAllocSize = 0x02a00000; // 42 meg base alloc
|
||||
|
||||
public:
|
||||
virtual ~memSavingState() { }
|
||||
memSavingState( MemoryAlloc& save_to );
|
||||
void FreezePlugin( const char* name, s32 (CALLBACK *freezer)(int mode, freezeData *data) );
|
||||
// Saving of state data to a memory buffer
|
||||
void FreezeMem( void* data, int size );
|
||||
bool IsSaving() const { return true; }
|
||||
};
|
||||
|
||||
class memLoadingState : public memBaseStateInfo
|
||||
{
|
||||
public:
|
||||
virtual ~memLoadingState();
|
||||
memLoadingState(MemoryAlloc& load_from );
|
||||
void FreezePlugin( const char* name, s32 (CALLBACK *freezer)(int mode, freezeData *data) );
|
||||
// Loading of state data from a memory buffer...
|
||||
void FreezeMem( void* data, int size );
|
||||
bool IsSaving() const { return false; }
|
||||
};
|
||||
|
||||
#endif
|
|
@ -588,8 +588,7 @@ __forceinline void dmaSIF2() {
|
|||
}
|
||||
|
||||
|
||||
int sifFreeze(gzFile f, int Mode) {
|
||||
gzfreeze(&sif0, sizeof(sif0));
|
||||
gzfreeze(&sif1, sizeof(sif1));
|
||||
return 0;
|
||||
void SaveState::sifFreeze() {
|
||||
Freeze(sif0);
|
||||
Freeze(sif1);
|
||||
}
|
||||
|
|
17
pcsx2/Sio.c
17
pcsx2/Sio.c
|
@ -515,22 +515,21 @@ void sioInterrupt() {
|
|||
psxRegs.interrupt&= ~(1 << 16);
|
||||
}
|
||||
|
||||
extern u32 dwCurSaveStateVer;
|
||||
int sioFreeze(gzFile f, int Mode) {
|
||||
void SaveState::sioFreeze() {
|
||||
|
||||
int savesize = sizeof(sio);
|
||||
if( Mode == 0 && dwCurSaveStateVer == 0x7a30000e )
|
||||
savesize -= 4;
|
||||
sio.count = 0;
|
||||
gzfreeze(&sio, savesize);
|
||||
// eh, not supported anymore.. :)
|
||||
//if( Mode == 0 && dwCurSaveStateVer == 0x7a30000e )
|
||||
// savesize -= 4;
|
||||
|
||||
return 0;
|
||||
if( IsLoading() )
|
||||
sio.count = 0;
|
||||
Freeze( sio );
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
*******************************************************************
|
||||
*************** MEMORY CARD SPECIFIC FUNTIONS ******************
|
||||
*************** MEMORY CARD SPECIFIC FUNCTIONS *****************
|
||||
*******************************************************************
|
||||
*******************************************************************/
|
||||
FILE *LoadMcd(int mcd) {
|
||||
|
|
|
@ -95,7 +95,6 @@ u8 sioRead8();
|
|||
void sioWrite8(unsigned char value);
|
||||
void sioWriteCtrl16(unsigned short value);
|
||||
extern void sioInterrupt();
|
||||
int sioFreeze(gzFile f, int Mode);
|
||||
void InitializeSIO(u8 value);
|
||||
|
||||
FILE *LoadMcd(int mcd);
|
||||
|
|
146
pcsx2/System.h
146
pcsx2/System.h
|
@ -19,8 +19,10 @@
|
|||
#ifndef __SYSTEM_H__
|
||||
#define __SYSTEM_H__
|
||||
|
||||
#include "Exceptions.h"
|
||||
|
||||
int SysInit(); // Init mem and plugins
|
||||
int SysReset(); // Resets mem
|
||||
void SysReset(); // Resets the various PS2 cpus, sub-systems, and recompilers.
|
||||
void SysUpdate(); // Called on VBlank (to update i.e. pads)
|
||||
void SysRunGui(); // Returns to the Gui
|
||||
void SysClose(); // Close mem and plugins
|
||||
|
@ -46,57 +48,173 @@ void SysMunmap(uptr base, u32 size);
|
|||
void SysPrintf(const char *fmt, ...); // *DEPRECIATED*
|
||||
|
||||
|
||||
static __forceinline void SysMunmap( void* base, u32 size )
|
||||
{
|
||||
SysMunmap( (uptr)base, size );
|
||||
}
|
||||
|
||||
// Console Namespace -- Replacements for SysPrintf.
|
||||
// SysPrintf is depreciated -- We should phase these in over time.
|
||||
namespace Console
|
||||
{
|
||||
enum Colors
|
||||
{
|
||||
Color_Black = 0,
|
||||
Color_Red,
|
||||
Color_Green,
|
||||
Color_Yellow,
|
||||
Color_Blue,
|
||||
Color_Magenta,
|
||||
Color_Cyan,
|
||||
Color_White
|
||||
};
|
||||
|
||||
extern void Open();
|
||||
extern void Close();
|
||||
extern void SetTitle( const char* title );
|
||||
|
||||
// Changes the active console color.
|
||||
// This color will be unset by calls to colored text methods
|
||||
// such as ErrorMsg and Notice.
|
||||
extern void __fastcall SetColor( Colors color );
|
||||
|
||||
// Restores the console color to default (usually low-intensity white on Win32)
|
||||
extern void ClearColor();
|
||||
|
||||
// The following Write functions return bool so that we can use macros to exclude
|
||||
// them from different buildypes. The return values are always zero.
|
||||
|
||||
// Writes a newline to the console.
|
||||
extern bool __fastcall WriteLn();
|
||||
|
||||
// Writes an unformatted string of text to the console (fast!)
|
||||
// No newline is appended.
|
||||
extern bool __fastcall Write( const char* fmt );
|
||||
|
||||
// Writes an unformatted string of text to the console (fast!)
|
||||
// A newline is automatically appended.
|
||||
extern bool __fastcall WriteLn( const char* fmt );
|
||||
extern bool Format( const char* fmt, ... );
|
||||
extern bool FormatLn( const char* fmt, ... );
|
||||
|
||||
// Writes a line of colored text to the console, with automatic newline appendage.
|
||||
// The console color is reset to default when the operation is complete.
|
||||
extern bool MsgLn( Colors color, const char* fmt, ... );
|
||||
|
||||
// Writes a line of colored text to the console (no newline).
|
||||
// The console color is reset to default when the operation is complete.
|
||||
extern bool Msg( Colors color, const char* fmt, ... );
|
||||
|
||||
// Writes a formatted message to the console (no newline)
|
||||
extern bool Msg( const char* fmt, ... );
|
||||
|
||||
// Writes a formatted message to the console, with appended newline.
|
||||
extern bool MsgLn( const char* fmt, ... );
|
||||
|
||||
// Displays a message in the console with red emphasis.
|
||||
// Newline is automatically appended.
|
||||
extern bool Error( const char* fmt, ... );
|
||||
|
||||
// Displays a message in the console with yellow emphasis.
|
||||
// Newline is automatically appended.
|
||||
extern bool Notice( const char* fmt, ... );
|
||||
}
|
||||
|
||||
using Console::Color_Red;
|
||||
using Console::Color_Green;
|
||||
using Console::Color_Blue;
|
||||
using Console::Color_Magenta;
|
||||
using Console::Color_Cyan;
|
||||
using Console::Color_Yellow;
|
||||
using Console::Color_White;
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// Class for allocating a resizable memory block.
|
||||
|
||||
class MemoryAlloc
|
||||
{
|
||||
public:
|
||||
static const int DefaultChunkSize = 0x1000;
|
||||
|
||||
protected:
|
||||
u8* m_ptr;
|
||||
int m_alloc; // size of the allocation of memory
|
||||
|
||||
public:
|
||||
int ChunkSize;
|
||||
|
||||
public:
|
||||
virtual ~MemoryAlloc();
|
||||
MemoryAlloc( int initalSize );
|
||||
MemoryAlloc();
|
||||
|
||||
int GetSize() const { return m_alloc; }
|
||||
|
||||
// Gets the pointer to the beginning of the memory allocation.
|
||||
// Returns null if no memory has been allocated to this handle.
|
||||
void *GetPtr() { return m_ptr; }
|
||||
const void *GetPtr() const { return m_ptr; }
|
||||
|
||||
void MakeRoomFor( int blockSize );
|
||||
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Safe deallocation macros -- always check pointer validity (non-null)
|
||||
// and set pointer to null on deallocation.
|
||||
|
||||
#define safe_delete( ptr ) \
|
||||
if( ptr != NULL ) { \
|
||||
delete ptr; \
|
||||
ptr = NULL; \
|
||||
}
|
||||
|
||||
#define safe_delete_array( ptr ) \
|
||||
if( ptr != NULL ) { \
|
||||
delete[] ptr; \
|
||||
ptr = NULL; \
|
||||
}
|
||||
|
||||
#define safe_free( ptr ) \
|
||||
if( ptr != NULL ) { \
|
||||
free( ptr ); \
|
||||
ptr = NULL; \
|
||||
}
|
||||
|
||||
#define safe_aligned_free( ptr ) \
|
||||
if( ptr != NULL ) { \
|
||||
_aligned_free( ptr ); \
|
||||
ptr = NULL; \
|
||||
}
|
||||
|
||||
#define SafeSysMunmap( ptr, size ) \
|
||||
if( ptr != NULL ) { \
|
||||
SysMunmap( (uptr)ptr, size ); \
|
||||
ptr = NULL; \
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Macros for ifdef'ing out specific lines of code.
|
||||
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
|
||||
# define DEVCODE(x) (x)
|
||||
# define DevCon Console
|
||||
# define PUBCODE 0&&
|
||||
|
||||
static const bool IsDevBuild = true;
|
||||
|
||||
#else
|
||||
|
||||
# define DEVCODE(x) 0&&(x)
|
||||
# define DevCon 0&&Console
|
||||
# define PUBCODE(x) (x)
|
||||
|
||||
static const bool IsDevBuild = false;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef _DEBUG
|
||||
|
||||
static const bool IsDebugBuild = true;
|
||||
|
||||
# define DBGCODE(x) (x)
|
||||
# define DbgCon 0&&Console
|
||||
static const bool IsDebugBuild = true;
|
||||
|
||||
#else
|
||||
|
||||
# define DBGCODE(x) 0&&
|
||||
# define DbgCon 0&&Console
|
||||
|
||||
static const bool IsDebugBuild = false;
|
||||
#endif
|
||||
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
int vu0Init();
|
||||
void vu0Reset();
|
||||
void vu0ResetRegs();
|
||||
void vu0Freeze(gzFile f, int Mode);
|
||||
void vu0Shutdown();
|
||||
|
||||
void recResetVU0( void );
|
||||
|
|
|
@ -81,7 +81,7 @@ int vu0Init()
|
|||
VU0.Mem = (u8*)VirtualAlloc((void*)0x11000000, 0x10000, MEM_RESERVE|MEM_PHYSICAL, PAGE_READWRITE);
|
||||
|
||||
if( VU0.Mem != (void*)0x11000000 ) {
|
||||
SysPrintf("Failed to alloc vu0mem 0x11000000 %d\n", GetLastError());
|
||||
Console::MsgLn("Failed to alloc vu0mem 0x11000000 %d", GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -131,11 +131,13 @@ void vu0Shutdown()
|
|||
#ifdef PCSX2_VIRTUAL_MEM
|
||||
if( !SysMapUserPhysicalPages(VU0.Mem, 16, NULL, 0) )
|
||||
SysPrintf("err releasing vu0 mem %d\n", GetLastError());
|
||||
|
||||
// note: this function *always* fails! (in XP at least)
|
||||
if( VirtualFree(VU0.Mem, 0, MEM_RELEASE) == 0 )
|
||||
SysPrintf("err freeing vu0 %d\n", GetLastError());
|
||||
#else
|
||||
_aligned_free(VU0.Mem);
|
||||
_aligned_free(VU0.Micro);
|
||||
safe_aligned_free(VU0.Mem);
|
||||
safe_aligned_free(VU0.Micro);
|
||||
#endif
|
||||
|
||||
VU0.Mem = NULL;
|
||||
|
@ -172,13 +174,13 @@ void recResetVU0( void )
|
|||
if( CHECK_VU0REC ) SuperVUReset(0);
|
||||
}
|
||||
|
||||
void vu0Freeze(gzFile f, int Mode) {
|
||||
gzfreeze(&VU0.ACC, sizeof(VECTOR));
|
||||
gzfreeze(&VU0.code, sizeof(u32));
|
||||
gzfreeze(VU0.Mem, 4*1024);
|
||||
gzfreeze(VU0.Micro, 4*1024);
|
||||
gzfreeze(VU0.VF, 32*sizeof(VECTOR));
|
||||
gzfreeze(VU0.VI, 32*sizeof(REG_VI));
|
||||
void SaveState::vu0Freeze() {
|
||||
Freeze(VU0.ACC);
|
||||
Freeze(VU0.code);
|
||||
FreezeMem(VU0.Mem, 4*1024);
|
||||
FreezeMem(VU0.Micro, 4*1024);
|
||||
FreezeMem(VU0.VF, 32*sizeof(VECTOR));
|
||||
FreezeMem(VU0.VI, 32*sizeof(REG_VI));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -124,13 +124,13 @@ void vu1Reset() {
|
|||
recResetVU1();
|
||||
}
|
||||
|
||||
void vu1Freeze(gzFile f, int Mode) {
|
||||
gzfreeze(&VU1.ACC, sizeof(VECTOR));
|
||||
gzfreeze(&VU1.code, sizeof(u32));
|
||||
gzfreeze(VU1.Mem, 16*1024);
|
||||
gzfreeze(VU1.Micro, 16*1024);
|
||||
gzfreeze(VU1.VF, 32*sizeof(VECTOR));
|
||||
gzfreeze(VU1.VI, 32*sizeof(REG_VI));
|
||||
void SaveState::vu1Freeze() {
|
||||
Freeze(VU1.ACC);
|
||||
Freeze(VU1.code);
|
||||
FreezeMem(VU1.Mem, 16*1024);
|
||||
FreezeMem(VU1.Micro, 16*1024);
|
||||
FreezeMem(VU1.VF, 32*sizeof(VECTOR));
|
||||
FreezeMem(VU1.VI, 32*sizeof(REG_VI));
|
||||
}
|
||||
|
||||
static int count;
|
||||
|
|
|
@ -62,7 +62,6 @@ extern void (*VU1regs_UPPER_FD_11_TABLE[32])(_VURegsNum *VUregsn);
|
|||
int vu0Init();
|
||||
void vu0Reset();
|
||||
void vu0ResetRegs();
|
||||
void vu0Freeze(gzFile f, int Mode);
|
||||
void vu0Shutdown();
|
||||
void vu0ExecMicro(u32 addr);
|
||||
void vu0Exec(VURegs* VU);
|
||||
|
@ -74,7 +73,6 @@ int vu1Init();
|
|||
void vu1Reset();
|
||||
void vu1ResetRegs();
|
||||
void recResetVU1( void );
|
||||
void vu1Freeze(gzFile f, int Mode);
|
||||
void vu1Shutdown();
|
||||
void vu1ExecMicro(u32 addr);
|
||||
void vu1Exec(VURegs* VU);
|
||||
|
|
|
@ -1438,12 +1438,10 @@ void vif0Reset() {
|
|||
//FreezeMMXRegs(0);
|
||||
}
|
||||
|
||||
int vif0Freeze(gzFile f, int Mode) {
|
||||
gzfreeze(&vif0, sizeof(vif0));
|
||||
if (Mode == 0)
|
||||
void SaveState::vif0Freeze() {
|
||||
Freeze(vif0);
|
||||
if( IsLoading() )
|
||||
SetNewMask(g_vif0Masks, g_vif0HasMask3, vif0Regs->mask, ~vif0Regs->mask);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -2452,10 +2450,8 @@ void vif1Reset() {
|
|||
FreezeMMXRegs(0);*/
|
||||
}
|
||||
|
||||
int vif1Freeze(gzFile f, int Mode) {
|
||||
gzfreeze(&vif1, sizeof(vif1));
|
||||
if (Mode == 0)
|
||||
void SaveState::vif1Freeze() {
|
||||
Freeze(vif1);
|
||||
if( IsLoading() )
|
||||
SetNewMask(g_vif1Masks, g_vif1HasMask3, vif1Regs->mask, ~vif1Regs->mask);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -93,7 +93,5 @@ void vif1Write32(u32 mem, u32 value);
|
|||
|
||||
void vif0Reset();
|
||||
void vif1Reset();
|
||||
int vif0Freeze(gzFile f, int Mode);
|
||||
int vif1Freeze(gzFile f, int Mode);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -455,6 +455,8 @@ bool vtlb_Init()
|
|||
vtlbUnmappedPWrite64<0x80000000>,vtlbUnmappedPWrite128<0x80000000>);
|
||||
DefaultPhyHandler=vtlb_RegisterHandler(0,0,0,0,0,0,0,0,0,0);
|
||||
|
||||
//done !
|
||||
|
||||
//Setup the initial mappings
|
||||
vtlb_MapHandler(DefaultPhyHandler,0,VTLB_PMAP_SZ);
|
||||
|
||||
|
@ -462,9 +464,15 @@ bool vtlb_Init()
|
|||
vtlb_VMapUnmap(0,(VTLB_VMAP_ITEMS-1)*VTLB_PAGE_SIZE);
|
||||
//yeah i know, its stupid .. but this code has to be here for now ;p
|
||||
vtlb_VMapUnmap((VTLB_VMAP_ITEMS-1)*VTLB_PAGE_SIZE,VTLB_PAGE_SIZE);
|
||||
//done !
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void vtlb_Reset()
|
||||
{
|
||||
for(int i=0; i<48; i++) UnmapTLB(i);
|
||||
}
|
||||
|
||||
void vtlb_Term()
|
||||
{
|
||||
//nothing to do for now
|
||||
|
|
|
@ -29,6 +29,7 @@ typedef void __fastcall vltbMemW128FP(u32 addr,const mem128_t* data);
|
|||
typedef u32 vtlbHandler;
|
||||
|
||||
bool vtlb_Init();
|
||||
void vtlb_Reset();
|
||||
void vtlb_Term();
|
||||
|
||||
//physical stuff
|
||||
|
|
|
@ -0,0 +1,182 @@
|
|||
/* Pcsx2 - Pc Ps2 Emulator
|
||||
* Copyright (C) 2002-2008 Pcsx2 Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include "Win32.h"
|
||||
#include <windowsx.h>
|
||||
|
||||
#include "Common.h"
|
||||
#include "ix86/ix86.h"
|
||||
|
||||
// the EE and VU roundmodes are passed in so that we can "retain" the config values during
|
||||
// default button action. The checkbox statuses are checked against the Config settings when
|
||||
// the user hits OK, and the game only resets if they differ.
|
||||
|
||||
static void InitRoundClampModes( HWND hDlg, u32 new_eeopt, u32 new_vuopt )
|
||||
{
|
||||
CheckRadioButton(hDlg, IDC_EE_ROUNDMODE0, IDC_EE_ROUNDMODE3, IDC_EE_ROUNDMODE0 + ((Config.sseMXCSR & 0x6000) >> 13));
|
||||
CheckRadioButton(hDlg, IDC_VU_ROUNDMODE0, IDC_VU_ROUNDMODE3, IDC_VU_ROUNDMODE0 + ((Config.sseVUMXCSR & 0x6000) >> 13));
|
||||
CheckRadioButton(hDlg, IDC_EE_CLAMPMODE0, IDC_EE_CLAMPMODE2, IDC_EE_CLAMPMODE0 + ((new_eeopt & 0x2) ? 2 : (new_eeopt & 0x1)));
|
||||
|
||||
if (new_vuopt & 0x4) CheckRadioButton(hDlg, IDC_VU_CLAMPMODE0, IDC_VU_CLAMPMODE3, IDC_VU_CLAMPMODE0 + 3);
|
||||
else if (new_vuopt & 0x2) CheckRadioButton(hDlg, IDC_VU_CLAMPMODE0, IDC_VU_CLAMPMODE3, IDC_VU_CLAMPMODE0 + 2);
|
||||
else if (new_vuopt & 0x1) CheckRadioButton(hDlg, IDC_VU_CLAMPMODE0, IDC_VU_CLAMPMODE3, IDC_VU_CLAMPMODE0 + 1);
|
||||
else CheckRadioButton(hDlg, IDC_VU_CLAMPMODE0, IDC_VU_CLAMPMODE3, IDC_VU_CLAMPMODE0 + 0);
|
||||
|
||||
if (Config.sseMXCSR & 0x8000) CheckDlgButton(hDlg, IDC_EE_CHECK1, TRUE);
|
||||
if (Config.sseVUMXCSR & 0x8000) CheckDlgButton(hDlg, IDC_VU_CHECK1, TRUE);
|
||||
}
|
||||
|
||||
BOOL APIENTRY AdvancedOptionsProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch (message)
|
||||
{
|
||||
case WM_INITDIALOG:
|
||||
|
||||
InitRoundClampModes( hDlg, Config.eeOptions, Config.vuOptions );
|
||||
|
||||
if( !cpucaps.hasStreamingSIMD2Extensions ) {
|
||||
// SSE1 cpus do not support Denormals Are Zero flag.
|
||||
Config.sseMXCSR &= ~0x0040;
|
||||
Config.sseVUMXCSR &= ~0x0040;
|
||||
EnableWindow( GetDlgItem( hDlg, IDC_EE_CHECK2 ), FALSE );
|
||||
EnableWindow( GetDlgItem( hDlg, IDC_VU_CHECK2 ), FALSE );
|
||||
CheckDlgButton( hDlg, IDC_EE_CHECK2, FALSE );
|
||||
CheckDlgButton( hDlg, IDC_VU_CHECK2, FALSE );
|
||||
}
|
||||
else {
|
||||
if (Config.sseMXCSR & 0x0040) CheckDlgButton(hDlg, IDC_EE_CHECK2, TRUE);
|
||||
if (Config.sseVUMXCSR & 0x0040) CheckDlgButton(hDlg, IDC_VU_CHECK2, TRUE);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
||||
case WM_COMMAND:
|
||||
switch (LOWORD(wParam))
|
||||
{
|
||||
case IDOK:
|
||||
{
|
||||
u32 new_eeopt = 0;
|
||||
u32 new_vuopt = 0;
|
||||
|
||||
Config.sseMXCSR &= 0x1fbf;
|
||||
Config.sseVUMXCSR &= 0x1fbf;
|
||||
|
||||
Config.sseMXCSR |= IsDlgButtonChecked(hDlg, IDC_EE_ROUNDMODE0) ? 0x0000 : 0; // Round Nearest
|
||||
Config.sseMXCSR |= IsDlgButtonChecked(hDlg, IDC_EE_ROUNDMODE1) ? 0x2000 : 0; // Round Negative
|
||||
Config.sseMXCSR |= IsDlgButtonChecked(hDlg, IDC_EE_ROUNDMODE2) ? 0x4000 : 0; // Round Postive
|
||||
Config.sseMXCSR |= IsDlgButtonChecked(hDlg, IDC_EE_ROUNDMODE3) ? 0x6000 : 0; // Round Zero / Chop
|
||||
|
||||
Config.sseVUMXCSR |= IsDlgButtonChecked(hDlg, IDC_VU_ROUNDMODE0) ? 0x0000 : 0; // Round Nearest
|
||||
Config.sseVUMXCSR |= IsDlgButtonChecked(hDlg, IDC_VU_ROUNDMODE1) ? 0x2000 : 0; // Round Negative
|
||||
Config.sseVUMXCSR |= IsDlgButtonChecked(hDlg, IDC_VU_ROUNDMODE2) ? 0x4000 : 0; // Round Postive
|
||||
Config.sseVUMXCSR |= IsDlgButtonChecked(hDlg, IDC_VU_ROUNDMODE3) ? 0x6000 : 0; // Round Zero / Chop
|
||||
|
||||
new_eeopt |= IsDlgButtonChecked(hDlg, IDC_EE_CLAMPMODE0) ? 0x0 : 0;
|
||||
new_eeopt |= IsDlgButtonChecked(hDlg, IDC_EE_CLAMPMODE1) ? 0x1 : 0;
|
||||
new_eeopt |= IsDlgButtonChecked(hDlg, IDC_EE_CLAMPMODE2) ? 0x3 : 0;
|
||||
|
||||
new_vuopt |= IsDlgButtonChecked(hDlg, IDC_VU_CLAMPMODE0) ? 0x0 : 0;
|
||||
new_vuopt |= IsDlgButtonChecked(hDlg, IDC_VU_CLAMPMODE1) ? 0x1 : 0;
|
||||
new_vuopt |= IsDlgButtonChecked(hDlg, IDC_VU_CLAMPMODE2) ? 0x3 : 0;
|
||||
new_vuopt |= IsDlgButtonChecked(hDlg, IDC_VU_CLAMPMODE3) ? 0x7 : 0;
|
||||
|
||||
Config.sseMXCSR |= IsDlgButtonChecked(hDlg, IDC_EE_CHECK1) ? 0x8000 : 0; // FtZ
|
||||
Config.sseVUMXCSR |= IsDlgButtonChecked(hDlg, IDC_VU_CHECK1) ? 0x8000 : 0; // FtZ
|
||||
|
||||
Config.sseMXCSR |= IsDlgButtonChecked(hDlg, IDC_EE_CHECK2) ? 0x0040 : 0; // DaZ
|
||||
Config.sseVUMXCSR |= IsDlgButtonChecked(hDlg, IDC_VU_CHECK2) ? 0x0040 : 0; // DaZ
|
||||
|
||||
EndDialog(hDlg, TRUE);
|
||||
|
||||
// Roundmode options do not require CPU resets to take effect.
|
||||
SetCPUState(Config.sseMXCSR, Config.sseVUMXCSR);
|
||||
|
||||
if( new_eeopt != Config.eeOptions || new_vuopt != Config.vuOptions )
|
||||
{
|
||||
// these do, however...
|
||||
Config.eeOptions = new_eeopt;
|
||||
Config.vuOptions = new_vuopt;
|
||||
SysRestorableReset();
|
||||
}
|
||||
|
||||
SaveConfig();
|
||||
break;
|
||||
}
|
||||
|
||||
case IDCANCEL:
|
||||
|
||||
EndDialog(hDlg, FALSE);
|
||||
break;
|
||||
|
||||
case IDDEFAULT:
|
||||
|
||||
Config.sseMXCSR = DEFAULT_sseMXCSR;
|
||||
Config.sseVUMXCSR = DEFAULT_sseVUMXCSR;
|
||||
|
||||
// SSE1 cpus do not support Denormals Are Zero flag.
|
||||
if( !cpucaps.hasStreamingSIMD2Extensions ) {
|
||||
Config.sseMXCSR &= ~0x0040;
|
||||
Config.sseVUMXCSR &= ~0x0040;
|
||||
}
|
||||
|
||||
InitRoundClampModes( hDlg, DEFAULT_eeOptions, DEFAULT_vuOptions );
|
||||
|
||||
CheckDlgButton(hDlg, IDC_EE_CHECK1, (Config.sseMXCSR & 0x8000) ? TRUE : FALSE);
|
||||
CheckDlgButton(hDlg, IDC_VU_CHECK1, (Config.sseVUMXCSR & 0x8000) ? TRUE : FALSE);
|
||||
|
||||
CheckDlgButton(hDlg, IDC_EE_CHECK2, (Config.sseMXCSR & 0x0040) ? TRUE : FALSE);
|
||||
CheckDlgButton(hDlg, IDC_VU_CHECK2, (Config.sseVUMXCSR & 0x0040) ? TRUE : FALSE);
|
||||
break;
|
||||
|
||||
case IDC_EE_ROUNDMODE0:
|
||||
case IDC_EE_ROUNDMODE1:
|
||||
case IDC_EE_ROUNDMODE2:
|
||||
case IDC_EE_ROUNDMODE3:
|
||||
|
||||
CheckRadioButton(hDlg, IDC_EE_ROUNDMODE0, IDC_EE_ROUNDMODE3, IDC_EE_ROUNDMODE0 + ( LOWORD(wParam) % IDC_EE_ROUNDMODE0 ) );
|
||||
break;
|
||||
|
||||
case IDC_VU_ROUNDMODE0:
|
||||
case IDC_VU_ROUNDMODE1:
|
||||
case IDC_VU_ROUNDMODE2:
|
||||
case IDC_VU_ROUNDMODE3:
|
||||
|
||||
CheckRadioButton(hDlg, IDC_VU_ROUNDMODE0, IDC_VU_ROUNDMODE3, IDC_VU_ROUNDMODE0 + ( LOWORD(wParam) % IDC_VU_ROUNDMODE0 ) );
|
||||
break;
|
||||
|
||||
case IDC_EE_CLAMPMODE0:
|
||||
case IDC_EE_CLAMPMODE1:
|
||||
case IDC_EE_CLAMPMODE2:
|
||||
|
||||
CheckRadioButton(hDlg, IDC_EE_CLAMPMODE0, IDC_EE_CLAMPMODE2, IDC_EE_CLAMPMODE0 + ( LOWORD(wParam) % IDC_EE_CLAMPMODE0 ) );
|
||||
break;
|
||||
|
||||
case IDC_VU_CLAMPMODE0:
|
||||
case IDC_VU_CLAMPMODE1:
|
||||
case IDC_VU_CLAMPMODE2:
|
||||
case IDC_VU_CLAMPMODE3:
|
||||
|
||||
CheckRadioButton(hDlg, IDC_VU_CLAMPMODE0, IDC_VU_CLAMPMODE3, IDC_VU_CLAMPMODE0 + ( LOWORD(wParam) % IDC_VU_CLAMPMODE0 ) );
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
|
@ -16,7 +16,8 @@
|
|||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
#include "Win32.h"
|
||||
|
||||
#include <windowsx.h>
|
||||
#include <shlobj.h>
|
||||
#include <stdio.h>
|
||||
|
@ -24,7 +25,6 @@
|
|||
#include "common.h"
|
||||
#include "plugins.h"
|
||||
#include "resource.h"
|
||||
#include "Win32.h"
|
||||
|
||||
#define ComboAddPlugin(hw, str) { \
|
||||
sprintf(tmpStr, "%s %d.%d.%d", PS2E_GetLibName(), (version>>8)&0xff, version&0xff, (version>>24)&0xff); \
|
||||
|
@ -251,7 +251,7 @@ void OnOK(HWND hW) {
|
|||
ApplyPluginPath( FW );
|
||||
|
||||
SaveConfig();
|
||||
needReset = 1;
|
||||
SysRestorableReset();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -26,6 +26,18 @@ namespace Console
|
|||
{
|
||||
static HANDLE hConsole = NULL;
|
||||
|
||||
static const int tbl_color_codes[] =
|
||||
{
|
||||
0 // black
|
||||
, FOREGROUND_RED | FOREGROUND_INTENSITY
|
||||
, FOREGROUND_GREEN | FOREGROUND_INTENSITY
|
||||
, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY
|
||||
, FOREGROUND_BLUE | FOREGROUND_INTENSITY
|
||||
, FOREGROUND_RED | FOREGROUND_BLUE
|
||||
, FOREGROUND_GREEN | FOREGROUND_BLUE
|
||||
, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY
|
||||
};
|
||||
|
||||
void SetTitle( const char* title )
|
||||
{
|
||||
if( !hConsole || title==NULL ) return;
|
||||
|
@ -61,6 +73,19 @@ namespace Console
|
|||
hConsole = NULL;
|
||||
}
|
||||
|
||||
__forceinline void __fastcall SetColor( Colors color )
|
||||
{
|
||||
SetConsoleTextAttribute( hConsole, tbl_color_codes[color] );
|
||||
}
|
||||
|
||||
__forceinline void ClearColor()
|
||||
{
|
||||
SetConsoleTextAttribute( hConsole,
|
||||
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE );
|
||||
}
|
||||
|
||||
|
||||
// Writes a newline to the console.
|
||||
__forceinline bool __fastcall WriteLn()
|
||||
{
|
||||
if (hConsole != NULL)
|
||||
|
@ -78,6 +103,8 @@ namespace Console
|
|||
return false;
|
||||
}
|
||||
|
||||
// Writes an unformatted string of text to the console (fast!)
|
||||
// No newline is appended.
|
||||
__forceinline bool __fastcall Write( const char* fmt )
|
||||
{
|
||||
if (hConsole != NULL)
|
||||
|
@ -93,6 +120,8 @@ namespace Console
|
|||
return false;
|
||||
}
|
||||
|
||||
// Writes an unformatted string of text to the console (fast!)
|
||||
// A newline is automatically appended.
|
||||
__forceinline bool __fastcall WriteLn( const char* fmt )
|
||||
{
|
||||
Write( fmt );
|
||||
|
@ -100,13 +129,39 @@ namespace Console
|
|||
return false;
|
||||
}
|
||||
|
||||
bool Format( const char* fmt, ... )
|
||||
// Writes a formatted message to the console, with appended newline.
|
||||
static __forceinline void __fastcall _MsgLn( Colors color, const char* fmt, va_list args )
|
||||
{
|
||||
char msg[2048];
|
||||
|
||||
vsprintf_s(msg,2045,fmt,args);
|
||||
strcat( msg, "\r\n" );
|
||||
SetColor( color );
|
||||
Write( msg );
|
||||
ClearColor();
|
||||
|
||||
if( emuLog != NULL )
|
||||
fflush( emuLog ); // manual flush to accompany manual newline
|
||||
}
|
||||
|
||||
// Writes a line of colored text to the console, with automatic newline appendage.
|
||||
bool MsgLn( Colors color, const char* fmt, ... )
|
||||
{
|
||||
va_list list;
|
||||
va_start(list,fmt);
|
||||
_MsgLn( Color_White, fmt, list );
|
||||
va_end(list);
|
||||
return false;
|
||||
}
|
||||
|
||||
// writes a formatted message to the console (no newline and no color)
|
||||
bool Msg( const char* fmt, ... )
|
||||
{
|
||||
va_list list;
|
||||
char msg[2048];
|
||||
|
||||
va_start(list,fmt);
|
||||
_vsnprintf(msg,2047,fmt,list);
|
||||
vsprintf_s(msg,fmt,list);
|
||||
msg[2047] = '\0';
|
||||
va_end(list);
|
||||
|
||||
|
@ -114,13 +169,32 @@ namespace Console
|
|||
return false;
|
||||
}
|
||||
|
||||
bool FormatLn( const char* fmt, ... )
|
||||
// writes a formatted message to the console (no newline and no color)
|
||||
bool Msg( Colors color, const char* fmt, ... )
|
||||
{
|
||||
va_list list;
|
||||
char msg[2048];
|
||||
|
||||
va_start(list,fmt);
|
||||
_vsnprintf(msg,2045,fmt,list);
|
||||
vsprintf_s(msg,fmt,list);
|
||||
msg[2047] = '\0';
|
||||
va_end(list);
|
||||
|
||||
SetColor( color );
|
||||
Write( msg );
|
||||
ClearColor();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Writes a formatted message to the console, with appended newline.
|
||||
// (no coloring)
|
||||
bool MsgLn( const char* fmt, ... )
|
||||
{
|
||||
va_list list;
|
||||
char msg[2048];
|
||||
|
||||
va_start(list,fmt);
|
||||
vsprintf_s(msg,2045,fmt,list);
|
||||
va_end(list);
|
||||
|
||||
strcat( msg, "\r\n" );
|
||||
|
@ -129,4 +203,26 @@ namespace Console
|
|||
fflush( emuLog ); // manual flush to accomany manual newline
|
||||
return false;
|
||||
}
|
||||
|
||||
// Displays a message in the console with red emphasis.
|
||||
// Newline is automatically appended.
|
||||
bool Error( const char* fmt, ... )
|
||||
{
|
||||
va_list list;
|
||||
va_start(list,fmt);
|
||||
_MsgLn( Color_Red, fmt, list );
|
||||
va_end(list);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Displays a message in the console with yellow emphasis.
|
||||
// Newline is automatically appended.
|
||||
bool Notice( const char* fmt, ... )
|
||||
{
|
||||
va_list list;
|
||||
va_start(list,fmt);
|
||||
_MsgLn( Color_Yellow, fmt, list );
|
||||
va_end(list);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,17 +16,14 @@
|
|||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
#include "Win32.h"
|
||||
#include <windowsx.h>
|
||||
#include <commctrl.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "Common.h"
|
||||
#include "VUmicro.h"
|
||||
#include "PsxCommon.h"
|
||||
#include "plugins.h"
|
||||
#include "resource.h"
|
||||
#include "Win32.h"
|
||||
|
||||
#include "ix86/ix86.h"
|
||||
|
||||
|
@ -69,8 +66,6 @@ BOOL CALLBACK CpuDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|||
Static_SetText(GetDlgItem(hW, IDC_FRAMESKIP_LABEL5), _("Consecutive Frames to skip:\n(See Note 3)"));
|
||||
Static_SetText(GetDlgItem(hW, IDC_FRAMESKIP_LABEL6), _("*Note 3: Will skip this number of frames before\n rendering the next sequence of frames. (0=default)\n (e.g. If set to 2, will skip 2 consecutive frames whenever its time\n to skip.)"));
|
||||
|
||||
|
||||
|
||||
Button_SetText(GetDlgItem(hW, IDOK), _("OK"));
|
||||
Button_SetText(GetDlgItem(hW, IDCANCEL), _("Cancel"));
|
||||
|
||||
|
@ -88,17 +83,8 @@ BOOL CALLBACK CpuDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|||
SetDlgItemText(hW, IDC_FEATURESINPUT, features);
|
||||
|
||||
CheckDlgButton(hW, IDC_CPU_EEREC, !!CHECK_EEREC);
|
||||
|
||||
//#ifdef PCSX2_DEVBUILD
|
||||
CheckDlgButton(hW, IDC_CPU_VU0REC, !!CHECK_VU0REC);
|
||||
CheckDlgButton(hW, IDC_CPU_VU1REC, !!CHECK_VU1REC);
|
||||
//#else
|
||||
// // don't show
|
||||
// ShowWindow(GetDlgItem(hW, IDC_CPU_VUGROUP), SW_HIDE);
|
||||
// ShowWindow(GetDlgItem(hW, IDC_CPU_VU0REC), SW_HIDE);
|
||||
// ShowWindow(GetDlgItem(hW, IDC_CPU_VU1REC), SW_HIDE);
|
||||
//#endif
|
||||
|
||||
|
||||
CheckDlgButton(hW, IDC_CPU_GSMULTI, !!CHECK_MULTIGS);
|
||||
|
||||
|
@ -116,19 +102,18 @@ BOOL CALLBACK CpuDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|||
sprintf(cConsecutiveSkip,"%d",Config.CustomConsecutiveSkip);
|
||||
SetDlgItemText(hW, IDC_CUSTOM_CONSECUTIVE_SKIP, cConsecutiveSkip);
|
||||
|
||||
//EnableWindow( GetDlgItem( hW, IDC_CPU_GSMULTI ), !g_GameInProgress );
|
||||
|
||||
return TRUE;
|
||||
|
||||
case WM_COMMAND:
|
||||
switch(LOWORD(wParam)) {
|
||||
switch(LOWORD(wParam))
|
||||
{
|
||||
case IDCANCEL:
|
||||
EndDialog(hW, FALSE);
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
|
||||
case IDOK:
|
||||
Cpu->Shutdown();
|
||||
vu0Shutdown();
|
||||
vu1Shutdown();
|
||||
|
||||
newopts = 0;
|
||||
|
||||
if( SendDlgItemMessage(hW,IDC_CPU_EEREC,BM_GETCHECK,0,0) ) newopts |= PCSX2_EEREC;
|
||||
|
@ -143,17 +128,8 @@ BOOL CALLBACK CpuDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|||
else if( SendDlgItemMessage(hW,IDC_CPU_FL_SKIP,BM_GETCHECK,0,0) ) newopts |= PCSX2_FRAMELIMIT_SKIP;
|
||||
else if( SendDlgItemMessage(hW,IDC_CPU_FL_SKIPVU,BM_GETCHECK,0,0) ) newopts |= PCSX2_FRAMELIMIT_VUSKIP;
|
||||
|
||||
if( (Config.Options&PCSX2_GSMULTITHREAD) ^ (newopts&PCSX2_GSMULTITHREAD) ) {
|
||||
Config.Options = newopts;
|
||||
SaveConfig();
|
||||
MessageBox(NULL, "Restart Pcsx2", "Query", MB_OK);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if( newopts & PCSX2_EEREC ) newopts |= PCSX2_COP2REC;
|
||||
|
||||
Config.Options = newopts;
|
||||
|
||||
GetDlgItemText(hW, IDC_CUSTOMFPS, cfps, 20);
|
||||
Config.CustomFps = atoi(cfps);
|
||||
|
||||
|
@ -166,15 +142,27 @@ BOOL CALLBACK CpuDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|||
GetDlgItemText(hW, IDC_CUSTOM_CONSECUTIVE_SKIP, cConsecutiveSkip, 20);
|
||||
Config.CustomConsecutiveSkip = atoi(cConsecutiveSkip);
|
||||
|
||||
// [TODO]: This needs to inform the GS too, but it doesn't matter for now
|
||||
// since the CPU is reset regardless.
|
||||
UpdateVSyncRate();
|
||||
EndDialog(hW, TRUE);
|
||||
|
||||
if( Config.Options != newopts )
|
||||
{
|
||||
SysRestorableReset();
|
||||
|
||||
if( (Config.Options&PCSX2_GSMULTITHREAD) ^ (newopts&PCSX2_GSMULTITHREAD) )
|
||||
{
|
||||
// gotta shut down *all* the plugins.
|
||||
ResetPlugins();
|
||||
}
|
||||
Config.Options = newopts;
|
||||
}
|
||||
else
|
||||
UpdateVSyncRate();
|
||||
|
||||
SaveConfig();
|
||||
|
||||
cpuRestartCPU();
|
||||
EndDialog(hW, TRUE);
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
|
|
@ -16,8 +16,7 @@
|
|||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
#include <commctrl.h>
|
||||
#include "win32.h"
|
||||
#include <windowsx.h>
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
|
@ -26,7 +25,6 @@
|
|||
#include "InterTables.h"
|
||||
#include "Debugger.h"
|
||||
#include "Common.h"
|
||||
#include "win32.h"
|
||||
#include "PsxMem.h"
|
||||
#include "R3000A.h"
|
||||
|
||||
|
|
|
@ -23,10 +23,9 @@
|
|||
* no interaction with emulation code
|
||||
***************************/
|
||||
|
||||
#include <windows.h>
|
||||
#include "win32.h"
|
||||
#include <windowsx.h>
|
||||
#include "Common.h"
|
||||
#include "win32.h"
|
||||
#include "resource.h"
|
||||
|
||||
/*
|
||||
|
|
|
@ -17,8 +17,7 @@
|
|||
*/
|
||||
|
||||
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#include "win32.h"
|
||||
#include <commctrl.h>
|
||||
#include <windowsx.h>
|
||||
#include "resource.h"
|
||||
|
@ -26,7 +25,6 @@
|
|||
#include "RDebugger.h"
|
||||
#include "Common.h"
|
||||
#include "PsxCommon.h"
|
||||
#include "win32.h"
|
||||
#include "../rdebug/deci2.h"
|
||||
|
||||
u32 port=8510;
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
SmallerTypeCheck="false"
|
||||
CompileAs="2"
|
||||
/>
|
||||
<Tool
|
||||
|
@ -123,6 +124,9 @@
|
|||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
MinimalRebuild="true"
|
||||
SmallerTypeCheck="false"
|
||||
EnableFunctionLevelLinking="true"
|
||||
CompileAs="2"
|
||||
/>
|
||||
<Tool
|
||||
|
@ -195,6 +199,10 @@
|
|||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
MinimalRebuild="true"
|
||||
ExceptionHandling="1"
|
||||
SmallerTypeCheck="false"
|
||||
EnableFunctionLevelLinking="true"
|
||||
CompileAs="2"
|
||||
/>
|
||||
<Tool
|
||||
|
@ -279,6 +287,7 @@
|
|||
PreprocessorDefinitions="NDEBUG,WIN32,_WINDOWS,__MSCW32__,__WIN32__,__i386__,ENABLE_NLS,PACKAGE=\"pcsx2\";PCSX2_DEVBUILD;_CRT_SECURE_NO_DEPRECATE;TIXML_USE_STL"
|
||||
StringPooling="true"
|
||||
ExceptionHandling="1"
|
||||
SmallerTypeCheck="false"
|
||||
RuntimeLibrary="0"
|
||||
StructMemberAlignment="5"
|
||||
BufferSecurityCheck="false"
|
||||
|
@ -363,6 +372,7 @@
|
|||
Name="VCCLCompilerTool"
|
||||
EnableFiberSafeOptimizations="true"
|
||||
PreprocessorDefinitions="NDEBUG"
|
||||
SmallerTypeCheck="false"
|
||||
EnableEnhancedInstructionSet="0"
|
||||
CompileAs="2"
|
||||
/>
|
||||
|
@ -441,6 +451,7 @@
|
|||
Name="VCCLCompilerTool"
|
||||
EnableFiberSafeOptimizations="true"
|
||||
PreprocessorDefinitions="NDEBUG"
|
||||
SmallerTypeCheck="false"
|
||||
EnableEnhancedInstructionSet="0"
|
||||
CompileAs="2"
|
||||
/>
|
||||
|
@ -496,6 +507,10 @@
|
|||
RelativePath="..\AboutDlg.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\AdvancedDlg.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\Cdrom02.ico"
|
||||
>
|
||||
|
@ -552,6 +567,10 @@
|
|||
RelativePath="..\WinMain.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\WinVM.cpp"
|
||||
>
|
||||
</File>
|
||||
<Filter
|
||||
Name="Debugger"
|
||||
>
|
||||
|
@ -608,6 +627,10 @@
|
|||
<Filter
|
||||
Name="Misc"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\Exceptions.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\x86\fast_routines.cpp"
|
||||
>
|
||||
|
@ -640,6 +663,14 @@
|
|||
RelativePath="..\..\SamplProf.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\SaveState.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\SaveState.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\SourceLog.cpp"
|
||||
>
|
||||
|
|
|
@ -16,11 +16,17 @@
|
|||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef __WIN32_H__
|
||||
#define __WIN32_H__
|
||||
#ifndef _PCSX2_WIN32_H__
|
||||
#define _PCSX2_WIN32_H__
|
||||
|
||||
#define WINVER 0x0501
|
||||
#define _WIN32_WINNT 0x0501
|
||||
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
|
||||
#include "Misc.h"
|
||||
#include "resource.h"
|
||||
|
||||
// --->> Ini Configuration [ini.c]
|
||||
|
||||
|
@ -39,30 +45,28 @@ struct AppData
|
|||
HMENU hMenu; // Main window menu
|
||||
};
|
||||
|
||||
extern AppData gApp;
|
||||
|
||||
extern int needReset;
|
||||
|
||||
extern AppData gApp;
|
||||
extern HWND hStatusWnd;
|
||||
extern PcsxConfig winConfig; // local storage of the configuration options.
|
||||
extern bool g_GameInProgress;
|
||||
|
||||
LRESULT WINAPI MainWndProc(HWND, UINT, WPARAM, LPARAM);
|
||||
void CreateMainWindow(int nCmdShow);
|
||||
void RunGui();
|
||||
|
||||
BOOL Open_File_Proc(char *filename);
|
||||
BOOL Pcsx2Configure(HWND hWnd);
|
||||
void RunExecute(int run);
|
||||
void InitLanguages();
|
||||
char *GetLanguageNext();
|
||||
void CloseLanguages();
|
||||
void ChangeLanguage(char *lang);
|
||||
#define StatusSet(text) SendMessage(hStatusWnd, SB_SETTEXT, 0, (LPARAM)text);
|
||||
#define StatusSet(text) SendMessage(hStatusWnd, SB_SETTEXT, 0, (LPARAM)(text));
|
||||
|
||||
void SysRestorableReset();
|
||||
|
||||
//patch browser window
|
||||
BOOL CALLBACK PatchBDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
//cpu dialog window
|
||||
BOOL CALLBACK CpuDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
BOOL CALLBACK AdvancedOptionsProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,470 @@
|
|||
/* Pcsx2 - Pc Ps2 Emulator
|
||||
* Copyright (C) 2002-2008 Pcsx2 Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include "win32.h"
|
||||
#include <windowsx.h>
|
||||
|
||||
|
||||
#ifdef PCSX2_VIRTUAL_MEM
|
||||
|
||||
// virtual memory/privileges
|
||||
#include "ntsecapi.h"
|
||||
|
||||
static wchar_t s_szUserName[255];
|
||||
|
||||
LRESULT WINAPI UserNameProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
|
||||
switch(uMsg) {
|
||||
case WM_INITDIALOG:
|
||||
SetWindowPos(hDlg, HWND_TOPMOST, 200, 100, 0, 0, SWP_NOSIZE);
|
||||
return TRUE;
|
||||
|
||||
case WM_COMMAND:
|
||||
switch(wParam) {
|
||||
case IDOK:
|
||||
{
|
||||
wchar_t str[255];
|
||||
GetWindowTextW(GetDlgItem(hDlg, IDC_USER_NAME), str, 255);
|
||||
swprintf(s_szUserName, 255, L"%S", str);
|
||||
EndDialog(hDlg, TRUE );
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
case IDCANCEL:
|
||||
EndDialog(hDlg, FALSE );
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL InitLsaString(
|
||||
PLSA_UNICODE_STRING pLsaString,
|
||||
LPCWSTR pwszString
|
||||
)
|
||||
{
|
||||
DWORD dwLen = 0;
|
||||
|
||||
if (NULL == pLsaString)
|
||||
return FALSE;
|
||||
|
||||
if (NULL != pwszString)
|
||||
{
|
||||
dwLen = wcslen(pwszString);
|
||||
if (dwLen > 0x7ffe) // String is too large
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Store the string.
|
||||
pLsaString->Buffer = (WCHAR *)pwszString;
|
||||
pLsaString->Length = (USHORT)dwLen * sizeof(WCHAR);
|
||||
pLsaString->MaximumLength= (USHORT)(dwLen+1) * sizeof(WCHAR);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
PLSA_TRANSLATED_SID2 GetSIDInformation (LPWSTR AccountName,LSA_HANDLE PolicyHandle)
|
||||
{
|
||||
LSA_UNICODE_STRING lucName;
|
||||
PLSA_TRANSLATED_SID2 ltsTranslatedSID;
|
||||
PLSA_REFERENCED_DOMAIN_LIST lrdlDomainList;
|
||||
//LSA_TRUST_INFORMATION myDomain;
|
||||
NTSTATUS ntsResult;
|
||||
PWCHAR DomainString = NULL;
|
||||
|
||||
// Initialize an LSA_UNICODE_STRING with the name.
|
||||
if (!InitLsaString(&lucName, AccountName))
|
||||
{
|
||||
wprintf(L"Failed InitLsaString\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ntsResult = LsaLookupNames2(
|
||||
PolicyHandle, // handle to a Policy object
|
||||
0,
|
||||
1, // number of names to look up
|
||||
&lucName, // pointer to an array of names
|
||||
&lrdlDomainList, // receives domain information
|
||||
<sTranslatedSID // receives relative SIDs
|
||||
);
|
||||
if (0 != ntsResult)
|
||||
{
|
||||
wprintf(L"Failed LsaLookupNames - %lu \n",
|
||||
LsaNtStatusToWinError(ntsResult));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Get the domain the account resides in.
|
||||
// myDomain = lrdlDomainList->Domains[ltsTranslatedSID->DomainIndex];
|
||||
// DomainString = (PWCHAR) LocalAlloc(LPTR, myDomain.Name.Length + 1);
|
||||
// wcsncpy(DomainString, myDomain.Name.Buffer, myDomain.Name.Length);
|
||||
|
||||
// Display the relative Id.
|
||||
// wprintf(L"Relative Id is %lu in domain %ws.\n",
|
||||
// ltsTranslatedSID->RelativeId,
|
||||
// DomainString);
|
||||
|
||||
LsaFreeMemory(lrdlDomainList);
|
||||
|
||||
return ltsTranslatedSID;
|
||||
}
|
||||
|
||||
BOOL AddPrivileges(PSID AccountSID, LSA_HANDLE PolicyHandle, BOOL bAdd)
|
||||
{
|
||||
LSA_UNICODE_STRING lucPrivilege;
|
||||
NTSTATUS ntsResult;
|
||||
|
||||
// Create an LSA_UNICODE_STRING for the privilege name(s).
|
||||
if (!InitLsaString(&lucPrivilege, L"SeLockMemoryPrivilege"))
|
||||
{
|
||||
wprintf(L"Failed InitLsaString\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if( bAdd ) {
|
||||
ntsResult = LsaAddAccountRights(
|
||||
PolicyHandle, // An open policy handle.
|
||||
AccountSID, // The target SID.
|
||||
&lucPrivilege, // The privilege(s).
|
||||
1 // Number of privileges.
|
||||
);
|
||||
}
|
||||
else {
|
||||
ntsResult = LsaRemoveAccountRights(
|
||||
PolicyHandle, // An open policy handle.
|
||||
AccountSID, // The target SID
|
||||
FALSE,
|
||||
&lucPrivilege, // The privilege(s).
|
||||
1 // Number of privileges.
|
||||
);
|
||||
}
|
||||
|
||||
if (ntsResult == 0)
|
||||
{
|
||||
wprintf(L"Privilege added.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
int err = LsaNtStatusToWinError(ntsResult);
|
||||
char str[255];
|
||||
_snprintf(str, 255, "Privilege was not added - %lu \n", LsaNtStatusToWinError(ntsResult));
|
||||
MessageBox(NULL, str, "Privilege error", MB_OK);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#define TARGET_SYSTEM_NAME L"mysystem"
|
||||
LSA_HANDLE GetPolicyHandle()
|
||||
{
|
||||
LSA_OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
WCHAR SystemName[] = TARGET_SYSTEM_NAME;
|
||||
USHORT SystemNameLength;
|
||||
LSA_UNICODE_STRING lusSystemName;
|
||||
NTSTATUS ntsResult;
|
||||
LSA_HANDLE lsahPolicyHandle;
|
||||
|
||||
// Object attributes are reserved, so initialize to zeroes.
|
||||
ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
|
||||
|
||||
//Initialize an LSA_UNICODE_STRING to the server name.
|
||||
SystemNameLength = wcslen(SystemName);
|
||||
lusSystemName.Buffer = SystemName;
|
||||
lusSystemName.Length = SystemNameLength * sizeof(WCHAR);
|
||||
lusSystemName.MaximumLength = (SystemNameLength+1) * sizeof(WCHAR);
|
||||
|
||||
// Get a handle to the Policy object.
|
||||
ntsResult = LsaOpenPolicy(
|
||||
NULL, //Name of the target system.
|
||||
&ObjectAttributes, //Object attributes.
|
||||
POLICY_ALL_ACCESS, //Desired access permissions.
|
||||
&lsahPolicyHandle //Receives the policy handle.
|
||||
);
|
||||
|
||||
if (ntsResult != 0)
|
||||
{
|
||||
// An error occurred. Display it as a win32 error code.
|
||||
wprintf(L"OpenPolicy returned %lu\n",
|
||||
LsaNtStatusToWinError(ntsResult));
|
||||
return NULL;
|
||||
}
|
||||
return lsahPolicyHandle;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************
|
||||
LoggedSetLockPagesPrivilege: a function to obtain, if possible, or
|
||||
release the privilege of locking physical pages.
|
||||
|
||||
Inputs:
|
||||
|
||||
HANDLE hProcess: Handle for the process for which the
|
||||
privilege is needed
|
||||
|
||||
BOOL bEnable: Enable (TRUE) or disable?
|
||||
|
||||
Return value: TRUE indicates success, FALSE failure.
|
||||
|
||||
*****************************************************************/
|
||||
BOOL SysLoggedSetLockPagesPrivilege ( HANDLE hProcess, BOOL bEnable)
|
||||
{
|
||||
struct {
|
||||
u32 Count;
|
||||
LUID_AND_ATTRIBUTES Privilege [1];
|
||||
} Info;
|
||||
|
||||
HANDLE Token;
|
||||
BOOL Result;
|
||||
|
||||
// Open the token.
|
||||
|
||||
Result = OpenProcessToken ( hProcess,
|
||||
TOKEN_ADJUST_PRIVILEGES,
|
||||
& Token);
|
||||
|
||||
if( Result != TRUE ) {
|
||||
Console::Error( "VirtualMemory Error > Cannot open process token." );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Enable or disable?
|
||||
|
||||
Info.Count = 1;
|
||||
if( bEnable )
|
||||
{
|
||||
Info.Privilege[0].Attributes = SE_PRIVILEGE_ENABLED;
|
||||
}
|
||||
else
|
||||
{
|
||||
Info.Privilege[0].Attributes = SE_PRIVILEGE_REMOVED;
|
||||
}
|
||||
|
||||
// Get the LUID.
|
||||
Result = LookupPrivilegeValue ( NULL,
|
||||
SE_LOCK_MEMORY_NAME,
|
||||
&(Info.Privilege[0].Luid));
|
||||
|
||||
if( Result != TRUE )
|
||||
{
|
||||
Console::Error( "VirtualMemory Error > Cannot get privilege value for %s.", SE_LOCK_MEMORY_NAME );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Adjust the privilege.
|
||||
|
||||
Result = AdjustTokenPrivileges ( Token, FALSE,
|
||||
(PTOKEN_PRIVILEGES) &Info,
|
||||
0, NULL, NULL);
|
||||
|
||||
// Check the result.
|
||||
if( Result != TRUE )
|
||||
{
|
||||
Console::Error( "VirtualMemory Error > Cannot adjust token privileges, error %u.", GetLastError() );
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( GetLastError() != ERROR_SUCCESS )
|
||||
{
|
||||
|
||||
BOOL bSuc = FALSE;
|
||||
LSA_HANDLE policy;
|
||||
PLSA_TRANSLATED_SID2 ltsTranslatedSID;
|
||||
|
||||
// if( !DialogBox(gApp.hInstance, MAKEINTRESOURCE(IDD_USERNAME), gApp.hWnd, (DLGPROC)UserNameProc) )
|
||||
// return FALSE;
|
||||
DWORD len = sizeof(s_szUserName);
|
||||
GetUserNameW(s_szUserName, &len);
|
||||
|
||||
policy = GetPolicyHandle();
|
||||
|
||||
if( policy != NULL ) {
|
||||
|
||||
ltsTranslatedSID = GetSIDInformation(s_szUserName, policy);
|
||||
|
||||
if( ltsTranslatedSID != NULL ) {
|
||||
bSuc = AddPrivileges(ltsTranslatedSID->Sid, policy, bEnable);
|
||||
LsaFreeMemory(ltsTranslatedSID);
|
||||
}
|
||||
|
||||
LsaClose(policy);
|
||||
}
|
||||
|
||||
if( bSuc ) {
|
||||
// Get the LUID.
|
||||
LookupPrivilegeValue ( NULL, SE_LOCK_MEMORY_NAME, &(Info.Privilege[0].Luid));
|
||||
|
||||
bSuc = AdjustTokenPrivileges ( Token, FALSE, (PTOKEN_PRIVILEGES) &Info, 0, NULL, NULL);
|
||||
}
|
||||
|
||||
if( bSuc ) {
|
||||
if( MessageBox(NULL, "PCSX2 just changed your SE_LOCK_MEMORY privilege in order to gain access to physical memory.\n"
|
||||
"Log off/on and run pcsx2 again. Do you want to log off?\n",
|
||||
"Privilege changed query", MB_YESNO) == IDYES ) {
|
||||
ExitWindows(EWX_LOGOFF, 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
MessageBox(NULL, "Failed adding SE_LOCK_MEMORY privilege, please check the local policy.\n"
|
||||
"Go to security settings->Local Policies->User Rights. There should be a \"Lock pages in memory\".\n"
|
||||
"Add your user to that and log off/on. This enables pcsx2 to run at real-time by allocating physical memory.\n"
|
||||
"Also can try Control Panel->Local Security Policy->... (this does not work on Windows XP Home)\n"
|
||||
"(zerofrog)\n", "Virtual Memory Access Denied", MB_OK);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CloseHandle( Token );
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static u32 s_dwPageSize = 0;
|
||||
int SysPhysicalAlloc(u32 size, PSMEMORYBLOCK* pblock)
|
||||
{
|
||||
//#ifdef WIN32_FILE_MAPPING
|
||||
// assert(0);
|
||||
//#endif
|
||||
ULONG_PTR NumberOfPagesInitial; // initial number of pages requested
|
||||
int PFNArraySize; // memory to request for PFN array
|
||||
BOOL bResult;
|
||||
|
||||
assert( pblock != NULL );
|
||||
memset(pblock, 0, sizeof(PSMEMORYBLOCK));
|
||||
|
||||
if( s_dwPageSize == 0 ) {
|
||||
SYSTEM_INFO sSysInfo; // useful system information
|
||||
GetSystemInfo(&sSysInfo); // fill the system information structure
|
||||
s_dwPageSize = sSysInfo.dwPageSize;
|
||||
|
||||
if( s_dwPageSize != 0x1000 ) {
|
||||
SysMessage("Error! OS page size must be 4Kb!\n"
|
||||
"If for some reason the OS cannot have 4Kb pages, then run the TLB build.");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate the number of pages of memory to request.
|
||||
pblock->NumberPages = (size+s_dwPageSize-1)/s_dwPageSize;
|
||||
PFNArraySize = pblock->NumberPages * sizeof (ULONG_PTR);
|
||||
|
||||
pblock->aPFNs = (uptr*)HeapAlloc (GetProcessHeap (), 0, PFNArraySize);
|
||||
|
||||
if (pblock->aPFNs == NULL) {
|
||||
SysPrintf("Failed to allocate on heap.\n");
|
||||
goto eCleanupAndExit;
|
||||
}
|
||||
|
||||
// Allocate the physical memory.
|
||||
NumberOfPagesInitial = pblock->NumberPages;
|
||||
bResult = AllocateUserPhysicalPages( GetCurrentProcess(), (PULONG_PTR)&pblock->NumberPages, (PULONG_PTR)pblock->aPFNs );
|
||||
|
||||
if( bResult != TRUE )
|
||||
{
|
||||
SysPrintf("Cannot allocate physical pages, error %u.\n", GetLastError() );
|
||||
goto eCleanupAndExit;
|
||||
}
|
||||
|
||||
if( NumberOfPagesInitial != pblock->NumberPages )
|
||||
{
|
||||
SysPrintf("Allocated only %p of %p pages.\n", pblock->NumberPages, NumberOfPagesInitial );
|
||||
goto eCleanupAndExit;
|
||||
}
|
||||
|
||||
pblock->aVFNs = (uptr*)HeapAlloc(GetProcessHeap(), 0, PFNArraySize);
|
||||
|
||||
return 0;
|
||||
|
||||
eCleanupAndExit:
|
||||
SysPhysicalFree(pblock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
void SysPhysicalFree(PSMEMORYBLOCK* pblock)
|
||||
{
|
||||
assert( pblock != NULL );
|
||||
|
||||
// Free the physical pages.
|
||||
FreeUserPhysicalPages( GetCurrentProcess(), (PULONG_PTR)&pblock->NumberPages, (PULONG_PTR)pblock->aPFNs );
|
||||
|
||||
if( pblock->aPFNs != NULL ) HeapFree(GetProcessHeap(), 0, pblock->aPFNs);
|
||||
if( pblock->aVFNs != NULL ) HeapFree(GetProcessHeap(), 0, pblock->aVFNs);
|
||||
memset(pblock, 0, sizeof(PSMEMORYBLOCK));
|
||||
}
|
||||
|
||||
int SysVirtualPhyAlloc(void* base, u32 size, PSMEMORYBLOCK* pblock)
|
||||
{
|
||||
BOOL bResult;
|
||||
int i;
|
||||
|
||||
LPVOID lpMemReserved = VirtualAlloc( base, size, MEM_RESERVE | MEM_PHYSICAL, PAGE_READWRITE );
|
||||
if( lpMemReserved == NULL || base != lpMemReserved )
|
||||
{
|
||||
Console::MsgLn("VirtualMemory Error %d > Cannot reserve memory at 0x%8.8x(%x).", base, lpMemReserved, GetLastError());
|
||||
goto eCleanupAndExit;
|
||||
}
|
||||
|
||||
// Map the physical memory into the window.
|
||||
bResult = MapUserPhysicalPages( base, (ULONG_PTR)pblock->NumberPages, (PULONG_PTR)pblock->aPFNs );
|
||||
|
||||
for(i = 0; i < pblock->NumberPages; ++i)
|
||||
pblock->aVFNs[i] = (uptr)base + 0x1000*i;
|
||||
|
||||
if( bResult != TRUE )
|
||||
{
|
||||
Console::MsgLn("VirtualMemory Error %u > MapUserPhysicalPages failed to map.", GetLastError() );
|
||||
goto eCleanupAndExit;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
eCleanupAndExit:
|
||||
SysVirtualFree(base, size);
|
||||
return -1;
|
||||
}
|
||||
|
||||
void SysVirtualFree(void* lpMemReserved, u32 size)
|
||||
{
|
||||
// unmap
|
||||
if( MapUserPhysicalPages( lpMemReserved, (size+s_dwPageSize-1)/s_dwPageSize, NULL ) != TRUE )
|
||||
{
|
||||
Console::MsgLn("VirtualMemory Error %u > MapUserPhysicalPages failed to unmap", GetLastError() );
|
||||
return;
|
||||
}
|
||||
|
||||
// Free virtual memory.
|
||||
VirtualFree( lpMemReserved, 0, MEM_RELEASE );
|
||||
}
|
||||
|
||||
int SysMapUserPhysicalPages(void* Addr, uptr NumPages, uptr* pfn, int pageoffset)
|
||||
{
|
||||
BOOL bResult = MapUserPhysicalPages(Addr, NumPages, (PULONG_PTR)(pfn+pageoffset));
|
||||
|
||||
#ifdef _DEBUG
|
||||
//if( !bResult )
|
||||
//__Log("Failed to map user pages: 0x%x:0x%x, error = %d\n", Addr, NumPages, GetLastError());
|
||||
#endif
|
||||
|
||||
return bResult;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#endif
|
|
@ -19,12 +19,11 @@
|
|||
15-09-2004 : file rewriten for work with inis (shadow)
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
#include "win32.h"
|
||||
#include <windowsx.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "Common.h"
|
||||
#include "win32.h"
|
||||
#include "Paths.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
|
|
@ -73,12 +73,12 @@ uptr *psxRecLUT;
|
|||
// R3000A statics
|
||||
int psxreclog = 0;
|
||||
|
||||
static u8 *recMem; // the recompiled blocks will be here
|
||||
static BASEBLOCK *recRAM; // and the ptr to the blocks here
|
||||
static BASEBLOCK *recROM; // and here
|
||||
static BASEBLOCK *recROM1; // also here
|
||||
static u8 *recMem = NULL; // the recompiled blocks will be here
|
||||
static BASEBLOCK *recRAM = NULL; // and the ptr to the blocks here
|
||||
static BASEBLOCK *recROM = NULL; // and here
|
||||
static BASEBLOCK *recROM1 = NULL; // also here
|
||||
static BASEBLOCKEX *recBlocks = NULL;
|
||||
static u8 *recPtr;
|
||||
static u8 *recPtr = NULL;
|
||||
u32 psxpc; // recompiler psxpc
|
||||
int psxbranch; // set for branch
|
||||
u32 g_iopCyclePenalty;
|
||||
|
@ -529,37 +529,53 @@ static int recInit() {
|
|||
uptr startaddr;
|
||||
|
||||
// can't have upper 4 bits nonzero!
|
||||
// ... we can't? (air)
|
||||
|
||||
startaddr = 0x0f000000;
|
||||
while(!(startaddr & 0xf0000000)) {
|
||||
if( recMem == NULL )
|
||||
//while(!(startaddr & 0xf0000000)) {
|
||||
recMem = (u8*)SysMmap(startaddr, RECMEM_SIZE);
|
||||
if( (uptr)recMem & 0xf0000000 ) {
|
||||
SysMunmap((uptr)recMem, RECMEM_SIZE); recMem = NULL;
|
||||
/*if( (uptr)recMem & 0xf0000000 ) {
|
||||
SysMunmap(recMem, RECMEM_SIZE); recMem = NULL;
|
||||
startaddr += 0x00100000;
|
||||
continue;
|
||||
}
|
||||
else break;
|
||||
}
|
||||
else break;*/
|
||||
//}
|
||||
|
||||
if( recMem == NULL ) {
|
||||
SysPrintf("R3000A bad rec memory allocation\n");
|
||||
Console::Error( "Error > R3000A failed to allocate recompiler memory." );
|
||||
return 1;
|
||||
}
|
||||
|
||||
ProfilerRegisterSource("IOPRec",recMem, RECMEM_SIZE);
|
||||
if( psxRecLUT == NULL )
|
||||
psxRecLUT = (uptr*) malloc(0x010000 * sizeof(uptr));
|
||||
|
||||
psxRecLUT = (uptr*) malloc(0x010000 * sizeof(uptr));
|
||||
memset(psxRecLUT, 0, 0x010000 * sizeof(uptr));
|
||||
if( recRAM == NULL )
|
||||
recRAM = (BASEBLOCK*) _aligned_malloc(sizeof(BASEBLOCK)/4*0x200000, 16);
|
||||
if( recROM == NULL )
|
||||
recROM = (BASEBLOCK*) _aligned_malloc(sizeof(BASEBLOCK)/4*0x400000, 16);
|
||||
if( recROM1 == NULL )
|
||||
recROM1= (BASEBLOCK*) _aligned_malloc(sizeof(BASEBLOCK)/4*0x040000, 16);
|
||||
if( recBlocks == NULL )
|
||||
recBlocks = (BASEBLOCKEX*) _aligned_malloc( sizeof(BASEBLOCKEX)*PSX_NUMBLOCKS, 16);
|
||||
|
||||
recRAM = (BASEBLOCK*) _aligned_malloc(sizeof(BASEBLOCK)/4*0x200000, 16);
|
||||
recROM = (BASEBLOCK*) _aligned_malloc(sizeof(BASEBLOCK)/4*0x400000, 16);
|
||||
recROM1= (BASEBLOCK*) _aligned_malloc(sizeof(BASEBLOCK)/4*0x040000, 16);
|
||||
recBlocks = (BASEBLOCKEX*) _aligned_malloc( sizeof(BASEBLOCKEX)*PSX_NUMBLOCKS, 16);
|
||||
if (recRAM == NULL || recROM == NULL || recROM1 == NULL ||
|
||||
recMem == NULL || psxRecLUT == NULL) {
|
||||
SysMessage("Error allocating memory"); return -1;
|
||||
if( s_pInstCache == NULL )
|
||||
{
|
||||
s_nInstCacheSize = 128;
|
||||
s_pInstCache = (EEINST*)malloc( sizeof(EEINST) * s_nInstCacheSize );
|
||||
}
|
||||
|
||||
s_nInstCacheSize = 128;
|
||||
s_pInstCache = (EEINST*)malloc( sizeof(EEINST) * s_nInstCacheSize );
|
||||
if( recRAM == NULL || recROM == NULL || recROM1 == NULL ||
|
||||
psxRecLUT == NULL || recBlocks == NULL || s_pInstCache == NULL )
|
||||
{
|
||||
SysMessage( _("Error allocating memory") ); return -1;
|
||||
}
|
||||
|
||||
// No errors! Proceed with initialization...
|
||||
|
||||
memset(psxRecLUT, 0, 0x010000 * sizeof(uptr));
|
||||
ProfilerRegisterSource("IOPRec",recMem, RECMEM_SIZE);
|
||||
|
||||
for (i=0; i<0x80; i++) psxRecLUT[i + 0x0000] = (uptr)&recRAM[(i & 0x1f) << 14];
|
||||
for (i=0; i<0x80; i++) psxRecLUT[i + 0x8000] = (uptr)&recRAM[(i & 0x1f) << 14];
|
||||
|
@ -578,11 +594,9 @@ static int recInit() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void recReset() {
|
||||
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
SysPrintf("IOP Recompiler data reset\n");
|
||||
#endif
|
||||
static void recReset()
|
||||
{
|
||||
DevCon::WriteLn("IOP Recompiler data reset");
|
||||
|
||||
memset(recRAM, 0, sizeof(BASEBLOCK)/4*0x200000);
|
||||
memset(recROM, 0, sizeof(BASEBLOCK)/4*0x400000);
|
||||
|
@ -597,15 +611,17 @@ static void recReset() {
|
|||
psxbranch = 0;
|
||||
}
|
||||
|
||||
static void recShutdown() {
|
||||
if (recMem == NULL) return;
|
||||
free(psxRecLUT);
|
||||
SysMunmap((uptr)recMem, RECMEM_SIZE);
|
||||
_aligned_free(recRAM);
|
||||
_aligned_free(recROM);
|
||||
_aligned_free(recROM1);
|
||||
_aligned_free( recBlocks ); recBlocks = NULL;
|
||||
free( s_pInstCache ); s_pInstCache = NULL; s_nInstCacheSize = 0;
|
||||
static void recShutdown()
|
||||
{
|
||||
SafeSysMunmap(recMem, RECMEM_SIZE);
|
||||
safe_free(psxRecLUT);
|
||||
safe_aligned_free(recRAM);
|
||||
safe_aligned_free(recROM);
|
||||
safe_aligned_free(recROM1);
|
||||
safe_aligned_free( recBlocks );
|
||||
|
||||
safe_free( s_pInstCache );
|
||||
s_nInstCacheSize = 0;
|
||||
|
||||
x86Shutdown();
|
||||
}
|
||||
|
|
|
@ -337,10 +337,21 @@ static void SuperVURecompile();
|
|||
void SuperVUInit(int vuindex)
|
||||
{
|
||||
if( vuindex < 0 ) {
|
||||
// upper 4 bits cannot be nonzero!
|
||||
s_recVUMem = (u8*)SysMmap(0x0c000000, VU_EXESIZE);
|
||||
if( (uptr)s_recVUMem > 0x80000000 )
|
||||
SysPrintf("bad SuperVU alloc %x\n", s_recVUMem);
|
||||
|
||||
// upper 4 bits cannot be nonzero!
|
||||
uptr baseaddr = 0x0c000000;
|
||||
while( baseaddr < 0x7a000000 && ( s_recVUMem == NULL || ((uptr)s_recVUMem > 0x80000000) ) )
|
||||
{
|
||||
s_recVUMem = (u8*)SysMmap( baseaddr, VU_EXESIZE);
|
||||
baseaddr += 0x100000;
|
||||
}
|
||||
|
||||
if( s_recVUMem == NULL || ((uptr)s_recVUMem > 0x80000000) )
|
||||
{
|
||||
Console::Error( "Error > SuperVU failed to allocate recompiler memory (addr: 0x%x)", (u32)s_recVUMem );
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
|
||||
ProfilerRegisterSource("VURec",s_recVUMem, VU_EXESIZE);
|
||||
memset(s_recVUMem, 0xcd, VU_EXESIZE);
|
||||
s_recVUPtr = s_recVUMem;
|
||||
|
@ -361,20 +372,19 @@ void SuperVUDestroy(int vuindex)
|
|||
if( vuindex < 0 ) {
|
||||
SuperVUDestroy(0);
|
||||
SuperVUDestroy(1);
|
||||
SysMunmap((uptr)s_recVUMem, VU_EXESIZE);
|
||||
s_recVUPtr = NULL;
|
||||
delete[] recVUStack; recVUStack = NULL;
|
||||
SafeSysMunmap(s_recVUMem, VU_EXESIZE);
|
||||
safe_delete_array( recVUStack );
|
||||
}
|
||||
else {
|
||||
delete[] recVUHeaders[vuindex]; recVUHeaders[vuindex] = NULL;
|
||||
delete[] recVUBlocks[vuindex]; recVUBlocks[vuindex] = NULL;
|
||||
safe_delete_array( recVUHeaders[vuindex] );
|
||||
safe_delete_array( recVUBlocks[vuindex] );
|
||||
|
||||
if( s_plistCachedHeaders[vuindex] != NULL ) {
|
||||
for(u32 j = 0; j < s_MemSize[vuindex]/8; ++j) {
|
||||
FORIT(it, s_plistCachedHeaders[vuindex][j]) delete *it;
|
||||
s_plistCachedHeaders[vuindex][j].clear();
|
||||
}
|
||||
delete[] s_plistCachedHeaders[vuindex]; s_plistCachedHeaders[vuindex] = NULL;
|
||||
safe_delete_array( s_plistCachedHeaders[vuindex] );
|
||||
}
|
||||
|
||||
FORIT(it, s_listVUHeaders[vuindex]) delete *it;
|
||||
|
@ -2587,7 +2597,7 @@ static void SuperVURecompile()
|
|||
// debug
|
||||
|
||||
#ifdef _DEBUG
|
||||
extern u32 s_vucount;
|
||||
u32 s_vucount=0;
|
||||
|
||||
static u32 g_vu1lastrec = 0, skipparent = -1;
|
||||
static u32 s_svulast = 0, s_vufnheader;
|
||||
|
@ -2647,7 +2657,7 @@ void svudispfntemp()
|
|||
{
|
||||
//static int curesp;
|
||||
//__asm mov curesp, esp
|
||||
Console::FormatLn("tVU: %x %x %x", s_svulast, s_vucount, s_vufnheader);
|
||||
Console::MsgLn("tVU: %x %x %x", s_svulast, s_vucount, s_vufnheader);
|
||||
if( g_curdebugvu ) iDumpVU1Registers();
|
||||
else iDumpVU0Registers();
|
||||
s_vucount++;
|
||||
|
|
|
@ -60,7 +60,7 @@
|
|||
#endif
|
||||
|
||||
u32 maxrecmem = 0;
|
||||
uptr *recLUT;
|
||||
uptr *recLUT = NULL;
|
||||
|
||||
#define X86
|
||||
#define RECSTACK_SIZE 0x00010000
|
||||
|
@ -1491,27 +1491,51 @@ int recInit( void )
|
|||
int i;
|
||||
const u8 macarr[16] = {0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15 };
|
||||
|
||||
recLUT = (uptr*) _aligned_malloc( 0x010000 * sizeof(uptr), 16 );
|
||||
memset( recLUT, 0, 0x010000 * sizeof(uptr) );
|
||||
if( recLUT == NULL )
|
||||
recLUT = (uptr*) _aligned_malloc( 0x010000 * sizeof(uptr), 16 );
|
||||
|
||||
// can't have upper 4 bits nonzero!
|
||||
recMem = (u8*)SysMmap(0x0d000000, REC_CACHEMEM+0x1000); // +0x1000 ? vtlb check.
|
||||
ProfilerRegisterSource("EERec",recMem, REC_CACHEMEM+0x1000);
|
||||
// ... then why don't we care to check if they are or not? (air)
|
||||
|
||||
if( recMem == NULL )
|
||||
recMem = (u8*)SysMmap(0x0d000000, REC_CACHEMEM+0x1000);
|
||||
|
||||
if( recMem == NULL ) {
|
||||
Console::Error("Error > R5900-32 failed to allocate recompiler memory.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 32 alignment necessary
|
||||
recRAM = (BASEBLOCK*) _aligned_malloc( sizeof(BASEBLOCK)/4*0x02000000 , 4*sizeof(BASEBLOCK));
|
||||
recROM = (BASEBLOCK*) _aligned_malloc( sizeof(BASEBLOCK)/4*0x00400000 , 4*sizeof(BASEBLOCK));
|
||||
recROM1= (BASEBLOCK*) _aligned_malloc( sizeof(BASEBLOCK)/4*0x00040000 , 4*sizeof(BASEBLOCK));
|
||||
recBlocks = (BASEBLOCKEX*) _aligned_malloc( sizeof(BASEBLOCKEX)*EE_NUMBLOCKS, 16);
|
||||
recStack = (u8*)malloc( RECSTACK_SIZE );
|
||||
if( recRAM == NULL )
|
||||
recRAM = (BASEBLOCK*) _aligned_malloc( sizeof(BASEBLOCK)/4*0x02000000 , 4*sizeof(BASEBLOCK));
|
||||
if( recROM == NULL )
|
||||
recROM = (BASEBLOCK*) _aligned_malloc( sizeof(BASEBLOCK)/4*0x00400000 , 4*sizeof(BASEBLOCK));
|
||||
if( recROM1 == NULL )
|
||||
recROM1 = (BASEBLOCK*) _aligned_malloc( sizeof(BASEBLOCK)/4*0x00040000 , 4*sizeof(BASEBLOCK));
|
||||
if( recBlocks == NULL )
|
||||
recBlocks = (BASEBLOCKEX*) _aligned_malloc( sizeof(BASEBLOCKEX)*EE_NUMBLOCKS, 16);
|
||||
if( recStack == NULL )
|
||||
recStack = (u8*)malloc( RECSTACK_SIZE );
|
||||
|
||||
s_nInstCacheSize = 128;
|
||||
s_pInstCache = (EEINST*)malloc( sizeof(EEINST) * s_nInstCacheSize );
|
||||
if( s_pInstCache == NULL )
|
||||
{
|
||||
s_nInstCacheSize = 128;
|
||||
s_pInstCache = (EEINST*)malloc( sizeof(EEINST) * s_nInstCacheSize );
|
||||
}
|
||||
|
||||
if ( recBlocks == NULL || recRAM == NULL || recROM == NULL || recROM1 == NULL || recMem == NULL || recLUT == NULL ) {
|
||||
if( recBlocks == NULL || recRAM == NULL || recROM == NULL ||
|
||||
recROM1 == NULL || recMem == NULL || recLUT == NULL ||
|
||||
recStack == NULL || s_pInstCache == NULL )
|
||||
{
|
||||
SysMessage( _( "Error allocating memory" ) );
|
||||
return -1;
|
||||
}
|
||||
|
||||
// No errors.. Proceed with initialization:
|
||||
|
||||
ProfilerRegisterSource("EERec",recMem, REC_CACHEMEM+0x1000);
|
||||
memset( recLUT, 0, 0x010000 * sizeof(uptr) );
|
||||
|
||||
for ( i = 0x0000; i < 0x0200; i++ )
|
||||
{
|
||||
recLUT[ i + 0x0000 ] = (uptr)&recRAM[ i << 14 ];
|
||||
|
@ -1607,9 +1631,8 @@ int recInit( void )
|
|||
|
||||
////////////////////////////////////////////////////
|
||||
static void recReset( void ) {
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
SysPrintf("EE Recompiler data reset\n");
|
||||
#endif
|
||||
|
||||
DevCon::WriteLn( "EE Recompiler data reset" );
|
||||
|
||||
s_nNextBlock = 0;
|
||||
maxrecmem = 0;
|
||||
|
@ -1644,21 +1667,20 @@ static void recReset( void ) {
|
|||
|
||||
void recShutdown( void )
|
||||
{
|
||||
if ( recMem == NULL ) {
|
||||
return;
|
||||
}
|
||||
SafeSysMunmap(recMem, REC_CACHEMEM);
|
||||
|
||||
_aligned_free( recLUT );
|
||||
SysMunmap((uptr)recMem, REC_CACHEMEM); recMem = NULL;
|
||||
_aligned_free( recRAM ); recRAM = NULL;
|
||||
_aligned_free( recROM ); recROM = NULL;
|
||||
_aligned_free( recROM1 ); recROM1 = NULL;
|
||||
_aligned_free( recBlocks ); recBlocks = NULL;
|
||||
free( s_pInstCache ); s_pInstCache = NULL; s_nInstCacheSize = 0;
|
||||
safe_aligned_free( recLUT );
|
||||
safe_aligned_free( recRAM );
|
||||
safe_aligned_free( recROM );
|
||||
safe_aligned_free( recROM1 );
|
||||
safe_aligned_free( recBlocks );
|
||||
|
||||
safe_free( s_pInstCache );
|
||||
s_nInstCacheSize = 0;
|
||||
|
||||
SuperVUDestroy(-1);
|
||||
|
||||
x86Shutdown( );
|
||||
x86Shutdown();
|
||||
}
|
||||
|
||||
void recEnableVU0micro(int enable) {
|
||||
|
@ -3287,7 +3309,7 @@ StartRecomp:
|
|||
stg-=4;
|
||||
lpc+=4;
|
||||
}
|
||||
DbgCon::FormatLn("Manual block @ %08X : %08X %d %d %d %d",
|
||||
DbgCon::MsgLn("Manual block @ %08X : %08X %d %d %d %d",
|
||||
startpc,inpage_ptr,pgsz,0x1000-inpage_offs,inpage_sz,sz*4);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1749,7 +1749,6 @@ extern void PFRCPIT2RtoR( x86IntRegType to, x86IntRegType from );
|
|||
extern void PFRSQRTRtoR( x86IntRegType to, x86IntRegType from );
|
||||
extern void PFRSQIT1RtoR( x86IntRegType to, x86IntRegType from );
|
||||
extern void PF2IDMtoR( x86IntRegType to, uptr from );
|
||||
extern void PF2IDRtoR( x86IntRegType to, x86IntRegType from );
|
||||
extern void PI2FDMtoR( x86IntRegType to, uptr from );
|
||||
extern void PI2FDRtoR( x86IntRegType to, x86IntRegType from );
|
||||
extern void PFMAXMtoR( x86IntRegType to, uptr from );
|
||||
|
|
|
@ -214,7 +214,7 @@ void cpudetectInit( void )
|
|||
u32 x86_64_8BITBRANDID;
|
||||
u32 x86_64_12BITBRANDID;
|
||||
int num;
|
||||
char str[50];
|
||||
char str[50];
|
||||
|
||||
memset( cpuinfo.x86ID, 0, sizeof( cpuinfo.x86ID ) );
|
||||
cpuinfo.x86Family = 0;
|
||||
|
|
Loading…
Reference in New Issue