all repos — mgba @ 5958d8c0da6af229b370e7b49879d559a718fcd5

mGBA Game Boy Advance Emulator

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}