Fix unattended dumping
[lsnes.git] / src / util / lsnes-dumpavi.cpp
blobe44598c124b55db882d52de0981253fedb43609d
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("jmd-level", l.str());
115 cmd << "dump-jmd " << prefix;
116 } else {
117 std::ostringstream l;
118 l << level;
119 setting::set("avi-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 platform::init();
169 init_lua();
171 messages << "BSNES version: " << bsnes_core_version << std::endl;
172 messages << "lsnes version: lsnes rr" << lsnes_version << std::endl;
173 messages << "Command line is: ";
174 for(auto k = cmdline.begin(); k != cmdline.end(); k++)
175 messages << "\"" << *k << "\" ";
176 messages << std::endl;
178 std::string cfgpath = get_config_path();
180 messages << "--- Loading ROM ---" << std::endl;
181 struct loaded_rom r;
182 try {
183 r = load_rom_from_commandline(cmdline);
184 r.load();
185 } catch(std::bad_alloc& e) {
186 OOM_panic();
187 } catch(std::exception& e) {
188 messages << "FATAL: Can't load ROM: " << e.what() << std::endl;
189 fatal_error();
190 exit(1);
192 messages << "Detected region: " << gtype::tostring(r.rtype, r.region) << std::endl;
193 if(r.region == REGION_PAL)
194 set_nominal_framerate(322445.0/6448.0);
195 else if(r.region == REGION_NTSC)
196 set_nominal_framerate(10738636.0/178683.0);
198 messages << "--- Internal memory mappings ---" << std::endl;
199 dump_region_map();
200 messages << "--- End of Startup --- " << std::endl;
203 moviefile movie;
204 try {
205 bool tried = false;
206 bool loaded = false;
207 for(auto i = cmdline.begin(); i != cmdline.end(); i++)
208 if(i->length() > 0 && (*i)[0] != '-') {
209 try {
210 tried = true;
211 movie = moviefile(*i);
212 loaded = true;
213 } catch(std::bad_alloc& e) {
214 OOM_panic();
215 } catch(std::exception& e) {
216 messages << "Error loading '" << *i << "': " << e.what() << std::endl;
219 if(!tried)
220 throw std::runtime_error("Specifying movie is required");
221 if(!loaded)
222 throw std::runtime_error("Can't load any of the movies specified");
223 //Load ROM before starting the dumper.
224 our_rom = &r;
225 our_rom->region = gtype::toromregion(movie.gametype);
226 our_rom->load();
227 dumper_startup(cmdline);
228 startup_lua_scripts(cmdline);
229 main_loop(r, movie, true);
230 } catch(std::bad_alloc& e) {
231 OOM_panic();
232 } catch(std::exception& e) {
233 messages << "FATAL: " << e.what() << std::endl;
234 fatal_error();
235 return 1;
237 rrdata::close();
238 quit_lua();
239 return 0;