Merge branch 'SaveStates'

This commit is contained in:
skidau 2011-10-22 16:18:02 +11:00
commit 3cdcdba25f
6 changed files with 112 additions and 16 deletions

View File

@ -373,6 +373,8 @@ void DoState(PointerWrap &p)
p.DoArray(m_pPhysicalRAM, RAM_SIZE);
// p.DoArray(m_pVirtualEFB, EFB_SIZE);
p.DoArray(m_pVirtualL1Cache, L1_CACHE_SIZE);
if (bFakeVMEM)
p.DoArray(m_pVirtualFakeVMEM, FAKEVMEM_SIZE);
if (wii)
p.DoArray(m_pEXRAM, EXRAM_SIZE);
}

View File

@ -28,6 +28,7 @@
#include "StringUtil.h"
#include "VideoBackendBase.h"
#include "State.h"
namespace VideoInterface
{
@ -698,6 +699,9 @@ void UpdateInterrupts()
{
ProcessorInterface::SetInterrupt(ProcessorInterface::INT_CAUSE_VI, false);
}
if (m_InterruptRegister[1].IR_INT && m_InterruptRegister[1].IR_MASK)
State::ProcessRequestedStates(1);
}
u32 GetXFBAddressTop()

View File

@ -82,6 +82,9 @@ void DoState(PointerWrap &p)
SystemTimers::DecrementerSet();
SystemTimers::TimeBaseSet();
if (jit && p.GetMode() == PointerWrap::MODE_READ)
jit->GetBlockCache()->ClearSafe();
}
void ResetRegisters()

View File

