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/settings.hpp"
11 #include "core/window.hpp"
12 #include "interface/cover.hpp"
13 #include "interface/romtype.hpp"
14 #include "interface/callbacks.hpp"
15 #include "library/pixfmt-rgb16.hpp"
16 #include "library/controller-data.hpp"
17 #include "library/patch.hpp"
18 #include "library/sha256.hpp"
19 #include "library/string.hpp"
20 #include "library/zip.hpp"
28 #include <boost/iostreams/categories.hpp>
29 #include <boost/iostreams/copy.hpp>
30 #include <boost/iostreams/stream.hpp>
31 #include <boost/iostreams/stream_buffer.hpp>
32 #include <boost/iostreams/filter/symmetric.hpp>
33 #include <boost/iostreams/filter/zlib.hpp>
34 #include <boost/iostreams/filtering_stream.hpp>
35 #include <boost/iostreams/device/back_inserter.hpp>
36 #include <boost/filesystem.hpp>
38 #ifdef BOOST_FILESYSTEM3
39 namespace boost_fs
= boost::filesystem3
;
41 namespace boost_fs
= boost::filesystem
;
46 const char* null_chars
= "F";
47 uint16_t null_cover_fbmem
[512 * 448];
50 struct framebuffer_info null_fbinfo
= {
51 &_pixel_format_bgr16
, //Format.
52 (char*)null_cover_fbmem
, //Memory.
53 512, 448, 1024, //Physical size.
54 512, 448, 1024, //Logical size.
58 port_index_triple sync_triple
= {true, 0, 0, 0 };
60 struct interface_device_reg null_registers
[] = {
64 struct _core_null
: public core_core
, public core_type
, public core_region
, public core_sysregion
66 _core_null() : core_core({}, {}), core_type({{
77 }}), core_region({{"null", "(null)", 0, 0, false, {1, 60}, {0}}}),
78 core_sysregion("null", *this, *this) {}
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 std::pair
<unsigned, unsigned> c_audio_rate() { return std::make_pair(48000, 1); }
83 std::map
<std::string
, std::vector
<char>> c_save_sram() throw (std::bad_alloc
) {
84 std::map
<std::string
, std::vector
<char>> x
;
87 void c_load_sram(std::map
<std::string
, std::vector
<char>>& sram
) throw (std::bad_alloc
) {}
88 void c_serialize(std::vector
<char>& out
) { out
.clear(); }
89 void c_unserialize(const char* in
, size_t insize
) {}
90 core_region
& c_get_region() { return *this; }
92 void c_unload_cartridge() {}
93 std::pair
<uint32_t, uint32_t> c_get_scale_factors(uint32_t width
, uint32_t height
) {
94 return std::make_pair(1, 1);
96 void c_install_handler() {}
97 void c_uninstall_handler() {}
100 bool c_get_pflag() { return false; }
101 void c_set_pflag(bool pflag
) {}
102 framebuffer_raw
& c_draw_cover() {
103 static framebuffer_raw
x(null_fbinfo
);
104 for(size_t i
= 0; i
< sizeof(null_cover_fbmem
)/sizeof(null_cover_fbmem
[0]); i
++)
105 null_cover_fbmem
[i
] = 0x0000;
106 std::string message
= "NO ROM LOADED";
107 cover_render_string(null_cover_fbmem
, 204, 220, message
, 0xFFFF, 0x0000, 512, 448, 1024, 2);
110 std::string
c_get_core_shortname() { return "null"; }
111 void c_pre_emulate_frame(controller_frame
& cf
) {}
112 void c_execute_action(unsigned id
, const std::vector
<interface_action_paramval
>& p
) {}
113 const interface_device_reg
* c_get_registers() { return null_registers
; }
114 int t_load_rom(core_romimage
* img
, std::map
<std::string
, std::string
>& settings
,
115 uint64_t secs
, uint64_t subsecs
)
119 controller_set
t_controllerconfig(std::map
<std::string
, std::string
>& settings
)
122 x
.ports
.push_back(&get_default_system_port_type());
123 x
.portindex
.indices
.push_back(sync_triple
);
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; }
133 core_type
* current_rom_type
= &core_null
;
134 core_region
* current_region
= &core_null
;
136 core_type
* find_core_by_extension(const std::string
& ext
, const std::string
& tmpprefer
)
138 std::string key
= "ext:" + ext
;
139 std::list
<core_type
*> possible
= core_type::get_core_types();
140 core_type
* fallback
= NULL
;
141 core_type
* preferred
= preferred_core
.count(key
) ? preferred_core
[key
] : NULL
;
142 //Tmpprefer overrides normal preferred core.
144 for(auto i
: possible
)
145 if(i
->get_iname() == tmpprefer
)
147 for(auto i
: possible
)
148 if(i
->is_known_extension(ext
)) {
150 if(!preferred
&& i
->get_core_shortname() == preferred_core_default
)
158 core_type
* find_core_by_name(const std::string
& name
, const std::string
& tmpprefer
)
160 std::string key
= "type:" + name
;
161 std::list
<core_type
*> possible
= core_type::get_core_types();
162 core_type
* fallback
= NULL
;
163 core_type
* preferred
= preferred_core
.count(key
) ? preferred_core
[key
] : NULL
;
164 //Tmpprefer overrides normal preferred core.
166 for(auto i
: possible
)
167 if(i
->get_iname() == tmpprefer
)
169 for(auto i
: possible
)
170 if(i
->get_iname() == name
) {
172 if(!preferred
&& i
->get_core_shortname() == preferred_core_default
)
180 bool file_exists(const std::string
& name
)
183 delete &open_file_relative(name
, "");
191 loaded_slot::loaded_slot() throw(std::bad_alloc
)
196 filename_flag
= false;
199 loaded_slot::loaded_slot(const std::string
& filename
, const std::string
& base
,
200 const struct core_romimage_info
& imginfo
, bool xml_flag
) throw(std::bad_alloc
, std::runtime_error
)
202 unsigned headered
= 0;
207 filename_flag
= (!xml
&& imginfo
.pass_mode
);
210 //XMLs are always loaded, no matter what.
211 if(!xml
&& imginfo
.pass_mode
) {
212 std::string _filename
= filename
;
213 //Translate the passed filename to absolute one.
214 _filename
= resolve_file_relative(_filename
, base
);
215 _filename
= boost_fs::absolute(boost_fs::path(_filename
)).string();
216 filename_flag
= true;
217 data
.resize(_filename
.length());
218 std::copy(_filename
.begin(), _filename
.end(), data
.begin());
219 //Compute the SHA-256.
220 std::istream
& s
= open_file_relative(filename
, "");
224 while((block
= s
.readsome(buffer
, 8192)))
225 hash
.write(buffer
, block
);
226 sha_256
= hash
.read();
231 filename_flag
= false;
233 data
= read_file_relative(filename
, base
);
234 if(!xml
&& imginfo
.headersize
)
235 headered
= ((data
.size() % (2 * imginfo
.headersize
)) == imginfo
.headersize
) ? imginfo
.headersize
: 0;
236 if(headered
&& !xml
) {
237 if(data
.size() >= headered
) {
238 memmove(&data
[0], &data
[headered
], data
.size() - headered
);
239 data
.resize(data
.size() - headered
);
244 sha_256
= sha256::hash(data
);
246 size_t osize
= data
.size();
247 data
.resize(osize
+ 1);
252 void loaded_slot::patch(const std::vector
<char>& patch
, int32_t offset
) throw(std::bad_alloc
, std::runtime_error
)
255 throw std::runtime_error("CD images can't be patched on the fly");
257 std::vector
<char> data2
= data
;
259 data2
.resize(data2
.size() - 1);
260 data2
= do_patch_file(data2
, patch
, offset
);
261 //Mark the slot as valid and update hash.
263 std::string new_sha256
= sha256::hash(data2
);
265 size_t osize
= data2
.size();
266 data2
.resize(osize
+ 1);
270 sha_256
= new_sha256
;
276 std::pair
<core_type
*, core_region
*> get_current_rom_info() throw()
278 return std::make_pair(current_rom_type
, current_region
);
281 loaded_rom::loaded_rom() throw()
284 region
= orig_region
= &core_null
;
287 loaded_rom::loaded_rom(const std::string
& file
, core_type
& ctype
) throw(std::bad_alloc
, std::runtime_error
)
290 region
= orig_region
= &rtype
->get_preferred_region();
293 if((bios
= ctype
.get_biosname()) != "") {
294 //This thing has a BIOS.
296 std::string basename
= lsnes_vset
["firmwarepath"].str() + "/" + bios
;
297 romimg
[0] = loaded_slot(basename
, "", ctype
.get_image_info(0), false);
298 if(file_exists(basename
+ ".xml"))
299 romxml
[0] = loaded_slot(basename
+ ".xml", "", ctype
.get_image_info(0), true);
301 romimg
[romidx
] = loaded_slot(file
, "", ctype
.get_image_info(romidx
), false);
302 if(file_exists(file
+ ".xml"))
303 romxml
[romidx
] = loaded_slot(file
+ ".xml", "", ctype
.get_image_info(romidx
), true);
304 msu1_base
= resolve_file_relative(file
, "");
308 loaded_rom::loaded_rom(const std::string
& file
, const std::string
& tmpprefer
) throw(std::bad_alloc
,
311 std::istream
& spec
= open_file_relative(file
, "");
313 std::getline(spec
, s
);
315 load_filename
= file
;
316 if(!spec
|| s
!= "[GAMEPACK FILE]") {
317 //This is a Raw ROM image.
319 std::string ext
= regex(".*\\.([^.]*)?", file
, "Unknown ROM file type")[1];
320 core_type
* coretype
= find_core_by_extension(ext
, tmpprefer
);
322 throw std::runtime_error("Unknown ROM file type");
324 region
= orig_region
= &rtype
->get_preferred_region();
327 if((bios
= coretype
->get_biosname()) != "") {
328 //This thing has a BIOS.
330 std::string basename
= lsnes_vset
["firmwarepath"].str() + "/" + bios
;
331 romimg
[0] = loaded_slot(basename
, "", coretype
->get_image_info(0), false);
332 if(file_exists(basename
+ ".xml"))
333 romxml
[0] = loaded_slot(basename
+ ".xml", "", coretype
->get_image_info(0), true);
335 romimg
[romidx
] = loaded_slot(file
, "", coretype
->get_image_info(romidx
), false);
336 if(file_exists(file
+ ".xml"))
337 romxml
[romidx
] = loaded_slot(file
+ ".xml", "", coretype
->get_image_info(romidx
), true);
338 msu1_base
= resolve_file_relative(file
, "");
341 std::vector
<std::string
> lines
;
342 while(std::getline(spec
, s
))
343 lines
.push_back(strip_CR(s
));
344 std::string platname
= "";
345 std::string platreg
= "";
346 for(auto i
: lines
) {
348 if(tmp
= regex("type[ \t]+(.+)", i
))
350 if(tmp
= regex("region[ \t]+(.+)", i
))
355 rtype
= find_core_by_name(platname
, tmpprefer
);
357 (stringfmt() << "Not a valid system type '" << platname
<< "'").throwex();
360 bool goodreg
= false;
361 orig_region
= &rtype
->get_preferred_region();
362 for(auto i
: rtype
->get_regions())
363 if(i
->get_iname() == platreg
) {
367 if(!goodreg
&& platreg
!= "")
368 (stringfmt() << "Not a valid system region '" << platreg
<< "'").throwex();
369 region
= orig_region
;
372 std::string cromimg
[sizeof(romimg
)/sizeof(romimg
[0])];
373 std::string cromxml
[sizeof(romimg
)/sizeof(romimg
[0])];
374 for(auto i
: lines
) {
376 if(!(tmp
= regex("(rom|xml)[ \t]+([^ \t]+)[ \t]+(.*)", i
)))
378 size_t idxs
= rtype
->get_image_count();
380 for(size_t i
= 0; i
< idxs
; i
++)
381 if(rtype
->get_image_info(i
).iname
== tmp
[2])
384 (stringfmt() << "Not a valid ROM name '" << tmp
[2] << "'").throwex();
386 cromimg
[idx
] = tmp
[3];
388 cromxml
[idx
] = tmp
[3];
392 unsigned mask1
= 0, mask2
= 0;
393 for(size_t i
= 0; i
< rtype
->get_image_count(); i
++) {
394 auto ii
= rtype
->get_image_info(i
);
395 mask1
|= ii
.mandatory
;
397 mask2
|= ii
.mandatory
;
398 if(cromimg
[i
] == "" && cromxml
[i
] != "") {
399 messages
<< "WARNING: Slot " << ii
.iname
<< ": XML without ROM." << std::endl
;
404 throw std::runtime_error("Required ROM missing");
407 for(size_t i
= 0; i
< rtype
->get_image_count(); i
++) {
408 romimg
[i
] = loaded_slot(cromimg
[i
], file
, rtype
->get_image_info(i
), false);
409 romxml
[i
] = loaded_slot(cromxml
[i
], file
, rtype
->get_image_info(i
), true);
413 for(auto i
: lines
) {
415 if(!(tmp
= regex("patch([+-][0-9]+)?[ \t]+([^ \t]+)[ \t]+(.*)", i
)))
417 size_t idxs
= rtype
->get_image_count();
419 for(size_t i
= 0; i
< idxs
; i
++)
420 if(rtype
->get_image_info(i
).iname
== tmp
[2])
423 (stringfmt() << "Not a valid ROM name '" << tmp
[2] << "'").throwex();
426 offset
= parse_value
<int32_t>(tmp
[1]);
427 romimg
[idx
].patch(read_file_relative(tmp
[3], file
), offset
);
432 msu1_base
= resolve_file_relative(cromimg
[1], file
);
434 msu1_base
= resolve_file_relative(cromimg
[0], file
);
437 void loaded_rom::load(std::map
<std::string
, std::string
>& settings
, uint64_t rtc_sec
, uint64_t rtc_subsec
)
438 throw(std::bad_alloc
, std::runtime_error
)
440 core_core
* old_core
= current_rom_type
->get_core();
441 current_rom_type
= &core_null
;
442 if(!orig_region
&& rtype
!= &core_null
)
443 orig_region
= &rtype
->get_preferred_region();
445 region
= orig_region
;
446 if(rtype
&& !orig_region
->compatible_with(*region
))
447 throw std::runtime_error("Trying to force incompatible region");
448 if(rtype
&& !rtype
->set_region(*region
))
449 throw std::runtime_error("Trying to force unknown region");
451 core_romimage images
[sizeof(romimg
)/sizeof(romimg
[0])];
452 for(size_t i
= 0; i
< sizeof(romimg
)/sizeof(romimg
[0]); i
++) {
453 images
[i
].markup
= (const char*)romxml
[i
];
454 images
[i
].data
= (const unsigned char*)romimg
[i
];
455 images
[i
].size
= (size_t)romimg
[i
];
457 if(!rtype
->load(images
, settings
, rtc_sec
, rtc_subsec
))
458 throw std::runtime_error("Can't load cartridge ROM");
460 region
= &rtype
->get_region();
462 auto nominal_fps
= rtype
->get_video_rate();
463 auto nominal_hz
= rtype
->get_audio_rate();
464 set_nominal_framerate(1.0 * nominal_fps
.first
/ nominal_fps
.second
);
465 information_dispatch::do_sound_rate(nominal_hz
.first
, nominal_hz
.second
);
466 current_rom_type
= rtype
;
467 current_region
= region
;
468 current_romfile
= load_filename
;
469 //If core changes, unload the cartridge.
470 if(old_core
!= current_rom_type
->get_core())
471 try { old_core
->unload_cartridge(); } catch(...) {}
472 refresh_cart_mappings();
475 std::map
<std::string
, std::vector
<char>> load_sram_commandline(const std::vector
<std::string
>& cmdline
)
476 throw(std::bad_alloc
, std::runtime_error
)
478 std::map
<std::string
, std::vector
<char>> ret
;
480 for(auto i
: cmdline
) {
481 if(opt
= regex("--continue=(.+)", i
)) {
482 zip_reader
r(opt
[1]);
484 auto sramname
= regex("sram\\.(.*)", j
);
487 std::istream
& x
= r
[j
];
489 std::vector
<char> out
;
490 boost::iostreams::back_insert_device
<std::vector
<char>> rd(out
);
491 boost::iostreams::copy(x
, rd
);
493 ret
[sramname
[1]] = out
;
500 } else if(opt
= regex("--sram-([^=]+)=(.+)", i
)) {
502 ret
[opt
[1]] = read_file_relative(opt
[2], "");
503 } catch(std::bad_alloc
& e
) {
505 } catch(std::runtime_error
& e
) {
506 throw std::runtime_error("Can't load SRAM '" + opt
[1] + "': " + e
.what());
513 std::vector
<char> loaded_rom::save_core_state(bool nochecksum
) throw(std::bad_alloc
)
515 std::vector
<char> ret
;
516 rtype
->serialize(ret
);
519 size_t offset
= ret
.size();
520 unsigned char tmp
[32];
521 sha256::hash(tmp
, ret
);
522 ret
.resize(offset
+ 32);
523 memcpy(&ret
[offset
], tmp
, 32);
527 void loaded_rom::load_core_state(const std::vector
<char>& buf
, bool nochecksum
) throw(std::runtime_error
)
530 rtype
->unserialize(&buf
[0], buf
.size());
535 throw std::runtime_error("Savestate corrupt");
536 unsigned char tmp
[32];
537 sha256::hash(tmp
, reinterpret_cast<const uint8_t*>(&buf
[0]), buf
.size() - 32);
538 if(memcmp(tmp
, &buf
[buf
.size() - 32], 32))
539 throw std::runtime_error("Savestate corrupt");
540 rtype
->unserialize(&buf
[0], buf
.size() - 32);;
543 std::map
<std::string
, core_type
*> preferred_core
;
544 std::string preferred_core_default
;
545 std::string current_romfile
;