Use virtual methods instead of pointers for core stuff

This commit is contained in:
Ilari Liusvaara 2013-07-03 18:21:16 +03:00
parent 84faf2f42e
commit a111afad42
8 changed files with 843 additions and 716 deletions

View file

@ -202,24 +202,6 @@ struct core_type_params
* System menu name. * System menu name.
*/ */
const char* sysname; const char* sysname;
/**
* Load a ROM slot set. Changes the ROM currently loaded for core.
*
* Parameter images: The set of images to load.
* Parameter settings: The settings to use.
* Parameter rtc_sec: The initial RTC seconds value.
* Parameter rtc_subsec: The initial RTC subseconds value.
* Returns: -1 on failure, 0 on success.
*/
int (*load_rom)(core_romimage* images, std::map<std::string, std::string>& settings, uint64_t rtc_sec,
uint64_t rtc_subsec);
/**
* Obtain controller config for given settings.
*
* Parameter settings: The settings to use.
* Returns: The controller configuration.
*/
controller_set (*controllerconfig)(std::map<std::string, std::string>& settings);
/** /**
* Semicolon-separated list of extensions this system type uses. * Semicolon-separated list of extensions this system type uses.
*/ */
@ -244,24 +226,6 @@ struct core_type_params
* Core this system is emulated by. * Core this system is emulated by.
*/ */
core_core* core; core_core* core;
/**
* Get bus mapping.
*
* Returns: The bus mapping (base,size), or (0,0) if this system does not have bus mapping.
*/
std::pair<uint64_t, uint64_t> (*get_bus_map)();
/**
* Get list of valid VMAs. ROM must be loaded.
*
* Returns: The list of VMAs.
*/
std::list<core_vma_info> (*vma_list)();
/**
* Get list of valid SRAM names. ROM must be loaded.
*
* Returns: The list of SRAMs.
*/
std::set<std::string> (*srams)();
}; };
/** /**
@ -271,117 +235,10 @@ struct core_type_params
*/ */
struct core_core_params struct core_core_params
{ {
/**
* Get the name of the core.
*/
std::string (*core_identifier)();
/**
* Set the current region.
*
* Parameter region: The new region.
* Returns: True on success, false on failure (bad region).
*/
bool (*set_region)(core_region& region);
/**
* Get current video frame rate as (numerator, denominator).
*/
std::pair<uint32_t, uint32_t> (*video_rate)();
/**
* Get audio sampling rate as (numerator, denominator).
*
* Note: This value should not be changed while ROM is running, since video dumper may malfunction.
*/
std::pair<uint32_t, uint32_t> (*audio_rate)();
/**
* Save all SRAMs.
*/
std::map<std::string, std::vector<char>> (*save_sram)() throw(std::bad_alloc);
/**
* Load all SRAMs.
*
* Note: Must handle SRAM being missing or shorter or longer than expected.
*/
void (*load_sram)(std::map<std::string, std::vector<char>>& sram) throw(std::bad_alloc);
/**
* Serialize the system state.
*/
void (*serialize)(std::vector<char>& out);
/**
* Unserialize the system state.
*/
void (*unserialize)(const char* in, size_t insize);
/**
* Get current region.
*/
core_region& (*get_region)();
/**
* Poweron the console.
*/
void (*power)();
/**
* Unload the cartridge from the console.
*/
void (*unload_cartridge)();
/**
* Get the current scale factors for screen as (xscale, yscale).
*/
std::pair<uint32_t, uint32_t> (*get_scale_factors)(uint32_t width, uint32_t height);
/**
* Do basic core initialization. Called on lsnes startup.
*/
void (*install_handler)();
/**
* Do basic core uninitialization. Called on lsnes shutdown.
*/
void (*uninstall_handler)();
/**
* Emulate one frame.
*/
void (*emulate)();
/**
* Get core into state where saving is possible. Must run less than one frame.
*/
void (*runtosave)();
/**
* Get the polled flag.
*
* The emulator core sets polled flag when the game asks for input.
*
* If polled flag is clear when frame ends, the frame is marked as lag.
*/
bool (*get_pflag)();
/**
* Set the polled flag.
*/
void (*set_pflag)(bool pflag);
/** /**
* Set of valid port types for the core. * Set of valid port types for the core.
*/ */
std::vector<port_type*> port_types; std::vector<port_type*> port_types;
/**
* Draw run cover screen.
*
* Should display information about the ROM loaded.
*/
framebuffer_raw& (*draw_cover)();
/**
* Get shortened name of the core.
*/
std::string (*get_core_shortname)();
/**
* Set the system controls to appropriate values for next frame.
*
* E.g. if core supports resetting, set the reset button in the frame to pressed if reset is wanted.
*/
void (*pre_emulate_frame)(controller_frame& cf);
/**
* Execute action.
*/
void (*execute_action)(unsigned id, const std::vector<interface_action_paramval>& p);
/**
* Get set of interface device registers.
*/
const struct interface_device_reg* (*get_registers)();
}; };
struct core_region struct core_region
@ -480,31 +337,116 @@ struct core_core
std::set<const interface_action*> get_actions(); std::set<const interface_action*> get_actions();
_param_register_proxy param_register_proxy; _param_register_proxy param_register_proxy;
const interface_device_reg* get_registers(); const interface_device_reg* get_registers();
protected:
/**
* Get the name of the core.
*/
virtual std::string c_core_identifier() = 0;
/**
* Set the current region.
*
* Parameter region: The new region.
* Returns: True on success, false on failure (bad region).
*/
virtual bool c_set_region(core_region& region) = 0;
/**
* Get current video frame rate as (numerator, denominator).
*/
virtual std::pair<uint32_t, uint32_t> c_video_rate() = 0;
/**
* Get audio sampling rate as (numerator, denominator).
*
* Note: This value should not be changed while ROM is running, since video dumper may malfunction.
*/
virtual std::pair<uint32_t, uint32_t> c_audio_rate() = 0;
/**
* Save all SRAMs.
*/
virtual std::map<std::string, std::vector<char>> c_save_sram() throw(std::bad_alloc) = 0;
/**
* Load all SRAMs.
*
* Note: Must handle SRAM being missing or shorter or longer than expected.
*/
virtual void c_load_sram(std::map<std::string, std::vector<char>>& sram) throw(std::bad_alloc) = 0;
/**
* Serialize the system state.
*/
virtual void c_serialize(std::vector<char>& out) = 0;
/**
* Unserialize the system state.
*/
virtual void c_unserialize(const char* in, size_t insize) = 0;
/**
* Get current region.
*/
virtual core_region& c_get_region() = 0;
/**
* Poweron the console.
*/
virtual void c_power() = 0;
/**
* Unload the cartridge from the console.
*/
virtual void c_unload_cartridge() = 0;
/**
* Get the current scale factors for screen as (xscale, yscale).
*/
virtual std::pair<uint32_t, uint32_t> c_get_scale_factors(uint32_t width, uint32_t height) = 0;
/**
* Do basic core initialization. Called on lsnes startup.
*/
virtual void c_install_handler() = 0;
/**
* Do basic core uninitialization. Called on lsnes shutdown.
*/
virtual void c_uninstall_handler() = 0;
/**
* Emulate one frame.
*/
virtual void c_emulate() = 0;
/**
* Get core into state where saving is possible. Must run less than one frame.
*/
virtual void c_runtosave() = 0;
/**
* Get the polled flag.
*
* The emulator core sets polled flag when the game asks for input.
*
* If polled flag is clear when frame ends, the frame is marked as lag.
*/
virtual bool c_get_pflag() = 0;
/**
* Set the polled flag.
*/
virtual void c_set_pflag(bool pflag) = 0;
/**
* Draw run cover screen.
*
* Should display information about the ROM loaded.
*/
virtual framebuffer_raw& c_draw_cover() = 0;
/**
* Get shortened name of the core.
*/
virtual std::string c_get_core_shortname() = 0;
/**
* Set the system controls to appropriate values for next frame.
*
* E.g. if core supports resetting, set the reset button in the frame to pressed if reset is wanted.
*/
virtual void c_pre_emulate_frame(controller_frame& cf) = 0;
/**
* Execute action.
*/
virtual void c_execute_action(unsigned id, const std::vector<interface_action_paramval>& p) = 0;
/**
* Get set of interface device registers.
*/
virtual const struct interface_device_reg* c_get_registers() = 0;
private: private:
std::string (*_core_identifier)();
bool (*_set_region)(core_region& region);
std::pair<uint32_t, uint32_t> (*_video_rate)();
std::pair<uint32_t, uint32_t> (*_audio_rate)();
std::map<std::string, std::vector<char>> (*_save_sram)() throw(std::bad_alloc);
void (*_load_sram)(std::map<std::string, std::vector<char>>& sram) throw(std::bad_alloc);
void (*_serialize)(std::vector<char>& out);
void (*_unserialize)(const char* in, size_t insize);
core_region& (*_get_region)();
void (*_power)();
void (*_unload_cartridge)();
std::pair<uint32_t, uint32_t> (*_get_scale_factors)(uint32_t width, uint32_t height);
void (*_install_handler)();
void (*_uninstall_handler)();
void (*_emulate)();
void (*_runtosave)();
bool (*_get_pflag)();
void (*_set_pflag)(bool pflag);
std::vector<port_type*> port_types; std::vector<port_type*> port_types;
framebuffer_raw& (*_draw_cover)();
std::string (*_get_core_shortname)();
void (*_pre_emulate_frame)(controller_frame& cf);
void (*_execute_action)(unsigned id, const std::vector<interface_action_paramval>& p);
const interface_device_reg* (*_get_registers)();
bool hidden; bool hidden;
std::map<std::string, interface_action*> actions; std::map<std::string, interface_action*> actions;
mutex_class actions_lock; mutex_class actions_lock;
@ -515,7 +457,7 @@ struct core_type
public: public:
core_type(const core_type_params& params); core_type(const core_type_params& params);
core_type(std::initializer_list<core_type_params> p) : core_type(*p.begin()) {} core_type(std::initializer_list<core_type_params> p) : core_type(*p.begin()) {}
~core_type() throw(); virtual ~core_type() throw();
static std::list<core_type*> get_core_types(); static std::list<core_type*> get_core_types();
core_region& get_preferred_region(); core_region& get_preferred_region();
std::list<core_region*> get_regions(); std::list<core_region*> get_regions();
@ -572,15 +514,46 @@ public:
void pre_emulate_frame(controller_frame& cf) { return core->pre_emulate_frame(cf); } void pre_emulate_frame(controller_frame& cf) { return core->pre_emulate_frame(cf); }
std::set<const interface_action*> get_actions() { return core->get_actions(); } std::set<const interface_action*> get_actions() { return core->get_actions(); }
const interface_device_reg* get_registers() { return core->get_registers(); } const interface_device_reg* get_registers() { return core->get_registers(); }
protected:
/**
* Load a ROM slot set. Changes the ROM currently loaded for core.
*
* Parameter images: The set of images to load.
* Parameter settings: The settings to use.
* Parameter rtc_sec: The initial RTC seconds value.
* Parameter rtc_subsec: The initial RTC subseconds value.
* Returns: -1 on failure, 0 on success.
*/
virtual int t_load_rom(core_romimage* images, std::map<std::string, std::string>& settings, uint64_t rtc_sec,
uint64_t rtc_subsec) = 0;
/**
* Obtain controller config for given settings.
*
* Parameter settings: The settings to use.
* Returns: The controller configuration.
*/
virtual controller_set t_controllerconfig(std::map<std::string, std::string>& settings) = 0;
/**
* Get bus mapping.
*
* Returns: The bus mapping (base,size), or (0,0) if this system does not have bus mapping.
*/
virtual std::pair<uint64_t, uint64_t> t_get_bus_map() = 0;
/**
* Get list of valid VMAs. ROM must be loaded.
*
* Returns: The list of VMAs.
*/
virtual std::list<core_vma_info> t_vma_list() = 0;
/**
* Get list of valid SRAM names. ROM must be loaded.
*
* Returns: The list of SRAMs.
*/
virtual std::set<std::string> t_srams() = 0;
private: private:
core_type(const core_type&); core_type(const core_type&);
core_type& operator=(const core_type&); core_type& operator=(const core_type&);
int (*loadimg)(core_romimage* images, std::map<std::string, std::string>& settings, uint64_t rtc_sec,
uint64_t rtc_subsec);
controller_set (*_controllerconfig)(std::map<std::string, std::string>& settings);
std::pair<uint64_t, uint64_t> (*_get_bus_map)();
std::list<core_vma_info> (*_vma_list)();
std::set<std::string> (*_srams)();
unsigned id; unsigned id;
std::string iname; std::string iname;
std::string hname; std::string hname;

