src/util/patch-ips.c (view raw)
1#include "util/patch-ips.h"
2
3#include "util/patch.h"
4#include "util/vfs.h"
5
6static size_t _IPSOutputSize(struct Patch* patch, size_t inSize);
7static bool _IPSApplyPatch(struct Patch* patch, void* out, size_t outSize);
8
9bool loadPatchIPS(struct Patch* patch) {
10 patch->vf->seek(patch->vf, 0, SEEK_SET);
11
12 char buffer[5];
13 if (patch->vf->read(patch->vf, buffer, 5) != 5) {
14 return false;
15 }
16
17 if (memcmp(buffer, "PATCH", 5) != 0) {
18 return false;
19 }
20
21 patch->vf->seek(patch->vf, -3, SEEK_END);
22 if (patch->vf->read(patch->vf, buffer, 3) != 3) {
23 return false;
24 }
25
26 if (memcmp(buffer, "EOF", 3) != 0) {
27 return false;
28 }
29
30 patch->outputSize = _IPSOutputSize;
31 patch->applyPatch = _IPSApplyPatch;
32 return true;
33}
34
35size_t _IPSOutputSize(struct Patch* patch, size_t inSize) {
36 UNUSED(patch);
37 return inSize;
38}
39
40bool _IPSApplyPatch(struct Patch* patch, void* out, size_t outSize) {
41 if (patch->vf->seek(patch->vf, 5, SEEK_SET) != 5) {
42 return false;
43 }
44 uint8_t* buf = out;
45
46 while (true) {
47 uint32_t offset = 0;
48 uint16_t size = 0;
49
50 if (patch->vf->read(patch->vf, &offset, 3) != 3) {
51 return false;
52 }
53
54 if (offset == 0x464F45) {
55 return true;
56 }
57
58 offset = (offset >> 16) | (offset & 0xFF00) | ((offset << 16) & 0xFF0000);
59 if (patch->vf->read(patch->vf, &size, 2) != 2) {
60 return false;
61 }
62 if (!size) {
63 // RLE chunk
64 if (patch->vf->read(patch->vf, &size, 2) != 2) {
65 return false;
66 }
67 size = (size >> 8) | (size << 8);
68 uint8_t byte;
69 if (patch->vf->read(patch->vf, &byte, 1) != 1) {
70 return false;
71 }
72 if (offset + size > outSize) {
73 return false;
74 }
75 memset(&buf[offset], byte, size);
76 } else {
77 size = (size >> 8) | (size << 8);
78 if (offset + size > outSize) {
79 return false;
80 }
81 if (patch->vf->read(patch->vf, &buf[offset], size) != size) {
82 return false;
83 }
84 }
85 }
86}