2 #include "core/emucore.hpp"
4 #include "core/command.hpp"
5 #include "core/dispatch.hpp"
6 #include "core/framerate.hpp"
7 #include "core/mainloop.hpp"
8 #include "core/memorymanip.hpp"
9 #include "core/misc.hpp"
10 #include "core/rom.hpp"
11 #include "core/settings.hpp"
12 #include "core/window.hpp"
13 #include "library/portfn.hpp"
14 #include "library/patch.hpp"
15 #include "library/sha256.hpp"
16 #include "library/string.hpp"
17 #include "library/zip.hpp"
25 #include <boost/iostreams/categories.hpp>
26 #include <boost/iostreams/copy.hpp>
27 #include <boost/iostreams/stream.hpp>
28 #include <boost/iostreams/stream_buffer.hpp>
29 #include <boost/iostreams/filter/symmetric.hpp>
30 #include <boost/iostreams/filter/zlib.hpp>
31 #include <boost/iostreams/filtering_stream.hpp>
32 #include <boost/iostreams/device/back_inserter.hpp>
33 #include <boost/filesystem.hpp>
35 #ifdef BOOST_FILESYSTEM3
36 namespace boost_fs
= boost::filesystem3
;
38 namespace boost_fs
= boost::filesystem
;
43 const char* null_chars
= "F";
45 port_controller_button
* null_buttons
[] = {};
46 port_controller simple_controller
= {"(system)", "system", 0, null_buttons
};
47 port_controller
* simple_controllers
[] = {&simple_controller
};
48 port_controller_set simple_port
= {1, simple_controllers
};
50 struct porttype_null
: public port_type
52 porttype_null() : port_type("null", "null", 999997, 1)
54 write
= generic_port_write
<1, 0, 1>;
55 read
= generic_port_read
<1, 0, 1>;
56 display
= generic_port_display
<1, 0, 1, &null_chars
>;
57 serialize
= generic_port_serialize
<1, 0, 1, &null_chars
>;
58 deserialize
= generic_port_deserialize
<1, 0, 1>;
59 legal
= generic_port_legal
<1>;
60 controller_info
= &simple_port
;
61 used_indices
= generic_used_indices
<1, 1>;
65 port_index_triple sync_triple
= {true, 0, 0, 0, false };
67 controller_set
null_controllerconfig(std::map
<std::string
, std::string
>& settings
)
70 x
.ports
.push_back(&pnull
);
71 x
.portindex
.indices
.push_back(sync_triple
);
75 std::pair
<unsigned, unsigned> videorate_null() { return std::make_pair(60, 1); }
76 std::pair
<unsigned, unsigned> audiorate_null() { return std::make_pair(48000, 1); }
78 bool set_region_null(core_region
& reg
)
83 int load_rom_null(core_romimage
* img
, std::map
<std::string
, std::string
>& settings
,
84 uint64_t secs
, uint64_t subsecs
)
89 core_setting_group null_settings
;
91 unsigned null_compatible
[] = {0, UINT_MAX
};
92 struct core_region_params _null_region
= {
93 "null", "(null)", 0, 0, false, {1, 60, 16666666, 40}, null_compatible
95 core_region
null_region(_null_region
);
96 core_region
* null_regions
[] = {&null_region
, NULL
};
97 core_romimage_info
* null_images
[] = {NULL
};
98 core_type_params _type_null
= {
99 "null", "(null)", 9999, 0, load_rom_null
, null_controllerconfig
,
100 "", NULL
, null_regions
, null_images
, &null_settings
, set_region_null
,
101 videorate_null
, audiorate_null
, NULL
103 core_type
type_null(_type_null
);
104 core_sysregion
sysregion_null("null", type_null
, null_region
);
106 core_type
* current_rom_type
= &type_null
;
107 core_region
* current_region
= &null_region
;
110 loaded_slot::loaded_slot() throw(std::bad_alloc
)
115 filename_flag
= false;
118 loaded_slot::loaded_slot(const std::string
& filename
, const std::string
& base
,
119 const struct core_romimage_info
& imginfo
, bool xml_flag
) throw(std::bad_alloc
, std::runtime_error
)
121 unsigned headered
= 0;
126 filename_flag
= (!xml
&& imginfo
.pass_mode
);
129 //XMLs are always loaded, no matter what.
130 if(!xml
&& imginfo
.pass_mode
) {
131 std::string _filename
= filename
;
132 //Translate the passed filename to absolute one.
133 _filename
= resolve_file_relative(_filename
, base
);
134 _filename
= boost_fs::absolute(boost_fs::path(_filename
)).string();
135 filename_flag
= true;
136 data
.resize(_filename
.length());
137 std::copy(_filename
.begin(), _filename
.end(), data
.begin());
138 //Compute the SHA-256.
139 std::istream
& s
= open_file_relative(filename
, "");
143 while(block
= s
.readsome(buffer
, 8192))
144 hash
.write(buffer
, block
);
145 sha_256
= hash
.read();
150 filename_flag
= false;
152 data
= read_file_relative(filename
, base
);
153 if(!xml
&& imginfo
.headersize
)
154 headered
= ((data
.size() % (2 * imginfo
.headersize
)) == imginfo
.headersize
) ? imginfo
.headersize
: 0;
155 if(headered
&& !xml
) {
156 if(data
.size() >= headered
) {
157 memmove(&data
[0], &data
[headered
], data
.size() - headered
);
158 data
.resize(data
.size() - headered
);
163 sha_256
= sha256::hash(data
);
165 size_t osize
= data
.size();
166 data
.resize(osize
+ 1);
171 void loaded_slot::patch(const std::vector
<char>& patch
, int32_t offset
) throw(std::bad_alloc
, std::runtime_error
)
174 throw std::runtime_error("CD images can't be patched on the fly");
176 std::vector
<char> data2
= data
;
179 data2
.resize(data2
.size() - 1);
180 data2
= do_patch_file(data2
, patch
, offset
);
181 //Mark the slot as valid and update hash.
183 std::string new_sha256
= sha256::hash(data2
);
185 size_t osize
= data2
.size();
186 data2
.resize(osize
+ 1);
190 sha_256
= new_sha256
;
196 std::pair
<core_type
*, core_region
*> get_current_rom_info() throw()
198 return std::make_pair(current_rom_type
, current_region
);
201 loaded_rom::loaded_rom() throw()
204 region
= orig_region
= &null_region
;
207 loaded_rom::loaded_rom(const std::string
& file
) throw(std::bad_alloc
, std::runtime_error
)
209 std::list
<core_type
*> possible
= core_type::get_core_types();
210 std::istream
& spec
= open_file_relative(file
, "");
212 std::getline(spec
, s
);
214 load_filename
= file
;
215 if(!spec
|| s
!= "[GAMEPACK FILE]") {
216 //This is a Raw ROM image.
218 std::string ext
= regex(".*\\.([^.]*)?", file
, "Unknown ROM file type")[1];
219 core_type
* coretype
= NULL
;
220 for(auto i
: possible
) {
221 if(i
->is_known_extension(ext
))
225 throw std::runtime_error("Unknown ROM file type");
227 region
= orig_region
= &rtype
->get_preferred_region();
230 if((bios
= coretype
->get_biosname()) != "") {
231 //This thing has a BIOS.
233 romimg
[0] = loaded_slot(lsnes_set
.get("firmwarepath") + "/" + bios
, "",
234 coretype
->get_image_info(0), false);
236 romimg
[romidx
] = loaded_slot(file
, "", coretype
->get_image_info(romidx
), false);
237 msu1_base
= resolve_file_relative(file
, "");
240 std::vector
<std::string
> lines
;
241 while(std::getline(spec
, s
))
242 lines
.push_back(strip_CR(s
));
243 std::string platname
= "";
244 std::string platreg
= "";
245 for(auto i
: lines
) {
247 if(tmp
= regex("type[ \t]+(.+)", i
))
249 if(tmp
= regex("region[ \t]+(.+)", i
))
255 for(auto i
: possible
)
256 if(i
->get_iname() == platname
)
258 if(rtype
== &type_null
)
259 (stringfmt() << "Not a valid system type '" << platname
<< "'").throwex();
262 bool goodreg
= false;
263 orig_region
= &rtype
->get_preferred_region();
264 for(auto i
: rtype
->get_regions())
265 if(i
->get_iname() == platreg
) {
269 if(!goodreg
&& platreg
!= "")
270 (stringfmt() << "Not a valid system region '" << platreg
<< "'").throwex();
271 region
= orig_region
;
274 std::string cromimg
[sizeof(romimg
)/sizeof(romimg
[0])];
275 std::string cromxml
[sizeof(romimg
)/sizeof(romimg
[0])];
276 for(auto i
: lines
) {
278 if(!(tmp
= regex("(rom|xml)[ \t]+([^ \t]+)[ \t]+(.*)", i
)))
280 size_t idxs
= rtype
->get_image_count();
282 for(size_t i
= 0; i
< idxs
; i
++)
283 if(rtype
->get_image_info(i
).iname
== tmp
[2])
286 (stringfmt() << "Not a valid ROM name '" << tmp
[2] << "'").throwex();
288 cromimg
[idx
] = tmp
[3];
290 cromxml
[idx
] = tmp
[3];
294 unsigned mask1
= 0, mask2
= 0;
295 for(size_t i
= 0; i
< rtype
->get_image_count(); i
++) {
296 auto ii
= rtype
->get_image_info(i
);
297 mask1
|= ii
.mandatory
;
299 mask2
|= ii
.mandatory
;
300 if(cromimg
[i
] == "" && cromxml
[i
] != "") {
301 messages
<< "WARNING: Slot " << ii
.iname
<< ": XML without ROM." << std::endl
;
306 throw std::runtime_error("Required ROM missing");
309 for(size_t i
= 0; i
< rtype
->get_image_count(); i
++) {
310 romimg
[i
] = loaded_slot(cromimg
[i
], file
, rtype
->get_image_info(i
), false);
311 romxml
[i
] = loaded_slot(cromxml
[i
], file
, rtype
->get_image_info(i
), true);
315 for(auto i
: lines
) {
317 if(!(tmp
= regex("patch([+-][0-9]+)?[ \t]+([^ \t]+)[ \t]+(.*)", i
)))
319 size_t idxs
= rtype
->get_image_count();
321 for(size_t i
= 0; i
< idxs
; i
++)
322 if(rtype
->get_image_info(i
).iname
== tmp
[2])
325 (stringfmt() << "Not a valid ROM name '" << tmp
[2] << "'").throwex();
328 offset
= parse_value
<int32_t>(tmp
[1]);
329 romimg
[idx
].patch(read_file_relative(tmp
[3], file
), offset
);
334 msu1_base
= resolve_file_relative(cromimg
[1], file
);
336 msu1_base
= resolve_file_relative(cromimg
[0], file
);
339 void loaded_rom::load(std::map
<std::string
, std::string
>& settings
, uint64_t rtc_sec
, uint64_t rtc_subsec
)
340 throw(std::bad_alloc
, std::runtime_error
)
342 current_rom_type
= &type_null
;
343 if(!orig_region
&& rtype
!= &type_null
)
344 orig_region
= &rtype
->get_preferred_region();
346 region
= orig_region
;
347 if(rtype
&& !orig_region
->compatible_with(*region
))
348 throw std::runtime_error("Trying to force incompatible region");
349 if(rtype
&& !rtype
->set_region(*region
))
350 throw std::runtime_error("Trying to force unknown region");
352 core_romimage images
[sizeof(romimg
)/sizeof(romimg
[0])];
353 for(size_t i
= 0; i
< sizeof(romimg
)/sizeof(romimg
[0]); i
++) {
354 images
[i
].markup
= (const char*)romxml
[i
];
355 images
[i
].data
= (const unsigned char*)romimg
[i
];
356 images
[i
].size
= (size_t)romimg
[i
];
359 if(!rtype
->load(images
, settings
, rtc_sec
, rtc_subsec
))
360 throw std::runtime_error("Can't load cartridge ROM");
362 core_unload_cartridge();
364 if(rtype
== &type_null
) {
365 region
= &null_region
;
367 region
= &core_get_region();
370 auto nominal_fps
= rtype
->get_video_rate();
371 auto nominal_hz
= rtype
->get_audio_rate();
372 set_nominal_framerate(1.0 * nominal_fps
.first
/ nominal_fps
.second
);
373 information_dispatch::do_sound_rate(nominal_hz
.first
, nominal_hz
.second
);
374 current_rom_type
= rtype
;
375 current_region
= region
;
376 refresh_cart_mappings();
379 std::map
<std::string
, std::vector
<char>> load_sram_commandline(const std::vector
<std::string
>& cmdline
)
380 throw(std::bad_alloc
, std::runtime_error
)
382 std::map
<std::string
, std::vector
<char>> ret
;
384 for(auto i
: cmdline
) {
385 if(opt
= regex("--continue=(.+)", i
)) {
386 zip_reader
r(opt
[1]);
388 auto sramname
= regex("sram\\.(.*)", j
);
391 std::istream
& x
= r
[j
];
393 std::vector
<char> out
;
394 boost::iostreams::back_insert_device
<std::vector
<char>> rd(out
);
395 boost::iostreams::copy(x
, rd
);
397 ret
[sramname
[1]] = out
;
404 } else if(opt
= regex("--sram-([^=]+)=(.+)", i
)) {
406 ret
[opt
[1]] = read_file_relative(opt
[2], "");
407 } catch(std::bad_alloc
& e
) {
409 } catch(std::runtime_error
& e
) {
410 throw std::runtime_error("Can't load SRAM '" + opt
[1] + "': " + e
.what());
417 std::vector
<char> save_core_state(bool nochecksum
) throw(std::bad_alloc
)
419 std::vector
<char> ret
;
423 size_t offset
= ret
.size();
424 unsigned char tmp
[32];
425 sha256::hash(tmp
, ret
);
426 ret
.resize(offset
+ 32);
427 memcpy(&ret
[offset
], tmp
, 32);
431 void load_core_state(const std::vector
<char>& buf
, bool nochecksum
) throw(std::runtime_error
)
434 core_unserialize(&buf
[0], buf
.size());
439 throw std::runtime_error("Savestate corrupt");
440 unsigned char tmp
[32];
441 sha256::hash(tmp
, reinterpret_cast<const uint8_t*>(&buf
[0]), buf
.size() - 32);
442 if(memcmp(tmp
, &buf
[buf
.size() - 32], 32))
443 throw std::runtime_error("Savestate corrupt");
444 core_unserialize(&buf
[0], buf
.size() - 32);;