@ -31,6 +31,9 @@
#include "VideoBackendBase.h"
#include <lzo/lzo1x.h>
#include "HW/Memmap.h"
#include "HW/VideoInterface.h"
#include "HW/SystemTimers.h"
namespace State
{
@ -64,6 +67,12 @@ static std::vector<u8> g_current_buffer;
static std::thread g_save_thread;
static const u8 NUM_HOOKS = 2;
static u8 waiting;
static u8 waitingslot;
static u64 lastCheckedStates[NUM_HOOKS];
static u8 hook;
// Don't forget to increase this after doing changes on the savestate system
static const int STATE_VERSION = 5;
@ -73,6 +82,13 @@ struct StateHeader
size_t size;
};
enum
{
STATE_NONE = 0,
STATE_SAVE = 1,
STATE_LOAD = 2,
};
static bool g_use_compression = true;
void EnableCompression(bool compression)
@ -105,6 +121,12 @@ void DoState(PointerWrap &p)
g_video_backend->RunLoop(true);
}
void ResetCounters()
{
for (int i = 0; i < NUM_HOOKS; ++i)
lastCheckedStates[i] = CoreTiming::GetTicks();
}
void LoadBufferStateCallback(u64 userdata, int cyclesLate)
{
u8* ptr = &g_current_buffer[0];
@ -217,10 +239,6 @@ void SaveFileStateCallback(u64 userdata, int cyclesLate)
// Pause the core while we save the state
CCPU::EnableStepping(true);
// Wait for the other threaded sub-systems to stop too
// TODO: this is ugly
SLEEP(100);
Flush();
// Measure the size of the buffer.
@ -318,10 +336,6 @@ void LoadFileStateCallback(u64 userdata, int cyclesLate)
// Stop the core while we load the state
CCPU::EnableStepping(true);
// Wait for the other threaded sub-systems to stop too
// TODO: uglyyy
SLEEP(100);
Flush();
// Save temp buffer for undo load state
@ -350,6 +364,8 @@ void LoadFileStateCallback(u64 userdata, int cyclesLate)
Movie::EndPlayInput(false);
}
ResetCounters();
g_op_in_progress = false;
// resume dat core
@ -386,6 +402,11 @@ void Init()
ev_BufferSave = CoreTiming::RegisterEvent("SaveBufferState", &SaveBufferStateCallback);
ev_BufferVerify = CoreTiming::RegisterEvent("VerifyBufferState", &VerifyBufferStateCallback);
waiting = STATE_NONE;
waitingslot = 0;
hook = 0;
ResetCounters();
if (lzo_init() != LZO_E_OK)
PanicAlertT("Internal LZO Error - lzo_init() failed");
}
@ -413,40 +434,100 @@ static std::string MakeStateFilename(int number)
SConfig::GetInstance().m_LocalCoreStartupParameter.GetUniqueID().c_str(), number);
}
void ScheduleFileEvent(const std::string &filename, int ev)
void ScheduleFileEvent(const std::string &filename, int ev, bool immediate)
{
if (g_op_in_progress)
return;
g_op_in_progress = true;
g_current_filename = filename;
CoreTiming::ScheduleEvent_Threadsafe_Immediate(ev);
if (immediate)
CoreTiming::ScheduleEvent_Threadsafe_Immediate(ev);
else
CoreTiming::ScheduleEvent_Threadsafe(0, ev);
}
void SaveAs(const std::string &filename, bool immediate)
{
g_last_filename = filename;
ScheduleFileEvent(filename, ev_FileSave, immediate);
}
void SaveAs(const std::string &filename)
{
g_last_filename = filename;
ScheduleFileEvent(filename, ev_FileSave);
SaveAs(filename, true);
}
void LoadAs(const std::string &filename, bool immediate)
{
ScheduleFileEvent(filename, ev_FileLoad, immediate);
}
void LoadAs(const std::string &filename)
{
ScheduleFileEvent(filename, ev_FileLoad);
LoadAs(filename, true);
}
void VerifyAt(const std::string &filename)
{
ScheduleFileEvent(filename, ev_FileVerify);
ScheduleFileEvent(filename, ev_FileVerify, true);
}
bool ProcessRequestedStates(int priority)
{
bool save = true;
if (hook == priority)
{
if (waiting == STATE_SAVE)
{
SaveAs(MakeStateFilename(waitingslot), false);
waitingslot = 0;
waiting = STATE_NONE;
}
else if (waiting == STATE_LOAD)
{
LoadAs(MakeStateFilename(waitingslot), false);
waitingslot = 0;
waiting = STATE_NONE;
save = false;
}
}
// Change hooks if the new hook gets called frequently (at least once a frame) and if the old
// hook has not been called for the last 5 seconds
if ((CoreTiming::GetTicks() - lastCheckedStates[priority]) < (VideoInterface::GetTicksPerFrame()))
{
lastCheckedStates[priority] = CoreTiming::GetTicks();
if (hook < NUM_HOOKS && priority >= (hook + 1) &&
(lastCheckedStates[priority] - lastCheckedStates[hook]) > (SystemTimers::GetTicksPerSecond() * 5))
{
hook++;
}
}
else
lastCheckedStates[priority] = CoreTiming::GetTicks();
return save;
}
void Save(int slot)
{
SaveAs(MakeStateFilename(slot));
if (waiting == STATE_NONE)
{
waiting = STATE_SAVE;
waitingslot = slot;
}
}
void Load(int slot)
{
LoadAs(MakeStateFilename(slot));
if (waiting == STATE_NONE)
{
waiting = STATE_LOAD;
waitingslot = slot;
}
}
void Verify(int slot)

View File

@ -26,6 +26,7 @@ namespace State
{
void Init();
void Shutdown();
void EnableCompression(bool compression);
@ -39,6 +40,8 @@ void Save(int slot);
void Load(int slot);
void Verify(int slot);
bool ProcessRequestedStates(int priority);
void SaveAs(const std::string &filename);
void LoadAs(const std::string &filename);
void VerifyAt(const std::string &filename);

View File

@ -31,6 +31,7 @@
#include "CommandProcessor.h"
#include "HW/ProcessorInterface.h"
#include "DLCache.h"
#include "State.h"
namespace PixelEngine
{
@ -329,6 +330,8 @@ void UpdateFinishInterrupt(bool active)
{
ProcessorInterface::SetInterrupt(INT_CAUSE_PE_FINISH, active);
interruptSetFinish = active;
if (active)
State::ProcessRequestedStates(0);
}
}