SDL: Fix compilation error
[lsnes.git] / src / plat-sdl / main.cpp
blob25ed2fcd81cdaa819784ed7683f05007953ac90c
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.port1 = PT_GAMEPAD;
38 movie.port2 = PT_NONE;
39 movie.coreversion = bsnes_core_version;
40 movie.projectid = get_random_hexstring(40);
41 movie.gametype = gtype::togametype(r.rtype, r.region);
42 movie.rom_sha256 = r.rom.sha256;
43 movie.romxml_sha256 = r.rom_xml.sha256;
44 movie.slota_sha256 = r.slota.sha256;
45 movie.slotaxml_sha256 = r.slota_xml.sha256;
46 movie.slotb_sha256 = r.slotb.sha256;
47 movie.slotbxml_sha256 = r.slotb_xml.sha256;
48 movie.movie_sram = load_sram_commandline(cmdline);
49 for(auto i = cmdline.begin(); i != cmdline.end(); i++) {
50 std::string o = *i;
51 if(o.length() >= 9 && o.substr(0, 9) == "--prefix=")
52 movie.prefix = sanitize_prefix(o.substr(9));
53 if(o.length() >= 8 && o.substr(0, 8) == "--port1=")
54 movie.port1 = porttype_info::lookup(o.substr(8)).value;
55 if(o.length() >= 8 && o.substr(0, 8) == "--port2=")
56 movie.port2 = porttype_info::lookup(o.substr(8)).value;
57 if(o.length() >= 11 && o.substr(0, 11) == "--gamename=")
58 movie.gamename = o.substr(11);
59 if(o.length() >= 9 && o.substr(0, 9) == "--author=") {
60 std::string line = o.substr(9);
61 auto g = split_author(line);
62 movie.authors.push_back(g);
64 if(o.length() >= 13 && o.substr(0, 13) == "--rtc-second=") {
65 movie.rtc_second = movie.movie_rtc_second = parse_value<int64_t>(o.substr(13));
67 if(o.length() >= 16 && o.substr(0, 16) == "--rtc-subsecond=") {
68 movie.rtc_subsecond = movie.movie_rtc_subsecond = parse_value<int64_t>(o.substr(16));
69 if(movie.rtc_subsecond < 0 || movie.rtc_subsecond > 3462619485019ULL)
70 throw std::runtime_error("Bad RTC subsecond value (range is 0-3462619485019)");
73 movie.input.clear(movie.port1, movie.port2);
75 return movie;
78 namespace
80 void run_extra_scripts(const std::vector<std::string>& cmdline)
82 for(auto i = cmdline.begin(); i != cmdline.end(); i++) {
83 std::string o = *i;
84 if(o.length() >= 6 && o.substr(0, 6) == "--run=") {
85 std::string file = o.substr(6);
86 messages << "--- Running " << file << " --- " << std::endl;
87 command::invokeC("run-script " + file);
88 messages << "--- End running " << file << " --- " << std::endl;
93 void sdl_main_loop(struct loaded_rom& rom, struct moviefile& initial, bool load_has_to_succeed = false)
94 throw(std::bad_alloc, std::runtime_error);
96 struct emu_args
98 struct loaded_rom* rom;
99 struct moviefile* initial;
100 bool load_has_to_succeed;
103 void* emulator_thread(void* _args)
105 struct emu_args* args = reinterpret_cast<struct emu_args*>(_args);
106 try {
107 main_loop(*args->rom, *args->initial, args->load_has_to_succeed);
108 notify_emulator_exit();
109 } catch(std::bad_alloc& e) {
110 OOM_panic();
111 } catch(std::exception& e) {
112 messages << "FATAL: " << e.what() << std::endl;
113 platform::fatal_error();
117 void* joystick_thread(void* _args)
119 joystick_plugin::thread_fn();
122 void sdl_main_loop(struct loaded_rom& rom, struct moviefile& initial, bool load_has_to_succeed)
123 throw(std::bad_alloc, std::runtime_error)
125 try {
126 struct emu_args args;
127 args.rom = &rom;
128 args.initial = &initial;
129 args.load_has_to_succeed = load_has_to_succeed;
130 thread* t;
131 thread* t2;
132 t = &thread::create(emulator_thread, &args);
133 t2 = &thread::create(joystick_thread, &args);
134 ui_loop();
135 joystick_plugin::signal();
136 t2->join();
137 t->join();
138 delete t;
139 delete t2;
140 } catch(std::bad_alloc& e) {
141 OOM_panic();
146 int main(int argc, char** argv)
148 reached_main();
149 std::vector<std::string> cmdline;
150 for(int i = 1; i < argc; i++)
151 cmdline.push_back(argv[i]);
152 if(cmdline.size() == 1 && cmdline[0] == "--version") {
153 std::cout << "lsnes rr" << lsnes_version << " (" << lsnes_git_revision << ")" << std::endl;
154 std::cout << snes_library_id() << " (" << SNES::Info::Profile << " core)" << std::endl;
155 return 0;
157 my_interfaced intrf;
158 SNES::interface = &intrf;
160 set_random_seed();
163 std::ostringstream x;
164 x << snes_library_id() << " (" << SNES::Info::Profile << " core)";
165 bsnes_core_version = x.str();
167 platform::init();
168 init_lua();
170 messages << "BSNES version: " << bsnes_core_version << std::endl;
171 messages << "lsnes version: lsnes rr" << lsnes_version << std::endl;
172 messages << "Command line is: ";
173 for(auto k = cmdline.begin(); k != cmdline.end(); k++)
174 messages << "\"" << *k << "\" ";
175 messages << std::endl;
177 std::string cfgpath = get_config_path();
178 create_lsnesrc();
179 messages << "Saving per-user data to: " << get_config_path() << std::endl;
180 messages << "--- Running lsnesrc --- " << std::endl;
181 command::invokeC("run-script " + cfgpath + "/lsnes.rc");
182 messages << "--- End running lsnesrc --- " << std::endl;
184 run_extra_scripts(cmdline);
186 messages << "--- Loading ROM ---" << std::endl;
187 struct loaded_rom r;
188 try {
189 r = load_rom_from_commandline(cmdline);
190 r.load();
191 } catch(std::bad_alloc& e) {
192 OOM_panic();
193 } catch(std::exception& e) {
194 messages << "FATAL: Can't load ROM: " << e.what() << std::endl;
195 fatal_error();
196 exit(1);
198 messages << "Detected region: " << gtype::tostring(r.rtype, r.region) << std::endl;
199 if(r.region == REGION_PAL)
200 set_nominal_framerate(322445.0/6448.0);
201 else if(r.region == REGION_NTSC)
202 set_nominal_framerate(10738636.0/178683.0);
204 messages << "--- Internal memory mappings ---" << std::endl;
205 dump_region_map();
206 messages << "--- End of Startup --- " << std::endl;
207 moviefile movie;
208 movie.force_corrupt = true;
209 try {
210 bool loaded = false;
211 bool tried = false;
212 for(auto i = cmdline.begin(); i != cmdline.end(); i++)
213 if(i->length() > 0 && (*i)[0] != '-') {
214 try {
215 tried = true;
216 movie = moviefile(*i);
217 loaded = true;
218 } catch(std::bad_alloc& e) {
219 OOM_panic();
220 } catch(std::exception& e) {
221 messages << "Error loading '" << *i << "': " << e.what() << std::endl;
224 if(!tried)
225 movie = generate_movie_template(cmdline, r);
226 sdl_main_loop(r, movie);
227 } catch(std::bad_alloc& e) {
228 OOM_panic();
229 } catch(std::exception& e) {
230 messages << "FATAL: " << e.what() << std::endl;
231 fatal_error();
232 return 1;
234 rrdata::close();
235 platform::quit();
236 quit_lua();
237 return 0;