sdmp2sox: Add blend 512x224/240 and enlarge to 512x448/480 mode
[lsnes.git] / lsnes-dumpavi.cpp
blobf946cc10d9edba8e4cd09387f95e9a4928bdccca
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 bool sdmp = false;
74 bool ssflag = false;
75 for(auto i = cmdline.begin(); i != cmdline.end(); i++) {
76 std::string a = *i;
77 if(a == "--jmd")
78 jmd = true;
79 if(a == "--sdmp")
80 sdmp = true;
81 if(a == "--ss")
82 ssflag = true;
83 if(a.length() > 9 && a.substr(0, 9) == "--prefix=")
84 prefix = a.substr(9);
85 if(a.length() > 8 && a.substr(0, 8) == "--level=")
86 try {
87 level = boost::lexical_cast<unsigned>(a.substr(8));
88 if(level < 0 || level > 18)
89 throw std::runtime_error("Level out of range (0-18)");
90 } catch(std::exception& e) {
91 std::cerr << "Bad --level: " << e.what() << std::endl;
92 exit(1);
94 if(a.length() > 9 && a.substr(0, 9) == "--length=")
95 try {
96 length = boost::lexical_cast<uint64_t>(a.substr(9));
97 if(!length)
98 throw std::runtime_error("Length out of range (1-)");
99 } catch(std::exception& e) {
100 std::cerr << "Bad --length: " << e.what() << std::endl;
101 exit(1);
104 if(!length) {
105 std::cerr << "--length=<frames> has to be specified" << std::endl;
106 exit(1);
108 if(jmd && sdmp) {
109 std::cerr << "--jmd and --sdmp are mutually exclusive" << std::endl;
110 exit(1);
112 std::cout << "Invoking dumper" << std::endl;
113 std::ostringstream cmd;
114 if(sdmp && ssflag)
115 cmd << "dump-sdmpss " << prefix;
116 else if(sdmp)
117 cmd << "dump-sdmp " << prefix;
118 else if(jmd)
119 cmd << "dump-jmd " << level << " " << prefix;
120 else
121 cmd << "dump-avi " << level << " " << prefix;
122 command::invokeC(cmd.str());
123 if(av_snooper::dump_in_progress()) {
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 std::vector<std::string> cmdline;
155 for(int i = 1; i < argc; i++)
156 cmdline.push_back(argv[i]);
157 my_interfaced intrf;
158 SNES::interface = &intrf;
160 set_random_seed();
163 std::ostringstream x;
164 x << snes_library_id() << " (" << SNES::Info::Profile << " core)";
165 bsnes_core_version = x.str();
167 init_lua();
169 messages << "BSNES version: " << bsnes_core_version << std::endl;
170 messages << "lsnes version: lsnes rr" << lsnes_version << std::endl;
171 messages << "Command line is: ";
172 for(auto k = cmdline.begin(); k != cmdline.end(); k++)
173 messages << "\"" << *k << "\" ";
174 messages << std::endl;
176 std::string cfgpath = get_config_path();
178 messages << "--- Loading ROM ---" << std::endl;
179 struct loaded_rom r;
180 try {
181 r = load_rom_from_commandline(cmdline);
182 r.load();
183 } catch(std::bad_alloc& e) {
184 OOM_panic();
185 } catch(std::exception& e) {
186 messages << "FATAL: Can't load ROM: " << e.what() << std::endl;
187 fatal_error();
188 exit(1);
190 messages << "Detected region: " << gtype::tostring(r.rtype, r.region) << std::endl;
191 if(r.region == REGION_PAL)
192 set_nominal_framerate(322445.0/6448.0);
193 else if(r.region == REGION_NTSC)
194 set_nominal_framerate(10738636.0/178683.0);
196 messages << "--- Internal memory mappings ---" << std::endl;
197 dump_region_map();
198 messages << "--- End of Startup --- " << std::endl;
201 moviefile movie;
202 try {
203 bool tried = false;
204 bool loaded = false;
205 for(auto i = cmdline.begin(); i != cmdline.end(); i++)
206 if(i->length() > 0 && (*i)[0] != '-') {
207 try {
208 tried = true;
209 movie = moviefile(*i);
210 loaded = true;
211 } catch(std::bad_alloc& e) {
212 OOM_panic();
213 } catch(std::exception& e) {
214 messages << "Error loading '" << *i << "': " << e.what() << std::endl;
217 if(!tried)
218 throw std::runtime_error("Specifying movie is required");
219 if(!loaded)
220 throw std::runtime_error("Can't load any of the movies specified");
221 //Load ROM before starting the dumper.
222 our_rom = &r;
223 our_rom->region = gtype::toromregion(movie.gametype);
224 our_rom->load();
225 dumper_startup(cmdline);
226 startup_lua_scripts(cmdline);
227 main_loop(r, movie, true);
228 } catch(std::bad_alloc& e) {
229 OOM_panic();
230 } catch(std::exception& e) {
231 messages << "FATAL: " << e.what() << std::endl;
232 fatal_error();
233 return 1;
235 rrdata::close();
236 return 0;