Added rewind feature to GTK version. Patch by Juha Laukkanen.
There are two config params: rewind_count_max => how many blocks are reserved maximum, higher value leads to greater memory usage naturally but longer rewind log rewind_interval => default interval is 165ms and higher value leads to more inaccurate rewind but longer rewind log Also fixes memtell() telling incorrect size because data is not flushed. wxWidgets front end having too small buffer for rewinds resulting overflows.
This commit is contained in:
parent
6605d4eb6d
commit
4116a72ae7
|
@ -34,7 +34,7 @@ struct EmulatedSystem {
|
||||||
// load memory state (rewind)
|
// load memory state (rewind)
|
||||||
bool (*emuReadMemState)(char *, int);
|
bool (*emuReadMemState)(char *, int);
|
||||||
// write memory state (rewind)
|
// write memory state (rewind)
|
||||||
bool (*emuWriteMemState)(char *, int);
|
bool (*emuWriteMemState)(char *, int, long&);
|
||||||
// write PNG file
|
// write PNG file
|
||||||
bool (*emuWritePNG)(const char *);
|
bool (*emuWritePNG)(const char *);
|
||||||
// write BMP file
|
// write BMP file
|
||||||
|
|
|
@ -691,6 +691,7 @@ int ZEXPORT memgzclose (file)
|
||||||
long ZEXPORT memtell(file)
|
long ZEXPORT memtell(file)
|
||||||
gzFile file;
|
gzFile file;
|
||||||
{
|
{
|
||||||
|
do_flush (file, Z_FULL_FLUSH); // makes memtell to tell truth
|
||||||
mem_stream *s = (mem_stream*)file;
|
mem_stream *s = (mem_stream*)file;
|
||||||
|
|
||||||
if (s == NULL) return Z_STREAM_ERROR;
|
if (s == NULL) return Z_STREAM_ERROR;
|
||||||
|
|
|
@ -3929,7 +3929,7 @@ static bool gbWriteSaveState(gzFile gzFile)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool gbWriteMemSaveState(char *memory, int available)
|
bool gbWriteMemSaveState(char *memory, int available, long& reserved)
|
||||||
{
|
{
|
||||||
gzFile gzFile = utilMemGzOpen(memory, available, "w");
|
gzFile gzFile = utilMemGzOpen(memory, available, "w");
|
||||||
|
|
||||||
|
@ -3939,9 +3939,9 @@ bool gbWriteMemSaveState(char *memory, int available)
|
||||||
|
|
||||||
bool res = gbWriteSaveState(gzFile);
|
bool res = gbWriteSaveState(gzFile);
|
||||||
|
|
||||||
long pos = utilGzMemTell(gzFile)+8;
|
reserved = utilGzMemTell(gzFile)+8;
|
||||||
|
|
||||||
if(pos >= (available))
|
if(reserved >= (available))
|
||||||
res = false;
|
res = false;
|
||||||
|
|
||||||
utilGzClose(gzFile);
|
utilGzClose(gzFile);
|
||||||
|
|
|
@ -35,7 +35,7 @@ bool gbWriteBatteryFile(const char *);
|
||||||
bool gbWriteBatteryFile(const char *, bool);
|
bool gbWriteBatteryFile(const char *, bool);
|
||||||
bool gbReadBatteryFile(const char *);
|
bool gbReadBatteryFile(const char *);
|
||||||
bool gbWriteSaveState(const char *);
|
bool gbWriteSaveState(const char *);
|
||||||
bool gbWriteMemSaveState(char *, int);
|
bool gbWriteMemSaveState(char *, int, long&);
|
||||||
bool gbReadSaveState(const char *);
|
bool gbReadSaveState(const char *);
|
||||||
bool gbReadMemSaveState(char *, int);
|
bool gbReadMemSaveState(char *, int);
|
||||||
void gbSgbRenderBorder();
|
void gbSgbRenderBorder();
|
||||||
|
|
|
@ -621,7 +621,7 @@ unsigned int CPUWriteState(u8* data, unsigned size)
|
||||||
return (ptrdiff_t)data - (ptrdiff_t)orig;
|
return (ptrdiff_t)data - (ptrdiff_t)orig;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CPUWriteMemState(char *memory, int available)
|
bool CPUWriteMemState(char *memory, int available, long& reserved)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -684,7 +684,7 @@ bool CPUWriteState(const char *file)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool CPUWriteMemState(char *memory, int available)
|
bool CPUWriteMemState(char *memory, int available, long& reserved)
|
||||||
{
|
{
|
||||||
gzFile gzFile = utilMemGzOpen(memory, available, "w");
|
gzFile gzFile = utilMemGzOpen(memory, available, "w");
|
||||||
|
|
||||||
|
@ -694,9 +694,9 @@ bool CPUWriteMemState(char *memory, int available)
|
||||||
|
|
||||||
bool res = CPUWriteState(gzFile);
|
bool res = CPUWriteState(gzFile);
|
||||||
|
|
||||||
long pos = utilGzMemTell(gzFile)+8;
|
reserved = utilGzMemTell(gzFile)+8;
|
||||||
|
|
||||||
if(pos >= (available))
|
if(reserved >= (available))
|
||||||
res = false;
|
res = false;
|
||||||
|
|
||||||
utilGzClose(gzFile);
|
utilGzClose(gzFile);
|
||||||
|
|
|
@ -104,7 +104,8 @@ Window::Window(GtkWindow * _pstWindow, const Glib::RefPtr<Gtk::Builder> & _poXml
|
||||||
m_iJoypadMax (PAD_4),
|
m_iJoypadMax (PAD_4),
|
||||||
m_iVideoOutputMin (OutputCairo),
|
m_iVideoOutputMin (OutputCairo),
|
||||||
m_iVideoOutputMax (OutputOpenGL),
|
m_iVideoOutputMax (OutputOpenGL),
|
||||||
m_bFullscreen (false)
|
m_bFullscreen (false),
|
||||||
|
m_psavestate (NULL)
|
||||||
{
|
{
|
||||||
m_poXml = _poXml;
|
m_poXml = _poXml;
|
||||||
m_poFileOpenDialog = NULL;
|
m_poFileOpenDialog = NULL;
|
||||||
|
@ -527,6 +528,11 @@ void Window::vInitConfig()
|
||||||
m_poCoreConfig->vSetKey("pause_when_inactive", true );
|
m_poCoreConfig->vSetKey("pause_when_inactive", true );
|
||||||
m_poCoreConfig->vSetKey("show_speed", ShowPercentage );
|
m_poCoreConfig->vSetKey("show_speed", ShowPercentage );
|
||||||
|
|
||||||
|
// Rewind
|
||||||
|
//
|
||||||
|
m_poCoreConfig->vSetKey("rewind_count_max", STATE_MAX_DEFAULT);
|
||||||
|
m_poCoreConfig->vSetKey("rewind_interval", STATE_INTERVAL_DEFAULT);
|
||||||
|
|
||||||
// Display section
|
// Display section
|
||||||
//
|
//
|
||||||
m_poDisplayConfig = m_oConfig.poAddSection("Display");
|
m_poDisplayConfig = m_oConfig.poAddSection("Display");
|
||||||
|
@ -569,6 +575,7 @@ void Window::vCheckConfig()
|
||||||
{
|
{
|
||||||
int iValue;
|
int iValue;
|
||||||
int iAdjusted;
|
int iAdjusted;
|
||||||
|
unsigned short i16Value;
|
||||||
float fValue;
|
float fValue;
|
||||||
float fAdjusted;
|
float fAdjusted;
|
||||||
std::string sValue;
|
std::string sValue;
|
||||||
|
@ -665,6 +672,22 @@ void Window::vCheckConfig()
|
||||||
m_poCoreConfig->vSetKey("emulator_type", iAdjusted);
|
m_poCoreConfig->vSetKey("emulator_type", iAdjusted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Rewind feature
|
||||||
|
// move to value change cb
|
||||||
|
i16Value = m_poCoreConfig->oGetKey<unsigned short>("rewind_count_max");
|
||||||
|
if (i16Value > 65535u)
|
||||||
|
{
|
||||||
|
m_poCoreConfig->vSetKey("rewind_count_max", STATE_MAX_DEFAULT);
|
||||||
|
}
|
||||||
|
m_state_count_max = m_poCoreConfig->oGetKey<unsigned short>("rewind_count_max");
|
||||||
|
|
||||||
|
iValue = m_poCoreConfig->oGetKey<unsigned short>("rewind_interval");
|
||||||
|
if (i16Value > 65535u)
|
||||||
|
{
|
||||||
|
m_poCoreConfig->vSetKey("rewind_interval", STATE_INTERVAL_DEFAULT);
|
||||||
|
}
|
||||||
|
m_rewind_interval = m_poCoreConfig->oGetKey<unsigned short>("rewind_interval");
|
||||||
|
|
||||||
// Display section
|
// Display section
|
||||||
//
|
//
|
||||||
iValue = m_poDisplayConfig->oGetKey<int>("scale");
|
iValue = m_poDisplayConfig->oGetKey<int>("scale");
|
||||||
|
@ -1108,6 +1131,15 @@ bool Window::bLoadROM(const std::string & _rsFile)
|
||||||
vOnLoadGameMostRecent();
|
vOnLoadGameMostRecent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// reserve rewind space for write operation
|
||||||
|
// this is used as work space
|
||||||
|
// actual state blocks are reserved in bOnEmuSaveStateRewind()
|
||||||
|
// when resulted size is known
|
||||||
|
//
|
||||||
|
if (m_state_count_max > 0 && m_psavestate == NULL) {
|
||||||
|
m_psavestate = new char[SZSTATE];
|
||||||
|
}
|
||||||
|
|
||||||
vStartEmu();
|
vStartEmu();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -1414,6 +1446,9 @@ void Window::vSaveCheats()
|
||||||
|
|
||||||
void Window::vStartEmu()
|
void Window::vStartEmu()
|
||||||
{
|
{
|
||||||
|
m_oEmuRewindSig.disconnect();
|
||||||
|
m_oEmuRewindSig = Glib::signal_timeout().connect(sigc::mem_fun(*this, &Window::bOnEmuSaveStateRewind), m_rewind_interval);
|
||||||
|
|
||||||
if (m_oEmuSig.connected())
|
if (m_oEmuSig.connected())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
@ -1426,6 +1461,7 @@ void Window::vStartEmu()
|
||||||
void Window::vStopEmu()
|
void Window::vStopEmu()
|
||||||
{
|
{
|
||||||
m_oEmuSig.disconnect();
|
m_oEmuSig.disconnect();
|
||||||
|
m_oEmuRewindSig.disconnect();
|
||||||
m_bWasEmulating = false;
|
m_bWasEmulating = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -166,6 +166,8 @@ protected:
|
||||||
virtual void vOnCheatDisableToggled(Gtk::CheckMenuItem * _poCMI);
|
virtual void vOnCheatDisableToggled(Gtk::CheckMenuItem * _poCMI);
|
||||||
virtual void vOnHelpAbout();
|
virtual void vOnHelpAbout();
|
||||||
virtual bool bOnEmuIdle();
|
virtual bool bOnEmuIdle();
|
||||||
|
virtual bool bOnEmuSaveStateRewind();
|
||||||
|
virtual bool bOnEmuRewind();
|
||||||
|
|
||||||
virtual bool on_focus_in_event(GdkEventFocus * _pstEvent);
|
virtual bool on_focus_in_event(GdkEventFocus * _pstEvent);
|
||||||
virtual bool on_focus_out_event(GdkEventFocus * _pstEvent);
|
virtual bool on_focus_out_event(GdkEventFocus * _pstEvent);
|
||||||
|
@ -242,7 +244,7 @@ private:
|
||||||
|
|
||||||
std::list<Gtk::Widget *> m_listSensitiveWhenPlaying;
|
std::list<Gtk::Widget *> m_listSensitiveWhenPlaying;
|
||||||
|
|
||||||
sigc::connection m_oEmuSig;
|
sigc::connection m_oEmuSig, m_oEmuRewindSig;
|
||||||
|
|
||||||
int m_bFullscreen;
|
int m_bFullscreen;
|
||||||
int m_iScreenWidth;
|
int m_iScreenWidth;
|
||||||
|
@ -257,6 +259,16 @@ private:
|
||||||
bool m_bAutoFrameskip;
|
bool m_bAutoFrameskip;
|
||||||
EShowSpeed m_eShowSpeed;
|
EShowSpeed m_eShowSpeed;
|
||||||
|
|
||||||
|
|
||||||
|
/* State saving into memory & rewind to saved state */
|
||||||
|
u16 m_state_count_max;
|
||||||
|
u16 m_rewind_interval;
|
||||||
|
static const u32 SZSTATE = 1024*512;
|
||||||
|
static const u16 STATE_MAX_DEFAULT = 180u;
|
||||||
|
static const u16 STATE_INTERVAL_DEFAULT = 165u;
|
||||||
|
std::deque<char*> m_rewind_load_q;
|
||||||
|
char *m_psavestate;
|
||||||
|
|
||||||
void vInitSystem();
|
void vInitSystem();
|
||||||
void vUnInitSystem();
|
void vUnInitSystem();
|
||||||
void vInitSDL();
|
void vInitSDL();
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
|
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
|
|
||||||
|
#include <deque>
|
||||||
|
|
||||||
#include <gtkmm/stock.h>
|
#include <gtkmm/stock.h>
|
||||||
#include <gtkmm/messagedialog.h>
|
#include <gtkmm/messagedialog.h>
|
||||||
#include <gtkmm/aboutdialog.h>
|
#include <gtkmm/aboutdialog.h>
|
||||||
|
@ -341,6 +343,13 @@ void Window::vOnFileClose()
|
||||||
m_eCartridge = CartridgeNone;
|
m_eCartridge = CartridgeNone;
|
||||||
emulating = 0;
|
emulating = 0;
|
||||||
|
|
||||||
|
while (!m_rewind_load_q.empty()) {
|
||||||
|
delete[] m_rewind_load_q.front();
|
||||||
|
m_rewind_load_q.pop_front();
|
||||||
|
}
|
||||||
|
delete[] m_psavestate;
|
||||||
|
m_psavestate = NULL;
|
||||||
|
|
||||||
vUpdateGameSlots();
|
vUpdateGameSlots();
|
||||||
|
|
||||||
for (std::list<Gtk::Widget *>::iterator it = m_listSensitiveWhenPlaying.begin();
|
for (std::list<Gtk::Widget *>::iterator it = m_listSensitiveWhenPlaying.begin();
|
||||||
|
@ -534,6 +543,57 @@ void Window::vOnHelpAbout()
|
||||||
oAboutDialog.run();
|
oAboutDialog.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Window::bOnEmuRewind()
|
||||||
|
{
|
||||||
|
if( !m_rewind_load_q.empty() ) {
|
||||||
|
// load a rewind save state
|
||||||
|
char *psavestate = m_rewind_load_q.front();
|
||||||
|
//memset(m_psavestate, 0x0, SZSTATE);
|
||||||
|
long szstate = *((long*)psavestate); // first there is size
|
||||||
|
//memmove(m_psavestate, psavestate+sizeof(szstate), szstate-sizeof(szstate));
|
||||||
|
if (m_stEmulator.emuReadMemState(psavestate+sizeof(szstate), szstate)) {
|
||||||
|
// the save state is now used so delete it and we have more space
|
||||||
|
m_rewind_load_q.pop_front();
|
||||||
|
delete[] psavestate;
|
||||||
|
//printf ("Restored %p! (%li bytes)\n", psavestate, szstate);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
// no more save states; either disabled, too early, or rewinded all the way to start
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Window::bOnEmuSaveStateRewind() {
|
||||||
|
// check if we're disabled
|
||||||
|
char *psavestate;
|
||||||
|
if (m_state_count_max == 0u) {
|
||||||
|
return false;
|
||||||
|
} else if (m_rewind_load_q.size() >= m_state_count_max) { // check if we can reserve more memory for save states
|
||||||
|
// if we can't reserve more memory let's take away used save states starting from oldest
|
||||||
|
psavestate = m_rewind_load_q.back();
|
||||||
|
m_rewind_load_q.pop_back();
|
||||||
|
delete[] psavestate;
|
||||||
|
} // otherwise we can reserve more memory
|
||||||
|
|
||||||
|
// Do the actual saving
|
||||||
|
long ressize;
|
||||||
|
if (m_stEmulator.emuWriteMemState(m_psavestate, SZSTATE, ressize)) {
|
||||||
|
/*ressize*=2; // if tell does not return correct size this leverage factor is needed
|
||||||
|
if (ressize > SZSTATE) ressize = SZSTATE;*/
|
||||||
|
g_assert( ressize <= SZSTATE );
|
||||||
|
ressize+=(sizeof(ressize)*8); // some leverage
|
||||||
|
psavestate = new char[ressize];
|
||||||
|
memmove(psavestate, &ressize, sizeof(ressize)); // pack size first
|
||||||
|
memmove(psavestate+sizeof(ressize), m_psavestate, ressize-sizeof(ressize)); // then actual save data
|
||||||
|
//printf("Wrote %p (%li bytes %i %i)\n", psavestate, ressize, *((long*)psavestate), sizeof(ressize));
|
||||||
|
m_rewind_load_q.push_front(psavestate);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool Window::bOnEmuIdle()
|
bool Window::bOnEmuIdle()
|
||||||
{
|
{
|
||||||
vSDLPollEvents();
|
vSDLPollEvents();
|
||||||
|
@ -573,6 +633,17 @@ bool Window::on_key_press_event(GdkEventKey * _pstEvent)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Rewind key CTRL+B
|
||||||
|
if (m_state_count_max > 0u && (_pstEvent->state & GDK_CONTROL_MASK) && _pstEvent->keyval == GDK_b) {
|
||||||
|
// disable saves first and then connect new handler
|
||||||
|
if (m_oEmuRewindSig.connected()) m_oEmuRewindSig.disconnect();
|
||||||
|
m_state_count_max = 0u;
|
||||||
|
//return this->bOnEmuRewind();
|
||||||
|
m_oEmuRewindSig = Glib::signal_timeout().connect(sigc::mem_fun(*this, &Window::bOnEmuRewind),
|
||||||
|
65u);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Forward the keyboard event to the input module by faking a SDL event
|
// Forward the keyboard event to the input module by faking a SDL event
|
||||||
SDL_Event event;
|
SDL_Event event;
|
||||||
event.type = SDL_KEYDOWN;
|
event.type = SDL_KEYDOWN;
|
||||||
|
@ -584,6 +655,15 @@ bool Window::on_key_press_event(GdkEventKey * _pstEvent)
|
||||||
|
|
||||||
bool Window::on_key_release_event(GdkEventKey * _pstEvent)
|
bool Window::on_key_release_event(GdkEventKey * _pstEvent)
|
||||||
{
|
{
|
||||||
|
// Rewind key CTRL+B
|
||||||
|
if (_pstEvent->keyval == GDK_b /*&& !(_pstEvent->state & GDK_CONTROL_MASK)*/) {
|
||||||
|
// connect save handler back
|
||||||
|
if (m_oEmuRewindSig.connected()) m_oEmuRewindSig.disconnect();
|
||||||
|
m_state_count_max = m_poCoreConfig->oGetKey<unsigned short>("rewind_count_max");
|
||||||
|
m_oEmuRewindSig = Glib::signal_timeout().connect(sigc::mem_fun(*this, &Window::bOnEmuSaveStateRewind), m_rewind_interval);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Forward the keyboard event to the input module by faking a SDL event
|
// Forward the keyboard event to the input module by faking a SDL event
|
||||||
SDL_Event event;
|
SDL_Event event;
|
||||||
event.type = SDL_KEYUP;
|
event.type = SDL_KEYUP;
|
||||||
|
|
|
@ -1438,13 +1438,14 @@ void handleRewinds()
|
||||||
rewindCount = REWIND_NUM;
|
rewindCount = REWIND_NUM;
|
||||||
|
|
||||||
curSavePos = (rewindTopPos + 1) % rewindCount; // [1] depends on previous
|
curSavePos = (rewindTopPos + 1) % rewindCount; // [1] depends on previous
|
||||||
|
long ressize;
|
||||||
if(
|
if(
|
||||||
emulator.emuWriteMemState
|
emulator.emuWriteMemState
|
||||||
&&
|
&&
|
||||||
emulator.emuWriteMemState(
|
emulator.emuWriteMemState(
|
||||||
&rewindMemory[curSavePos*REWIND_SIZE],
|
&rewindMemory[curSavePos*REWIND_SIZE],
|
||||||
REWIND_SIZE
|
REWIND_SIZE, /* available*/
|
||||||
|
ressize /* actual size */
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
char rewMsgBuf[100];
|
char rewMsgBuf[100];
|
||||||
|
@ -2048,6 +2049,16 @@ void systemScreenCapture(int a)
|
||||||
systemScreenMessage("Screen capture");
|
systemScreenMessage("Screen capture");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void systemSaveOldest()
|
||||||
|
{
|
||||||
|
// I need to be implemented
|
||||||
|
}
|
||||||
|
|
||||||
|
void systemLoadRecent()
|
||||||
|
{
|
||||||
|
// I need to be implemented
|
||||||
|
}
|
||||||
|
|
||||||
u32 systemGetClock()
|
u32 systemGetClock()
|
||||||
{
|
{
|
||||||
return SDL_GetTicks();
|
return SDL_GetTicks();
|
||||||
|
|
|
@ -1316,8 +1316,9 @@ BOOL VBA::OnIdle(LONG lCount)
|
||||||
rewindCount++;
|
rewindCount++;
|
||||||
if(rewindCount > 8)
|
if(rewindCount > 8)
|
||||||
rewindCount = 8;
|
rewindCount = 8;
|
||||||
|
long ressize;
|
||||||
if(emulator.emuWriteMemState(&rewindMemory[rewindPos*REWIND_SIZE],
|
if(emulator.emuWriteMemState(&rewindMemory[rewindPos*REWIND_SIZE],
|
||||||
REWIND_SIZE)) {
|
REWIND_SIZE, ressize)) { /* available and actual size */
|
||||||
rewindPos = ++rewindPos & 7;
|
rewindPos = ++rewindPos & 7;
|
||||||
if(rewindCount == 8)
|
if(rewindCount == 8)
|
||||||
rewindTopPos = ++rewindTopPos & 7;
|
rewindTopPos = ++rewindTopPos & 7;
|
||||||
|
|
|
@ -1081,8 +1081,10 @@ void GameArea::OnIdle(wxIdleEvent &event)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
long ressize;
|
||||||
|
|
||||||
if (!emusys->emuWriteMemState(&rewind_mem[REWIND_SIZE * next_rewind_state],
|
if (!emusys->emuWriteMemState(&rewind_mem[REWIND_SIZE * next_rewind_state],
|
||||||
REWIND_SIZE))
|
REWIND_SIZE, ressize /* actual size */))
|
||||||
// if you see a lot of these, maybe increase REWIND_SIZE
|
// if you see a lot of these, maybe increase REWIND_SIZE
|
||||||
wxLogInfo(_("Error writing rewind state"));
|
wxLogInfo(_("Error writing rewind state"));
|
||||||
else
|
else
|
||||||
|
|
|
@ -494,6 +494,17 @@ void systemScreenCapture(int num)
|
||||||
systemScreenMessage(msg);
|
systemScreenMessage(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void systemSaveOldest()
|
||||||
|
{
|
||||||
|
// I need to be implemented
|
||||||
|
}
|
||||||
|
|
||||||
|
void systemLoadRecent()
|
||||||
|
{
|
||||||
|
// I need to be implemented
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
u32 systemGetClock()
|
u32 systemGetClock()
|
||||||
{
|
{
|
||||||
return wxGetApp().timer.Time();
|
return wxGetApp().timer.Time();
|
||||||
|
|
|
@ -452,9 +452,9 @@ public:
|
||||||
u32 rom_size;
|
u32 rom_size;
|
||||||
|
|
||||||
// FIXME: size this properly
|
// FIXME: size this properly
|
||||||
#define REWIND_SIZE 400000
|
|
||||||
// FIXME: make this a config option
|
|
||||||
#define NUM_REWINDS 8
|
#define NUM_REWINDS 8
|
||||||
|
#define REWIND_SIZE 1024*512*NUM_REWINDS
|
||||||
|
// FIXME: make this a config option
|
||||||
|
|
||||||
void ShowFullScreen(bool full);
|
void ShowFullScreen(bool full);
|
||||||
bool IsFullScreen() { return fullscreen; }
|
bool IsFullScreen() { return fullscreen; }
|
||||||
|
|
Loading…
Reference in New Issue