Merge branch 'rr1-maint'
[lsnes.git] / src / util / lsvsdump.cpp
blob976d3ba116e3a5b047b8e7b6a8716ae4f9d4012a
1 #include "library/filesys.hpp"
2 #include "library/serialization.hpp"
3 #include "library/string.hpp"
4 #include <iostream>
6 struct stream_statistics
8 stream_statistics()
10 size = length = packets = clusters = 0;
12 stream_statistics operator+(const stream_statistics& s) const
14 stream_statistics r;
15 r.size = size + s.size;
16 r.length = length + s.length;
17 r.packets = packets + s.packets;
18 r.clusters = clusters + s.clusters;
19 return r;
21 stream_statistics& operator+=(const stream_statistics& s)
23 *this = *this + s;
24 return *this;
26 uint64_t size;
27 uint64_t length;
28 uint64_t packets;
29 uint64_t clusters;
32 stream_statistics dump_stream(filesystem& fs, uint32_t ccluster, uint32_t dcluster)
34 stream_statistics ss;
35 uint32_t ctrl_c = ccluster;
36 uint32_t ctrl_o = 0;
37 uint32_t data_c = dcluster;
38 uint32_t data_o = 0;
39 ss.clusters = 2;
40 while(true) {
41 uint32_t ctrl_uc = ctrl_c;
42 uint32_t ctrl_uo = ctrl_o;
43 uint32_t data_uc = data_c;
44 uint32_t data_uo = data_o;
45 char buffer[4];
46 size_t r = fs.read_data(ctrl_c, ctrl_o, buffer, 4);
47 if(r < 4)
48 break;
49 uint16_t psize = read16ube(buffer + 0);
50 uint16_t plength = 120 * read8ube(buffer + 2);
51 if(!read8ube(buffer + 3))
52 break;
53 r = fs.skip_data(data_c, data_o, psize);
54 if(r < psize)
55 (stringfmt() << "Unexpected end of data, read " << r << " bytes, expected "
56 << psize).throwex();
57 ss.size += psize;
58 ss.length += plength;
59 ss.packets++;
60 if(ctrl_uc != ctrl_c)
61 ss.clusters++;
62 if(data_uc != data_c)
63 ss.clusters++;
64 std::cout << "\tPacket: " << psize << " bytes@" << data_uc << ":" << data_uo << "(" << ctrl_uc
65 << ":" << ctrl_uo << "), " << plength << " samples." << std::endl;
67 std::cout << "\tTotal of " << ss.size << " bytes in " << ss.packets << " packets, " << ss.length
68 << " samples" << " (" << ss.clusters << " clusters used)" << std::endl;
69 return ss;
72 int main(int argc, char** argv)
74 stream_statistics ss;
75 if(argc != 2) {
76 std::cerr << "Syntax: lsvsdump <filename>" << std::endl;
77 return 1;
79 filesystem* fs;
80 uint64_t stream_count = 0;
81 try {
82 fs = new filesystem(argv[1]);
83 } catch(std::exception& e) {
84 std::cerr << "Can't load .lsvs file '" << argv[1] << "': " << e.what() << std::endl;
85 return 1;
87 try {
88 uint32_t maindir_c = 2;
89 uint32_t maindir_o = 0;
90 uint32_t maindir_uc;
91 uint32_t maindir_uo;
92 ss.clusters++;
93 while(true) {
94 maindir_uc = maindir_c;
95 maindir_uo = maindir_o;
96 char buffer[16];
97 size_t r = fs->read_data(maindir_c, maindir_o, buffer, 16);
98 if(r < 16)
99 break;
100 uint64_t stream_ts = read64ube(buffer);
101 uint32_t stream_c = read32ube(buffer + 8);
102 uint32_t stream_d = read32ube(buffer + 12);
103 if(!stream_c)
104 continue;
105 std::cout << "Found stream (from " << maindir_uc << ":" << maindir_uo << "): ts=" << stream_ts
106 << ", cluster=" << stream_c << "/" << stream_d << std::endl;
107 auto ss2 = dump_stream(*fs, stream_c, stream_d);
108 stream_count++;
109 ss += ss2;
110 if(maindir_c != maindir_uc)
111 ss.clusters++;
113 } catch(std::exception& e) {
114 std::cerr << "Error reading .lsvs file '" << argv[1] << "': " << e.what() << std::endl;
115 return 1;
117 std::cout << "Totals: " << ss.size << " bytes in " << ss.packets << " packets in " << stream_count <<
118 " streams, totalling " << ss.length << " samples. " << ss.clusters << " clusters used." << std::endl;
119 delete fs;