Skip to content

Commit b91ba4f

Browse files
authored
Don't hard-code the Stadium data handling in tools/make_patch.c (#1206)
Instead, have a `--ignore addr:size` option that's set in the Makefile
1 parent d138ed1 commit b91ba4f

File tree

3 files changed

+63
-19
lines changed

3 files changed

+63
-19
lines changed

Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,8 @@ $(pokecrystal11_debug_obj): RGBASMFLAGS += -D _CRYSTAL11 -D _DEBUG
118118
$(pokecrystal11_vc_obj): RGBASMFLAGS += -D _CRYSTAL11 -D _CRYSTAL11_VC
119119

120120
%.patch: %_vc.gbc %.gbc vc/%.patch.template
121-
tools/make_patch $*_vc.sym $^ $@
121+
# Ignore the checksums added by tools/stadium at the end of the ROM
122+
tools/make_patch --ignore 0x1ffde0:0x220 $*_vc.sym $^ $@
122123

123124
rgbdscheck.o: rgbdscheck.asm
124125
$(RGBASM) -o $@ $<

docs/vc_patch.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,17 @@ The program used to convert a `.patch.template` into a `.patch` file.
3838
To convert `vc.patch.template` into `vc.patch`:
3939

4040
```bash
41-
tools/make_patch values.sym patched.gbc original.gbc vc.patch.template vc.patch
41+
tools/make_patch [--ignore addr:size] values.sym patched.gbc original.gbc vc.patch.template vc.patch
4242
```
4343

4444
For example, this is what `make crystal11_vc` does:
4545

4646
```bash
47-
tools/make_patch pokecrystal11_vc.sym pokecrystal11_vc.gbc pokecrystal11.gbc vc/pokecrystal11.patch.template pokecrystal11.patch
47+
tools/make_patch --ignore 0x1ffde0:0x220 pokecrystal11_vc.sym pokecrystal11_vc.gbc pokecrystal11.gbc vc/pokecrystal11.patch.template pokecrystal11.patch
4848
```
4949

