Lua: Fix type confusion between signed and unsigned
[lsnes.git] / src / core / rom.cpp
blob884fc882ac237c7bc96d247e7dbaf90077a783c5
1 #include "lsnes.hpp"
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"
22 #include <stdexcept>
23 #include <sstream>
24 #include <iomanip>
25 #include <cstdint>
26 #include <set>
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
37 #include <gcrypt.h>
38 #endif
40 namespace
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();
49 std::pair<core_type*, core_region*> get_current_rom_info() throw()
51 return std::make_pair(current_rom_type, current_region);
54 loaded_rom::loaded_rom() throw()
56 region = &image->get_region();
59 loaded_rom::loaded_rom(rom_image_handle _image) throw(std::bad_alloc, std::runtime_error)
61 image = _image;
62 region = &image->get_region();
65 void loaded_rom::load(std::map<std::string, std::string>& settings, uint64_t rtc_sec, uint64_t rtc_subsec)
66 throw(std::bad_alloc, std::runtime_error)
68 auto& core = CORE();
69 core_type* old_type = current_rom_type;
70 core_core* old_core = current_rom_type->get_core();
71 current_rom_type = &get_null_type();
72 if(&rtype() != &get_null_type())
73 image->setup_region(rtype().get_preferred_region());
74 if(!region)
75 region = &image->get_region();
76 if(!image->get_region().compatible_with(*region))
77 throw std::runtime_error("Trying to force incompatible region");
78 if(!rtype().set_region(*region))
79 throw std::runtime_error("Trying to force unknown region");
81 core_romimage images[ROM_SLOT_COUNT];
82 for(size_t i = 0; i < ROM_SLOT_COUNT; i++) {
83 auto& img = image->get_image(i, false);
84 auto& xml = image->get_image(i, true);
85 images[i].markup = (const char*)xml;
86 images[i].data = (const unsigned char*)img;
87 images[i].size = (size_t)img;
89 if(!rtype().load(images, settings, rtc_sec, rtc_subsec))
90 throw std::runtime_error("Can't load cartridge ROM");
92 region = &rtype().get_region();
93 rtype().power();
94 auto nominal_fps = rtype().get_video_rate();
95 auto nominal_hz = rtype().get_audio_rate();
96 core.framerate->set_nominal_framerate(1.0 * nominal_fps.first / nominal_fps.second);
97 core.mdumper->on_rate_change(nominal_hz.first, nominal_hz.second);
99 current_rom_type = &rtype();
100 current_region = region;
101 //If core changes, unload the cartridge.
102 if(old_core != current_rom_type->get_core())
103 try {
104 old_core->debug_reset();
105 old_core->unload_cartridge();
106 } catch(...) {}
107 (*core.cmapper)();
108 core.dispatch->core_changed(old_type != current_rom_type);
111 std::map<std::string, std::vector<char>> load_sram_commandline(const std::vector<std::string>& cmdline)
112 throw(std::bad_alloc, std::runtime_error)
114 std::map<std::string, std::vector<char>> ret;
115 regex_results opt;
116 for(auto i : cmdline) {
117 if(opt = regex("--continue=(.+)", i)) {
118 zip::reader r(opt[1]);
119 for(auto j : r) {
120 auto sramname = regex("sram\\.(.*)", j);
121 if(!sramname)
122 continue;
123 std::istream& x = r[j];
124 try {
125 std::vector<char> out;
126 boost::iostreams::back_insert_device<std::vector<char>> rd(out);
127 boost::iostreams::copy(x, rd);
128 delete &x;
129 ret[sramname[1]] = out;
130 } catch(...) {
131 delete &x;
132 throw;
135 continue;
136 } else if(opt = regex("--sram-([^=]+)=(.+)", i)) {
137 try {
138 ret[opt[1]] = zip::readrel(opt[2], "");
139 } catch(std::bad_alloc& e) {
140 throw;
141 } catch(std::runtime_error& e) {
142 throw std::runtime_error("Can't load SRAM '" + opt[1] + "': " + e.what());
146 return ret;
149 std::vector<char> loaded_rom::save_core_state(bool nochecksum) throw(std::bad_alloc, std::runtime_error)
151 std::vector<char> ret;
152 rtype().serialize(ret);
153 if(nochecksum)
154 return ret;
155 size_t offset = ret.size();
156 unsigned char tmp[32];
157 #ifdef USE_LIBGCRYPT_SHA256
158 gcry_md_hash_buffer(GCRY_MD_SHA256, tmp, &ret[0], offset);
159 #else
160 sha256::hash(tmp, ret);
161 #endif
162 ret.resize(offset + 32);
163 memcpy(&ret[offset], tmp, 32);
164 return ret;
167 void loaded_rom::load_core_state(const std::vector<char>& buf, bool nochecksum) throw(std::runtime_error)
169 if(nochecksum) {
170 rtype().unserialize(&buf[0], buf.size());
171 return;
174 if(buf.size() < 32)
175 throw std::runtime_error("Savestate corrupt");
176 if(!savestate_no_check(*CORE().settings)) {
177 unsigned char tmp[32];
178 #ifdef USE_LIBGCRYPT_SHA256
179 gcry_md_hash_buffer(GCRY_MD_SHA256, tmp, &buf[0], buf.size() - 32);
180 #else
181 sha256::hash(tmp, reinterpret_cast<const uint8_t*>(&buf[0]), buf.size() - 32);
182 #endif
183 if(memcmp(tmp, &buf[buf.size() - 32], 32))
184 throw std::runtime_error("Savestate corrupt");
186 rtype().unserialize(&buf[0], buf.size() - 32);