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/nullcore.hpp"
10 #include "core/rom.hpp"
11 #include "core/settings.hpp"
12 #include "core/window.hpp"
13 #include "interface/callbacks.hpp"
14 #include "interface/cover.hpp"
15 #include "interface/romtype.hpp"
16 #include "library/portctrl-data.hpp"
17 #include "library/fileimage-patch.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 settingvar::supervariable
<settingvar::model_bool
<settingvar::yes_no
>> savestate_no_check(lsnes_setgrp
,
43 "dont-check-savestate", "Movie‣Loading‣Don't check savestates", false);
45 core_type
* current_rom_type
= &get_null_type();
46 core_region
* current_region
= &get_null_region();
48 core_type
* prompt_core_fallback(const std::vector
<core_type
*>& choices
)
50 if(choices
.size() == 0)
52 if(choices
.size() == 1)
56 req
.core_guessed
= false;
58 //Tell that all ROMs have been correctly guessed, leaving only core select.
59 for(unsigned i
= 0; i
< ROM_SLOT_COUNT
; i
++) {
60 req
.has_slot
[i
] = false;
61 req
.guessed
[i
] = false;
64 graphics_driver_request_rom(req
);
66 throw std::runtime_error("Canceled ROM loading");
67 if(req
.selected
< choices
.size())
68 return choices
[req
.selected
];
72 core_type
* find_core_by_extension(const std::string
& ext
, const std::string
& tmpprefer
)
74 std::string key
= "ext:" + ext
;
75 std::list
<core_type
*> possible
= core_type::get_core_types();
76 core_type
* preferred
= preferred_core
.count(key
) ? preferred_core
[key
] : NULL
;
77 std::vector
<core_type
*> fallbacks
;
78 //Tmpprefer overrides normal preferred core.
80 for(auto i
: possible
)
81 if(i
->get_core_identifier() == tmpprefer
)
83 for(auto i
: possible
)
84 if(i
->is_known_extension(ext
)) {
85 fallbacks
.push_back(i
);
89 core_type
* fallback
= prompt_core_fallback(fallbacks
);
90 if(!fallback
) throw std::runtime_error("No core available to load the ROM");
94 core_type
* find_core_by_name(const std::string
& name
, const std::string
& tmpprefer
)
96 std::string key
= "type:" + name
;
97 std::list
<core_type
*> possible
= core_type::get_core_types();
98 std::vector
<core_type
*> fallbacks
;
99 core_type
* preferred
= preferred_core
.count(key
) ? preferred_core
[key
] : NULL
;
100 //Tmpprefer overrides normal preferred core.
102 for(auto i
: possible
)
103 if(i
->get_iname() == tmpprefer
)
105 for(auto i
: possible
)
106 if(i
->get_iname() == name
) {
107 fallbacks
.push_back(i
);
111 core_type
* fallback
= prompt_core_fallback(fallbacks
);
112 if(!fallback
) throw std::runtime_error("No core available to load the ROM");
116 struct fileimage::image::info
get_xml_info()
118 fileimage::image::info i
;
119 i
.type
= fileimage::image::info::IT_MARKUP
;
124 struct fileimage::image::info
xlate_info(core_romimage_info ri
)
126 fileimage::image::info i
;
127 if(ri
.pass_mode
== 0) i
.type
= fileimage::image::info::IT_MEMORY
;
128 if(ri
.pass_mode
== 1) i
.type
= fileimage::image::info::IT_FILE
;
129 i
.headersize
= ri
.headersize
;
133 void record_files(loaded_rom
& rom
)
135 for(unsigned i
= 0; i
< ROM_SLOT_COUNT
; i
++) {
137 auto& j
= rom
.get_rom(i
);
138 record_filehash(j
.filename
, j
.stripped
, j
.sha_256
.read());
141 auto& j
= rom
.get_markup(i
);
142 record_filehash(j
.filename
, j
.stripped
, j
.sha_256
.read());
148 fileimage::hash lsnes_image_hasher
;
149 fileimage::image
loaded_rom::null_img
;
151 std::pair
<core_type
*, core_region
*> get_current_rom_info() throw()
153 return std::make_pair(current_rom_type
, current_region
);
156 loaded_rom::loaded_rom() throw()
158 rtype
= &get_null_type();
159 region
= orig_region
= &get_null_region();
162 loaded_rom::loaded_rom(const std::string
& file
, core_type
& ctype
) throw(std::bad_alloc
, std::runtime_error
)
165 region
= orig_region
= &rtype
->get_preferred_region();
168 unsigned pmand
= 0, tmand
= 0;
169 for(unsigned i
= 0; i
< ctype
.get_image_count(); i
++)
170 tmand
|= ctype
.get_image_info(i
).mandatory
;
171 if((bios
= ctype
.get_biosname()) != "") {
172 //This thing has a BIOS.
174 std::string basename
= CORE().setcache
->get("firmwarepath") + "/" + bios
;
175 romimg
[0] = fileimage::image(lsnes_image_hasher
, basename
, "", xlate_info(ctype
.get_image_info(0)));
176 if(zip::file_exists(basename
+ ".xml"))
177 romxml
[0] = fileimage::image(lsnes_image_hasher
, basename
+ ".xml", "", get_xml_info());
178 pmand
|= ctype
.get_image_info(0).mandatory
;
180 romimg
[romidx
] = fileimage::image(lsnes_image_hasher
, file
, "", xlate_info(ctype
.get_image_info(romidx
)));
181 if(zip::file_exists(file
+ ".xml"))
182 romxml
[romidx
] = fileimage::image(lsnes_image_hasher
, file
+ ".xml", "", get_xml_info());
183 pmand
|= ctype
.get_image_info(romidx
).mandatory
;
184 msu1_base
= zip::resolverel(file
, "");
187 throw std::runtime_error("Required ROM images missing");
191 loaded_rom::loaded_rom(const std::string
& file
, const std::string
& tmpprefer
) throw(std::bad_alloc
,
194 std::istream
& spec
= zip::openrel(file
, "");
196 std::getline(spec
, s
);
198 if(!spec
|| s
!= "[GAMEPACK FILE]") {
199 //This is a Raw ROM image.
201 std::string ext
= regex(".*\\.([^.]*)?", file
, "Can't read file extension")[1];
202 core_type
* coretype
= find_core_by_extension(ext
, tmpprefer
);
204 (stringfmt() << "Extension '" << ext
<< "' unknown").throwex();
206 region
= orig_region
= &rtype
->get_preferred_region();
209 unsigned pmand
= 0, tmand
= 0;
210 for(unsigned i
= 0; i
< rtype
->get_image_count(); i
++)
211 tmand
|= rtype
->get_image_info(i
).mandatory
;
212 if((bios
= coretype
->get_biosname()) != "") {
213 //This thing has a BIOS.
215 std::string basename
= CORE().setcache
->get("firmwarepath") + "/" + bios
;
216 romimg
[0] = fileimage::image(lsnes_image_hasher
, basename
, "",
217 xlate_info(coretype
->get_image_info(0)));
218 if(zip::file_exists(basename
+ ".xml"))
219 romxml
[0] = fileimage::image(lsnes_image_hasher
, basename
+ ".xml", "",
221 pmand
|= rtype
->get_image_info(0).mandatory
;
223 romimg
[romidx
] = fileimage::image(lsnes_image_hasher
, file
, "",
224 xlate_info(coretype
->get_image_info(romidx
)));
225 if(zip::file_exists(file
+ ".xml"))
226 romxml
[romidx
] = fileimage::image(lsnes_image_hasher
, file
+ ".xml", "", get_xml_info());
227 pmand
|= rtype
->get_image_info(romidx
).mandatory
;
228 msu1_base
= zip::resolverel(file
, "");
231 throw std::runtime_error("Required ROM images missing");
234 load_bundle(file
, spec
, tmpprefer
);
237 void loaded_rom::load_bundle(const std::string
& file
, std::istream
& spec
, const std::string
& tmpprefer
) throw(std::bad_alloc
,
241 load_filename
= file
;
242 std::vector
<std::string
> lines
;
243 while(std::getline(spec
, s
))
244 lines
.push_back(strip_CR(s
));
245 std::string platname
= "";
246 std::string platreg
= "";
247 for(auto i
: lines
) {
249 if(tmp
= regex("type[ \t]+(.+)", i
))
251 if(tmp
= regex("region[ \t]+(.+)", i
))
256 rtype
= find_core_by_name(platname
, tmpprefer
);
258 (stringfmt() << "Not a valid system type '" << platname
<< "'").throwex();
261 bool goodreg
= false;
262 orig_region
= &rtype
->get_preferred_region();
263 for(auto i
: rtype
->get_regions())
264 if(i
->get_iname() == platreg
) {
268 if(!goodreg
&& platreg
!= "")
269 (stringfmt() << "Not a valid system region '" << platreg
<< "'").throwex();
270 region
= orig_region
;
273 std::string cromimg
[ROM_SLOT_COUNT
];
274 std::string cromxml
[ROM_SLOT_COUNT
];
275 for(auto i
: lines
) {
277 if(!(tmp
= regex("(rom|xml)[ \t]+([^ \t]+)[ \t]+(.*)", i
)))
279 size_t idxs
= rtype
->get_image_count();
281 for(size_t i
= 0; i
< idxs
; i
++)
282 if(rtype
->get_image_info(i
).iname
== tmp
[2])
285 (stringfmt() << "Not a valid ROM name '" << tmp
[2] << "'").throwex();
287 cromimg
[idx
] = tmp
[3];
289 cromxml
[idx
] = tmp
[3];
293 unsigned mask1
= 0, mask2
= 0;
294 for(size_t i
= 0; i
< rtype
->get_image_count(); i
++) {
295 auto ii
= rtype
->get_image_info(i
);
296 mask1
|= ii
.mandatory
;
298 mask2
|= ii
.mandatory
;
299 if(cromimg
[i
] == "" && cromxml
[i
] != "") {
300 messages
<< "WARNING: Slot " << ii
.iname
<< ": XML without ROM." << std::endl
;
305 throw std::runtime_error("Required ROM missing");
308 for(size_t i
= 0; i
< rtype
->get_image_count(); i
++) {
309 romimg
[i
] = fileimage::image(lsnes_image_hasher
, cromimg
[i
], file
,
310 xlate_info(rtype
->get_image_info(i
)));
311 romxml
[i
] = fileimage::image(lsnes_image_hasher
, cromxml
[i
], file
, get_xml_info());
313 record_files(*this); //Have to do this before patching.
316 for(auto i
: lines
) {
318 if(!(tmp
= regex("patch([+-][0-9]+)?[ \t]+([^ \t]+)[ \t]+(.*)", i
)))
320 size_t idxs
= rtype
->get_image_count();
322 for(size_t i
= 0; i
< idxs
; i
++)
323 if(rtype
->get_image_info(i
).iname
== tmp
[2])
326 (stringfmt() << "Not a valid ROM name '" << tmp
[2] << "'").throwex();
329 offset
= parse_value
<int32_t>(tmp
[1]);
330 romimg
[idx
].patch(zip::readrel(tmp
[3], file
), offset
);
335 msu1_base
= zip::resolverel(cromimg
[1], file
);
337 msu1_base
= zip::resolverel(cromimg
[0], file
);
342 bool filter_by_core(core_type
& ctype
, const std::string
& core
)
344 return (core
== "" || ctype
.get_core_identifier() == core
);
347 bool filter_by_type(core_type
& ctype
, const std::string
& type
)
349 return (type
== "" || ctype
.get_iname() == type
);
352 bool filter_by_region(core_type
& ctype
, const std::string
& region
)
356 for(auto i
: ctype
.get_regions())
357 if(i
->get_iname() == region
)
362 bool filter_by_extension(core_type
& ctype
, const std::string
& file
)
364 regex_results tmp
= regex(".*\\.([^.]*)", file
);
367 std::string ext
= tmp
[1];
368 return ctype
.is_known_extension(ext
);
371 bool filter_by_fileset(core_type
& ctype
, const std::string file
[ROM_SLOT_COUNT
])
373 uint32_t m
= 0, t
= 0;
374 for(unsigned i
= 0; i
< ROM_SLOT_COUNT
; i
++) {
375 if(i
>= ctype
.get_image_count() && file
[i
] != "")
377 auto s
= ctype
.get_image_info(i
);
385 core_region
* detect_region(core_type
* t
, const std::string
& region
)
387 core_region
* r
= NULL
;
388 for(auto i
: t
->get_regions())
389 if(i
->get_iname() == region
)
391 if(!r
&& region
!= "")
392 (stringfmt() << "Not a valid system region '" << region
<< "'").throwex();
393 if(!r
) r
= &t
->get_preferred_region(); //Default region.
398 loaded_rom::loaded_rom(const std::string
& file
, const std::string
& core
, const std::string
& type
,
399 const std::string
& _region
)
402 core_region
* r
= NULL
;
403 bool fullspec
= (core
!= "" && type
!= "");
404 for(auto i
: core_type::get_core_types()) {
405 if(!filter_by_core(*i
, core
))
407 if(!filter_by_type(*i
, type
))
409 if(!fullspec
&& !filter_by_region(*i
, _region
))
411 if(!fullspec
&& !filter_by_extension(*i
, file
))
415 if(!t
) throw std::runtime_error("No matching core found");
416 r
= detect_region(t
, _region
);
417 unsigned pmand
= 0, tmand
= 0;
418 for(unsigned i
= 0; i
< t
->get_image_count(); i
++)
419 tmand
|= t
->get_image_info(i
).mandatory
;
420 std::string bios
= t
->get_biosname();
421 unsigned romidx
= (bios
!= "") ? 1 : 0;
423 std::string basename
= CORE().setcache
->get("firmwarepath") + "/" + bios
;
424 romimg
[0] = fileimage::image(lsnes_image_hasher
, basename
, "", xlate_info(t
->get_image_info(0)));
425 if(zip::file_exists(basename
+ ".xml"))
426 romxml
[0] = fileimage::image(lsnes_image_hasher
, basename
+ ".xml", "", get_xml_info());
427 pmand
|= t
->get_image_info(0).mandatory
;
429 romimg
[romidx
] = fileimage::image(lsnes_image_hasher
, file
, "", xlate_info(t
->get_image_info(romidx
)));
430 if(zip::file_exists(file
+ ".xml"))
431 romxml
[romidx
] = fileimage::image(lsnes_image_hasher
, file
+ ".xml", "", get_xml_info());
432 pmand
|= t
->get_image_info(romidx
).mandatory
;
433 msu1_base
= zip::resolverel(file
, "");
436 throw std::runtime_error("Required ROM images missing");
438 orig_region
= region
= r
;
441 loaded_rom::loaded_rom(const std::string file
[ROM_SLOT_COUNT
], const std::string
& core
, const std::string
& type
,
442 const std::string
& _region
)
445 core_region
* r
= NULL
;
446 bool fullspec
= (core
!= "" && type
!= "");
447 for(auto i
: core_type::get_core_types()) {
448 if(!filter_by_core(*i
, core
)) {
451 if(!filter_by_type(*i
, type
)) {
454 if(!fullspec
&& !filter_by_region(*i
, _region
)) {
457 if(!fullspec
&& !filter_by_fileset(*i
, file
)) {
462 if(!t
) throw std::runtime_error("No matching core found");
463 r
= detect_region(t
, _region
);
464 std::string bios
= t
->get_biosname();
465 unsigned romidx
= (bios
!= "") ? 1 : 0;
466 unsigned pmand
= 0, tmand
= 0;
467 for(unsigned i
= 0; i
< 27; i
++) {
468 if(i
>= t
->get_image_count())
471 pmand
|= t
->get_image_info(i
).mandatory
;
472 tmand
|= t
->get_image_info(i
).mandatory
;
473 romimg
[i
] = fileimage::image(lsnes_image_hasher
, file
[i
], "", xlate_info(t
->get_image_info(i
)));
474 if(zip::file_exists(file
[i
] + ".xml"))
475 romxml
[i
] = fileimage::image(lsnes_image_hasher
, file
[i
] + ".xml", "", get_xml_info());
477 msu1_base
= zip::resolverel(file
[romidx
], "");
480 throw std::runtime_error("Required ROM images missing");
482 orig_region
= region
= r
;
485 void loaded_rom::load(std::map
<std::string
, std::string
>& settings
, uint64_t rtc_sec
, uint64_t rtc_subsec
)
486 throw(std::bad_alloc
, std::runtime_error
)
489 core_type
* old_type
= current_rom_type
;
490 core_core
* old_core
= current_rom_type
->get_core();
491 current_rom_type
= &get_null_type();
492 if(!orig_region
&& rtype
!= &get_null_type())
493 orig_region
= &rtype
->get_preferred_region();
495 region
= orig_region
;
496 if(rtype
&& !orig_region
->compatible_with(*region
))
497 throw std::runtime_error("Trying to force incompatible region");
498 if(rtype
&& !rtype
->set_region(*region
))
499 throw std::runtime_error("Trying to force unknown region");
501 core_romimage images
[ROM_SLOT_COUNT
];
502 for(size_t i
= 0; i
< ROM_SLOT_COUNT
; i
++) {
503 images
[i
].markup
= (const char*)romxml
[i
];
504 images
[i
].data
= (const unsigned char*)romimg
[i
];
505 images
[i
].size
= (size_t)romimg
[i
];
507 if(!rtype
->load(images
, settings
, rtc_sec
, rtc_subsec
))
508 throw std::runtime_error("Can't load cartridge ROM");
510 region
= &rtype
->get_region();
512 auto nominal_fps
= rtype
->get_video_rate();
513 auto nominal_hz
= rtype
->get_audio_rate();
514 core
.framerate
->set_nominal_framerate(1.0 * nominal_fps
.first
/ nominal_fps
.second
);
515 core
.mdumper
->on_rate_change(nominal_hz
.first
, nominal_hz
.second
);
517 current_rom_type
= rtype
;
518 current_region
= region
;
519 //If core changes, unload the cartridge.
520 if(old_core
!= current_rom_type
->get_core())
522 old_core
->debug_reset();
523 old_core
->unload_cartridge();
526 core
.dispatch
->core_changed(old_type
!= current_rom_type
);
529 std::map
<std::string
, std::vector
<char>> load_sram_commandline(const std::vector
<std::string
>& cmdline
)
530 throw(std::bad_alloc
, std::runtime_error
)
532 std::map
<std::string
, std::vector
<char>> ret
;
534 for(auto i
: cmdline
) {
535 if(opt
= regex("--continue=(.+)", i
)) {
536 zip::reader
r(opt
[1]);
538 auto sramname
= regex("sram\\.(.*)", j
);
541 std::istream
& x
= r
[j
];
543 std::vector
<char> out
;
544 boost::iostreams::back_insert_device
<std::vector
<char>> rd(out
);
545 boost::iostreams::copy(x
, rd
);
547 ret
[sramname
[1]] = out
;
554 } else if(opt
= regex("--sram-([^=]+)=(.+)", i
)) {
556 ret
[opt
[1]] = zip::readrel(opt
[2], "");
557 } catch(std::bad_alloc
& e
) {
559 } catch(std::runtime_error
& e
) {
560 throw std::runtime_error("Can't load SRAM '" + opt
[1] + "': " + e
.what());
567 std::vector
<char> loaded_rom::save_core_state(bool nochecksum
) throw(std::bad_alloc
, std::runtime_error
)
569 std::vector
<char> ret
;
570 rtype
->serialize(ret
);
573 size_t offset
= ret
.size();
574 unsigned char tmp
[32];
575 #ifdef USE_LIBGCRYPT_SHA256
576 gcry_md_hash_buffer(GCRY_MD_SHA256
, tmp
, &ret
[0], offset
);
578 sha256::hash(tmp
, ret
);
580 ret
.resize(offset
+ 32);
581 memcpy(&ret
[offset
], tmp
, 32);
585 void loaded_rom::load_core_state(const std::vector
<char>& buf
, bool nochecksum
) throw(std::runtime_error
)
588 rtype
->unserialize(&buf
[0], buf
.size());
593 throw std::runtime_error("Savestate corrupt");
594 if(!savestate_no_check(*CORE().settings
)) {
595 unsigned char tmp
[32];
596 #ifdef USE_LIBGCRYPT_SHA256
597 gcry_md_hash_buffer(GCRY_MD_SHA256
, tmp
, &buf
[0], buf
.size() - 32);
599 sha256::hash(tmp
, reinterpret_cast<const uint8_t*>(&buf
[0]), buf
.size() - 32);
601 if(memcmp(tmp
, &buf
[buf
.size() - 32], 32))
602 throw std::runtime_error("Savestate corrupt");
604 rtype
->unserialize(&buf
[0], buf
.size() - 32);
607 bool loaded_rom::is_gamepak(const std::string
& filename
) throw(std::bad_alloc
, std::runtime_error
)
609 std::istream
* spec
= NULL
;
611 spec
= &zip::openrel(filename
, "");
613 std::getline(*spec
, line
);
615 bool ret
= (line
== "[GAMEPACK FILE]");
624 void set_hasher_callback(std::function
<void(uint64_t, uint64_t)> cb
)
626 lsnes_image_hasher
.set_callback(cb
);
629 std::map
<std::string
, core_type
*> preferred_core
;