Pack movie data in memory
[lsnes.git] / src / plat-sdl / main.cpp
blob3eadb1580c0bc2df609a43bf933817ce00a9887e
1 #include "lsnes.hpp"
2 #include <snes/snes.hpp>
3 #include <ui-libsnes/libsnes.hpp>
5 #include "core/command.hpp"
6 #include "core/framerate.hpp"
7 #include "core/keymapper.hpp"
8 #include "core/lua.hpp"
9 #include "core/mainloop.hpp"
10 #include "core/misc.hpp"
11 #include "core/moviedata.hpp"
12 #include "core/rom.hpp"
13 #include "core/rrdata.hpp"
14 #include "core/window.hpp"
16 #include "plat-sdl/platform.hpp"
18 #include <sys/time.h>
19 #include <sstream>
21 #if defined(_WIN32) || defined(_WIN64) || defined(TEST_WIN32_CODE) || defined(__APPLE__)
22 #include "SDL_main.h"
23 #endif
26 class my_interfaced : public SNES::Interface
28 string path(SNES::Cartridge::Slot slot, const string &hint)
30 return "./";
34 struct moviefile generate_movie_template(std::vector<std::string> cmdline, loaded_rom& r)
36 struct moviefile movie;
37 movie.coreversion = bsnes_core_version;
38 movie.projectid = get_random_hexstring(40);
39 movie.gametype = gtype::togametype(r.rtype, r.region);
40 movie.rom_sha256 = r.rom.sha256;
41 movie.romxml_sha256 = r.rom_xml.sha256;
42 movie.slota_sha256 = r.slota.sha256;
43 movie.slotaxml_sha256 = r.slota_xml.sha256;
44 movie.slotb_sha256 = r.slotb.sha256;
45 movie.slotbxml_sha256 = r.slotb_xml.sha256;
46 movie.movie_sram = load_sram_commandline(cmdline);
47 for(auto i = cmdline.begin(); i != cmdline.end(); i++) {
48 std::string o = *i;
49 if(o.length() >= 8 && o.substr(0, 8) == "--port1=")
50 movie.port1 = porttype_info::lookup(o.substr(8)).value;
51 if(o.length() >= 8 && o.substr(0, 8) == "--port2=")
52 movie.port2 = porttype_info::lookup(o.substr(8)).value;
53 if(o.length() >= 11 && o.substr(0, 11) == "--gamename=")
54 movie.gamename = o.substr(11);
55 if(o.length() >= 9 && o.substr(0, 9) == "--author=") {
56 std::string line = o.substr(9);
57 auto g = split_author(line);
58 movie.authors.push_back(g);
60 if(o.length() >= 13 && o.substr(0, 13) == "--rtc-second=") {
61 movie.rtc_second = movie.movie_rtc_second = parse_value<int64_t>(o.substr(13));
63 if(o.length() >= 16 && o.substr(0, 16) == "--rtc-subsecond=") {
64 movie.rtc_subsecond = movie.movie_rtc_subsecond = parse_value<int64_t>(o.substr(16));
65 if(movie.rtc_subsecond < 0 || movie.rtc_subsecond > 3462619485019ULL)
66 throw std::runtime_error("Bad RTC subsecond value (range is 0-3462619485019)");
69 movie.input.clear(movie.port1, movie.port2);
71 return movie;
74 namespace
76 void run_extra_scripts(const std::vector<std::string>& cmdline)
78 for(auto i = cmdline.begin(); i != cmdline.end(); i++) {
79 std::string o = *i;
80 if(o.length() >= 6 && o.substr(0, 6) == "--run=") {
81 std::string file = o.substr(6);
82 messages << "--- Running " << file << " --- " << std::endl;
83 command::invokeC("run-script " + file);
84 messages << "--- End running " << file << " --- " << std::endl;
89 void sdl_main_loop(struct loaded_rom& rom, struct moviefile& initial, bool load_has_to_succeed = false)
90 throw(std::bad_alloc, std::runtime_error);
92 struct emu_args
94 struct loaded_rom* rom;
95 struct moviefile* initial;
96 bool load_has_to_succeed;
99 void* emulator_thread(void* _args)
101 struct emu_args* args = reinterpret_cast<struct emu_args*>(_args);
102 try {
103 main_loop(*args->rom, *args->initial, args->load_has_to_succeed);
104 notify_emulator_exit();
105 } catch(std::bad_alloc& e) {
106 OOM_panic();
107 } catch(std::exception& e) {
108 messages << "FATAL: " << e.what() << std::endl;
109 platform::fatal_error();
113 void* joystick_thread(void* _args)
115 joystick_plugin::thread_fn();
118 void sdl_main_loop(struct loaded_rom& rom, struct moviefile& initial, bool load_has_to_succeed)
119 throw(std::bad_alloc, std::runtime_error)
121 try {
122 struct emu_args args;
123 args.rom = &rom;
124 args.initial = &initial;
125 args.load_has_to_succeed = load_has_to_succeed;
126 thread* t;
127 thread* t2;
128 t = &thread::create(emulator_thread, &args);
129 t2 = &thread::create(joystick_thread, &args);
130 ui_loop();
131 joystick_plugin::signal();
132 t2->join();
133 t->join();
134 delete t;
135 delete t2;
136 } catch(std::bad_alloc& e) {
137 OOM_panic();
142 int main(int argc, char** argv)
144 std::vector<std::string> cmdline;
145 for(int i = 1; i < argc; i++)
146 cmdline.push_back(argv[i]);
147 my_interfaced intrf;
148 SNES::interface = &intrf;
150 set_random_seed();
153 std::ostringstream x;
154 x << snes_library_id() << " (" << SNES::Info::Profile << " core)";
155 bsnes_core_version = x.str();
157 platform::init();
158 init_lua();
160 messages << "BSNES version: " << bsnes_core_version << std::endl;
161 messages << "lsnes version: lsnes rr" << lsnes_version << std::endl;
162 messages << "Command line is: ";
163 for(auto k = cmdline.begin(); k != cmdline.end(); k++)
164 messages << "\"" << *k << "\" ";
165 messages << std::endl;
167 std::string cfgpath = get_config_path();
168 create_lsnesrc();
169 messages << "Saving per-user data to: " << get_config_path() << std::endl;
170 messages << "--- Running lsnesrc --- " << std::endl;
171 command::invokeC("run-script " + cfgpath + "/lsnes.rc");
172 messages << "--- End running lsnesrc --- " << std::endl;
174 run_extra_scripts(cmdline);
176 messages << "--- Loading ROM ---" << std::endl;
177 struct loaded_rom r;
178 try {
179 r = load_rom_from_commandline(cmdline);
180 r.load();
181 } catch(std::bad_alloc& e) {
182 OOM_panic();
183 } catch(std::exception& e) {
184 messages << "FATAL: Can't load ROM: " << e.what() << std::endl;
185 fatal_error();
186 exit(1);
188 messages << "Detected region: " << gtype::tostring(r.rtype, r.region) << std::endl;
189 if(r.region == REGION_PAL)
190 set_nominal_framerate(322445.0/6448.0);
191 else if(r.region == REGION_NTSC)
192 set_nominal_framerate(10738636.0/178683.0);
194 messages << "--- Internal memory mappings ---" << std::endl;
195 dump_region_map();
196 messages << "--- End of Startup --- " << std::endl;
197 moviefile movie;
198 movie.force_corrupt = true;
199 try {
200 bool loaded = false;
201 bool tried = false;
202 for(auto i = cmdline.begin(); i != cmdline.end(); i++)
203 if(i->length() > 0 && (*i)[0] != '-') {
204 try {
205 tried = true;
206 movie = moviefile(*i);
207 loaded = true;
208 } catch(std::bad_alloc& e) {
209 OOM_panic();
210 } catch(std::exception& e) {
211 messages << "Error loading '" << *i << "': " << e.what() << std::endl;
214 if(!tried)
215 movie = generate_movie_template(cmdline, r);
216 sdl_main_loop(r, movie);
217 } catch(std::bad_alloc& e) {
218 OOM_panic();
219 } catch(std::exception& e) {
220 messages << "FATAL: " << e.what() << std::endl;
221 fatal_error();
222 return 1;
224 rrdata::close();
225 platform::quit();
226 quit_lua();
227 return 0;