10 #define kLineBufferSize 4095
12 static inline unsigned long parseCrc32(const char * s)
14 return strtoul(s, 0, 16);
17 static unsigned long getGameCrc32()
19 unsigned long crc = crc32(0L, Z_NULL, 0);
20 crc = crc32(crc, ROM, Memory.CalculatedSize);
24 static int loadHacks(char * line)
27 bool end_of_line = false;
28 char *pos = strchr(line, '|'), *start = line;
31 printf("Hacks: detected \"%s\"\n", start);
34 pos = strchr(start, '|');
36 // If there are no flags, jump directly to hacks
39 // Skip: Flags1[start..pos]
42 pos = strchr(start, '|');
44 // Skip: Flags2[start..pos]
47 pos = strchr(start, '|');
49 // Skip: Autoscroll1[start..pos]
52 pos = strchr(start, '|');
54 // Skip: Autoscroll2[start..pos]
57 pos = strchr(start, '|');
59 // Skip: Scale[start..pos]
62 pos = strchr(start, '|');
63 // Skip: Offset[start..pos|end_of_line]
65 if (!pos) return 0; // No patches!
75 //start is at the "address to modify" string start
77 pos = strchr(start, '=');
80 addr = strtoul(start, &end, 16);
81 if (end != pos) return -1;
83 start = pos + 1; //start is at the "bytes to modify" string start
84 pos = strchr(start, ',');
86 len = (pos - start) / 2;
88 len = (strlen(start) - 1) / 2;
92 if (Settings.HacksFilter) {
94 // Only accept patches which contain opcode 42
96 for (int i = 0; i < len; i++) {
97 if (pos[0] == '4' && pos[1] == '2') {
105 start = pos + 1; // Go to end of individual patch
106 continue; // Skip this hack.
111 for (int i = 0; i < len; i++) {
112 char valStr[3] = { pos[0], pos[1], '\0' };
113 unsigned char val = strtoul(valStr, 0, 16);
116 printf("ROM[0x%lx..0x%lx]=0x%hhx 0x%hhx 0x%hhx\n",
117 addr + i - 1, addr + i + 1,
118 ROM[addr + i - 1], ROM[addr + i], ROM[addr + i + 1]);
119 printf("--> ROM[0x%lx]=0x%hhx\n", addr + i, val);
128 } while (!end_of_line);
133 void S9xHacksLoadFile(const char * file)
135 unsigned long gameCrc;
139 if (!Settings.HacksEnabled) goto no_hacks;
140 if (!file) goto no_hacks;
142 // At this point, the ROM is already loaded.
143 fp = fopen(file, "r");
145 fprintf(stderr, "Can't open hacks file %s: %s\n", file, strerror(errno));
149 // Get current ROM CRC
150 gameCrc = getGameCrc32();
152 line = (char*) malloc(kLineBufferSize + 1);
154 fgets(line, kLineBufferSize, fp);
156 char *pos = strchr(line, '|');
160 if (gameCrc == parseCrc32(line)) {
161 // Hit! This line's CRC matches our current ROM CRC.
162 int res = loadHacks(pos + 1);
164 printf("Hacks: searched %s for crc %lX, %d byte%s patched\n",
165 file, gameCrc, res, (res == 1 ? "" : "s"));
166 } else if (res < 0) {
167 printf("Hacks: searched %s for crc %lX, error parsing line\n",
170 printf("Hacks: searched %s for crc %lX, no hacks\n",
175 } while (!feof(fp) && !ferror(fp));
178 fprintf(stderr, "Error reading hacks file: %s\n", file);
181 printf("Hacks: searched %s for crc %lX; nothing found\n", file, gameCrc);
189 printf("Hacks: disabled\n");