Fix some memory leak complaints from Valgrind
[lsnes.git] / src / core / rom.cpp
blob8f24596044ebfff4524d9b8a5e0179330cc6f9bc
1 #include "lsnes.hpp"
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"
23 #include <stdexcept>
25 #include <sstream>
26 #include <iomanip>
27 #include <cstdint>
28 #include <set>
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
39 #include <gcrypt.h>
40 #endif
42 namespace
44 const char* null_chars = "F";
45 uint16_t null_cover_fbmem[512 * 448];
47 settingvar::variable<settingvar::model_bool<settingvar::yes_no>> savestate_no_check(lsnes_vset,
48 "dont-check-savestate", "Movie‣Loading‣Don't check savestates", false);
50 //Framebuffer.
51 struct framebuffer::info null_fbinfo = {
52 &framebuffer::pixfmt_bgr16, //Format.
53 (char*)null_cover_fbmem, //Memory.
54 512, 448, 1024, //Physical size.
55 512, 448, 1024, //Logical size.
56 0, 0 //Offset.
59 port_index_triple sync_triple = {true, 0, 0, 0 };
61 struct interface_device_reg null_registers[] = {
62 {NULL, NULL, NULL}
65 struct _core_null : public core_core, public core_type, public core_region, public core_sysregion
67 _core_null() : core_core({}, {}), core_type({{
68 .iname = "null",
69 .hname = "(null)",
70 .id = 9999,
71 .sysname = "System",
72 .bios = NULL,
73 .regions = {this},
74 .images = {},
75 .settings = {},
76 .core = this,
77 }}), core_region({{"null", "(null)", 0, 0, false, {1, 60}, {0}}}),
78 core_sysregion("null", *this, *this) { hide(); }
79 std::string c_core_identifier() { return "null core"; }
80 bool c_set_region(core_region& reg) { return true; }
81 std::pair<unsigned, unsigned> c_video_rate() { return std::make_pair(60, 1); }
82 double c_get_PAR() { return 1.0; }
83 std::pair<unsigned, unsigned> c_audio_rate() { return std::make_pair(48000, 1); }
84 std::map<std::string, std::vector<char>> c_save_sram() throw (std::bad_alloc) {
85 std::map<std::string, std::vector<char>> x;
86 return x;
88 void c_load_sram(std::map<std::string, std::vector<char>>& sram) throw (std::bad_alloc) {}
89 void c_serialize(std::vector<char>& out) { out.clear(); }
90 void c_unserialize(const char* in, size_t insize) {}
91 core_region& c_get_region() { return *this; }
92 void c_power() {}
93 void c_unload_cartridge() {}
94 std::pair<uint32_t, uint32_t> c_get_scale_factors(uint32_t width, uint32_t height) {
95 return std::make_pair(1, 1);
97 void c_install_handler() {}
98 void c_uninstall_handler() {}
99 void c_emulate() {}
100 void c_runtosave() {}
101 bool c_get_pflag() { return false; }
102 void c_set_pflag(bool pflag) {}
103 framebuffer::raw& c_draw_cover() {
104 static framebuffer::raw x(null_fbinfo);
105 for(size_t i = 0; i < sizeof(null_cover_fbmem)/sizeof(null_cover_fbmem[0]); i++)
106 null_cover_fbmem[i] = 0x0000;
107 std::string message = "NO ROM LOADED";
108 cover_render_string(null_cover_fbmem, 204, 220, message, 0xFFFF, 0x0000, 512, 448, 1024, 2);
109 return x;
111 std::string c_get_core_shortname() { return "null"; }
112 void c_pre_emulate_frame(controller_frame& cf) {}
113 void c_execute_action(unsigned id, const std::vector<interface_action_paramval>& p) {}
114 const interface_device_reg* c_get_registers() { return null_registers; }
115 int t_load_rom(core_romimage* img, std::map<std::string, std::string>& settings,
116 uint64_t secs, uint64_t subsecs)
118 return 0;
120 controller_set t_controllerconfig(std::map<std::string, std::string>& settings)
122 controller_set x;
123 x.ports.push_back(&get_default_system_port_type());
124 return x;
126 std::pair<uint64_t, uint64_t> c_get_bus_map() { return std::make_pair(0ULL, 0ULL); }
127 std::list<core_vma_info> c_vma_list() { return std::list<core_vma_info>(); }
128 std::set<std::string> c_srams() { return std::set<std::string>(); }
129 unsigned c_action_flags(unsigned id) { return 0; }
130 int c_reset_action(bool hard) { return -1; }
131 bool c_isnull() { return true; }
132 void c_set_debug_flags(uint64_t addr, unsigned int sflags, unsigned int cflags) {}
133 void c_set_cheat(uint64_t addr, uint64_t value, bool set) {}
134 void c_debug_reset() {}
135 std::vector<std::string> c_get_trace_cpus()
137 return std::vector<std::string>();
139 } core_null;
141 core_type* current_rom_type = &core_null;
142 core_region* current_region = &core_null;
144 core_type* find_core_by_extension(const std::string& ext, const std::string& tmpprefer)
146 std::string key = "ext:" + ext;
147 std::list<core_type*> possible = core_type::get_core_types();
148 core_type* fallback = NULL;
149 core_type* preferred = preferred_core.count(key) ? preferred_core[key] : NULL;
150 //Tmpprefer overrides normal preferred core.
151 if(tmpprefer != "")
152 for(auto i : possible)
153 if(i->is_known_extension(ext) && i->get_core_identifier() == tmpprefer)
154 preferred = i;
155 for(auto i : possible)
156 if(i->is_known_extension(ext)) {
157 fallback = i;
158 if(!preferred && i->get_core_shortname() == preferred_core_default)
159 return i;
160 if(i == preferred)
161 return i;
163 return fallback;
166 core_type* find_core_by_name(const std::string& name, const std::string& tmpprefer)
168 std::string key = "type:" + name;
169 std::list<core_type*> possible = core_type::get_core_types();
170 core_type* fallback = NULL;
171 core_type* preferred = preferred_core.count(key) ? preferred_core[key] : NULL;
172 //Tmpprefer overrides normal preferred core.
173 if(tmpprefer != "")
174 for(auto i : possible)
175 if(i->get_iname() == tmpprefer)
176 preferred = i;
177 for(auto i : possible)
178 if(i->get_iname() == name) {
179 fallback = i;
180 if(!preferred && i->get_core_shortname() == preferred_core_default)
181 return i;
182 if(i == preferred)
183 return i;
185 return fallback;
188 struct fileimage::image::info get_xml_info()
190 fileimage::image::info i;
191 i.type = fileimage::image::info::IT_MARKUP;
192 i.headersize = 0;
193 return i;
196 struct fileimage::image::info xlate_info(core_romimage_info ri)
198 fileimage::image::info i;
199 if(ri.pass_mode == 0) i.type = fileimage::image::info::IT_MEMORY;
200 if(ri.pass_mode == 1) i.type = fileimage::image::info::IT_FILE;
201 i.headersize = ri.headersize;
202 return i;
205 void record_files(loaded_rom& rom)
207 for(unsigned i = 0; i < ROM_SLOT_COUNT; i++) {
208 try {
209 record_filehash(rom.romimg[i].filename, rom.romimg[i].stripped,
210 rom.romimg[i].sha_256.read());
211 } catch(...) {}
212 try {
213 record_filehash(rom.romxml[i].filename, rom.romxml[i].stripped,
214 rom.romxml[i].sha_256.read());
215 } catch(...) {}
220 fileimage::hash lsnes_image_hasher;
222 std::pair<core_type*, core_region*> get_current_rom_info() throw()
224 return std::make_pair(current_rom_type, current_region);
227 loaded_rom::loaded_rom() throw()
229 rtype = &core_null;
230 region = orig_region = &core_null;
233 loaded_rom::loaded_rom(const std::string& file, core_type& ctype) throw(std::bad_alloc, std::runtime_error)
235 rtype = &ctype;
236 region = orig_region = &rtype->get_preferred_region();
237 unsigned romidx = 0;
238 std::string bios;
239 unsigned pmand = 0, tmand = 0;
240 for(unsigned i = 0; i < ctype.get_image_count(); i++)
241 tmand |= ctype.get_image_info(i).mandatory;
242 if((bios = ctype.get_biosname()) != "") {
243 //This thing has a BIOS.
244 romidx = 1;
245 std::string basename = lsnes_vset["firmwarepath"].str() + "/" + bios;
246 romimg[0] = fileimage::image(lsnes_image_hasher, basename, "", xlate_info(ctype.get_image_info(0)));
247 if(zip::file_exists(basename + ".xml"))
248 romxml[0] = fileimage::image(lsnes_image_hasher, basename + ".xml", "", get_xml_info());
249 pmand |= ctype.get_image_info(0).mandatory;
251 romimg[romidx] = fileimage::image(lsnes_image_hasher, file, "", xlate_info(ctype.get_image_info(romidx)));
252 if(zip::file_exists(file + ".xml"))
253 romxml[romidx] = fileimage::image(lsnes_image_hasher, file + ".xml", "", get_xml_info());
254 pmand |= ctype.get_image_info(romidx).mandatory;
255 msu1_base = zip::resolverel(file, "");
256 record_files(*this);
257 if(pmand != tmand)
258 throw std::runtime_error("Required ROM images missing");
259 return;
262 loaded_rom::loaded_rom(const std::string& file, const std::string& tmpprefer) throw(std::bad_alloc,
263 std::runtime_error)
265 std::istream& spec = zip::openrel(file, "");
266 std::string s;
267 std::getline(spec, s);
268 istrip_CR(s);
269 if(!spec || s != "[GAMEPACK FILE]") {
270 //This is a Raw ROM image.
271 regex_results tmp;
272 std::string ext = regex(".*\\.([^.]*)?", file, "Can't read file extension")[1];
273 core_type* coretype = find_core_by_extension(ext, tmpprefer);
274 if(!coretype)
275 (stringfmt() << "Extension '" << ext << "' unknown").throwex();
276 rtype = coretype;
277 region = orig_region = &rtype->get_preferred_region();
278 unsigned romidx = 0;
279 std::string bios;
280 unsigned pmand = 0, tmand = 0;
281 for(unsigned i = 0; i < rtype->get_image_count(); i++)
282 tmand |= rtype->get_image_info(i).mandatory;
283 if((bios = coretype->get_biosname()) != "") {
284 //This thing has a BIOS.
285 romidx = 1;
286 std::string basename = lsnes_vset["firmwarepath"].str() + "/" + bios;
287 romimg[0] = fileimage::image(lsnes_image_hasher, basename, "",
288 xlate_info(coretype->get_image_info(0)));
289 if(zip::file_exists(basename + ".xml"))
290 romxml[0] = fileimage::image(lsnes_image_hasher, basename + ".xml", "",
291 get_xml_info());
292 pmand |= rtype->get_image_info(0).mandatory;
294 romimg[romidx] = fileimage::image(lsnes_image_hasher, file, "",
295 xlate_info(coretype->get_image_info(romidx)));
296 if(zip::file_exists(file + ".xml"))
297 romxml[romidx] = fileimage::image(lsnes_image_hasher, file + ".xml", "", get_xml_info());
298 pmand |= rtype->get_image_info(romidx).mandatory;
299 msu1_base = zip::resolverel(file, "");
300 record_files(*this);
301 if(pmand != tmand)
302 throw std::runtime_error("Required ROM images missing");
303 return;
305 load_filename = file;
306 std::vector<std::string> lines;
307 while(std::getline(spec, s))
308 lines.push_back(strip_CR(s));
309 std::string platname = "";
310 std::string platreg = "";
311 for(auto i : lines) {
312 regex_results tmp;
313 if(tmp = regex("type[ \t]+(.+)", i))
314 platname = tmp[1];
315 if(tmp = regex("region[ \t]+(.+)", i))
316 platreg = tmp[1];
319 //Detect type.
320 rtype = find_core_by_name(platname, tmpprefer);
321 if(!rtype)
322 (stringfmt() << "Not a valid system type '" << platname << "'").throwex();
324 //Detect region.
325 bool goodreg = false;
326 orig_region = &rtype->get_preferred_region();
327 for(auto i: rtype->get_regions())
328 if(i->get_iname() == platreg) {
329 orig_region = i;
330 goodreg = true;
332 if(!goodreg && platreg != "")
333 (stringfmt() << "Not a valid system region '" << platreg << "'").throwex();
334 region = orig_region;
336 //ROM files.
337 std::string cromimg[ROM_SLOT_COUNT];
338 std::string cromxml[ROM_SLOT_COUNT];
339 for(auto i : lines) {
340 regex_results tmp;
341 if(!(tmp = regex("(rom|xml)[ \t]+([^ \t]+)[ \t]+(.*)", i)))
342 continue;
343 size_t idxs = rtype->get_image_count();
344 size_t idx = idxs;
345 for(size_t i = 0; i < idxs; i++)
346 if(rtype->get_image_info(i).iname == tmp[2])
347 idx = i;
348 if(idx == idxs)
349 (stringfmt() << "Not a valid ROM name '" << tmp[2] << "'").throwex();
350 if(tmp[1] == "rom")
351 cromimg[idx] = tmp[3];
352 else
353 cromxml[idx] = tmp[3];
356 //Check ROMs.
357 unsigned mask1 = 0, mask2 = 0;
358 for(size_t i = 0; i < rtype->get_image_count(); i++) {
359 auto ii = rtype->get_image_info(i);
360 mask1 |= ii.mandatory;
361 if(cromimg[i] != "")
362 mask2 |= ii.mandatory;
363 if(cromimg[i] == "" && cromxml[i] != "") {
364 messages << "WARNING: Slot " << ii.iname << ": XML without ROM." << std::endl;
365 cromxml[i] = "";
368 if(mask1 != mask2)
369 throw std::runtime_error("Required ROM missing");
371 //Load ROMs.
372 for(size_t i = 0; i < rtype->get_image_count(); i++) {
373 romimg[i] = fileimage::image(lsnes_image_hasher, cromimg[i], file,
374 xlate_info(rtype->get_image_info(i)));
375 romxml[i] = fileimage::image(lsnes_image_hasher, cromxml[i], file, get_xml_info());
377 record_files(*this); //Have to do this before patching.
379 //Patch ROMs.
380 for(auto i : lines) {
381 regex_results tmp;
382 if(!(tmp = regex("patch([+-][0-9]+)?[ \t]+([^ \t]+)[ \t]+(.*)", i)))
383 continue;
384 size_t idxs = rtype->get_image_count();
385 size_t idx = idxs;
386 for(size_t i = 0; i < idxs; i++)
387 if(rtype->get_image_info(i).iname == tmp[2])
388 idx = i;
389 if(idx == idxs)
390 (stringfmt() << "Not a valid ROM name '" << tmp[2] << "'").throwex();
391 int32_t offset = 0;
392 if(tmp[1] != "")
393 offset = parse_value<int32_t>(tmp[1]);
394 romimg[idx].patch(zip::readrel(tmp[3], file), offset);
397 //MSU-1 base.
398 if(cromimg[1] != "")
399 msu1_base = zip::resolverel(cromimg[1], file);
400 else
401 msu1_base = zip::resolverel(cromimg[0], file);
404 namespace
406 bool filter_by_core(core_type& ctype, const std::string& core)
408 return (core == "" || ctype.get_core_identifier() == core);
411 bool filter_by_type(core_type& ctype, const std::string& type)
413 return (type == "" || ctype.get_iname() == type);
416 bool filter_by_region(core_type& ctype, const std::string& region)
418 if(region == "")
419 return true;
420 for(auto i : ctype.get_regions())
421 if(i->get_iname() == region)
422 return true;
423 return false;
426 bool filter_by_extension(core_type& ctype, const std::string& file)
428 regex_results tmp = regex(".*\\.([^.]*)", file);
429 if(!tmp)
430 return false;
431 std::string ext = tmp[1];
432 return ctype.is_known_extension(ext);
435 bool filter_by_fileset(core_type& ctype, const std::string file[ROM_SLOT_COUNT])
437 uint32_t m = 0, t = 0;
438 for(unsigned i = 0; i < ROM_SLOT_COUNT; i++) {
439 if(i >= ctype.get_image_count() && file[i] != "")
440 return false;
441 auto s = ctype.get_image_info(i);
442 if(file[i] != "")
443 m |= s.mandatory;
444 t |= s.mandatory;
446 return (m == t);
449 core_region* detect_region(core_type* t, const std::string& region)
451 core_region* r = NULL;
452 for(auto i: t->get_regions())
453 if(i->get_iname() == region)
454 r = i;
455 if(!r && region != "")
456 (stringfmt() << "Not a valid system region '" << region << "'").throwex();
457 if(!r) r = &t->get_preferred_region(); //Default region.
458 return r;
462 loaded_rom::loaded_rom(const std::string& file, const std::string& core, const std::string& type,
463 const std::string& _region)
465 core_type* t = NULL;
466 core_region* r = NULL;
467 bool fullspec = (core != "" && type != "");
468 for(auto i : core_type::get_core_types()) {
469 if(!filter_by_core(*i, core))
470 continue;
471 if(!filter_by_type(*i, type))
472 continue;
473 if(!fullspec && !filter_by_region(*i, _region))
474 continue;
475 if(!fullspec && !filter_by_extension(*i, file))
476 continue;
477 t = i;
479 if(!t) throw std::runtime_error("No matching core found");
480 r = detect_region(t, _region);
481 unsigned pmand = 0, tmand = 0;
482 for(unsigned i = 0; i < t->get_image_count(); i++)
483 tmand |= t->get_image_info(i).mandatory;
484 std::string bios = t->get_biosname();
485 unsigned romidx = (bios != "") ? 1 : 0;
486 if(bios != "") {
487 std::string basename = lsnes_vset["firmwarepath"].str() + "/" + bios;
488 romimg[0] = fileimage::image(lsnes_image_hasher, basename, "", xlate_info(t->get_image_info(0)));
489 if(zip::file_exists(basename + ".xml"))
490 romxml[0] = fileimage::image(lsnes_image_hasher, basename + ".xml", "", get_xml_info());
491 pmand |= t->get_image_info(0).mandatory;
493 romimg[romidx] = fileimage::image(lsnes_image_hasher, file, "", xlate_info(t->get_image_info(romidx)));
494 if(zip::file_exists(file + ".xml"))
495 romxml[romidx] = fileimage::image(lsnes_image_hasher, file + ".xml", "", get_xml_info());
496 pmand |= t->get_image_info(romidx).mandatory;
497 msu1_base = zip::resolverel(file, "");
498 record_files(*this);
499 if(pmand != tmand)
500 throw std::runtime_error("Required ROM images missing");
501 rtype = t;
502 orig_region = region = r;
505 loaded_rom::loaded_rom(const std::string file[ROM_SLOT_COUNT], const std::string& core, const std::string& type,
506 const std::string& _region)
508 core_type* t = NULL;
509 core_region* r = NULL;
510 bool fullspec = (core != "" && type != "");
511 for(auto i : core_type::get_core_types()) {
512 if(!filter_by_core(*i, core)) {
513 continue;
515 if(!filter_by_type(*i, type)) {
516 continue;
518 if(!fullspec && !filter_by_region(*i, _region)) {
519 continue;
521 if(!fullspec && !filter_by_fileset(*i, file)) {
522 continue;
524 t = i;
526 if(!t) throw std::runtime_error("No matching core found");
527 r = detect_region(t, _region);
528 std::string bios = t->get_biosname();
529 unsigned romidx = (bios != "") ? 1 : 0;
530 unsigned pmand = 0, tmand = 0;
531 for(unsigned i = 0; i < 27; i++) {
532 if(i >= t->get_image_count())
533 continue;
534 if(file[i] != "")
535 pmand |= t->get_image_info(i).mandatory;
536 tmand |= t->get_image_info(i).mandatory;
537 romimg[i] = fileimage::image(lsnes_image_hasher, file[i], "", xlate_info(t->get_image_info(i)));
538 if(zip::file_exists(file[i] + ".xml"))
539 romxml[i] = fileimage::image(lsnes_image_hasher, file[i] + ".xml", "", get_xml_info());
541 msu1_base = zip::resolverel(file[romidx], "");
542 record_files(*this);
543 if(pmand != tmand)
544 throw std::runtime_error("Required ROM images missing");
545 rtype = t;
546 orig_region = region = r;
549 void loaded_rom::load(std::map<std::string, std::string>& settings, uint64_t rtc_sec, uint64_t rtc_subsec)
550 throw(std::bad_alloc, std::runtime_error)
552 core_type* old_type = current_rom_type;
553 core_core* old_core = current_rom_type->get_core();
554 current_rom_type = &core_null;
555 if(!orig_region && rtype != &core_null)
556 orig_region = &rtype->get_preferred_region();
557 if(!region)
558 region = orig_region;
559 if(rtype && !orig_region->compatible_with(*region))
560 throw std::runtime_error("Trying to force incompatible region");
561 if(rtype && !rtype->set_region(*region))
562 throw std::runtime_error("Trying to force unknown region");
564 core_romimage images[ROM_SLOT_COUNT];
565 for(size_t i = 0; i < ROM_SLOT_COUNT; i++) {
566 images[i].markup = (const char*)romxml[i];
567 images[i].data = (const unsigned char*)romimg[i];
568 images[i].size = (size_t)romimg[i];
570 if(!rtype->load(images, settings, rtc_sec, rtc_subsec))
571 throw std::runtime_error("Can't load cartridge ROM");
573 region = &rtype->get_region();
574 rtype->power();
575 auto nominal_fps = rtype->get_video_rate();
576 auto nominal_hz = rtype->get_audio_rate();
577 set_nominal_framerate(1.0 * nominal_fps.first / nominal_fps.second);
578 information_dispatch::do_sound_rate(nominal_hz.first, nominal_hz.second);
579 current_rom_type = rtype;
580 current_region = region;
581 //If core changes, unload the cartridge.
582 if(old_core != current_rom_type->get_core())
583 try {
584 old_core->debug_reset();
585 old_core->unload_cartridge();
586 } catch(...) {}
587 refresh_cart_mappings();
588 notify_core_changed(old_type != current_rom_type);
591 std::map<std::string, std::vector<char>> load_sram_commandline(const std::vector<std::string>& cmdline)
592 throw(std::bad_alloc, std::runtime_error)
594 std::map<std::string, std::vector<char>> ret;
595 regex_results opt;
596 for(auto i : cmdline) {
597 if(opt = regex("--continue=(.+)", i)) {
598 zip::reader r(opt[1]);
599 for(auto j : r) {
600 auto sramname = regex("sram\\.(.*)", j);
601 if(!sramname)
602 continue;
603 std::istream& x = r[j];
604 try {
605 std::vector<char> out;
606 boost::iostreams::back_insert_device<std::vector<char>> rd(out);
607 boost::iostreams::copy(x, rd);
608 delete &x;
609 ret[sramname[1]] = out;
610 } catch(...) {
611 delete &x;
612 throw;
615 continue;
616 } else if(opt = regex("--sram-([^=]+)=(.+)", i)) {
617 try {
618 ret[opt[1]] = zip::readrel(opt[2], "");
619 } catch(std::bad_alloc& e) {
620 throw;
621 } catch(std::runtime_error& e) {
622 throw std::runtime_error("Can't load SRAM '" + opt[1] + "': " + e.what());
626 return ret;
629 std::vector<char> loaded_rom::save_core_state(bool nochecksum) throw(std::bad_alloc, std::runtime_error)
631 std::vector<char> ret;
632 rtype->serialize(ret);
633 if(nochecksum)
634 return ret;
635 size_t offset = ret.size();
636 unsigned char tmp[32];
637 #ifdef USE_LIBGCRYPT_SHA256
638 gcry_md_hash_buffer(GCRY_MD_SHA256, tmp, &ret[0], offset);
639 #else
640 sha256::hash(tmp, ret);
641 #endif
642 ret.resize(offset + 32);
643 memcpy(&ret[offset], tmp, 32);
644 return ret;
647 void loaded_rom::load_core_state(const std::vector<char>& buf, bool nochecksum) throw(std::runtime_error)
649 if(nochecksum) {
650 rtype->unserialize(&buf[0], buf.size());
651 return;
654 if(buf.size() < 32)
655 throw std::runtime_error("Savestate corrupt");
656 if(!savestate_no_check) {
657 unsigned char tmp[32];
658 #ifdef USE_LIBGCRYPT_SHA256
659 gcry_md_hash_buffer(GCRY_MD_SHA256, tmp, &buf[0], buf.size() - 32);
660 #else
661 sha256::hash(tmp, reinterpret_cast<const uint8_t*>(&buf[0]), buf.size() - 32);
662 #endif
663 if(memcmp(tmp, &buf[buf.size() - 32], 32))
664 throw std::runtime_error("Savestate corrupt");
666 rtype->unserialize(&buf[0], buf.size() - 32);
669 void set_hasher_callback(std::function<void(uint64_t, uint64_t)> cb)
671 lsnes_image_hasher.set_callback(cb);
674 std::map<std::string, core_type*> preferred_core;
675 std::string preferred_core_default;