PRET's crystal and crystal_au builds reproduce both retail cartridges, and every label the profile pins keeps its address in all three; check:reference now verifies that when the rebuilds are present. The revision comes from the header. Revision 1.0's Battle Tower draws only the first 21 trainers and picks its texts' gender from the name's sixth character, checked against each cartridge. A native backup imports across the three, which share every map, event and object. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
55 lines
1.8 KiB
TypeScript
55 lines
1.8 KiB
TypeScript
import type { Page } from "@playwright/test";
|
|
import { readFileSync } from "node:fs";
|
|
import { resolve } from "node:path";
|
|
|
|
export const romPath = resolve(
|
|
process.env.CRYSTAL_ROM_PATH ??
|
|
"Pokemon - Crystal Version (UE) (V1.1) [C][!].gbc",
|
|
);
|
|
export const symbolsPath = ".reference/pokecrystal/pokecrystal11.sym";
|
|
/** PRET's rebuilds of the other English cartridges (`make crystal
|
|
* crystal_au`), which keep 1.1's addresses for every label the port reads. */
|
|
export const revisionRoms = {
|
|
"1.0": resolve(".reference/pokecrystal/pokecrystal.gbc"),
|
|
au: resolve(".reference/pokecrystal/pokecrystal_au.gbc"),
|
|
} as const;
|
|
|
|
/** Banked addresses from the private PRET rebuild's symbol file. */
|
|
export function loadSymbols() {
|
|
const symbols = new Map(
|
|
readFileSync(symbolsPath, "utf8")
|
|
.split("\n")
|
|
.flatMap((line) => {
|
|
const match = /^([0-9a-f]{2}):([0-9a-f]{4}) (\S+)$/.exec(line);
|
|
return match
|
|
? [
|
|
[
|
|
match[3],
|
|
{
|
|
bank: parseInt(match[1], 16),
|
|
address: parseInt(match[2], 16),
|
|
},
|
|
] as const,
|
|
]
|
|
: [];
|
|
}),
|
|
);
|
|
return {
|
|
at: (name: string) => symbols.get(name)!.address,
|
|
routine: (name: string) => symbols.get(name)!,
|
|
};
|
|
}
|
|
|
|
/** Open the reference page and hand it the ROM (by default the user's 1.1)
|
|
* through an isolated file input, without an HTTP ROM endpoint. */
|
|
export async function openReference(page: Page, rom = romPath) {
|
|
await page.goto("/reference.html");
|
|
await page.evaluate(() => {
|
|
const input = document.createElement("input");
|
|
input.type = "file";
|
|
input.id = "reference-fixture";
|
|
document.body.append(input);
|
|
});
|
|
await page.locator("#reference-fixture").setInputFiles(rom);
|
|
}
|