Actually call on_reset callback
[lsnes.git] / src / core / rom.cpp
blobf107c438ff9e506688715895cdee9e3e6f37205d
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)
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)
67 auto& core = CORE();
68 core_type* old_type = current_rom_type;
69 core_core* old_core = current_rom_type->get_core();
70 current_rom_type = &get_null_type();
71 if(&rtype() != &get_null_type())
72 image->setup_region(rtype().get_preferred_region());
73 if(!region)
74 region = &image->get_region();
75 if(!image->get_region().compatible_with(*region))
76 throw std::runtime_error("Trying to force incompatible region");
77 if(!rtype().set_region(*region))
78 throw std::runtime_error("Trying to force unknown region");
80 core_romimage images[ROM_SLOT_COUNT];
81 for(size_t i = 0; i < ROM_SLOT_COUNT; i++) {
82 auto& img = image->get_image(i, false);
83 auto& xml = image->get_image(i, true);
84 images[i].markup = (const char*)xml;
85 images[i].data = (const unsigned char*)img;
86 images[i].size = (size_t)img;
88 if(!rtype().load(images, settings, rtc_sec, rtc_subsec))
89 throw std::runtime_error("Can't load cartridge ROM");
91 region = &rtype().get_region();
92 rtype().power();
93 auto nominal_fps = rtype().get_video_rate();
94 auto nominal_hz = rtype().get_audio_rate();
95 core.framerate->set_nominal_framerate(1.0 * nominal_fps.first / nominal_fps.second);
96 core.mdumper->on_rate_change(nominal_hz.first, nominal_hz.second);
98 current_rom_type = &rtype();
99 current_region = region;
100 //If core changes, unload the cartridge.
101 if(old_core != current_rom_type->get_core())
102 try {
103 old_core->debug_reset();
104 old_core->unload_cartridge();
105 } catch(...) {}
106 (*core.cmapper)();
107 core.dispatch->core_changed(old_type != current_rom_type);
110 std::map<std::string, std::vector<char>> load_sram_commandline(const std::vector<std::string>& cmdline)
112 std::map<std::string, std::vector<char>> ret;
113 regex_results opt;
114 for(auto i : cmdline) {
115 if(opt = regex("--continue=(.+)", i)) {
116 zip::reader r(opt[1]);
117 for(auto j : r) {
118 auto sramname = regex("sram\\.(.*)", j);
119 if(!sramname)
120 continue;
121 std::istream& x = r[j];
122 try {
123 std::vector<char> out;
124 boost::iostreams::back_insert_device<std::vector<char>> rd(out);
125 boost::iostreams::copy(x, rd);
126 delete &x;
127 ret[sramname[1]] = out;
128 } catch(...) {
129 delete &x;
130 throw;
133 continue;
134 } else if(opt = regex("--sram-([^=]+)=(.+)", i)) {
135 try {
136 ret[opt[1]] = zip::readrel(opt[2], "");
137 } catch(std::bad_alloc& e) {
138 throw;
139 } catch(std::runtime_error& e) {
140 throw std::runtime_error("Can't load SRAM '" + opt[1] + "': " + e.what());
144 return ret;
147 std::vector<char> loaded_rom::save_core_state(bool nochecksum)
149 std::vector<char> ret;
150 rtype().serialize(ret);
151 if(nochecksum)
152 return ret;
153 size_t offset = ret.size();
154 unsigned char tmp[32];
155 #ifdef USE_LIBGCRYPT_SHA256
156 gcry_md_hash_buffer(GCRY_MD_SHA256, tmp, &ret[0], offset);
157 #else
158 sha256::hash(tmp, ret);
159 #endif
160 ret.resize(offset + 32);
161 memcpy(&ret[offset], tmp, 32);
162 return ret;
165 void loaded_rom::load_core_state(const std::vector<char>& buf, bool nochecksum)
167 if(nochecksum) {
168 rtype().unserialize(&buf[0], buf.size());
169 return;
172 if(buf.size() < 32)
173 throw std::runtime_error("Savestate corrupt");
174 if(!savestate_no_check(*CORE().settings)) {
175 unsigned char tmp[32];
176 #ifdef USE_LIBGCRYPT_SHA256
177 gcry_md_hash_buffer(GCRY_MD_SHA256, tmp, &buf[0], buf.size() - 32);
178 #else
179 sha256::hash(tmp, reinterpret_cast<const uint8_t*>(&buf[0]), buf.size() - 32);
180 #endif
181 if(memcmp(tmp, &buf[buf.size() - 32], 32))
182 throw std::runtime_error("Savestate corrupt");
184 rtype().unserialize(&buf[0], buf.size() - 32);