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 "library/pixfmt-rgb16.hpp"
15 #include "library/controller-data.hpp"
16 #include "library/patch.hpp"
17 #include "library/sha256.hpp"
18 #include "library/string.hpp"
19 #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>
35 #include <boost/filesystem.hpp>
37 #ifdef BOOST_FILESYSTEM3
38 namespace boost_fs
= boost::filesystem3
;
40 namespace boost_fs
= boost::filesystem
;
45 const char* null_chars
= "F";
46 uint16_t null_cover_fbmem
[512 * 448];
49 struct framebuffer_info null_fbinfo
= {
50 &_pixel_format_bgr16
, //Format.
51 (char*)null_cover_fbmem
, //Memory.
52 512, 448, 1024, //Physical size.
53 512, 448, 1024, //Logical size.
57 port_type
* port_types
[] = {NULL
};
58 port_index_triple sync_triple
= {true, 0, 0, 0 };
60 core_setting_group null_settings
;
62 unsigned null_compatible
[] = {0, UINT_MAX
};
63 struct core_region_params _null_region
= {
64 "null", "(null)", 0, 0, false, {1, 60}, null_compatible
66 core_region
null_region(_null_region
);
67 core_region
* null_regions
[] = {&null_region
, NULL
};
68 core_romimage_info
* null_images
[] = {NULL
};
69 core_core_params _core_null
= {
70 .core_identifier
= []() -> std::string
{ return "null core"; },
71 .set_region
= [](core_region
& reg
) -> bool { return true; },
72 .video_rate
= []() -> std::pair
<unsigned, unsigned> { return std::make_pair(60, 1); },
73 .audio_rate
= []() -> std::pair
<unsigned, unsigned> { return std::make_pair(48000, 1); },
75 .save_sram
= []() -> std::map
<std::string
, std::vector
<char>> {
76 std::map
<std::string
, std::vector
<char>> x
;
79 .load_sram
= [](std::map
<std::string
, std::vector
<char>>& sram
) -> void {},
80 .serialize
= [](std::vector
<char>& out
) -> void { out
.clear(); },
81 .unserialize
= [](const char* in
, size_t insize
) -> void {},
82 .get_region
= []() -> core_region
& { return null_region
; },
83 .power
= []() -> void {},
84 .unload_cartridge
= []() -> void {},
85 .get_scale_factors
= [](uint32_t width
, uint32_t height
) -> std::pair
<uint32_t, uint32_t> {
86 return std::make_pair(1, 1);
88 .install_handler
= []() -> void {},
89 .uninstall_handler
= []() -> void {},
90 .emulate
= []() -> void {},
91 .runtosave
= []() -> void {},
92 .get_pflag
= []() -> bool { return false; },
93 .set_pflag
= [](bool pflag
) -> void {},
94 .request_reset
= [](long delay
, bool hard
) -> void {},
95 .port_types
= port_types
,
96 .draw_cover
= []() -> framebuffer_raw
& {
97 static framebuffer_raw
x(null_fbinfo
);
98 for(size_t i
= 0; i
< sizeof(null_cover_fbmem
)/sizeof(null_cover_fbmem
[0]); i
++)
99 null_cover_fbmem
[i
] = 0x0000;
100 std::string message
= "NO ROM LOADED";
101 cover_render_string(null_cover_fbmem
, 204, 220, message
, 0xFFFF, 0x0000, 512, 448, 1024, 2);
104 .get_core_shortname
= []() -> std::string
{ return "null"; },
105 .pre_emulate_frame
= [](controller_frame
& cf
) -> void {}
107 core_core
core_null(_core_null
);
109 core_type_params _type_null
= {
110 "null", "(null)", 9999, 0,
111 [](core_romimage
* img
, std::map
<std::string
, std::string
>& settings
,
112 uint64_t secs
, uint64_t subsecs
) -> int {
115 [](std::map
<std::string
, std::string
>& settings
) -> controller_set
{
117 x
.ports
.push_back(&get_default_system_port_type());
118 x
.portindex
.indices
.push_back(sync_triple
);
121 "", NULL
, null_regions
, null_images
, &null_settings
, &core_null
,
122 []() -> std::pair
<uint64_t, uint64_t> { return std::make_pair(0ULL, 0ULL); },
123 []() -> std::list
<core_vma_info
> {
124 std::list
<core_vma_info
> x
;
127 []() -> std::set
<std::string
> {
128 std::set
<std::string
> x
;
132 core_type
type_null(_type_null
);
133 core_sysregion
sysregion_null("null", type_null
, null_region
);
135 core_type
* current_rom_type
= &type_null
;
136 core_region
* current_region
= &null_region
;
138 core_type
* find_core_by_extension(const std::string
& ext
)
140 std::string key
= "ext:" + ext
;
141 std::list
<core_type
*> possible
= core_type::get_core_types();
142 core_type
* fallback
= NULL
;
143 core_type
* preferred
= preferred_core
.count(key
) ? preferred_core
[key
] : NULL
;
144 for(auto i
: possible
)
145 if(i
->is_known_extension(ext
)) {
147 if(!preferred
&& i
->get_core_shortname() == preferred_core_default
)
155 core_type
* find_core_by_name(const std::string
& name
)
157 std::string key
= "type:" + name
;
158 std::list
<core_type
*> possible
= core_type::get_core_types();
159 core_type
* fallback
= NULL
;
160 core_type
* preferred
= preferred_core
.count(key
) ? preferred_core
[key
] : NULL
;
161 for(auto i
: possible
)
162 if(i
->get_iname() == name
) {
164 if(!preferred
&& i
->get_core_shortname() == preferred_core_default
)
172 bool file_exists(const std::string
& name
)
175 delete &open_file_relative(name
, "");
183 loaded_slot::loaded_slot() throw(std::bad_alloc
)
188 filename_flag
= false;
191 loaded_slot::loaded_slot(const std::string
& filename
, const std::string
& base
,
192 const struct core_romimage_info
& imginfo
, bool xml_flag
) throw(std::bad_alloc
, std::runtime_error
)
194 unsigned headered
= 0;
199 filename_flag
= (!xml
&& imginfo
.pass_mode
);
202 //XMLs are always loaded, no matter what.
203 if(!xml
&& imginfo
.pass_mode
) {
204 std::string _filename
= filename
;
205 //Translate the passed filename to absolute one.
206 _filename
= resolve_file_relative(_filename
, base
);
207 _filename
= boost_fs::absolute(boost_fs::path(_filename
)).string();
208 filename_flag
= true;
209 data
.resize(_filename
.length());
210 std::copy(_filename
.begin(), _filename
.end(), data
.begin());
211 //Compute the SHA-256.
212 std::istream
& s
= open_file_relative(filename
, "");
216 while((block
= s
.readsome(buffer
, 8192)))
217 hash
.write(buffer
, block
);
218 sha_256
= hash
.read();
223 filename_flag
= false;
225 data
= read_file_relative(filename
, base
);
226 if(!xml
&& imginfo
.headersize
)
227 headered
= ((data
.size() % (2 * imginfo
.headersize
)) == imginfo
.headersize
) ? imginfo
.headersize
: 0;
228 if(headered
&& !xml
) {
229 if(data
.size() >= headered
) {
230 memmove(&data
[0], &data
[headered
], data
.size() - headered
);
231 data
.resize(data
.size() - headered
);
236 sha_256
= sha256::hash(data
);
238 size_t osize
= data
.size();
239 data
.resize(osize
+ 1);
244 void loaded_slot::patch(const std::vector
<char>& patch
, int32_t offset
) throw(std::bad_alloc
, std::runtime_error
)
247 throw std::runtime_error("CD images can't be patched on the fly");
249 std::vector
<char> data2
= data
;
251 data2
.resize(data2
.size() - 1);
252 data2
= do_patch_file(data2
, patch
, offset
);
253 //Mark the slot as valid and update hash.
255 std::string new_sha256
= sha256::hash(data2
);
257 size_t osize
= data2
.size();
258 data2
.resize(osize
+ 1);
262 sha_256
= new_sha256
;
268 std::pair
<core_type
*, core_region
*> get_current_rom_info() throw()
270 return std::make_pair(current_rom_type
, current_region
);
273 loaded_rom::loaded_rom() throw()
276 region
= orig_region
= &null_region
;
279 loaded_rom::loaded_rom(const std::string
& file
) throw(std::bad_alloc
, std::runtime_error
)
281 std::istream
& spec
= open_file_relative(file
, "");
283 std::getline(spec
, s
);
285 load_filename
= file
;
286 if(!spec
|| s
!= "[GAMEPACK FILE]") {
287 //This is a Raw ROM image.
289 std::string ext
= regex(".*\\.([^.]*)?", file
, "Unknown ROM file type")[1];
290 core_type
* coretype
= find_core_by_extension(ext
);
292 throw std::runtime_error("Unknown ROM file type");
294 region
= orig_region
= &rtype
->get_preferred_region();
297 if((bios
= coretype
->get_biosname()) != "") {
298 //This thing has a BIOS.
300 std::string basename
= lsnes_vset
["firmwarepath"].str() + "/" + bios
;
301 romimg
[0] = loaded_slot(basename
, "", coretype
->get_image_info(0), false);
302 if(file_exists(basename
+ ".xml"))
303 romxml
[0] = loaded_slot(basename
+ ".xml", "", coretype
->get_image_info(0), true);
305 romimg
[romidx
] = loaded_slot(file
, "", coretype
->get_image_info(romidx
), false);
306 if(file_exists(file
+ ".xml"))
307 romxml
[romidx
] = loaded_slot(file
+ ".xml", "", coretype
->get_image_info(romidx
), true);
308 msu1_base
= resolve_file_relative(file
, "");
311 std::vector
<std::string
> lines
;
312 while(std::getline(spec
, s
))
313 lines
.push_back(strip_CR(s
));
314 std::string platname
= "";
315 std::string platreg
= "";
316 for(auto i
: lines
) {
318 if(tmp
= regex("type[ \t]+(.+)", i
))
320 if(tmp
= regex("region[ \t]+(.+)", i
))
325 rtype
= find_core_by_name(platname
);
327 (stringfmt() << "Not a valid system type '" << platname
<< "'").throwex();
330 bool goodreg
= false;
331 orig_region
= &rtype
->get_preferred_region();
332 for(auto i
: rtype
->get_regions())
333 if(i
->get_iname() == platreg
) {
337 if(!goodreg
&& platreg
!= "")
338 (stringfmt() << "Not a valid system region '" << platreg
<< "'").throwex();
339 region
= orig_region
;
342 std::string cromimg
[sizeof(romimg
)/sizeof(romimg
[0])];
343 std::string cromxml
[sizeof(romimg
)/sizeof(romimg
[0])];
344 for(auto i
: lines
) {
346 if(!(tmp
= regex("(rom|xml)[ \t]+([^ \t]+)[ \t]+(.*)", i
)))
348 size_t idxs
= rtype
->get_image_count();
350 for(size_t i
= 0; i
< idxs
; i
++)
351 if(rtype
->get_image_info(i
).iname
== tmp
[2])
354 (stringfmt() << "Not a valid ROM name '" << tmp
[2] << "'").throwex();
356 cromimg
[idx
] = tmp
[3];
358 cromxml
[idx
] = tmp
[3];
362 unsigned mask1
= 0, mask2
= 0;
363 for(size_t i
= 0; i
< rtype
->get_image_count(); i
++) {
364 auto ii
= rtype
->get_image_info(i
);
365 mask1
|= ii
.mandatory
;
367 mask2
|= ii
.mandatory
;
368 if(cromimg
[i
] == "" && cromxml
[i
] != "") {
369 messages
<< "WARNING: Slot " << ii
.iname
<< ": XML without ROM." << std::endl
;
374 throw std::runtime_error("Required ROM missing");
377 for(size_t i
= 0; i
< rtype
->get_image_count(); i
++) {
378 romimg
[i
] = loaded_slot(cromimg
[i
], file
, rtype
->get_image_info(i
), false);
379 romxml
[i
] = loaded_slot(cromxml
[i
], file
, rtype
->get_image_info(i
), true);
383 for(auto i
: lines
) {
385 if(!(tmp
= regex("patch([+-][0-9]+)?[ \t]+([^ \t]+)[ \t]+(.*)", i
)))
387 size_t idxs
= rtype
->get_image_count();
389 for(size_t i
= 0; i
< idxs
; i
++)
390 if(rtype
->get_image_info(i
).iname
== tmp
[2])
393 (stringfmt() << "Not a valid ROM name '" << tmp
[2] << "'").throwex();
396 offset
= parse_value
<int32_t>(tmp
[1]);
397 romimg
[idx
].patch(read_file_relative(tmp
[3], file
), offset
);
402 msu1_base
= resolve_file_relative(cromimg
[1], file
);
404 msu1_base
= resolve_file_relative(cromimg
[0], file
);
407 void loaded_rom::load(std::map
<std::string
, std::string
>& settings
, uint64_t rtc_sec
, uint64_t rtc_subsec
)
408 throw(std::bad_alloc
, std::runtime_error
)
410 current_rom_type
= &type_null
;
411 if(!orig_region
&& rtype
!= &type_null
)
412 orig_region
= &rtype
->get_preferred_region();
414 region
= orig_region
;
415 if(rtype
&& !orig_region
->compatible_with(*region
))
416 throw std::runtime_error("Trying to force incompatible region");
417 if(rtype
&& !rtype
->set_region(*region
))
418 throw std::runtime_error("Trying to force unknown region");
420 core_romimage images
[sizeof(romimg
)/sizeof(romimg
[0])];
421 for(size_t i
= 0; i
< sizeof(romimg
)/sizeof(romimg
[0]); i
++) {
422 images
[i
].markup
= (const char*)romxml
[i
];
423 images
[i
].data
= (const unsigned char*)romimg
[i
];
424 images
[i
].size
= (size_t)romimg
[i
];
426 if(!rtype
->load(images
, settings
, rtc_sec
, rtc_subsec
))
427 throw std::runtime_error("Can't load cartridge ROM");
429 region
= &rtype
->get_region();
431 auto nominal_fps
= rtype
->get_video_rate();
432 auto nominal_hz
= rtype
->get_audio_rate();
433 set_nominal_framerate(1.0 * nominal_fps
.first
/ nominal_fps
.second
);
434 information_dispatch::do_sound_rate(nominal_hz
.first
, nominal_hz
.second
);
435 current_rom_type
= rtype
;
436 current_region
= region
;
437 refresh_cart_mappings();
440 std::map
<std::string
, std::vector
<char>> load_sram_commandline(const std::vector
<std::string
>& cmdline
)
441 throw(std::bad_alloc
, std::runtime_error
)
443 std::map
<std::string
, std::vector
<char>> ret
;
445 for(auto i
: cmdline
) {
446 if(opt
= regex("--continue=(.+)", i
)) {
447 zip_reader
r(opt
[1]);
449 auto sramname
= regex("sram\\.(.*)", j
);
452 std::istream
& x
= r
[j
];
454 std::vector
<char> out
;
455 boost::iostreams::back_insert_device
<std::vector
<char>> rd(out
);
456 boost::iostreams::copy(x
, rd
);
458 ret
[sramname
[1]] = out
;
465 } else if(opt
= regex("--sram-([^=]+)=(.+)", i
)) {
467 ret
[opt
[1]] = read_file_relative(opt
[2], "");
468 } catch(std::bad_alloc
& e
) {
470 } catch(std::runtime_error
& e
) {
471 throw std::runtime_error("Can't load SRAM '" + opt
[1] + "': " + e
.what());
478 std::vector
<char> loaded_rom::save_core_state(bool nochecksum
) throw(std::bad_alloc
)
480 std::vector
<char> ret
;
481 rtype
->serialize(ret
);
484 size_t offset
= ret
.size();
485 unsigned char tmp
[32];
486 sha256::hash(tmp
, ret
);
487 ret
.resize(offset
+ 32);
488 memcpy(&ret
[offset
], tmp
, 32);
492 void loaded_rom::load_core_state(const std::vector
<char>& buf
, bool nochecksum
) throw(std::runtime_error
)
495 rtype
->unserialize(&buf
[0], buf
.size());
500 throw std::runtime_error("Savestate corrupt");
501 unsigned char tmp
[32];
502 sha256::hash(tmp
, reinterpret_cast<const uint8_t*>(&buf
[0]), buf
.size() - 32);
503 if(memcmp(tmp
, &buf
[buf
.size() - 32], 32))
504 throw std::runtime_error("Savestate corrupt");
505 rtype
->unserialize(&buf
[0], buf
.size() - 32);;
508 std::map
<std::string
, core_type
*> preferred_core
;
509 std::string preferred_core_default
;