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); }