View file

@ -59,73 +59,80 @@ namespace
core_setting_group null_settings; core_setting_group null_settings;
core_region null_region{{"null", "(null)", 0, 0, false, {1, 60}, {0}}}; struct interface_device_reg null_registers[] = {
core_core core_null{{ {NULL, NULL, NULL}
.core_identifier = []() -> std::string { return "null core"; }, };
.set_region = [](core_region& reg) -> bool { return true; },
.video_rate = []() -> std::pair<unsigned, unsigned> { return std::make_pair(60, 1); }, struct _core_null : public core_core, public core_type, public core_region, public core_sysregion
.audio_rate = []() -> std::pair<unsigned, unsigned> { return std::make_pair(48000, 1); }, {
.save_sram = []() -> std::map<std::string, std::vector<char>> { _core_null() : core_core({{{}}}), core_type({{
.iname = "null",
.hname = "(null)",
.id = 9999,
.sysname = "System",
.extensions = "",
.bios = NULL,
.regions = {this},
.images = {},
.settings = &null_settings,
.core = this,
}}), core_region({{"null", "(null)", 0, 0, false, {1, 60}, {0}}}),
core_sysregion("null", *this, *this) {}
std::string c_core_identifier() { return "null core"; }
bool c_set_region(core_region& reg) { return true; }
std::pair<unsigned, unsigned> c_video_rate() { return std::make_pair(60, 1); }
std::pair<unsigned, unsigned> c_audio_rate() { return std::make_pair(48000, 1); }
std::map<std::string, std::vector<char>> c_save_sram() throw (std::bad_alloc) {
std::map<std::string, std::vector<char>> x; std::map<std::string, std::vector<char>> x;
return x; return x;
}, }
.load_sram = [](std::map<std::string, std::vector<char>>& sram) -> void {}, void c_load_sram(std::map<std::string, std::vector<char>>& sram) throw (std::bad_alloc) {}
.serialize = [](std::vector<char>& out) -> void { out.clear(); }, void c_serialize(std::vector<char>& out) { out.clear(); }
.unserialize = [](const char* in, size_t insize) -> void {}, void c_unserialize(const char* in, size_t insize) {}
.get_region = []() -> core_region& { return null_region; }, core_region& c_get_region() { return *this; }
.power = []() -> void {}, void c_power() {}
.unload_cartridge = []() -> void {}, void c_unload_cartridge() {}
.get_scale_factors = [](uint32_t width, uint32_t height) -> std::pair<uint32_t, uint32_t> { std::pair<uint32_t, uint32_t> c_get_scale_factors(uint32_t width, uint32_t height) {
return std::make_pair(1, 1); return std::make_pair(1, 1);
}, }
.install_handler = []() -> void {}, void c_install_handler() {}
.uninstall_handler = []() -> void {}, void c_uninstall_handler() {}
.emulate = []() -> void {}, void c_emulate() {}
.runtosave = []() -> void {}, void c_runtosave() {}
.get_pflag = []() -> bool { return false; }, bool c_get_pflag() { return false; }
.set_pflag = [](bool pflag) -> void {}, void c_set_pflag(bool pflag) {}
.port_types = {}, framebuffer_raw& c_draw_cover() {
.draw_cover = []() -> framebuffer_raw& {
static framebuffer_raw x(null_fbinfo); static framebuffer_raw x(null_fbinfo);
for(size_t i = 0; i < sizeof(null_cover_fbmem)/sizeof(null_cover_fbmem[0]); i++) for(size_t i = 0; i < sizeof(null_cover_fbmem)/sizeof(null_cover_fbmem[0]); i++)
null_cover_fbmem[i] = 0x0000; null_cover_fbmem[i] = 0x0000;
std::string message = "NO ROM LOADED"; std::string message = "NO ROM LOADED";
cover_render_string(null_cover_fbmem, 204, 220, message, 0xFFFF, 0x0000, 512, 448, 1024, 2); cover_render_string(null_cover_fbmem, 204, 220, message, 0xFFFF, 0x0000, 512, 448, 1024, 2);
return x; return x;
}, }
.get_core_shortname = []() -> std::string { return "null"; }, std::string c_get_core_shortname() { return "null"; }
.pre_emulate_frame = [](controller_frame& cf) -> void {}, void c_pre_emulate_frame(controller_frame& cf) {}
.execute_action = [](unsigned id, const std::vector<interface_action_paramval>& p) -> void {} void c_execute_action(unsigned id, const std::vector<interface_action_paramval>& p) {}
}}; const interface_device_reg* c_get_registers() { return null_registers; }
int t_load_rom(core_romimage* img, std::map<std::string, std::string>& settings,
core_type type_null{{ uint64_t secs, uint64_t subsecs)
"null", "(null)", 9999, "System", {
[](core_romimage* img, std::map<std::string, std::string>& settings,
uint64_t secs, uint64_t subsecs) -> int {
ecore_callbacks->set_reset_actions(-1, -1); ecore_callbacks->set_reset_actions(-1, -1);
return 0; return 0;
}, }
[](std::map<std::string, std::string>& settings) -> controller_set { controller_set t_controllerconfig(std::map<std::string, std::string>& settings)
{
controller_set x; controller_set x;
x.ports.push_back(&get_default_system_port_type()); x.ports.push_back(&get_default_system_port_type());
x.portindex.indices.push_back(sync_triple); x.portindex.indices.push_back(sync_triple);
return x; return x;
},
"", NULL, {&null_region}, {}, &null_settings, &core_null,
[]() -> std::pair<uint64_t, uint64_t> { return std::make_pair(0ULL, 0ULL); },
[]() -> std::list<core_vma_info> {
std::list<core_vma_info> x;
return x;
},
[]() -> std::set<std::string> {
std::set<std::string> x;
return x;
} }
}}; std::pair<uint64_t, uint64_t> t_get_bus_map() { return std::make_pair(0ULL, 0ULL); }
core_sysregion sysregion_null("null", type_null, null_region); std::list<core_vma_info> t_vma_list() { return std::list<core_vma_info>(); }
std::set<std::string> t_srams() { return std::set<std::string>(); }
} core_null;
core_type* current_rom_type = &type_null; core_type* current_rom_type = &core_null;
core_region* current_region = &null_region; core_region* current_region = &core_null;
core_type* find_core_by_extension(const std::string& ext, const std::string& tmpprefer) core_type* find_core_by_extension(const std::string& ext, const std::string& tmpprefer)
{ {
@ -274,8 +281,8 @@ std::pair<core_type*, core_region*> get_current_rom_info() throw()
loaded_rom::loaded_rom() throw() loaded_rom::loaded_rom() throw()
{ {
rtype = &type_null; rtype = &core_null;
region = orig_region = &null_region; region = orig_region = &core_null;
} }
loaded_rom::loaded_rom(const std::string& file, core_type& ctype) throw(std::bad_alloc, std::runtime_error) loaded_rom::loaded_rom(const std::string& file, core_type& ctype) throw(std::bad_alloc, std::runtime_error)
@ -432,8 +439,8 @@ void loaded_rom::load(std::map<std::string, std::string>& settings, uint64_t rtc
throw(std::bad_alloc, std::runtime_error) throw(std::bad_alloc, std::runtime_error)
{ {
core_core* old_core = current_rom_type->get_core(); core_core* old_core = current_rom_type->get_core();
current_rom_type = &type_null; current_rom_type = &core_null;
if(!orig_region && rtype != &type_null) if(!orig_region && rtype != &core_null)
orig_region = &rtype->get_preferred_region(); orig_region = &rtype->get_preferred_region();
if(!region) if(!region)
region = orig_region; region = orig_region;

View file

@ -146,7 +146,10 @@ namespace
#include "ports.inc" #include "ports.inc"
#include "slots.inc" #include "slots.inc"
#include "regions.inc"
core_region region_auto{{"autodetect", "Autodetect", 1, 0, true, {178683, 10738636}, {0,1,2}}};
core_region region_pal{{"pal", "PAL", 0, 2, false, {6448, 322445}, {2}}};
core_region region_ntsc{{"ntsc", "NTSC", 0, 1, false, {178683, 10738636}, {1}}};
core_setting_group bsnes_settings; core_setting_group bsnes_settings;
core_setting setting_port1(bsnes_settings, "port1", "Port 1 Type", "gamepad", { core_setting setting_port1(bsnes_settings, "port1", "Port 1 Type", "gamepad", {
@ -162,7 +165,7 @@ namespace
{"0", "False", 0}, {"1", "True", 1}}); {"0", "False", 0}, {"1", "True", 1}});
core_setting setting_randinit(bsnes_settings, "radominit", "Random initial state", "0", { core_setting setting_randinit(bsnes_settings, "radominit", "Random initial state", "0", {
{"0", "False", 0}, {"1", "True", 1}}); {"0", "False", 0}, {"1", "True", 1}});
////////////////// PORTS COMMON /////////////////// ////////////////// PORTS COMMON ///////////////////
port_type* index_to_ptype[] = { port_type* index_to_ptype[] = {
&none, &gamepad, &gamepad16, &multitap, &multitap16, &mouse, &justifier, &justifiers, &superscope &none, &gamepad, &gamepad16, &multitap, &multitap16, &mouse, &justifier, &justifiers, &superscope
@ -195,15 +198,6 @@ namespace
} }
core_type* internal_rom = NULL; core_type* internal_rom = NULL;
extern core_core bsnes_core;
interface_action act_reset(bsnes_core, 0, "Soft reset", "reset", {});
interface_action act_hreset(bsnes_core, 1, "Hard reset", "hardreset", {});
#ifdef BSNES_HAS_DEBUGGER
interface_action act_dreset(bsnes_core, 2, "Delayed soft reset", "delayreset", {{"Delay","int:0,99999999"}});
interface_action act_dhreset(bsnes_core, 3, "Delayed hard reset", "delayhardreset",
{{"Delay","int:0,99999999"}});
#endif
template<bool(*T)(const char*,const unsigned char*, unsigned)> template<bool(*T)(const char*,const unsigned char*, unsigned)>
bool load_rom_X1(core_romimage* img) bool load_rom_X1(core_romimage* img)
@ -228,9 +222,8 @@ namespace
} }
template<core_type* ctype> int load_rom(core_type* ctype, core_romimage* img, std::map<std::string, std::string>& settings,
int load_rom(core_romimage* img, std::map<std::string, std::string>& settings, uint64_t secs, uint64_t secs, uint64_t subsecs, bool(*fun)(core_romimage*))
uint64_t subsecs, bool(*fun)(core_romimage*))
{ {
std::map<std::string, std::string> _settings = settings; std::map<std::string, std::string> _settings = settings;
bsnes_settings.fill_defaults(_settings); bsnes_settings.fill_defaults(_settings);
@ -284,7 +277,7 @@ namespace
tab.push_back(t(p, i, j, true)); tab.push_back(t(p, i, j, true));
} }
controller_set _controllerconfig(std::map<std::string, std::string>& settings) controller_set bsnes_controllerconfig(std::map<std::string, std::string>& settings)
{ {
std::map<std::string, std::string> _settings = settings; std::map<std::string, std::string> _settings = settings;
bsnes_settings.fill_defaults(_settings); bsnes_settings.fill_defaults(_settings);
@ -366,44 +359,7 @@ namespace
return ecore_callbacks->get_randomseed(); return ecore_callbacks->get_randomseed();
} }
void videoRefresh(const uint32_t* data, bool hires, bool interlace, bool overscan) void videoRefresh(const uint32_t* data, bool hires, bool interlace, bool overscan);
{
last_hires = hires;
last_interlace = interlace;
bool region = (SNES::system.region() == SNES::System::Region::PAL);
if(stepping_into_save)
messages << "Got video refresh in runtosave, expect desyncs!" << std::endl;
video_refresh_done = true;
uint32_t fps_n, fps_d;
auto fps = bsnes_core.get_video_rate();
fps_n = fps.first;
fps_d = fps.second;
uint32_t g = gcd(fps_n, fps_d);
fps_n /= g;
fps_d /= g;
framebuffer_info inf;
inf.type = &_pixel_format_lrgb;
inf.mem = const_cast<char*>(reinterpret_cast<const char*>(data));
inf.physwidth = 512;
inf.physheight = 512;
inf.physstride = 2048;
inf.width = hires ? 512 : 256;
inf.height = (region ? 239 : 224) * (interlace ? 2 : 1);
inf.stride = interlace ? 2048 : 4096;
inf.offset_x = 0;
inf.offset_y = (region ? (overscan ? 9 : 1) : (overscan ? 16 : 9)) * 2;
framebuffer_raw ls(inf);
ecore_callbacks->output_frame(ls, fps_n, fps_d);
information_dispatch::do_raw_frame(data, hires, interlace, overscan, region ?
VIDEO_REGION_PAL : VIDEO_REGION_NTSC);
if(soundbuf_fill > 0) {
auto freq = SNES::system.apu_frequency();
audioapi_submit_buffer(soundbuf, soundbuf_fill / 2, true, freq / 768.0);
soundbuf_fill = 0;
}
}
void audioSample(int16_t l_sample, int16_t r_sample) void audioSample(int16_t l_sample, int16_t r_sample)
{ {
@ -574,56 +530,8 @@ namespace
memsize, true, true); memsize, true, true);
} }
std::list<core_vma_info> get_VMAlist() std::list<core_vma_info> get_VMAlist();
{ std::set<std::string> bsnes_srams()
std::list<core_vma_info> ret;
if(!internal_rom)
return ret;
create_region(ret, "WRAM", 0x007E0000, SNES::cpu.wram, 131072, false);
create_region(ret, "APURAM", 0x00000000, SNES::smp.apuram, 65536, false);
create_region(ret, "VRAM", 0x00010000, SNES::ppu.vram, 65536, false);
create_region(ret, "OAM", 0x00020000, SNES::ppu.oam, 544, false);
create_region(ret, "CGRAM", 0x00021000, SNES::ppu.cgram, 512, false);
if(SNES::cartridge.has_srtc()) create_region(ret, "RTC", 0x00022000, SNES::srtc.rtc, 20, false);
if(SNES::cartridge.has_spc7110rtc()) create_region(ret, "RTC", 0x00022000, SNES::spc7110.rtc, 20,
false);
if(SNES::cartridge.has_necdsp()) {
create_region(ret, "DSPRAM", 0x00023000, reinterpret_cast<uint8_t*>(SNES::necdsp.dataRAM),
4096, false, true);
create_region(ret, "DSPPROM", 0xF0000000, reinterpret_cast<uint8_t*>(SNES::necdsp.programROM),
65536, true, true);
create_region(ret, "DSPDROM", 0xF0010000, reinterpret_cast<uint8_t*>(SNES::necdsp.dataROM),
4096, true, true);
}
create_region(ret, "SRAM", 0x10000000, SNES::cartridge.ram, false);
create_region(ret, "ROM", 0x80000000, SNES::cartridge.rom, true);
create_region(ret, "BUS", 0x1000000, 0x1000000, snes_bus_iospace_rw);
create_region(ret, "PTRTABLE", 0x100000000, 0x100000, ptrtable_iospace_rw);
map_internal(ret, "CPU_STATE", 0, &SNES::cpu, sizeof(SNES::cpu));
map_internal(ret, "PPU_STATE", 1, &SNES::ppu, sizeof(SNES::ppu));
map_internal(ret, "SMP_STATE", 2, &SNES::smp, sizeof(SNES::smp));
map_internal(ret, "DSP_STATE", 3, &SNES::dsp, sizeof(SNES::dsp));
if(internal_rom == &type_bsx || internal_rom == &type_bsxslotted) {
create_region(ret, "BSXFLASH", 0x90000000, SNES::bsxflash.memory, true);
create_region(ret, "BSX_RAM", 0x20000000, SNES::bsxcartridge.sram, false);
create_region(ret, "BSX_PRAM", 0x30000000, SNES::bsxcartridge.psram, false);
}
if(internal_rom == &type_sufamiturbo) {
create_region(ret, "SLOTA_ROM", 0x90000000, SNES::sufamiturbo.slotA.rom, true);
create_region(ret, "SLOTB_ROM", 0xA0000000, SNES::sufamiturbo.slotB.rom, true);
create_region(ret, "SLOTA_RAM", 0x20000000, SNES::sufamiturbo.slotA.ram, false);
create_region(ret, "SLOTB_RAM", 0x30000000, SNES::sufamiturbo.slotB.ram, false);
}
if(internal_rom == &type_sgb) {
create_region(ret, "GBROM", 0x90000000, GameBoy::cartridge.romdata,
GameBoy::cartridge.romsize, true);
create_region(ret, "GBRAM", 0x20000000, GameBoy::cartridge.ramdata,
GameBoy::cartridge.ramsize, false);
}
return ret;
}
std::set<std::string> srams()
{ {
std::set<std::string> r; std::set<std::string> r;
if(!internal_rom) if(!internal_rom)
@ -637,35 +545,16 @@ namespace
const char* hexes = "0123456789ABCDEF"; const char* hexes = "0123456789ABCDEF";
void redraw_cover_fbinfo()
{
for(size_t i = 0; i < sizeof(cover_fbmem) / sizeof(cover_fbmem[0]); i++)
cover_fbmem[i] = 0;
std::string ident = bsnes_core.get_core_identifier();
cover_render_string(cover_fbmem, 0, 0, ident, 0x7FFFF, 0x00000, 512, 448, 2048, 4);
std::ostringstream name;
name << "Internal ROM name: ";
for(unsigned i = 0; i < 21; i++) {
unsigned busaddr = 0x00FFC0 + i;
unsigned char ch = SNES::bus.read(busaddr);
if(ch < 32 || ch > 126)
name << "<" << hexes[ch / 16] << hexes[ch % 16] << ">";
else
name << ch;
}
cover_render_string(cover_fbmem, 0, 16, name.str(), 0x7FFFF, 0x00000, 512, 448, 2048, 4);
unsigned y = 32;
for(auto i : cover_information()) {
cover_render_string(cover_fbmem, 0, y, i, 0x7FFFF, 0x00000, 512, 448, 2048, 4);
y += 16;
}
}
core_core bsnes_core{{ void redraw_cover_fbinfo();
.core_identifier = []() -> std::string {
struct _bsnes_core : public core_core
{
_bsnes_core() : core_core({{_port_types}}) {}
std::string c_core_identifier() {
return (stringfmt() << snes_library_id() << " (" << SNES::Info::Profile << " core)").str(); return (stringfmt() << snes_library_id() << " (" << SNES::Info::Profile << " core)").str();
}, }
.set_region = [](core_region& region) -> bool { bool c_set_region(core_region& region) {
if(&region == &region_auto) if(&region == &region_auto)
SNES::config.region = SNES::System::Region::Autodetect; SNES::config.region = SNES::System::Region::Autodetect;
else if(&region == &region_ntsc) else if(&region == &region_ntsc)
@ -675,8 +564,8 @@ namespace
else else
return false; return false;
return true; return true;
}, }
.video_rate = []() -> std::pair<uint32_t, uint32_t> { std::pair<uint32_t, uint32_t> c_video_rate() {
if(!internal_rom) if(!internal_rom)
return std::make_pair(60, 1); return std::make_pair(60, 1);
uint32_t div; uint32_t div;
@ -685,13 +574,13 @@ namespace
else else
div = last_interlace ? DURATION_NTSC_FIELD : DURATION_NTSC_FRAME; div = last_interlace ? DURATION_NTSC_FIELD : DURATION_NTSC_FRAME;
return std::make_pair(SNES::system.cpu_frequency(), div); return std::make_pair(SNES::system.cpu_frequency(), div);
}, }
.audio_rate = []() -> std::pair<uint32_t, uint32_t> { std::pair<uint32_t, uint32_t> c_audio_rate() {
if(!internal_rom) if(!internal_rom)
return std::make_pair(64081, 2); return std::make_pair(64081, 2);
return std::make_pair(SNES::system.apu_frequency(), static_cast<uint32_t>(768)); return std::make_pair(SNES::system.apu_frequency(), static_cast<uint32_t>(768));
}, }
.save_sram = []() -> std::map<std::string, std::vector<char>> { std::map<std::string, std::vector<char>> c_save_sram() throw(std::bad_alloc) {
std::map<std::string, std::vector<char>> out; std::map<std::string, std::vector<char>> out;
if(!internal_rom) if(!internal_rom)
return out; return out;
@ -704,8 +593,8 @@ namespace
out[savename] = x; out[savename] = x;
} }
return out; return out;
}, }
.load_sram = [](std::map<std::string, std::vector<char>>& sram) -> void { void c_load_sram(std::map<std::string, std::vector<char>>& sram) throw(std::bad_alloc) {
std::set<std::string> used; std::set<std::string> used;
if(!internal_rom) { if(!internal_rom) {
for(auto i : sram) for(auto i : sram)
@ -732,15 +621,15 @@ namespace
if(!used.count(i.first)) if(!used.count(i.first))
messages << "WARNING: SRAM '" << i.first << ": Not found on cartridge." messages << "WARNING: SRAM '" << i.first << ": Not found on cartridge."
<< std::endl; << std::endl;
}, }
.serialize = [](std::vector<char>& out) -> void { void c_serialize(std::vector<char>& out) {
if(!internal_rom) if(!internal_rom)
throw std::runtime_error("No ROM loaded"); throw std::runtime_error("No ROM loaded");
serializer s = SNES::system.serialize(); serializer s = SNES::system.serialize();
out.resize(s.size()); out.resize(s.size());
memcpy(&out[0], s.data(), s.size()); memcpy(&out[0], s.data(), s.size());
}, }
.unserialize = [](const char* in, size_t insize) -> void { void c_unserialize(const char* in, size_t insize) {
if(!internal_rom) if(!internal_rom)
throw std::runtime_error("No ROM loaded"); throw std::runtime_error("No ROM loaded");
serializer s(reinterpret_cast<const uint8_t*>(in), insize); serializer s(reinterpret_cast<const uint8_t*>(in), insize);
@ -748,31 +637,31 @@ namespace
throw std::runtime_error("SNES core rejected savestate"); throw std::runtime_error("SNES core rejected savestate");
have_saved_this_frame = true; have_saved_this_frame = true;
do_reset_flag = -1; do_reset_flag = -1;
}, }
.get_region = []() -> core_region& { core_region& c_get_region() {
return (SNES::system.region() == SNES::System::Region::PAL) ? region_pal : region_ntsc; return (SNES::system.region() == SNES::System::Region::PAL) ? region_pal : region_ntsc;
}, }
.power = []() -> void { void c_power() {
if(internal_rom) snes_power(); if(internal_rom) snes_power();
}, }
.unload_cartridge = []() -> void { void c_unload_cartridge() {
if(!internal_rom) return; if(!internal_rom) return;
snes_term(); snes_term();
snes_unload_cartridge(); snes_unload_cartridge();
internal_rom = NULL; internal_rom = NULL;
}, }
.get_scale_factors = [](uint32_t width, uint32_t height) -> std::pair<uint32_t, uint32_t> { std::pair<uint32_t, uint32_t> c_get_scale_factors(uint32_t width, uint32_t height) {
return std::make_pair((width < 400) ? 2 : 1, (height < 400) ? 2 : 1); return std::make_pair((width < 400) ? 2 : 1, (height < 400) ? 2 : 1);
}, }
.install_handler = []() -> void { void c_install_handler() {
basic_init(); basic_init();
old = SNES::interface; old = SNES::interface;
SNES::interface = &my_interface_obj; SNES::interface = &my_interface_obj;
SNES::system.init(); SNES::system.init();
magic_flags |= 1; magic_flags |= 1;
}, }
.uninstall_handler = []() -> void { SNES::interface = old; }, void c_uninstall_handler() { SNES::interface = old; }
.emulate = []() -> void { void c_emulate() {
if(!internal_rom) if(!internal_rom)
return; return;
bool was_delay_reset = false; bool was_delay_reset = false;
@ -856,32 +745,31 @@ again2:
SNES::cpu.step_event = nall::function<bool()>(); SNES::cpu.step_event = nall::function<bool()>();
#endif #endif
have_saved_this_frame = false; have_saved_this_frame = false;
}, }
.runtosave = []() -> void { void c_runtosave() {
if(!internal_rom) if(!internal_rom)
return; return;
stepping_into_save = true; stepping_into_save = true;
SNES::system.runtosave(); SNES::system.runtosave();
have_saved_this_frame = true; have_saved_this_frame = true;
stepping_into_save = false; stepping_into_save = false;
}, }
.get_pflag = []() -> bool { return SNES::cpu.controller_flag; }, bool c_get_pflag() { return SNES::cpu.controller_flag; }
.set_pflag = [](bool pflag) -> void { SNES::cpu.controller_flag = pflag; }, void c_set_pflag(bool pflag) { SNES::cpu.controller_flag = pflag; }
.port_types = port_types, framebuffer_raw& c_draw_cover() {
.draw_cover = []() -> framebuffer_raw& {
static framebuffer_raw x(cover_fbinfo); static framebuffer_raw x(cover_fbinfo);
redraw_cover_fbinfo(); redraw_cover_fbinfo();
return x; return x;
}, }
.get_core_shortname = []() -> std::string std::string c_get_core_shortname()
{ {
#ifdef BSNES_IS_COMPAT #ifdef BSNES_IS_COMPAT
return (stringfmt() << "bsnes" << BSNES_VERSION << "c").str(); return (stringfmt() << "bsnes" << BSNES_VERSION << "c").str();
#else #else
return (stringfmt() << "bsnes" << BSNES_VERSION << "a").str(); return (stringfmt() << "bsnes" << BSNES_VERSION << "a").str();
#endif #endif
}, }
.pre_emulate_frame = [](controller_frame& cf) -> void void c_pre_emulate_frame(controller_frame& cf)
{ {
cf.axis3(0, 0, 1, (do_reset_flag >= 0) ? 1 : 0); cf.axis3(0, 0, 1, (do_reset_flag >= 0) ? 1 : 0);
if(support_hreset) if(support_hreset)
@ -893,8 +781,8 @@ again2:
cf.axis3(0, 0, 2, 0); cf.axis3(0, 0, 2, 0);
cf.axis3(0, 0, 3, 0); cf.axis3(0, 0, 3, 0);
} }
}, }
.execute_action = [](unsigned id, const std::vector<interface_action_paramval>& p) -> void void c_execute_action(unsigned id, const std::vector<interface_action_paramval>& p)
{ {
switch(id) { switch(id) {
case 0: //Soft reset. case 0: //Soft reset.
@ -914,67 +802,281 @@ again2:
do_hreset_flag = true; do_hreset_flag = true;
break; break;
} }
}, }
.get_registers = []() -> const interface_device_reg* { return snes_registers; }, const interface_device_reg* c_get_registers() { return snes_registers; }
}}; } bsnes_core;
core_type type_snes{{ interface_action act_reset(bsnes_core, 0, "Soft reset", "reset", {});
.iname = "snes", .hname = "SNES", .id = 0, .sysname = "SNES", interface_action act_hreset(bsnes_core, 1, "Hard reset", "hardreset", {});
.load_rom = [](core_romimage* img, std::map<std::string, std::string>& settings, uint64_t secs, #ifdef BSNES_HAS_DEBUGGER
uint64_t subsecs) -> int { interface_action act_dreset(bsnes_core, 2, "Delayed soft reset", "delayreset", {{"Delay","int:0,99999999"}});
return load_rom<&type_snes>(img, settings, secs, subsecs, interface_action act_dhreset(bsnes_core, 3, "Delayed hard reset", "delayhardreset",
load_rom_X1<snes_load_cartridge_normal>); {{"Delay","int:0,99999999"}});
}, #endif
.controllerconfig = _controllerconfig, .extensions = "sfc;smc;swc;fig;ufo;sf2;gd3;gd7;dx2;mgd;mgh",
.bios = NULL, .regions = snes_regions, .images = snes_images, struct _type_snes : public core_type
.settings = &bsnes_settings, .core = &bsnes_core, .get_bus_map = bsnes_get_bus_map, {
.vma_list = get_VMAlist, .srams = srams _type_snes() : core_type({{
}}; .iname = "snes",
core_type type_bsx{{ .hname = "SNES",
.iname = "bsx", .hname = "BS-X (non-slotted)", .id = 1, .sysname = "BS-X", .id = 0,
.load_rom = [](core_romimage* img, std::map<std::string, std::string>& settings, uint64_t secs, .sysname = "SNES",
uint64_t subsecs) -> int { .extensions = "sfc;smc;swc;fig;ufo;sf2;gd3;gd7;dx2;mgd;mgh",
return load_rom<&type_bsx>(img, settings, secs, subsecs, .bios = NULL,
load_rom_X2<snes_load_cartridge_bsx>); .regions = {&region_auto, &region_ntsc, &region_pal},
}, .images = snes_images,
.controllerconfig = _controllerconfig, .extensions = "bs", .bios = "bsx.sfc", .regions = bsx_regions, .settings = &bsnes_settings,
.images = bsx_images, .settings = &bsnes_settings, .core = &bsnes_core, .core = &bsnes_core,
.get_bus_map = bsnes_get_bus_map, .vma_list = get_VMAlist, .srams = srams }}) {}
}}; int t_load_rom(core_romimage* img, std::map<std::string, std::string>& settings,
core_type type_bsxslotted{{ uint64_t secs, uint64_t subsecs)
.iname = "bsxslotted", .hname = "BS-X (slotted)", .id = 2, .sysname = "BS-X",
.load_rom = [](core_romimage* img, std::map<std::string, std::string>& settings,
uint64_t secs, uint64_t subsecs) -> int {
return load_rom<&type_bsxslotted>(img, settings, secs, subsecs,
load_rom_X2<snes_load_cartridge_bsx_slotted>);
},
.controllerconfig = _controllerconfig, .extensions = "bss", .bios = "bsxslotted.sfc",
.regions = bsxs_regions, .images = bsxs_images, .settings = &bsnes_settings, .core = &bsnes_core,
.get_bus_map = bsnes_get_bus_map, .vma_list = get_VMAlist, .srams = srams
}};
core_type type_sufamiturbo{{
.iname = "sufamiturbo", .hname = "Sufami Turbo", .id = 3, .sysname = "SufamiTurbo",
.load_rom = [](core_romimage* img, std::map<std::string, std::string>& settings, uint64_t secs,
uint64_t subsecs) -> int {
return load_rom<&type_sufamiturbo>(img, settings, secs, subsecs,
load_rom_X3<snes_load_cartridge_sufami_turbo>);
},
.controllerconfig = _controllerconfig, .extensions = "st", .bios = "sufamiturbo.sfc",
.regions = sufamiturbo_regions, .images = sufamiturbo_images, .settings = &bsnes_settings,
.core = &bsnes_core, .get_bus_map = bsnes_get_bus_map, .vma_list = get_VMAlist, .srams = srams
}};
core_type type_sgb{{
.iname = "sgb", .hname = "Super Game Boy", .id = 4, .sysname = "SGB",
.load_rom = [](core_romimage* img, std::map<std::string, std::string>& settings, uint64_t secs,
uint64_t subsecs) -> int
{ {
return load_rom<&type_sgb>(img, settings, secs, subsecs, return load_rom(this, img, settings, secs, subsecs,
load_rom_X1<snes_load_cartridge_normal>);
}
controller_set t_controllerconfig(std::map<std::string, std::string>& settings)
{
return bsnes_controllerconfig(settings);
}
std::pair<uint64_t, uint64_t> t_get_bus_map() { return bsnes_get_bus_map(); }
std::list<core_vma_info> t_vma_list() { return get_VMAlist(); }
std::set<std::string> t_srams() { return bsnes_srams(); }
} type_snes;
core_sysregion snes_pal("snes_pal", type_snes, region_pal);
core_sysregion snes_ntsc("snes_ntsc", type_snes, region_ntsc);
struct _type_bsx : public core_type
{
_type_bsx() : core_type({{
.iname = "bsx",
.hname = "BS-X (non-slotted)",
.id = 1,
.sysname = "BS-X",
.extensions = "bs",
.bios = "bsx.sfc",
.regions = {&region_ntsc},
.images = bsx_images,
.settings = &bsnes_settings,
.core = &bsnes_core,
}}) {}
int t_load_rom(core_romimage* img, std::map<std::string, std::string>& settings,
uint64_t secs, uint64_t subsecs)
{
return load_rom(this, img, settings, secs, subsecs,
load_rom_X2<snes_load_cartridge_bsx>);
}
controller_set t_controllerconfig(std::map<std::string, std::string>& settings)
{
return bsnes_controllerconfig(settings);
}
std::pair<uint64_t, uint64_t> t_get_bus_map() { return bsnes_get_bus_map(); }
std::list<core_vma_info> t_vma_list() { return get_VMAlist(); }
std::set<std::string> t_srams() { return bsnes_srams(); }
} type_bsx;
core_sysregion bsx_sr("bsx", type_bsx, region_ntsc);
struct _type_bsxslotted : public core_type
{
_type_bsxslotted() : core_type({{
.iname = "bsxslotted",
.hname = "BS-X (slotted)",
.id = 2,
.sysname = "BS-X",
.extensions = "bss",
.bios = "bsxslotted.sfc",
.regions = {&region_ntsc},
.images = bsxs_images,
.settings = &bsnes_settings,
.core = &bsnes_core,
}}) {}
int t_load_rom(core_romimage* img, std::map<std::string, std::string>& settings,
uint64_t secs, uint64_t subsecs)
{
return load_rom(this, img, settings, secs, subsecs,
load_rom_X2<snes_load_cartridge_bsx_slotted>);
}
controller_set t_controllerconfig(std::map<std::string, std::string>& settings)
{
return bsnes_controllerconfig(settings);
}
std::pair<uint64_t, uint64_t> t_get_bus_map() { return bsnes_get_bus_map(); }
std::list<core_vma_info> t_vma_list() { return get_VMAlist(); }
std::set<std::string> t_srams() { return bsnes_srams(); }
} type_bsxslotted;
core_sysregion bsxslotted_sr("bsxslotted", type_bsxslotted, region_ntsc);
struct _type_sufamiturbo : public core_type
{
_type_sufamiturbo() : core_type({{
.iname = "sufamiturbo",
.hname = "Sufami Turbo",
.id = 3,
.sysname = "SufamiTurbo",
.extensions = "st",
.bios = "sufamiturbo.sfc",
.regions = {&region_ntsc},
.images = sufamiturbo_images,
.settings = &bsnes_settings,
.core = &bsnes_core,
}}) {}
int t_load_rom(core_romimage* img, std::map<std::string, std::string>& settings,
uint64_t secs, uint64_t subsecs)
{
return load_rom(this, img, settings, secs, subsecs,
load_rom_X3<snes_load_cartridge_sufami_turbo>);
}
controller_set t_controllerconfig(std::map<std::string, std::string>& settings)
{
return bsnes_controllerconfig(settings);
}
std::pair<uint64_t, uint64_t> t_get_bus_map() { return bsnes_get_bus_map(); }
std::list<core_vma_info> t_vma_list() { return get_VMAlist(); }
std::set<std::string> t_srams() { return bsnes_srams(); }
} type_sufamiturbo;
core_sysregion sufamiturbo_sr("sufamiturbo", type_sufamiturbo, region_ntsc);
struct _type_sgb : public core_type
{
_type_sgb() : core_type({{
.iname = "sgb",
.hname = "Super Game Boy",
.id = 4,
.sysname = "SGB",
.extensions = "gb;dmg;sgb",
.bios = "sgb.sfc",
.regions = {&region_auto, &region_ntsc, &region_pal},
.images = sgb_images,
.settings = &bsnes_settings,
.core = &bsnes_core,
}}) {}
int t_load_rom(core_romimage* img, std::map<std::string, std::string>& settings,
uint64_t secs, uint64_t subsecs)
{
return load_rom(this, img, settings, secs, subsecs,
load_rom_X2<snes_load_cartridge_super_game_boy>); load_rom_X2<snes_load_cartridge_super_game_boy>);
}, }
.controllerconfig = _controllerconfig, .extensions = "gb;dmg;sgb", .bios = "sgb.sfc", controller_set t_controllerconfig(std::map<std::string, std::string>& settings)
.regions = sgb_regions, .images = sgb_images, .settings = &bsnes_settings, .core = &bsnes_core, {
.get_bus_map = bsnes_get_bus_map, .vma_list = get_VMAlist, .srams = srams return bsnes_controllerconfig(settings);
}}; }
std::pair<uint64_t, uint64_t> t_get_bus_map() { return bsnes_get_bus_map(); }
std::list<core_vma_info> t_vma_list() { return get_VMAlist(); }
std::set<std::string> t_srams() { return bsnes_srams(); }
} type_sgb;
core_sysregion sgb_pal("sgb_pal", type_sgb, region_pal);
core_sysregion sgb_ntsc("sgb_ntsc", type_sgb, region_ntsc);
void redraw_cover_fbinfo()
{
for(size_t i = 0; i < sizeof(cover_fbmem) / sizeof(cover_fbmem[0]); i++)
cover_fbmem[i] = 0;
std::string ident = bsnes_core.get_core_identifier();
cover_render_string(cover_fbmem, 0, 0, ident, 0x7FFFF, 0x00000, 512, 448, 2048, 4);
std::ostringstream name;
name << "Internal ROM name: ";
for(unsigned i = 0; i < 21; i++) {
unsigned busaddr = 0x00FFC0 + i;
unsigned char ch = SNES::bus.read(busaddr);
if(ch < 32 || ch > 126)
name << "<" << hexes[ch / 16] << hexes[ch % 16] << ">";
else
name << ch;
}
cover_render_string(cover_fbmem, 0, 16, name.str(), 0x7FFFF, 0x00000, 512, 448, 2048, 4);
unsigned y = 32;
for(auto i : cover_information()) {
cover_render_string(cover_fbmem, 0, y, i, 0x7FFFF, 0x00000, 512, 448, 2048, 4);
y += 16;
}
}
void my_interface::videoRefresh(const uint32_t* data, bool hires, bool interlace, bool overscan)
{
last_hires = hires;
last_interlace = interlace;
bool region = (SNES::system.region() == SNES::System::Region::PAL);
if(stepping_into_save)
messages << "Got video refresh in runtosave, expect desyncs!" << std::endl;
video_refresh_done = true;
uint32_t fps_n, fps_d;
auto fps = bsnes_core.get_video_rate();
fps_n = fps.first;
fps_d = fps.second;
uint32_t g = gcd(fps_n, fps_d);
fps_n /= g;
fps_d /= g;
framebuffer_info inf;
inf.type = &_pixel_format_lrgb;
inf.mem = const_cast<char*>(reinterpret_cast<const char*>(data));
inf.physwidth = 512;
inf.physheight = 512;
inf.physstride = 2048;
inf.width = hires ? 512 : 256;
inf.height = (region ? 239 : 224) * (interlace ? 2 : 1);
inf.stride = interlace ? 2048 : 4096;
inf.offset_x = 0;
inf.offset_y = (region ? (overscan ? 9 : 1) : (overscan ? 16 : 9)) * 2;
framebuffer_raw ls(inf);
ecore_callbacks->output_frame(ls, fps_n, fps_d);
information_dispatch::do_raw_frame(data, hires, interlace, overscan, region ?
VIDEO_REGION_PAL : VIDEO_REGION_NTSC);
if(soundbuf_fill > 0) {
auto freq = SNES::system.apu_frequency();
audioapi_submit_buffer(soundbuf, soundbuf_fill / 2, true, freq / 768.0);
soundbuf_fill = 0;
}
}
std::list<core_vma_info> get_VMAlist()
{
std::list<core_vma_info> ret;
if(!internal_rom)
return ret;
create_region(ret, "WRAM", 0x007E0000, SNES::cpu.wram, 131072, false);
create_region(ret, "APURAM", 0x00000000, SNES::smp.apuram, 65536, false);
create_region(ret, "VRAM", 0x00010000, SNES::ppu.vram, 65536, false);
create_region(ret, "OAM", 0x00020000, SNES::ppu.oam, 544, false);
create_region(ret, "CGRAM", 0x00021000, SNES::ppu.cgram, 512, false);
if(SNES::cartridge.has_srtc()) create_region(ret, "RTC", 0x00022000, SNES::srtc.rtc, 20, false);
if(SNES::cartridge.has_spc7110rtc()) create_region(ret, "RTC", 0x00022000, SNES::spc7110.rtc, 20,
false);
if(SNES::cartridge.has_necdsp()) {
create_region(ret, "DSPRAM", 0x00023000, reinterpret_cast<uint8_t*>(SNES::necdsp.dataRAM),
4096, false, true);
create_region(ret, "DSPPROM", 0xF0000000, reinterpret_cast<uint8_t*>(SNES::necdsp.programROM),
65536, true, true);
create_region(ret, "DSPDROM", 0xF0010000, reinterpret_cast<uint8_t*>(SNES::necdsp.dataROM),
4096, true, true);
}
create_region(ret, "SRAM", 0x10000000, SNES::cartridge.ram, false);
create_region(ret, "ROM", 0x80000000, SNES::cartridge.rom, true);
create_region(ret, "BUS", 0x1000000, 0x1000000, snes_bus_iospace_rw);
create_region(ret, "PTRTABLE", 0x100000000, 0x100000, ptrtable_iospace_rw);
map_internal(ret, "CPU_STATE", 0, &SNES::cpu, sizeof(SNES::cpu));
map_internal(ret, "PPU_STATE", 1, &SNES::ppu, sizeof(SNES::ppu));
map_internal(ret, "SMP_STATE", 2, &SNES::smp, sizeof(SNES::smp));
map_internal(ret, "DSP_STATE", 3, &SNES::dsp, sizeof(SNES::dsp));
if(internal_rom == &type_bsx || internal_rom == &type_bsxslotted) {
create_region(ret, "BSXFLASH", 0x90000000, SNES::bsxflash.memory, true);
create_region(ret, "BSX_RAM", 0x20000000, SNES::bsxcartridge.sram, false);
create_region(ret, "BSX_PRAM", 0x30000000, SNES::bsxcartridge.psram, false);
}
if(internal_rom == &type_sufamiturbo) {
create_region(ret, "SLOTA_ROM", 0x90000000, SNES::sufamiturbo.slotA.rom, true);
create_region(ret, "SLOTB_ROM", 0xA0000000, SNES::sufamiturbo.slotB.rom, true);
create_region(ret, "SLOTA_RAM", 0x20000000, SNES::sufamiturbo.slotA.ram, false);
create_region(ret, "SLOTB_RAM", 0x30000000, SNES::sufamiturbo.slotB.ram, false);
}
if(internal_rom == &type_sgb) {
create_region(ret, "GBROM", 0x90000000, GameBoy::cartridge.romdata,
GameBoy::cartridge.romsize, true);
create_region(ret, "GBRAM", 0x20000000, GameBoy::cartridge.ramdata,
GameBoy::cartridge.ramsize, false);
}
return ret;
}
function_ptr_command<arg_filename> dump_core(lsnes_cmd, "dump-core", "No description available", function_ptr_command<arg_filename> dump_core(lsnes_cmd, "dump-core", "No description available",
"No description available\n", "No description available\n",

View file

@ -46,7 +46,6 @@ namespace
{ {
bool do_reset_flag = false; bool do_reset_flag = false;
core_type* internal_rom = NULL; core_type* internal_rom = NULL;
extern core_core gambatte_core;
bool rtc_fixed; bool rtc_fixed;
time_t rtc_fixed_val; time_t rtc_fixed_val;
gambatte::GB* instance; gambatte::GB* instance;
@ -59,7 +58,6 @@ namespace
unsigned accumulator_s = 0; unsigned accumulator_s = 0;
bool pflag = false; bool pflag = false;
interface_action act_reset(gambatte_core, 0, "Soft reset", "reset", {});
struct interface_device_reg gb_registers[] = { struct interface_device_reg gb_registers[] = {
{NULL, NULL, NULL} {NULL, NULL, NULL}
@ -76,7 +74,6 @@ namespace
#include "ports.inc" #include "ports.inc"
#include "slots.inc" #include "slots.inc"
#include "regions.inc"
core_setting_group gambatte_settings; core_setting_group gambatte_settings;
@ -161,7 +158,7 @@ namespace
return x; return x;
} }
controller_set _controllerconfig(std::map<std::string, std::string>& settings) controller_set gambatte_controllerconfig(std::map<std::string, std::string>& settings)
{ {
std::map<std::string, std::string> _settings = settings; std::map<std::string, std::string> _settings = settings;
controller_set r; controller_set r;
@ -244,7 +241,7 @@ namespace
return vmas; return vmas;
} }
std::set<std::string> srams() std::set<std::string> gambatte_srams()
{ {
std::set<std::string> s; std::set<std::string> s;
if(!internal_rom) if(!internal_rom)
@ -270,27 +267,17 @@ namespace
return name.str(); return name.str();
} }
void redraw_cover_fbinfo() void redraw_cover_fbinfo();
{
for(size_t i = 0; i < sizeof(cover_fbmem) / sizeof(cover_fbmem[0]); i++)
cover_fbmem[i] = 0x00000000;
std::string ident = gambatte_core.get_core_identifier();
cover_render_string(cover_fbmem, 0, 0, ident, 0xFFFFFF, 0x00000, 480, 432, 1920, 4);
cover_render_string(cover_fbmem, 0, 16, "Internal ROM name: " + get_cartridge_name(),
0xFFFFFF, 0x00000, 480, 432, 1920, 4);
unsigned y = 32;
for(auto i : cover_information()) {
cover_render_string(cover_fbmem, 0, y, i, 0xFFFFFF, 0x000000, 480, 432, 1920, 4);
y += 16;
}
}
core_core gambatte_core{{ struct _gambatte_core : public core_core, public core_region
.core_identifier = []() -> std::string { return "libgambatte "+gambatte::GB::version(); }, {
.set_region = [](core_region& region) -> bool { return (&region == &region_world); }, _gambatte_core() : core_core({{_port_types}}),
.video_rate = []() -> std::pair<uint32_t, uint32_t> { return std::make_pair(262144, 4389); }, core_region({{"world", "World", 0, 0, false, {4389, 262144}, {0}}}) {}
.audio_rate = []() -> std::pair<uint32_t, uint32_t> { return std::make_pair(32768, 1); }, std::string c_core_identifier() { return "libgambatte "+gambatte::GB::version(); }
.save_sram = []() -> std::map<std::string, std::vector<char>> { bool c_set_region(core_region& region) { return (&region == this); }
std::pair<uint32_t, uint32_t> c_video_rate() { return std::make_pair(262144, 4389); }
std::pair<uint32_t, uint32_t> c_audio_rate() { return std::make_pair(32768, 1); }
std::map<std::string, std::vector<char>> c_save_sram() throw(std::bad_alloc) {
std::map<std::string, std::vector<char>> s; std::map<std::string, std::vector<char>> s;
if(!internal_rom) if(!internal_rom)
return s; return s;
@ -302,8 +289,8 @@ namespace
for(size_t i = 0; i < 8; i++) for(size_t i = 0; i < 8; i++)
s["rtc"][i] = ((unsigned long long)timebase >> (8 * i)); s["rtc"][i] = ((unsigned long long)timebase >> (8 * i));
return s; return s;
}, }
.load_sram = [](std::map<std::string, std::vector<char>>& sram) -> void { void c_load_sram(std::map<std::string, std::vector<char>>& sram) throw(std::bad_alloc) {
if(!internal_rom) if(!internal_rom)
return; return;
std::vector<char> x = sram.count("main") ? sram["main"] : std::vector<char>(); std::vector<char> x = sram.count("main") ? sram["main"] : std::vector<char>();
@ -321,8 +308,8 @@ namespace
timebase |= (unsigned long long)(unsigned char)x2[i] << (8 * i); timebase |= (unsigned long long)(unsigned char)x2[i] << (8 * i);
instance->setRtcBase(timebase); instance->setRtcBase(timebase);
} }
}, }
.serialize = [](std::vector<char>& out) -> void { void c_serialize(std::vector<char>& out) {
if(!internal_rom) if(!internal_rom)
throw std::runtime_error("Can't save without ROM"); throw std::runtime_error("Can't save without ROM");
instance->saveState(out); instance->saveState(out);
@ -332,8 +319,8 @@ namespace
write32ube(&out[osize + 4 * i], primary_framebuffer[i]); write32ube(&out[osize + 4 * i], primary_framebuffer[i]);
out.push_back(frame_overflow >> 8); out.push_back(frame_overflow >> 8);
out.push_back(frame_overflow); out.push_back(frame_overflow);
}, }
.unserialize = [](const char* in, size_t insize) -> void { void c_unserialize(const char* in, size_t insize) {
if(!internal_rom) if(!internal_rom)
throw std::runtime_error("Can't load without ROM"); throw std::runtime_error("Can't load without ROM");
size_t foffset = insize - 2 - 4 * sizeof(primary_framebuffer) / size_t foffset = insize - 2 - 4 * sizeof(primary_framebuffer) /
@ -349,16 +336,16 @@ namespace
unsigned x2 = (unsigned char)in[insize - 1]; unsigned x2 = (unsigned char)in[insize - 1];
frame_overflow = x1 * 256 + x2; frame_overflow = x1 * 256 + x2;
do_reset_flag = false; do_reset_flag = false;
}, }
.get_region = []() -> core_region& { return region_world; }, core_region& c_get_region() { return *this; }
.power = []() -> void {}, void c_power() {}
.unload_cartridge = []() -> void {}, void c_unload_cartridge() {}
.get_scale_factors = [](uint32_t width, uint32_t height) -> std::pair<uint32_t, uint32_t> { std::pair<uint32_t, uint32_t> c_get_scale_factors(uint32_t width, uint32_t height) {
return std::make_pair(max(512 / width, (uint32_t)1), max(448 / height, (uint32_t)1)); return std::make_pair(max(512 / width, (uint32_t)1), max(448 / height, (uint32_t)1));
}, }
.install_handler = []() -> void { magic_flags |= 2; }, void c_install_handler() { magic_flags |= 2; }
.uninstall_handler = []() -> void {}, void c_uninstall_handler() {}
.emulate = []() -> void { void c_emulate() {
if(!internal_rom) if(!internal_rom)
return; return;
int16_t reset = ecore_callbacks->get_input(0, 0, 1); int16_t reset = ecore_callbacks->get_input(0, 0, 1);
@ -412,61 +399,129 @@ namespace
framebuffer_raw ls(inf); framebuffer_raw ls(inf);
ecore_callbacks->output_frame(ls, 262144, 4389); ecore_callbacks->output_frame(ls, 262144, 4389);
}, }
.runtosave = []() -> void {}, void c_runtosave() {}
.get_pflag = []() -> bool { return pflag; }, bool c_get_pflag() { return pflag; }
.set_pflag = [](bool _pflag) -> void { pflag = _pflag; }, void c_set_pflag(bool _pflag) { pflag = _pflag; }
.port_types = port_types, framebuffer_raw& c_draw_cover() {
.draw_cover = []() -> framebuffer_raw& {
static framebuffer_raw x(cover_fbinfo); static framebuffer_raw x(cover_fbinfo);
redraw_cover_fbinfo(); redraw_cover_fbinfo();
return x; return x;
}, }
.get_core_shortname = []() -> std::string { return "gambatte"+gambatte::GB::version(); }, std::string c_get_core_shortname() { return "gambatte"+gambatte::GB::version(); }
.pre_emulate_frame = [](controller_frame& cf) -> void { void c_pre_emulate_frame(controller_frame& cf) {
cf.axis3(0, 0, 1, do_reset_flag ? 1 : 0); cf.axis3(0, 0, 1, do_reset_flag ? 1 : 0);
}, }
.execute_action = [](unsigned id, const std::vector<interface_action_paramval>& p) -> void void c_execute_action(unsigned id, const std::vector<interface_action_paramval>& p)
{ {
switch(id) { switch(id) {
case 0: //Soft reset. case 0: //Soft reset.
do_reset_flag = true; do_reset_flag = true;
break; break;
} }
}, }
.get_registers = []() -> const interface_device_reg* { return gb_registers; }, const interface_device_reg* c_get_registers() { return gb_registers; }
}}; } gambatte_core;
interface_action act_reset(gambatte_core, 0, "Soft reset", "reset", {});
core_type type_dmg{{
.iname = "dmg", .hname = "Game Boy", .id = 1, .sysname = "Gameboy", struct _type_dmg : public core_type, public core_sysregion
.load_rom = [](core_romimage* img, std::map<std::string, std::string>& settings, uint64_t rtc_sec, {
uint64_t rtc_subsec) -> int { _type_dmg() : core_type({{
return load_rom_common(img, gambatte::GB::FORCE_DMG, rtc_sec, rtc_subsec, &type_dmg); .iname = "dmg",
}, .hname = "Game Boy",
.controllerconfig = _controllerconfig, .extensions = "gb;dmg", .bios = NULL, .regions = dmg_regions, .id = 1,
.images = dmg_images, .settings = &gambatte_settings, .core = &gambatte_core, .sysname = "Gameboy",
.get_bus_map = gambatte_bus_map, .vma_list = get_VMAlist, .srams = srams .extensions = "gb;dmg",
}}; .bios = NULL,
core_type type_gbc{{ .regions = {&gambatte_core},
.iname = "gbc", .hname = "Game Boy Color", .id = 0, .sysname = "Gameboy", .images = dmg_images,
.load_rom = [](core_romimage* img, std::map<std::string, std::string>& settings, uint64_t rtc_sec, .settings = &gambatte_settings,
uint64_t rtc_subsec) -> int { .core = &gambatte_core,
return load_rom_common(img, 0, rtc_sec, rtc_subsec, &type_gbc); }}), core_sysregion("gdmg", *this, gambatte_core) {}
}, int t_load_rom(core_romimage* img, std::map<std::string, std::string>& settings,
.controllerconfig = _controllerconfig, .extensions = "gbc;cgb", .bios = NULL, .regions = gbc_regions, uint64_t secs, uint64_t subsecs)
.images = gbc_images, .settings = &gambatte_settings, .core = &gambatte_core, {
.get_bus_map = gambatte_bus_map, .vma_list = get_VMAlist, .srams = srams return load_rom_common(img, gambatte::GB::FORCE_DMG, secs, subsecs, this);
}}; }
core_type type_gbca{{ controller_set t_controllerconfig(std::map<std::string, std::string>& settings)
.iname = "gbc_gba", .hname = "Game Boy Color (GBA)", .id = 2, .sysname = "Gameboy", {
.load_rom = [](core_romimage* img, std::map<std::string, std::string>& settings, uint64_t rtc_sec, return gambatte_controllerconfig(settings);
uint64_t rtc_subsec) -> int { }
return load_rom_common(img, gambatte::GB::GBA_CGB, rtc_sec, rtc_subsec, &type_gbca); std::pair<uint64_t, uint64_t> t_get_bus_map() { return gambatte_bus_map(); }
}, std::list<core_vma_info> t_vma_list() { return get_VMAlist(); }
.controllerconfig = _controllerconfig, .extensions = "", .bios = NULL, .regions = gbca_regions, std::set<std::string> t_srams() { return gambatte_srams(); }
.images = gbca_images, .settings = &gambatte_settings, .core = &gambatte_core, } type_dmg;
.get_bus_map = gambatte_bus_map, .vma_list = get_VMAlist, .srams = srams
}}; struct _type_gbc : public core_type, public core_sysregion
{
_type_gbc() : core_type({{
.iname = "gbc",
.hname = "Game Boy Color",
.id = 0,
.sysname = "Gameboy",
.extensions = "gbc;cgb",
.bios = NULL,
.regions = {&gambatte_core},
.images = gbc_images,
.settings = &gambatte_settings,
.core = &gambatte_core,
}}), core_sysregion("ggbc", *this, gambatte_core) {}
int t_load_rom(core_romimage* img, std::map<std::string, std::string>& settings,
uint64_t secs, uint64_t subsecs)
{
return load_rom_common(img, 0, secs, subsecs, this);
}
controller_set t_controllerconfig(std::map<std::string, std::string>& settings)
{
return gambatte_controllerconfig(settings);
}
std::pair<uint64_t, uint64_t> t_get_bus_map() { return gambatte_bus_map(); }
std::list<core_vma_info> t_vma_list() { return get_VMAlist(); }
std::set<std::string> t_srams() { return gambatte_srams(); }
} type_gbc;
struct _type_gbca : public core_type, public core_sysregion
{
_type_gbca() : core_type({{
.iname = "gbc_gba",
.hname = "Game Boy Color (GBA)",
.id = 2,
.sysname = "Gameboy",
.extensions = "",
.bios = NULL,
.regions = {&gambatte_core},
.images = gbca_images,
.settings = &gambatte_settings,
.core = &gambatte_core,
}}), core_sysregion("ggbca", *this, gambatte_core) {}
int t_load_rom(core_romimage* img, std::map<std::string, std::string>& settings,
uint64_t secs, uint64_t subsecs)
{
return load_rom_common(img, gambatte::GB::GBA_CGB, secs, subsecs, this);
}
controller_set t_controllerconfig(std::map<std::string, std::string>& settings)
{
return gambatte_controllerconfig(settings);
}
std::pair<uint64_t, uint64_t> t_get_bus_map() { return gambatte_bus_map(); }
std::list<core_vma_info> t_vma_list() { return get_VMAlist(); }
std::set<std::string> t_srams() { return gambatte_srams(); }
} type_gbca;
void redraw_cover_fbinfo()
{
for(size_t i = 0; i < sizeof(cover_fbmem) / sizeof(cover_fbmem[0]); i++)
cover_fbmem[i] = 0x00000000;
std::string ident = gambatte_core.get_core_identifier();
cover_render_string(cover_fbmem, 0, 0, ident, 0xFFFFFF, 0x00000, 480, 432, 1920, 4);
cover_render_string(cover_fbmem, 0, 16, "Internal ROM name: " + get_cartridge_name(),
0xFFFFFF, 0x00000, 480, 432, 1920, 4);
unsigned y = 32;
for(auto i : cover_information()) {
cover_render_string(cover_fbmem, 0, y, i, 0xFFFFFF, 0x000000, 480, 432, 1920, 4);
y += 16;
}
}
std::vector<char> cmp_save; std::vector<char> cmp_save;

View file

@ -263,7 +263,7 @@ for i = 1,#ports do
print("\t}"); print("\t}");
print("} "..port.symbol..";"); print("} "..port.symbol..";");
end end
local s = "std::vector<port_type*> port_types{ "; local s = "std::vector<port_type*> _port_types{ ";
for i = 1,#ports do for i = 1,#ports do
s = s .."&"..ports[i].symbol..", "; s = s .."&"..ports[i].symbol..", ";
end end

View file

@ -217,7 +217,7 @@ namespace sky
controller_info = &X2; controller_info = &X2;
} }
} psystem; } psystem;
port_index_triple t(unsigned p, unsigned c, unsigned i, bool nl) port_index_triple t(unsigned p, unsigned c, unsigned i, bool nl)
{ {
port_index_triple x; port_index_triple x;
@ -228,56 +228,87 @@ namespace sky
return x; return x;
} }
void controller_magic()
{
if(magic_flags & 1) {
X2.controllers[1] = &A8;
cstyle = 1;
} else if(magic_flags & 2) {
X2.controllers[1] = &B8;
cstyle = 2;
} else if(magic_flags & 4) {
X2.controllers[1] = &C8;
cstyle = 2;
} else {
cstyle = 0;
}
}
struct core_setting_group sky_settings; struct core_setting_group sky_settings;
core_region world_region{{
.iname = "world", .hname = "World", .priority = 0, .handle = 0, .multi = false,
.framemagic = {656250, 18227}, .compatible_runs = {0, UINT_MAX}
}};
struct core_romimage_info skyzip{{"rom", "skyroads.zip", .mandatory = 1, .pass_mode = 1, .headersize = 0}}; struct core_romimage_info skyzip{{"rom", "skyroads.zip", .mandatory = 1, .pass_mode = 1, .headersize = 0}};
extern struct core_core sky_core; struct _sky_core : public core_core, public core_type, public core_region, public core_sysregion
{
struct core_core sky_core{{ _sky_core() : core_core({{{&psystem}}}), core_type({{
.core_identifier = []() -> std::string { return "Sky"; }, .iname = "sky",
.set_region = [](core_region& region) -> bool { return (&region == &world_region); }, .hname = "Sky",
.video_rate = []() -> std::pair<uint32_t, uint32_t> { return std::make_pair(656250, 18227); }, .id = 3522,
.audio_rate = []() -> std::pair<uint32_t, uint32_t> { return std::make_pair(48000, 1); }, .sysname = "Sky",
.save_sram = []() -> std::map<std::string, std::vector<char>> { .extensions = "sky",
.bios = NULL,
.regions = {this},
.images = {&skyzip},
.settings = &sky_settings,
.core = this,
}}), core_region({{
.iname = "world",
.hname = "World",
.priority = 0,
.handle = 0,
.multi = false,
.framemagic = {656250, 18227},
.compatible_runs = {0}
}}), core_sysregion("sky", *this, *this) {}
std::string c_core_identifier() { return "Sky"; }
bool c_set_region(core_region& region) { return (&region == this); }
std::pair<uint32_t, uint32_t> c_video_rate() { return std::make_pair(656250, 18227); }
std::pair<uint32_t, uint32_t> c_audio_rate() { return std::make_pair(48000, 1); }
std::map<std::string, std::vector<char>> c_save_sram() throw(std::bad_alloc) {
std::map<std::string, std::vector<char>> r; std::map<std::string, std::vector<char>> r;
std::vector<char> sram; std::vector<char> sram;
sram.resize(32); sram.resize(32);
memcpy(&sram[0], _gstate.sram, 32); memcpy(&sram[0], _gstate.sram, 32);
r["sram"] = sram; r["sram"] = sram;
return r; return r;
}, }
.load_sram = [](std::map<std::string, std::vector<char>>& sram) -> void { void c_load_sram(std::map<std::string, std::vector<char>>& sram) throw(std::bad_alloc) {
if(sram.count("sram") && sram["sram"].size() == 32) if(sram.count("sram") && sram["sram"].size() == 32)
memcpy(_gstate.sram, &sram["sram"][0], 32); memcpy(_gstate.sram, &sram["sram"][0], 32);
else else
memset(_gstate.sram, 0, 32); memset(_gstate.sram, 0, 32);
}, }
.serialize = [](std::vector<char>& out) -> void { void c_serialize(std::vector<char>& out) {
auto wram = _gstate.as_ram(); auto wram = _gstate.as_ram();
out.resize(wram.second); out.resize(wram.second);
memcpy(&out[0], wram.first, wram.second); memcpy(&out[0], wram.first, wram.second);
}, }
.unserialize =[](const char* in, size_t insize) -> void { void c_unserialize(const char* in, size_t insize) {
auto wram = _gstate.as_ram(); auto wram = _gstate.as_ram();
if(insize != wram.second) if(insize != wram.second)
throw std::runtime_error("Save is of wrong size"); throw std::runtime_error("Save is of wrong size");
memcpy(wram.first, in, wram.second); memcpy(wram.first, in, wram.second);
handle_loadstate(_gstate); handle_loadstate(_gstate);
}, }
.get_region = []() -> core_region& { return world_region; }, core_region& c_get_region() { return *this; }
.power = []() -> void {}, void c_power() {}
.unload_cartridge = []() -> void {}, void c_unload_cartridge() {}
.get_scale_factors = [](uint32_t w, uint32_t h) -> std::pair<uint32_t, uint32_t> { std::pair<uint32_t, uint32_t> c_get_scale_factors(uint32_t w, uint32_t h) {
return std::make_pair(FB_WIDTH / w, FB_HEIGHT / h); return std::make_pair(FB_WIDTH / w, FB_HEIGHT / h);
}, }
.install_handler = []() -> void { sky_core.hide(); }, void c_install_handler() { hide(); }
.uninstall_handler = []() -> void {}, void c_uninstall_handler() {}
.emulate = []() -> void { void c_emulate() {
static unsigned count[4]; static unsigned count[4];
static unsigned tcount[4] = {5, 7, 8, 25}; static unsigned tcount[4] = {5, 7, 8, 25};
uint16_t x = 0; uint16_t x = 0;
@ -318,41 +349,21 @@ namespace sky
audioapi_submit_buffer(sbuf, samples, true, 48000); audioapi_submit_buffer(sbuf, samples, true, 48000);
for(unsigned i = 0; i < samples; i++) for(unsigned i = 0; i < samples; i++)
information_dispatch::do_sample(sbuf[2 * i + 0], sbuf[2 * i + 1]); information_dispatch::do_sample(sbuf[2 * i + 0], sbuf[2 * i + 1]);
}, }
.runtosave = []() -> void {}, void c_runtosave() {}
.get_pflag = []() -> bool { return pflag; }, bool c_get_pflag() { return pflag; }
.set_pflag = [](bool _pflag) -> void { pflag = _pflag; }, void c_set_pflag(bool _pflag) { pflag = _pflag; }
.port_types = {&psystem}, framebuffer_raw& c_draw_cover() {
.draw_cover = []() -> framebuffer_raw& {
static framebuffer_raw x(cover_fbinfo); static framebuffer_raw x(cover_fbinfo);
return x; return x;
},
.get_core_shortname = []() -> std::string { return "sky"; },
.pre_emulate_frame = [](controller_frame& cf) -> void {},
.execute_action = [](unsigned id, const std::vector<interface_action_paramval>& p) -> void {},
.get_registers = []() -> const interface_device_reg* { return sky_registers; },
}};
void controller_magic()
{
if(magic_flags & 1) {
X2.controllers[1] = &A8;
cstyle = 1;
} else if(magic_flags & 2) {
X2.controllers[1] = &B8;
cstyle = 2;
} else if(magic_flags & 4) {
X2.controllers[1] = &C8;
cstyle = 2;
} else {
cstyle = 0;
} }
} std::string c_get_core_shortname() { return "sky"; }
void c_pre_emulate_frame(controller_frame& cf) {}
core_type skytype{{ void c_execute_action(unsigned id, const std::vector<interface_action_paramval>& p) {}
.iname = "sky", .hname = "Sky", .id = 3522, .sysname = "Sky", const interface_device_reg* c_get_registers() { return sky_registers; }
.load_rom = [](core_romimage* images, std::map<std::string, std::string>& settings, uint64_t rtc_sec, int t_load_rom(core_romimage* images, std::map<std::string, std::string>& settings,
uint64_t rtc_subsec) -> int { uint64_t rtc_sec, uint64_t rtc_subsec)
{
controller_magic(); controller_magic();
const unsigned char* _filename = images[0].data; const unsigned char* _filename = images[0].data;
size_t size = images[0].size; size_t size = images[0].size;
@ -366,8 +377,8 @@ namespace sky
rom_boot_vector(_gstate); rom_boot_vector(_gstate);
ecore_callbacks->set_reset_actions(-1, -1); ecore_callbacks->set_reset_actions(-1, -1);
return 0; return 0;
}, }
.controllerconfig = [](std::map<std::string, std::string>& settings) -> controller_set controller_set t_controllerconfig(std::map<std::string, std::string>& settings)
{ {
controller_magic(); controller_magic();
controller_set r; controller_set r;
@ -378,13 +389,11 @@ namespace sky
r.portindex.logical_map.push_back(std::make_pair(0, 1)); r.portindex.logical_map.push_back(std::make_pair(0, 1));
r.portindex.pcid_map.push_back(std::make_pair(0, 1)); r.portindex.pcid_map.push_back(std::make_pair(0, 1));
return r; return r;
}, }
.extensions = "sky", .bios = NULL, .regions = {&world_region}, .images = {&skyzip}, std::pair<uint64_t, uint64_t> t_get_bus_map() { return std::make_pair(0, 0); }
.settings = &sky_settings, .core = &sky_core, std::list<core_vma_info> t_vma_list()
.get_bus_map = []() -> std::pair<uint64_t, uint64_t> { return std::make_pair(0, 0); }, {
.vma_list = []() -> std::list<core_vma_info> {
std::list<core_vma_info> r; std::list<core_vma_info> r;
core_vma_info ram; core_vma_info ram;
ram.name = "RAM"; ram.name = "RAM";
ram.backing_ram = _gstate.as_ram().first; ram.backing_ram = _gstate.as_ram().first;
@ -394,14 +403,13 @@ namespace sky
ram.endian = 0; ram.endian = 0;
ram.iospace_rw = NULL; ram.iospace_rw = NULL;
r.push_back(ram); r.push_back(ram);
return r; return r;
}, }
.srams = []() -> std::set<std::string> { std::set<std::string> t_srams()
{
std::set<std::string> r; std::set<std::string> r;
r.insert("sram"); r.insert("sram");
return r; return r;
} }
}}; } sky_core;
core_sysregion X24("sky", skytype, world_region);
} }

