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"
21 #if defined(_WIN32) || defined(_WIN64) || defined(TEST_WIN32_CODE) || defined(__APPLE__)
26 class my_interfaced
: public SNES::Interface
28 string
path(SNES::Cartridge::Slot slot
, const string
&hint
)
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
++) {
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
);
76 void run_extra_scripts(const std::vector
<std::string
>& cmdline
)
78 for(auto i
= cmdline
.begin(); i
!= cmdline
.end(); 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
);
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
);
103 main_loop(*args
->rom
, *args
->initial
, args
->load_has_to_succeed
);
104 notify_emulator_exit();
105 } catch(std::bad_alloc
& e
) {
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
)
122 struct emu_args args
;
124 args
.initial
= &initial
;
125 args
.load_has_to_succeed
= load_has_to_succeed
;
128 t
= &thread::create(emulator_thread
, &args
);
129 t2
= &thread::create(joystick_thread
, &args
);
131 joystick_plugin::signal();
136 } catch(std::bad_alloc
& e
) {
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
]);
148 SNES::interface
= &intrf
;
153 std::ostringstream x
;
154 x
<< snes_library_id() << " (" << SNES::Info::Profile
<< " core)";
155 bsnes_core_version
= x
.str();
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();
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
;
179 r
= load_rom_from_commandline(cmdline
);
181 } catch(std::bad_alloc
& e
) {
183 } catch(std::exception
& e
) {
184 messages
<< "FATAL: Can't load ROM: " << e
.what() << std::endl
;
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
;
196 messages
<< "--- End of Startup --- " << std::endl
;
198 movie
.force_corrupt
= true;
202 for(auto i
= cmdline
.begin(); i
!= cmdline
.end(); i
++)
203 if(i
->length() > 0 && (*i
)[0] != '-') {
206 movie
= moviefile(*i
);
208 } catch(std::bad_alloc
& e
) {
210 } catch(std::exception
& e
) {
211 messages
<< "Error loading '" << *i
<< "': " << e
.what() << std::endl
;
215 movie
= generate_movie_template(cmdline
, r
);
216 sdl_main_loop(r
, movie
);
217 } catch(std::bad_alloc
& e
) {
219 } catch(std::exception
& e
) {
220 messages
<< "FATAL: " << e
.what() << std::endl
;