Wxwidgets: Allow controlling dumper start/stop from menu
[lsnes.git] / src / util / lsnes-dumpavi.cpp
blobcf890d810a053b81de02f5b2e34aa099d7caad0d
1 #include "lsnes.hpp"
2 #include <snes/snes.hpp>
3 #include <ui-libsnes/libsnes.hpp>
5 #include "core/command.hpp"
6 #include "core/dispatch.hpp"
7 #include "core/framerate.hpp"
8 #include "core/keymapper.hpp"
9 #include "core/lua.hpp"
10 #include "core/mainloop.hpp"
11 #include "core/misc.hpp"
12 #include "core/moviedata.hpp"
13 #include "core/rom.hpp"
14 #include "core/rrdata.hpp"
15 #include "core/settings.hpp"
16 #include "core/window.hpp"
18 #include <sys/time.h>
19 #include <sstream>
21 namespace
23 class myavsnoop : public information_dispatch
25 public:
26 myavsnoop(uint64_t frames_to_dump)
27 : information_dispatch("myavsnoop-monitor")
29 frames_dumped = 0;
30 total = frames_to_dump;
33 ~myavsnoop()
37 void on_frame(struct lcscreen& _frame, uint32_t fps_n, uint32_t fps_d)
39 frames_dumped++;
40 if(frames_dumped % 100 == 0) {
41 std::cout << "Dumping frame " << frames_dumped << "/" << total << " ("
42 << (100 * frames_dumped / total) << "%)" << std::endl;
44 if(frames_dumped == total) {
45 //Rough way to end it.
46 information_dispatch::do_dump_end();
47 exit(0);
51 void on_dump_end()
53 std::cout << "Finished!" << std::endl;
55 private:
56 uint64_t frames_dumped;
57 uint64_t total;
60 void dumper_startup(const std::vector<std::string>& cmdline)
62 unsigned level = 7;
63 std::string prefix = "avidump";
64 uint64_t length = 0;
65 bool jmd = false;
66 bool sdmp = false;
67 bool ssflag = false;
68 for(auto i = cmdline.begin(); i != cmdline.end(); i++) {
69 std::string a = *i;
70 if(a == "--jmd")
71 jmd = true;
72 if(a == "--sdmp")
73 sdmp = true;
74 if(a == "--ss")
75 ssflag = true;
76 if(a.length() > 9 && a.substr(0, 9) == "--prefix=")
77 prefix = a.substr(9);
78 if(a.length() > 8 && a.substr(0, 8) == "--level=")
79 try {
80 level = boost::lexical_cast<unsigned>(a.substr(8));
81 if(level < 0 || level > 18)
82 throw std::runtime_error("Level out of range (0-18)");
83 } catch(std::exception& e) {
84 std::cerr << "Bad --level: " << e.what() << std::endl;
85 exit(1);
87 if(a.length() > 9 && a.substr(0, 9) == "--length=")
88 try {
89 length = boost::lexical_cast<uint64_t>(a.substr(9));
90 if(!length)
91 throw std::runtime_error("Length out of range (1-)");
92 } catch(std::exception& e) {
93 std::cerr << "Bad --length: " << e.what() << std::endl;
94 exit(1);
97 if(!length) {
98 std::cerr << "--length=<frames> has to be specified" << std::endl;
99 exit(1);
101 if(jmd && sdmp) {
102 std::cerr << "--jmd and --sdmp are mutually exclusive" << std::endl;
103 exit(1);
105 std::cout << "Invoking dumper" << std::endl;
106 std::ostringstream cmd;
107 if(sdmp && ssflag)
108 cmd << "dump-sdmpss " << prefix;
109 else if(sdmp)
110 cmd << "dump-sdmp " << prefix;
111 else if(jmd) {
112 std::ostringstream l;
113 l << level;
114 setting::set("avi-level", l.str());
115 cmd << "dump-jmd " << prefix;
116 } else {
117 std::ostringstream l;
118 l << level;
119 setting::set("jmd-level", l.str());
120 cmd << "dump-avi " << prefix;
122 command::invokeC(cmd.str());
123 if(information_dispatch::get_dumper_count()) {
124 std::cout << "Dumper attach confirmed" << std::endl;
125 } else {
126 std::cout << "Can't start dumper!" << std::endl;
127 exit(1);
129 myavsnoop* s = new myavsnoop(length);
132 void startup_lua_scripts(const std::vector<std::string>& cmdline)
134 for(auto i = cmdline.begin(); i != cmdline.end(); i++) {
135 std::string a = *i;
136 if(a.length() > 6 && a.substr(0, 6) == "--lua=") {
137 command::invokeC("run-lua " + a.substr(6));
143 class my_interfaced : public SNES::Interface
145 string path(SNES::Cartridge::Slot slot, const string &hint)
147 return "./";
152 int main(int argc, char** argv)
154 reached_main();
155 std::vector<std::string> cmdline;
156 for(int i = 1; i < argc; i++)
157 cmdline.push_back(argv[i]);
158 my_interfaced intrf;
159 SNES::interface = &intrf;
161 set_random_seed();
164 std::ostringstream x;
165 x << snes_library_id() << " (" << SNES::Info::Profile << " core)";
166 bsnes_core_version = x.str();
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();
179 messages << "--- Loading ROM ---" << std::endl;
180 struct loaded_rom r;
181 try {
182 r = load_rom_from_commandline(cmdline);
183 r.load();
184 } catch(std::bad_alloc& e) {
185 OOM_panic();
186 } catch(std::exception& e) {
187 messages << "FATAL: Can't load ROM: " << e.what() << std::endl;
188 fatal_error();
189 exit(1);
191 messages << "Detected region: " << gtype::tostring(r.rtype, r.region) << std::endl;
192 if(r.region == REGION_PAL)
193 set_nominal_framerate(322445.0/6448.0);
194 else if(r.region == REGION_NTSC)
195 set_nominal_framerate(10738636.0/178683.0);
197 messages << "--- Internal memory mappings ---" << std::endl;
198 dump_region_map();
199 messages << "--- End of Startup --- " << std::endl;
202 moviefile movie;
203 try {
204 bool tried = false;
205 bool loaded = false;
206 for(auto i = cmdline.begin(); i != cmdline.end(); i++)
207 if(i->length() > 0 && (*i)[0] != '-') {
208 try {
209 tried = true;
210 movie = moviefile(*i);
211 loaded = true;
212 } catch(std::bad_alloc& e) {
213 OOM_panic();
214 } catch(std::exception& e) {
215 messages << "Error loading '" << *i << "': " << e.what() << std::endl;
218 if(!tried)
219 throw std::runtime_error("Specifying movie is required");
220 if(!loaded)
221 throw std::runtime_error("Can't load any of the movies specified");
222 //Load ROM before starting the dumper.
223 our_rom = &r;
224 our_rom->region = gtype::toromregion(movie.gametype);
225 our_rom->load();
226 dumper_startup(cmdline);
227 startup_lua_scripts(cmdline);
228 main_loop(r, movie, true);
229 } catch(std::bad_alloc& e) {
230 OOM_panic();
231 } catch(std::exception& e) {
232 messages << "FATAL: " << e.what() << std::endl;
233 fatal_error();
234 return 1;
236 rrdata::close();
237 quit_lua();
238 return 0;