Change the RTC time format
[lsnes.git] / lsnes-dumpavi.cpp
blob2cc3e78958b2ef23dafbd41ce698ddfc9299b981
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 #include "avsnoop.hpp"
18 namespace
20 class myavsnoop : public av_snooper
22 public:
23 myavsnoop(uint64_t frames_to_dump)
25 frames_dumped = 0;
26 total = frames_to_dump;
29 ~myavsnoop()
33 void frame(struct lcscreen& _frame, uint32_t fps_n, uint32_t fps_d) throw(std::bad_alloc,
34 std::runtime_error)
36 frames_dumped++;
37 if(frames_dumped % 100 == 0) {
38 std::cout << "Dumping frame " << frames_dumped << "/" << total << " ("
39 << (100 * frames_dumped / total) << "%)" << std::endl;
41 if(frames_dumped == total) {
42 //Rough way to end it.
43 av_snooper::end(true);
44 exit(1);
48 void sample(short l, short r) throw(std::bad_alloc, std::runtime_error)
52 void end() throw(std::bad_alloc, std::runtime_error)
54 std::cout << "Finished!" << std::endl;
57 void gameinfo(const std::string& gamename, const std::list<std::pair<std::string, std::string>>&
58 authors, double gametime, const std::string& rerecords) throw(std::bad_alloc,
59 std::runtime_error)
62 private:
63 uint64_t frames_dumped;
64 uint64_t total;
67 void dumper_startup(const std::vector<std::string>& cmdline)
69 unsigned level = 7;
70 std::string prefix = "avidump";
71 uint64_t length = 0;
72 bool jmd = false;
73 for(auto i = cmdline.begin(); i != cmdline.end(); i++) {
74 std::string a = *i;
75 if(a == "--jmd")
76 jmd = true;
77 if(a.length() > 9 && a.substr(0, 9) == "--prefix=")
78 prefix = a.substr(9);
79 if(a.length() > 8 && a.substr(0, 8) == "--level=")
80 try {
81 level = boost::lexical_cast<unsigned>(a.substr(8));
82 if(level < 0 || level > 18)
83 throw std::runtime_error("Level out of range (0-18)");
84 } catch(std::exception& e) {
85 std::cerr << "Bad --level: " << e.what() << std::endl;
86 exit(1);
88 if(a.length() > 9 && a.substr(0, 9) == "--length=")
89 try {
90 length = boost::lexical_cast<uint64_t>(a.substr(9));
91 if(!length)
92 throw std::runtime_error("Length out of range (1-)");
93 } catch(std::exception& e) {
94 std::cerr << "Bad --length: " << e.what() << std::endl;
95 exit(1);
98 if(!length) {
99 std::cerr << "--length=<frames> has to be specified" << std::endl;
100 exit(1);
102 std::cout << "Invoking dumper" << std::endl;
103 std::ostringstream cmd;
104 if(jmd)
105 cmd << "dump-jmd " << level << " " << prefix;
106 else
107 cmd << "dump-avi " << level << " " << prefix;
108 command::invokeC(cmd.str());
109 if(av_snooper::dump_in_progress()) {
110 std::cout << "Dumper attach confirmed" << std::endl;
111 } else {
112 std::cout << "Can't start dumper!" << std::endl;
113 exit(1);
115 myavsnoop* s = new myavsnoop(length);
118 void startup_lua_scripts(const std::vector<std::string>& cmdline)
120 for(auto i = cmdline.begin(); i != cmdline.end(); i++) {
121 std::string a = *i;
122 if(a.length() > 6 && a.substr(0, 6) == "--lua=") {
123 command::invokeC("run-lua " + a.substr(6));
129 class my_interfaced : public SNES::Interface
131 string path(SNES::Cartridge::Slot slot, const string &hint)
133 return "./";
138 int main(int argc, char** argv)
140 std::vector<std::string> cmdline;
141 for(int i = 1; i < argc; i++)
142 cmdline.push_back(argv[i]);
143 my_interfaced intrf;
144 SNES::interface = &intrf;
146 set_random_seed();
149 std::ostringstream x;
150 x << snes_library_id() << " (" << SNES::Info::Profile << " core)";
151 bsnes_core_version = x.str();
153 init_lua();
155 messages << "BSNES version: " << bsnes_core_version << std::endl;
156 messages << "lsnes version: lsnes rr" << lsnes_version << std::endl;
157 messages << "Command line is: ";
158 for(auto k = cmdline.begin(); k != cmdline.end(); k++)
159 messages << "\"" << *k << "\" ";
160 messages << std::endl;
162 std::string cfgpath = get_config_path();
164 messages << "--- Loading ROM ---" << std::endl;
165 struct loaded_rom r;
166 try {
167 r = load_rom_from_commandline(cmdline);
168 r.load();
169 } catch(std::bad_alloc& e) {
170 OOM_panic();
171 } catch(std::exception& e) {
172 messages << "FATAL: Can't load ROM: " << e.what() << std::endl;
173 fatal_error();
174 exit(1);
176 messages << "Detected region: " << gtype::tostring(r.rtype, r.region) << std::endl;
177 if(r.region == REGION_PAL)
178 set_nominal_framerate(322445.0/6448.0);
179 else if(r.region == REGION_NTSC)
180 set_nominal_framerate(10738636.0/178683.0);
182 messages << "--- Internal memory mappings ---" << std::endl;
183 dump_region_map();
184 messages << "--- End of Startup --- " << std::endl;
187 moviefile movie;
188 try {
189 bool tried = false;
190 bool loaded = false;
191 for(auto i = cmdline.begin(); i != cmdline.end(); i++)
192 if(i->length() > 0 && (*i)[0] != '-') {
193 try {
194 tried = true;
195 movie = moviefile(*i);
196 loaded = true;
197 } catch(std::bad_alloc& e) {
198 OOM_panic();
199 } catch(std::exception& e) {
200 messages << "Error loading '" << *i << "': " << e.what() << std::endl;
203 if(!tried)
204 throw std::runtime_error("Specifying movie is required");
205 if(!loaded)
206 throw std::runtime_error("Can't load any of the movies specified");
207 //Load ROM before starting the dumper.
208 our_rom = &r;
209 our_rom->region = gtype::toromregion(movie.gametype);
210 our_rom->load();
211 dumper_startup(cmdline);
212 startup_lua_scripts(cmdline);
213 main_loop(r, movie, true);
214 } catch(std::bad_alloc& e) {
215 OOM_panic();
216 } catch(std::exception& e) {
217 messages << "FATAL: " << e.what() << std::endl;
218 fatal_error();
219 return 1;
221 rrdata::close();
222 return 0;