Merge branch 'rr1-maint'
Conflicts: include/core/rom.hpp src/core/rom.cpp
This commit is contained in:
commit
591770ffa9
19 changed files with 333 additions and 13 deletions
|
@ -13,5 +13,14 @@ void main_loop(struct loaded_rom& rom, struct moviefile& settings, bool load_has
|
|||
std::vector<std::string> get_jukebox_names();
|
||||
void set_jukebox_names(const std::vector<std::string>& newj);
|
||||
void update_movie_state();
|
||||
extern std::string msu1_base_path;
|
||||
|
||||
/**
|
||||
* Signal that fast rewind operation is needed.
|
||||
*
|
||||
* Parameter ptr: If NULL, saves a state and calls lua_callback_do_unsafe_rewind() with quicksave, movie and NULL.
|
||||
* If non-NULL, calls lua_callback_do_unsafe_rewind() with movie and this parameter, but without quicksave.
|
||||
*/
|
||||
void mainloop_signal_need_rewind(void* ptr);
|
||||
|
||||
#endif
|
|
@ -230,6 +230,15 @@ public:
|
|||
* movie, reads all released.
|
||||
*/
|
||||
controller_frame read_subframe(uint64_t frame, uint64_t subframe) throw();
|
||||
/**
|
||||
* Fast save.
|
||||
*/
|
||||
void fast_save(uint64_t& _frame, uint64_t& _ptr, uint64_t& _lagc, std::vector<uint32_t>& counters);
|
||||
/**
|
||||
* Fast load.
|
||||
*/
|
||||
void fast_load(uint64_t& _frame, uint64_t& _ptr, uint64_t& _lagc, std::vector<uint32_t>& counters);
|
||||
|
||||
private:
|
||||
//TRUE if readonly mode is active.
|
||||
bool readonly;
|
||||
|
|
|
@ -33,4 +33,14 @@ std::string translate_name_mprefix(std::string original, bool forio = false);
|
|||
extern std::string last_save;
|
||||
extern movie_logic movb;
|
||||
|
||||
/**
|
||||
* Restore the actual core state from quicksave. Only call in rewind callback.
|
||||
*
|
||||
* Parameter state: The state to restore.
|
||||
* Parameter secs: The seconds counter.
|
||||
* Parameter ssecs: The subsecond counter.
|
||||
*/
|
||||
void mainloop_restore_state(const std::vector<char>& state, uint64_t secs, uint64_t ssecs);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -176,7 +176,11 @@ struct loaded_rom
|
|||
*/
|
||||
std::vector<loaded_slot> markup_slots;
|
||||
/**
|
||||
* Patch the ROMs.
|
||||
* MSU-1 base.
|
||||
*/
|
||||
std::string msu1_base;
|
||||
/**
|
||||
* Patch the ROM.
|
||||
*
|
||||
* parameter cmdline: The command line.
|
||||
* throws std::bad_alloc: Not enough memory.
|
||||
|
@ -222,7 +226,27 @@ std::map<std::string, std::vector<char>> load_sram_commandline(const std::vector
|
|||
throw(std::bad_alloc, std::runtime_error);
|
||||
|
||||
/**
|
||||
<<<<<<< HEAD
|
||||
* Given commandline arguments, load a ROM.
|
||||
=======
|
||||
* Saves core state into buffer. WARNING: This takes emulated time.
|
||||
*
|
||||
* returns: The saved state.
|
||||
* throws std::bad_alloc: Not enough memory.
|
||||
*/
|
||||
std::vector<char> save_core_state(bool nochecksum = false) throw(std::bad_alloc);
|
||||
|
||||
/**
|
||||
* Loads core state from buffer.
|
||||
*
|
||||
* parameter buf: The buffer containing the state.
|
||||
* throws std::runtime_error: Loading state failed.
|
||||
*/
|
||||
void load_core_state(const std::vector<char>& buf, bool nochecksum = false) throw(std::runtime_error);
|
||||
|
||||
/**
|
||||
* Read index of ROMs and add ROMs found to content-searchable storage.
|
||||
>>>>>>> rr1-maint
|
||||
*
|
||||
* parameter cmdline: The command line.
|
||||
* returns: The loaded ROM set.
|
||||
|
|
|
@ -89,8 +89,8 @@ struct sram_slot_structure* emucore_sram_slot(size_t index);
|
|||
size_t emucore_vma_slots();
|
||||
struct vma_structure* emucore_vma_slot(size_t index);
|
||||
void emucore_refresh_cart();
|
||||
std::vector<char> emucore_serialize();
|
||||
void emucore_unserialize(const std::vector<char>& data);
|
||||
std::vector<char> emucore_serialize(bool nochecksum = false);
|
||||
void emucore_unserialize(const std::vector<char>& data, bool nochecksum = false);
|
||||
void emucore_load_rom(systype_info_structure* rtype, region_info_structure* region,
|
||||
const std::vector<std::vector<char>>& romslots, const std::vector<std::vector<char>>& markslots);
|
||||
struct region_info_structure* emucore_current_region();
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "core/controllerframe.hpp"
|
||||
#include "core/keymapper.hpp"
|
||||
#include "core/render.hpp"
|
||||
#include "core/movie.hpp"
|
||||
|
||||
struct lua_State;
|
||||
|
||||
|
@ -88,6 +89,7 @@ void lua_callback_post_save(const std::string& name, bool is_state) throw();
|
|||
void lua_callback_snoop_input(uint32_t port, uint32_t controller, uint32_t index, short value) throw();
|
||||
void lua_callback_quit() throw();
|
||||
void lua_callback_keyhook(const std::string& key, const struct keygroup::parameters& p) throw();
|
||||
void lua_callback_do_unsafe_rewind(const std::vector<char>& save, uint64_t secs, uint64_t ssecs, movie& mov, void* u);
|
||||
|
||||
#define LUA_TIMED_HOOK_IDLE 0
|
||||
#define LUA_TIMED_HOOK_TIMER 1
|
||||
|
|
15
include/lua/unsaferewind.hpp
Normal file
15
include/lua/unsaferewind.hpp
Normal file
|
@ -0,0 +1,15 @@
|
|||
#ifndef _lua__unsaferewind__hpp__included__
|
||||
#define _lua__unsaferewind__hpp__included__
|
||||
|
||||
struct lua_unsaferewind
|
||||
{
|
||||
std::vector<char> state;
|
||||
uint64_t frame;
|
||||
uint64_t lag;
|
||||
uint64_t ptr;
|
||||
uint64_t secs;
|
||||
uint64_t ssecs;
|
||||
std::vector<uint32_t> pollcounters;
|
||||
};
|
||||
|
||||
#endif
|
69
manual.lyx
69
manual.lyx
|
@ -2918,6 +2918,51 @@ Read specifed subframe in specified frame and return data as array (100
|
|||
elements, numbered 0-99 currently).
|
||||
\end_layout
|
||||
|
||||
\begin_layout Subsubsection
|
||||
movie.unsafe_rewind([UNSAFEREWIND state])
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
Start setting point for unsafe rewind or jump to point of unsafe rewind.
|
||||
\end_layout
|
||||
|
||||
\begin_layout Itemize
|
||||
If called without argument, causes emulator to start process of setting
|
||||
unsafe rewind point.
|
||||
When this has finished, callback on_set_rewind occurs, passing the rewind
|
||||
state to lua script.
|
||||
\end_layout
|
||||
|
||||
\begin_layout Itemize
|
||||
If called with argument, causes emulator rewind to passed rewind point as
|
||||
soon as possible.
|
||||
Readwrite mode is implicitly activated.
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
The following warnings apply to unsafe rewinding:
|
||||
\end_layout
|
||||
|
||||
\begin_layout Itemize
|
||||
There are no safety checks against misuse (that's what
|
||||
\begin_inset Quotes eld
|
||||
\end_inset
|
||||
|
||||
unsafe
|
||||
\begin_inset Quotes erd
|
||||
\end_inset
|
||||
|
||||
comes from)!
|
||||
\end_layout
|
||||
|
||||
\begin_layout Itemize
|
||||
Only call rewind from timeline rewind point was set from.
|
||||
\end_layout
|
||||
|
||||
\begin_layout Itemize
|
||||
Only call rewind from after the rewind point was set.
|
||||
\end_layout
|
||||
|
||||
\begin_layout Subsection
|
||||
Table settings
|
||||
\end_layout
|
||||
|
@ -3341,6 +3386,30 @@ Called when requested by set_idle_timeout() and the timeout has expired
|
|||
(regardless if emulator is waiting).
|
||||
\end_layout
|
||||
|
||||
\begin_layout Subsubsection
|
||||
Callback: on_set_rewind(UNSAFEREWIND r)
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
Called when unsafe rewind object has been constructed.
|
||||
\end_layout
|
||||
|
||||
\begin_layout Subsubsection
|
||||
Callback: on_pre_rewind()
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
Called just before unsafe rewind is about to occur.
|
||||
\end_layout
|
||||
|
||||
\begin_layout Subsubsection
|
||||
Callback: on_post_rewind()
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
Called just after unsafe rewind has occured.
|
||||
\end_layout
|
||||
|
||||
\begin_layout Section
|
||||
Memory watch expression syntax
|
||||
\end_layout
|
||||
|
|
34
manual.txt
34
manual.txt
|
@ -1476,6 +1476,28 @@ Count number of subframes in specified frame (frame numbers are
|
|||
Read specifed subframe in specified frame and return data as
|
||||
array (100 elements, numbered 0-99 currently).
|
||||
|
||||
8.6.7 movie.unsafe_rewind([UNSAFEREWIND state])
|
||||
|
||||
Start setting point for unsafe rewind or jump to point of unsafe
|
||||
rewind.
|
||||
|
||||
• If called without argument, causes emulator to start process of
|
||||
setting unsafe rewind point. When this has finished, callback
|
||||
on_set_rewind occurs, passing the rewind state to lua script.
|
||||
|
||||
• If called with argument, causes emulator rewind to passed
|
||||
rewind point as soon as possible. Readwrite mode is implicitly
|
||||
activated.
|
||||
|
||||
The following warnings apply to unsafe rewinding:
|
||||
|
||||
• There are no safety checks against misuse (that's what “unsafe”
|
||||
comes from)!
|
||||
|
||||
• Only call rewind from timeline rewind point was set from.
|
||||
|
||||
• Only call rewind from after the rewind point was set.
|
||||
|
||||
8.7 Table settings
|
||||
|
||||
Routines for settings manipulation
|
||||
|
@ -1712,6 +1734,18 @@ expired and emulator is waiting.
|
|||
Called when requested by set_idle_timeout() and the timeout has
|
||||
expired (regardless if emulator is waiting).
|
||||
|
||||
8.10.21 Callback: on_set_rewind(UNSAFEREWIND r)
|
||||
|
||||
Called when unsafe rewind object has been constructed.
|
||||
|
||||
8.10.22 Callback: on_pre_rewind()
|
||||
|
||||
Called just before unsafe rewind is about to occur.
|
||||
|
||||
8.10.23 Callback: on_post_rewind()
|
||||
|
||||
Called just after unsafe rewind has occured.
|
||||
|
||||
9 Memory watch expression syntax
|
||||
|
||||
Memory watch expressions are in RPN (Reverse Polish Notation). At
|
||||
|
|
|
@ -80,6 +80,11 @@ namespace
|
|||
//Delay reset.
|
||||
unsigned long long delayreset_cycles_run;
|
||||
unsigned long long delayreset_cycles_target;
|
||||
//Unsafe rewind.
|
||||
bool do_unsafe_rewind = false;
|
||||
void* unsafe_rewind_obj = NULL;
|
||||
|
||||
enum advance_mode old_mode;
|
||||
|
||||
bool delayreset_fn()
|
||||
{
|
||||
|
@ -97,6 +102,16 @@ namespace
|
|||
|
||||
path_setting firmwarepath_setting("firmwarepath");
|
||||
|
||||
void mainloop_signal_need_rewind(void* ptr)
|
||||
{
|
||||
if(ptr) {
|
||||
old_mode = amode;
|
||||
amode = ADVANCE_LOAD;
|
||||
}
|
||||
do_unsafe_rewind = true;
|
||||
unsafe_rewind_obj = ptr;
|
||||
}
|
||||
|
||||
controller_frame movie_logic::update_controls(bool subframe) throw(std::bad_alloc, std::runtime_error)
|
||||
{
|
||||
if(lua_requests_subframe_paint)
|
||||
|
@ -165,7 +180,6 @@ controller_frame movie_logic::update_controls(bool subframe) throw(std::bad_allo
|
|||
|
||||
namespace
|
||||
{
|
||||
enum advance_mode old_mode;
|
||||
|
||||
//Do pending load (automatically unpauses).
|
||||
void mark_pending_load(const std::string& filename, int lmode)
|
||||
|
@ -286,7 +300,7 @@ void update_movie_state()
|
|||
uint64_t audio_irq_time;
|
||||
uint64_t controller_irq_time;
|
||||
uint64_t frame_irq_time;
|
||||
|
||||
std::string msu1_base_path;
|
||||
|
||||
class my_interface : public SNES::Interface
|
||||
{
|
||||
|
@ -295,6 +309,23 @@ class my_interface : public SNES::Interface
|
|||
const char* _hint = hint;
|
||||
std::string _hint2 = _hint;
|
||||
std::string fwp = firmwarepath_setting;
|
||||
regex_results r;
|
||||
std::string msubase = msu1_base_path;
|
||||
if(regex_match(".*\\.sfc", msu1_base_path))
|
||||
msubase = msu1_base_path.substr(0, msu1_base_path.length() - 4);
|
||||
|
||||
if(_hint2 == "msu1.rom" || _hint2 == ".msu") {
|
||||
//MSU-1 main ROM.
|
||||
std::string x = msubase + ".msu";
|
||||
messages << "MSU main data file: " << x << std::endl;
|
||||
return x.c_str();
|
||||
}
|
||||
if(r = regex("(track)?(-([0-9])+\\.pcm)", _hint2)) {
|
||||
//MSU track.
|
||||
std::string x = msubase + r[2];
|
||||
messages << "MSU track " << r[3] << "': " << x << std::endl;
|
||||
return x.c_str();
|
||||
}
|
||||
std::string finalpath = fwp + "/" + _hint2;
|
||||
return finalpath.c_str();
|
||||
}
|
||||
|
@ -736,6 +767,18 @@ namespace
|
|||
//failing.
|
||||
int handle_load()
|
||||
{
|
||||
if(do_unsafe_rewind && unsafe_rewind_obj) {
|
||||
uint64_t t = get_utime();
|
||||
std::vector<char> s;
|
||||
lua_callback_do_unsafe_rewind(s, 0, 0, movb.get_movie(), unsafe_rewind_obj);
|
||||
information_dispatch::do_mode_change(false);
|
||||
do_unsafe_rewind = false;
|
||||
our_movie.is_savestate = true;
|
||||
location_special = SPECIAL_SAVEPOINT;
|
||||
update_movie_state();
|
||||
messages << "Rewind done in " << (get_utime() - t) << " usec." << std::endl;
|
||||
return 1;
|
||||
}
|
||||
if(pending_load != "") {
|
||||
system_corrupt = false;
|
||||
if(loadmode != LOAD_STATE_BEGINNING && !do_load_state(pending_load, loadmode)) {
|
||||
|
@ -763,12 +806,21 @@ namespace
|
|||
//If there are pending saves, perform them.
|
||||
void handle_saves()
|
||||
{
|
||||
if(!queued_saves.empty()) {
|
||||
if(!queued_saves.empty() || (do_unsafe_rewind && !unsafe_rewind_obj)) {
|
||||
stepping_into_save = true;
|
||||
SNES::system.runtosave();
|
||||
stepping_into_save = false;
|
||||
for(auto i : queued_saves)
|
||||
do_save_state(i);
|
||||
if(do_unsafe_rewind && !unsafe_rewind_obj) {
|
||||
uint64_t t = get_utime();
|
||||
std::vector<char> s = emucore_serialize(true);
|
||||
uint64_t secs = our_movie.rtc_second;
|
||||
uint64_t ssecs = our_movie.rtc_subsecond;
|
||||
lua_callback_do_unsafe_rewind(s, secs, ssecs, movb.get_movie(), NULL);
|
||||
do_unsafe_rewind = false;
|
||||
messages << "Rewind point set in " << (get_utime() - t) << " usec." << std::endl;
|
||||
}
|
||||
}
|
||||
queued_saves.clear();
|
||||
}
|
||||
|
|
|
@ -459,6 +459,25 @@ void movie::reset_state() throw()
|
|||
clear_caches();
|
||||
}
|
||||
|
||||
void movie::fast_save(uint64_t& _frame, uint64_t& _ptr, uint64_t& _lagc, std::vector<uint32_t>& _counters)
|
||||
{
|
||||
pollcounters.save_state(_counters);
|
||||
_frame = current_frame;
|
||||
_ptr = current_frame_first_subframe;
|
||||
_lagc = lag_frames;
|
||||
}
|
||||
|
||||
void movie::fast_load(uint64_t& _frame, uint64_t& _ptr, uint64_t& _lagc, std::vector<uint32_t>& _counters)
|
||||
{
|
||||
readonly = true;
|
||||
current_frame = _frame;
|
||||
current_frame_first_subframe = (_ptr <= movie_data.size()) ? _ptr : movie_data.size();
|
||||
lag_frames = _lagc;
|
||||
pollcounters.load_state(_counters);
|
||||
readonly_mode(false);
|
||||
}
|
||||
|
||||
|
||||
movie_logic::movie_logic() throw()
|
||||
{
|
||||
}
|
||||
|
|
|
@ -291,6 +291,7 @@ void do_load_beginning() throw(std::bad_alloc, std::runtime_error)
|
|||
redraw_framebuffer(screen_corrupt, true);
|
||||
throw;
|
||||
}
|
||||
information_dispatch::do_mode_change(movb.get_movie().readonly_mode());
|
||||
our_movie.is_savestate = false;
|
||||
our_movie.host_memory.clear();
|
||||
messages << "Movie rewound to beginning." << std::endl;
|
||||
|
@ -469,3 +470,11 @@ bool do_load_state(const std::string& filename, int lmode)
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void mainloop_restore_state(const std::vector<char>& state, uint64_t secs, uint64_t ssecs)
|
||||
{
|
||||
rrdata::add_internal();
|
||||
our_movie.rtc_second = secs;
|
||||
our_movie.rtc_subsecond = ssecs;
|
||||
emucore_unserialize(state, true);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "core/command.hpp"
|
||||
#include "core/dispatch.hpp"
|
||||
#include "core/framerate.hpp"
|
||||
#include "core/mainloop.hpp"
|
||||
#include "core/memorymanip.hpp"
|
||||
#include "core/misc.hpp"
|
||||
#include "core/rom.hpp"
|
||||
|
@ -210,6 +211,10 @@ loaded_rom::loaded_rom(const rom_files& files) throw(std::bad_alloc, std::runtim
|
|||
markup_slots[i] = loaded_slot(files.markup_slots[i], files.base_file, *rtype->rom_slot(i),
|
||||
true);
|
||||
orig_region = region = files.region;
|
||||
if(main_slots.size() > 1)
|
||||
msu1_base = resolve_file_relative(files.main_slots[1], files.base_file);
|
||||
else
|
||||
msu1_base = resolve_file_relative(files.main_slots[0], files.base_file);
|
||||
}
|
||||
|
||||
void loaded_rom::load() throw(std::bad_alloc, std::runtime_error)
|
||||
|
@ -234,6 +239,7 @@ void loaded_rom::load() throw(std::bad_alloc, std::runtime_error)
|
|||
auto soundrate = emucore_get_audio_rate();
|
||||
set_nominal_framerate(1.0 * framerate.first / framerate.second);
|
||||
information_dispatch::do_sound_rate(soundrate.first, soundrate.second);
|
||||
msu1_base_path = msu1_base;
|
||||
refresh_cart_mappings();
|
||||
}
|
||||
|
||||
|
|
|
@ -446,12 +446,14 @@ void emucore_refresh_cart()
|
|||
delete i;
|
||||
}
|
||||
|
||||
std::vector<char> emucore_serialize()
|
||||
std::vector<char> emucore_serialize(bool nochecksum)
|
||||
{
|
||||
std::vector<char> ret;
|
||||
serializer s = SNES::system.serialize();
|
||||
ret.resize(s.size());
|
||||
memcpy(&ret[0], s.data(), s.size());
|
||||
if(nochecksum)
|
||||
return ret;
|
||||
size_t offset = ret.size();
|
||||
unsigned char tmp[32];
|
||||
sha256::hash(tmp, ret);
|
||||
|
@ -460,8 +462,14 @@ std::vector<char> emucore_serialize()
|
|||
return ret;
|
||||
}
|
||||
|
||||
void emucore_unserialize(const std::vector<char>& buf)
|
||||
void emucore_unserialize(const std::vector<char>& buf, bool nochecksum)
|
||||
{
|
||||
if(nochecksum) {
|
||||
serializer s(reinterpret_cast<const uint8_t*>(&buf[0]), buf.size());
|
||||
if(!SNES::system.unserialize(s))
|
||||
throw std::runtime_error("SNES core rejected savestate");
|
||||
return;
|
||||
}
|
||||
if(buf.size() < 32)
|
||||
throw std::runtime_error("Savestate corrupt");
|
||||
unsigned char tmp[32];
|
||||
|
|
|
@ -27,6 +27,8 @@ void lua_callback_keyhook(const std::string& key, const struct keygroup::paramet
|
|||
void init_lua() throw() {}
|
||||
void quit_lua() throw() {}
|
||||
uint64_t lua_timed_hook(int timer) throw() { return 0x7EFFFFFFFFFFFFFFULL; }
|
||||
void lua_callback_do_unsafe_rewind(const std::vector<char>& save, movie& mov, void* u) {}
|
||||
|
||||
|
||||
bool lua_requests_repaint = false;
|
||||
bool lua_requests_subframe_paint = false;
|
||||
|
|
|
@ -2,8 +2,10 @@
|
|||
#include "core/globalwrap.hpp"
|
||||
#include "lua/internal.hpp"
|
||||
#include "lua/lua.hpp"
|
||||
#include "lua/unsaferewind.hpp"
|
||||
#include "core/mainloop.hpp"
|
||||
#include "core/memorymanip.hpp"
|
||||
#include "core/moviedata.hpp"
|
||||
#include "core/misc.hpp"
|
||||
|
||||
#include <map>
|
||||
|
@ -555,7 +557,38 @@ uint64_t lua_timed_hook(int timer) throw()
|
|||
}
|
||||
}
|
||||
|
||||
void lua_callback_do_unsafe_rewind(const std::vector<char>& save, uint64_t secs, uint64_t ssecs, movie& mov, void* u)
|
||||
{
|
||||
if(u) {
|
||||
lua_unsaferewind* u2 = reinterpret_cast<lua_obj_pin<lua_unsaferewind>*>(u)->object();
|
||||
//Load.
|
||||
try {
|
||||
if(callback_exists("on_pre_rewind"))
|
||||
run_lua_cb(0);
|
||||
mainloop_restore_state(u2->state, u2->secs, u2->ssecs);
|
||||
mov.fast_load(u2->frame, u2->ptr, u2->lag, u2->pollcounters);
|
||||
if(callback_exists("on_post_rewind"))
|
||||
run_lua_cb(0);
|
||||
} catch(...) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
//Save
|
||||
if(callback_exists("on_set_rewind")) {
|
||||
lua_unsaferewind* u2 = lua_class<lua_unsaferewind>::create(L);
|
||||
u2->state = save;
|
||||
u2->secs = secs,
|
||||
u2->ssecs = ssecs;
|
||||
mov.fast_save(u2->frame, u2->ptr, u2->lag, u2->pollcounters);
|
||||
run_lua_cb(1);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool lua_requests_repaint = false;
|
||||
bool lua_requests_subframe_paint = false;
|
||||
bool lua_supported = true;
|
||||
|
||||
DECLARE_LUACLASS(lua_unsaferewind, "UNSAFEREWIND");
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#include "lua/internal.hpp"
|
||||
#include "lua/unsaferewind.hpp"
|
||||
#include "core/movie.hpp"
|
||||
#include "core/moviedata.hpp"
|
||||
#include "core/mainloop.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
@ -68,4 +70,20 @@ namespace
|
|||
lua_pushnumber(LS, our_movie.rtc_subsecond);
|
||||
return 2;
|
||||
});
|
||||
|
||||
function_ptr_luafun musv("movie.unsafe_rewind", [](lua_State* LS, const std::string& fname) -> int {
|
||||
if(lua_isnoneornil(LS, 1)) {
|
||||
//Start process to mark save.
|
||||
mainloop_signal_need_rewind(NULL);
|
||||
} else if(lua_class<lua_unsaferewind>::is(LS, 1)) {
|
||||
//Load the save.
|
||||
lua_obj_pin<lua_unsaferewind>* u = lua_class<lua_unsaferewind>::pin(LS, 1, fname.c_str());
|
||||
mainloop_signal_need_rewind(u);
|
||||
} else {
|
||||
lua_pushstring(LS, "movie.unsafe_rewind: Expected nil or UNSAFEREWIND as 1st argument");
|
||||
lua_error(LS);
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -473,7 +473,7 @@ void boot_emulator(loaded_rom& rom, moviefile& movie)
|
|||
}
|
||||
|
||||
wxwin_mainwindow::panel::panel(wxWindow* win)
|
||||
: wxPanel(win)
|
||||
: wxPanel(win, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxWANTS_CHARS)
|
||||
{
|
||||
this->Connect(wxEVT_PAINT, wxPaintEventHandler(panel::on_paint), NULL, this);
|
||||
this->Connect(wxEVT_ERASE_BACKGROUND, wxEraseEventHandler(panel::on_erase), NULL, this);
|
||||
|
|
|
@ -100,11 +100,11 @@ namespace
|
|||
int horiz_padding = 60;
|
||||
|
||||
wxdialog_pressbutton::wxdialog_pressbutton(wxWindow* parent, const std::string& title)
|
||||
: wxDialog(parent, wxID_ANY, towxstring(title), wxDefaultPosition, wxSize(-1, -1))
|
||||
: wxDialog(parent, wxID_ANY, towxstring(title))
|
||||
{
|
||||
wxStaticText* t;
|
||||
wxBoxSizer* s2 = new wxBoxSizer(wxVERTICAL);
|
||||
wxPanel* p = new wxPanel(this, wxID_ANY);
|
||||
wxPanel* p = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(-1, -1), wxWANTS_CHARS);
|
||||
s2->Add(p, 1, wxGROW);
|
||||
lastkbdkey = -1;
|
||||
mouseflag = 0;
|
||||
|
@ -116,7 +116,8 @@ namespace
|
|||
s->Add(0, 0);
|
||||
s->Add(0, 0);
|
||||
s->Add(0, 0);
|
||||
s->Add(t = new wxStaticText(p, wxID_ANY, wxT("Press the key to assign")), 1, wxGROW);
|
||||
s->Add(t = new wxStaticText(p, wxID_ANY, wxT("Press the key to assign"), wxDefaultPosition,
|
||||
wxSize(-1, -1), wxWANTS_CHARS), 1, wxGROW);
|
||||
s->Add(0, 0);
|
||||
s->Add(0, 0);
|
||||
s->Add(0, 0);
|
||||
|
|
Loading…
Add table
Reference in a new issue