Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libsnes/bsnes/nall/bps/metadata.hpp
2 views
1
#ifndef NALL_BPS_METADATA_HPP
2
#define NALL_BPS_METADATA_HPP
3
4
#include <nall/crc32.hpp>
5
#include <nall/file.hpp>
6
#include <nall/filemap.hpp>
7
#include <nall/stdint.hpp>
8
#include <nall/string.hpp>
9
10
namespace nall {
11
12
struct bpsmetadata {
13
inline bool load(const string &filename);
14
inline bool save(const string &filename, const string &metadata);
15
inline string metadata() const;
16
17
protected:
18
file sourceFile;
19
string metadataString;
20
};
21
22
bool bpsmetadata::load(const string &filename) {
23
if(sourceFile.open(filename, file::mode::read) == false) return false;
24
25
auto read = [&]() -> uint8_t {
26
return sourceFile.read();
27
};
28
29
auto decode = [&]() -> uint64_t {
30
uint64_t data = 0, shift = 1;
31
while(true) {
32
uint8_t x = read();
33
data += (x & 0x7f) * shift;
34
if(x & 0x80) break;
35
shift <<= 7;
36
data += shift;
37
}
38
return data;
39
};
40
41
if(read() != 'B') return false;
42
if(read() != 'P') return false;
43
if(read() != 'S') return false;
44
if(read() != '1') return false;
45
decode();
46
decode();
47
unsigned metadataSize = decode();
48
char data[metadataSize + 1];
49
for(unsigned n = 0; n < metadataSize; n++) data[n] = read();
50
data[metadataSize] = 0;
51
metadataString = (const char*)data;
52
53
return true;
54
}
55
56
bool bpsmetadata::save(const string &filename, const string &metadata) {
57
file targetFile;
58
if(targetFile.open(filename, file::mode::write) == false) return false;
59
if(sourceFile.open() == false) return false;
60
sourceFile.seek(0);
61
62
auto read = [&]() -> uint8_t {
63
return sourceFile.read();
64
};
65
66
auto decode = [&]() -> uint64_t {
67
uint64_t data = 0, shift = 1;
68
while(true) {
69
uint8_t x = read();
70
data += (x & 0x7f) * shift;
71
if(x & 0x80) break;
72
shift <<= 7;
73
data += shift;
74
}
75
return data;
76
};
77
78
uint32_t checksum = ~0;
79
80
auto write = [&](uint8_t data) {
81
targetFile.write(data);
82
checksum = crc32_adjust(checksum, data);
83
};
84
85
auto encode = [&](uint64_t data) {
86
while(true) {
87
uint64_t x = data & 0x7f;
88
data >>= 7;
89
if(data == 0) {
90
write(0x80 | x);
91
break;
92
}
93
write(x);
94
data--;
95
}
96
};
97
98
for(unsigned n = 0; n < 4; n++) write(read());
99
encode(decode());
100
encode(decode());
101
unsigned sourceLength = decode();
102
unsigned targetLength = metadata.length();
103
encode(targetLength);
104
sourceFile.seek(sourceLength, file::index::relative);
105
for(unsigned n = 0; n < targetLength; n++) write(metadata[n]);
106
unsigned length = sourceFile.size() - sourceFile.offset() - 4;
107
for(unsigned n = 0; n < length; n++) write(read());
108
uint32_t outputChecksum = ~checksum;
109
for(unsigned n = 0; n < 32; n += 8) write(outputChecksum >> n);
110
111
targetFile.close();
112
return true;
113
}
114
115
string bpsmetadata::metadata() const {
116
return metadataString;
117
}
118
119
}
120
121
#endif
122
123