View file

@ -58,7 +58,6 @@ namespace
#include "ports.inc" #include "ports.inc"
#include "slots.inc" #include "slots.inc"
#include "regions.inc"
core_setting_group test_settings; core_setting_group test_settings;
@ -72,7 +71,7 @@ namespace
return x; return x;
} }
controller_set _controllerconfig(std::map<std::string, std::string>& settings) controller_set test_controllerconfig(std::map<std::string, std::string>& settings)
{ {
std::map<std::string, std::string> _settings = settings; std::map<std::string, std::string> _settings = settings;
controller_set r; controller_set r;
@ -125,29 +124,41 @@ namespace
} }
} }
extern core_core test_core; struct _test_core : public core_core, public core_type, public core_region, public core_sysregion
{
core_core test_core{{ _test_core() : core_core({{_port_types}}), core_type({{
.core_identifier = []() -> std::string { return "TEST"; }, .iname = "test",
.set_region = [](core_region& region) -> bool { return (&region == &region_world); }, .hname = "test",
.video_rate = []() -> std::pair<uint32_t, uint32_t> { return std::make_pair(60, 1); }, .id = 0,
.audio_rate = []() -> std::pair<uint32_t, uint32_t> { return std::make_pair(48000, 1); }, .sysname = "Test",
.save_sram = []() -> std::map<std::string, std::vector<char>> { .extensions = "test",
.bios = NULL,
.regions = {this},
.images = test_images,
.settings = &test_settings,
.core = this,
}}), core_region({{"world", "World", 0, 0, false, {1, 60}, {0}}}),
core_sysregion("test", *this, *this) {}
std::string c_core_identifier() { return "TEST"; }
bool c_set_region(core_region& region) { return (&region == this); }
std::pair<uint32_t, uint32_t> c_video_rate() { return std::make_pair(60, 1); }
std::pair<uint32_t, uint32_t> c_audio_rate() { return std::make_pair(48000, 1); }
std::map<std::string, std::vector<char>> c_save_sram() throw(std::bad_alloc) {
std::map<std::string, std::vector<char>> s; std::map<std::string, std::vector<char>> s;
return s; return s;
}, }
.load_sram = [](std::map<std::string, std::vector<char>>& sram) -> void {}, void c_load_sram(std::map<std::string, std::vector<char>>& sram) throw(std::bad_alloc) {}
.serialize = [](std::vector<char>& out) -> void { out.clear(); }, void c_serialize(std::vector<char>& out) { out.clear(); }
.unserialize = [](const char* in, size_t insize) -> void {}, void c_unserialize(const char* in, size_t insize) {}
.get_region = []() -> core_region& { return region_world; }, core_region& c_get_region() { return *this; }
.power = []() -> void {}, void c_power() {}
.unload_cartridge = []() -> void {}, void c_unload_cartridge() {}
.get_scale_factors = [](uint32_t width, uint32_t height) -> std::pair<uint32_t, uint32_t> { std::pair<uint32_t, uint32_t> c_get_scale_factors(uint32_t width, uint32_t height) {
return std::make_pair(max(512 / width, (uint32_t)1), max(448 / height, (uint32_t)1)); return std::make_pair(max(512 / width, (uint32_t)1), max(448 / height, (uint32_t)1));
}, }
.install_handler = []() -> void { test_core.hide(); }, void c_install_handler() { hide(); }
.uninstall_handler = []() -> void {}, void c_uninstall_handler() {}
.emulate = []() -> void { void c_emulate() {
pflag = false; pflag = false;
redraw_screen(); redraw_screen();
framebuffer_info inf; framebuffer_info inf;
@ -163,30 +174,31 @@ namespace
inf.offset_y = 0; inf.offset_y = 0;
framebuffer_raw ls(inf); framebuffer_raw ls(inf);
ecore_callbacks->output_frame(ls, 60,1); ecore_callbacks->output_frame(ls, 60,1);
}, }
.runtosave = []() -> void {}, void c_runtosave() {}
.get_pflag = []() -> bool { return pflag; }, bool c_get_pflag() { return pflag; }
.set_pflag = [](bool _pflag) -> void { pflag = _pflag; }, void c_set_pflag(bool _pflag) { pflag = _pflag; }
.port_types = port_types, framebuffer_raw& c_draw_cover() {
.draw_cover = []() -> framebuffer_raw& {
static framebuffer_raw x(cover_fbinfo); static framebuffer_raw x(cover_fbinfo);
redraw_cover_fbinfo(); redraw_cover_fbinfo();
return x; return x;
}, }
.get_core_shortname = []() -> std::string { return "test"; }, std::string c_get_core_shortname() { return "test"; }
.pre_emulate_frame = [](controller_frame& cf) -> void {}, void c_pre_emulate_frame(controller_frame& cf) {}
.execute_action = [](unsigned id, const std::vector<interface_action_paramval>& p) -> void {}, void c_execute_action(unsigned id, const std::vector<interface_action_paramval>& p) {}
.get_registers = []() -> const interface_device_reg* { return test_registers; }, const interface_device_reg* c_get_registers() { return test_registers; }
}}; int t_load_rom(core_romimage* images, std::map<std::string, std::string>& settings,
uint64_t rtc_sec, uint64_t rtc_subsec)
core_type type_test{{ {
.iname = "test", .hname = "test", .id = 0, .sysname = "Test", ecore_callbacks->set_reset_actions(-1, -1);
.load_rom = [](core_romimage* img, std::map<std::string, std::string>& settings, uint64_t rtc_sec, return 0;
uint64_t rtc_subsec) -> int { ecore_callbacks->set_reset_actions(-1, -1); return 0; }, }
.controllerconfig = _controllerconfig, .extensions = "test", .bios = NULL, .regions = test_regions, controller_set t_controllerconfig(std::map<std::string, std::string>& settings)
.images = test_images, .settings = &test_settings, .core = &test_core, {
.get_bus_map = []() -> std::pair<uint64_t, uint64_t> { return std::make_pair(0, 0); }, return test_controllerconfig(settings);
.vma_list = []() -> std::list<core_vma_info> { return std::list<core_vma_info>();}, }
.srams = []() -> std::set<std::string> { return std::set<std::string>();} std::pair<uint64_t, uint64_t> t_get_bus_map() { return std::make_pair(0, 0); }
}}; std::list<core_vma_info> t_vma_list() { return std::list<core_vma_info>(); }
std::set<std::string> t_srams() { return std::set<std::string>(); }
} test_core;
} }

