lsnes rr0-β15
[lsnes.git] / lsnes.cpp
blobee98b4796b78a78e1f98efe58c56a4e405e8ff95
1 #include <sstream>
2 #include "mainloop.hpp"
3 #include "command.hpp"
4 #include "lua.hpp"
5 #include "moviedata.hpp"
6 #include "rrdata.hpp"
7 #include "lsnes.hpp"
8 #include "rom.hpp"
9 #include "keymapper.hpp"
10 #include "misc.hpp"
11 #include "window.hpp"
12 #include <sys/time.h>
13 #include <snes/snes.hpp>
14 #include <ui-libsnes/libsnes.hpp>
15 #include "framerate.hpp"
16 #if defined(_WIN32) || defined(_WIN64) || defined(TEST_WIN32_CODE) || defined(__APPLE__)
17 #include "SDL_main.h"
18 #endif
21 class my_interfaced : public SNES::Interface
23 string path(SNES::Cartridge::Slot slot, const string &hint)
25 return "./";
29 struct moviefile generate_movie_template(std::vector<std::string> cmdline, loaded_rom& r)
31 struct moviefile movie;
32 movie.coreversion = bsnes_core_version;
33 movie.projectid = get_random_hexstring(40);
34 movie.gametype = gtype::togametype(r.rtype, r.region);
35 movie.rom_sha256 = r.rom.sha256;
36 movie.romxml_sha256 = r.rom_xml.sha256;
37 movie.slota_sha256 = r.slota.sha256;
38 movie.slotaxml_sha256 = r.slota_xml.sha256;
39 movie.slotb_sha256 = r.slotb.sha256;
40 movie.slotbxml_sha256 = r.slotb_xml.sha256;
41 movie.movie_sram = load_sram_commandline(cmdline);
42 for(auto i = cmdline.begin(); i != cmdline.end(); i++) {
43 std::string o = *i;
44 if(o.length() >= 8 && o.substr(0, 8) == "--port1=")
45 movie.port1 = port_type::lookup(o.substr(8), false).ptype;
46 if(o.length() >= 8 && o.substr(0, 8) == "--port2=")
47 movie.port2 = port_type::lookup(o.substr(8), true).ptype;
48 if(o.length() >= 11 && o.substr(0, 11) == "--gamename=")
49 movie.gamename = o.substr(11);
50 if(o.length() >= 9 && o.substr(0, 9) == "--author=") {
51 std::string line = o.substr(9);
52 auto g = split_author(line);
53 movie.authors.push_back(g);
55 if(o.length() >= 13 && o.substr(0, 13) == "--rtc-second=") {
56 movie.rtc_second = movie.movie_rtc_second = parse_value<int64_t>(o.substr(13));
58 if(o.length() >= 16 && o.substr(0, 16) == "--rtc-subsecond=") {
59 movie.rtc_subsecond = movie.movie_rtc_subsecond = parse_value<int64_t>(o.substr(16));
60 if(movie.rtc_subsecond < 0 || movie.rtc_subsecond > 3462619485019ULL)
61 throw std::runtime_error("Bad RTC subsecond value (range is 0-3462619485019)");
67 return movie;
70 namespace
72 void run_extra_scripts(const std::vector<std::string>& cmdline)
74 for(auto i = cmdline.begin(); i != cmdline.end(); i++) {
75 std::string o = *i;
76 if(o.length() >= 6 && o.substr(0, 6) == "--run=") {
77 std::string file = o.substr(6);
78 messages << "--- Running " << file << " --- " << std::endl;
79 command::invokeC("run-script " + file);
80 messages << "--- End running " << file << " --- " << std::endl;
86 int main(int argc, char** argv)
88 std::vector<std::string> cmdline;
89 for(int i = 1; i < argc; i++)
90 cmdline.push_back(argv[i]);
91 my_interfaced intrf;
92 SNES::system.interface = &intrf;
94 set_random_seed();
97 std::ostringstream x;
98 x << snes_library_id() << " (" << SNES::Info::Profile << " core)";
99 bsnes_core_version = x.str();
101 window::init();
102 init_lua();
104 messages << "BSNES version: " << bsnes_core_version << std::endl;
105 messages << "lsnes version: lsnes rr" << lsnes_version << std::endl;
106 messages << "Command line is: ";
107 for(auto k = cmdline.begin(); k != cmdline.end(); k++)
108 messages << "\"" << *k << "\" ";
109 messages << std::endl;
111 std::string cfgpath = get_config_path();
112 create_lsnesrc();
113 messages << "Saving per-user data to: " << get_config_path() << std::endl;
114 messages << "--- Running lsnesrc --- " << std::endl;
115 command::invokeC("run-script " + cfgpath + "/lsnes.rc");
116 messages << "--- End running lsnesrc --- " << std::endl;
118 run_extra_scripts(cmdline);
120 messages << "--- Loading ROM ---" << std::endl;
121 struct loaded_rom r;
122 try {
123 r = load_rom_from_commandline(cmdline);
124 r.load();
125 } catch(std::bad_alloc& e) {
126 OOM_panic();
127 } catch(std::exception& e) {
128 messages << "FATAL: Can't load ROM: " << e.what() << std::endl;
129 fatal_error();
130 exit(1);
132 messages << "Detected region: " << gtype::tostring(r.rtype, r.region) << std::endl;
133 if(r.region == REGION_PAL)
134 set_nominal_framerate(322445.0/6448.0);
135 else if(r.region == REGION_NTSC)
136 set_nominal_framerate(10738636.0/178683.0);
138 messages << "--- Internal memory mappings ---" << std::endl;
139 dump_region_map();
140 messages << "--- End of Startup --- " << std::endl;
141 moviefile movie;
142 movie.force_corrupt = true;
143 try {
144 bool loaded = false;
145 bool tried = false;
146 for(auto i = cmdline.begin(); i != cmdline.end(); i++)
147 if(i->length() > 0 && (*i)[0] != '-') {
148 try {
149 tried = true;
150 movie = moviefile(*i);
151 loaded = true;
152 } catch(std::bad_alloc& e) {
153 OOM_panic();
154 } catch(std::exception& e) {
155 messages << "Error loading '" << *i << "': " << e.what() << std::endl;
158 if(!tried)
159 movie = generate_movie_template(cmdline, r);
160 main_loop(r, movie);
161 } catch(std::bad_alloc& e) {
162 OOM_panic();
163 } catch(std::exception& e) {
164 messages << "FATAL: " << e.what() << std::endl;
165 fatal_error();
166 return 1;
168 rrdata::close();
169 window::quit();
170 return 0;