Port forced movement (turn delays, bumps, ice, currents, pits), dynamic return warps, elevators, Surf, Cut, Strength and cycling rules, working map blocks with changeblock/changemapblocks, and the remaining NPC movement types and movement commands. Add tileset animation from the ROM's command tables, grass sprite priority and special map palettes; room decorations with ownership, the bedroom PC and save migration; and Key Items access to the Bicycle. Fourteen original-engine traces compare positions, facing, actors, event flags and scripted poses. Tile animation matches original VRAM for four tilesets, and LoadMapPals matches 192 palette cases. skyfall_top now keeps the $60 sprite offset its step function leaves behind. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
9ac111f262
commit
451464f7c6
38 files changed
+5600
-490
No files matched your search
@@ -186,6 +186,8 @@ const ramNames = {
|
||||
hiddenItemID: "wHiddenItemID",
|
||||
runningTrainerBattleScript: "wRunningTrainerBattleScript",
|
||||
callerContact: "wCallerContact",
|
||||
surfingPlayerState: "wSurfingPlayerState",
|
||||
strengthSpecies: "wStrengthSpecies",
|
||||
moneyTemp: "hMoneyTemp",
|
||||
};
|
||||
const profile = readFileSync("src/game/rom/profile.ts", "utf8");
|
||||
@@ -199,14 +201,14 @@ for (const [key, symbol] of Object.entries(ramNames)) {
|
||||
if (!match || Number(match[1]) !== ram.get(symbol))
|
||||
throw new Error(`Profile RAM mismatch: ${key} / ${symbol}`);
|
||||
}
|
||||
// BATTLE entries are keyed by their PRET labels.
|
||||
{
|
||||
const block = /export const BATTLE = \{([\s\S]*?)\} as const;/.exec(profile)?.[1];
|
||||
if (!block) throw new Error("Battle symbol table is missing.");
|
||||
// BATTLE and OVERWORLD entries are keyed by their PRET labels.
|
||||
for (const table of ["BATTLE", "OVERWORLD"]) {
|
||||
const block = new RegExp(`export const ${table} = \\{([\\s\\S]*?)\\} as const;`).exec(profile)?.[1];
|
||||
if (!block) throw new Error(`${table} symbol table is missing.`);
|
||||
for (const [, quoted, bare, literal] of block.matchAll(/^\s+(?:"([^"]+)"|(\w+)):\s*(0x[0-9a-f]+),/gm)) {
|
||||
const label = quoted ?? bare;
|
||||
if (symbols.get(label) !== Number(literal))
|
||||
throw new Error(`Battle symbol mismatch: ${label}`);
|
||||
throw new Error(`${table} symbol mismatch: ${label}`);
|
||||
}
|
||||
}
|
||||
if (!profile.includes(`NUM_TRAINER_CLASSES = ${(symbols.get("Trainers") - symbols.get("TrainerGroups")) / 2};`))
|
||||
@@ -294,6 +296,9 @@ const pretConstants = new Map();
|
||||
pretConstants.set(match[2], stored);
|
||||
if (match[1] === "shift_const") pretConstants.set(`${match[2]}_F`, value);
|
||||
value += step;
|
||||
} else if ((match = /^DEF\s+(\w+)\s+EQU\s+const_value\s*-\s*(\w+)$/.exec(line))) {
|
||||
const offset = /^\d+$/.test(match[2]) ? Number(match[2]) : pretConstants.get(match[2]);
|
||||
if (offset !== undefined) pretConstants.set(match[1], value - offset);
|
||||
} else if ((match = /^DEF\s+(\w+)\s+EQU\s+([$%]?[0-9a-fA-F]+|\w+)$/.exec(line))) {
|
||||
const target = match[2];
|
||||
const resolved =
|
||||
@@ -307,7 +312,9 @@ const pretConstants = new Map();
|
||||
}
|
||||
}
|
||||
}
|
||||
const battleConstants = readFileSync("src/game/battle/constants.ts", "utf8");
|
||||
const battleConstants = ["src/game/battle/constants.ts", "src/game/world/constants.ts"]
|
||||
.map((file) => readFileSync(file, "utf8"))
|
||||
.join("\n");
|
||||
for (const [, block] of battleConstants.matchAll(/export const \w+ = \{([\s\S]*?)\} as const;/g)) {
|
||||
for (const [, name, literal] of block.matchAll(/^\s+(\w+):\s*(0x[0-9a-f]+|\d+),/gim)) {
|
||||
const expected = pretConstants.get(name);
|
||||
|
||||
Reference in new issue
Block a user