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 char *pos = strchr(line, '|'), *start = line;
28 // Skip: Title[start..pos]
31 pos = strchr(start, '|');
33 // Skip: Flags1[start..pos]
36 pos = strchr(start, '|');
38 // Skip: Flags2[start..pos]
41 pos = strchr(start, '|');
43 // Skip: Autoscroll1[start..pos]
46 pos = strchr(start, '|');
48 // Skip: Autoscroll2[start..pos]
51 pos = strchr(start, '|');
53 // Skip: Scale[start..pos]
56 pos = strchr(start, '|');
57 // Skip: Offset[start..pos|end_of_line]
59 if (!pos) return 0; // No patches!
62 bool end_of_line = false;
63 printf("Loading patches: %s", start);
69 //start is at the "address to modify" string start
71 pos = strchr(start, '=');
74 addr = strtoul(start, &end, 16);
75 if (end != pos) return -1;
77 start = pos + 1; //start is at the "bytes to modify" string start
78 pos = strchr(start, ',');
80 len = (pos - start) / 2;
82 len = (strlen(start) - 1) / 2;
86 if (Settings.HacksFilter) {
88 // Only accept patches which contain opcode 42
90 for (int i = 0; i < len; i++) {
91 if (pos[0] == '4' && pos[1] == '2') {
99 start = pos + 1; // Go to end of individual patch
100 continue; // Skip this hack.
105 for (int i = 0; i < len; i++) {
106 char valStr[3] = { pos[0], pos[1], '\0' };
107 unsigned char val = strtoul(valStr, 0, 16);
109 printf("ROM[0x%lx..0x%lx]=0x%hhx 0x%hhx 0x%hhx\n",
110 addr + i - 1, addr + i + 1,
111 ROM[addr + i - 1], ROM[addr + i], ROM[addr + i + 1]);
112 printf("--> ROM[0x%lx]=0x%hhx\n", addr + i, val);
120 } while (!end_of_line);
125 void S9xHacksLoadFile(const char * file)
127 unsigned long gameCrc;
131 if (!Settings.HacksEnabled) goto no_hacks;
132 if (!file) goto no_hacks;
134 // At this point, the ROM is already loaded.
135 fp = fopen(file, "r");
137 fprintf(stderr, "Can't open hacks file %s: %s\n", file, strerror(errno));
141 // Get current ROM CRC
142 gameCrc = getGameCrc32();
144 line = (char*) malloc(kLineBufferSize + 1);
146 fgets(line, kLineBufferSize, fp);
148 char *pos = strchr(line, '|');
152 if (gameCrc == parseCrc32(line)) {
153 // Hit! This line's CRC matches our current ROM CRC.
154 int res = loadHacks(pos + 1);
156 printf("Hacks: searched %s for crc %lx, %d hacks loaded\n",
158 } else if (res < 0) {
159 printf("Hacks: searched %s for crc %lx, error parsing line\n",
162 printf("Hacks: searched %s for crc %lx, no hacks\n",
167 } while (!feof(fp) && !ferror(fp));
170 fprintf(stderr, "Error reading hacks file: %s\n", file);
173 printf("Hacks: searched %s for crc %lu; nothing found\n", file, gameCrc);
181 printf("Hacks: disabled\n");