Navigation Menu

Skip to content

Commit

Permalink
PCSX2:Save/load slot improvements.
Browse files Browse the repository at this point in the history
With these changes, saveslots will be labeled as either empty or
with the date that the file was last updated on. The menu items
for loading them are also disabled if the slot is empty.

It's possible if you are very fast to access the menu before the
slots change. It updates when the crc changes. When you save a saveslot,
the menu item also changes to show the time you told it to save until the
file is actually done saving.
  • Loading branch information
arcum42 authored and lightningterror committed Sep 4, 2018
1 parent 55155ca commit 77271ed
Show file tree
Hide file tree
Showing 11 changed files with 287 additions and 101 deletions.
1 change: 1 addition & 0 deletions pcsx2/CMakeLists.txt
Expand Up @@ -343,6 +343,7 @@ set(pcsx2GuiHeaders
gui/Panels/MemoryCardPanels.h
gui/pxEventThread.h
gui/RecentIsoList.h
gui/Saveslots.h
)

# Warning: the declaration of the .h are mandatory in case of resources files. It will ensure the creation
Expand Down
20 changes: 20 additions & 0 deletions pcsx2/SaveState.cpp
Expand Up @@ -63,6 +63,26 @@ wxString SaveStateBase::GetFilename( int slot )
// pxsFmt( L"%08X.%03d", ElfCRC, slot )).GetFullPath();
}

bool SaveStateBase::isSlotUsed(int slot)
{
if (ElfCRC == 0)
return false;
else
return wxFileExists(SaveStateBase::GetFilename(slot));
}

wxDateTime SaveStateBase::GetSlotTimestamp(int slot)
{
if (isSlotUsed(slot))
{
return wxDateTime(wxFileModificationTime(GetFilename(slot)));
}
else
{
return wxInvalidDateTime;
}
}

SaveStateBase::SaveStateBase( SafeArray<u8>& memblock )
{
Init( &memblock );
Expand Down
2 changes: 2 additions & 0 deletions pcsx2/SaveState.h
Expand Up @@ -113,6 +113,8 @@ class SaveStateBase
virtual ~SaveStateBase() { }

static wxString GetFilename( int slot );
static bool isSlotUsed(int slot);
static wxDateTime GetSlotTimestamp(int slot);

// Gets the version of savestate that this object is acting on.
// The version refers to the low 16 bits only (high 16 bits classifies Pcsx2 build types)
Expand Down
1 change: 1 addition & 0 deletions pcsx2/System/SysCoreThread.cpp
Expand Up @@ -236,6 +236,7 @@ void SysCoreThread::GameStartingInThread()
sApp.PostAppMethod(&Pcsx2App::resetDebugger);

ApplyLoadedPatches(PPT_ONCE_ON_LOAD);
UI_UpdateSysControls();
}

bool SysCoreThread::StateCheckInThread()
Expand Down
13 changes: 1 addition & 12 deletions pcsx2/gui/AppSaveStates.h
Expand Up @@ -17,6 +17,7 @@

#include "App.h"
#include "SaveState.h"
#include "Saveslots.h"

// --------------------------------------------------------------------------------------
// SysExecEvent_SaveSinglePlugin
Expand Down Expand Up @@ -60,15 +61,3 @@ extern void StateCopy_SaveToFile( const wxString& file );
extern void StateCopy_LoadFromFile( const wxString& file );
extern void StateCopy_SaveToSlot( uint num );
extern void StateCopy_LoadFromSlot( uint slot, bool isFromBackup = false );

extern void States_registerLoadBackupMenuItem( wxMenuItem* loadBackupMenuItem );

extern bool States_isSlotUsed(int num);
extern void States_DefrostCurrentSlotBackup();
extern void States_DefrostCurrentSlot();
extern void States_FreezeCurrentSlot();
extern void States_CycleSlotForward();
extern void States_CycleSlotBackward();

extern void States_SetCurrentSlot( int slot );
extern int States_GetCurrentSlot();
16 changes: 12 additions & 4 deletions pcsx2/gui/MainFrame.cpp
Expand Up @@ -28,6 +28,7 @@
#include "AppAccelerators.h"

#include "svnrev.h"
#include "Saveslots.h"

// ------------------------------------------------------------------------
wxMenu* MainEmuFrame::MakeStatesSubMenu( int baseid, int loadBackupId ) const
Expand All @@ -36,15 +37,22 @@ wxMenu* MainEmuFrame::MakeStatesSubMenu( int baseid, int loadBackupId ) const

