Add dedicated method for resetting to poweron state
This speeds up "rewind to beginning" operation.
This commit is contained in:
parent
9aa8578e74
commit
eeaf3706d8
11 changed files with 88 additions and 4 deletions
|
@ -37,6 +37,10 @@ struct loaded_rom
|
|||
*/
|
||||
void load(std::map<std::string, std::string>& settings, uint64_t rtc_sec, uint64_t rtc_subsec)
|
||||
throw(std::bad_alloc, std::runtime_error);
|
||||
/**
|
||||
* Reset the emulation state to state just before last load.
|
||||
*/
|
||||
void reset_to_load() { return rtype().reset_to_load(); }
|
||||
/**
|
||||
* Saves core state into buffer. WARNING: This takes emulated time.
|
||||
*
|
||||
|
|
|
@ -166,6 +166,10 @@ template<> struct e2t<LSNES_CORE_GET_VMA_LIST> {
|
|||
typedef lsnes_core_get_vma_list* t;
|
||||
typedef lsnes_core_get_vma_list& r;
|
||||
};
|
||||
template<> struct e2t<LSNES_CORE_REINIT> {
|
||||
typedef lsnes_core_reinit* t;
|
||||
typedef lsnes_core_reinit& r;
|
||||
};
|
||||
|
||||
template<typename T> class t2e {};
|
||||
template<> struct t2e<lsnes_core_enumerate_cores> { const static int e = LSNES_CORE_ENUMERATE_CORES; };
|
||||
|
@ -202,6 +206,7 @@ template<> struct t2e<lsnes_core_draw_cover> { const static int e = LSNES_CORE_D
|
|||
template<> struct t2e<lsnes_core_pre_emulate> { const static int e = LSNES_CORE_PRE_EMULATE; };
|
||||
template<> struct t2e<lsnes_core_get_device_regs> { const static int e = LSNES_CORE_GET_DEVICE_REGS; };
|
||||
template<> struct t2e<lsnes_core_get_vma_list> { const static int e = LSNES_CORE_GET_VMA_LIST; };
|
||||
template<> struct t2e<lsnes_core_reinit> { const static int e = LSNES_CORE_REINIT; };
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -109,8 +109,9 @@ extern "C" {
|
|||
#define LSNES_CORE_CAP1_MEMWATCH 0x00010000U
|
||||
//Core supports lightguns (By setting lightgun_height/lightgun_width in LSNES_CORE_GET_AV_STATE).
|
||||
#define LSNES_CORE_CAP1_LIGHTGUN 0x00020000U
|
||||
//Core supports fast reinit (By supporting LSNES_CORE_REINIT).
|
||||
#define LSNES_CORE_CAP1_REINIT 0x00040000U
|
||||
//Reserved capabilities.
|
||||
#define LSNES_CORE_CAP1_RESERVED18 0x00040000U
|
||||
#define LSNES_CORE_CAP1_RESERVED19 0x00080000U
|
||||
#define LSNES_CORE_CAP1_RESERVED20 0x00100000U
|
||||
#define LSNES_CORE_CAP1_RESERVED21 0x00200000U
|
||||
|
@ -838,6 +839,16 @@ struct lsnes_core_get_vma_list
|
|||
struct lsnes_core_get_vma_list_vma** vmas;
|
||||
};
|
||||
|
||||
//Request 34: Reinit core to last loaded state.
|
||||
//Item id: Core ID.
|
||||
//Default action: Emulate using loadstate.
|
||||
//Signals that the core state should be reset to state just after last load (load savestate at moment of initial
|
||||
//poweron).
|
||||
#define LSNES_CORE_REINIT 27
|
||||
struct lsnes_core_reinit
|
||||
{
|
||||
};
|
||||
|
||||
|
||||
#ifdef LSNES_BUILD_AS_BUILTIN_CORE
|
||||
void lsnes_register_builtin_core(lsnes_core_func_t fn);
|
||||
|
|
|
@ -362,6 +362,7 @@ struct core_core
|
|||
std::vector<std::string> get_trace_cpus();
|
||||
void debug_reset();
|
||||
bool isnull() const;
|
||||
void reset_to_load() { c_reset_to_load(); }
|
||||
bool safe_to_unload(loadlib::module& mod) { return !mod.is_marked(this); }
|
||||
protected:
|
||||
/**
|
||||
|
@ -530,6 +531,10 @@ protected:
|
|||
* Reset all debug hooks.
|
||||
*/
|
||||
virtual void c_debug_reset() = 0;
|
||||
/**
|
||||
* Reset to state equivalent to ROM load.
|
||||
*/
|
||||
virtual void c_reset_to_load() = 0;
|
||||
/**
|
||||
* Is null core (only NULL core should define this).
|
||||
*/
|
||||
|
@ -618,6 +623,7 @@ public:
|
|||
std::vector<std::string> get_trace_cpus() { return core->get_trace_cpus(); }
|
||||
void debug_reset() { core->debug_reset(); }
|
||||
bool isnull() const { return core->isnull(); }
|
||||
void reset_to_load() { return core->reset_to_load(); }
|
||||
bool safe_to_unload(loadlib::module& mod) const { return core->safe_to_unload(mod); }
|
||||
protected:
|
||||
/**
|
||||
|
|
|
@ -427,8 +427,11 @@ namespace
|
|||
core.rom->set_pflag(_movie.dyn.poll_flag);
|
||||
core.controls->set_macro_frames(_movie.dyn.active_macros);
|
||||
} else {
|
||||
//Reload the ROM in order to rewind to the beginning.
|
||||
core.rom->load(_movie.settings, _movie.movie_rtc_second, _movie.movie_rtc_subsecond);
|
||||
//If settings possibly change, reload the ROM. Otherwise rewind to beginning.
|
||||
if(!*core.mlogic || core.mlogic->get_mfile().projectid != _movie.projectid)
|
||||
core.rom->load(_movie.settings, _movie.movie_rtc_second, _movie.movie_rtc_subsecond);
|
||||
else
|
||||
core.rom->reset_to_load();
|
||||
//Load the SRAM and volatile RAM. Or anchor savestate if any.
|
||||
core.controls->set_ports(portset);
|
||||
_movie.dyn.rtc_second = _movie.movie_rtc_second;
|
||||
|
|
|
@ -96,6 +96,7 @@ namespace
|
|||
{
|
||||
return std::vector<std::string>();
|
||||
}
|
||||
void c_reset_to_load() {}
|
||||
} core_null;
|
||||
}
|
||||
|
||||
|
|
|
@ -89,6 +89,7 @@ namespace
|
|||
bool video_refresh_done;
|
||||
bool forced_hook = false;
|
||||
std::map<int16_t, std::pair<uint64_t, uint64_t>> ptrmap;
|
||||
std::vector<uint8_t> init_savestate;
|
||||
uint32_t cover_fbmem[512 * 448];
|
||||
//Delay reset.
|
||||
unsigned long long delayreset_cycles_run;
|
||||
|
@ -668,6 +669,10 @@ namespace
|
|||
do_reset_flag = -1;
|
||||
if(ecore_callbacks)
|
||||
ecore_callbacks->action_state_updated();
|
||||
//Save initial state, so we can restore it later.
|
||||
serializer s = SNES::system.serialize();
|
||||
init_savestate.resize(s.size());
|
||||
memcpy(&init_savestate[0], s.data(), s.size());
|
||||
}
|
||||
return r ? 0 : -1;
|
||||
}
|
||||
|
@ -1539,6 +1544,16 @@ again2:
|
|||
//TODO: Trace various chips.
|
||||
return r;
|
||||
}
|
||||
void c_reset_to_load()
|
||||
{
|
||||
serializer s(&init_savestate[0], init_savestate.size());
|
||||
if(!SNES::system.unserialize(s))
|
||||
throw std::runtime_error("SNES core rejected initial state?");
|
||||
have_saved_this_frame = false;
|
||||
do_reset_flag = -1;
|
||||
if(ecore_callbacks)
|
||||
ecore_callbacks->action_state_updated();
|
||||
}
|
||||
} bsnes_core;
|
||||
|
||||
struct _type_snes : public core_type
|
||||
|
|
|
@ -71,6 +71,7 @@ namespace
|
|||
#endif
|
||||
unsigned frame_overflow = 0;
|
||||
std::vector<unsigned char> romdata;
|
||||
std::vector<char> init_savestate;
|
||||
uint32_t cover_fbmem[480 * 432];
|
||||
uint32_t primary_framebuffer[160*144];
|
||||
uint32_t accumulator_l = 0;
|
||||
|
@ -407,7 +408,8 @@ namespace
|
|||
for(unsigned i = 0; i < 12; i++)
|
||||
if(!palette_colors_default[i >> 2])
|
||||
instance->setDmgPaletteColor(i >> 2, i & 3, palette_colors[i]);
|
||||
|
||||
//Save initial savestate.
|
||||
instance->saveState(init_savestate);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -845,6 +847,13 @@ namespace
|
|||
r.push_back("cpu");
|
||||
return r;
|
||||
}
|
||||
void c_reset_to_load()
|
||||
{
|
||||
instance->loadState(init_savestate);
|
||||
memset(primary_framebuffer, 0, sizeof(primary_framebuffer));
|
||||
frame_overflow = 0; //frame_overflow is always 0 at the beginning.
|
||||
do_reset_flag = false;
|
||||
}
|
||||
} gambatte_core;
|
||||
|
||||
std::vector<core_setting_value_param> boolean_values = {{"0", "False", 0}, {"1", "True", 1}};
|
||||
|
|
|
@ -420,5 +420,11 @@ namespace sky
|
|||
std::vector<std::string> r;
|
||||
return r;
|
||||
}
|
||||
void c_reset_to_load()
|
||||
{
|
||||
//Clear the RAM and jump to boot vector.
|
||||
memset(corei.state.as_ram().first, 0, corei.state.as_ram().second);
|
||||
rom_boot_vector(corei);
|
||||
}
|
||||
} sky_core;
|
||||
}
|
||||
|
|
|
@ -203,5 +203,8 @@ namespace
|
|||
{
|
||||
return std::vector<std::string>();
|
||||
}
|
||||
void c_reset_to_load()
|
||||
{
|
||||
}
|
||||
} test_core;
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@ template<> int ccore_call_param_map<lsnes_core_draw_cover>::id = LSNES_CORE_DRAW
|
|||
template<> int ccore_call_param_map<lsnes_core_pre_emulate>::id = LSNES_CORE_PRE_EMULATE;
|
||||
template<> int ccore_call_param_map<lsnes_core_get_device_regs>::id = LSNES_CORE_GET_DEVICE_REGS;
|
||||
template<> int ccore_call_param_map<lsnes_core_get_vma_list>::id = LSNES_CORE_GET_VMA_LIST;
|
||||
template<> int ccore_call_param_map<lsnes_core_reinit>::id = LSNES_CORE_REINIT;
|
||||
|
||||
template<> const char* ccore_call_param_map<lsnes_core_enumerate_cores>::name = "LSNES_CORE_ENUMERATE_CORES";
|
||||
template<> const char* ccore_call_param_map<lsnes_core_get_core_info>::name = "LSNES_CORE_GET_CORE_INFO";
|
||||
|
@ -86,6 +87,7 @@ template<> const char* ccore_call_param_map<lsnes_core_draw_cover>::name = "LSNE
|
|||
template<> const char* ccore_call_param_map<lsnes_core_pre_emulate>::name = "LSNES_CORE_PRE_EMULATE";
|
||||
template<> const char* ccore_call_param_map<lsnes_core_get_device_regs>::name = "LSNES_CORE_GET_DEVICE_REGS";
|
||||
template<> const char* ccore_call_param_map<lsnes_core_get_vma_list>::name = "LSNES_CORE_GET_VMA_LIST";
|
||||
template<> const char* ccore_call_param_map<lsnes_core_reinit>::name = "LSNES_CORE_REINIT";
|
||||
|
||||
namespace
|
||||
{
|
||||
|
@ -660,6 +662,18 @@ failed:
|
|||
failed:
|
||||
return std::list<core_vma_info>();
|
||||
}
|
||||
void c_reset_to_load()
|
||||
{
|
||||
lsnes_core_reinit r;
|
||||
if(caps1 & LSNES_CORE_CAP1_REINIT) {
|
||||
entrypoint(id, r, [](const char* name, const char* err) {
|
||||
throw std::runtime_error("Resetting state failed: " + std::string(err));
|
||||
});
|
||||
return;
|
||||
}
|
||||
//Emulate by loadstate.
|
||||
c_unserialize(&init_savestate[0], init_savestate.size());
|
||||
}
|
||||
std::map<unsigned, portctrl::type*> get_ports()
|
||||
{
|
||||
return ports;
|
||||
|
@ -668,6 +682,11 @@ failed:
|
|||
{
|
||||
internal_pflag = true;
|
||||
}
|
||||
void update_initial_savestate()
|
||||
{
|
||||
if((caps1 & LSNES_CORE_CAP1_REINIT) == 0)
|
||||
c_serialize(init_savestate);
|
||||
}
|
||||
private:
|
||||
std::string fullname;
|
||||
std::string shortname;
|
||||
|
@ -680,6 +699,7 @@ failed:
|
|||
std::vector<interface_action> actions;
|
||||
framebuffer::raw cover;
|
||||
std::vector<char> covermem;
|
||||
std::vector<char> init_savestate;
|
||||
entrypoint_fn entrypoint;
|
||||
c_lib_init* plugin;
|
||||
};
|
||||
|
@ -721,6 +741,7 @@ failed:
|
|||
entrypoint(_id, r, [_id](const char* name, const char* err) {
|
||||
(stringfmt() << "LSNES_CORE_LOAD_ROM(" << _id << ") failed: " << err).throwex();
|
||||
});
|
||||
dynamic_cast<c_core_core*>(get_core())->update_initial_savestate();
|
||||
return 0;
|
||||
}
|
||||
controller_set t_controllerconfig(std::map<std::string, std::string>& settings)
|
||||
|
|
Loading…
Add table
Reference in a new issue