lsnes rr2-β24
[lsnes.git] / src / interface / romtype.cpp
blob89a25c2a29b66f73acf120f691bd4443071f255a
1 #include "core/misc.hpp"
2 #include "interface/romtype.hpp"
3 #include "interface/callbacks.hpp"
4 #include "library/minmax.hpp"
5 #include "library/string.hpp"
6 #include <set>
7 #include <map>
8 #include <string>
9 #include <algorithm>
10 #include <cctype>
11 #include <stdexcept>
12 #include <list>
13 #include <limits>
15 thread_local const loadlib::module* module_loading;
17 namespace
19 void mark_against_loading(const void* obj)
21 auto i = module_loading;
22 if(i) i->mark(obj);
23 auto j = loadlib::library::loading();
24 if(j) j->mark(obj);
27 bool install_handlers_automatically;
29 std::map<std::string, std::string>& sysreg_mapping()
31 static std::map<std::string, std::string> x;
32 return x;
35 std::set<core_core*>& all_cores_set()
37 static std::set<core_core*> x;
38 return x;
41 std::set<core_core*>& uninitialized_cores_set()
43 static std::set<core_core*> x;
44 return x;
47 std::multimap<std::string, core_sysregion*>& sysregions()
49 static std::multimap<std::string, core_sysregion*> x;
50 return x;
53 std::set<core_type*>& types()
55 static std::set<core_type*> x;
56 return x;
59 bool compare_coretype(core_type* a, core_type* b)
61 return (a->get_id() < b->get_id());
64 bool compare_regions(core_region* a, core_region* b)
66 return (a->get_handle() < b->get_handle());
70 bool interface_action::is_toggle() const
72 for(auto i : params)
73 if(!strcmp(i.model, "toggle"))
74 return true;
75 return false;
78 core_region::core_region(const core_region_params& params)
80 iname = params.iname;
81 hname = params.hname;
82 multi = params.multi;
83 handle = params.handle;
84 priority = params.priority;
85 magic[0] = params.framemagic[0];
86 magic[1] = params.framemagic[1];
87 magic[2] = 1000 * params.framemagic[0] / params.framemagic[1];
88 magic[3] = 1000 * params.framemagic[0] % params.framemagic[1];
89 compatible = params.compatible_runs;
93 bool core_region::compatible_with(core_region& run)
95 for(auto i : compatible)
96 if(i == run.handle)
97 return true;
98 return false;
101 bool core_region::is_multi()
103 return multi;
106 const std::string& core_region::get_iname()
108 return iname;
111 const std::string& core_region::get_hname()
113 return hname;
116 unsigned core_region::get_priority()
118 return priority;
121 unsigned core_region:: get_handle()
123 return handle;
126 void core_region::fill_framerate_magic(uint64_t* _magic)
128 for(size_t i = 0; i < 4; i++)
129 _magic[i] = magic[i];
132 double core_region::approx_framerate()
134 return (double)magic[1] / magic[0];
137 core_romimage_info::core_romimage_info(const core_romimage_info_params& params)
139 iname = params.iname;
140 hname = params.hname;
141 mandatory = params.mandatory;
142 pass_mode = params.pass_mode;
143 headersize = params.headersize;
144 if(params.extensions) {
145 std::string tmp = params.extensions;
146 for(auto& ext : token_iterator<char>::foreach(tmp, {";"}))
147 extensions.insert(ext);
151 size_t core_romimage_info::get_headnersize(size_t imagesize)
153 if(headersize && imagesize % (2 * headersize) == headersize)
154 return headersize;
155 return 0;
158 core_type::core_type(const core_type_params& params)
159 : settings(params.settings)
161 iname = params.iname;
162 hname = params.hname;
163 sysname = params.sysname;
164 id = params.id;
165 core = params.core;
166 if(params.bios)
167 biosname = params.bios;
168 for(auto i : params.regions)
169 regions.push_back(i);
170 imageinfo = params.images.get();
171 types().insert(this);
174 core_type::~core_type() throw()
176 types().erase(this);
179 unsigned core_type::get_id() const
181 return id;
184 const std::string& core_type::get_iname() const
186 return iname;
189 const std::string& core_type::get_hname() const
191 return hname;
194 unsigned core_type::get_image_count() const
196 return imageinfo.size();
199 core_setting_group& core_type::get_settings()
201 return settings;
204 core_romimage_info core_type::get_image_info(unsigned index) const
206 if(index >= imageinfo.size())
207 throw std::runtime_error("Requested invalid image index");
208 return imageinfo[index];
211 std::list<core_type*> core_type::get_core_types()
213 std::list<core_type*> ret;
214 for(auto i : types())
215 ret.push_back(i);
216 ret.sort(compare_coretype);
217 return ret;
220 std::list<core_region*> core_type::get_regions() const
222 std::list<core_region*> ret = regions;
223 ret.sort(compare_regions);
224 return ret;
227 core_region& core_type::get_preferred_region() const
229 core_region* p = NULL;
230 unsigned cutoff = 0;
231 for(auto i : regions) {
232 unsigned pri = i->get_priority();
233 if(pri >= cutoff) {
234 cutoff = max(pri + 1, pri);
235 p = i;
238 return *p;
241 bool core_type::load(core_romimage* images, std::map<std::string, std::string>& settings, uint64_t rtc_sec,
242 uint64_t rtc_subsec)
244 return (t_load_rom(images, settings, rtc_sec, rtc_subsec) >= 0);
247 core_sysregion& core_type::combine_region(core_region& reg) const
249 for(auto i : sysregions())
250 if(&(i.second->get_type()) == this && &(i.second->get_region()) == &reg)
251 return *(i.second);
252 throw std::runtime_error("Invalid region for system type");
255 std::list<std::string> core_type::get_extensions() const
257 static std::list<std::string> empty;
258 unsigned base = (biosname != "") ? 1 : 0;
259 if(imageinfo.size() <= base)
260 return empty;
261 auto s = imageinfo[base].extensions;
262 std::list<std::string> ret;
263 for(auto i : s)
264 ret.push_back(i);
265 return ret;
268 std::string core_type::get_biosname() const
270 return biosname;
273 bool core_type::is_known_extension(const std::string& ext) const
275 std::string _ext = ext;
276 std::transform(_ext.begin(), _ext.end(), _ext.begin(), ::tolower);
277 for(auto i : get_extensions())
278 if(i == _ext)
279 return true;
280 return false;
283 controller_set core_type::controllerconfig(std::map<std::string, std::string>& settings)
285 return t_controllerconfig(settings);
288 std::pair<uint64_t, uint64_t> core_core::get_bus_map()
290 return c_get_bus_map();
293 double core_core::get_PAR()
295 return c_get_PAR();
298 std::list<core_vma_info> core_core::vma_list()
300 return c_vma_list();
303 std::set<std::string> core_core::srams()
305 return c_srams();
308 bool core_core::isnull() const
310 return c_isnull();
313 std::pair<unsigned, unsigned> core_core::lightgun_scale()
315 return c_lightgun_scale();
318 std::pair<unsigned, unsigned> core_core::c_lightgun_scale()
320 return std::make_pair(0, 0);
323 void core_core::debug_reset()
325 return c_debug_reset();
328 bool core_core::c_isnull() const
330 return false;
333 core_sysregion::core_sysregion(const std::string& _name, core_type& _type, core_region& _region)
334 : name(_name), type(_type), region(_region)
336 sysregions().insert(std::make_pair(_name, this));
339 core_sysregion::~core_sysregion() throw()
341 for(auto i = sysregions().begin(); i != sysregions().end(); i++)
342 if(i->second == this) {
343 sysregions().erase(i);
344 break;
348 core_sysregion& core_type::lookup_sysregion(const std::string& sysreg) const
350 for(auto i : sysregions())
351 if(i.first == sysreg && &i.second->get_type() == this)
352 return *i.second;
353 throw std::runtime_error("Bad system-region type");
356 const std::string& core_sysregion::get_name() const
358 return name;
361 core_region& core_sysregion::get_region()
363 return region;
366 core_type& core_sysregion::get_type()
368 return type;
371 void core_sysregion::fill_framerate_magic(uint64_t* magic)
373 region.fill_framerate_magic(magic);
376 core_core::core_core(std::initializer_list<portctrl::type*> ports, std::initializer_list<interface_action> x_actions)
378 for(auto i : ports)
379 port_types.push_back(i);
380 for(auto i : x_actions)
381 actions[i._symbol] = i;
383 hidden = false;
384 uninitialized_cores_set().insert(this);
385 all_cores_set().insert(this);
386 new_core_flag = true;
387 mark_against_loading(this);
390 core_core::core_core(std::vector<portctrl::type*> ports, std::vector<interface_action> x_actions)
392 for(auto i : ports)
393 port_types.push_back(i);
394 for(auto i : x_actions)
395 actions[i._symbol] = i;
397 hidden = false;
398 uninitialized_cores_set().insert(this);
399 all_cores_set().insert(this);
400 new_core_flag = true;
401 mark_against_loading(this);
404 core_core::~core_core() throw()
406 all_cores().erase(this);
407 all_cores_set().erase(this);
410 void core_core::initialize_new_cores()
412 for(auto i : uninitialized_cores_set())
413 i->install_handler();
414 uninitialized_cores_set().clear();
417 std::string core_core::get_core_shortname() const
419 return c_get_core_shortname();
422 bool core_core::set_region(core_region& region)
424 return c_set_region(region);
427 std::pair<uint32_t, uint32_t> core_core::get_video_rate()
429 return c_video_rate();
432 std::pair<uint32_t, uint32_t> core_core::get_audio_rate()
434 return c_audio_rate();
437 std::string core_core::get_core_identifier() const
439 return c_core_identifier();
442 std::set<core_core*> core_core::all_cores()
444 return all_cores_set();
447 void core_core::install_all_handlers()
449 install_handlers_automatically = true;
450 for(auto i : all_cores_set())
451 i->install_handler();
454 void core_core::uninstall_all_handlers()
456 install_handlers_automatically = false;
457 for(auto i : all_cores_set())
458 i->uninstall_handler();
461 std::map<std::string, std::vector<char>> core_core::save_sram() throw(std::bad_alloc)
463 return c_save_sram();
466 void core_core::load_sram(std::map<std::string, std::vector<char>>& sram) throw(std::bad_alloc)
468 c_load_sram(sram);
471 void core_core::serialize(std::vector<char>& out)
473 c_serialize(out);
476 void core_core::unserialize(const char* in, size_t insize)
478 c_unserialize(in, insize);
481 core_region& core_core::get_region()
483 return c_get_region();
486 void core_core::power()
488 c_power();
491 void core_core::unload_cartridge()
493 c_unload_cartridge();
496 std::pair<uint32_t, uint32_t> core_core::get_scale_factors(uint32_t width, uint32_t height)
498 return c_get_scale_factors(width, height);
501 void core_core::install_handler()
503 c_install_handler();
506 void core_core::uninstall_handler()
508 c_uninstall_handler();
511 void core_core::emulate()
513 c_emulate();
516 void core_core::runtosave()
518 c_runtosave();
521 bool core_core::get_pflag()
523 return c_get_pflag();
526 void core_core::set_pflag(bool pflag)
528 return c_set_pflag(pflag);
531 framebuffer::raw& core_core::draw_cover()
533 return c_draw_cover();
536 void core_core::pre_emulate_frame(portctrl::frame& cf)
538 c_pre_emulate_frame(cf);
541 void core_core::execute_action(unsigned id, const std::vector<interface_action_paramval>& p)
543 return c_execute_action(id, p);
546 const struct interface_device_reg* core_core::get_registers()
548 return c_get_registers();
551 unsigned core_core::action_flags(unsigned id)
553 return c_action_flags(id);
556 std::set<const interface_action*> core_core::get_actions()
558 threads::alock h(actions_lock);
559 std::set<const interface_action*> r;
560 for(auto& i : actions)
561 r.insert(&i.second);
562 return r;
565 int core_core::reset_action(bool hard)
567 return c_reset_action(hard);
570 void core_core::set_debug_flags(uint64_t addr, unsigned flags_set, unsigned flags_clear)
572 return c_set_debug_flags(addr, flags_set, flags_clear);
575 void core_core::set_cheat(uint64_t addr, uint64_t value, bool set)
577 return c_set_cheat(addr, value, set);
580 std::vector<std::string> core_core::get_trace_cpus()
582 return c_get_trace_cpus();
585 emucore_callbacks::~emucore_callbacks() throw()
589 core_romimage_info_collection::core_romimage_info_collection()
593 core_romimage_info_collection::core_romimage_info_collection(std::initializer_list<core_romimage_info_params> idata)
595 for(auto i : idata)
596 data.push_back(core_romimage_info(i));
599 core_romimage_info_collection::core_romimage_info_collection(std::vector<core_romimage_info_params> idata)
601 for(auto i : idata)
602 data.push_back(core_romimage_info(i));
605 std::set<core_sysregion*> core_sysregion::find_matching(const std::string& name)
607 std::set<core_sysregion*> ret;
608 auto u = sysregions().upper_bound(name);
609 for(auto i = sysregions().lower_bound(name); i != u; ++i)
610 ret.insert(i->second);
611 return ret;
614 void register_sysregion_mapping(std::string from, std::string to)
616 sysreg_mapping()[from] = to;
619 std::string lookup_sysregion_mapping(std::string from)
621 if(sysreg_mapping().count(from))
622 return sysreg_mapping()[from];
623 else
624 return "";
627 struct emucore_callbacks* ecore_callbacks;
629 bool new_core_flag = false;
630 uint32_t magic_flags = 0;