50+
The optional `--ignore` takes a colon-separated address and size of data to ignore in the ROM, so any differences between the `.gbc` and `_vc.gbc` files in that region will not be warned about. This is meant to allow ignoring the per-bank checksums generated by `tools/stadium` at the end of the ROM (data related to playing the ROM in Pokémon Stadium 2's Game Boy Tower).
51+
5052

5153
## Patch types
5254

tools/make_patch.c

Lines changed: 57 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#define PROGRAM_NAME "make_patch"
2-
#define USAGE_OPTS "values.sym patched.gbc original.gbc vc.patch.template vc.patch"
2+
#define USAGE_OPTS "[--ignore addr:size] values.sym patched.gbc original.gbc vc.patch.template vc.patch"
33

44
#include "common.h"
55

@@ -127,7 +127,7 @@ struct Symbol *parse_symbols(const char *filename) {
127127
if (c == EOF || c == '\n' || c == '\r' || c == ';' || (state == SYM_NAME && (c == ' ' || c == '\t'))) {
128128
if (state == SYM_NAME) {
129129
// The symbol name has ended; append the buffered symbol
130-
buffer_append(buffer, &(char []){'\0'});
130+
buffer_append(buffer, &(char){'\0'});
131131
symbol_append(&symbols, buffer->data, bank, address);
132132
}
133133
// Skip to the next line, ignoring anything after the symbol value and name
@@ -143,7 +143,7 @@ struct Symbol *parse_symbols(const char *filename) {
143143
// The symbol value or name has started; buffer its contents
144144
if (++state == SYM_NAME) {
145145
// The symbol name has started; parse the buffered value
146-
buffer_append(buffer, &(char []){'\0'});
146+
buffer_append(buffer, &(char){'\0'});
147147
parse_symbol_value(buffer->data, &bank, &address);
148148
}
149149
buffer->size = 0;
@@ -349,7 +349,15 @@ void skip_to_next_line(FILE *restrict input, FILE *restrict output) {
349349
}
350350
}
351351

352-
struct Buffer *process_template(const char *template_filename, const char *patch_filename, FILE *restrict new_rom, FILE *restrict orig_rom, const struct Symbol *symbols) {
352+
struct Buffer *process_template(
353+
const char *template_filename,
354+
const char *patch_filename,
355+
FILE *restrict new_rom,
356+
FILE *restrict orig_rom,
357+
const struct Symbol *symbols,
358+
unsigned int ignore_addr,
359+
unsigned int ignore_size
360+
) {
353361
FILE *input = xfopen(template_filename, 'r');
354362
FILE *output = xfopen(patch_filename, 'w');
355363

@@ -358,11 +366,10 @@ struct Buffer *process_template(const char *template_filename, const char *patch
358366

359367
// The ROM checksum will always differ
360368
buffer_append(patches, &(struct Patch){0x14e, 2});
361-
// The Stadium data (see stadium.c) will always differ
369+
// The ignored data will always differ
362370
unsigned int rom_size = (unsigned int)xfsize("", orig_rom);
363-
if (rom_size == 128 * 0x4000) {
364-
unsigned int stadium_size = 24 + 6 + 2 + 128 * 2 * 2;
365-
buffer_append(patches, &(struct Patch){rom_size - stadium_size, stadium_size});
371+
if (ignore_size > 0 && ignore_size <= rom_size && ignore_addr <= rom_size - ignore_size) {
372+
buffer_append(patches, &(struct Patch){ignore_addr, ignore_size});
366373
}
367374

368375
// Fill in the template
@@ -381,7 +388,7 @@ struct Buffer *process_template(const char *template_filename, const char *patch
381388
for (c = getc(input); c != EOF && c != '}'; c = getc(input)) {
382389
buffer_append(buffer, &c);
383390
}
384-
buffer_append(buffer, &(char []){'\0'});
391+
buffer_append(buffer, &(char){'\0'});
385392
// Interpret the command in the context of the current patch
386393
interpret_command(buffer->data, current_hook, symbols, patches, new_rom, orig_rom, output);
387394
break;
@@ -410,7 +417,7 @@ struct Buffer *process_template(const char *template_filename, const char *patch
410417
buffer_append(buffer, &c);
411418
}
412419
}
413-
buffer_append(buffer, &(char []){'\0'});
420+
buffer_append(buffer, &(char){'\0'});
414421
// The current patch should have a corresponding ".VC_" label
415422
current_hook = symbol_find_cat(symbols, ".VC_", buffer->data);
416423
skip_to_next_line(input, output);
@@ -464,19 +471,53 @@ bool verify_completeness(FILE *restrict orig_rom, FILE *restrict new_rom, struct
464471
}
465472
}
466473

474+
void parse_args(int argc, char *argv[], unsigned int *ignore_addr, unsigned int *ignore_size) {
475+
struct option long_options[] = {
476+
{"ignore", required_argument, 0, 'i'},
477+
{"help", no_argument, 0, 'h'},
478+
{0}
479+
};
480+
for (int opt; (opt = getopt_long(argc, argv, "h", long_options)) != -1;) {
481+
switch (opt) {
482+
case 'i': {
483+
char *colon = strchr(optarg, ':');
484+
if (colon) {
485+
*colon++ = '\0';
486+
*ignore_addr = strtoul(optarg, NULL, 0);
487+
*ignore_size = strtoul(colon, NULL, 0);
488+
} else {
489+
error_exit("Error: Invalid argument for '--ignore': \"%s\"\n", optarg);
490+
}
491+
break;
492+
}
493+
case 'h':
494+
usage_exit(0);
495+
break;
496+
default:
497+
usage_exit(1);
498+
}
499+
}
500+
}
501+
467502
int main(int argc, char *argv[]) {
468-
if (argc != 6) {
503+
unsigned int ignore_addr = 0, ignore_size = 0;
504+
505+
parse_args(argc, argv, &ignore_addr, &ignore_size);
506+
507+
argc -= optind;
508+
argv += optind;
509+
if (argc != 5) {
469510
usage_exit(1);
470511
}
471512

472-
struct Symbol *symbols = parse_symbols(argv[1]);
513+
struct Symbol *symbols = parse_symbols(argv[0]);
473514

474-
FILE *new_rom = xfopen(argv[2], 'r');
475-
FILE *orig_rom = xfopen(argv[3], 'r');
476-
struct Buffer *patches = process_template(argv[4], argv[5], new_rom, orig_rom, symbols);
515+
FILE *new_rom = xfopen(argv[1], 'r');
516+
FILE *orig_rom = xfopen(argv[2], 'r');
517+
struct Buffer *patches = process_template(argv[3], argv[4], new_rom, orig_rom, symbols, ignore_addr, ignore_size);
477518

478519
if (!verify_completeness(orig_rom, new_rom, patches)) {
479-
fprintf(stderr, PROGRAM_NAME ": Warning: Not all ROM differences are defined by \"%s\"\n", argv[5]);
520+
fprintf(stderr, PROGRAM_NAME ": Warning: Not all ROM differences are defined by \"%s\"\n", argv[4]);
480521
}
481522

482523
symbol_free(symbols);

0 commit comments

Comments
 (0)