summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorskidau <skidau@gmail.com>2011-10-22 16:18:02 +1100
committerskidau <skidau@gmail.com>2011-10-22 16:18:02 +1100
commit3cdcdba25f2d6f0eb5631b60d98a5a7df4405d2a (patch)
treef4aae72920ae1344f4f81e05b379c2950d69d012 /Source/Core
parent8d9061ac39ee8841557ce461c48fdc2791ec8a20 (diff)
parent599c3ccd7bc0c7b75c9ef6c4a3fd4f0fb2ae266c (diff)
Merge branch 'SaveStates'
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Core/Src/HW/Memmap.cpp2
-rw-r--r--Source/Core/Core/Src/HW/VideoInterface.cpp4
-rw-r--r--Source/Core/Core/Src/PowerPC/PowerPC.cpp3
-rw-r--r--Source/Core/Core/Src/State.cpp113
-rw-r--r--Source/Core/Core/Src/State.h3
-rw-r--r--Source/Core/VideoCommon/Src/PixelEngine.cpp3
6 files changed, 112 insertions, 16 deletions
diff --git a/Source/Core/Core/Src/HW/Memmap.cpp b/Source/Core/Core/Src/HW/Memmap.cpp
index 1c185ccaf3..c1c01d26a9 100644
--- a/Source/Core/Core/Src/HW/Memmap.cpp
+++ b/Source/Core/Core/Src/HW/Memmap.cpp
@@ -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);
}
diff --git a/Source/Core/Core/Src/HW/VideoInterface.cpp b/Source/Core/Core/Src/HW/VideoInterface.cpp
index d8d6d98570..93c48d92f9 100644
--- a/Source/Core/Core/Src/HW/VideoInterface.cpp
+++ b/Source/Core/Core/Src/HW/VideoInterface.cpp
@@ -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()
diff --git a/Source/Core/Core/Src/PowerPC/PowerPC.cpp b/Source/Core/Core/Src/PowerPC/PowerPC.cpp
index aef4c78c7b..4e58873d7e 100644
--- a/Source/Core/Core/Src/PowerPC/PowerPC.cpp
+++ b/Source/Core/Core/Src/PowerPC/PowerPC.cpp
@@ -82,6 +82,9 @@ void DoState(PointerWrap &p)
SystemTimers::DecrementerSet();
SystemTimers::TimeBaseSet();
+
+ if (jit && p.GetMode() == PointerWrap::MODE_READ)
+ jit->GetBlockCache()->ClearSafe();
}
void ResetRegisters()
diff --git a/Source/Core/Core/Src/State.cpp b/Source/Core/Core/Src/State.cpp
index d942255d2a..650f5a788f 100644
--- a/Source/Core/Core/Src/State.cpp
+++ b/Source/Core/Core/Src/State.cpp
@@ -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)
+void SaveAs(const std::string &filename, bool immediate)
{
g_last_filename = filename;
- ScheduleFileEvent(filename, ev_FileSave);
+ ScheduleFileEvent(filename, ev_FileSave, immediate);
+}
+
+void SaveAs(const std::string &filename)
+{
+ 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)
diff --git a/Source/Core/Core/Src/State.h b/Source/Core/Core/Src/State.h
index 791468f154..111c4e24f0 100644
--- a/Source/Core/Core/Src/State.h
+++ b/Source/Core/Core/Src/State.h
@@ -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);
diff --git a/Source/Core/VideoCommon/Src/PixelEngine.cpp b/Source/Core/VideoCommon/Src/PixelEngine.cpp
index 2a328de95d..3b6d1b7487 100644
--- a/Source/Core/VideoCommon/Src/PixelEngine.cpp
+++ b/Source/Core/VideoCommon/Src/PixelEngine.cpp
@@ -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);
}
}