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