View file

@ -151,11 +151,6 @@ core_type::core_type(const core_type_params& params)
hname = params.hname; hname = params.hname;
sysname = params.sysname; sysname = params.sysname;
id = params.id; id = params.id;
loadimg = params.load_rom;
_controllerconfig = params.controllerconfig;
_get_bus_map = params.get_bus_map;
_vma_list = params.vma_list;
_srams = params.srams;
core = params.core; core = params.core;
settings = params.settings; settings = params.settings;
if(params.bios) if(params.bios)
@ -245,7 +240,7 @@ core_region& core_type::get_preferred_region()
bool core_type::load(core_romimage* images, std::map<std::string, std::string>& settings, uint64_t rtc_sec, bool core_type::load(core_romimage* images, std::map<std::string, std::string>& settings, uint64_t rtc_sec,
uint64_t rtc_subsec) uint64_t rtc_subsec)
{ {
return (loadimg(images, settings, rtc_sec, rtc_subsec) >= 0); return (t_load_rom(images, settings, rtc_sec, rtc_subsec) >= 0);
} }
core_sysregion& core_type::combine_region(core_region& reg) core_sysregion& core_type::combine_region(core_region& reg)
@ -278,22 +273,22 @@ bool core_type::is_known_extension(const std::string& ext)
controller_set core_type::controllerconfig(std::map<std::string, std::string>& settings) controller_set core_type::controllerconfig(std::map<std::string, std::string>& settings)
{ {
return _controllerconfig(settings); return t_controllerconfig(settings);
} }
std::pair<uint64_t, uint64_t> core_type::get_bus_map() std::pair<uint64_t, uint64_t> core_type::get_bus_map()
{ {
return _get_bus_map(); return t_get_bus_map();
} }
std::list<core_vma_info> core_type::vma_list() std::list<core_vma_info> core_type::vma_list()
{ {
return _vma_list(); return t_vma_list();
} }
std::set<std::string> core_type::srams() std::set<std::string> core_type::srams()
{ {
return _srams(); return t_srams();
} }
core_sysregion::core_sysregion(const std::string& _name, core_type& _type, core_region& _region) core_sysregion::core_sysregion(const std::string& _name, core_type& _type, core_region& _region)
@ -342,38 +337,13 @@ void core_sysregion::fill_framerate_magic(uint64_t* magic)
core_core::core_core(const core_core_params& params) core_core::core_core(const core_core_params& params)
: param_register_proxy(*this) : param_register_proxy(*this)
{ {
_core_identifier = params.core_identifier;
_set_region = params.set_region;
_video_rate = params.video_rate;
_audio_rate = params.audio_rate;
_save_sram = params.save_sram;
_load_sram = params.load_sram;
_serialize = params.serialize;
_unserialize = params.unserialize;
_get_region = params.get_region;
_power = params.power;
_unload_cartridge = params.unload_cartridge;
_get_scale_factors = params.get_scale_factors;
_install_handler = params.install_handler;
_uninstall_handler = params.uninstall_handler;
_emulate = params.emulate;
_runtosave = params.runtosave;
_get_pflag = params.get_pflag;
_set_pflag = params.set_pflag;
port_types = params.port_types; port_types = params.port_types;
_draw_cover = params.draw_cover;
_get_core_shortname = params.get_core_shortname;
_pre_emulate_frame = params.pre_emulate_frame;
_execute_action = params.execute_action;
_get_registers = params.get_registers;
hidden = false; hidden = false;
all_cores_set().insert(this); all_cores_set().insert(this);
if(install_handlers_automatically) if(install_handlers_automatically)
install_handler(); install_handler();
new_core_flag = true; new_core_flag = true;
register_queue<core_core::_param_register_proxy, interface_action>::do_ready(param_register_proxy, true); register_queue<core_core::_param_register_proxy, interface_action>::do_ready(param_register_proxy, true);
if(!in_global_ctors())
messages << "Loaded core: " << _core_identifier() << std::endl;
} }
core_core::~core_core() throw() core_core::~core_core() throw()
@ -384,27 +354,27 @@ core_core::~core_core() throw()
std::string core_core::get_core_shortname() std::string core_core::get_core_shortname()
{ {
return _get_core_shortname(); return c_get_core_shortname();
} }
bool core_core::set_region(core_region& region) bool core_core::set_region(core_region& region)
{ {
return _set_region(region); return c_set_region(region);
} }
std::pair<uint32_t, uint32_t> core_core::get_video_rate() std::pair<uint32_t, uint32_t> core_core::get_video_rate()
{ {
return _video_rate(); return c_video_rate();
} }
std::pair<uint32_t, uint32_t> core_core::get_audio_rate() std::pair<uint32_t, uint32_t> core_core::get_audio_rate()
{ {
return _audio_rate(); return c_audio_rate();
} }
std::string core_core::get_core_identifier() std::string core_core::get_core_identifier()
{ {
return _core_identifier(); return c_core_identifier();
} }
std::set<core_core*> core_core::all_cores() std::set<core_core*> core_core::all_cores()
@ -428,92 +398,92 @@ void core_core::uninstall_all_handlers()
std::map<std::string, std::vector<char>> core_core::save_sram() throw(std::bad_alloc) std::map<std::string, std::vector<char>> core_core::save_sram() throw(std::bad_alloc)
{ {
return _save_sram(); return c_save_sram();
} }
void core_core::load_sram(std::map<std::string, std::vector<char>>& sram) throw(std::bad_alloc) void core_core::load_sram(std::map<std::string, std::vector<char>>& sram) throw(std::bad_alloc)
{ {
_load_sram(sram); c_load_sram(sram);
} }
void core_core::serialize(std::vector<char>& out) void core_core::serialize(std::vector<char>& out)
{ {
_serialize(out); c_serialize(out);
} }
void core_core::unserialize(const char* in, size_t insize) void core_core::unserialize(const char* in, size_t insize)
{ {
_unserialize(in, insize); c_unserialize(in, insize);
} }
core_region& core_core::get_region() core_region& core_core::get_region()
{ {
return _get_region(); return c_get_region();
} }
void core_core::power() void core_core::power()
{ {
_power(); c_power();
} }
void core_core::unload_cartridge() void core_core::unload_cartridge()
{ {
_unload_cartridge(); c_unload_cartridge();
} }
std::pair<uint32_t, uint32_t> core_core::get_scale_factors(uint32_t width, uint32_t height) std::pair<uint32_t, uint32_t> core_core::get_scale_factors(uint32_t width, uint32_t height)
{ {
return _get_scale_factors(width, height); return c_get_scale_factors(width, height);
} }
void core_core::install_handler() void core_core::install_handler()
{ {
_install_handler(); c_install_handler();
} }
void core_core::uninstall_handler() void core_core::uninstall_handler()
{ {
_uninstall_handler(); c_uninstall_handler();
} }
void core_core::emulate() void core_core::emulate()
{ {
_emulate(); c_emulate();
} }
void core_core::runtosave() void core_core::runtosave()
{ {
_runtosave(); c_runtosave();
} }
bool core_core::get_pflag() bool core_core::get_pflag()
{ {
return _get_pflag(); return c_get_pflag();
} }
void core_core::set_pflag(bool pflag) void core_core::set_pflag(bool pflag)
{ {
return _set_pflag(pflag); return c_set_pflag(pflag);
} }
framebuffer_raw& core_core::draw_cover() framebuffer_raw& core_core::draw_cover()
{ {
return _draw_cover(); return c_draw_cover();
} }
void core_core::pre_emulate_frame(controller_frame& cf) void core_core::pre_emulate_frame(controller_frame& cf)
{ {
_pre_emulate_frame(cf); c_pre_emulate_frame(cf);
} }
void core_core::execute_action(unsigned id, const std::vector<interface_action_paramval>& p) void core_core::execute_action(unsigned id, const std::vector<interface_action_paramval>& p)
{ {
return _execute_action(id, p); return c_execute_action(id, p);
} }
const struct interface_device_reg* core_core::get_registers() const struct interface_device_reg* core_core::get_registers()
{ {
return _get_registers(); return c_get_registers();
} }
void core_core::do_register_action(const std::string& key, interface_action& act) void core_core::do_register_action(const std::string& key, interface_action& act)