Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libsnes/bsnes/nall/ips.hpp
2 views
1
#ifndef NALL_IPS_HPP
2
#define NALL_IPS_HPP
3
4
#include <nall/file.hpp>
5
#include <nall/stdint.hpp>
6
#include <nall/string.hpp>
7
8
namespace nall {
9
10
struct ips {
11
inline bool apply();
12
inline void source(const uint8_t *data, unsigned size);
13
inline void modify(const uint8_t *data, unsigned size);
14
inline bool source(const string &filename);
15
inline bool modify(const string &filename);
16
inline ips();
17
inline ~ips();
18
19
uint8_t *data;
20
unsigned size;
21
const uint8_t *sourceData;
22
unsigned sourceSize;
23
const uint8_t *modifyData;
24
unsigned modifySize;
25
};
26
27
bool ips::apply() {
28
if(modifySize < 8) return false;
29
if(modifyData[0] != 'P') return false;
30
if(modifyData[1] != 'A') return false;
31
if(modifyData[2] != 'T') return false;
32
if(modifyData[3] != 'C') return false;
33
if(modifyData[4] != 'H') return false;
34
35
if(data) delete[] data;
36
data = new uint8_t[16 * 1024 * 1024 + 65536](); //maximum size of IPS patch + single-tag padding
37
size = sourceSize;
38
memcpy(data, sourceData, sourceSize);
39
unsigned offset = 5;
40
41
while(true) {
42
unsigned address, length;
43
44
if(offset > modifySize - 3) break;
45
address = modifyData[offset++] << 16;
46
address |= modifyData[offset++] << 8;
47
address |= modifyData[offset++] << 0;
48
49
if(address == 0x454f46) { //EOF
50
if(offset == modifySize) return true;
51
if(offset == modifySize - 3) {
52
size = modifyData[offset++] << 16;
53
size |= modifyData[offset++] << 8;
54
size |= modifyData[offset++] << 0;
55
return true;
56
}
57
}
58
59
if(offset > modifySize - 2) break;
60
length = modifyData[offset++] << 8;
61
length |= modifyData[offset++] << 0;
62
63
if(length) { //Copy
64
if(offset > modifySize - length) break;
65
while(length--) data[address++] = modifyData[offset++];
66
} else { //RLE
67
if(offset > modifySize - 3) break;
68
length = modifyData[offset++] << 8;
69
length |= modifyData[offset++] << 0;
70
if(length == 0) break; //illegal
71
while(length--) data[address++] = modifyData[offset];
72
offset++;
73
}
74
75
size = max(size, address);
76
}
77
78
delete[] data;
79
data = nullptr;
80
return false;
81
}
82
83
void ips::source(const uint8_t *data, unsigned size) {
84
sourceData = data, sourceSize = size;
85
}
86
87
void ips::modify(const uint8_t *data, unsigned size) {
88
modifyData = data, modifySize = size;
89
}
90
91
bool ips::source(const string &filename) {
92
return file::read(filename, sourceData, sourceSize);
93
}
94
95
bool ips::modify(const string &filename) {
96
return file::read(filename, modifyData, modifySize);
97
}
98
99
ips::ips() : data(nullptr), sourceData(nullptr), modifyData(nullptr) {
100
}
101
102
ips::~ips() {
103
if(data) delete[] data;
104
if(sourceData) delete[] sourceData;
105
if(modifyData) delete[] modifyData;
106
}
107
108
}
109
110
#endif
111
112