for (int i = 0; i < 10; i++)
{
mnuSubstates->Append( baseid+i+1, wxsFormat(_("Slot %d"), i) );
// Will be changed once an iso is loaded.
mnuSubstates->Append(baseid + i + 1, wxsFormat(_("Slot %d"), i));

if (baseid == MenuId_State_Load01)
{
saveslot_cache[i].slot_num = i;
}
}
if( loadBackupId>=0 )

if (loadBackupId >= 0)
{
mnuSubstates->AppendSeparator();

wxMenuItem* m = mnuSubstates->Append( loadBackupId, _("Backup") );
wxMenuItem* m = mnuSubstates->Append(loadBackupId, _("Backup"));
m->Enable( false );
States_registerLoadBackupMenuItem( m );
//States_registerLoadBackupMenuItem(m);
}

//mnuSubstates->Append( baseid - 1, _("Other...") );
Expand Down
1 change: 1 addition & 0 deletions pcsx2/gui/MainFrame.h
Expand Up @@ -137,6 +137,7 @@ class MainEmuFrame : public wxFrame,
void UpdateIsoSrcSelection();
void RemoveCdvdMenu();
void EnableMenuItem( int id, bool enable );
void SetMenuItemLabel(int id, wxString str);
void EnableCdvdPluginSubmenu(bool isEnable = true);

bool Destroy();
Expand Down
109 changes: 53 additions & 56 deletions pcsx2/gui/Saveslots.cpp
Expand Up @@ -17,27 +17,21 @@
#include "App.h"
#include "AppSaveStates.h"
#include "ConsoleLogger.h"
#include "MainFrame.h"

#include "Common.h"

#include "GS.h"
#include "Elfheader.h"
#include "Saveslots.h"

// --------------------------------------------------------------------------------------
// Saveslot Section
// --------------------------------------------------------------------------------------

static int StatesC = 0;
static const int StateSlotsCount = 10;
static wxMenuItem* g_loadBackupMenuItem =NULL;

bool States_isSlotUsed(int num)
{
if (ElfCRC == 0)
return false;
else
return wxFileExists( SaveStateBase::GetFilename( num ) );
}
Saveslot saveslot_cache[10];

// FIXME : Use of the IsSavingOrLoading flag is mostly a hack until we implement a
// complete thread to manage queuing savestate tasks, and zipping states to disk. --air
Expand All @@ -53,83 +47,99 @@ class SysExecEvent_ClearSavingLoadingFlag : public SysExecEvent
{
}

SysExecEvent_ClearSavingLoadingFlag* Clone() const { return new SysExecEvent_ClearSavingLoadingFlag(); }
SysExecEvent_ClearSavingLoadingFlag *Clone() const { return new SysExecEvent_ClearSavingLoadingFlag(); }

protected:
void InvokeEvent()
{
IsSavingOrLoading = false;
UI_UpdateSysControls();
}
};

void Sstates_updateLoadBackupMenuItem( bool isBeforeSave = false);
void Saveslots_UpdateFromDisk()
{
for (int i = 0; i < StateSlotsCount; i++) {
saveslot_cache[i].UpdateCache();
}
}

void Sstates_updateLoadBackupMenuItem(bool isBeforeSave = false);

