mirror of https://github.com/PCSX2/pcsx2.git
Major GUI API Cleanups. Most likely buggy as all hell.
* Moved most of the shared code between the two GUIs into platform independent source modules (System.cpp, Saveslots.cpp, and RecoverySystem.cpp) * Created two new namespaces which house functions that need to be implemented by OS/platforms: HostGui and HostSys. HostGui is useful -- HostSys I'm not sure I'll keep around in the long run. * Moved keyEvent struct from PS2Edefs.h to PS2Etypes.h * Many improvements to the logic flow of the GUI (should be a little less fallible). git-svn-id: http://pcsx2.googlecode.com/svn/trunk@675 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
900d4bd485
commit
cc930f86c5
|
@ -95,15 +95,6 @@ char* CALLBACK PS2EgetLibName(void);
|
|||
linux: the XK_XXX will be used (XFree86)
|
||||
*/
|
||||
|
||||
// event values:
|
||||
#define KEYPRESS 1
|
||||
#define KEYRELEASE 2
|
||||
|
||||
typedef struct _keyEvent {
|
||||
u32 key;
|
||||
u32 evt;
|
||||
} keyEvent;
|
||||
|
||||
// for 64bit compilers
|
||||
typedef char __keyEvent_Size__[(sizeof(keyEvent) == 8)?1:-1];
|
||||
|
||||
|
|
|
@ -219,6 +219,15 @@ typedef struct {
|
|||
s8 *data;
|
||||
} freezeData;
|
||||
|
||||
// event values:
|
||||
#define KEYPRESS 1
|
||||
#define KEYRELEASE 2
|
||||
|
||||
typedef struct _keyEvent {
|
||||
u32 key;
|
||||
u32 evt;
|
||||
} keyEvent;
|
||||
|
||||
/* common defines */
|
||||
#ifndef C_ASSERT
|
||||
#define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1]
|
||||
|
|
|
@ -21,28 +21,6 @@
|
|||
|
||||
#include "PS2Etypes.h"
|
||||
|
||||
struct TESTRUNARGS
|
||||
{
|
||||
u8 enabled;
|
||||
u8 jpgcapture;
|
||||
|
||||
int frame; // if < 0, frame is unlimited (run until crash).
|
||||
int numimages;
|
||||
int curimage;
|
||||
u32 autopad; // mask for auto buttons
|
||||
bool efile;
|
||||
int snapdone;
|
||||
|
||||
const char* ptitle;
|
||||
const char* pimagename;
|
||||
const char* plogname;
|
||||
const char* pgsdll, *pcdvddll, *pspudll;
|
||||
const char* ppad1dll, *ppad2dll, *pdev9dll;
|
||||
|
||||
};
|
||||
|
||||
extern TESTRUNARGS g_TestRun;
|
||||
|
||||
#define BIAS 2 // Bus is half of the actual ps2 speed
|
||||
//#define PS2CLK 36864000 /* 294.912 mhz */
|
||||
//#define PSXCLK 9216000 /* 36.864 Mhz */
|
||||
|
|
|
@ -137,7 +137,7 @@ void rcntInit() {
|
|||
|
||||
// debug code, used for stats
|
||||
int g_nCounters[4];
|
||||
static int iFrame = 0;
|
||||
static uint iFrame = 0;
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <sys/time.h>
|
||||
|
@ -270,81 +270,6 @@ u32 UpdateVSyncRate()
|
|||
|
||||
extern u32 vu0time;
|
||||
|
||||
|
||||
void vSyncDebugStuff() {
|
||||
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
if( g_TestRun.enabled && g_TestRun.frame > 0 ) {
|
||||
if( iFrame > g_TestRun.frame ) {
|
||||
// take a snapshot
|
||||
if( g_TestRun.pimagename != NULL && GSmakeSnapshot2 != NULL ) {
|
||||
if( g_TestRun.snapdone ) {
|
||||
g_TestRun.curimage++;
|
||||
g_TestRun.snapdone = 0;
|
||||
g_TestRun.frame += 20;
|
||||
if( g_TestRun.curimage >= g_TestRun.numimages ) {
|
||||
// exit
|
||||
SysClose();
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// query for the image
|
||||
GSmakeSnapshot2(g_TestRun.pimagename, &g_TestRun.snapdone, g_TestRun.jpgcapture);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// exit
|
||||
SysClose();
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GSVSYNC();
|
||||
|
||||
if( g_SaveGSStream == 1 ) {
|
||||
freezeData fP;
|
||||
|
||||
g_SaveGSStream = 2;
|
||||
g_fGSSave->gsFreeze();
|
||||
|
||||
if (GSfreeze(FREEZE_SIZE, &fP) == -1) {
|
||||
safe_delete( g_fGSSave );
|
||||
g_SaveGSStream = 0;
|
||||
}
|
||||
else {
|
||||
fP.data = (s8*)malloc(fP.size);
|
||||
if (fP.data == NULL) {
|
||||
safe_delete( g_fGSSave );
|
||||
g_SaveGSStream = 0;
|
||||
}
|
||||
else {
|
||||
if (GSfreeze(FREEZE_SAVE, &fP) == -1) {
|
||||
safe_delete( g_fGSSave );
|
||||
g_SaveGSStream = 0;
|
||||
}
|
||||
else {
|
||||
g_fGSSave->Freeze( fP.size );
|
||||
if (fP.size) {
|
||||
g_fGSSave->FreezeMem( fP.data, fP.size );
|
||||
free(fP.data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( g_SaveGSStream == 2 ) {
|
||||
|
||||
if( --g_nLeftGSFrames <= 0 ) {
|
||||
safe_delete( g_fGSSave );
|
||||
g_SaveGSStream = 0;
|
||||
Console::WriteLn("Done saving GS stream");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void frameLimitReset()
|
||||
{
|
||||
m_iStart = GetCPUTicks();
|
||||
|
@ -401,7 +326,7 @@ static __forceinline void frameLimit()
|
|||
static __forceinline void VSyncStart(u32 sCycle)
|
||||
{
|
||||
EECNT_LOG( "///////// EE COUNTER VSYNC START \\\\\\\\\\\\\\\\\\\\ (frame: %d)\n", iFrame );
|
||||
vSyncDebugStuff(); // EE Profiling and Debug code
|
||||
vSyncDebugStuff( iFrame ); // EE Profiling and Debug code
|
||||
|
||||
if ((CSRw & 0x8)) GSCSRr|= 0x8;
|
||||
if (!(GSIMR&0x800)) gsIrq();
|
||||
|
@ -512,7 +437,6 @@ __forceinline bool rcntUpdate_vSync()
|
|||
counters[5].modeval = MODE_VRENDER;
|
||||
|
||||
return true;
|
||||
// SysUpdate(); // check for and handle keyevents
|
||||
}
|
||||
else // VSYNC end / VRENDER begin
|
||||
{
|
||||
|
|
|
@ -540,7 +540,7 @@ int loadElfFile(const char *filename)
|
|||
// Reset all recompilers prior to initiating a BIOS or new ELF. The cleaner the
|
||||
// slate, the happier the recompiler!
|
||||
|
||||
SysResetExecutionState();
|
||||
SysClearExecutionCache();
|
||||
|
||||
if( filename == NULL || filename[0] == 0 )
|
||||
{
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
/* Pcsx2 - Pc Ps2 Emulator
|
||||
* Copyright (C) 2002-2009 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
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// TestRun Parameters.
|
||||
|
||||
struct TESTRUNARGS
|
||||
{
|
||||
u8 enabled;
|
||||
u8 jpgcapture;
|
||||
|
||||
uint frame; // if == 0, frame is unlimited (run until crash).
|
||||
int numimages;
|
||||
int curimage;
|
||||
u32 autopad; // mask for auto buttons
|
||||
bool efile;
|
||||
int snapdone;
|
||||
|
||||
const char* ptitle;
|
||||
const char* pimagename;
|
||||
const char* plogname;
|
||||
const char* pgsdll, *pcdvddll, *pspudll;
|
||||
const char* ppad1dll, *ppad2dll, *pdev9dll;
|
||||
};
|
||||
|
||||
extern TESTRUNARGS g_TestRun;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Core Gui APIs (shared by all platforms)
|
||||
//
|
||||
// Most of these are implemented in SystemGui.cpp
|
||||
|
||||
extern void States_Load( const string& file );
|
||||
extern void States_Save( const string& file );
|
||||
extern void States_Load( int num );
|
||||
extern void States_Save( int num );
|
||||
extern bool States_isSlotUsed(int num);
|
||||
|
||||
extern bool g_EmulationInProgress; // Set TRUE if a game is actively running (set to false on reset)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// External Gui APIs (platform specific)
|
||||
//
|
||||
// The following section contains API declarations for GUI callback functions that the
|
||||
// Pcsx2 core expects and needs to be implemented by Pcsx2 platform dependent code
|
||||
// (Win32/Linux). If anything in this header comes up as a missing external during link,
|
||||
// it means that the necessary platform dependent files are not being compiled, or the
|
||||
// platform code is incomplete.
|
||||
//
|
||||
// These APIs have been namespaced to help simplify and organize the process of implementing
|
||||
// them and resolving linker errors.
|
||||
//
|
||||
|
||||
// Namespace housing gui-level implementations relating to events and signals such
|
||||
// as keyboard events, menu/status updates, and cpu execution invocation.
|
||||
namespace HostGui
|
||||
{
|
||||
// Signal for informing the GUI that the saveslot status has been altered.
|
||||
// The guis hould re-enumerate the slot information displayed in the menu, or wherever.
|
||||
extern void ResetMenuSlots();
|
||||
|
||||
// Signals to the GUI that execution of the emulator should begin. This can be either
|
||||
// a blocking or non-blocking (threaded) action.
|
||||
extern void BeginExecution();
|
||||
|
||||
// Signals the gui with a keystroke. Handle or discard or dispatch, or enjoy its
|
||||
// pleasant flavor.
|
||||
extern void __fastcall KeyEvent( keyEvent* ev );
|
||||
|
||||
// For issuing notices to both the status bar and the console at the same time.
|
||||
// Single-line text only please! Multi-line msgs should be directed to the
|
||||
// console directly, thanks.
|
||||
extern void Notice( const std::string& text );
|
||||
|
||||
// sets the contents of the pcsx2 window status bar.
|
||||
extern void SetStatusMsg( const std::string& text );
|
||||
};
|
|
@ -27,12 +27,6 @@ const char* g_pRunGSState = NULL;
|
|||
|
||||
int efile = 0;
|
||||
char elfname[g_MaxPath];
|
||||
bool Slots[5] = { false, false, false, false, false };
|
||||
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
TESTRUNARGS g_TestRun;
|
||||
#endif
|
||||
|
||||
char MAIN_DIR[g_MaxPath];
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
|
@ -275,7 +269,7 @@ void StartGui()
|
|||
gtk_widget_destroy(lookup_widget(MainWindow, "GtkMenuItem_Debug"));
|
||||
#endif
|
||||
|
||||
CheckSlots();
|
||||
ResetMenuSlots();
|
||||
|
||||
gtk_widget_show_all(MainWindow);
|
||||
gtk_window_activate_focus(GTK_WINDOW(MainWindow));
|
||||
|
@ -312,7 +306,7 @@ void OnLanguage(GtkMenuItem *menuitem, gpointer user_data)
|
|||
void OnFile_RunCD(GtkMenuItem *menuitem, gpointer user_data)
|
||||
{
|
||||
SysReset();
|
||||
RunExecute(NULL);
|
||||
SysPrepareExecution(NULL);
|
||||
}
|
||||
|
||||
void OnRunElf_Ok(GtkButton* button, gpointer user_data)
|
||||
|
@ -323,7 +317,7 @@ void OnRunElf_Ok(GtkButton* button, gpointer user_data)
|
|||
strcpy(elfname, File);
|
||||
gtk_widget_destroy(FileSel);
|
||||
|
||||
RunExecute(elfname);
|
||||
SysPrepareExecution(elfname);
|
||||
}
|
||||
|
||||
void OnRunElf_Cancel(GtkButton* button, gpointer user_data)
|
||||
|
@ -400,11 +394,7 @@ void OnFile_Exit(GtkMenuItem *menuitem, gpointer user_data)
|
|||
|
||||
void OnEmu_Run(GtkMenuItem *menuitem, gpointer user_data)
|
||||
{
|
||||
if (g_EmulationInProgress)
|
||||
ExecuteCpu();
|
||||
else
|
||||
RunExecute(NULL, true); // boots bios if no savestate is to be recovered
|
||||
|
||||
SysPrepareExecution(NULL, true); // boots bios if no savestate is to be recovered
|
||||
}
|
||||
|
||||
void OnEmu_Reset(GtkMenuItem *menuitem, gpointer user_data)
|
||||
|
@ -412,46 +402,6 @@ void OnEmu_Reset(GtkMenuItem *menuitem, gpointer user_data)
|
|||
SysReset();
|
||||
}
|
||||
|
||||
void ResetMenuSlots()
|
||||
{
|
||||
GtkWidget *Item;
|
||||
char str[g_MaxPath], str2[g_MaxPath];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
|
||||
sprintf(str, "load_slot_%d", i);
|
||||
sprintf(str2, "save_slot_%d", i);
|
||||
Item = lookup_widget(MainWindow, str);
|
||||
|
||||
if GTK_IS_WIDGET(Item)
|
||||
gtk_widget_set_sensitive(Item, Slots[i]);
|
||||
else
|
||||
Console::Error("No such widget: %s", params str);
|
||||
|
||||
Item = lookup_widget(MainWindow, str2);
|
||||
gtk_widget_set_sensitive(Item, (ElfCRC != 0));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void CheckSlots()
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
if (ElfCRC == 0) Console::Notice("Disabling game slots until a game is loaded.");
|
||||
|
||||
for (i=0; i<5; i++)
|
||||
{
|
||||
if (isSlotUsed(i))
|
||||
Slots[i] = true;
|
||||
else
|
||||
Slots[i] = false;
|
||||
}
|
||||
ResetMenuSlots();
|
||||
}
|
||||
|
||||
//2002-09-28 (Florin)
|
||||
void OnArguments_Ok(GtkButton *button, gpointer user_data)
|
||||
{
|
||||
|
|
|
@ -20,22 +20,13 @@
|
|||
#define __LNXMAIN_H__
|
||||
|
||||
#include "Linux.h"
|
||||
#include "HostGui.h"
|
||||
|
||||
extern bool applychanges;
|
||||
|
||||
extern SafeArray<u8>* g_RecoveryState;
|
||||
extern bool g_EmulationInProgress; // Set TRUE if a game is actively running (set to false on reset)
|
||||
|
||||
extern void RunExecute(const char* elf_file, bool use_bios = false);
|
||||
extern void ExecuteCpu();
|
||||
extern void CheckSlots();
|
||||
extern bool isSlotUsed(int num);
|
||||
extern bool ParseCommandLine(int argc, char *argv[], char *file);
|
||||
extern void MemoryCard_Init();
|
||||
|
||||
extern void StatusBar_Notice( const std::string& text );
|
||||
extern void StatusBar_SetMsg( const std::string& text );
|
||||
|
||||
void OnLanguage(GtkMenuItem *menuitem, gpointer user_data);
|
||||
void InitLanguages();
|
||||
char *GetLanguageNext();
|
||||
|
|
|
@ -18,16 +18,9 @@
|
|||
|
||||
#include "Linux.h"
|
||||
#include "LnxSysExec.h"
|
||||
#include "R5900Exceptions.h"
|
||||
|
||||
bool UseGui = true;
|
||||
|
||||
SafeArray<u8>* g_RecoveryState = NULL;
|
||||
SafeArray<u8>* g_gsRecoveryState = NULL;
|
||||
|
||||
bool g_ReturnToGui = false; // set to exit the execution of the emulator and return control to the GUI
|
||||
bool g_EmulationInProgress = false; // Set TRUE if a game is actively running (set to false on reset)
|
||||
|
||||
static bool sinit = false;
|
||||
GtkWidget *FileSel;
|
||||
|
||||
|
@ -69,25 +62,6 @@ void SysPageFaultExceptionFilter( int signal, siginfo_t *info, void * )
|
|||
mmap_ClearCpuBlock( offset & ~m_pagemask );
|
||||
}
|
||||
|
||||
// For issuing notices to both the status bar and the console at the same time.
|
||||
// Single-line text only please! Mutli-line msgs should be directed to the
|
||||
// console directly, thanks.
|
||||
void StatusBar_Notice( const std::string& text )
|
||||
{
|
||||
// mirror output to the console!
|
||||
Console::Status( text.c_str() );
|
||||
|
||||
// don't try this in Visual C++ folks!
|
||||
gtk_statusbar_push(GTK_STATUSBAR(pStatusBar), 0, text.c_str());
|
||||
}
|
||||
|
||||
// Sets the status bar message without mirroring the output to the console.
|
||||
void StatusBar_SetMsg( const std::string& text )
|
||||
{
|
||||
// don't try this in Visual C++ folks!
|
||||
gtk_statusbar_push(GTK_STATUSBAR(pStatusBar), 0, text.c_str());
|
||||
}
|
||||
|
||||
bool ParseCommandLine(int argc, char *argv[], char *file)
|
||||
{
|
||||
int i = 1;
|
||||
|
@ -206,410 +180,11 @@ void SysPrintf(const char *fmt, ...)
|
|||
Console::Write(msg);
|
||||
}
|
||||
|
||||
static void KeyEvent(keyEvent* ev);
|
||||
|
||||
void SysUpdate()
|
||||
{
|
||||
KeyEvent(PAD1keyEvent());
|
||||
KeyEvent(PAD2keyEvent());
|
||||
}
|
||||
|
||||
static void TryRecoverFromGsState()
|
||||
{
|
||||
if( g_gsRecoveryState != NULL )
|
||||
{
|
||||
s32 dummylen;
|
||||
|
||||
memLoadingState eddie( *g_gsRecoveryState );
|
||||
eddie.FreezePlugin( "GS", gsSafeFreeze );
|
||||
eddie.Freeze( dummylen ); // reads the length value recorded earlier.
|
||||
eddie.gsFreeze();
|
||||
}
|
||||
}
|
||||
|
||||
void ExecuteCpu()
|
||||
{
|
||||
// Make sure any left-over recovery states are cleaned up.
|
||||
safe_delete( g_RecoveryState );
|
||||
|
||||
// Just in case they weren't initialized earlier (no harm in calling this multiple times)
|
||||
if (OpenPlugins(NULL) == -1) return;
|
||||
|
||||
// this needs to be called for every new game!
|
||||
// (note: sometimes launching games through bios will give a crc of 0)
|
||||
|
||||
if( GSsetGameCRC != NULL ) GSsetGameCRC(ElfCRC, g_ZeroGSOptions);
|
||||
|
||||
TryRecoverFromGsState();
|
||||
|
||||
safe_delete( g_gsRecoveryState );
|
||||
|
||||
// Destroy the window. Ugly thing.
|
||||
gtk_widget_destroy(MainWindow);
|
||||
gtk_main_quit();
|
||||
|
||||
while (gtk_events_pending()) gtk_main_iteration();
|
||||
|
||||
g_EmulationInProgress = true;
|
||||
g_ReturnToGui = false;
|
||||
|
||||
signal(SIGINT, SignalExit);
|
||||
signal(SIGPIPE, SignalExit);
|
||||
|
||||
// Optimization: We hardcode two versions of the EE here -- one for recs and one for ints.
|
||||
// This is because recs are performance critical, and being able to inline them into the
|
||||
// function here helps a small bit (not much but every small bit counts!).
|
||||
try
|
||||
{
|
||||
if (CHECK_EEREC)
|
||||
{
|
||||
while (!g_ReturnToGui)
|
||||
{
|
||||
recExecute();
|
||||
SysUpdate();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (!g_ReturnToGui)
|
||||
{
|
||||
Cpu->Execute();
|
||||
SysUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch( R5900Exception::BaseExcept& ex )
|
||||
{
|
||||
Console::Error( ex.cMessage() );
|
||||
Console::Error( fmt_string( "(EE) PC: 0x%8.8x \tCycle:0x8.8x", ex.cpuState.pc, ex.cpuState.cycle ).c_str() );
|
||||
}
|
||||
}
|
||||
|
||||
void RunGui()
|
||||
{
|
||||
StartGui();
|
||||
}
|
||||
|
||||
// Runs an ELF image directly (ISO or ELF program or BIN)
|
||||
// Used by Run::FromCD and such
|
||||
void RunExecute(const char* elf_file, bool use_bios)
|
||||
{
|
||||
|
||||
// (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 SafeArray, 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
|
||||
|
||||
// Sounds like a good idea, at this point.
|
||||
|
||||
try
|
||||
{
|
||||
cpuReset();
|
||||
}
|
||||
|
||||
catch( Exception::BaseException& ex )
|
||||
{
|
||||
Msgbox::Alert( ex.cMessage() );
|
||||
return;
|
||||
}
|
||||
|
||||
if (OpenPlugins(NULL) == -1)
|
||||
{
|
||||
RunGui();
|
||||
return;
|
||||
}
|
||||
|
||||
if (elf_file == NULL)
|
||||
{
|
||||
if (g_RecoveryState != NULL)
|
||||
{
|
||||
try
|
||||
{
|
||||
memLoadingState(*g_RecoveryState).FreezeAll();
|
||||
}
|
||||
catch (std::runtime_error& ex)
|
||||
{
|
||||
Msgbox::Alert(
|
||||
"Gamestate recovery failed. Your game progress will be lost (sorry!)\n"
|
||||
"\nError: %s\n", params ex.what());
|
||||
|
||||
// Take the user back to the GUI...
|
||||
safe_delete(g_RecoveryState);
|
||||
ClosePlugins( true );
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if( g_gsRecoveryState == NULL )
|
||||
{
|
||||
// Not recovering a state, so need to execute the bios and load the ELF information.
|
||||
|
||||
// if the elf_file is null we use the CDVD elf file.
|
||||
// But if the elf_file is an empty string then we boot the bios instead.
|
||||
|
||||
char ename[g_MaxPath];
|
||||
ename[0] = 0;
|
||||
|
||||
if (!use_bios) GetPS2ElfName(ename);
|
||||
loadElfFile(ename);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Custom ELF specified (not using CDVD).
|
||||
// Run the BIOS and load the ELF.
|
||||
|
||||
loadElfFile(elf_file);
|
||||
}
|
||||
ExecuteCpu();
|
||||
}
|
||||
|
||||
class RecoveryMemSavingState : public memSavingState, Sealed
|
||||
{
|
||||
public:
|
||||
virtual ~RecoveryMemSavingState() { }
|
||||
RecoveryMemSavingState() : memSavingState( *g_RecoveryState )
|
||||
{
|
||||
}
|
||||
|
||||
void gsFreeze()
|
||||
{
|
||||
if (g_gsRecoveryState != NULL)
|
||||
{
|
||||
// just copy the data from src to dst.
|
||||
// the normal savestate doesn't expect a length prefix for internal structures,
|
||||
// so don't copy that part.
|
||||
const u32 pluginlen = *((u32*)g_gsRecoveryState->GetPtr());
|
||||
const u32 gslen = *((u32*)g_gsRecoveryState->GetPtr(pluginlen+4));
|
||||
memcpy( m_memory.GetPtr(m_idx), g_gsRecoveryState->GetPtr(pluginlen+8), gslen );
|
||||
m_idx += gslen;
|
||||
}
|
||||
else
|
||||
memSavingState::gsFreeze();
|
||||
}
|
||||
|
||||
void FreezePlugin( const char* name, s32 (CALLBACK* freezer)(int mode, freezeData *data) )
|
||||
{
|
||||
if ((freezer == gsSafeFreeze) && (g_gsRecoveryState != NULL))
|
||||
{
|
||||
// Gs data is already in memory, so just copy from src to dest:
|
||||
// length of the GS data is stored as the first u32, so use that to run the copy:
|
||||
const u32 len = *((u32*)g_gsRecoveryState->GetPtr());
|
||||
memcpy( m_memory.GetPtr(m_idx), g_gsRecoveryState->GetPtr(), len+4 );
|
||||
m_idx += len+4;
|
||||
}
|
||||
else
|
||||
memSavingState::FreezePlugin( name, freezer );
|
||||
}
|
||||
};
|
||||
|
||||
class RecoveryZipSavingState : public gzSavingState, Sealed
|
||||
{
|
||||
public:
|
||||
virtual ~RecoveryZipSavingState() { }
|
||||
RecoveryZipSavingState( const string& filename ) : gzSavingState( filename )
|
||||
{
|
||||
}
|
||||
|
||||
void gsFreeze()
|
||||
{
|
||||
if (g_gsRecoveryState != NULL)
|
||||
{
|
||||
// read data from the gsRecoveryState allocation instead of the GS, since the gs
|
||||
// info was invalidated when the plugin was shut down.
|
||||
|
||||
// the normal savestate doesn't expect a length prefix for internal structures,
|
||||
// so don't copy that part.
|
||||
|
||||
u32& pluginlen = *((u32*)g_gsRecoveryState->GetPtr(0));
|
||||
u32& gslen = *((u32*)g_gsRecoveryState->GetPtr(pluginlen+4));
|
||||
gzwrite( m_file, g_gsRecoveryState->GetPtr(pluginlen+4), gslen );
|
||||
}
|
||||
else
|
||||
gzSavingState::gsFreeze();
|
||||
}
|
||||
|
||||
void FreezePlugin( const char* name, s32 (CALLBACK* freezer)(int mode, freezeData *data) )
|
||||
{
|
||||
if ((freezer == gsSafeFreeze) && (g_gsRecoveryState != NULL))
|
||||
{
|
||||
// Gs data is already in memory, so just copy from there into the gzip file.
|
||||
// length of the GS data is stored as the first u32, so use that to run the copy:
|
||||
u32& len = *((u32*)g_gsRecoveryState->GetPtr());
|
||||
gzwrite( m_file, g_gsRecoveryState->GetPtr(), len+4 );
|
||||
}
|
||||
else
|
||||
gzSavingState::FreezePlugin( name, freezer );
|
||||
}
|
||||
};
|
||||
|
||||
bool isSlotUsed(int num)
|
||||
{
|
||||
if (ElfCRC == 0)
|
||||
return false;
|
||||
else
|
||||
return Path::isFile(SaveState::GetFilename( num ));
|
||||
}
|
||||
|
||||
void States_Load(const string& file, int num = -1)
|
||||
{
|
||||
if( !Path::isFile( file ) )
|
||||
{
|
||||
Console::Notice( "Saveslot %d is empty.", params num );
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
char Text[g_MaxPath];
|
||||
gzLoadingState joe( file ); // this'll throw an StateLoadError_Recoverable.
|
||||
|
||||
// Make sure the cpu and plugins are ready to be state-ified!
|
||||
cpuReset();
|
||||
OpenPlugins( NULL );
|
||||
|
||||
joe.FreezeAll();
|
||||
|
||||
if( num != -1 )
|
||||
sprintf (Text, _("*PCSX2*: Loaded State %d"), num);
|
||||
else
|
||||
sprintf (Text, _("*PCSX2*: Loaded State %s"), file.c_str());
|
||||
|
||||
StatusBar_Notice( Text );
|
||||
|
||||
if( GSsetGameCRC != NULL ) GSsetGameCRC(ElfCRC, g_ZeroGSOptions);
|
||||
}
|
||||
catch( Exception::StateLoadError_Recoverable& ex)
|
||||
{
|
||||
if( num != -1 )
|
||||
Console::Notice( "Could not load savestate from slot %d.\n\n%s", params num, ex.cMessage() );
|
||||
else
|
||||
Console::Notice( "Could not load savestate file: %s.\n\n%s", params file.c_str(), ex.cMessage() );
|
||||
|
||||
// At this point the cpu hasn't been reset, so we can return
|
||||
// control to the user safely... (that's why we use a console notice instead of a popup)
|
||||
|
||||
return;
|
||||
}
|
||||
catch( Exception::BaseException& ex )
|
||||
{
|
||||
// The emulation state is ruined. Might as well give them a popup and start the gui.
|
||||
|
||||
string message;
|
||||
|
||||
if( num != -1 )
|
||||
ssprintf( message,
|
||||
"Encountered an error while loading savestate from slot %d.\n", num );
|
||||
else
|
||||
ssprintf( message,
|
||||
"Encountered an error while loading savestate from file: %s.\n", file.c_str() );
|
||||
|
||||
if( g_EmulationInProgress )
|
||||
message += "Since the savestate load was incomplete, the emulator has been reset.\n";
|
||||
|
||||
message += "\nError: " + ex.Message();
|
||||
|
||||
Msgbox::Alert( message.c_str() );
|
||||
SysClose();
|
||||
return;
|
||||
}
|
||||
|
||||
// Start emulating!
|
||||
ExecuteCpu();
|
||||
}
|
||||
|
||||
void States_Load(int num)
|
||||
{
|
||||
States_Load( SaveState::GetFilename( num ), num );
|
||||
}
|
||||
|
||||
void States_Save( const string& file, int num = -1 )
|
||||
{
|
||||
try
|
||||
{
|
||||
string text;
|
||||
RecoveryZipSavingState( file ).FreezeAll();
|
||||
if( num != -1 )
|
||||
ssprintf( text, _( "State saved to slot %d" ), num );
|
||||
else
|
||||
ssprintf( text, _( "State saved to file: %s" ), file.c_str() );
|
||||
|
||||
StatusBar_Notice( text );
|
||||
}
|
||||
catch( Exception::BaseException& ex )
|
||||
{
|
||||
string message;
|
||||
|
||||
if( num != -1 )
|
||||
ssprintf( message, "An error occurred while trying to save to slot %d\n", num );
|
||||
else
|
||||
ssprintf( message, "An error occurred while trying to save to file: %s\n", file.c_str() );
|
||||
|
||||
message += "Your emulation state has not been saved!\n\nError: " + ex.Message();
|
||||
|
||||
Console::Error( message.c_str() );
|
||||
}
|
||||
CheckSlots();
|
||||
}
|
||||
|
||||
void States_Save(int num)
|
||||
{
|
||||
if( g_RecoveryState != NULL )
|
||||
{
|
||||
// State is already saved into memory, and the emulator (and in-progress flag)
|
||||
// have likely been cleared out. So save from the Recovery buffer instead of
|
||||
// doing a "standard" save:
|
||||
|
||||
string text( SaveState::GetFilename( num ) );
|
||||
gzFile fileptr = gzopen( text.c_str(), "wb" );
|
||||
if( fileptr == NULL )
|
||||
{
|
||||
Msgbox::Alert( _("File permissions error while trying to save to slot %d"), params num );
|
||||
return;
|
||||
}
|
||||
gzwrite( fileptr, &g_SaveVersion, sizeof( u32 ) );
|
||||
gzwrite( fileptr, g_RecoveryState->GetPtr(), g_RecoveryState->GetSizeInBytes() );
|
||||
gzclose( fileptr );
|
||||
return;
|
||||
}
|
||||
|
||||
if( !g_EmulationInProgress )
|
||||
{
|
||||
Msgbox::Alert( "You need to start a game first before you can save it's state." );
|
||||
return;
|
||||
}
|
||||
|
||||
States_Save( SaveState::GetFilename( num ), num );
|
||||
}
|
||||
|
||||
class JustGsSavingState : public memSavingState, Sealed
|
||||
{
|
||||
public:
|
||||
virtual ~JustGsSavingState() { }
|
||||
JustGsSavingState() : memSavingState( *g_gsRecoveryState )
|
||||
{
|
||||
}
|
||||
|
||||
// This special override saves the gs info to m_idx+4, and then goes back and
|
||||
// writes in the length of data saved.
|
||||
void gsFreeze()
|
||||
{
|
||||
int oldmidx = m_idx;
|
||||
m_idx += 4;
|
||||
memSavingState::gsFreeze();
|
||||
if( IsSaving() )
|
||||
{
|
||||
s32& len = *((s32*)m_memory.GetPtr( oldmidx ));
|
||||
len = (m_idx - oldmidx)-4;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void OnStates_Load(GtkMenuItem *menuitem, gpointer user_data)
|
||||
{
|
||||
char *name;
|
||||
|
@ -626,7 +201,8 @@ void OnStates_Load(GtkMenuItem *menuitem, gpointer user_data)
|
|||
}
|
||||
|
||||
sscanf(name, "Slot %d", &i);
|
||||
States_Load(i);
|
||||
if( States_Load(i) )
|
||||
ExecuteCpu();
|
||||
}
|
||||
|
||||
void OnLoadOther_Ok(GtkButton* button, gpointer user_data)
|
||||
|
@ -638,7 +214,8 @@ void OnLoadOther_Ok(GtkButton* button, gpointer user_data)
|
|||
strcpy(str, File);
|
||||
gtk_widget_destroy(FileSel);
|
||||
|
||||
States_Load(str);
|
||||
if( States_Load(str) )
|
||||
ExecuteCpu();
|
||||
}
|
||||
|
||||
void OnLoadOther_Cancel(GtkButton* button, gpointer user_data)
|
||||
|
@ -726,156 +303,6 @@ void OnStates_SaveOther(GtkMenuItem *menuitem, gpointer user_data)
|
|||
#define ALT_EVT(evt) ((evt == XK_Alt_L) || (evt == XK_Alt_R))
|
||||
#define CAPS_LOCK_EVT(evt) (evt == XK_Caps_Lock)
|
||||
|
||||
void KeyEvent(keyEvent* ev)
|
||||
{
|
||||
static int shift = 0;
|
||||
|
||||
if (ev == NULL) return;
|
||||
|
||||
if (GSkeyEvent != NULL) GSkeyEvent(ev);
|
||||
|
||||
if (ev->evt == KEYPRESS)
|
||||
{
|
||||
if (SHIFT_EVT(ev->key))
|
||||
shift = 1;
|
||||
if (CAPS_LOCK_EVT(ev->key))
|
||||
{
|
||||
//Set up anything we want to happen while caps lock is down.
|
||||
}
|
||||
|
||||
switch (ev->key)
|
||||
{
|
||||
case XK_F1:
|
||||
case XK_F2:
|
||||
case XK_F3:
|
||||
case XK_F4:
|
||||
case XK_F5:
|
||||
case XK_F6:
|
||||
case XK_F7:
|
||||
case XK_F8:
|
||||
case XK_F9:
|
||||
case XK_F10:
|
||||
case XK_F11:
|
||||
case XK_F12:
|
||||
try
|
||||
{
|
||||
ProcessFKeys(ev->key - XK_F1 + 1, shift);
|
||||
}
|
||||
catch (Exception::CpuStateShutdown&)
|
||||
{
|
||||
// Woops! Something was unrecoverable. Bummer.
|
||||
// Let's give the user a RunGui!
|
||||
|
||||
g_EmulationInProgress = false;
|
||||
g_ReturnToGui = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case XK_Tab:
|
||||
CycleFrameLimit(0);
|
||||
break;
|
||||
|
||||
case XK_Escape:
|
||||
signal(SIGINT, SIG_DFL);
|
||||
signal(SIGPIPE, SIG_DFL);
|
||||
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
if (g_SaveGSStream >= 3)
|
||||
{
|
||||
g_SaveGSStream = 4;// gs state
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
if( Config.closeGSonEsc )
|
||||
{
|
||||
safe_delete( g_gsRecoveryState );
|
||||
safe_delete( g_RecoveryState );
|
||||
g_gsRecoveryState = new SafeArray<u8>();
|
||||
JustGsSavingState eddie;
|
||||
eddie.FreezePlugin( "GS", gsSafeFreeze ) ;
|
||||
eddie.gsFreeze();
|
||||
PluginsResetGS();
|
||||
}
|
||||
|
||||
ClosePlugins( Config.closeGSonEsc );
|
||||
|
||||
if (!UseGui) exit(0);
|
||||
|
||||
// fixme: The GUI is now capable of receiving control back from the
|
||||
// emulator. Which means that when I set g_ReturnToGui here, the emulation
|
||||
// loop in ExecuteCpu() will exit. You should be able to set it up so
|
||||
// that it returns control to the existing GTK event loop, instead of
|
||||
// always starting a new one via RunGui(). (but could take some trial and
|
||||
// error) -- (air)
|
||||
|
||||
// Easier said then done; running gtk in two threads at the same time can't be
|
||||
// done, and working around that is pretty fiddly.
|
||||
g_ReturnToGui = true;
|
||||
RunGui();
|
||||
break;
|
||||
|
||||
default:
|
||||
GSkeyEvent(ev);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (ev->evt == KEYRELEASE)
|
||||
{
|
||||
if (SHIFT_EVT(ev->key))
|
||||
shift = 0;
|
||||
if (CAPS_LOCK_EVT(ev->key))
|
||||
{
|
||||
//Release caps lock
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SysRestorableReset()
|
||||
{
|
||||
// already reset? and saved?
|
||||
if( !g_EmulationInProgress ) return;
|
||||
if( g_RecoveryState != NULL ) return;
|
||||
|
||||
try
|
||||
{
|
||||
g_RecoveryState = new SafeArray<u8>( "Memory Savestate Recovery" );
|
||||
RecoveryMemSavingState().FreezeAll();
|
||||
safe_delete( g_gsRecoveryState );
|
||||
g_EmulationInProgress = false;
|
||||
}
|
||||
catch( Exception::RuntimeError& ex )
|
||||
{
|
||||
Msgbox::Alert(
|
||||
"Pcsx2 gamestate recovery failed. Some options may have been reverted to protect your game's state.\n"
|
||||
"Error: %s", params ex.cMessage() );
|
||||
safe_delete( g_RecoveryState );
|
||||
}
|
||||
}
|
||||
|
||||
void SysReset()
|
||||
{
|
||||
if (!sinit) return;
|
||||
|
||||
StatusBar_Notice(_("Resetting..."));
|
||||
//Console::SetTitle(_("Resetting..."));
|
||||
|
||||
g_EmulationInProgress = false;
|
||||
safe_delete( g_RecoveryState );
|
||||
safe_delete( g_gsRecoveryState );
|
||||
ResetPlugins();
|
||||
|
||||
ElfCRC = 0;
|
||||
|
||||
// Note : No need to call cpuReset() here. It gets called automatically before the
|
||||
// emulator resumes execution.
|
||||
|
||||
StatusBar_Notice(_("Ready"));
|
||||
//Console::SetTitle(_("*PCSX2* Emulation state is reset."));
|
||||
}
|
||||
|
||||
bool SysInit()
|
||||
{
|
||||
if (sinit) return true;
|
||||
|
@ -928,61 +355,212 @@ void SysClose()
|
|||
emuLog = NULL;
|
||||
}
|
||||
sinit = false;
|
||||
|
||||
// Precautionary extra shutdown stuff.
|
||||
SysEndExecution();
|
||||
g_EmulationInProgress = false;
|
||||
}
|
||||
|
||||
void *SysLoadLibrary(const char *lib)
|
||||
namespace HostSys
|
||||
{
|
||||
return dlopen(lib, RTLD_NOW);
|
||||
}
|
||||
|
||||
void *SysLoadSym(void *lib, const char *sym)
|
||||
{
|
||||
return dlsym(lib, sym);
|
||||
}
|
||||
|
||||
const char *SysLibError()
|
||||
{
|
||||
return dlerror();
|
||||
}
|
||||
|
||||
void SysCloseLibrary(void *lib)
|
||||
{
|
||||
dlclose(lib);
|
||||
}
|
||||
|
||||
void SysRunGui()
|
||||
{
|
||||
RunGui();
|
||||
}
|
||||
|
||||
void *SysMmap(uptr base, u32 size)
|
||||
{
|
||||
u8 *Mem;
|
||||
Mem = (u8*)mmap((uptr*)base, size, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
|
||||
if (Mem == MAP_FAILED) Console::Notice("Mmap Failed!");
|
||||
|
||||
return Mem;
|
||||
}
|
||||
|
||||
void SysMunmap(uptr base, u32 size)
|
||||
{
|
||||
munmap((uptr*)base, size);
|
||||
}
|
||||
|
||||
void SysMemProtect( void* baseaddr, size_t size, PageProtectionMode mode, bool allowExecution )
|
||||
{
|
||||
int lnxmode = 0;
|
||||
|
||||
// make sure size is aligned to the system page size:
|
||||
size = (size + m_pagemask) & ~m_pagemask;
|
||||
|
||||
switch( mode )
|
||||
void *LoadLibrary(const char *lib)
|
||||
{
|
||||
case Protect_NoAccess: break;
|
||||
case Protect_ReadOnly: lnxmode = PROT_READ; break;
|
||||
case Protect_ReadWrite: lnxmode = PROT_READ | PROT_WRITE; break;
|
||||
return dlopen(lib, RTLD_NOW);
|
||||
}
|
||||
|
||||
void *LoadSym(void *lib, const char *sym)
|
||||
{
|
||||
return dlsym(lib, sym);
|
||||
}
|
||||
|
||||
const char *LibError()
|
||||
{
|
||||
return dlerror();
|
||||
}
|
||||
|
||||
void CloseLibrary(void *lib)
|
||||
{
|
||||
dlclose(lib);
|
||||
}
|
||||
|
||||
void *Mmap(uptr base, u32 size)
|
||||
{
|
||||
u8 *Mem;
|
||||
Mem = (u8*)mmap((uptr*)base, size, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
|
||||
if (Mem == MAP_FAILED) Console::Notice("Mmap Failed!");
|
||||
|
||||
return Mem;
|
||||
}
|
||||
|
||||
void Munmap(uptr base, u32 size)
|
||||
{
|
||||
munmap((uptr*)base, size);
|
||||
}
|
||||
|
||||
void MemProtect( void* baseaddr, size_t size, PageProtectionMode mode, bool allowExecution )
|
||||
{
|
||||
int lnxmode = 0;
|
||||
|
||||
// make sure size is aligned to the system page size:
|
||||
size = (size + m_pagemask) & ~m_pagemask;
|
||||
|
||||
switch( mode )
|
||||
{
|
||||
case Protect_NoAccess: break;
|
||||
case Protect_ReadOnly: lnxmode = PROT_READ; break;
|
||||
case Protect_ReadWrite: lnxmode = PROT_READ | PROT_WRITE; break;
|
||||
}
|
||||
|
||||
if( allowExecution ) lnxmode |= PROT_EXEC;
|
||||
mprotect( baseaddr, size, lnxmode );
|
||||
}
|
||||
}
|
||||
|
||||
namespace HostGui
|
||||
{
|
||||
// Sets the status bar message without mirroring the output to the console.
|
||||
void SetStatusMsg( const string& text )
|
||||
{
|
||||
// don't try this in Visual C++ folks!
|
||||
gtk_statusbar_push(GTK_STATUSBAR(pStatusBar), 0, text.c_str());
|
||||
}
|
||||
|
||||
void Notice( const string& text )
|
||||
{
|
||||
// mirror output to the console!
|
||||
Console::Status( text.c_str() );
|
||||
SetStatusMsg( test );
|
||||
}
|
||||
|
||||
void ResetMenuSlots()
|
||||
{
|
||||
GtkWidget *Item;
|
||||
char str[g_MaxPath], str2[g_MaxPath];
|
||||
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
sprintf(str, "load_slot_%d", i);
|
||||
sprintf(str2, "save_slot_%d", i);
|
||||
Item = lookup_widget(MainWindow, str);
|
||||
|
||||
if GTK_IS_WIDGET(Item)
|
||||
gtk_widget_set_sensitive(Item, Slots[i]);
|
||||
else
|
||||
Console::Error("No such widget: %s", params str);
|
||||
|
||||
Item = lookup_widget(MainWindow, str2);
|
||||
gtk_widget_set_sensitive(Item, (ElfCRC != 0));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void BeginExecution()
|
||||
{
|
||||
// Destroy the window. Ugly thing.
|
||||
gtk_widget_destroy(MainWindow);
|
||||
gtk_main_quit();
|
||||
|
||||
while (gtk_events_pending()) gtk_main_iteration();
|
||||
|
||||
signal(SIGINT, SignalExit);
|
||||
signal(SIGPIPE, SignalExit);
|
||||
|
||||
// no try/catch needed since no cleanup needed.. ?
|
||||
SysExecute();
|
||||
}
|
||||
|
||||
void __fastcall KeyEvent(keyEvent* ev)
|
||||
{
|
||||
static int shift = 0;
|
||||
|
||||
if (ev == NULL) return;
|
||||
|
||||
if (GSkeyEvent != NULL) GSkeyEvent(ev);
|
||||
|
||||
if (ev->evt == KEYPRESS)
|
||||
{
|
||||
if (SHIFT_EVT(ev->key))
|
||||
shift = 1;
|
||||
if (CAPS_LOCK_EVT(ev->key))
|
||||
{
|
||||
//Set up anything we want to happen while caps lock is down.
|
||||
}
|
||||
|
||||
switch (ev->key)
|
||||
{
|
||||
case XK_F1:
|
||||
case XK_F2:
|
||||
case XK_F3:
|
||||
case XK_F4:
|
||||
case XK_F5:
|
||||
case XK_F6:
|
||||
case XK_F7:
|
||||
case XK_F8:
|
||||
case XK_F9:
|
||||
case XK_F10:
|
||||
case XK_F11:
|
||||
case XK_F12:
|
||||
try
|
||||
{
|
||||
ProcessFKeys(ev->key - XK_F1 + 1, shift);
|
||||
}
|
||||
catch (Exception::CpuStateShutdown&)
|
||||
{
|
||||
// Woops! Something was unrecoverable. Bummer.
|
||||
// Let's give the user a RunGui!
|
||||
|
||||
g_EmulationInProgress = false;
|
||||
SysEndExecution();
|
||||
}
|
||||
break;
|
||||
|
||||
case XK_Tab:
|
||||
CycleFrameLimit(0);
|
||||
break;
|
||||
|
||||
case XK_Escape:
|
||||
signal(SIGINT, SIG_DFL);
|
||||
signal(SIGPIPE, SIG_DFL);
|
||||
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
if (g_SaveGSStream >= 3)
|
||||
{
|
||||
g_SaveGSStream = 4;// gs state
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
SysEndExecution();
|
||||
|
||||
if (!UseGui) exit(0);
|
||||
|
||||
// fixme: The GUI is now capable of receiving control back from the
|
||||
// emulator. Which means that when we call SysEscapeExecute() here, the
|
||||
// emulation loop in ExecuteCpu() will exit. You should be able to set it
|
||||
// up so that it returns control to the existing GTK event loop, instead of
|
||||
// always starting a new one via RunGui(). (but could take some trial and
|
||||
// error) -- (air)
|
||||
|
||||
// Easier said then done; running gtk in two threads at the same time can't be
|
||||
// done, and working around that is pretty fiddly.
|
||||
RunGui();
|
||||
break;
|
||||
|
||||
default:
|
||||
GSkeyEvent(ev);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (ev->evt == KEYRELEASE)
|
||||
{
|
||||
if (SHIFT_EVT(ev->key))
|
||||
shift = 0;
|
||||
if (CAPS_LOCK_EVT(ev->key))
|
||||
{
|
||||
//Release caps lock
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if( allowExecution ) lnxmode |= PROT_EXEC;
|
||||
mprotect( baseaddr, size, lnxmode );
|
||||
}
|
|
@ -10,7 +10,8 @@ Memory.cpp MemoryCard.cpp Misc.cpp Patch.cpp PathUtils.cpp Plugins.cpp Precompil
|
|||
R3000AInterpreter.cpp R3000AOpcodeTables.cpp R5900.cpp R5900OpcodeImpl.cpp R5900OpcodeTables.cpp \
|
||||
SPR.cpp SaveState.cpp Sif.cpp Sio.cpp SourceLog.cpp Stats.cpp System.cpp ThreadTools.cpp \
|
||||
VU0.cpp VU0micro.cpp VU0microInterp.cpp VU1micro.cpp VU1microInterp.cpp VUflags.cpp VUmicroMem.cpp VUops.cpp \
|
||||
Vif.cpp VifDma.cpp vssprintf.cpp vtlb.cpp xmlpatchloader.cpp AlignedMalloc.cpp
|
||||
Vif.cpp VifDma.cpp vssprintf.cpp vtlb.cpp xmlpatchloader.cpp AlignedMalloc.cpp \
|
||||
RecoverySystem.cpp Saveslots.cpp
|
||||
|
||||
|
||||
libpcsx2_a_SOURCES += \
|
||||
|
@ -18,6 +19,6 @@ CDVD.h CDVDiso.h CDVDisodrv.h CDVDlib.h COP0.h Cache.h CdRom.h Common.h Counters
|
|||
Elfheader.h Exceptions.h GS.h Hw.h IopBios.h IopBios2.h IopCounters.h IopDma.h IopHw.h IopMem.h IopSio2.h Memcpyfast.h \
|
||||
Memory.h MemoryCard.h Misc.h Patch.h Paths.h Plugins.h PrecompiledHeader.h PsxCommon.h R3000A.h R5900.h R5900OpcodeTables.h \
|
||||
SPR.h SamplProf.h SaveState.h Sif.h Sifcmd.h Sio.h SafeArray.h Stats.h StringUtils.h System.h Threading.h \
|
||||
VU.h VUflags.h VUmicro.h VUops.h Vif.h VifDma.h cheatscpp.h vtlb.h NakedAsm.h R5900Exceptions.h
|
||||
VU.h VUflags.h VUmicro.h VUops.h Vif.h VifDma.h cheatscpp.h vtlb.h NakedAsm.h R5900Exceptions.h HostGui.h
|
||||
|
||||
SUBDIRS = x86 . DebugTools IPU RDebug tinyxml Linux
|
|
@ -651,7 +651,7 @@ void memReset()
|
|||
{
|
||||
// VTLB Protection Preparations.
|
||||
|
||||
SysMemProtect( m_psAllMem, m_allMemSize, Protect_ReadWrite );
|
||||
HostSys::MemProtect( m_psAllMem, m_allMemSize, Protect_ReadWrite );
|
||||
|
||||
// Note!! Ideally the vtlb should only be initialized once, and then subsequent
|
||||
// resets of the system hardware would only clear vtlb mappings, but since the
|
||||
|
@ -821,7 +821,7 @@ int mmap_GetRamPageInfo(void* ptr)
|
|||
|
||||
void mmap_MarkCountedRamPage(void* ptr,u32 vaddr)
|
||||
{
|
||||
SysMemProtect( ptr, 1, Protect_ReadOnly );
|
||||
HostSys::MemProtect( ptr, 1, Protect_ReadOnly );
|
||||
|
||||
u32 offset=((u8*)ptr-psM);
|
||||
offset>>=12;
|
||||
|
@ -842,12 +842,12 @@ void mmap_ResetBlockTracking()
|
|||
{
|
||||
psMPWVA[i].clear();
|
||||
}
|
||||
SysMemProtect( psM, Ps2MemSize::Base, Protect_ReadWrite );
|
||||
HostSys::MemProtect( psM, Ps2MemSize::Base, Protect_ReadWrite );
|
||||
}
|
||||
|
||||
void mmap_ClearCpuBlock( uint offset )
|
||||
{
|
||||
SysMemProtect( &psM[offset], 1, Protect_ReadWrite );
|
||||
HostSys::MemProtect( &psM[offset], 1, Protect_ReadWrite );
|
||||
|
||||
offset>>=12;
|
||||
psMPWC[(offset/32)]|=(1<<(offset&31));
|
||||
|
|
|
@ -63,7 +63,7 @@ const char *LabelAuthors = { N_(
|
|||
"\n"
|
||||
"Betatesting: Bositman, ChaosCode,\n"
|
||||
"CKemu, crushtest, GeneralPlot,\n"
|
||||
"Krakatos, Paorotaku, Rudy_X\n"
|
||||
"Krakatos, Parotaku, Rudy_X\n"
|
||||
"\n"
|
||||
"Webmasters: CKemu, Falcon4ever"
|
||||
)
|
||||
|
@ -611,7 +611,7 @@ void ProcessFKeys(int fkey, int shift)
|
|||
{
|
||||
gzLoadingState joe( SaveState::GetFilename( StatesC ) ); // throws exception on version mismatch
|
||||
cpuReset();
|
||||
SysResetExecutionState();
|
||||
SysClearExecutionCache();
|
||||
joe.FreezeAll();
|
||||
}
|
||||
catch( Exception::StateLoadError_Recoverable& )
|
||||
|
@ -647,7 +647,7 @@ void ProcessFKeys(int fkey, int shift)
|
|||
|
||||
// note: VK_F5-VK_F7 are reserved for GS
|
||||
case 8:
|
||||
GSmakeSnapshot("snaps/");
|
||||
GSmakeSnapshot( SNAPSHOTS_DIR "/" );
|
||||
break;
|
||||
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
|
|
|
@ -18,6 +18,7 @@ extern char MAIN_DIR[g_MaxPath];
|
|||
#define SSTATES_DIR "sstates"
|
||||
#define LANGS_DIR "Langs"
|
||||
#define LOGS_DIR "logs"
|
||||
#define SNAPSHOTS_DIR "snaps"
|
||||
|
||||
#define DEFAULT_MEMCARD1 "Mcd001.ps2"
|
||||
#define DEFAULT_MEMCARD2 "Mcd002.ps2"
|
||||
|
|
|
@ -649,6 +649,7 @@ void ShutdownPlugins()
|
|||
{
|
||||
if( !initp ) return;
|
||||
|
||||
mtgsWaitGS();
|
||||
ClosePlugins( true );
|
||||
|
||||
if( GSshutdown != NULL )
|
||||
|
@ -848,15 +849,6 @@ void ClosePlugins( bool closegs )
|
|||
}
|
||||
}
|
||||
|
||||
void ResetPlugins()
|
||||
{
|
||||
|
||||
mtgsWaitGS();
|
||||
|
||||
ShutdownPlugins();
|
||||
InitPlugins();
|
||||
}
|
||||
|
||||
void ReleasePlugins()
|
||||
{
|
||||
if (!loadp) return;
|
||||
|
|
|
@ -34,11 +34,7 @@ int OpenPlugins(const char* pTitleFilename);
|
|||
void ClosePlugins( bool closegs );
|
||||
|
||||
int InitPlugins();
|
||||
|
||||
// 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();
|
||||
void ShutdownPlugins();
|
||||
|
||||
void PluginsResetGS();
|
||||
|
||||
|
|
|
@ -58,31 +58,11 @@ bool eeEventTestIsActive = false;
|
|||
|
||||
R5900Exception::BaseExcept::~BaseExcept() throw (){}
|
||||
|
||||
// A run-once procedure for initializing the emulation state.
|
||||
// Can be done anytime after allocating memory, and before calling Cpu->Execute().
|
||||
// Multiple calls to this function are automatically ignored.
|
||||
/*void cpuInit()
|
||||
{
|
||||
DevCon::WriteLn( "cpuInit > %s", params cpuIsInitialized ? "Initializing..." : "Skipping (already initialized)" );
|
||||
|
||||
if( cpuIsInitialized ) return;
|
||||
|
||||
cpuIsInitialized = true;
|
||||
|
||||
// non memInit() currently since we don't support soft resets. memory is initialized in full
|
||||
// instead during cpuReset() [using memReset()]
|
||||
//memInit();
|
||||
}*/
|
||||
|
||||
void cpuReset()
|
||||
{
|
||||
mtgsWaitGS(); // GS better be done processing before we reset the EE, just in case.
|
||||
//cpuInit(); // more just-in-caseness!
|
||||
|
||||
//if( !cpuIsInitialized )
|
||||
{
|
||||
cpuIsInitialized = true;
|
||||
}
|
||||
cpuIsInitialized = true;
|
||||
|
||||
memReset();
|
||||
psxMemReset();
|
||||
|
@ -118,9 +98,6 @@ void cpuReset()
|
|||
|
||||
void cpuShutdown()
|
||||
{
|
||||
//if( !cpuIsInitialized ) return;
|
||||
//cpuIsInitialized = false;
|
||||
|
||||
mtgsWaitGS();
|
||||
|
||||
hwShutdown();
|
||||
|
|
|
@ -0,0 +1,290 @@
|
|||
/* Pcsx2 - Pc Ps2 Emulator
|
||||
* Copyright (C) 2002-2009 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 "PrecompiledHeader.h"
|
||||
|
||||
#include "Common.h"
|
||||
#include "HostGui.h"
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// RecoverySystem.cpp -- houses code for recovering from on-the-fly changes to the emu
|
||||
// configuration, and for saving/restoring the GS state (for more seamless exiting of
|
||||
// fullscreen GS operation).
|
||||
//
|
||||
// The following handful of local classes are implemented att he bottom of this file.
|
||||
|
||||
static SafeArray<u8>* g_RecoveryState = NULL;
|
||||
static SafeArray<u8>* g_gsRecoveryState = NULL;
|
||||
|
||||
// This class type creates a memory savestate using the existing Recovery information
|
||||
// (if present) to generate the savestate material. If no recovery data is present,
|
||||
// the current emulation state is used instead.
|
||||
class RecoveryMemSavingState : public memSavingState, Sealed
|
||||
{
|
||||
public:
|
||||
virtual ~RecoveryMemSavingState() { }
|
||||
RecoveryMemSavingState();
|
||||
|
||||
void gsFreeze();
|
||||
void FreezePlugin( const char* name, s32 (CALLBACK* freezer)(int mode, freezeData *data) );
|
||||
};
|
||||
|
||||
// This class type creates an on-disk (zipped) savestate using the existing Recovery
|
||||
// information (if present) to generate the savestate material. If no recovery data is
|
||||
// present, the current emulation state is used instead.
|
||||
class RecoveryZipSavingState : public gzSavingState, Sealed
|
||||
{
|
||||
public:
|
||||
virtual ~RecoveryZipSavingState() { }
|
||||
RecoveryZipSavingState( const string& filename );
|
||||
|
||||
void gsFreeze();
|
||||
void FreezePlugin( const char* name, s32 (CALLBACK* freezer)(int mode, freezeData *data) );
|
||||
};
|
||||
|
||||
// Special helper class used to save *just* the GS-relevant state information.
|
||||
class JustGsSavingState : public memSavingState, Sealed
|
||||
{
|
||||
public:
|
||||
virtual ~JustGsSavingState() { }
|
||||
JustGsSavingState();
|
||||
|
||||
// This special override saves the gs info to m_idx+4, and then goes back and
|
||||
// writes in the length of data saved.
|
||||
void gsFreeze();
|
||||
};
|
||||
|
||||
namespace StateRecovery {
|
||||
|
||||
bool HasState()
|
||||
{
|
||||
return g_RecoveryState != NULL || g_gsRecoveryState != NULL;
|
||||
}
|
||||
|
||||
// Exceptions:
|
||||
void Recover()
|
||||
{
|
||||
// Just in case they weren't initialized earlier (no harm in calling this multiple times)
|
||||
if( OpenPlugins(NULL) == -1 ) return;
|
||||
|
||||
if( g_RecoveryState != NULL )
|
||||
{
|
||||
Console::Status( "Resuming execution from full memory state..." );
|
||||
memLoadingState( *g_RecoveryState ).FreezeAll();
|
||||
}
|
||||
else if( g_gsRecoveryState != NULL )
|
||||
{
|
||||
s32 dummylen;
|
||||
|
||||
Console::Status( "Resuming execution from gsState..." );
|
||||
memLoadingState eddie( *g_gsRecoveryState );
|
||||
eddie.FreezePlugin( "GS", gsSafeFreeze );
|
||||
eddie.Freeze( dummylen ); // reads the length value recorded earlier.
|
||||
eddie.gsFreeze();
|
||||
}
|
||||
|
||||
StateRecovery::Clear();
|
||||
|
||||
// this needs to be called for every new game!
|
||||
// (note: sometimes launching games through bios will give a crc of 0)
|
||||
|
||||
if( GSsetGameCRC != NULL )
|
||||
GSsetGameCRC(ElfCRC, g_ZeroGSOptions);
|
||||
}
|
||||
|
||||
// Saves recovery state info to the given filename, or saves the active emulation state
|
||||
// (if one exists) and no recovery data was found. This is needed because when a recovery
|
||||
// state is made, the emulation state is usually reset so the only persisting state is
|
||||
// the one in the memory save. :)
|
||||
void SaveToFile( const string& file )
|
||||
{
|
||||
if( g_RecoveryState != NULL )
|
||||
{
|
||||
// State is already saved into memory, and the emulator (and in-progress flag)
|
||||
// have likely been cleared out. So save from the Recovery buffer instead of
|
||||
// doing a "standard" save:
|
||||
|
||||
gzFile fileptr = gzopen( file.c_str(), "wb" );
|
||||
if( fileptr == NULL )
|
||||
{
|
||||
Msgbox::Alert( _("File permissions error while trying to save to file:\n\t%ts"), params &file );
|
||||
return;
|
||||
}
|
||||
gzwrite( fileptr, &g_SaveVersion, sizeof( u32 ) );
|
||||
gzwrite( fileptr, g_RecoveryState->GetPtr(), g_RecoveryState->GetSizeInBytes() );
|
||||
gzclose( fileptr );
|
||||
}
|
||||
else if( g_gsRecoveryState != NULL )
|
||||
{
|
||||
RecoveryZipSavingState( file ).FreezeAll();
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !g_EmulationInProgress )
|
||||
{
|
||||
Msgbox::Alert( "You need to start a game first before you can save it's state." );
|
||||
return;
|
||||
}
|
||||
|
||||
States_Save( file );
|
||||
}
|
||||
}
|
||||
|
||||
// Saves recovery state info to the given saveslot, or saves the active emulation state
|
||||
// (if one exists) and no recovery data was found. This is needed because when a recovery
|
||||
// state is made, the emulation state is usually reset so the only persisting state is
|
||||
// the one in the memory save. :)
|
||||
void SaveToSlot( uint num )
|
||||
{
|
||||
SaveToFile( SaveState::GetFilename( num ) );
|
||||
}
|
||||
|
||||
// This method will override any existing recovery states, so call it with caution, if you
|
||||
// think that there could be existing important state info in the recovery buffers (but
|
||||
// really there shouldn't be, unless you're calling this function when it's not intended
|
||||
// to be called).
|
||||
void MakeGsOnly()
|
||||
{
|
||||
StateRecovery::Clear();
|
||||
|
||||
if( !g_EmulationInProgress ) return;
|
||||
|
||||
g_gsRecoveryState = new SafeArray<u8>();
|
||||
JustGsSavingState eddie;
|
||||
eddie.FreezePlugin( "GS", gsSafeFreeze ) ;
|
||||
eddie.gsFreeze();
|
||||
}
|
||||
|
||||
// Creates a full recovery of the entire emulation state (CPU and all plugins).
|
||||
// If a current recovery state is already present, then nothing is done (the
|
||||
// existing recovery state takes precedence).
|
||||
void MakeFull()
|
||||
{
|
||||
if( g_RecoveryState != NULL ) return;
|
||||
|
||||
try
|
||||
{
|
||||
g_RecoveryState = new SafeArray<u8>( "Memory Savestate Recovery" );
|
||||
RecoveryMemSavingState().FreezeAll();
|
||||
safe_delete( g_gsRecoveryState );
|
||||
g_EmulationInProgress = false;
|
||||
}
|
||||
catch( Exception::RuntimeError& ex )
|
||||
{
|
||||
Msgbox::Alert(
|
||||
"Pcsx2 gamestate recovery failed. Some options may have been reverted to protect your game's state.\n"
|
||||
"Error: %s", params ex.cMessage() );
|
||||
safe_delete( g_RecoveryState );
|
||||
}
|
||||
}
|
||||
|
||||
// Clears and deallocates any recovery states.
|
||||
void Clear()
|
||||
{
|
||||
safe_delete( g_RecoveryState );
|
||||
safe_delete( g_gsRecoveryState );
|
||||
}
|
||||
}
|
||||
|
||||
RecoveryMemSavingState::RecoveryMemSavingState() : memSavingState( *g_RecoveryState )
|
||||
{
|
||||
}
|
||||
|
||||
void RecoveryMemSavingState::gsFreeze()
|
||||
{
|
||||
if( g_gsRecoveryState != NULL )
|
||||
{
|
||||
// just copy the data from src to dst.
|
||||
// the normal savestate doesn't expect a length prefix for internal structures,
|
||||
// so don't copy that part.
|
||||
const u32 pluginlen = *((u32*)g_gsRecoveryState->GetPtr());
|
||||
const u32 gslen = *((u32*)g_gsRecoveryState->GetPtr(pluginlen+4));
|
||||
memcpy( m_memory.GetPtr(m_idx), g_gsRecoveryState->GetPtr(pluginlen+8), gslen );
|
||||
m_idx += gslen;
|
||||
}
|
||||
else
|
||||
memSavingState::gsFreeze();
|
||||
}
|
||||
|
||||
void RecoveryMemSavingState::FreezePlugin( const char* name, s32 (CALLBACK* freezer)(int mode, freezeData *data) )
|
||||
{
|
||||
if( (freezer == gsSafeFreeze) && (g_gsRecoveryState != NULL) )
|
||||
{
|
||||
// Gs data is already in memory, so just copy from src to dest:
|
||||
// length of the GS data is stored as the first u32, so use that to run the copy:
|
||||
const u32 len = *((u32*)g_gsRecoveryState->GetPtr());
|
||||
memcpy( m_memory.GetPtr(m_idx), g_gsRecoveryState->GetPtr(), len+4 );
|
||||
m_idx += len+4;
|
||||
}
|
||||
else
|
||||
memSavingState::FreezePlugin( name, freezer );
|
||||
}
|
||||
|
||||
RecoveryZipSavingState::RecoveryZipSavingState( const string& filename ) : gzSavingState( filename )
|
||||
{
|
||||
}
|
||||
|
||||
void RecoveryZipSavingState::gsFreeze()
|
||||
{
|
||||
if( g_gsRecoveryState != NULL )
|
||||
{
|
||||
// read data from the gsRecoveryState allocation instead of the GS, since the gs
|
||||
// info was invalidated when the plugin was shut down.
|
||||
|
||||
// the normal savestate doesn't expect a length prefix for internal structures,
|
||||
// so don't copy that part.
|
||||
|
||||
u32& pluginlen = *((u32*)g_gsRecoveryState->GetPtr(0));
|
||||
u32& gslen = *((u32*)g_gsRecoveryState->GetPtr(pluginlen+4));
|
||||
gzwrite( m_file, g_gsRecoveryState->GetPtr(pluginlen+4), gslen );
|
||||
}
|
||||
else
|
||||
gzSavingState::gsFreeze();
|
||||
}
|
||||
|
||||
void RecoveryZipSavingState::FreezePlugin( const char* name, s32 (CALLBACK* freezer)(int mode, freezeData *data) )
|
||||
{
|
||||
if( (freezer == gsSafeFreeze) && (g_gsRecoveryState != NULL) )
|
||||
{
|
||||
// Gs data is already in memory, so just copy from there into the gzip file.
|
||||
// length of the GS data is stored as the first u32, so use that to run the copy:
|
||||
u32& len = *((u32*)g_gsRecoveryState->GetPtr());
|
||||
gzwrite( m_file, g_gsRecoveryState->GetPtr(), len+4 );
|
||||
}
|
||||
else
|
||||
gzSavingState::FreezePlugin( name, freezer );
|
||||
}
|
||||
|
||||
JustGsSavingState::JustGsSavingState() : memSavingState( *g_gsRecoveryState )
|
||||
{
|
||||
}
|
||||
|
||||
// This special override saves the gs info to m_idx+4, and then goes back and
|
||||
// writes in the length of data saved.
|
||||
void JustGsSavingState::gsFreeze()
|
||||
{
|
||||
int oldmidx = m_idx;
|
||||
m_idx += 4;
|
||||
memSavingState::gsFreeze();
|
||||
if( IsSaving() )
|
||||
{
|
||||
s32& len = *((s32*)m_memory.GetPtr( oldmidx ));
|
||||
len = (m_idx - oldmidx)-4;
|
||||
}
|
||||
}
|
|
@ -62,7 +62,7 @@ extern void pcsx2_aligned_free(void* pmem);
|
|||
|
||||
#define SafeSysMunmap( ptr, size ) \
|
||||
if( ptr != NULL ) { \
|
||||
SysMunmap( (uptr)ptr, size ); \
|
||||
HostSys::Munmap( (uptr)ptr, size ); \
|
||||
ptr = NULL; \
|
||||
}
|
||||
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
#include "COP0.h"
|
||||
#include "Cache.h"
|
||||
|
||||
|
||||
using namespace R5900;
|
||||
|
||||
extern int g_psxWriteOk;
|
||||
|
@ -41,7 +40,7 @@ extern void recResetIOP();
|
|||
|
||||
static void PreLoadPrep()
|
||||
{
|
||||
SysResetExecutionState();
|
||||
SysClearExecutionCache();
|
||||
}
|
||||
|
||||
static void PostLoadPrep()
|
||||
|
|
|
@ -200,4 +200,15 @@ public:
|
|||
bool IsSaving() const { return false; }
|
||||
};
|
||||
|
||||
namespace StateRecovery
|
||||
{
|
||||
extern bool HasState();
|
||||
extern void Recover();
|
||||
extern void SaveToFile( const string& file );
|
||||
extern void SaveToSlot( uint num );
|
||||
extern void MakeGsOnly();
|
||||
extern void MakeFull();
|
||||
extern void Clear();
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,251 @@
|
|||
/* Pcsx2 - Pc Ps2 Emulator
|
||||
* Copyright (C) 2002-2009 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 "PrecompiledHeader.h"
|
||||
#include "Common.h"
|
||||
#include "HostGui.h"
|
||||
|
||||
#include "GS.h"
|
||||
|
||||
TESTRUNARGS g_TestRun;
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Save Slot Detection System
|
||||
|
||||
static int Slots[5] = { -1, -1, -1, -1, -1 };
|
||||
|
||||
bool States_isSlotUsed(int num)
|
||||
{
|
||||
if (ElfCRC == 0)
|
||||
return false;
|
||||
else
|
||||
return Path::isFile(SaveState::GetFilename( num ));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Save state load-from-file (or slot) helpers.
|
||||
|
||||
// Internal use state loading function which does not trap exceptions.
|
||||
// The calling function should trap ahnd handle exceptions as needed.
|
||||
static void _loadStateOrExcept( const string& file )
|
||||
{
|
||||
gzLoadingState joe( file ); // this'll throw an StateLoadError_Recoverable.
|
||||
|
||||
// Make sure the cpu and plugins are ready to be state-ified!
|
||||
cpuReset();
|
||||
OpenPlugins( NULL );
|
||||
|
||||
joe.FreezeAll();
|
||||
|
||||
if( GSsetGameCRC != NULL )
|
||||
GSsetGameCRC(ElfCRC, g_ZeroGSOptions);
|
||||
}
|
||||
|
||||
// returns true if the new state was loaded, or false if nothing happened.
|
||||
void States_Load( const string& file )
|
||||
{
|
||||
try
|
||||
{
|
||||
_loadStateOrExcept( file );
|
||||
HostGui::Notice( fmt_string(_("*PCSX2*: Loaded State %s"), file) );
|
||||
}
|
||||
catch( Exception::StateLoadError_Recoverable& ex)
|
||||
{
|
||||
Console::Notice( "Could not load savestate file: %s.\n\n%s", params file, ex.cMessage() );
|
||||
|
||||
// At this point the cpu hasn't been reset, so we can return
|
||||
// control to the user safely... (that's why we use a console notice instead of a popup)
|
||||
|
||||
return;
|
||||
}
|
||||
catch( Exception::BaseException& ex )
|
||||
{
|
||||
// The emulation state is ruined. Might as well give them a popup and start the gui.
|
||||
|
||||
string message( fmt_string(
|
||||
"Encountered an error while loading savestate from file: %s.\n", file ) );
|
||||
|
||||
if( g_EmulationInProgress )
|
||||
message += "Since the savestate load was incomplete, the emulator must reset.\n";
|
||||
|
||||
message += "\nError: " + ex.Message();
|
||||
|
||||
Msgbox::Alert( message.c_str() );
|
||||
SysReset();
|
||||
return;
|
||||
}
|
||||
HostGui::BeginExecution();
|
||||
}
|
||||
|
||||
void States_Load(int num)
|
||||
{
|
||||
string file( SaveState::GetFilename( num ) );
|
||||
|
||||
if( !Path::isFile( file ) )
|
||||
{
|
||||
Console::Notice( "Saveslot %d is empty.", params num );
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
_loadStateOrExcept( file );
|
||||
HostGui::Notice( fmt_string( _("*PCSX2*: Loaded State %d"), num ) );
|
||||
}
|
||||
catch( Exception::StateLoadError_Recoverable& ex)
|
||||
{
|
||||
Console::Notice( "Could not load savestate slot %d.\n\n%s", params num, ex.cMessage() );
|
||||
|
||||
// At this point the cpu hasn't been reset, so we can return
|
||||
// control to the user safely... (that's why we use a console notice instead of a popup)
|
||||
|
||||
return;
|
||||
}
|
||||
catch( Exception::BaseException& ex )
|
||||
{
|
||||
// The emulation state is ruined. Might as well give them a popup and start the gui.
|
||||
|
||||
string message( fmt_string(
|
||||
"Encountered an error while loading savestate from slot %d.\n", num ) );
|
||||
|
||||
if( g_EmulationInProgress )
|
||||
message += "Since the savestate load was incomplete, the emulator has been reset.\n";
|
||||
|
||||
message += "\nError: " + ex.Message();
|
||||
|
||||
Msgbox::Alert( message.c_str() );
|
||||
SysEndExecution();
|
||||
return;
|
||||
}
|
||||
|
||||
HostGui::BeginExecution();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Save state save-to-file (or slot) helpers.
|
||||
|
||||
void States_Save( const string& file )
|
||||
{
|
||||
try
|
||||
{
|
||||
StateRecovery::SaveToFile( file );
|
||||
HostGui::Notice( fmt_string( _( "State saved to file: %s" ), file ) );
|
||||
}
|
||||
catch( Exception::BaseException& ex )
|
||||
{
|
||||
Console::Error( (fmt_string(
|
||||
"An error occurred while trying to save to file %s\n", file ) +
|
||||
"Your emulation state has not been saved!\n\nError: " + ex.Message()).c_str()
|
||||
);
|
||||
}
|
||||
|
||||
// Filename could be a valid slot, so still need to update
|
||||
HostGui::ResetMenuSlots();
|
||||
}
|
||||
|
||||
void States_Save(int num)
|
||||
{
|
||||
try
|
||||
{
|
||||
StateRecovery::SaveToSlot( num );
|
||||
HostGui::Notice( fmt_string( _( "State saved to slot %d" ) , num ) );
|
||||
}
|
||||
catch( Exception::BaseException& ex )
|
||||
{
|
||||
Console::Error( (fmt_string(
|
||||
"An error occurred while trying to save to slot %d\n", num ) +
|
||||
"Your emulation state has not been saved!\n\nError: " + ex.Message()).c_str()
|
||||
);
|
||||
}
|
||||
HostGui::ResetMenuSlots();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void vSyncDebugStuff( uint frame )
|
||||
{
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
if( g_TestRun.enabled && g_TestRun.frame > 0 ) {
|
||||
if( frame > g_TestRun.frame ) {
|
||||
// take a snapshot
|
||||
if( g_TestRun.pimagename != NULL && GSmakeSnapshot2 != NULL ) {
|
||||
if( g_TestRun.snapdone ) {
|
||||
g_TestRun.curimage++;
|
||||
g_TestRun.snapdone = 0;
|
||||
g_TestRun.frame += 20;
|
||||
if( g_TestRun.curimage >= g_TestRun.numimages ) {
|
||||
// exit
|
||||
SysEndExecution();
|
||||
}
|
||||
}
|
||||
else {
|
||||
// query for the image
|
||||
GSmakeSnapshot2(g_TestRun.pimagename, &g_TestRun.snapdone, g_TestRun.jpgcapture);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// exit
|
||||
SysEndExecution();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GSVSYNC();
|
||||
|
||||
if( g_SaveGSStream == 1 ) {
|
||||
freezeData fP;
|
||||
|
||||
g_SaveGSStream = 2;
|
||||
g_fGSSave->gsFreeze();
|
||||
|
||||
if (GSfreeze(FREEZE_SIZE, &fP) == -1) {
|
||||
safe_delete( g_fGSSave );
|
||||
g_SaveGSStream = 0;
|
||||
}
|
||||
else {
|
||||
fP.data = (s8*)malloc(fP.size);
|
||||
if (fP.data == NULL) {
|
||||
safe_delete( g_fGSSave );
|
||||
g_SaveGSStream = 0;
|
||||
}
|
||||
else {
|
||||
if (GSfreeze(FREEZE_SAVE, &fP) == -1) {
|
||||
safe_delete( g_fGSSave );
|
||||
g_SaveGSStream = 0;
|
||||
}
|
||||
else {
|
||||
g_fGSSave->Freeze( fP.size );
|
||||
if (fP.size) {
|
||||
g_fGSSave->FreezeMem( fP.data, fP.size );
|
||||
free(fP.data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( g_SaveGSStream == 2 ) {
|
||||
|
||||
if( --g_nLeftGSFrames <= 0 ) {
|
||||
safe_delete( g_fGSSave );
|
||||
g_SaveGSStream = 0;
|
||||
Console::WriteLn("Done saving GS stream");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
157
pcsx2/System.cpp
157
pcsx2/System.cpp
|
@ -19,14 +19,16 @@
|
|||
#include "PrecompiledHeader.h"
|
||||
|
||||
#include "Common.h"
|
||||
#include "VUmicro.h"
|
||||
#include "Threading.h"
|
||||
#include "HostGui.h"
|
||||
|
||||
#include "VUmicro.h"
|
||||
#include "iR5900.h"
|
||||
#include "R3000A.h"
|
||||
#include "IopMem.h"
|
||||
#include "iVUzerorec.h" // for SuperVUReset
|
||||
|
||||
#include "R5900Exceptions.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace Console;
|
||||
|
@ -279,12 +281,16 @@ void SysShutdownDynarecs()
|
|||
recCpu.Shutdown();
|
||||
}
|
||||
|
||||
// Resets all PS2 cpu execution states, which does not affect that actual PS2 state/condition.
|
||||
|
||||
bool g_ReturnToGui = false; // set to exit the execution of the emulator and return control to the GUI
|
||||
bool g_EmulationInProgress = false; // Set TRUE if a game is actively running (set to false on reset)
|
||||
|
||||
// Resets all PS2 cpu execution caches, which does not affect that actual PS2 state/condition.
|
||||
// This can be called at any time outside the context of a Cpu->Execute() block without
|
||||
// bad things happening (recompilers will slow down for a brief moment since rec code blocks
|
||||
// are dumped).
|
||||
// Use this method to reset the recs when important global pointers like the MTGS are re-assigned.
|
||||
void SysResetExecutionState()
|
||||
void SysClearExecutionCache()
|
||||
{
|
||||
if( CHECK_EEREC )
|
||||
{
|
||||
|
@ -306,9 +312,146 @@ void SysResetExecutionState()
|
|||
vu1MicroDisableSkip();
|
||||
}
|
||||
|
||||
__forceinline void SysUpdate()
|
||||
{
|
||||
keyEvent* ev1 = PAD1keyEvent();
|
||||
keyEvent* ev2 = PAD2keyEvent();
|
||||
|
||||
HostGui::KeyEvent( (ev1 != NULL) ? ev1 : ev2);
|
||||
}
|
||||
|
||||
void SysExecute()
|
||||
{
|
||||
g_EmulationInProgress = true;
|
||||
g_ReturnToGui = false;
|
||||
|
||||
// Optimization: We hardcode two versions of the EE here -- one for recs and one for ints.
|
||||
// This is because recs are performance critical, and being able to inline them into the
|
||||
// function here helps a small bit (not much but every small bit counts!).
|
||||
|
||||
try
|
||||
{
|
||||
if( CHECK_EEREC )
|
||||
{
|
||||
while( !g_ReturnToGui )
|
||||
{
|
||||
recExecute();
|
||||
SysUpdate();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while( !g_ReturnToGui )
|
||||
{
|
||||
Cpu->Execute();
|
||||
SysUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch( R5900Exception::BaseExcept& ex )
|
||||
{
|
||||
Console::Error( ex.cMessage() );
|
||||
Console::Error( fmt_string( "(EE) PC: 0x%8.8x \tCycle:0x8.8x", ex.cpuState.pc, ex.cpuState.cycle ).c_str() );
|
||||
}
|
||||
}
|
||||
|
||||
// Function provided to escape the emulation state, by shutting down plugins and saving
|
||||
// the GS state. The execution state is effectively preserved, and can be resumed with a
|
||||
// call to SysExecute.
|
||||
void SysEndExecution()
|
||||
{
|
||||
if( Config.closeGSonEsc )
|
||||
StateRecovery::MakeGsOnly();
|
||||
|
||||
ClosePlugins( Config.closeGSonEsc );
|
||||
g_ReturnToGui = true;
|
||||
}
|
||||
|
||||
// Runs an ELF image directly (ISO or ELF program or BIN)
|
||||
// Used by Run::FromCD, and Run->Execute when no active emulation state is present.
|
||||
// elf_file - if NULL, the CDVD plugin is queried for the ELF file.
|
||||
// use_bios - forces the game to boot through the PS2 bios, instead of bypassing it.
|
||||
void SysPrepareExecution( const char* elf_file, bool use_bios )
|
||||
{
|
||||
if( !g_EmulationInProgress )
|
||||
{
|
||||
try
|
||||
{
|
||||
cpuReset();
|
||||
}
|
||||
catch( Exception::BaseException& ex )
|
||||
{
|
||||
Msgbox::Alert( ex.cMessage() );
|
||||
return;
|
||||
}
|
||||
|
||||
if (OpenPlugins(g_TestRun.ptitle) == -1)
|
||||
return;
|
||||
|
||||
if( elf_file == NULL )
|
||||
{
|
||||
if( !StateRecovery::HasState() )
|
||||
{
|
||||
// Not recovering a state, so need to execute the bios and load the ELF information.
|
||||
// (note: gsRecoveries are done from ExecuteCpu)
|
||||
|
||||
// if the elf_file is null we use the CDVD elf file.
|
||||
// But if the elf_file is an empty string then we boot the bios instead.
|
||||
|
||||
char ename[g_MaxPath];
|
||||
ename[0] = 0;
|
||||
if( !use_bios )
|
||||
GetPS2ElfName( ename );
|
||||
|
||||
loadElfFile( ename );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Custom ELF specified (not using CDVD).
|
||||
// Run the BIOS and load the ELF.
|
||||
|
||||
loadElfFile( elf_file );
|
||||
}
|
||||
}
|
||||
|
||||
StateRecovery::Recover();
|
||||
HostGui::BeginExecution();
|
||||
}
|
||||
|
||||
void SysRestorableReset()
|
||||
{
|
||||
if( !g_EmulationInProgress ) return;
|
||||
StateRecovery::MakeFull();
|
||||
}
|
||||
|
||||
void SysReset()
|
||||
{
|
||||
// fixme - this code sets the statusbar but never returns control to the window message pump
|
||||
// so the status bar won't receive the WM_PAINT messages needed to update itself anyway.
|
||||
// Oops! (air)
|
||||
|
||||
HostGui::Notice(_("Resetting..."));
|
||||
Console::SetTitle(_("Resetting..."));
|
||||
|
||||
g_EmulationInProgress = false;
|
||||
StateRecovery::Clear();
|
||||
|
||||
cpuShutdown();
|
||||
ShutdownPlugins();
|
||||
|
||||
ElfCRC = 0;
|
||||
|
||||
// Note : No need to call cpuReset() here. It gets called automatically before the
|
||||
// emulator resumes execution.
|
||||
|
||||
HostGui::Notice(_("Ready"));
|
||||
Console::SetTitle(_("*PCSX2* Emulation state is reset."));
|
||||
}
|
||||
|
||||
u8 *SysMmapEx(uptr base, u32 size, uptr bounds, const char *caller)
|
||||
{
|
||||
u8 *Mem = (u8*)SysMmap( base, size );
|
||||
u8 *Mem = (u8*)HostSys::Mmap( base, size );
|
||||
|
||||
if( (Mem == NULL) || (bounds != 0 && (((uptr)Mem + size) > bounds)) )
|
||||
{
|
||||
|
@ -319,7 +462,7 @@ u8 *SysMmapEx(uptr base, u32 size, uptr bounds, const char *caller)
|
|||
|
||||
SafeSysMunmap( Mem, size );
|
||||
|
||||
Mem = (u8*)SysMmap( NULL, size );
|
||||
Mem = (u8*)HostSys::Mmap( NULL, size );
|
||||
if( bounds != 0 && (((uptr)Mem + size) > bounds) )
|
||||
{
|
||||
DevCon::Error( "Fatal Error:\n\tSecond try failed allocating %s, block ptr 0x%x does not meet required criteria.", params caller, Mem );
|
||||
|
@ -331,3 +474,7 @@ u8 *SysMmapEx(uptr base, u32 size, uptr bounds, const char *caller)
|
|||
return Mem;
|
||||
}
|
||||
|
||||
void *SysLoadLibrary(const char *lib) { return HostSys::LoadLibrary( lib ); }
|
||||
void *SysLoadSym(void *lib, const char *sym) { return HostSys::LoadSym( lib, sym ); }
|
||||
const char *SysLibError() { return HostSys::LibError(); }
|
||||
void SysCloseLibrary(void *lib) { HostSys::CloseLibrary( lib ); }
|
||||
|
|
102
pcsx2/System.h
102
pcsx2/System.h
|
@ -25,41 +25,6 @@
|
|||
#include "MemcpyFast.h"
|
||||
#include "SafeArray.h"
|
||||
|
||||
void SysDetect(); // Detects cpu type and fills cpuInfo structs.
|
||||
bool SysInit(); // Init logfiles, directories, critical memory resources, and other OS-specific one-time
|
||||
void SysReset(); // Resets the various PS2 cpus, sub-systems, and recompilers.
|
||||
void SysUpdate(); // Called on VBlank (to update i.e. pads)
|
||||
void SysClose(); // Close mem and plugins
|
||||
|
||||
bool SysAllocateMem(); // allocates memory for all PS2 systems; returns FALSe on critical error.
|
||||
void SysAllocateDynarecs(); // allocates memory for all dynarecs, and force-disables any failures.
|
||||
void SysShutdownDynarecs();
|
||||
void SysShutdownMem();
|
||||
void SysResetExecutionState();
|
||||
|
||||
void *SysLoadLibrary(const char *lib); // Loads Library
|
||||
void *SysLoadSym(void *lib, const char *sym); // Loads Symbol from Library
|
||||
const char *SysLibError(); // Gets previous error loading symbols
|
||||
void SysCloseLibrary(void *lib); // Closes Library
|
||||
|
||||
// Maps a block of memory for use as a recompiled code buffer.
|
||||
// The allocated block has code execution privileges.
|
||||
// Returns NULL on allocation failure.
|
||||
void *SysMmap(uptr base, u32 size);
|
||||
|
||||
// Maps a block of memory for use as a recompiled code buffer, and ensures that the
|
||||
// allocation is below a certain memory address (specified in "bounds" parameter).
|
||||
// The allocated block has code execution privileges.
|
||||
// Returns NULL on allocation failure.
|
||||
u8 *SysMmapEx(uptr base, u32 size, uptr bounds, const char *caller="Unnamed");
|
||||
|
||||
// Unmaps a block allocated by SysMmap
|
||||
void SysMunmap(uptr base, u32 size);
|
||||
|
||||
static __forceinline void SysMunmap( void* base, u32 size )
|
||||
{
|
||||
SysMunmap( (uptr)base, size );
|
||||
}
|
||||
|
||||
enum PageProtectionMode
|
||||
{
|
||||
|
@ -68,7 +33,72 @@ enum PageProtectionMode
|
|||
Protect_ReadWrite
|
||||
};
|
||||
|
||||
void SysMemProtect( void* baseaddr, size_t size, PageProtectionMode mode, bool allowExecution=false );
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// HostSys - Namespace housing general system-level implementations relating to loading
|
||||
// plugins and allocating memory. For now, these functions are all accessed via Sys*
|
||||
// versions defined in System.h/cpp.
|
||||
namespace HostSys
|
||||
{
|
||||
// Damn windows.h namespace pollution!!
|
||||
#undef LoadLibrary
|
||||
|
||||
extern void *LoadLibrary(const char *lib); // Loads Library
|
||||
extern void *LoadSym(void *lib, const char *sym); // Loads Symbol from Library
|
||||
extern const char *LibError(); // Gets previous error loading symbols
|
||||
extern void CloseLibrary(void *lib); // Closes Library
|
||||
|
||||
// Maps a block of memory for use as a recompiled code buffer.
|
||||
// The allocated block has code execution privileges.
|
||||
// Returns NULL on allocation failure.
|
||||
extern void *Mmap(uptr base, u32 size);
|
||||
|
||||
// Unmaps a block allocated by SysMmap
|
||||
extern void Munmap(uptr base, u32 size);
|
||||
|
||||
extern void MemProtect( void* baseaddr, size_t size, PageProtectionMode mode, bool allowExecution=false );
|
||||
|
||||
static __forceinline void Munmap( void* base, u32 size )
|
||||
{
|
||||
Munmap( (uptr)base, size );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extern void SysDetect(); // Detects cpu type and fills cpuInfo structs.
|
||||
extern void SysReset(); // Resets the various PS2 cpus, sub-systems, and recompilers.
|
||||
extern void SysUpdate(); // Called on VBlank (to update i.e. pads)
|
||||
|
||||
extern bool SysAllocateMem(); // allocates memory for all PS2 systems; returns FALSe on critical error.
|
||||
extern void SysAllocateDynarecs(); // allocates memory for all dynarecs, and force-disables any failures.
|
||||
extern void SysShutdownDynarecs();
|
||||
extern void SysShutdownMem();
|
||||
|
||||
extern void SysRestorableReset(); // Saves the current emulation state prior to spu reset.
|
||||
extern void SysClearExecutionCache(); // clears recompiled execution caches!
|
||||
extern void SysEndExecution(); // terminates plugins, saves GS state (if enabled), and signals emulation loop to end.
|
||||
extern void SysPrepareExecution( const char* elf_file, bool use_bios=false );
|
||||
|
||||
// initiates high-speed execution of the emulation state. This function is currently
|
||||
// designed to be run from an event loop, but will eventually be re-tooled with threading
|
||||
// in mindunder the new GUI (assuming Linux approves!), which will make life easier *and*
|
||||
// improve overall performance too!
|
||||
extern void SysExecute();
|
||||
|
||||
|
||||
// Library Helpers for HostSys functions, left in for now for convenience.
|
||||
|
||||
extern void *SysLoadLibrary(const char *lib); // Loads Library
|
||||
extern void *SysLoadSym(void *lib, const char *sym); // Loads Symbol from Library
|
||||
extern const char *SysLibError(); // Gets previous error loading symbols
|
||||
extern void SysCloseLibrary(void *lib); // Closes Library
|
||||
|
||||
// Maps a block of memory for use as a recompiled code buffer, and ensures that the
|
||||
// allocation is below a certain memory address (specified in "bounds" parameter).
|
||||
// The allocated block has code execution privileges.
|
||||
// Returns NULL on allocation failure.
|
||||
extern u8 *SysMmapEx(uptr base, u32 size, uptr bounds, const char *caller="Unnamed");
|
||||
|
||||
extern void vSyncDebugStuff( uint frame );
|
||||
|
||||
// Writes text to the console.
|
||||
// *DEPRECIATED* Use Console namespace methods instead.
|
||||
|
|
|
@ -581,7 +581,7 @@ void vtlb_free( void* pmem, uint size )
|
|||
SafeSysMunmap( pmem, size );
|
||||
#else
|
||||
// Make sure and unprotect memory first, since CrtDebug will try to write to it.
|
||||
SysMemProtect( pmem, size, Protect_ReadWrite );
|
||||
HostSys::MemProtect( pmem, size, Protect_ReadWrite );
|
||||
safe_aligned_free( pmem );
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -21,28 +21,29 @@
|
|||
#include "AboutDlg.h"
|
||||
#include "Common.h"
|
||||
|
||||
#include "Hyperlinks.h"
|
||||
|
||||
#define IDC_STATIC (-1)
|
||||
|
||||
HWND hW;
|
||||
HBITMAP hBMP, hSilverBMP;
|
||||
static HWND hW;
|
||||
static HBITMAP hSilverBMP;
|
||||
|
||||
LRESULT WINAPI AboutDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch(uMsg)
|
||||
{
|
||||
case WM_INITDIALOG:
|
||||
//hBMP = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(SPLASH_LOGO));
|
||||
hSilverBMP = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_PS2SILVER));
|
||||
|
||||
/*hW = CreateWindow("STATIC", "", WS_VISIBLE | WS_CHILD | SS_BITMAP,
|
||||
230, 10, 211, 110, hDlg, (HMENU)IDC_STATIC, GetModuleHandle(NULL), NULL);
|
||||
SendMessage(hW, STM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)hBMP);*/
|
||||
|
||||
SetWindowText(hDlg, _("About PCSX2"));
|
||||
|
||||
Button_SetText(GetDlgItem(hDlg, IDOK), _("OK"));
|
||||
Static_SetText(GetDlgItem(hDlg, IDC_PCSX_ABOUT_AUTHORS), _(LabelAuthors));
|
||||
Static_SetText(GetDlgItem(hDlg, IDC_PCSX_ABOUT_GREETS), _(LabelGreets));
|
||||
|
||||
ConvertStaticToHyperlink( hDlg, IDC_LINK_GOOGLECODE );
|
||||
ConvertStaticToHyperlink( hDlg, IDC_LINK_WEBSITE );
|
||||
|
||||
return TRUE;
|
||||
|
||||
case WM_COMMAND:
|
||||
|
@ -51,6 +52,16 @@ LRESULT WINAPI AboutDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|||
case IDOK:
|
||||
EndDialog( hDlg, TRUE );
|
||||
return TRUE;
|
||||
|
||||
case IDC_LINK_WEBSITE:
|
||||
ShellExecute(hDlg, "open", "http://www.pcsx2.net/",
|
||||
NULL, NULL, SW_SHOWNORMAL);
|
||||
return TRUE;
|
||||
|
||||
case IDC_LINK_GOOGLECODE:
|
||||
ShellExecute(hDlg, "open", "http://code.google.com/p/pcsx2",
|
||||
NULL, NULL, SW_SHOWNORMAL);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
|
||||
|
|
|
@ -63,7 +63,7 @@ struct ComboInitializer
|
|||
bool LoadNextLibrary()
|
||||
{
|
||||
string tmpStr( Path::Combine( Config.PluginsDir, FindData.cFileName ) );
|
||||
Lib = LoadLibrary( tmpStr.c_str() );
|
||||
Lib = HostSys::LoadLibrary( tmpStr.c_str() );
|
||||
if (Lib == NULL)
|
||||
{
|
||||
Console::Error( "Plugin load failure: %hs\n\tSysLibError Message: %s", params &tmpStr, SysLibError() );
|
||||
|
|
|
@ -0,0 +1,167 @@
|
|||
// Hyperlinks.cpp
|
||||
//
|
||||
// Copyright 2002 Neal Stublen
|
||||
// All rights reserved.
|
||||
//
|
||||
// http://www.awesoftware.com
|
||||
//
|
||||
|
||||
// This taken as found on Codeguru: http://www.codeguru.com/cpp/controls/staticctrl/article.php/c5803
|
||||
|
||||
#include "Win32.h"
|
||||
#include "Hyperlinks.h"
|
||||
|
||||
|
||||
#define PROP_ORIGINAL_FONT TEXT("_Hyperlink_Original_Font_")
|
||||
#define PROP_ORIGINAL_PROC TEXT("_Hyperlink_Original_Proc_")
|
||||
#define PROP_STATIC_HYPERLINK TEXT("_Hyperlink_From_Static_")
|
||||
#define PROP_UNDERLINE_FONT TEXT("_Hyperlink_Underline_Font_")
|
||||
|
||||
|
||||
LRESULT CALLBACK _HyperlinkParentProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
WNDPROC pfnOrigProc = (WNDPROC) GetProp(hwnd, PROP_ORIGINAL_PROC);
|
||||
|
||||
switch (message)
|
||||
{
|
||||
case WM_CTLCOLORSTATIC:
|
||||
{
|
||||
HDC hdc = (HDC) wParam;
|
||||
HWND hwndCtl = (HWND) lParam;
|
||||
|
||||
BOOL fHyperlink = (NULL != GetProp(hwndCtl, PROP_STATIC_HYPERLINK));
|
||||
if (fHyperlink)
|
||||
{
|
||||
LRESULT lr = CallWindowProc(pfnOrigProc, hwnd, message, wParam, lParam);
|
||||
SetTextColor(hdc, RGB(0, 0, 192));
|
||||
return lr;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case WM_DESTROY:
|
||||
{
|
||||
SetWindowLong(hwnd, GWL_WNDPROC, (LONG) pfnOrigProc);
|
||||
RemoveProp(hwnd, PROP_ORIGINAL_PROC);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return CallWindowProc(pfnOrigProc, hwnd, message, wParam, lParam);
|
||||
}
|
||||
|
||||
LRESULT CALLBACK _HyperlinkProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
WNDPROC pfnOrigProc = (WNDPROC) GetProp(hwnd, PROP_ORIGINAL_PROC);
|
||||
|
||||
switch (message)
|
||||
{
|
||||
case WM_DESTROY:
|
||||
{
|
||||
SetWindowLong(hwnd, GWL_WNDPROC, (LONG) pfnOrigProc);
|
||||
RemoveProp(hwnd, PROP_ORIGINAL_PROC);
|
||||
|
||||
HFONT hOrigFont = (HFONT) GetProp(hwnd, PROP_ORIGINAL_FONT);
|
||||
SendMessage(hwnd, WM_SETFONT, (WPARAM) hOrigFont, 0);
|
||||
RemoveProp(hwnd, PROP_ORIGINAL_FONT);
|
||||
|
||||
HFONT hFont = (HFONT) GetProp(hwnd, PROP_UNDERLINE_FONT);
|
||||
DeleteObject(hFont);
|
||||
RemoveProp(hwnd, PROP_UNDERLINE_FONT);
|
||||
|
||||
RemoveProp(hwnd, PROP_STATIC_HYPERLINK);
|
||||
|
||||
break;
|
||||
}
|
||||
case WM_MOUSEMOVE:
|
||||
{
|
||||
if (GetCapture() != hwnd)
|
||||
{
|
||||
HFONT hFont = (HFONT) GetProp(hwnd, PROP_UNDERLINE_FONT);
|
||||
SendMessage(hwnd, WM_SETFONT, (WPARAM) hFont, FALSE);
|
||||
InvalidateRect(hwnd, NULL, FALSE);
|
||||
SetCapture(hwnd);
|
||||
}
|
||||
else
|
||||
{
|
||||
RECT rect;
|
||||
GetWindowRect(hwnd, &rect);
|
||||
|
||||
POINT pt = { LOWORD(lParam), HIWORD(lParam) };
|
||||
ClientToScreen(hwnd, &pt);
|
||||
|
||||
if (!PtInRect(&rect, pt))
|
||||
{
|
||||
HFONT hFont = (HFONT) GetProp(hwnd, PROP_ORIGINAL_FONT);
|
||||
SendMessage(hwnd, WM_SETFONT, (WPARAM) hFont, FALSE);
|
||||
InvalidateRect(hwnd, NULL, FALSE);
|
||||
ReleaseCapture();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WM_SETCURSOR:
|
||||
{
|
||||
// Since IDC_HAND is not available on all operating systems,
|
||||
// we will load the arrow cursor if IDC_HAND is not present.
|
||||
HCURSOR hCursor = LoadCursor(NULL, MAKEINTRESOURCE(IDC_HAND));
|
||||
if (NULL == hCursor)
|
||||
{
|
||||
hCursor = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW));
|
||||
}
|
||||
SetCursor(hCursor);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return CallWindowProc(pfnOrigProc, hwnd, message, wParam, lParam);
|
||||
}
|
||||
|
||||
BOOL ConvertStaticToHyperlink(HWND hwndCtl)
|
||||
{
|
||||
// Subclass the parent so we can color the controls as we desire.
|
||||
|
||||
HWND hwndParent = GetParent(hwndCtl);
|
||||
if (NULL != hwndParent)
|
||||
{
|
||||
WNDPROC pfnOrigProc = (WNDPROC) GetWindowLong(hwndParent, GWL_WNDPROC);
|
||||
if (pfnOrigProc != _HyperlinkParentProc)
|
||||
{
|
||||
SetProp(hwndParent, PROP_ORIGINAL_PROC, (HANDLE) pfnOrigProc);
|
||||
SetWindowLong(hwndParent, GWL_WNDPROC, (LONG) (WNDPROC) _HyperlinkParentProc);
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure the control will send notifications.
|
||||
|
||||
DWORD dwStyle = GetWindowLong(hwndCtl, GWL_STYLE);
|
||||
SetWindowLong(hwndCtl, GWL_STYLE, dwStyle | SS_NOTIFY);
|
||||
|
||||
// Subclass the existing control.
|
||||
|
||||
WNDPROC pfnOrigProc = (WNDPROC) GetWindowLong(hwndCtl, GWL_WNDPROC);
|
||||
SetProp(hwndCtl, PROP_ORIGINAL_PROC, (HANDLE) pfnOrigProc);
|
||||
SetWindowLong(hwndCtl, GWL_WNDPROC, (LONG) (WNDPROC) _HyperlinkProc);
|
||||
|
||||
// Create an updated font by adding an underline.
|
||||
|
||||
HFONT hOrigFont = (HFONT) SendMessage(hwndCtl, WM_GETFONT, 0, 0);
|
||||
SetProp(hwndCtl, PROP_ORIGINAL_FONT, (HANDLE) hOrigFont);
|
||||
|
||||
LOGFONT lf;
|
||||
GetObject(hOrigFont, sizeof(lf), &lf);
|
||||
lf.lfUnderline = TRUE;
|
||||
|
||||
HFONT hFont = CreateFontIndirect(&lf);
|
||||
SetProp(hwndCtl, PROP_UNDERLINE_FONT, (HANDLE) hFont);
|
||||
|
||||
// Set a flag on the control so we know what color it should be.
|
||||
|
||||
SetProp(hwndCtl, PROP_STATIC_HYPERLINK, (HANDLE) 1);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL ConvertStaticToHyperlink(HWND hwndParent, UINT uiCtlId)
|
||||
{
|
||||
return ConvertStaticToHyperlink(GetDlgItem(hwndParent, uiCtlId));
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
// Hyperlinks.h
|
||||
//
|
||||
// Copyright 2002 Neal Stublen
|
||||
// All rights reserved.
|
||||
//
|
||||
// http://www.awesoftware.com
|
||||
//
|
||||
|
||||
BOOL ConvertStaticToHyperlink(HWND hwndCtl);
|
||||
BOOL ConvertStaticToHyperlink(HWND hwndParent, UINT uiCtlId);
|
|
@ -305,10 +305,6 @@
|
|||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\AboutDlg.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\AdvancedDlg.cpp"
|
||||
>
|
||||
|
@ -433,6 +429,37 @@
|
|||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\Hyperlinks.cpp"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
PrecompiledHeaderThrough="Win32.h"
|
||||
PrecompiledHeaderFile="$(IntDir)\win32.pch"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Devel|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
PrecompiledHeaderThrough="Win32.h"
|
||||
PrecompiledHeaderFile="$(IntDir)\win32.pch"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
PrecompiledHeaderThrough="Win32.h"
|
||||
PrecompiledHeaderFile="$(IntDir)\win32.pch"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\ini.cpp"
|
||||
>
|
||||
|
@ -520,10 +547,6 @@
|
|||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\McdsDlg.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\PatchBrowser.cpp"
|
||||
>
|
||||
|
@ -578,11 +601,7 @@
|
|||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\RDebugger.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\Win32.h"
|
||||
RelativePath="..\..\Saveslots.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
|
@ -839,10 +858,42 @@
|
|||
RelativePath="..\ps2_silver.bmp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Include"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\AboutDlg.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\HostGui.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\Hyperlinks.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\McdsDlg.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\RDebugger.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\resource.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\Win32.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\WinDebugResource.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<Filter
|
||||
|
@ -2287,14 +2338,6 @@
|
|||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Dynarec"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\x86\iIPU.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="memory"
|
||||
|
@ -2343,38 +2386,6 @@
|
|||
RelativePath="..\..\MTGS.cpp"
|
||||
>
|
||||
</File>
|
||||
<Filter
|
||||
Name="Dynarec"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\x86\iGS.cpp"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Devel|Win32"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="VUmicro"
|
||||
|
@ -2595,42 +2606,6 @@
|
|||
RelativePath="..\..\SPR.h"
|
||||
>
|
||||
</File>
|
||||
<Filter
|
||||
Name="Dynarec"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\x86\iHw.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\x86\iPsxHw.cpp"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Devel|Win32"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Sif"
|
||||
|
@ -2732,6 +2707,10 @@
|
|||
RelativePath="..\..\Plugins.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\RecoverySystem.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\SamplProf.cpp"
|
||||
>
|
||||
|
@ -3096,7 +3075,7 @@
|
|||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\WinDebugResource.h"
|
||||
RelativePath="..\WinDebugResource"
|
||||
>
|
||||
</File>
|
||||
</Files>
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <tchar.h>
|
||||
|
||||
#include "Misc.h"
|
||||
#include "HostGui.h"
|
||||
#include "resource.h"
|
||||
#include "WinDebugResource.h"
|
||||
|
||||
|
@ -121,43 +122,35 @@ public:
|
|||
void EnumEntry( const string& var, int& value, const char* const* enumArray, const int defvalue=0 );
|
||||
};
|
||||
|
||||
LRESULT WINAPI MainWndProc(HWND, UINT, WPARAM, LPARAM);
|
||||
void CreateMainWindow();
|
||||
void RunGui();
|
||||
extern LRESULT WINAPI MainWndProc(HWND, UINT, WPARAM, LPARAM);
|
||||
extern void CreateMainWindow();
|
||||
extern void RunGui();
|
||||
extern bool HostGuiInit();
|
||||
|
||||
BOOL Pcsx2Configure(HWND hWnd);
|
||||
void InitLanguages();
|
||||
char *GetLanguageNext();
|
||||
void CloseLanguages();
|
||||
void ChangeLanguage(char *lang);
|
||||
extern BOOL Pcsx2Configure(HWND hWnd);
|
||||
extern void InitLanguages();
|
||||
extern char *GetLanguageNext();
|
||||
extern void CloseLanguages();
|
||||
extern void ChangeLanguage(char *lang);
|
||||
|
||||
void SysRestorableReset();
|
||||
extern void WinClose();
|
||||
extern void ExecuteCpu();
|
||||
extern void OnStates_LoadOther();
|
||||
extern void OnStates_SaveOther();
|
||||
extern int ParseCommandLine( int tokenCount, TCHAR *const *const tokens );
|
||||
extern void strcatz(char *dst, char *src);
|
||||
|
||||
void WinClose();
|
||||
void States_Load( const string& file, int num=-1 );
|
||||
void States_Save( const string& file, int num=-1 );
|
||||
void States_Load(int num);
|
||||
void States_Save(int num);
|
||||
void OnStates_LoadOther();
|
||||
void OnStates_SaveOther();
|
||||
int ParseCommandLine( int tokenCount, TCHAR *const *const tokens );
|
||||
void RunExecute( const char* elf_file, bool use_bios=false );
|
||||
void ExecuteCpu();
|
||||
void strcatz(char *dst, char *src);
|
||||
|
||||
BOOL CALLBACK PatchBDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
BOOL CALLBACK CpuDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
BOOL CALLBACK AdvancedOptionsProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
BOOL CALLBACK HacksProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
|
||||
extern BOOL CALLBACK PatchBDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
extern BOOL CALLBACK CpuDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
extern BOOL CALLBACK AdvancedOptionsProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
extern BOOL CALLBACK HacksProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
extern AppData gApp;
|
||||
extern HWND hStatusWnd;
|
||||
extern PcsxConfig winConfig; // local storage of the configuration options.
|
||||
extern bool g_ReturnToGui; // set to exit the execution of the emulator and return control to the GUI
|
||||
extern bool g_EmulationInProgress; // Set TRUE if a game is actively running (set to false on reset)
|
||||
|
||||
extern int UseGui;
|
||||
extern int nDisableSC; // screensaver
|
||||
extern bool UseGui;
|
||||
extern bool nDisableSC; // screensaver
|
||||
extern unsigned int langsMax;
|
||||
|
||||
extern SafeArray<u8>* g_RecoveryState;
|
||||
|
@ -165,11 +158,6 @@ extern SafeArray<u8>* g_gsRecoveryState;
|
|||
extern const char* g_pRunGSState;
|
||||
extern int g_SaveGSStream;
|
||||
|
||||
|
||||
// sets the contents of the Pcsx2 status bar...
|
||||
extern void StatusBar_Notice( const std::string& text );
|
||||
extern void StatusBar_SetMsg( const std::string& text );
|
||||
|
||||
// Throws an exception based on the value returned from GetLastError.
|
||||
// Performs an option return value success/fail check on hresult.
|
||||
extern void StreamException_ThrowLastError( const string& streamname, HANDLE result=INVALID_HANDLE_VALUE );
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#define IDD_BPCNT 105
|
||||
#define IDD_DEBUG 108
|
||||
#define IDD_VU0REGS 111
|
||||
#define IDD_JUMP 112
|
||||
#define IDD_VU0INTEGER 113
|
||||
#define IDD_GPREGS 114
|
||||
#define IDD_CP0REGS 115
|
||||
|
@ -172,6 +173,7 @@
|
|||
#define IDC_VU1_VF26 1097
|
||||
#define IDC_DEBUG_DUMP 1097
|
||||
#define IDC_CP04 1097
|
||||
#define IDC_JUMP_PC 1097
|
||||
#define IDC_VU1_VF27 1098
|
||||
#define IDC_DUMP_END 1098
|
||||
#define IDC_DEBUG_MEMORY 1098
|
||||
|
|
|
@ -59,8 +59,6 @@ void strcatz(char *dst, char *src)
|
|||
BOOL APIENTRY CmdlineProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);//forward def
|
||||
//-------------------
|
||||
|
||||
TESTRUNARGS g_TestRun;
|
||||
|
||||
static const char* phelpmsg =
|
||||
"pcsx2 [options] [file]\n\n"
|
||||
"-cfg [file] {configuration file}\n"
|
||||
|
@ -175,7 +173,7 @@ static PTCHAR* _CommandLineToArgv( const TCHAR *CmdLine, int* _argc )
|
|||
|
||||
void WinClose()
|
||||
{
|
||||
SysClose();
|
||||
cpuShutdown();
|
||||
|
||||
// Don't check Config.Profiler here -- the Profiler will know if it's running or not.
|
||||
ProfilerTerm();
|
||||
|
@ -197,9 +195,9 @@ static bool TestRunMode()
|
|||
if( IsDevBuild && (g_TestRun.enabled || g_TestRun.ptitle != NULL) )
|
||||
{
|
||||
// run without ui
|
||||
UseGui = 0;
|
||||
UseGui = false;
|
||||
PCSX2_MEM_PROTECT_BEGIN();
|
||||
RunExecute( g_TestRun.efile ? g_TestRun.ptitle : NULL );
|
||||
SysPrepareExecution( g_TestRun.efile ? g_TestRun.ptitle : NULL );
|
||||
PCSX2_MEM_PROTECT_END();
|
||||
return true;
|
||||
}
|
||||
|
@ -347,7 +345,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
|||
// Important! Always allocate dynarecs before loading plugins, to give the dynarecs
|
||||
// the best possible chance of claiming ideal memory space!
|
||||
|
||||
SysInit();
|
||||
HostGuiInit();
|
||||
|
||||
if( needsToConfig )
|
||||
{
|
||||
|
@ -630,22 +628,24 @@ LRESULT WINAPI MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|||
|
||||
case ID_FILEOPEN:
|
||||
{
|
||||
std::string outstr;
|
||||
string outstr;
|
||||
if( Open_File_Proc( outstr ) )
|
||||
RunExecute( outstr.c_str() );
|
||||
{
|
||||
SysReset();
|
||||
SysPrepareExecution( outstr.c_str() );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ID_RUN_EXECUTE:
|
||||
if( g_EmulationInProgress )
|
||||
ExecuteCpu();
|
||||
else
|
||||
RunExecute( NULL, true ); // boots bios if no savestate is to be recovered
|
||||
// Execute without reset -- resumes existing states or runs the BIOS if
|
||||
// the state is cleared/reset.
|
||||
SysPrepareExecution( NULL, true );
|
||||
break;
|
||||
|
||||
case ID_FILE_RUNCD:
|
||||
SysReset();
|
||||
RunExecute( NULL );
|
||||
SysPrepareExecution( NULL );
|
||||
break;
|
||||
|
||||
case ID_RUN_RESET:
|
||||
|
@ -745,7 +745,7 @@ LRESULT WINAPI MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|||
if (remoteDebugBios)
|
||||
{
|
||||
cpuReset();
|
||||
SysResetExecutionState();
|
||||
SysClearExecutionCache();
|
||||
cpuExecuteBios();
|
||||
|
||||
DialogBox(gApp.hInstance, MAKEINTRESOURCE(IDD_RDEBUG), NULL, (DLGPROC)RemoteDebuggerProc);
|
||||
|
@ -870,19 +870,6 @@ LRESULT WINAPI MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|||
return DefWindowProc(hWnd, msg, wParam, lParam);
|
||||
}
|
||||
|
||||
int Slots[5] = { -1, -1, -1, -1, -1 };
|
||||
|
||||
void ResetMenuSlots() {
|
||||
int i;
|
||||
|
||||
for (i=0; i<5; i++) {
|
||||
if (Slots[i] == -1)
|
||||
EnableMenuItem(GetSubMenu(gApp.hMenu, 0), ID_FILE_STATES_LOAD_SLOT1+i, MF_GRAYED);
|
||||
else
|
||||
EnableMenuItem(GetSubMenu(gApp.hMenu, 0), ID_FILE_STATES_LOAD_SLOT1+i, MF_ENABLED);
|
||||
}
|
||||
}
|
||||
|
||||
// fixme - this looks like the beginnings of a dynamic "list of valid saveslots"
|
||||
// feature. Too bad it's never called and CheckState was old/dead code.
|
||||
/*void UpdateMenuSlots() {
|
||||
|
@ -1040,7 +1027,7 @@ void CreateMainWindow()
|
|||
RECT rect;
|
||||
int w, h;
|
||||
|
||||
g_ReturnToGui = true;
|
||||
//g_ReturnToGui = true;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
sprintf(COMPILER, "(VC%d)", (_MSC_VER+100)/200);//hacky:) works for VC6 & VC.NET
|
||||
|
@ -1080,7 +1067,7 @@ void CreateMainWindow()
|
|||
);
|
||||
|
||||
gApp.hWnd = hWnd;
|
||||
ResetMenuSlots();
|
||||
HostGui::ResetMenuSlots();
|
||||
CreateMainMenu();
|
||||
|
||||
SetMenu(gApp.hWnd, gApp.hMenu);
|
||||
|
@ -1100,7 +1087,7 @@ void CreateMainWindow()
|
|||
MoveWindow(hWnd, 60, 60, w, h, TRUE);
|
||||
SendMessage( hStatusWnd, WM_SIZE, 0, 0 );
|
||||
|
||||
StatusBar_SetMsg("F1 - save, F2 - next state, Shift+F2 - prev state, F3 - load, F8 - snapshot");
|
||||
HostGui::SetStatusMsg("F1 - save, F2 - next state, Shift+F2 - prev state, F3 - load, F8 - snapshot");
|
||||
|
||||
ShowWindow(hWnd, true);
|
||||
SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
|
||||
|
|
|
@ -20,20 +20,14 @@
|
|||
#include <winnt.h>
|
||||
|
||||
#include "Common.h"
|
||||
//#include "PsxCommon.h"
|
||||
#include "VUmicro.h"
|
||||
|
||||
#include "iR5900.h"
|
||||
|
||||
int UseGui = 1;
|
||||
int nDisableSC = 0; // screensaver
|
||||
static bool sinit = false;
|
||||
bool UseGui = true;
|
||||
bool nDisableSC = false; // screensaver
|
||||
|
||||
SafeArray<u8>* g_RecoveryState = NULL;
|
||||
SafeArray<u8>* g_gsRecoveryState = NULL;
|
||||
|
||||
|
||||
bool g_ReturnToGui = false; // set to exit the execution of the emulator and return control to the GUI
|
||||
bool g_EmulationInProgress = false; // Set TRUE if a game is actively running (set to false on reset)
|
||||
|
||||
// This instance is not modified by command line overrides so
|
||||
// that command line plugins and stuff won't be saved into the
|
||||
|
@ -50,7 +44,6 @@ const char* g_pRunGSState = NULL;
|
|||
int SysPageFaultExceptionFilter( EXCEPTION_POINTERS* eps )
|
||||
{
|
||||
const _EXCEPTION_RECORD& ExceptionRecord = *eps->ExceptionRecord;
|
||||
//const _CONTEXT& ContextRecord = *eps->ContextRecord;
|
||||
|
||||
if (ExceptionRecord.ExceptionCode != EXCEPTION_ACCESS_VIOLATION)
|
||||
{
|
||||
|
@ -69,25 +62,6 @@ int SysPageFaultExceptionFilter( EXCEPTION_POINTERS* eps )
|
|||
}
|
||||
|
||||
|
||||
// For issuing notices to both the status bar and the console at the same time.
|
||||
// Single-line text only please! Mutli-line msgs should be directed to the
|
||||
// console directly, thanks.
|
||||
void StatusBar_Notice( const std::string& text )
|
||||
{
|
||||
// mirror output to the console!
|
||||
Console::Status( text.c_str() );
|
||||
|
||||
// don't try this in GCC folks!
|
||||
SendMessage(hStatusWnd, SB_SETTEXT, 0, (LPARAM)text.c_str() );
|
||||
}
|
||||
|
||||
// Sets the status bar message without mirroring the output to the console.
|
||||
void StatusBar_SetMsg( const std::string& text )
|
||||
{
|
||||
// don't try this in GCC folks!
|
||||
SendMessage(hStatusWnd, SB_SETTEXT, 0, (LPARAM)text.c_str() );
|
||||
}
|
||||
|
||||
// returns 1 if the user requested help (show help and exit)
|
||||
// returns zero on success.
|
||||
// returns -1 on failure (bad command line argument)
|
||||
|
@ -116,7 +90,7 @@ int ParseCommandLine( int tokenCount, TCHAR *const *const tokens )
|
|||
return -1;
|
||||
}
|
||||
else if( CmdSwitchIs( "nogui" ) ) {
|
||||
UseGui = 0;
|
||||
UseGui = false;
|
||||
}
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
else if( CmdSwitchIs( "jpg" ) ) {
|
||||
|
@ -205,376 +179,6 @@ void SysPrintf(const char *fmt, ...)
|
|||
Console::Write( msg );
|
||||
}
|
||||
|
||||
static void __fastcall KeyEvent(keyEvent* ev);
|
||||
|
||||
__forceinline void SysUpdate() {
|
||||
|
||||
keyEvent* ev1 = PAD1keyEvent();
|
||||
keyEvent* ev2 = PAD2keyEvent();
|
||||
|
||||
KeyEvent( (ev1 != NULL) ? ev1 : ev2);
|
||||
}
|
||||
|
||||
static void TryRecoverFromGsState()
|
||||
{
|
||||
if( g_gsRecoveryState != NULL )
|
||||
{
|
||||
s32 dummylen;
|
||||
|
||||
memLoadingState eddie( *g_gsRecoveryState );
|
||||
eddie.FreezePlugin( "GS", gsSafeFreeze );
|
||||
eddie.Freeze( dummylen ); // reads the length value recorded earlier.
|
||||
eddie.gsFreeze();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#include "R5900Exceptions.h"
|
||||
|
||||
void ExecuteCpu()
|
||||
{
|
||||
// Make sure any left-over recovery states are cleaned up.
|
||||
safe_delete( g_RecoveryState );
|
||||
|
||||
// Just in case they weren't initialized earlier (no harm in calling this multiple times)
|
||||
if (OpenPlugins(NULL) == -1) return;
|
||||
|
||||
// this needs to be called for every new game!
|
||||
// (note: sometimes launching games through bios will give a crc of 0)
|
||||
|
||||
if( GSsetGameCRC != NULL )
|
||||
GSsetGameCRC(ElfCRC, g_ZeroGSOptions);
|
||||
|
||||
TryRecoverFromGsState();
|
||||
|
||||
safe_delete( g_gsRecoveryState );
|
||||
|
||||
// ... and hide the window. Ugly thing.
|
||||
|
||||
ShowWindow( gApp.hWnd, SW_HIDE );
|
||||
|
||||
g_EmulationInProgress = true;
|
||||
g_ReturnToGui = false;
|
||||
|
||||
// Optimization: We hardcode two versions of the EE here -- one for recs and one for ints.
|
||||
// This is because recs are performance critical, and being able to inline them into the
|
||||
// function here helps a small bit (not much but every small bit counts!).
|
||||
|
||||
timeBeginPeriod( 1 );
|
||||
|
||||
try
|
||||
{
|
||||
if( CHECK_EEREC )
|
||||
{
|
||||
while( !g_ReturnToGui )
|
||||
{
|
||||
recExecute();
|
||||
SysUpdate();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while( !g_ReturnToGui )
|
||||
{
|
||||
Cpu->Execute();
|
||||
SysUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch( R5900Exception::BaseExcept& ex )
|
||||
{
|
||||
Console::Error( ex.cMessage() );
|
||||
Console::Error( fmt_string( "(EE) PC: 0x%8.8x \tCycle:0x8.8x", ex.cpuState.pc, ex.cpuState.cycle ).c_str() );
|
||||
|
||||
if( !Config.PsxOut )
|
||||
{
|
||||
// TODO : no console opened, so use a popup to msg the user.
|
||||
// Need to take care to shut down the GS first, or else it'll cause ugliness on fullscreen execution.
|
||||
}
|
||||
}
|
||||
|
||||
timeEndPeriod( 1 );
|
||||
|
||||
ShowWindow( gApp.hWnd, SW_SHOW );
|
||||
SetForegroundWindow( gApp.hWnd );
|
||||
}
|
||||
|
||||
// Runs and ELF image directly (ISO or ELF program or BIN)
|
||||
// Used by Run::FromCD and such
|
||||
void RunExecute( const char* elf_file, bool use_bios )
|
||||
{
|
||||
nDisableSC = 1;
|
||||
|
||||
try
|
||||
{
|
||||
cpuReset();
|
||||
}
|
||||
catch( Exception::BaseException& ex )
|
||||
{
|
||||
Msgbox::Alert( ex.cMessage() );
|
||||
return;
|
||||
}
|
||||
|
||||
if (OpenPlugins(g_TestRun.ptitle) == -1)
|
||||
return;
|
||||
|
||||
if( elf_file == NULL )
|
||||
{
|
||||
if(g_RecoveryState != NULL)
|
||||
{
|
||||
try
|
||||
{
|
||||
memLoadingState( *g_RecoveryState ).FreezeAll();
|
||||
}
|
||||
catch( std::runtime_error& ex )
|
||||
{
|
||||
Msgbox::Alert(
|
||||
"Gamestate recovery failed. Your game progress will be lost (sorry!)\n"
|
||||
"\nError: %s\n", params ex.what() );
|
||||
|
||||
// Take the user back to the GUI...
|
||||
safe_delete( g_RecoveryState );
|
||||
ClosePlugins( true );
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if( g_gsRecoveryState == NULL )
|
||||
{
|
||||
// Not recovering a state, so need to execute the bios and load the ELF information.
|
||||
// (note: gsRecoveries are done from ExecuteCpu)
|
||||
|
||||
// if the elf_file is null we use the CDVD elf file.
|
||||
// But if the elf_file is an empty string then we boot the bios instead.
|
||||
|
||||
char ename[g_MaxPath];
|
||||
ename[0] = 0;
|
||||
if( !use_bios )
|
||||
GetPS2ElfName( ename );
|
||||
|
||||
loadElfFile( ename );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Custom ELF specified (not using CDVD).
|
||||
// Run the BIOS and load the ELF.
|
||||
|
||||
loadElfFile( elf_file );
|
||||
}
|
||||
|
||||
ExecuteCpu();
|
||||
}
|
||||
|
||||
class RecoveryMemSavingState : public memSavingState, Sealed
|
||||
{
|
||||
public:
|
||||
virtual ~RecoveryMemSavingState() { }
|
||||
RecoveryMemSavingState() : memSavingState( *g_RecoveryState )
|
||||
{
|
||||
}
|
||||
|
||||
void gsFreeze()
|
||||
{
|
||||
if( g_gsRecoveryState != NULL )
|
||||
{
|
||||
// just copy the data from src to dst.
|
||||
// the normal savestate doesn't expect a length prefix for internal structures,
|
||||
// so don't copy that part.
|
||||
const u32 pluginlen = *((u32*)g_gsRecoveryState->GetPtr());
|
||||
const u32 gslen = *((u32*)g_gsRecoveryState->GetPtr(pluginlen+4));
|
||||
memcpy( m_memory.GetPtr(m_idx), g_gsRecoveryState->GetPtr(pluginlen+8), gslen );
|
||||
m_idx += gslen;
|
||||
}
|
||||
else
|
||||
memSavingState::gsFreeze();
|
||||
}
|
||||
|
||||
void FreezePlugin( const char* name, s32 (CALLBACK* freezer)(int mode, freezeData *data) )
|
||||
{
|
||||
if( (freezer == gsSafeFreeze) && (g_gsRecoveryState != NULL) )
|
||||
{
|
||||
// Gs data is already in memory, so just copy from src to dest:
|
||||
// length of the GS data is stored as the first u32, so use that to run the copy:
|
||||
const u32 len = *((u32*)g_gsRecoveryState->GetPtr());
|
||||
memcpy( m_memory.GetPtr(m_idx), g_gsRecoveryState->GetPtr(), len+4 );
|
||||
m_idx += len+4;
|
||||
}
|
||||
else
|
||||
memSavingState::FreezePlugin( name, freezer );
|
||||
}
|
||||
};
|
||||
|
||||
class RecoveryZipSavingState : public gzSavingState, Sealed
|
||||
{
|
||||
public:
|
||||
virtual ~RecoveryZipSavingState() { }
|
||||
RecoveryZipSavingState( const string& filename ) : gzSavingState( filename )
|
||||
{
|
||||
}
|
||||
|
||||
void gsFreeze()
|
||||
{
|
||||
if( g_gsRecoveryState != NULL )
|
||||
{
|
||||
// read data from the gsRecoveryState allocation instead of the GS, since the gs
|
||||
// info was invalidated when the plugin was shut down.
|
||||
|
||||
// the normal savestate doesn't expect a length prefix for internal structures,
|
||||
// so don't copy that part.
|
||||
|
||||
u32& pluginlen = *((u32*)g_gsRecoveryState->GetPtr(0));
|
||||
u32& gslen = *((u32*)g_gsRecoveryState->GetPtr(pluginlen+4));
|
||||
gzwrite( m_file, g_gsRecoveryState->GetPtr(pluginlen+4), gslen );
|
||||
}
|
||||
else
|
||||
gzSavingState::gsFreeze();
|
||||
}
|
||||
|
||||
void FreezePlugin( const char* name, s32 (CALLBACK* freezer)(int mode, freezeData *data) )
|
||||
{
|
||||
if( (freezer == gsSafeFreeze) && (g_gsRecoveryState != NULL) )
|
||||
{
|
||||
// Gs data is already in memory, so just copy from there into the gzip file.
|
||||
// length of the GS data is stored as the first u32, so use that to run the copy:
|
||||
u32& len = *((u32*)g_gsRecoveryState->GetPtr());
|
||||
gzwrite( m_file, g_gsRecoveryState->GetPtr(), len+4 );
|
||||
}
|
||||
else
|
||||
gzSavingState::FreezePlugin( name, freezer );
|
||||
}
|
||||
};
|
||||
|
||||
void States_Load( const string& file, int num )
|
||||
{
|
||||
if( !Path::isFile( file ) )
|
||||
{
|
||||
Console::Notice( "Saveslot %d is empty.", params num );
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
char Text[g_MaxPath];
|
||||
gzLoadingState joe( file ); // this'll throw an StateLoadError_Recoverable.
|
||||
|
||||
// Make sure the cpu and plugins are ready to be state-ified!
|
||||
cpuReset();
|
||||
OpenPlugins( NULL );
|
||||
|
||||
joe.FreezeAll();
|
||||
|
||||
if( num != -1 )
|
||||
sprintf (Text, _("*PCSX2*: Loaded State %d"), num);
|
||||
else
|
||||
sprintf (Text, _("*PCSX2*: Loaded State %s"), file);
|
||||
|
||||
StatusBar_Notice( Text );
|
||||
|
||||
if( GSsetGameCRC != NULL )
|
||||
GSsetGameCRC(ElfCRC, g_ZeroGSOptions);
|
||||
}
|
||||
catch( Exception::StateLoadError_Recoverable& ex)
|
||||
{
|
||||
if( num != -1 )
|
||||
Console::Notice( "Could not load savestate from slot %d.\n\n%s", params num, ex.cMessage() );
|
||||
else
|
||||
Console::Notice( "Could not load savestate file: %s.\n\n%s", params file, ex.cMessage() );
|
||||
|
||||
// At this point the cpu hasn't been reset, so we can return
|
||||
// control to the user safely... (that's why we use a console notice instead of a popup)
|
||||
|
||||
return;
|
||||
}
|
||||
catch( Exception::BaseException& ex )
|
||||
{
|
||||
// The emulation state is ruined. Might as well give them a popup and start the gui.
|
||||
|
||||
string message;
|
||||
|
||||
if( num != -1 )
|
||||
ssprintf( message,
|
||||
"Encountered an error while loading savestate from slot %d.\n", num );
|
||||
else
|
||||
ssprintf( message,
|
||||
"Encountered an error while loading savestate from file: %s.\n", file );
|
||||
|
||||
if( g_EmulationInProgress )
|
||||
message += "Since the savestate load was incomplete, the emulator has been reset.\n";
|
||||
|
||||
message += "\nError: " + ex.Message();
|
||||
|
||||
Msgbox::Alert( message.c_str() );
|
||||
SysClose();
|
||||
return;
|
||||
}
|
||||
|
||||
// Start emulating!
|
||||
ExecuteCpu();
|
||||
}
|
||||
|
||||
void States_Save( const string& file, int num )
|
||||
{
|
||||
try
|
||||
{
|
||||
string text;
|
||||
RecoveryZipSavingState( file ).FreezeAll();
|
||||
if( num != -1 )
|
||||
ssprintf( text, _( "State saved to slot %d" ), num );
|
||||
else
|
||||
ssprintf( text, _( "State saved to file: %s" ), file );
|
||||
|
||||
StatusBar_Notice( text );
|
||||
}
|
||||
catch( Exception::BaseException& ex )
|
||||
{
|
||||
string message;
|
||||
|
||||
if( num != -1 )
|
||||
ssprintf( message, "An error occurred while trying to save to slot %d\n", num );
|
||||
else
|
||||
ssprintf( message, "An error occurred while trying to save to file: %s\n", file );
|
||||
|
||||
message += "Your emulation state has not been saved!\n\nError: " + ex.Message();
|
||||
|
||||
Console::Error( message.c_str() );
|
||||
}
|
||||
}
|
||||
|
||||
void States_Load(int num)
|
||||
{
|
||||
States_Load( SaveState::GetFilename( num ), num );
|
||||
}
|
||||
|
||||
void States_Save(int num)
|
||||
{
|
||||
if( g_RecoveryState != NULL )
|
||||
{
|
||||
// State is already saved into memory, and the emulator (and in-progress flag)
|
||||
// have likely been cleared out. So save from the Recovery buffer instead of
|
||||
// doing a "standard" save:
|
||||
|
||||
string text( SaveState::GetFilename( num ) );
|
||||
gzFile fileptr = gzopen( text.c_str(), "wb" );
|
||||
if( fileptr == NULL )
|
||||
{
|
||||
Msgbox::Alert( _("File permissions error while trying to save to slot %d"), params num );
|
||||
return;
|
||||
}
|
||||
gzwrite( fileptr, &g_SaveVersion, sizeof( u32 ) );
|
||||
gzwrite( fileptr, g_RecoveryState->GetPtr(), g_RecoveryState->GetSizeInBytes() );
|
||||
gzclose( fileptr );
|
||||
return;
|
||||
}
|
||||
|
||||
if( !g_EmulationInProgress )
|
||||
{
|
||||
Msgbox::Alert( "You need to start a game first before you can save it's state." );
|
||||
return;
|
||||
}
|
||||
|
||||
States_Save( SaveState::GetFilename( num ), num );
|
||||
}
|
||||
|
||||
void OnStates_LoadOther()
|
||||
{
|
||||
OPENFILENAME ofn;
|
||||
|
@ -639,171 +243,14 @@ void OnStates_SaveOther()
|
|||
States_Save( szFileName );
|
||||
}
|
||||
|
||||
class JustGsSavingState : public memSavingState, Sealed
|
||||
{
|
||||
public:
|
||||
virtual ~JustGsSavingState() { }
|
||||
JustGsSavingState() : memSavingState( *g_gsRecoveryState )
|
||||
{
|
||||
}
|
||||
|
||||
// This special override saves the gs info to m_idx+4, and then goes back and
|
||||
// writes in the length of data saved.
|
||||
void gsFreeze()
|
||||
{
|
||||
int oldmidx = m_idx;
|
||||
m_idx += 4;
|
||||
memSavingState::gsFreeze();
|
||||
if( IsSaving() )
|
||||
{
|
||||
s32& len = *((s32*)m_memory.GetPtr( oldmidx ));
|
||||
len = (m_idx - oldmidx)-4;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static int shiftkey = 0;
|
||||
static void __fastcall KeyEvent(keyEvent* ev)
|
||||
{
|
||||
if (ev == NULL) return;
|
||||
if (ev->evt == KEYRELEASE) {
|
||||
switch (ev->key) {
|
||||
case VK_SHIFT: shiftkey = 0; break;
|
||||
}
|
||||
GSkeyEvent(ev); return;
|
||||
}
|
||||
if (ev->evt != KEYPRESS)
|
||||
return;
|
||||
|
||||
//some pad plugins don't give a key released event for shift, so this is needed
|
||||
//shiftkey = GetKeyState(VK_SHIFT)&0x8000;
|
||||
//Well SSXPad breaks with your code, thats why my code worked and your makes reg dumping impossible
|
||||
//So i suggest you fix the plugins that dont.
|
||||
|
||||
switch (ev->key) {
|
||||
case VK_SHIFT: shiftkey = 1; break;
|
||||
|
||||
case VK_F1: case VK_F2: case VK_F3: case VK_F4:
|
||||
case VK_F5: case VK_F6: case VK_F7: case VK_F8:
|
||||
case VK_F9: case VK_F10: case VK_F11: case VK_F12:
|
||||
try
|
||||
{
|
||||
ProcessFKeys(ev->key-VK_F1 + 1, shiftkey);
|
||||
}
|
||||
catch( Exception::CpuStateShutdown& )
|
||||
{
|
||||
// Woops! Something was unrecoverable. Bummer.
|
||||
// Let's give the user a RunGui!
|
||||
|
||||
g_EmulationInProgress = false;
|
||||
g_ReturnToGui = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case VK_TAB:
|
||||
CycleFrameLimit(0);
|
||||
break;
|
||||
|
||||
case VK_ESCAPE:
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
if( g_SaveGSStream >= 3 ) {
|
||||
// gs state
|
||||
g_SaveGSStream = 4;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
g_ReturnToGui = true;
|
||||
if( CHECK_ESCAPE_HACK )
|
||||
{
|
||||
//PostMessage(GetForegroundWindow(), WM_CLOSE, 0, 0);
|
||||
DestroyWindow( gApp.hWnd );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !UseGui ) {
|
||||
// not using GUI and user just quit, so exit
|
||||
WinClose();
|
||||
}
|
||||
|
||||
if( Config.closeGSonEsc )
|
||||
{
|
||||
safe_delete( g_gsRecoveryState );
|
||||
safe_delete( g_RecoveryState );
|
||||
g_gsRecoveryState = new SafeArray<u8>();
|
||||
JustGsSavingState eddie;
|
||||
eddie.FreezePlugin( "GS", gsSafeFreeze ) ;
|
||||
eddie.gsFreeze();
|
||||
}
|
||||
|
||||
ClosePlugins( Config.closeGSonEsc );
|
||||
nDisableSC = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
GSkeyEvent(ev);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static bool sinit=false;
|
||||
|
||||
|
||||
void SysRestorableReset()
|
||||
{
|
||||
// already reset? and saved?
|
||||
if( !g_EmulationInProgress ) return;
|
||||
if( g_RecoveryState != NULL ) return;
|
||||
|
||||
try
|
||||
{
|
||||
g_RecoveryState = new SafeArray<u8>( "Memory Savestate Recovery" );
|
||||
RecoveryMemSavingState().FreezeAll();
|
||||
safe_delete( g_gsRecoveryState );
|
||||
g_EmulationInProgress = false;
|
||||
}
|
||||
catch( Exception::RuntimeError& ex )
|
||||
{
|
||||
Msgbox::Alert(
|
||||
"Pcsx2 gamestate recovery failed. Some options may have been reverted to protect your game's state.\n"
|
||||
"Error: %s", params ex.cMessage() );
|
||||
safe_delete( g_RecoveryState );
|
||||
}
|
||||
}
|
||||
|
||||
void SysReset()
|
||||
{
|
||||
if (!sinit) return;
|
||||
|
||||
// fixme - this code sets the statusbar but never returns control to the window message pump
|
||||
// so the status bar won't receive the WM_PAINT messages needed to update itself anyway.
|
||||
// Oops! (air)
|
||||
|
||||
StatusBar_Notice(_("Resetting..."));
|
||||
Console::SetTitle(_("Resetting..."));
|
||||
|
||||
g_EmulationInProgress = false;
|
||||
safe_delete( g_RecoveryState );
|
||||
safe_delete( g_gsRecoveryState );
|
||||
ResetPlugins();
|
||||
|
||||
ElfCRC = 0;
|
||||
|
||||
// Note : No need to call cpuReset() here. It gets called automatically before the
|
||||
// emulator resumes execution.
|
||||
|
||||
StatusBar_Notice(_("Ready"));
|
||||
Console::SetTitle(_("*PCSX2* Emulation state is reset."));
|
||||
}
|
||||
|
||||
bool SysInit()
|
||||
bool HostGuiInit()
|
||||
{
|
||||
if( sinit ) return true;
|
||||
sinit = true;
|
||||
|
||||
CreateDirectory(MEMCARDS_DIR, NULL);
|
||||
CreateDirectory(SSTATES_DIR, NULL);
|
||||
CreateDirectory(SNAPSHOTS_DIR, NULL);
|
||||
|
||||
// Set the compression attribute on the Memcards folder.
|
||||
// Memcards generally compress very well via NTFS compression.
|
||||
|
@ -827,80 +274,208 @@ bool SysInit()
|
|||
return true;
|
||||
}
|
||||
|
||||
// completely shuts down the emulator's cpu state, and unloads all plugins from memory.
|
||||
void SysClose()
|
||||
{
|
||||
if (!sinit) return;
|
||||
cpuShutdown();
|
||||
ClosePlugins( true );
|
||||
ReleasePlugins();
|
||||
sinit = false;
|
||||
}
|
||||
|
||||
|
||||
static const char *err = N_("Error Loading Symbol");
|
||||
static int errval;
|
||||
|
||||
void *SysLoadLibrary(const char *lib) {
|
||||
return LoadLibrary(lib);
|
||||
}
|
||||
|
||||
void *SysLoadSym(void *lib, const char *sym) {
|
||||
void *tmp = GetProcAddress((HINSTANCE)lib, sym);
|
||||
if (tmp == NULL) errval = GetLastError();
|
||||
else errval = 0;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
const char *SysLibError() {
|
||||
if( errval )
|
||||
namespace HostSys
|
||||
{
|
||||
void *LoadLibrary(const char *lib)
|
||||
{
|
||||
static char perr[4096];
|
||||
|
||||
FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM,NULL,GetLastError(),NULL,perr,4095,NULL);
|
||||
|
||||
errval = 0;
|
||||
return _(perr);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void SysCloseLibrary(void *lib)
|
||||
{
|
||||
FreeLibrary((HINSTANCE)lib);
|
||||
}
|
||||
|
||||
void *SysMmap(uptr base, u32 size)
|
||||
{
|
||||
return VirtualAlloc((void*)base, size, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
|
||||
}
|
||||
|
||||
void SysMunmap(uptr base, u32 size)
|
||||
{
|
||||
if( base == NULL ) return;
|
||||
VirtualFree((void*)base, size, MEM_DECOMMIT);
|
||||
VirtualFree((void*)base, 0, MEM_RELEASE);
|
||||
}
|
||||
|
||||
void SysMemProtect( void* baseaddr, size_t size, PageProtectionMode mode, bool allowExecution )
|
||||
{
|
||||
DWORD winmode = 0;
|
||||
|
||||
switch( mode )
|
||||
{
|
||||
case Protect_NoAccess:
|
||||
winmode = ( allowExecution ) ? PAGE_EXECUTE : PAGE_NOACCESS;
|
||||
break;
|
||||
|
||||
case Protect_ReadOnly:
|
||||
winmode = ( allowExecution ) ? PAGE_EXECUTE_READ : PAGE_READONLY;
|
||||
break;
|
||||
|
||||
case Protect_ReadWrite:
|
||||
winmode = ( allowExecution ) ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
|
||||
break;
|
||||
return LoadLibraryA( lib );
|
||||
}
|
||||
|
||||
DWORD OldProtect; // enjoy my uselessness, yo!
|
||||
VirtualProtect( baseaddr, size, winmode, &OldProtect );
|
||||
void *LoadSym(void *lib, const char *sym)
|
||||
{
|
||||
void *tmp = GetProcAddress((HINSTANCE)lib, sym);
|
||||
if (tmp == NULL) errval = GetLastError();
|
||||
else errval = 0;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
const char *LibError()
|
||||
{
|
||||
if( errval )
|
||||
{
|
||||
static char perr[4096];
|
||||
|
||||
FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM,NULL,GetLastError(),NULL,perr,4095,NULL);
|
||||
|
||||
errval = 0;
|
||||
return _(perr);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void CloseLibrary(void *lib)
|
||||
{
|
||||
FreeLibrary((HINSTANCE)lib);
|
||||
}
|
||||
|
||||
void *Mmap(uptr base, u32 size)
|
||||
{
|
||||
return VirtualAlloc((void*)base, size, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
|
||||
}
|
||||
|
||||
void Munmap(uptr base, u32 size)
|
||||
{
|
||||
if( base == NULL ) return;
|
||||
VirtualFree((void*)base, size, MEM_DECOMMIT);
|
||||
VirtualFree((void*)base, 0, MEM_RELEASE);
|
||||
}
|
||||
|
||||
void MemProtect( void* baseaddr, size_t size, PageProtectionMode mode, bool allowExecution )
|
||||
{
|
||||
DWORD winmode = 0;
|
||||
|
||||
switch( mode )
|
||||
{
|
||||
case Protect_NoAccess:
|
||||
winmode = ( allowExecution ) ? PAGE_EXECUTE : PAGE_NOACCESS;
|
||||
break;
|
||||
|
||||
case Protect_ReadOnly:
|
||||
winmode = ( allowExecution ) ? PAGE_EXECUTE_READ : PAGE_READONLY;
|
||||
break;
|
||||
|
||||
case Protect_ReadWrite:
|
||||
winmode = ( allowExecution ) ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
|
||||
break;
|
||||
}
|
||||
|
||||
DWORD OldProtect; // enjoy my uselessness, yo!
|
||||
VirtualProtect( baseaddr, size, winmode, &OldProtect );
|
||||
}
|
||||
}
|
||||
|
||||
namespace HostGui
|
||||
{
|
||||
// Sets the status bar message without mirroring the output to the console.
|
||||
void SetStatusMsg( const string& text )
|
||||
{
|
||||
// don't try this in GCC folks!
|
||||
SendMessage(hStatusWnd, SB_SETTEXT, 0, (LPARAM)text.c_str() );
|
||||
}
|
||||
|
||||
void Notice( const string& text )
|
||||
{
|
||||
// mirror output to the console!
|
||||
Console::Status( text.c_str() );
|
||||
SetStatusMsg( text );
|
||||
}
|
||||
|
||||
void ResetMenuSlots()
|
||||
{
|
||||
for( int i=0; i<5; i++ )
|
||||
{
|
||||
EnableMenuItem( GetSubMenu(gApp.hMenu, 0),
|
||||
ID_FILE_STATES_LOAD_SLOT1+i,
|
||||
States_isSlotUsed(i) ? MF_ENABLED : MF_GRAYED
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Because C++ lacks the finally clause >_<
|
||||
static void _executeCpuFinally()
|
||||
{
|
||||
timeEndPeriod( 1 );
|
||||
ShowWindow( gApp.hWnd, SW_SHOW );
|
||||
SetForegroundWindow( gApp.hWnd );
|
||||
nDisableSC = false;
|
||||
}
|
||||
|
||||
void BeginExecution()
|
||||
{
|
||||
nDisableSC = true;
|
||||
|
||||
// ... and hide the window. Ugly thing.
|
||||
ShowWindow( gApp.hWnd, SW_HIDE );
|
||||
timeBeginPeriod( 1 ); // improves multithreaded responsiveness
|
||||
|
||||
try
|
||||
{
|
||||
SysExecute();
|
||||
}
|
||||
catch( Exception::BaseException& )
|
||||
{
|
||||
_executeCpuFinally();
|
||||
throw;
|
||||
}
|
||||
|
||||
_executeCpuFinally();
|
||||
}
|
||||
|
||||
void __fastcall KeyEvent( keyEvent* ev )
|
||||
{
|
||||
static int shiftkey = 0;
|
||||
|
||||
if (ev == NULL) return;
|
||||
if (ev->evt == KEYRELEASE)
|
||||
{
|
||||
switch (ev->key)
|
||||
{
|
||||
case VK_SHIFT: shiftkey = 0; break;
|
||||
}
|
||||
GSkeyEvent(ev); return;
|
||||
}
|
||||
|
||||
if (ev->evt != KEYPRESS) return;
|
||||
|
||||
switch (ev->key)
|
||||
{
|
||||
case VK_SHIFT: shiftkey = 1; break;
|
||||
|
||||
case VK_F1: case VK_F2: case VK_F3: case VK_F4:
|
||||
case VK_F5: case VK_F6: case VK_F7: case VK_F8:
|
||||
case VK_F9: case VK_F10: case VK_F11: case VK_F12:
|
||||
try
|
||||
{
|
||||
ProcessFKeys(ev->key-VK_F1 + 1, shiftkey);
|
||||
}
|
||||
catch( Exception::CpuStateShutdown& )
|
||||
{
|
||||
// Woops! Something was unrecoverable (like state load). Bummer.
|
||||
// Let's give the user a RunGui!
|
||||
|
||||
g_EmulationInProgress = false;
|
||||
SysEndExecution();
|
||||
}
|
||||
break;
|
||||
|
||||
case VK_TAB:
|
||||
CycleFrameLimit(0);
|
||||
break;
|
||||
|
||||
case VK_ESCAPE:
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
if( g_SaveGSStream >= 3 ) {
|
||||
// gs state
|
||||
g_SaveGSStream = 4;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
if( CHECK_ESCAPE_HACK )
|
||||
{
|
||||
g_EmulationInProgress = false;
|
||||
DestroyWindow( gApp.hWnd );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !UseGui ) {
|
||||
// not using GUI and user just quit, so exit
|
||||
WinClose();
|
||||
}
|
||||
|
||||
nDisableSC = 0;
|
||||
}
|
||||
|
||||
SysEndExecution();
|
||||
break;
|
||||
|
||||
default:
|
||||
GSkeyEvent(ev);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,7 +8,6 @@
|
|||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "afxresmw.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
|
@ -731,6 +730,17 @@ BEGIN
|
|||
EDITTEXT IDC_CP031,191,218,51,12,ES_READONLY
|
||||
END
|
||||
|
||||
IDD_JUMP DIALOGEX 0, 0, 175, 64
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Jump to specific address"
|
||||
FONT 8, "MS Shell Dlg", 0, 0, 0x0
|
||||
BEGIN
|
||||
EDITTEXT IDC_JUMP_PC,73,14,82,13
|
||||
DEFPUSHBUTTON "OK",IDOK,25,43,50,14
|
||||
PUSHBUTTON "Cancel",IDCANCEL,101,42,50,14
|
||||
LTEXT "Enter new PC Address:",IDC_STATIC,3,16,65,8
|
||||
END
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
@ -890,7 +900,6 @@ END
|
|||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
||||
|
|
|
@ -129,17 +129,6 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
|||
// Dialog
|
||||
//
|
||||
|
||||
IDD_JUMP DIALOGEX 0, 0, 175, 64
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Jump to specific address"
|
||||
FONT 8, "MS Shell Dlg", 0, 0, 0x0
|
||||
BEGIN
|
||||
EDITTEXT IDC_JUMP_PC,73,14,82,13
|
||||
DEFPUSHBUTTON "OK",IDOK,25,43,50,14
|
||||
PUSHBUTTON "Cancel",IDCANCEL,101,42,50,14
|
||||
LTEXT "Enter new PC Address:",IDC_STATIC,3,16,65,8
|
||||
END
|
||||
|
||||
IDD_MEMORY DIALOG 0, 0, 317, 270
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Memory"
|
||||
|
@ -235,10 +224,7 @@ BEGIN
|
|||
GROUPBOX "Clamp Mode",IDC_STATIC,281,80,236,127,BS_LEFT
|
||||
GROUPBOX "Other Options",IDC_STATIC,281,210,237,34,BS_LEFT
|
||||
LTEXT "These options specify how PCSX2's recompilers will clamp Infinities and NaN (Not a Number) values in the opcode instructions.",IDC_STATIC,286,94,224,19
|
||||
LTEXT "*None* - No clamping. (Fastest Mode)\n*Normal* - Clamps the result.\n*Extra* - Clamps the operands, the result, and anywhere in between.\n*Extra + Preserve Sign* - Same as ""Extra"", except preserves NaN's sign when clamping the operands.",IDC_STATIC,286,114,224,48
|
||||
LTEXT "*Full* - Attempts to emulate large numbers correctly for the EE's FPU. VU's clamp mode should be set to ""Extra + Preserve Sign"" for this to work best. (but still works for most games even with ""Normal"" VU clamping)",IDC_STATIC,287,163,214,36
|
||||
LTEXT "Flush to Zero - Makes floating point underflows become zero.\nDenormals are Zero - Makes floating point denormals become zero.",IDC_STATIC,287,222,224,18
|
||||
END
|
||||
LTEXT "*None* - No clamping. (Fastest Mode)\n*Normal* - Clamps the result.\n*Extra* - Clamps the operands, the result, and anywhere in between.\n*Extra + Preserve Sign* - Same as ""Extra"", except preserves NaN's sign when clamping the operands.",IDC_STATIC,286,114,224,48 LTEXT "*Full* - Attempts to emulate large numbers correctly for the EE's FPU. VU's clamp mode should be set to ""Extra + Preserve Sign"" for this to work best. (but still works for most games even with ""Normal"" VU clamping)",IDC_STATIC,287,163,214,36 LTEXT "Flush to Zero - Makes floating point underflows become zero.\nDenormals are Zero - Makes floating point denormals become zero.",IDC_STATIC,287,222,224,18END
|
||||
|
||||
IDD_CONF_MEMCARD DIALOGEX 0, 0, 451, 215
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
|
@ -343,11 +329,13 @@ FONT 8, "MS Shell Dlg", 400, 0, 0x0
|
|||
BEGIN
|
||||
DEFPUSHBUTTON "OK",IDOK,205,274,50,14
|
||||
CTEXT "PCSX2, a PS2 Emulator...",IDC_PCSX_ABOUT_AUTHORS,9,10,135,127,0,WS_EX_TRANSPARENT
|
||||
CTEXT "Greets to...",IDC_PCSX_ABOUT_GREETS,94,178,319,77
|
||||
CTEXT "Greets to...",IDC_PCSX_ABOUT_GREETS,94,186,319,77
|
||||
GROUPBOX "",IDC_STATIC,5,3,145,141
|
||||
GROUPBOX "",IDC_STATIC,87,169,333,91
|
||||
CONTROL 132,IDC_PS2SILVER_RECT,"Static",SS_BITMAP | SS_SUNKEN,10,179,71,75
|
||||
GROUPBOX "",IDC_STATIC,87,177,333,91
|
||||
CONTROL 132,IDC_PS2SILVER_RECT,"Static",SS_BITMAP | SS_SUNKEN,10,187,71,75
|
||||
CONTROL 113,IDC_STATIC,"Static",SS_BITMAP,162,7,259,137,WS_EX_CLIENTEDGE
|
||||
CTEXT "Pcsx2 Official Svn Repository @ Googlecode",IDC_LINK_GOOGLECODE,79,164,273,10,SS_NOPREFIX | SS_NOTIFY
|
||||
CTEXT "Pcsx2 Official Website and Forums",IDC_LINK_WEBSITE,79,151,273,10,SS_NOPREFIX | SS_NOTIFY
|
||||
END
|
||||
|
||||
IDD_HACKS DIALOGEX 0, 0, 335, 263
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
#define ABOUT_DIALOG 104
|
||||
#define IDI_ICON 108
|
||||
#define IDD_MEMORY 110
|
||||
#define IDD_JUMP 112
|
||||
#define SPLASH_LOGO 113
|
||||
#define IDD_LOGGING 119
|
||||
#define IDD_CMDLINE 120
|
||||
|
@ -69,8 +68,10 @@
|
|||
#define IDC_LISTCDVD 1054
|
||||
#define IDC_DEBUG_L17 1055
|
||||
#define IDC_LISTBIOS 1055
|
||||
#define IDC_LINK_WEBSITE 1055
|
||||
#define IDC_DEBUG_L18 1056
|
||||
#define IDC_CONFIGGS 1056
|
||||
#define IDC_LINK_GOOGLECODE 1056
|
||||
#define IDC_DEBUG_L19 1057
|
||||
#define IDC_TESTGS 1057
|
||||
#define IDC_DEBUG_L20 1058
|
||||
|
@ -139,7 +140,6 @@
|
|||
#define IDC_DEBUG_R27 1094
|
||||
#define IDC_DEBUG_R28 1095
|
||||
#define IDC_DEBUG_R29 1096
|
||||
#define IDC_JUMP_PC 1097
|
||||
#define IDC_DEBUG_LOGGING 1098
|
||||
#define IDC_CMDLINE 1155
|
||||
#define IDC_PCSX_ABOUT_GREETS 1163
|
||||
|
|
|
@ -389,14 +389,14 @@ void cpudetectInit()
|
|||
// intrinsic equivalents available. So we use our own ix86 emitter to generate
|
||||
// some code and run it that way. :)
|
||||
|
||||
u8* recSSE = (u8*)SysMmap( NULL, 0x1000 );
|
||||
u8* recSSE = (u8*)HostSys::Mmap( NULL, 0x1000 );
|
||||
if( recSSE != NULL )
|
||||
{
|
||||
x86SetPtr(recSSE);
|
||||
SSE3_MOVSLDUP_XMM_to_XMM(XMM0, XMM0);
|
||||
RET();
|
||||
cpudetectSSE3(recSSE);
|
||||
SysMunmap( recSSE, 0x1000 );
|
||||
HostSys::Munmap( recSSE, 0x1000 );
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
|
|
|
@ -77,7 +77,7 @@ microVUt(void) mVUclose() {
|
|||
|
||||
microVU* mVU = mVUx;
|
||||
|
||||
if ( mVU->cache ) { SysMunmap( mVU->cache, mVU->cacheSize ); mVU->cache = NULL; }
|
||||
if ( mVU->cache ) { HostSys::Munmap( mVU->cache, mVU->cacheSize ); mVU->cache = NULL; }
|
||||
|
||||
// Delete Block Managers
|
||||
for (int i; i <= mVU->prog.max; i++) {
|
||||
|
|
Loading…
Reference in New Issue