3 #include "core/advdumper.hpp"
4 #include "core/dispatch.hpp"
5 #include "core/framerate.hpp"
6 #include "core/instance.hpp"
7 #include "core/memorymanip.hpp"
8 #include "core/messages.hpp"
9 #include "core/rom.hpp"
10 #include "core/settings.hpp"
11 #include "core/window.hpp"
12 #include "interface/callbacks.hpp"
13 #include "interface/cover.hpp"
14 #include "interface/romtype.hpp"
15 #include "library/portctrl-data.hpp"
16 #include "library/fileimage-patch.hpp"
17 #include "library/framebuffer-pixfmt-rgb16.hpp"
18 #include "library/sha256.hpp"
19 #include "library/string.hpp"
20 #include "library/zip.hpp"
27 #include <boost/iostreams/categories.hpp>
28 #include <boost/iostreams/copy.hpp>
29 #include <boost/iostreams/stream.hpp>
30 #include <boost/iostreams/stream_buffer.hpp>
31 #include <boost/iostreams/filter/symmetric.hpp>
32 #include <boost/iostreams/filter/zlib.hpp>
33 #include <boost/iostreams/filtering_stream.hpp>
34 #include <boost/iostreams/device/back_inserter.hpp>
36 #ifdef USE_LIBGCRYPT_SHA256
42 uint16_t null_cover_fbmem
[512 * 448];
44 settingvar::supervariable
<settingvar::model_bool
<settingvar::yes_no
>> savestate_no_check(lsnes_setgrp
,
45 "dont-check-savestate", "Movie‣Loading‣Don't check savestates", false);
48 struct framebuffer::info null_fbinfo
= {
49 &framebuffer::pixfmt_bgr16
, //Format.
50 (char*)null_cover_fbmem
, //Memory.
51 512, 448, 1024, //Physical size.
52 512, 448, 1024, //Logical size.
56 struct interface_device_reg null_registers
[] = {
60 struct _core_null
: public core_core
, public core_type
, public core_region
, public core_sysregion
62 _core_null() : core_core({}, {}), core_type({{
72 }}), core_region({{"null", "(null)", 0, 0, false, {1, 60}, {0}}}),
73 core_sysregion("null", *this, *this) { hide(); }
74 std::string
c_core_identifier() { return "null core"; }
75 bool c_set_region(core_region
& reg
) { return true; }
76 std::pair
<unsigned, unsigned> c_video_rate() { return std::make_pair(60, 1); }
77 double c_get_PAR() { return 1.0; }
78 std::pair
<unsigned, unsigned> c_audio_rate() { return std::make_pair(48000, 1); }
79 std::map
<std::string
, std::vector
<char>> c_save_sram() throw (std::bad_alloc
) {
80 std::map
<std::string
, std::vector
<char>> x
;
83 void c_load_sram(std::map
<std::string
, std::vector
<char>>& sram
) throw (std::bad_alloc
) {}
84 void c_serialize(std::vector
<char>& out
) { out
.clear(); }
85 void c_unserialize(const char* in
, size_t insize
) {}
86 core_region
& c_get_region() { return *this; }
88 void c_unload_cartridge() {}
89 std::pair
<uint32_t, uint32_t> c_get_scale_factors(uint32_t width
, uint32_t height
) {
90 return std::make_pair(1, 1);
92 void c_install_handler() {}
93 void c_uninstall_handler() {}
96 bool c_get_pflag() { return false; }
97 void c_set_pflag(bool pflag
) {}
98 framebuffer::raw
& c_draw_cover() {
99 static framebuffer::raw
x(null_fbinfo
);
100 for(size_t i
= 0; i
< sizeof(null_cover_fbmem
)/sizeof(null_cover_fbmem
[0]); i
++)
101 null_cover_fbmem
[i
] = 0x0000;
102 std::string message
= "NO ROM LOADED";
103 cover_render_string(null_cover_fbmem
, 204, 220, message
, 0xFFFF, 0x0000, 512, 448, 1024, 2);
106 std::string
c_get_core_shortname() { return "null"; }
107 void c_pre_emulate_frame(portctrl::frame
& cf
) {}
108 void c_execute_action(unsigned id
, const std::vector
<interface_action_paramval
>& p
) {}
109 const interface_device_reg
* c_get_registers() { return null_registers
; }
110 int t_load_rom(core_romimage
* img
, std::map
<std::string
, std::string
>& settings
,
111 uint64_t secs
, uint64_t subsecs
)
115 controller_set
t_controllerconfig(std::map
<std::string
, std::string
>& settings
)
118 x
.ports
.push_back(&portctrl::get_default_system_port_type());
121 std::pair
<uint64_t, uint64_t> c_get_bus_map() { return std::make_pair(0ULL, 0ULL); }
122 std::list
<core_vma_info
> c_vma_list() { return std::list
<core_vma_info
>(); }
123 std::set
<std::string
> c_srams() { return std::set
<std::string
>(); }
124 unsigned c_action_flags(unsigned id
) { return 0; }
125 int c_reset_action(bool hard
) { return -1; }
126 bool c_isnull() { return true; }
127 void c_set_debug_flags(uint64_t addr
, unsigned int sflags
, unsigned int cflags
) {}
128 void c_set_cheat(uint64_t addr
, uint64_t value
, bool set
) {}
129 void c_debug_reset() {}
130 std::vector
<std::string
> c_get_trace_cpus()
132 return std::vector
<std::string
>();
136 core_type
* current_rom_type
= &core_null
;
137 core_region
* current_region
= &core_null
;
139 core_type
* prompt_core_fallback(const std::vector
<core_type
*>& choices
)
141 if(choices
.size() == 0)
143 if(choices
.size() == 1)
147 req
.core_guessed
= false;
149 //Tell that all ROMs have been correctly guessed, leaving only core select.
150 for(unsigned i
= 0; i
< ROM_SLOT_COUNT
; i
++) {
151 req
.has_slot
[i
] = false;
152 req
.guessed
[i
] = false;
154 req
.canceled
= false;
155 graphics_driver_request_rom(req
);
157 throw std::runtime_error("Canceled ROM loading");
158 if(req
.selected
< choices
.size())
159 return choices
[req
.selected
];
163 core_type
* find_core_by_extension(const std::string
& ext
, const std::string
& tmpprefer
)
165 std::string key
= "ext:" + ext
;
166 std::list
<core_type
*> possible
= core_type::get_core_types();
167 core_type
* preferred
= preferred_core
.count(key
) ? preferred_core
[key
] : NULL
;
168 std::vector
<core_type
*> fallbacks
;
169 //Tmpprefer overrides normal preferred core.
171 for(auto i
: possible
)
172 if(i
->get_core_identifier() == tmpprefer
)
174 for(auto i
: possible
)
175 if(i
->is_known_extension(ext
)) {
176 fallbacks
.push_back(i
);
180 core_type
* fallback
= prompt_core_fallback(fallbacks
);
181 if(!fallback
) throw std::runtime_error("No core available to load the ROM");
185 core_type
* find_core_by_name(const std::string
& name
, const std::string
& tmpprefer
)
187 std::string key
= "type:" + name
;
188 std::list
<core_type
*> possible
= core_type::get_core_types();
189 std::vector
<core_type
*> fallbacks
;
190 core_type
* preferred
= preferred_core
.count(key
) ? preferred_core
[key
] : NULL
;
191 //Tmpprefer overrides normal preferred core.
193 for(auto i
: possible
)
194 if(i
->get_iname() == tmpprefer
)
196 for(auto i
: possible
)
197 if(i
->get_iname() == name
) {
198 fallbacks
.push_back(i
);
202 core_type
* fallback
= prompt_core_fallback(fallbacks
);
203 if(!fallback
) throw std::runtime_error("No core available to load the ROM");
207 struct fileimage::image::info
get_xml_info()
209 fileimage::image::info i
;
210 i
.type
= fileimage::image::info::IT_MARKUP
;
215 struct fileimage::image::info
xlate_info(core_romimage_info ri
)
217 fileimage::image::info i
;
218 if(ri
.pass_mode
== 0) i
.type
= fileimage::image::info::IT_MEMORY
;
219 if(ri
.pass_mode
== 1) i
.type
= fileimage::image::info::IT_FILE
;
220 i
.headersize
= ri
.headersize
;
224 void record_files(loaded_rom
& rom
)
226 for(unsigned i
= 0; i
< ROM_SLOT_COUNT
; i
++) {
228 record_filehash(rom
.romimg
[i
].filename
, rom
.romimg
[i
].stripped
,
229 rom
.romimg
[i
].sha_256
.read());
232 record_filehash(rom
.romxml
[i
].filename
, rom
.romxml
[i
].stripped
,
233 rom
.romxml
[i
].sha_256
.read());
239 fileimage::hash lsnes_image_hasher
;
241 std::pair
<core_type
*, core_region
*> get_current_rom_info() throw()
243 return std::make_pair(current_rom_type
, current_region
);
246 loaded_rom::loaded_rom() throw()
249 region
= orig_region
= &core_null
;
252 loaded_rom::loaded_rom(const std::string
& file
, core_type
& ctype
) throw(std::bad_alloc
, std::runtime_error
)
255 region
= orig_region
= &rtype
->get_preferred_region();
258 unsigned pmand
= 0, tmand
= 0;
259 for(unsigned i
= 0; i
< ctype
.get_image_count(); i
++)
260 tmand
|= ctype
.get_image_info(i
).mandatory
;
261 if((bios
= ctype
.get_biosname()) != "") {
262 //This thing has a BIOS.
264 std::string basename
= CORE().setcache
->get("firmwarepath") + "/" + bios
;
265 romimg
[0] = fileimage::image(lsnes_image_hasher
, basename
, "", xlate_info(ctype
.get_image_info(0)));
266 if(zip::file_exists(basename
+ ".xml"))
267 romxml
[0] = fileimage::image(lsnes_image_hasher
, basename
+ ".xml", "", get_xml_info());
268 pmand
|= ctype
.get_image_info(0).mandatory
;
270 romimg
[romidx
] = fileimage::image(lsnes_image_hasher
, file
, "", xlate_info(ctype
.get_image_info(romidx
)));
271 if(zip::file_exists(file
+ ".xml"))
272 romxml
[romidx
] = fileimage::image(lsnes_image_hasher
, file
+ ".xml", "", get_xml_info());
273 pmand
|= ctype
.get_image_info(romidx
).mandatory
;
274 msu1_base
= zip::resolverel(file
, "");
277 throw std::runtime_error("Required ROM images missing");
281 loaded_rom::loaded_rom(const std::string
& file
, const std::string
& tmpprefer
) throw(std::bad_alloc
,
284 std::istream
& spec
= zip::openrel(file
, "");
286 std::getline(spec
, s
);
288 if(!spec
|| s
!= "[GAMEPACK FILE]") {
289 //This is a Raw ROM image.
291 std::string ext
= regex(".*\\.([^.]*)?", file
, "Can't read file extension")[1];
292 core_type
* coretype
= find_core_by_extension(ext
, tmpprefer
);
294 (stringfmt() << "Extension '" << ext
<< "' unknown").throwex();
296 region
= orig_region
= &rtype
->get_preferred_region();
299 unsigned pmand
= 0, tmand
= 0;
300 for(unsigned i
= 0; i
< rtype
->get_image_count(); i
++)
301 tmand
|= rtype
->get_image_info(i
).mandatory
;
302 if((bios
= coretype
->get_biosname()) != "") {
303 //This thing has a BIOS.
305 std::string basename
= CORE().setcache
->get("firmwarepath") + "/" + bios
;
306 romimg
[0] = fileimage::image(lsnes_image_hasher
, basename
, "",
307 xlate_info(coretype
->get_image_info(0)));
308 if(zip::file_exists(basename
+ ".xml"))
309 romxml
[0] = fileimage::image(lsnes_image_hasher
, basename
+ ".xml", "",
311 pmand
|= rtype
->get_image_info(0).mandatory
;
313 romimg
[romidx
] = fileimage::image(lsnes_image_hasher
, file
, "",
314 xlate_info(coretype
->get_image_info(romidx
)));
315 if(zip::file_exists(file
+ ".xml"))
316 romxml
[romidx
] = fileimage::image(lsnes_image_hasher
, file
+ ".xml", "", get_xml_info());
317 pmand
|= rtype
->get_image_info(romidx
).mandatory
;
318 msu1_base
= zip::resolverel(file
, "");
321 throw std::runtime_error("Required ROM images missing");
324 load_filename
= file
;
325 std::vector
<std::string
> lines
;
326 while(std::getline(spec
, s
))
327 lines
.push_back(strip_CR(s
));
328 std::string platname
= "";
329 std::string platreg
= "";
330 for(auto i
: lines
) {
332 if(tmp
= regex("type[ \t]+(.+)", i
))
334 if(tmp
= regex("region[ \t]+(.+)", i
))
339 rtype
= find_core_by_name(platname
, tmpprefer
);
341 (stringfmt() << "Not a valid system type '" << platname
<< "'").throwex();
344 bool goodreg
= false;
345 orig_region
= &rtype
->get_preferred_region();
346 for(auto i
: rtype
->get_regions())
347 if(i
->get_iname() == platreg
) {
351 if(!goodreg
&& platreg
!= "")
352 (stringfmt() << "Not a valid system region '" << platreg
<< "'").throwex();
353 region
= orig_region
;
356 std::string cromimg
[ROM_SLOT_COUNT
];
357 std::string cromxml
[ROM_SLOT_COUNT
];
358 for(auto i
: lines
) {
360 if(!(tmp
= regex("(rom|xml)[ \t]+([^ \t]+)[ \t]+(.*)", i
)))
362 size_t idxs
= rtype
->get_image_count();
364 for(size_t i
= 0; i
< idxs
; i
++)
365 if(rtype
->get_image_info(i
).iname
== tmp
[2])
368 (stringfmt() << "Not a valid ROM name '" << tmp
[2] << "'").throwex();
370 cromimg
[idx
] = tmp
[3];
372 cromxml
[idx
] = tmp
[3];
376 unsigned mask1
= 0, mask2
= 0;
377 for(size_t i
= 0; i
< rtype
->get_image_count(); i
++) {
378 auto ii
= rtype
->get_image_info(i
);
379 mask1
|= ii
.mandatory
;
381 mask2
|= ii
.mandatory
;
382 if(cromimg
[i
] == "" && cromxml
[i
] != "") {
383 messages
<< "WARNING: Slot " << ii
.iname
<< ": XML without ROM." << std::endl
;
388 throw std::runtime_error("Required ROM missing");
391 for(size_t i
= 0; i
< rtype
->get_image_count(); i
++) {
392 romimg
[i
] = fileimage::image(lsnes_image_hasher
, cromimg
[i
], file
,
393 xlate_info(rtype
->get_image_info(i
)));
394 romxml
[i
] = fileimage::image(lsnes_image_hasher
, cromxml
[i
], file
, get_xml_info());
396 record_files(*this); //Have to do this before patching.
399 for(auto i
: lines
) {
401 if(!(tmp
= regex("patch([+-][0-9]+)?[ \t]+([^ \t]+)[ \t]+(.*)", i
)))
403 size_t idxs
= rtype
->get_image_count();
405 for(size_t i
= 0; i
< idxs
; i
++)
406 if(rtype
->get_image_info(i
).iname
== tmp
[2])
409 (stringfmt() << "Not a valid ROM name '" << tmp
[2] << "'").throwex();
412 offset
= parse_value
<int32_t>(tmp
[1]);
413 romimg
[idx
].patch(zip::readrel(tmp
[3], file
), offset
);
418 msu1_base
= zip::resolverel(cromimg
[1], file
);
420 msu1_base
= zip::resolverel(cromimg
[0], file
);
425 bool filter_by_core(core_type
& ctype
, const std::string
& core
)
427 return (core
== "" || ctype
.get_core_identifier() == core
);
430 bool filter_by_type(core_type
& ctype
, const std::string
& type
)
432 return (type
== "" || ctype
.get_iname() == type
);
435 bool filter_by_region(core_type
& ctype
, const std::string
& region
)
439 for(auto i
: ctype
.get_regions())
440 if(i
->get_iname() == region
)
445 bool filter_by_extension(core_type
& ctype
, const std::string
& file
)
447 regex_results tmp
= regex(".*\\.([^.]*)", file
);
450 std::string ext
= tmp
[1];
451 return ctype
.is_known_extension(ext
);
454 bool filter_by_fileset(core_type
& ctype
, const std::string file
[ROM_SLOT_COUNT
])
456 uint32_t m
= 0, t
= 0;
457 for(unsigned i
= 0; i
< ROM_SLOT_COUNT
; i
++) {
458 if(i
>= ctype
.get_image_count() && file
[i
] != "")
460 auto s
= ctype
.get_image_info(i
);
468 core_region
* detect_region(core_type
* t
, const std::string
& region
)
470 core_region
* r
= NULL
;
471 for(auto i
: t
->get_regions())
472 if(i
->get_iname() == region
)
474 if(!r
&& region
!= "")
475 (stringfmt() << "Not a valid system region '" << region
<< "'").throwex();
476 if(!r
) r
= &t
->get_preferred_region(); //Default region.
481 loaded_rom::loaded_rom(const std::string
& file
, const std::string
& core
, const std::string
& type
,
482 const std::string
& _region
)
485 core_region
* r
= NULL
;
486 bool fullspec
= (core
!= "" && type
!= "");
487 for(auto i
: core_type::get_core_types()) {
488 if(!filter_by_core(*i
, core
))
490 if(!filter_by_type(*i
, type
))
492 if(!fullspec
&& !filter_by_region(*i
, _region
))
494 if(!fullspec
&& !filter_by_extension(*i
, file
))
498 if(!t
) throw std::runtime_error("No matching core found");
499 r
= detect_region(t
, _region
);
500 unsigned pmand
= 0, tmand
= 0;
501 for(unsigned i
= 0; i
< t
->get_image_count(); i
++)
502 tmand
|= t
->get_image_info(i
).mandatory
;
503 std::string bios
= t
->get_biosname();
504 unsigned romidx
= (bios
!= "") ? 1 : 0;
506 std::string basename
= CORE().setcache
->get("firmwarepath") + "/" + bios
;
507 romimg
[0] = fileimage::image(lsnes_image_hasher
, basename
, "", xlate_info(t
->get_image_info(0)));
508 if(zip::file_exists(basename
+ ".xml"))
509 romxml
[0] = fileimage::image(lsnes_image_hasher
, basename
+ ".xml", "", get_xml_info());
510 pmand
|= t
->get_image_info(0).mandatory
;
512 romimg
[romidx
] = fileimage::image(lsnes_image_hasher
, file
, "", xlate_info(t
->get_image_info(romidx
)));
513 if(zip::file_exists(file
+ ".xml"))
514 romxml
[romidx
] = fileimage::image(lsnes_image_hasher
, file
+ ".xml", "", get_xml_info());
515 pmand
|= t
->get_image_info(romidx
).mandatory
;
516 msu1_base
= zip::resolverel(file
, "");
519 throw std::runtime_error("Required ROM images missing");
521 orig_region
= region
= r
;
524 loaded_rom::loaded_rom(const std::string file
[ROM_SLOT_COUNT
], const std::string
& core
, const std::string
& type
,
525 const std::string
& _region
)
528 core_region
* r
= NULL
;
529 bool fullspec
= (core
!= "" && type
!= "");
530 for(auto i
: core_type::get_core_types()) {
531 if(!filter_by_core(*i
, core
)) {
534 if(!filter_by_type(*i
, type
)) {
537 if(!fullspec
&& !filter_by_region(*i
, _region
)) {
540 if(!fullspec
&& !filter_by_fileset(*i
, file
)) {
545 if(!t
) throw std::runtime_error("No matching core found");
546 r
= detect_region(t
, _region
);
547 std::string bios
= t
->get_biosname();
548 unsigned romidx
= (bios
!= "") ? 1 : 0;
549 unsigned pmand
= 0, tmand
= 0;
550 for(unsigned i
= 0; i
< 27; i
++) {
551 if(i
>= t
->get_image_count())
554 pmand
|= t
->get_image_info(i
).mandatory
;
555 tmand
|= t
->get_image_info(i
).mandatory
;
556 romimg
[i
] = fileimage::image(lsnes_image_hasher
, file
[i
], "", xlate_info(t
->get_image_info(i
)));
557 if(zip::file_exists(file
[i
] + ".xml"))
558 romxml
[i
] = fileimage::image(lsnes_image_hasher
, file
[i
] + ".xml", "", get_xml_info());
560 msu1_base
= zip::resolverel(file
[romidx
], "");
563 throw std::runtime_error("Required ROM images missing");
565 orig_region
= region
= r
;
568 void loaded_rom::load(std::map
<std::string
, std::string
>& settings
, uint64_t rtc_sec
, uint64_t rtc_subsec
)
569 throw(std::bad_alloc
, std::runtime_error
)
572 core_type
* old_type
= current_rom_type
;
573 core_core
* old_core
= current_rom_type
->get_core();
574 current_rom_type
= &core_null
;
575 if(!orig_region
&& rtype
!= &core_null
)
576 orig_region
= &rtype
->get_preferred_region();
578 region
= orig_region
;
579 if(rtype
&& !orig_region
->compatible_with(*region
))
580 throw std::runtime_error("Trying to force incompatible region");
581 if(rtype
&& !rtype
->set_region(*region
))
582 throw std::runtime_error("Trying to force unknown region");
584 core_romimage images
[ROM_SLOT_COUNT
];
585 for(size_t i
= 0; i
< ROM_SLOT_COUNT
; i
++) {
586 images
[i
].markup
= (const char*)romxml
[i
];
587 images
[i
].data
= (const unsigned char*)romimg
[i
];
588 images
[i
].size
= (size_t)romimg
[i
];
590 if(!rtype
->load(images
, settings
, rtc_sec
, rtc_subsec
))
591 throw std::runtime_error("Can't load cartridge ROM");
593 region
= &rtype
->get_region();
595 auto nominal_fps
= rtype
->get_video_rate();
596 auto nominal_hz
= rtype
->get_audio_rate();
597 core
.framerate
->set_nominal_framerate(1.0 * nominal_fps
.first
/ nominal_fps
.second
);
598 core
.mdumper
->on_rate_change(nominal_hz
.first
, nominal_hz
.second
);
600 current_rom_type
= rtype
;
601 current_region
= region
;
602 //If core changes, unload the cartridge.
603 if(old_core
!= current_rom_type
->get_core())
605 old_core
->debug_reset();
606 old_core
->unload_cartridge();
609 core
.dispatch
->core_changed(old_type
!= current_rom_type
);
612 std::map
<std::string
, std::vector
<char>> load_sram_commandline(const std::vector
<std::string
>& cmdline
)
613 throw(std::bad_alloc
, std::runtime_error
)
615 std::map
<std::string
, std::vector
<char>> ret
;
617 for(auto i
: cmdline
) {
618 if(opt
= regex("--continue=(.+)", i
)) {
619 zip::reader
r(opt
[1]);
621 auto sramname
= regex("sram\\.(.*)", j
);
624 std::istream
& x
= r
[j
];
626 std::vector
<char> out
;
627 boost::iostreams::back_insert_device
<std::vector
<char>> rd(out
);
628 boost::iostreams::copy(x
, rd
);
630 ret
[sramname
[1]] = out
;
637 } else if(opt
= regex("--sram-([^=]+)=(.+)", i
)) {
639 ret
[opt
[1]] = zip::readrel(opt
[2], "");
640 } catch(std::bad_alloc
& e
) {
642 } catch(std::runtime_error
& e
) {
643 throw std::runtime_error("Can't load SRAM '" + opt
[1] + "': " + e
.what());
650 std::vector
<char> loaded_rom::save_core_state(bool nochecksum
) throw(std::bad_alloc
, std::runtime_error
)
652 std::vector
<char> ret
;
653 rtype
->serialize(ret
);
656 size_t offset
= ret
.size();
657 unsigned char tmp
[32];
658 #ifdef USE_LIBGCRYPT_SHA256
659 gcry_md_hash_buffer(GCRY_MD_SHA256
, tmp
, &ret
[0], offset
);
661 sha256::hash(tmp
, ret
);
663 ret
.resize(offset
+ 32);
664 memcpy(&ret
[offset
], tmp
, 32);
668 void loaded_rom::load_core_state(const std::vector
<char>& buf
, bool nochecksum
) throw(std::runtime_error
)
671 rtype
->unserialize(&buf
[0], buf
.size());
676 throw std::runtime_error("Savestate corrupt");
677 if(!savestate_no_check(*CORE().settings
)) {
678 unsigned char tmp
[32];
679 #ifdef USE_LIBGCRYPT_SHA256
680 gcry_md_hash_buffer(GCRY_MD_SHA256
, tmp
, &buf
[0], buf
.size() - 32);
682 sha256::hash(tmp
, reinterpret_cast<const uint8_t*>(&buf
[0]), buf
.size() - 32);
684 if(memcmp(tmp
, &buf
[buf
.size() - 32], 32))
685 throw std::runtime_error("Savestate corrupt");
687 rtype
->unserialize(&buf
[0], buf
.size() - 32);
690 bool loaded_rom::is_gamepak(const std::string
& filename
) throw(std::bad_alloc
, std::runtime_error
)
692 std::istream
* spec
= NULL
;
694 spec
= &zip::openrel(filename
, "");
696 std::getline(*spec
, line
);
698 bool ret
= (line
== "[GAMEPACK FILE]");
707 void set_hasher_callback(std::function
<void(uint64_t, uint64_t)> cb
)
709 lsnes_image_hasher
.set_callback(cb
);
712 std::map
<std::string
, core_type
*> preferred_core
;