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/patch.hpp"
14 #include "library/sha256.hpp"
15 #include "library/string.hpp"
16 #include "library/zip.hpp"
23 #include <boost/iostreams/categories.hpp>
24 #include <boost/iostreams/copy.hpp>
25 #include <boost/iostreams/stream.hpp>
26 #include <boost/iostreams/stream_buffer.hpp>
27 #include <boost/iostreams/filter/symmetric.hpp>
28 #include <boost/iostreams/filter/zlib.hpp>
29 #include <boost/iostreams/filtering_stream.hpp>
30 #include <boost/iostreams/device/back_inserter.hpp>
34 core_type
* current_rom_type
= NULL
;
35 core_region
* current_region
= NULL
;
37 bool file_exists(const std::string
& name
)
40 delete &open_file_relative(name
, "");
48 loaded_slot::loaded_slot() throw(std::bad_alloc
)
55 loaded_slot::loaded_slot(const std::string
& filename
, const std::string
& base
,
56 const struct core_romimage_info
& imginfo
, bool xml_flag
) throw(std::bad_alloc
, std::runtime_error
)
58 unsigned headered
= 0;
66 data
= read_file_relative(filename
, base
);
68 headered
= imginfo
.headersize(data
.size());
69 if(headered
&& !xml
) {
70 if(data
.size() >= headered
) {
71 memmove(&data
[0], &data
[headered
], data
.size() - headered
);
72 data
.resize(data
.size() - headered
);
77 sha256
= sha256::hash(data
);
79 size_t osize
= data
.size();
80 data
.resize(osize
+ 1);
85 void loaded_slot::patch(const std::vector
<char>& patch
, int32_t offset
) throw(std::bad_alloc
, std::runtime_error
)
88 std::vector
<char> data2
= data
;
91 data2
.resize(data2
.size() - 1);
92 data2
= do_patch_file(data2
, patch
, offset
);
93 //Mark the slot as valid and update hash.
95 std::string new_sha256
= sha256::hash(data2
);
97 size_t osize
= data2
.size();
98 data2
.resize(osize
+ 1);
110 std::pair
<core_type
*, core_region
*> get_current_rom_info() throw()
112 return std::make_pair(current_rom_type
, current_region
);
115 loaded_rom::loaded_rom() throw()
118 region
= orig_region
= NULL
;
121 loaded_rom::loaded_rom(const std::string
& file
) throw(std::bad_alloc
, std::runtime_error
)
123 std::list
<core_type
*> possible
= core_type::get_core_types();
124 std::istream
& spec
= open_file_relative(file
, "");
126 std::getline(spec
, s
);
128 load_filename
= file
;
129 if(!spec
|| s
!= "[GAMEPACK FILE]") {
130 //This is a Raw ROM image.
132 std::string ext
= regex(".*\\.([^.]*)?", file
, "Unknown ROM file type")[1];
133 core_type
* coretype
= NULL
;
134 for(auto i
: possible
) {
135 if(i
->is_known_extension(ext
))
139 throw std::runtime_error("Unknown ROM file type");
141 region
= orig_region
= &rtype
->get_preferred_region();
144 if((bios
= coretype
->get_biosname()) != "") {
145 //This thing has a BIOS.
147 std::string basename
= setting::get("firmwarepath") + "/" + bios
;
148 romimg
[0] = loaded_slot(basename
, "", coretype
->get_image_info(0), false);
149 if(file_exists(basename
+ ".xml"))
150 romxml
[0] = loaded_slot(basename
+ ".xml", "", coretype
->get_image_info(0), true);
152 romimg
[romidx
] = loaded_slot(file
, "", coretype
->get_image_info(romidx
), false);
153 if(file_exists(file
+ ".xml"))
154 romxml
[romidx
] = loaded_slot(file
+ ".xml", "", coretype
->get_image_info(romidx
), true);
155 msu1_base
= resolve_file_relative(file
, "");
158 std::vector
<std::string
> lines
;
159 while(std::getline(spec
, s
))
160 lines
.push_back(strip_CR(s
));
161 std::string platname
= "";
162 std::string platreg
= "";
163 for(auto i
: lines
) {
165 if(tmp
= regex("type[ \t]+(.+)", i
))
167 if(tmp
= regex("region[ \t]+(.+)", i
))
173 for(auto i
: possible
)
174 if(i
->get_iname() == platname
)
177 (stringfmt() << "Not a valid system type '" << platname
<< "'").throwex();
180 bool goodreg
= false;
181 orig_region
= &rtype
->get_preferred_region();
182 for(auto i
: rtype
->get_regions())
183 if(i
->get_iname() == platreg
) {
187 if(!goodreg
&& platreg
!= "")
188 (stringfmt() << "Not a valid system region '" << platreg
<< "'").throwex();
189 region
= orig_region
;
192 std::string cromimg
[sizeof(romimg
)/sizeof(romimg
[0])];
193 std::string cromxml
[sizeof(romimg
)/sizeof(romimg
[0])];
194 for(auto i
: lines
) {
196 if(!(tmp
= regex("(rom|xml)[ \t]+([^ \t]+)[ \t]+(.*)", i
)))
198 size_t idxs
= rtype
->get_image_count();
200 for(size_t i
= 0; i
< idxs
; i
++)
201 if(rtype
->get_image_info(i
).iname
== tmp
[2])
204 (stringfmt() << "Not a valid ROM name '" << tmp
[2] << "'").throwex();
206 cromimg
[idx
] = tmp
[3];
208 cromxml
[idx
] = tmp
[3];
212 unsigned mask1
= 0, mask2
= 0;
213 for(size_t i
= 0; i
< rtype
->get_image_count(); i
++) {
214 auto ii
= rtype
->get_image_info(i
);
215 mask1
|= ii
.mandatory
;
217 mask2
|= ii
.mandatory
;
218 if(cromimg
[i
] == "" && cromxml
[i
] != "") {
219 messages
<< "WARNING: Slot " << ii
.iname
<< ": XML without ROM." << std::endl
;
224 throw std::runtime_error("Required ROM missing");
227 for(size_t i
= 0; i
< rtype
->get_image_count(); i
++) {
228 romimg
[i
] = loaded_slot(cromimg
[i
], file
, rtype
->get_image_info(i
), false);
229 romxml
[i
] = loaded_slot(cromxml
[i
], file
, rtype
->get_image_info(i
), true);
233 for(auto i
: lines
) {
235 if(!(tmp
= regex("patch([+-][0-9]+)?[ \t]+([^ \t]+)[ \t]+(.*)", i
)))
237 size_t idxs
= rtype
->get_image_count();
239 for(size_t i
= 0; i
< idxs
; i
++)
240 if(rtype
->get_image_info(i
).iname
== tmp
[2])
243 (stringfmt() << "Not a valid ROM name '" << tmp
[2] << "'").throwex();
246 offset
= parse_value
<int32_t>(tmp
[1]);
247 romimg
[idx
].patch(read_file_relative(tmp
[3], file
), offset
);
252 msu1_base
= resolve_file_relative(cromimg
[1], file
);
254 msu1_base
= resolve_file_relative(cromimg
[0], file
);
257 void loaded_rom::load(uint64_t rtc_sec
, uint64_t rtc_subsec
) throw(std::bad_alloc
, std::runtime_error
)
259 current_rom_type
= NULL
;
260 if(!orig_region
&& rtype
)
261 orig_region
= &rtype
->get_preferred_region();
263 region
= orig_region
;
264 if(rtype
&& !orig_region
->compatible_with(*region
))
265 throw std::runtime_error("Trying to force incompatible region");
266 if(rtype
&& !core_set_region(*region
))
267 throw std::runtime_error("Trying to force unknown region");
269 core_romimage images
[sizeof(romimg
)/sizeof(romimg
[0])];
270 for(size_t i
= 0; i
< sizeof(romimg
)/sizeof(romimg
[0]); i
++) {
271 images
[i
].markup
= (const char*)romxml
[i
];
272 images
[i
].data
= (const unsigned char*)romimg
[i
];
273 images
[i
].size
= (size_t)romimg
[i
];
276 if(!rtype
->load(images
, rtc_sec
, rtc_subsec
))
277 throw std::runtime_error("Can't load cartridge ROM");
279 core_unload_cartridge();
281 region
= &core_get_region();
283 auto nominal_fps
= get_video_rate();
284 auto nominal_hz
= get_audio_rate();
285 set_nominal_framerate(1.0 * nominal_fps
.first
/ nominal_fps
.second
);
286 information_dispatch::do_sound_rate(nominal_hz
.first
, nominal_hz
.second
);
287 current_rom_type
= rtype
;
288 current_region
= region
;
289 refresh_cart_mappings();
292 std::map
<std::string
, std::vector
<char>> load_sram_commandline(const std::vector
<std::string
>& cmdline
)
293 throw(std::bad_alloc
, std::runtime_error
)
295 std::map
<std::string
, std::vector
<char>> ret
;
297 for(auto i
: cmdline
) {
298 if(opt
= regex("--continue=(.+)", i
)) {
299 zip_reader
r(opt
[1]);
301 auto sramname
= regex("sram\\.(.*)", j
);
304 std::istream
& x
= r
[j
];
306 std::vector
<char> out
;
307 boost::iostreams::back_insert_device
<std::vector
<char>> rd(out
);
308 boost::iostreams::copy(x
, rd
);
310 ret
[sramname
[1]] = out
;
317 } else if(opt
= regex("--sram-([^=]+)=(.+)", i
)) {
319 ret
[opt
[1]] = read_file_relative(opt
[2], "");
320 } catch(std::bad_alloc
& e
) {
322 } catch(std::runtime_error
& e
) {
323 throw std::runtime_error("Can't load SRAM '" + opt
[1] + "': " + e
.what());
330 std::vector
<char> save_core_state(bool nochecksum
) throw(std::bad_alloc
)
332 std::vector
<char> ret
;
336 size_t offset
= ret
.size();
337 unsigned char tmp
[32];
338 sha256::hash(tmp
, ret
);
339 ret
.resize(offset
+ 32);
340 memcpy(&ret
[offset
], tmp
, 32);
344 void load_core_state(const std::vector
<char>& buf
, bool nochecksum
) throw(std::runtime_error
)
347 core_unserialize(&buf
[0], buf
.size());
352 throw std::runtime_error("Savestate corrupt");
353 unsigned char tmp
[32];
354 sha256::hash(tmp
, reinterpret_cast<const uint8_t*>(&buf
[0]), buf
.size() - 32);
355 if(memcmp(tmp
, &buf
[buf
.size() - 32], 32))
356 throw std::runtime_error("Savestate corrupt");
357 core_unserialize(&buf
[0], buf
.size() - 32);;