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 if (!Settings.HacksEnabled) goto no_hacks;
128 if (!file) goto no_hacks;
130 // At this point, the ROM is already loaded.
131 FILE * fp = fopen(file, "r");
133 fprintf(stderr, "Can't open hacks file %s: %s\n", file, strerror(errno));
137 const unsigned long gameCrc = getGameCrc32();
138 char * line = (char*) malloc(kLineBufferSize + 1);
141 fgets(line, kLineBufferSize, fp);
143 char *pos = strchr(line, '|');
147 if (gameCrc == parseCrc32(line)) {
149 int res = loadHacks(pos + 1);
151 printf("Hacks: searched %s for crc32 %lx, %d hacks loaded\n",
153 } else if (res < 0) {
154 printf("Hacks: searched %s for crc32 %lx, error parsing line\n",
157 printf("Hacks: searched %s for crc32 %lx, no hacks\n",
162 } while (!feof(fp) && !ferror(fp));
165 fprintf(stderr, "Error reading hacks file: %s\n");
168 printf("Hacks: searched %s for crc %lu; nothing found\n", file, gameCrc);
176 printf("Hacks: disabled\n");