| 96 | } |
| 97 | |
| 98 | bool patchApplyIPS(MFILE * f, u8 **r, int *s) { |
| 99 | // from the IPS spec at http://zerosoft.zophar.net/ips.htm |
| 100 | |
| 101 | bool result = false; |
| 102 | |
| 103 | u8 *rom = *r; |
| 104 | int size = *s; |
| 105 | if (memfgetc(f) == 'P' && memfgetc(f) == 'A' && memfgetc(f) == 'T' |
| 106 | && memfgetc(f) == 'C' && memfgetc(f) == 'H') { |
| 107 | int b; |
| 108 | int offset; |
| 109 | int len; |
| 110 | |
| 111 | result = true; |
| 112 | |
| 113 | for (;;) { |
| 114 | // read offset |
| 115 | offset = readInt3(f); |
| 116 | // if offset == MEOF, end of patch |
| 117 | if (offset == 0x454f46 || offset == -1) |
| 118 | break; |
| 119 | // read length |
| 120 | len = readInt2(f); |
| 121 | if (!len) { |
| 122 | // len == 0, RLE block |
| 123 | len = readInt2(f); |
| 124 | // byte to fill |
| 125 | int c = memfgetc(f); |
| 126 | if (c == -1) |
| 127 | break; |
| 128 | b = (u8) c; |
| 129 | } else |
| 130 | b = -1; |
| 131 | // check if we need to reallocate our ROM |
| 132 | if ((offset + len) >= size) { |
| 133 | #ifdef GEKKO |
| 134 | size = offset + len; |
| 135 | #else |
| 136 | size *= 2; |
| 137 | rom = (u8 *) realloc(rom, size); |
| 138 | #endif |
| 139 | *r = rom; |
| 140 | *s = size; |
| 141 | } |
| 142 | if (b == -1) { |
| 143 | // normal block, just read the data |
| 144 | if (memfread(&rom[offset], 1, len, f) != (size_t) len) |
| 145 | break; |
| 146 | } else { |
| 147 | // fill the region with the given byte |
| 148 | while (len--) { |
| 149 | rom[offset++] = b; |
| 150 | } |
| 151 | } |
| 152 | } |
| 153 | } |
| 154 | return result; |
| 155 | } |