void States_FreezeCurrentSlot()
{
// FIXME : Use of the IsSavingOrLoading flag is mostly a hack until we implement a
// complete thread to manage queuing savestate tasks, and zipping states to disk. --air
if( !SysHasValidState() )
{
Console.WriteLn( "Save state: Aborting (VM is not active)." );
if (!SysHasValidState()) {
Console.WriteLn("Save state: Aborting (VM is not active).");
return;
}

if( wxGetApp().HasPendingSaves() || IsSavingOrLoading.exchange(true) )
{
Console.WriteLn( "Load or save action is already pending." );
if (wxGetApp().HasPendingSaves() || IsSavingOrLoading.exchange(true)) {
Console.WriteLn("Load or save action is already pending.");
return;
}
Sstates_updateLoadBackupMenuItem( true );
Sstates_updateLoadBackupMenuItem(true);

GSchangeSaveState(StatesC, SaveStateBase::GetFilename(StatesC).ToUTF8());
StateCopy_SaveToSlot(StatesC);

// Hack: Update the saveslot saying it's filled *right now* because it's still writing the file and we don't have a timestamp.
saveslot_cache[StatesC].empty = false;
saveslot_cache[StatesC].updated = wxDateTime::Now();
saveslot_cache[StatesC].crc = ElfCRC;

GSchangeSaveState( StatesC, SaveStateBase::GetFilename( StatesC ).ToUTF8() );
StateCopy_SaveToSlot( StatesC );

GetSysExecutorThread().PostIdleEvent( SysExecEvent_ClearSavingLoadingFlag() );
GetSysExecutorThread().PostIdleEvent(SysExecEvent_ClearSavingLoadingFlag());
}

void _States_DefrostCurrentSlot( bool isFromBackup )
void _States_DefrostCurrentSlot(bool isFromBackup)
{
if( !SysHasValidState() )
{
Console.WriteLn( "Load state: Aborting (VM is not active)." );
if (!SysHasValidState()) {
Console.WriteLn("Load state: Aborting (VM is not active).");
return;
}

if( IsSavingOrLoading.exchange(true) )
{
Console.WriteLn( "Load or save action is already pending." );
if (IsSavingOrLoading.exchange(true)) {
Console.WriteLn("Load or save action is already pending.");
return;
}

GSchangeSaveState( StatesC, SaveStateBase::GetFilename( StatesC ).ToUTF8() );
StateCopy_LoadFromSlot( StatesC, isFromBackup );
GSchangeSaveState(StatesC, SaveStateBase::GetFilename(StatesC).ToUTF8());
StateCopy_LoadFromSlot(StatesC, isFromBackup);

GetSysExecutorThread().PostIdleEvent( SysExecEvent_ClearSavingLoadingFlag() );
GetSysExecutorThread().PostIdleEvent(SysExecEvent_ClearSavingLoadingFlag());

Sstates_updateLoadBackupMenuItem();
}

void States_DefrostCurrentSlot()
{
_States_DefrostCurrentSlot( false );
_States_DefrostCurrentSlot(false);
}

void States_DefrostCurrentSlotBackup()
{
_States_DefrostCurrentSlot( true );
_States_DefrostCurrentSlot(true);
}


void States_registerLoadBackupMenuItem( wxMenuItem* loadBackupMenuItem )
// It doesn't seem like this is working at the moment, in that the menu item always seems disabled in tests, but it also doesn't seem like it was working previously...
void Sstates_updateLoadBackupMenuItem(bool isBeforeSave)
{
g_loadBackupMenuItem = loadBackupMenuItem;
wxString file = SaveStateBase::GetFilename(StatesC);

if (!(isBeforeSave && g_Conf->EmuOptions.BackupSavestate)) {
file = file + L".backup";
}

sMainFrame.EnableMenuItem(MenuId_State_LoadBackup, wxFileExists(file));
sMainFrame.SetMenuItemLabel(MenuId_State_LoadBackup, wxsFormat(L"%s %d", _("Backup"), StatesC));
}

static void OnSlotChanged()
{
OSDlog( Color_StrongGreen, true, " > Selected savestate slot %d", StatesC );
OSDlog(Color_StrongGreen, true, " > Selected savestate slot %d", StatesC);

if( GSchangeSaveState != NULL )
if (GSchangeSaveState != NULL)
GSchangeSaveState(StatesC, SaveStateBase::GetFilename(StatesC).utf8_str());

Sstates_updateLoadBackupMenuItem();
Expand All @@ -140,33 +150,20 @@ int States_GetCurrentSlot()
return StatesC;
}

void Sstates_updateLoadBackupMenuItem( bool isBeforeSave )
void States_SetCurrentSlot(int slot)
{
if( !g_loadBackupMenuItem ) return;

int slot = States_GetCurrentSlot();
wxString file = SaveStateBase::GetFilename( slot );
g_loadBackupMenuItem->Enable( wxFileExists( isBeforeSave && g_Conf->EmuOptions.BackupSavestate ? file : file + L".backup" ) );
wxString label;
label.Printf(L"%s %d", _("Backup"), slot );
g_loadBackupMenuItem->SetItemLabel( label );
}

void States_SetCurrentSlot( int slot )
{
StatesC = std::min( std::max( slot, 0 ), StateSlotsCount );
StatesC = std::min(std::max(slot, 0), StateSlotsCount);
OnSlotChanged();
}

void States_CycleSlotForward()
{
StatesC = (StatesC+1) % StateSlotsCount;
StatesC = (StatesC + 1) % StateSlotsCount;
OnSlotChanged();
}

void States_CycleSlotBackward()
{
StatesC = (StatesC+StateSlotsCount-1) % StateSlotsCount;
StatesC = (StatesC + StateSlotsCount - 1) % StateSlotsCount;
OnSlotChanged();
}

0 comments on commit 77271ed

Please sign in to comment.