Refactor some generic reading/writing routines out of moviefile.cpp
[lsnes.git] / src / interface / romtype.cpp
blob78f4e37d523f227c22838888a3249f6cfef8b460
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 "library/register-queue.hpp"
7 #include <set>
8 #include <map>
9 #include <string>
10 #include <algorithm>
11 #include <cctype>
12 #include <stdexcept>
13 #include <list>
14 #include <limits>
16 namespace
18 bool install_handlers_automatically;
20 std::map<std::string, std::string>& sysreg_mapping()
22 static std::map<std::string, std::string> x;
23 return x;
26 std::set<core_core*>& all_cores_set()
28 static std::set<core_core*> x;
29 return x;
32 std::set<core_core*>& uninitialized_cores_set()
34 static std::set<core_core*> x;
35 return x;
38 std::multimap<std::string, core_sysregion*>& sysregions()
40 static std::multimap<std::string, core_sysregion*> x;
41 return x;
44 std::set<core_type*>& types()
46 static std::set<core_type*> x;
47 return x;
50 bool compare_coretype(core_type* a, core_type* b)
52 return (a->get_id() < b->get_id());
55 bool compare_regions(core_region* a, core_region* b)
57 return (a->get_handle() < b->get_handle());
60 unsigned default_headersize(size_t imagesize)
62 return 0;
66 bool interface_action::is_toggle() const
68 for(auto i : params)
69 if(!strcmp(i.model, "toggle"))
70 return true;
71 return false;
74 core_region::core_region(const core_region_params& params)
76 iname = params.iname;
77 hname = params.hname;
78 multi = params.multi;
79 handle = params.handle;
80 priority = params.priority;
81 magic[0] = params.framemagic[0];
82 magic[1] = params.framemagic[1];
83 magic[2] = 1000000000 * params.framemagic[0] / params.framemagic[1];
84 magic[3] = 1000000000 * params.framemagic[0] % params.framemagic[1];
85 compatible = params.compatible_runs;
89 bool core_region::compatible_with(core_region& run)
91 for(auto i : compatible)
92 if(i == run.handle)
93 return true;
94 return false;
97 bool core_region::is_multi()
99 return multi;
102 const std::string& core_region::get_iname()
104 return iname;
107 const std::string& core_region::get_hname()
109 return hname;
112 unsigned core_region::get_priority()
114 return priority;
117 unsigned core_region:: get_handle()
119 return handle;
122 void core_region::fill_framerate_magic(uint64_t* _magic)
124 for(size_t i = 0; i < 4; i++)
125 _magic[i] = magic[i];
128 double core_region::approx_framerate()
130 return (double)magic[1] / magic[0];
133 core_romimage_info::core_romimage_info(const core_romimage_info_params& params)
135 iname = params.iname;
136 hname = params.hname;
137 mandatory = params.mandatory;
138 pass_mode = params.pass_mode;
139 headersize = params.headersize;
140 if(params.extensions) {
141 std::string tmp = params.extensions;
142 for(auto& ext : token_iterator_foreach(tmp, {";"}))
143 extensions.insert(ext);
147 size_t core_romimage_info::get_headnersize(size_t imagesize)
149 if(headersize && imagesize % (2 * headersize) == headersize)
150 return headersize;
151 return 0;
154 core_type::core_type(const core_type_params& params)
155 : settings(params.settings)
157 iname = params.iname;
158 hname = params.hname;
159 sysname = params.sysname;
160 id = params.id;
161 core = params.core;
162 if(params.bios)
163 biosname = params.bios;
164 for(auto i : params.regions)
165 regions.push_back(i);
166 imageinfo = params.images.get();
167 types().insert(this);
170 core_type::~core_type() throw()
172 types().erase(this);
175 unsigned core_type::get_id()
177 return id;
180 const std::string& core_type::get_iname()
182 return iname;
185 const std::string& core_type::get_hname()
187 return hname;
190 unsigned core_type::get_image_count()
192 return imageinfo.size();
195 core_setting_group& core_type::get_settings()
197 return settings;
200 core_romimage_info core_type::get_image_info(unsigned index)
202 if(index >= imageinfo.size())
203 throw std::runtime_error("Requested invalid image index");
204 return imageinfo[index];
207 std::list<core_type*> core_type::get_core_types()
209 std::list<core_type*> ret;
210 for(auto i : types())
211 ret.push_back(i);
212 ret.sort(compare_coretype);
213 return ret;
216 std::list<core_region*> core_type::get_regions()
218 std::list<core_region*> ret = regions;
219 ret.sort(compare_regions);
220 return ret;
223 core_region& core_type::get_preferred_region()
225 core_region* p = NULL;
226 unsigned cutoff = 0;
227 for(auto i : regions) {
228 unsigned pri = i->get_priority();
229 if(pri >= cutoff) {
230 cutoff = max(pri + 1, pri);
231 p = i;
234 return *p;
237 bool core_type::load(core_romimage* images, std::map<std::string, std::string>& settings, uint64_t rtc_sec,
238 uint64_t rtc_subsec)
240 return (t_load_rom(images, settings, rtc_sec, rtc_subsec) >= 0);
243 core_sysregion& core_type::combine_region(core_region& reg)
245 for(auto i : sysregions())
246 if(&(i.second->get_type()) == this && &(i.second->get_region()) == &reg)
247 return *(i.second);
248 throw std::runtime_error("Invalid region for system type");
251 std::list<std::string> core_type::get_extensions()
253 static std::list<std::string> empty;
254 unsigned base = (biosname != "") ? 1 : 0;
255 if(imageinfo.size() <= base)
256 return empty;
257 auto s = imageinfo[base].extensions;
258 std::list<std::string> ret;
259 for(auto i : s)
260 ret.push_back(i);
261 return ret;
264 std::string core_type::get_biosname()
266 return biosname;
269 bool core_type::is_known_extension(const std::string& ext)
271 std::string _ext = ext;
272 std::transform(_ext.begin(), _ext.end(), _ext.begin(), ::tolower);
273 for(auto i : get_extensions())
274 if(i == _ext)
275 return true;
276 return false;
279 controller_set core_type::controllerconfig(std::map<std::string, std::string>& settings)
281 return t_controllerconfig(settings);
284 std::pair<uint64_t, uint64_t> core_core::get_bus_map()
286 return c_get_bus_map();
289 double core_core::get_PAR()
291 return c_get_PAR();
294 std::list<core_vma_info> core_core::vma_list()
296 return c_vma_list();
299 std::set<std::string> core_core::srams()
301 return c_srams();
304 bool core_core::isnull()
306 return c_isnull();
309 std::pair<unsigned, unsigned> core_core::lightgun_scale()
311 return c_lightgun_scale();
314 std::pair<unsigned, unsigned> core_core::c_lightgun_scale()
316 return std::make_pair(0, 0);
319 void core_core::debug_reset()
321 return c_debug_reset();
324 bool core_core::c_isnull()
326 return false;
329 core_sysregion::core_sysregion(const std::string& _name, core_type& _type, core_region& _region)
330 : name(_name), type(_type), region(_region)
332 sysregions().insert(std::make_pair(_name, this));
335 core_sysregion::~core_sysregion() throw()
337 for(auto i = sysregions().begin(); i != sysregions().end(); i++)
338 if(i->second == this) {
339 sysregions().erase(i);
340 break;
344 core_sysregion& core_type::lookup_sysregion(const std::string& sysreg)
346 for(auto i : sysregions())
347 if(i.first == sysreg && &i.second->get_type() == this)
348 return *i.second;
349 throw std::runtime_error("Bad system-region type");
352 const std::string& core_sysregion::get_name()
354 return name;
357 core_region& core_sysregion::get_region()
359 return region;
362 core_type& core_sysregion::get_type()
364 return type;
367 void core_sysregion::fill_framerate_magic(uint64_t* magic)
369 region.fill_framerate_magic(magic);
372 core_core::core_core(std::initializer_list<port_type*> ports, std::initializer_list<interface_action> x_actions)
374 for(auto i : ports)
375 port_types.push_back(i);
376 for(auto i : x_actions)
377 actions[i._symbol] = i;
379 hidden = false;
380 uninitialized_cores_set().insert(this);
381 all_cores_set().insert(this);
382 new_core_flag = true;
385 core_core::~core_core() throw()
387 all_cores().erase(this);
390 void core_core::initialize_new_cores()
392 for(auto i : uninitialized_cores_set())
393 i->install_handler();
394 uninitialized_cores_set().clear();
397 std::string core_core::get_core_shortname()
399 return c_get_core_shortname();
402 bool core_core::set_region(core_region& region)
404 return c_set_region(region);
407 std::pair<uint32_t, uint32_t> core_core::get_video_rate()
409 return c_video_rate();
412 std::pair<uint32_t, uint32_t> core_core::get_audio_rate()
414 return c_audio_rate();
417 std::string core_core::get_core_identifier()
419 return c_core_identifier();
422 std::set<core_core*> core_core::all_cores()
424 return all_cores_set();
427 void core_core::install_all_handlers()
429 install_handlers_automatically = true;
430 for(auto i : all_cores_set())
431 i->install_handler();
434 void core_core::uninstall_all_handlers()
436 install_handlers_automatically = false;
437 for(auto i : all_cores_set())
438 i->uninstall_handler();
441 std::map<std::string, std::vector<char>> core_core::save_sram() throw(std::bad_alloc)
443 return c_save_sram();
446 void core_core::load_sram(std::map<std::string, std::vector<char>>& sram) throw(std::bad_alloc)
448 c_load_sram(sram);
451 void core_core::serialize(std::vector<char>& out)
453 c_serialize(out);
456 void core_core::unserialize(const char* in, size_t insize)
458 c_unserialize(in, insize);
461 core_region& core_core::get_region()
463 return c_get_region();
466 void core_core::power()
468 c_power();
471 void core_core::unload_cartridge()
473 c_unload_cartridge();
476 std::pair<uint32_t, uint32_t> core_core::get_scale_factors(uint32_t width, uint32_t height)
478 return c_get_scale_factors(width, height);
481 void core_core::install_handler()
483 c_install_handler();
486 void core_core::uninstall_handler()
488 c_uninstall_handler();
491 void core_core::emulate()
493 c_emulate();
496 void core_core::runtosave()
498 c_runtosave();
501 bool core_core::get_pflag()
503 return c_get_pflag();
506 void core_core::set_pflag(bool pflag)
508 return c_set_pflag(pflag);
511 framebuffer::raw& core_core::draw_cover()
513 return c_draw_cover();
516 void core_core::pre_emulate_frame(controller_frame& cf)
518 c_pre_emulate_frame(cf);
521 void core_core::execute_action(unsigned id, const std::vector<interface_action_paramval>& p)
523 return c_execute_action(id, p);
526 const struct interface_device_reg* core_core::get_registers()
528 return c_get_registers();
531 unsigned core_core::action_flags(unsigned id)
533 return c_action_flags(id);
536 std::set<const interface_action*> core_core::get_actions()
538 umutex_class h(actions_lock);
539 std::set<const interface_action*> r;
540 for(auto& i : actions)
541 r.insert(&i.second);
542 return r;
545 int core_core::reset_action(bool hard)
547 return c_reset_action(hard);
550 void core_core::set_debug_flags(uint64_t addr, unsigned flags_set, unsigned flags_clear)
552 return c_set_debug_flags(addr, flags_set, flags_clear);
555 void core_core::set_cheat(uint64_t addr, uint64_t value, bool set)
557 return c_set_cheat(addr, value, set);
560 std::vector<std::string> core_core::get_trace_cpus()
562 return c_get_trace_cpus();
565 emucore_callbacks::~emucore_callbacks() throw()
569 core_romimage_info_collection::core_romimage_info_collection(std::initializer_list<core_romimage_info_params> idata)
571 for(auto i : idata)
572 data.push_back(core_romimage_info(i));
575 std::set<core_sysregion*> core_sysregion::find_matching(const std::string& name)
577 std::set<core_sysregion*> ret;
578 auto u = sysregions().upper_bound(name);
579 for(auto i = sysregions().lower_bound(name); i != u; ++i)
580 ret.insert(i->second);
581 return ret;
584 void register_sysregion_mapping(std::string from, std::string to)
586 sysreg_mapping()[from] = to;
589 std::string lookup_sysregion_mapping(std::string from)
591 if(sysreg_mapping().count(from))
592 return sysreg_mapping()[from];
593 else
594 return "";
597 struct emucore_callbacks* ecore_callbacks;
599 bool new_core_flag = false;
600 uint32_t magic_flags = 0;