3 #include "core/command.hpp"
4 #include "core/dispatch.hpp"
5 #include "core/framerate.hpp"
6 #include "core/mainloop.hpp"
7 #include "core/memorymanip.hpp"
8 #include "core/misc.hpp"
9 #include "core/rom.hpp"
10 #include "core/romguess.hpp"
11 #include "core/settings.hpp"
12 #include "core/window.hpp"
13 #include "interface/cover.hpp"
14 #include "interface/romtype.hpp"
15 #include "interface/callbacks.hpp"
16 #include "library/framebuffer-pixfmt-rgb16.hpp"
17 #include "library/controller-data.hpp"
18 #include "library/fileimage-patch.hpp"
19 #include "library/sha256.hpp"
20 #include "library/string.hpp"
21 #include "library/zip.hpp"
29 #include <boost/iostreams/categories.hpp>
30 #include <boost/iostreams/copy.hpp>
31 #include <boost/iostreams/stream.hpp>
32 #include <boost/iostreams/stream_buffer.hpp>
33 #include <boost/iostreams/filter/symmetric.hpp>
34 #include <boost/iostreams/filter/zlib.hpp>
35 #include <boost/iostreams/filtering_stream.hpp>
36 #include <boost/iostreams/device/back_inserter.hpp>
38 #ifdef USE_LIBGCRYPT_SHA256
44 uint16_t null_cover_fbmem
[512 * 448];
46 settingvar::variable
<settingvar::model_bool
<settingvar::yes_no
>> savestate_no_check(lsnes_vset
,
47 "dont-check-savestate", "Movie‣Loading‣Don't check savestates", false);
50 struct framebuffer::info null_fbinfo
= {
51 &framebuffer::pixfmt_bgr16
, //Format.
52 (char*)null_cover_fbmem
, //Memory.
53 512, 448, 1024, //Physical size.
54 512, 448, 1024, //Logical size.
58 struct interface_device_reg null_registers
[] = {
62 struct _core_null
: public core_core
, public core_type
, public core_region
, public core_sysregion
64 _core_null() : core_core({}, {}), core_type({{
74 }}), core_region({{"null", "(null)", 0, 0, false, {1, 60}, {0}}}),
75 core_sysregion("null", *this, *this) { hide(); }
76 std::string
c_core_identifier() { return "null core"; }
77 bool c_set_region(core_region
& reg
) { return true; }
78 std::pair
<unsigned, unsigned> c_video_rate() { return std::make_pair(60, 1); }
79 double c_get_PAR() { return 1.0; }
80 std::pair
<unsigned, unsigned> c_audio_rate() { return std::make_pair(48000, 1); }
81 std::map
<std::string
, std::vector
<char>> c_save_sram() throw (std::bad_alloc
) {
82 std::map
<std::string
, std::vector
<char>> x
;
85 void c_load_sram(std::map
<std::string
, std::vector
<char>>& sram
) throw (std::bad_alloc
) {}
86 void c_serialize(std::vector
<char>& out
) { out
.clear(); }
87 void c_unserialize(const char* in
, size_t insize
) {}
88 core_region
& c_get_region() { return *this; }
90 void c_unload_cartridge() {}
91 std::pair
<uint32_t, uint32_t> c_get_scale_factors(uint32_t width
, uint32_t height
) {
92 return std::make_pair(1, 1);
94 void c_install_handler() {}
95 void c_uninstall_handler() {}
98 bool c_get_pflag() { return false; }
99 void c_set_pflag(bool pflag
) {}
100 framebuffer::raw
& c_draw_cover() {
101 static framebuffer::raw
x(null_fbinfo
);
102 for(size_t i
= 0; i
< sizeof(null_cover_fbmem
)/sizeof(null_cover_fbmem
[0]); i
++)
103 null_cover_fbmem
[i
] = 0x0000;
104 std::string message
= "NO ROM LOADED";
105 cover_render_string(null_cover_fbmem
, 204, 220, message
, 0xFFFF, 0x0000, 512, 448, 1024, 2);
108 std::string
c_get_core_shortname() { return "null"; }
109 void c_pre_emulate_frame(controller_frame
& cf
) {}
110 void c_execute_action(unsigned id
, const std::vector
<interface_action_paramval
>& p
) {}
111 const interface_device_reg
* c_get_registers() { return null_registers
; }
112 int t_load_rom(core_romimage
* img
, std::map
<std::string
, std::string
>& settings
,
113 uint64_t secs
, uint64_t subsecs
)
117 controller_set
t_controllerconfig(std::map
<std::string
, std::string
>& settings
)
120 x
.ports
.push_back(&get_default_system_port_type());
123 std::pair
<uint64_t, uint64_t> c_get_bus_map() { return std::make_pair(0ULL, 0ULL); }
124 std::list
<core_vma_info
> c_vma_list() { return std::list
<core_vma_info
>(); }
125 std::set
<std::string
> c_srams() { return std::set
<std::string
>(); }
126 unsigned c_action_flags(unsigned id
) { return 0; }
127 int c_reset_action(bool hard
) { return -1; }
128 bool c_isnull() { return true; }
129 void c_set_debug_flags(uint64_t addr
, unsigned int sflags
, unsigned int cflags
) {}
130 void c_set_cheat(uint64_t addr
, uint64_t value
, bool set
) {}
131 void c_debug_reset() {}
132 std::vector
<std::string
> c_get_trace_cpus()
134 return std::vector
<std::string
>();
138 core_type
* current_rom_type
= &core_null
;
139 core_region
* current_region
= &core_null
;
141 core_type
* prompt_core_fallback(const std::vector
<core_type
*>& choices
)
143 if(choices
.size() == 0)
145 if(choices
.size() == 1)
149 req
.core_guessed
= false;
151 //Tell that all ROMs have been correctly guessed, leaving only core select.
152 for(unsigned i
= 0; i
< ROM_SLOT_COUNT
; i
++) {
153 req
.has_slot
[i
] = false;
154 req
.guessed
[i
] = false;
156 req
.canceled
= false;
157 graphics_driver_request_rom(req
);
159 throw std::runtime_error("Canceled ROM loading");
160 if(req
.selected
< choices
.size())
161 return choices
[req
.selected
];
165 core_type
* find_core_by_extension(const std::string
& ext
, const std::string
& tmpprefer
)
167 std::string key
= "ext:" + ext
;
168 std::list
<core_type
*> possible
= core_type::get_core_types();
169 core_type
* preferred
= preferred_core
.count(key
) ? preferred_core
[key
] : NULL
;
170 std::vector
<core_type
*> fallbacks
;
171 //Tmpprefer overrides normal preferred core.
173 for(auto i
: possible
)
174 if(i
->get_core_identifier() == tmpprefer
)
176 for(auto i
: possible
)
177 if(i
->is_known_extension(ext
)) {
178 fallbacks
.push_back(i
);
182 core_type
* fallback
= prompt_core_fallback(fallbacks
);
183 if(!fallback
) throw std::runtime_error("No core available to load the ROM");
187 core_type
* find_core_by_name(const std::string
& name
, const std::string
& tmpprefer
)
189 std::string key
= "type:" + name
;
190 std::list
<core_type
*> possible
= core_type::get_core_types();
191 std::vector
<core_type
*> fallbacks
;
192 core_type
* preferred
= preferred_core
.count(key
) ? preferred_core
[key
] : NULL
;
193 //Tmpprefer overrides normal preferred core.
195 for(auto i
: possible
)
196 if(i
->get_iname() == tmpprefer
)
198 for(auto i
: possible
)
199 if(i
->get_iname() == name
) {
200 fallbacks
.push_back(i
);
204 core_type
* fallback
= prompt_core_fallback(fallbacks
);
205 if(!fallback
) throw std::runtime_error("No core available to load the ROM");
209 struct fileimage::image::info
get_xml_info()
211 fileimage::image::info i
;
212 i
.type
= fileimage::image::info::IT_MARKUP
;
217 struct fileimage::image::info
xlate_info(core_romimage_info ri
)
219 fileimage::image::info i
;
220 if(ri
.pass_mode
== 0) i
.type
= fileimage::image::info::IT_MEMORY
;
221 if(ri
.pass_mode
== 1) i
.type
= fileimage::image::info::IT_FILE
;
222 i
.headersize
= ri
.headersize
;
226 void record_files(loaded_rom
& rom
)
228 for(unsigned i
= 0; i
< ROM_SLOT_COUNT
; i
++) {
230 record_filehash(rom
.romimg
[i
].filename
, rom
.romimg
[i
].stripped
,
231 rom
.romimg
[i
].sha_256
.read());
234 record_filehash(rom
.romxml
[i
].filename
, rom
.romxml
[i
].stripped
,
235 rom
.romxml
[i
].sha_256
.read());
241 fileimage::hash lsnes_image_hasher
;
243 std::pair
<core_type
*, core_region
*> get_current_rom_info() throw()
245 return std::make_pair(current_rom_type
, current_region
);
248 loaded_rom::loaded_rom() throw()
251 region
= orig_region
= &core_null
;
254 loaded_rom::loaded_rom(const std::string
& file
, core_type
& ctype
) throw(std::bad_alloc
, std::runtime_error
)
257 region
= orig_region
= &rtype
->get_preferred_region();
260 unsigned pmand
= 0, tmand
= 0;
261 for(unsigned i
= 0; i
< ctype
.get_image_count(); i
++)
262 tmand
|= ctype
.get_image_info(i
).mandatory
;
263 if((bios
= ctype
.get_biosname()) != "") {
264 //This thing has a BIOS.
266 std::string basename
= lsnes_vset
["firmwarepath"].str() + "/" + bios
;
267 romimg
[0] = fileimage::image(lsnes_image_hasher
, basename
, "", xlate_info(ctype
.get_image_info(0)));
268 if(zip::file_exists(basename
+ ".xml"))
269 romxml
[0] = fileimage::image(lsnes_image_hasher
, basename
+ ".xml", "", get_xml_info());
270 pmand
|= ctype
.get_image_info(0).mandatory
;
272 romimg
[romidx
] = fileimage::image(lsnes_image_hasher
, file
, "", xlate_info(ctype
.get_image_info(romidx
)));
273 if(zip::file_exists(file
+ ".xml"))
274 romxml
[romidx
] = fileimage::image(lsnes_image_hasher
, file
+ ".xml", "", get_xml_info());
275 pmand
|= ctype
.get_image_info(romidx
).mandatory
;
276 msu1_base
= zip::resolverel(file
, "");
279 throw std::runtime_error("Required ROM images missing");
283 loaded_rom::loaded_rom(const std::string
& file
, const std::string
& tmpprefer
) throw(std::bad_alloc
,
286 std::istream
& spec
= zip::openrel(file
, "");
288 std::getline(spec
, s
);
290 if(!spec
|| s
!= "[GAMEPACK FILE]") {
291 //This is a Raw ROM image.
293 std::string ext
= regex(".*\\.([^.]*)?", file
, "Can't read file extension")[1];
294 core_type
* coretype
= find_core_by_extension(ext
, tmpprefer
);
296 (stringfmt() << "Extension '" << ext
<< "' unknown").throwex();
298 region
= orig_region
= &rtype
->get_preferred_region();
301 unsigned pmand
= 0, tmand
= 0;
302 for(unsigned i
= 0; i
< rtype
->get_image_count(); i
++)
303 tmand
|= rtype
->get_image_info(i
).mandatory
;
304 if((bios
= coretype
->get_biosname()) != "") {
305 //This thing has a BIOS.
307 std::string basename
= lsnes_vset
["firmwarepath"].str() + "/" + bios
;
308 romimg
[0] = fileimage::image(lsnes_image_hasher
, basename
, "",
309 xlate_info(coretype
->get_image_info(0)));
310 if(zip::file_exists(basename
+ ".xml"))
311 romxml
[0] = fileimage::image(lsnes_image_hasher
, basename
+ ".xml", "",
313 pmand
|= rtype
->get_image_info(0).mandatory
;
315 romimg
[romidx
] = fileimage::image(lsnes_image_hasher
, file
, "",
316 xlate_info(coretype
->get_image_info(romidx
)));
317 if(zip::file_exists(file
+ ".xml"))
318 romxml
[romidx
] = fileimage::image(lsnes_image_hasher
, file
+ ".xml", "", get_xml_info());
319 pmand
|= rtype
->get_image_info(romidx
).mandatory
;
320 msu1_base
= zip::resolverel(file
, "");
323 throw std::runtime_error("Required ROM images missing");
326 load_filename
= file
;
327 std::vector
<std::string
> lines
;
328 while(std::getline(spec
, s
))
329 lines
.push_back(strip_CR(s
));
330 std::string platname
= "";
331 std::string platreg
= "";
332 for(auto i
: lines
) {
334 if(tmp
= regex("type[ \t]+(.+)", i
))
336 if(tmp
= regex("region[ \t]+(.+)", i
))
341 rtype
= find_core_by_name(platname
, tmpprefer
);
343 (stringfmt() << "Not a valid system type '" << platname
<< "'").throwex();
346 bool goodreg
= false;
347 orig_region
= &rtype
->get_preferred_region();
348 for(auto i
: rtype
->get_regions())
349 if(i
->get_iname() == platreg
) {
353 if(!goodreg
&& platreg
!= "")
354 (stringfmt() << "Not a valid system region '" << platreg
<< "'").throwex();
355 region
= orig_region
;
358 std::string cromimg
[ROM_SLOT_COUNT
];
359 std::string cromxml
[ROM_SLOT_COUNT
];
360 for(auto i
: lines
) {
362 if(!(tmp
= regex("(rom|xml)[ \t]+([^ \t]+)[ \t]+(.*)", i
)))
364 size_t idxs
= rtype
->get_image_count();
366 for(size_t i
= 0; i
< idxs
; i
++)
367 if(rtype
->get_image_info(i
).iname
== tmp
[2])
370 (stringfmt() << "Not a valid ROM name '" << tmp
[2] << "'").throwex();
372 cromimg
[idx
] = tmp
[3];
374 cromxml
[idx
] = tmp
[3];
378 unsigned mask1
= 0, mask2
= 0;
379 for(size_t i
= 0; i
< rtype
->get_image_count(); i
++) {
380 auto ii
= rtype
->get_image_info(i
);
381 mask1
|= ii
.mandatory
;
383 mask2
|= ii
.mandatory
;
384 if(cromimg
[i
] == "" && cromxml
[i
] != "") {
385 messages
<< "WARNING: Slot " << ii
.iname
<< ": XML without ROM." << std::endl
;
390 throw std::runtime_error("Required ROM missing");
393 for(size_t i
= 0; i
< rtype
->get_image_count(); i
++) {
394 romimg
[i
] = fileimage::image(lsnes_image_hasher
, cromimg
[i
], file
,
395 xlate_info(rtype
->get_image_info(i
)));
396 romxml
[i
] = fileimage::image(lsnes_image_hasher
, cromxml
[i
], file
, get_xml_info());
398 record_files(*this); //Have to do this before patching.
401 for(auto i
: lines
) {
403 if(!(tmp
= regex("patch([+-][0-9]+)?[ \t]+([^ \t]+)[ \t]+(.*)", i
)))
405 size_t idxs
= rtype
->get_image_count();
407 for(size_t i
= 0; i
< idxs
; i
++)
408 if(rtype
->get_image_info(i
).iname
== tmp
[2])
411 (stringfmt() << "Not a valid ROM name '" << tmp
[2] << "'").throwex();
414 offset
= parse_value
<int32_t>(tmp
[1]);
415 romimg
[idx
].patch(zip::readrel(tmp
[3], file
), offset
);
420 msu1_base
= zip::resolverel(cromimg
[1], file
);
422 msu1_base
= zip::resolverel(cromimg
[0], file
);
427 bool filter_by_core(core_type
& ctype
, const std::string
& core
)
429 return (core
== "" || ctype
.get_core_identifier() == core
);
432 bool filter_by_type(core_type
& ctype
, const std::string
& type
)
434 return (type
== "" || ctype
.get_iname() == type
);
437 bool filter_by_region(core_type
& ctype
, const std::string
& region
)
441 for(auto i
: ctype
.get_regions())
442 if(i
->get_iname() == region
)
447 bool filter_by_extension(core_type
& ctype
, const std::string
& file
)
449 regex_results tmp
= regex(".*\\.([^.]*)", file
);
452 std::string ext
= tmp
[1];
453 return ctype
.is_known_extension(ext
);
456 bool filter_by_fileset(core_type
& ctype
, const std::string file
[ROM_SLOT_COUNT
])
458 uint32_t m
= 0, t
= 0;
459 for(unsigned i
= 0; i
< ROM_SLOT_COUNT
; i
++) {
460 if(i
>= ctype
.get_image_count() && file
[i
] != "")
462 auto s
= ctype
.get_image_info(i
);
470 core_region
* detect_region(core_type
* t
, const std::string
& region
)
472 core_region
* r
= NULL
;
473 for(auto i
: t
->get_regions())
474 if(i
->get_iname() == region
)
476 if(!r
&& region
!= "")
477 (stringfmt() << "Not a valid system region '" << region
<< "'").throwex();
478 if(!r
) r
= &t
->get_preferred_region(); //Default region.
483 loaded_rom::loaded_rom(const std::string
& file
, const std::string
& core
, const std::string
& type
,
484 const std::string
& _region
)
487 core_region
* r
= NULL
;
488 bool fullspec
= (core
!= "" && type
!= "");
489 for(auto i
: core_type::get_core_types()) {
490 if(!filter_by_core(*i
, core
))
492 if(!filter_by_type(*i
, type
))
494 if(!fullspec
&& !filter_by_region(*i
, _region
))
496 if(!fullspec
&& !filter_by_extension(*i
, file
))
500 if(!t
) throw std::runtime_error("No matching core found");
501 r
= detect_region(t
, _region
);
502 unsigned pmand
= 0, tmand
= 0;
503 for(unsigned i
= 0; i
< t
->get_image_count(); i
++)
504 tmand
|= t
->get_image_info(i
).mandatory
;
505 std::string bios
= t
->get_biosname();
506 unsigned romidx
= (bios
!= "") ? 1 : 0;
508 std::string basename
= lsnes_vset
["firmwarepath"].str() + "/" + bios
;
509 romimg
[0] = fileimage::image(lsnes_image_hasher
, basename
, "", xlate_info(t
->get_image_info(0)));
510 if(zip::file_exists(basename
+ ".xml"))
511 romxml
[0] = fileimage::image(lsnes_image_hasher
, basename
+ ".xml", "", get_xml_info());
512 pmand
|= t
->get_image_info(0).mandatory
;
514 romimg
[romidx
] = fileimage::image(lsnes_image_hasher
, file
, "", xlate_info(t
->get_image_info(romidx
)));
515 if(zip::file_exists(file
+ ".xml"))
516 romxml
[romidx
] = fileimage::image(lsnes_image_hasher
, file
+ ".xml", "", get_xml_info());
517 pmand
|= t
->get_image_info(romidx
).mandatory
;
518 msu1_base
= zip::resolverel(file
, "");
521 throw std::runtime_error("Required ROM images missing");
523 orig_region
= region
= r
;
526 loaded_rom::loaded_rom(const std::string file
[ROM_SLOT_COUNT
], const std::string
& core
, const std::string
& type
,
527 const std::string
& _region
)
530 core_region
* r
= NULL
;
531 bool fullspec
= (core
!= "" && type
!= "");
532 for(auto i
: core_type::get_core_types()) {
533 if(!filter_by_core(*i
, core
)) {
536 if(!filter_by_type(*i
, type
)) {
539 if(!fullspec
&& !filter_by_region(*i
, _region
)) {
542 if(!fullspec
&& !filter_by_fileset(*i
, file
)) {
547 if(!t
) throw std::runtime_error("No matching core found");
548 r
= detect_region(t
, _region
);
549 std::string bios
= t
->get_biosname();
550 unsigned romidx
= (bios
!= "") ? 1 : 0;
551 unsigned pmand
= 0, tmand
= 0;
552 for(unsigned i
= 0; i
< 27; i
++) {
553 if(i
>= t
->get_image_count())
556 pmand
|= t
->get_image_info(i
).mandatory
;
557 tmand
|= t
->get_image_info(i
).mandatory
;
558 romimg
[i
] = fileimage::image(lsnes_image_hasher
, file
[i
], "", xlate_info(t
->get_image_info(i
)));
559 if(zip::file_exists(file
[i
] + ".xml"))
560 romxml
[i
] = fileimage::image(lsnes_image_hasher
, file
[i
] + ".xml", "", get_xml_info());
562 msu1_base
= zip::resolverel(file
[romidx
], "");
565 throw std::runtime_error("Required ROM images missing");
567 orig_region
= region
= r
;
570 void loaded_rom::load(std::map
<std::string
, std::string
>& settings
, uint64_t rtc_sec
, uint64_t rtc_subsec
)
571 throw(std::bad_alloc
, std::runtime_error
)
573 core_type
* old_type
= current_rom_type
;
574 core_core
* old_core
= current_rom_type
->get_core();
575 current_rom_type
= &core_null
;
576 if(!orig_region
&& rtype
!= &core_null
)
577 orig_region
= &rtype
->get_preferred_region();
579 region
= orig_region
;
580 if(rtype
&& !orig_region
->compatible_with(*region
))
581 throw std::runtime_error("Trying to force incompatible region");
582 if(rtype
&& !rtype
->set_region(*region
))
583 throw std::runtime_error("Trying to force unknown region");
585 core_romimage images
[ROM_SLOT_COUNT
];
586 for(size_t i
= 0; i
< ROM_SLOT_COUNT
; i
++) {
587 images
[i
].markup
= (const char*)romxml
[i
];
588 images
[i
].data
= (const unsigned char*)romimg
[i
];
589 images
[i
].size
= (size_t)romimg
[i
];
591 if(!rtype
->load(images
, settings
, rtc_sec
, rtc_subsec
))
592 throw std::runtime_error("Can't load cartridge ROM");
594 region
= &rtype
->get_region();
596 auto nominal_fps
= rtype
->get_video_rate();
597 auto nominal_hz
= rtype
->get_audio_rate();
598 set_nominal_framerate(1.0 * nominal_fps
.first
/ nominal_fps
.second
);
599 information_dispatch::do_sound_rate(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();
608 refresh_cart_mappings();
609 notify_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
) {
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
;