Wxwidgets: Allow controlling dumper start/stop from menu
[lsnes.git] / src / util / movieinfo.cpp
blob0fca184d1af601043537cd7b25c0a688e68b7023
1 #include "core/moviefile.hpp"
2 #include "core/rrdata.hpp"
4 #include <iostream>
5 #include <iomanip>
6 #include <string>
7 #include <sstream>
9 std::string name_romtype(rom_type r)
11 if(r == ROMTYPE_SNES) return "SNES";
12 if(r == ROMTYPE_BSX) return "BS-X (non-slotted)";
13 if(r == ROMTYPE_BSXSLOTTED) return "BS-X (slotted)";
14 if(r == ROMTYPE_SUFAMITURBO) return "Sufami turbo";
15 if(r == ROMTYPE_SGB) return "SGB";
16 return "Unknown";
19 std::string name_region(rom_region r)
21 if(r == REGION_PAL) return "PAL";
22 if(r == REGION_NTSC) return "NTSC";
23 return "Unknown";
26 std::string name_porttype(porttype_t r)
28 if(r == PT_NONE) return "No device";
29 if(r == PT_GAMEPAD) return "Gamepad";
30 if(r == PT_MULTITAP) return "Multitap";
31 if(r == PT_MOUSE) return "Mouse";
32 if(r == PT_SUPERSCOPE) return "Super Scope";
33 if(r == PT_JUSTIFIER) return "Justifier";
34 if(r == PT_JUSTIFIERS) return "2 Justifiers";
35 return "Unknown";
38 std::string escape_string(std::string x)
40 std::ostringstream out;
41 for(size_t i = 0; i < x.length(); i++)
42 if((x[i] < 0 || x[i] > 31) && x[i] != '\\')
43 out << x[i];
44 else {
45 unsigned char y = static_cast<unsigned char>(x[i]);
46 out << "\\" << ('0' + static_cast<char>((y >> 6) & 7))
47 << ('0' + static_cast<char>((y >> 3) & 7))
48 << ('0' + static_cast<char>(y & 7));
50 return out.str();
53 int main(int argc, char** argv)
55 reached_main();
56 if(argc != 2) {
57 std::cerr << "Syntax: " << argv[0] << " <moviefile>" << std::endl;
58 return 1;
60 try {
61 uint64_t starting_point = 0;
62 struct moviefile m(argv[1]);
63 rom_type rtype = gtype::toromtype(m.gametype);
64 rom_region reg = gtype::toromregion(m.gametype);
65 std::cout << "Console: " << name_romtype(rtype) << std::endl;
66 std::cout << "Region: " << name_region(reg) << std::endl;
67 std::cout << "Port #1: " << name_porttype(m.port1) << std::endl;
68 std::cout << "Port #2: " << name_porttype(m.port1) << std::endl;
69 std::cout << "Used emulator core: " << escape_string(m.coreversion) << std::endl;
70 if(m.gamename != "")
71 std::cout << "Game name: " << escape_string(m.gamename) << std::endl;
72 else
73 std::cout << "No game name available" << std::endl;
74 std::cout << "Project ID: " << escape_string(m.projectid) << std::endl;
75 if(m.rom_sha256 != "") {
76 std::cout << "ROM checksum: " << escape_string(m.rom_sha256) << std::endl;
77 if(m.romxml_sha256 != "")
78 std::cout << "ROM XML checksum: " << escape_string(m.romxml_sha256) << std::endl;
79 else
80 std::cout << "Using default settings for ROM" << std::endl;
81 } else
82 std::cout << "No main ROM present" << std::endl;
83 if(m.slota_sha256 != "") {
84 std::cout << "BS/ST-A/DMG checksum: " << escape_string(m.slota_sha256) << std::endl;
85 if(m.slotaxml_sha256 != "")
86 std::cout << "BS/ST-A/DMG XML checksum: " << escape_string(m.slotaxml_sha256)
87 << std::endl;
88 else
89 std::cout << "Using default settings for BS/ST-A/DMG" << std::endl;
90 } else
91 std::cout << "No BS/ST-A/DMG present" << std::endl;
92 if(m.slotb_sha256 != "") {
93 std::cout << "ST-B checksum: " << escape_string(m.slotb_sha256) << std::endl;
94 if(m.slotbxml_sha256 != "")
95 std::cout << "ST-B XML checksum: " << escape_string(m.slotbxml_sha256)
96 << std::endl;
97 else
98 std::cout << "Using default settings for BS/ST-A/DMG" << std::endl;
99 } else
100 std::cout << "No ST-B present" << std::endl;
101 for(auto i = m.authors.begin(); i != m.authors.end(); i++) {
102 if(i->first != "" && i->second != "")
103 std::cout << "Author: " << escape_string(i->first) << " (" << escape_string(i->second)
104 << ")" << std::endl;
105 else if(i->first != "" && i->second == "")
106 std::cout << "Author: " << escape_string(i->first) << std::endl;
107 else if(i->first == "" && i->second != "")
108 std::cout << "Author: (" << escape_string(i->second) << ")" << std::endl;
110 if(m.authors.size() == 0)
111 std::cout << "No author info available" << std::endl;
112 if(m.is_savestate) {
113 std::cout << "Movie starts from savestate" << std::endl;
114 for(auto i = m.movie_sram.begin(); i != m.movie_sram.end(); i++)
115 std::cout << "Start SRAM: " << escape_string(i->first) << ": [" << i->second.size()
116 << " bytes of binary data]" << std::endl;
117 if(!m.movie_sram.size())
118 std::cout << "No starting SRAM" << std::endl;
119 for(auto i = m.sram.begin(); i != m.sram.end(); i++)
120 std::cout << "Saved SRAM: " << escape_string(i->first) << ": [" << i->second.size()
121 << " bytes of binary data]" << std::endl;
122 if(!m.sram.size())
123 std::cout << "No saved SRAM" << std::endl;
124 std::cout << "Savestate: [" << m.savestate.size() << " bytes of binary data]" << std::endl;
125 std::cout << "Host memory: [" << m.host_memory.size() << " bytes of binary data]"
126 << std::endl;
127 std::cout << "Screenshot: [" << m.screenshot.size() << " bytes of binary data]" << std::endl;
128 if(m.screenshot.size() >= 4) {
129 uint16_t a = static_cast<uint8_t>(m.screenshot[0]);
130 uint16_t b = static_cast<uint8_t>(m.screenshot[1]);
131 std::cout << "Screenshot size: " << (a * 256 + b) << "*" << (m.screenshot.size() - 2)
132 / (a * 256 + b) / 3 << std::endl;
133 } else
134 std::cout << "Screenshot is corrupt" << std::endl;
135 starting_point = m.save_frame;
136 std::cout << "Starting frame: " << starting_point << std::endl;
137 std::cout << "Lag frames so far: " << m.lagged_frames << std::endl;
138 } else if(m.movie_sram.size() > 0) {
139 std::cout << "Movie starts from SRAM" << std::endl;
140 for(auto i = m.movie_sram.begin(); i != m.movie_sram.end(); i++)
141 std::cout << "Start SRAM: " << escape_string(i->first) << " (" << i->second.size()
142 << " bytes)" << std::endl;
143 } else
144 std::cout << "Movie starts from clean state" << std::endl;
145 if(m.get_frame_count() > starting_point)
146 std::cout << "Movie frame count: " << (m.get_frame_count() - starting_point) << std::endl;
147 else
148 std::cout << "Movie frame count: 0" << std::endl;
149 uint64_t length = m.get_movie_length(starting_point);
151 std::ostringstream x;
152 if(length >= 3600000000000ULL) {
153 x << (length / 3600000000000ULL) << ":";
154 length %= 3600000000000ULL;
156 x << std::setw(2) << std::setfill('0') << (length / 60000000000ULL) << ":";
157 length %= 60000000000ULL;
158 x << std::setw(2) << std::setfill('0') << (length / 1000000000ULL) << ".";
159 length %= 1000000000ULL;
160 x << std::setw(3) << std::setfill('0') << (length + 500000) / 1000000;
161 std::cout << "Movie length: " << x.str() << std::endl;
163 std::cout << "Rerecord count: " << rrdata::count(m.c_rrdata) << std::endl;
164 } catch(std::exception& e) {
165 std::cerr << "ERROR: " << e.what() << std::endl;
166 return 1;
168 return 0;