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