mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-10 16:19:28 +01:00
1. TAS Groundwork: Saving the state (compression and memory dump to file) is now done on a separate thread (thread-safe). Now state saving is silent and quick.
2. When stopping, GUI doesn't let the user choose another game and effectively crash Dolphin 3. Omitted an unneeded loop in AudioCommon git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@3552 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
8a6fcdc2bc
commit
46b0fd3c96
@ -71,13 +71,6 @@ namespace AudioCommon
|
|||||||
soundStream = NULL;
|
soundStream = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that soundstream already is stopped.
|
|
||||||
while (soundStream)
|
|
||||||
{
|
|
||||||
ERROR_LOG(DSPHLE, "Waiting for sound stream");
|
|
||||||
Common::SleepCurrentThread(2000);
|
|
||||||
}
|
|
||||||
|
|
||||||
INFO_LOG(DSPHLE, "Done shutting down sound stream");
|
INFO_LOG(DSPHLE, "Done shutting down sound stream");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,7 +184,10 @@ void ReconnectWiimote()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
bool isRunning()
|
||||||
|
{
|
||||||
|
return (GetState() != CORE_UNINITIALIZED) || g_bHwInit;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// This is called from the GUI thread. See the booting call schedule in BootManager.cpp
|
// This is called from the GUI thread. See the booting call schedule in BootManager.cpp
|
||||||
@ -563,25 +566,23 @@ void EmuThreadEnd()
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// The hardware is uninitialized
|
|
||||||
g_bHwInit = false;
|
|
||||||
|
|
||||||
HW::Shutdown();
|
HW::Shutdown();
|
||||||
Plugins.ShutdownPlugins();
|
Plugins.ShutdownPlugins();
|
||||||
|
|
||||||
|
// The hardware is uninitialized
|
||||||
|
g_bHwInit = false;
|
||||||
|
|
||||||
INFO_LOG(MASTER_LOG, "EmuThread exited");
|
INFO_LOG(MASTER_LOG, "EmuThread exited");
|
||||||
// The CPU should return when a game is stopped and cleanup should be done here,
|
|
||||||
// so we can restart the plugins (or load new ones) for the next game.
|
|
||||||
if (_CoreParameter.hMainWindow == g_pWindowHandle)
|
|
||||||
Host_UpdateMainFrame();
|
Host_UpdateMainFrame();
|
||||||
|
|
||||||
#ifdef SETUP_TIMER_WAITING
|
#ifdef SETUP_TIMER_WAITING
|
||||||
EmuThreadReachedEnd = true;
|
EmuThreadReachedEnd = true;
|
||||||
Host_UpdateGUI();
|
Host_UpdateGUI();
|
||||||
INFO_LOG(CONSOLE, "Stop [Video Thread]: Done\n");
|
INFO_LOG(CONSOLE, "Stop [Video Thread]: Done\n");
|
||||||
delete g_EmuThread; // Wait for emuthread to close.
|
delete g_EmuThread; // Wait for emuthread to close.
|
||||||
g_EmuThread = 0;
|
g_EmuThread = 0;
|
||||||
#endif
|
#else
|
||||||
#ifndef SETUP_TIMER_WAITING
|
|
||||||
return 0;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,8 @@ namespace Core
|
|||||||
bool Init();
|
bool Init();
|
||||||
void Stop();
|
void Stop();
|
||||||
|
|
||||||
|
bool isRunning();
|
||||||
|
|
||||||
void SetState(EState _State);
|
void SetState(EState _State);
|
||||||
EState GetState();
|
EState GetState();
|
||||||
|
|
||||||
|
@ -78,26 +78,21 @@ void DoState(PointerWrap &p)
|
|||||||
CoreTiming::DoState(p);
|
CoreTiming::DoState(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SaveStateCallback(u64 userdata, int cyclesLate)
|
THREAD_RETURN CompressAndDumpState(void *pArgs)
|
||||||
{
|
{
|
||||||
|
saveStruct *saveArg = (saveStruct *)pArgs;
|
||||||
|
u8 *buffer = saveArg->buffer;
|
||||||
|
size_t sz = saveArg->size;
|
||||||
lzo_uint out_len = 0;
|
lzo_uint out_len = 0;
|
||||||
|
|
||||||
|
delete saveArg;
|
||||||
|
|
||||||
FILE *f = fopen(cur_filename.c_str(), "wb");
|
FILE *f = fopen(cur_filename.c_str(), "wb");
|
||||||
if(f == NULL) {
|
if(f == NULL) {
|
||||||
Core::DisplayMessage("Could not save state", 2000);
|
Core::DisplayMessage("Could not save state", 2000);
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
jit.ClearCache();
|
|
||||||
u8 *ptr = 0;
|
|
||||||
PointerWrap p(&ptr, PointerWrap::MODE_MEASURE);
|
|
||||||
DoState(p);
|
|
||||||
size_t sz = (size_t)ptr;
|
|
||||||
u8 *buffer = new u8[sz];
|
|
||||||
ptr = buffer;
|
|
||||||
p.SetMode(PointerWrap::MODE_WRITE);
|
|
||||||
DoState(p);
|
|
||||||
|
|
||||||
if (bCompressed) {
|
if (bCompressed) {
|
||||||
fwrite(&sz, sizeof(int), 1, f);
|
fwrite(&sz, sizeof(int), 1, f);
|
||||||
} else {
|
} else {
|
||||||
@ -140,6 +135,38 @@ void SaveStateCallback(u64 userdata, int cyclesLate)
|
|||||||
|
|
||||||
Core::DisplayMessage(StringFromFormat("Saved State to %s",
|
Core::DisplayMessage(StringFromFormat("Saved State to %s",
|
||||||
cur_filename.c_str()).c_str(), 2000);
|
cur_filename.c_str()).c_str(), 2000);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Common::Thread *saveThread = NULL;
|
||||||
|
|
||||||
|
void SaveStateCallback(u64 userdata, int cyclesLate)
|
||||||
|
{
|
||||||
|
// If already saving state, wait for it to finish
|
||||||
|
if(saveThread)
|
||||||
|
{
|
||||||
|
delete saveThread;
|
||||||
|
saveThread = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
jit.ClearCache();
|
||||||
|
u8 *ptr = 0;
|
||||||
|
PointerWrap p(&ptr, PointerWrap::MODE_MEASURE);
|
||||||
|
DoState(p);
|
||||||
|
size_t sz = (size_t)ptr;
|
||||||
|
u8 *buffer = new u8[sz];
|
||||||
|
ptr = buffer;
|
||||||
|
p.SetMode(PointerWrap::MODE_WRITE);
|
||||||
|
DoState(p);
|
||||||
|
|
||||||
|
saveStruct *saveData = new saveStruct;
|
||||||
|
saveData->buffer = buffer;
|
||||||
|
saveData->size = sz;
|
||||||
|
|
||||||
|
Core::DisplayMessage("Saving State...", 1000);
|
||||||
|
|
||||||
|
saveThread = new Common::Thread(CompressAndDumpState, saveData);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoadStateCallback(u64 userdata, int cyclesLate)
|
void LoadStateCallback(u64 userdata, int cyclesLate)
|
||||||
@ -214,7 +241,11 @@ void State_Init()
|
|||||||
|
|
||||||
void State_Shutdown()
|
void State_Shutdown()
|
||||||
{
|
{
|
||||||
// nothing to do, here for consistency.
|
if(saveThread)
|
||||||
|
{
|
||||||
|
delete saveThread;
|
||||||
|
saveThread = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string MakeStateFilename(int state_number)
|
std::string MakeStateFilename(int state_number)
|
||||||
|
@ -28,4 +28,10 @@ void State_Shutdown();
|
|||||||
void State_Save(int slot);
|
void State_Save(int slot);
|
||||||
void State_Load(int slot);
|
void State_Load(int slot);
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
u8 *buffer;
|
||||||
|
size_t size;
|
||||||
|
} saveStruct;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -584,18 +584,12 @@ void CFrame::DoStop()
|
|||||||
|
|
||||||
Core::Stop();
|
Core::Stop();
|
||||||
|
|
||||||
/*
|
#ifdef SETUP_TIMER_WAITING
|
||||||
This is needed together with the option to not "delete g_EmuThread" in Core.cpp, because then
|
// Idle-wait for core to completely shut down (without this wait the
|
||||||
we have to wait a moment before GetState() == CORE_UNINITIALIZED so that UpdateGUI() works.
|
// GameCtrlPanel is restored to a state where we can open another game
|
||||||
It's also needed when a WaitForSingleObject() has timed out so that the ShutDown() process
|
// and effectively crash Dolphin)
|
||||||
has continued without all threads having come to a rest. It's not compatible with the
|
while(Core::isRunning())
|
||||||
SETUP_TIMER_WAITING option (because the Stop returns before it's finished).
|
SLEEP(10);
|
||||||
|
|
||||||
Without this we just see the gray CPanel background because the ISO list will not be displayed.
|
|
||||||
*/
|
|
||||||
#ifndef SETUP_TIMER_WAITING
|
|
||||||
if (bRenderToMain)
|
|
||||||
while(Core::GetState() != Core::CORE_UNINITIALIZED) SLEEP(10);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
UpdateGUI();
|
UpdateGUI();
|
||||||
@ -828,7 +822,7 @@ void CFrame::UpdateGUI()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Save status
|
// Save status
|
||||||
bool initialized = Core::GetState() != Core::CORE_UNINITIALIZED;
|
bool initialized = Core::isRunning();
|
||||||
bool running = Core::GetState() == Core::CORE_RUN;
|
bool running = Core::GetState() == Core::CORE_RUN;
|
||||||
bool paused = Core::GetState() == Core::CORE_PAUSE;
|
bool paused = Core::GetState() == Core::CORE_PAUSE;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user