Measure, weigh and name the European releases' own way (#84)
Checks / web (push) Failing after 19s
Private ROM checks / private-rom (push) Failing after 27m7s

The French, German, Italian and Spanish releases store Magikarp's
length in millimetres (and print a tenth of them), start the Magikarp
house's record at their own length and holder, keep Pokédex heights in
decimetres and weights in hectograms (printed in metres and kilograms),
read the Heavy Ball's weight byte without converting it, and place the
enemy's nickname before EnemyText (French, Italian) or the trainer's
name before the class (French, Italian, Spanish).

map-revision --symbols writes each release's symbol file, so the
reference specs run against a release; specs that pin English data skip
there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
kawaandClaude Opus 5.5 committed 2026-10-17 19:04:51 +02:00
1 parent 627f87d8b5
commit d3e3faff72
15 files changed
+246 -63

No files matched your search

+41 -10
View File
@@ -12,7 +12,10 @@
// Needs the pinned PRET checkout built for 1.1 (its .o, .map and .sym) and
// the releases' ROMs at the repository root (or CRYSTAL_<FR|DE|IT|ES>_ROM_PATH).
// MAP_REVISION_DUMP=dir also writes every 1.1 label's place in each release
// (<dir>/<language>.json), for comparing routines.
// (<dir>/<language>.json), for comparing routines. --symbols writes
// .reference/pokecrystal/pokecrystal_<language>.sym: 1.1's symbol file with
// each release's places (labels not found left out), so the reference specs
// run against a release with CRYSTAL_ROM_PATH and CRYSTAL_SYMBOLS_PATH.
import { createHash } from "node:crypto";
import { existsSync, readFileSync, writeFileSync } from "node:fs";
import { PROFILE_RAM, PROFILE_SYMBOLS } from "./profile-symbols.mjs";
@@ -393,15 +396,24 @@ function resolve(en, fr, symbols, refs) {
// near the resolved routine.
if (i >= 0 && p - starts[i] <= 64 && Math.floor(starts[i] / BANK) === Math.floor(p / BANK)) {
const from = startAt.get(starts[i]);
const pattern = [];
for (let d = -3; d <= 3; d++) pattern.push(cover.has(p + d) ? -1 : en[p + d]);
let hit;
for (let q = from; q < from + 128 && q + 3 < fr.length; q++)
if (pattern.every((b, k) => b < 0 || fr[q - 3 + k] === b)) {
if (hit !== undefined) return undefined;
hit = q;
}
return hit;
// Widest first; narrower when a changed byte sits next to it.
for (const [before, after] of [[3, 3], [1, 3]]) {
const pattern = [];
// The pointer itself is what the release changes.
for (let d = -before; d <= after; d++) pattern.push(d === 0 || d === 1 || cover.has(p + d) ? -1 : en[p + d]);
if (pattern.filter((b) => b >= 0).length < (before === 3 ? 3 : 2)) continue;
// The hit nearest where 1.1's distance from the routine puts it,
// within 16 bytes and nearer than any other.
const expected = from + (p - starts[i]);
const hits = [];
for (let q = from; q < from + 128 && q + after < fr.length; q++)
if (pattern.every((b, k) => b < 0 || fr[q - before + k] === b)) hits.push(q);
hits.sort((x, y) => Math.abs(x - expected) - Math.abs(y - expected));
if (hits.length === 1) return hits[0];
if (hits.length && Math.abs(hits[0] - expected) <= 16 && Math.abs(hits[1] - expected) > Math.abs(hits[0] - expected))
return hits[0];
}
return undefined;
}
return undefined;
};
@@ -650,6 +662,25 @@ function generate() {
const { known, how, cover } = resolve(en, fr, symbols, refs);
if (process.env.MAP_REVISION_DUMP)
writeFileSync(`${process.env.MAP_REVISION_DUMP}/${language}.json`, JSON.stringify(Object.fromEntries(known)));
if (process.argv.includes("--symbols")) {
const out = [];
for (const line of readFileSync(`${root}/pokecrystal11.sym`, "utf8").split("\n")) {
const match = /^([0-9a-f]{2}):([0-9a-f]{4}) (\S+)$/.exec(line.trim());
if (!match) {
out.push(line);
continue;
}
const name = match[3],
address = parseInt(match[2], 16);
const hex = (value, width) => value.toString(16).padStart(width, "0");
if (address >= 0x8000) out.push(`${match[1]}:${hex(known.get(name) ?? address, 4)} ${name}`);
else if (known.has(name)) {
const f = known.get(name);
out.push(`${hex(f < BANK ? 0 : Math.floor(f / BANK), 2)}:${hex(f < BANK ? f : (f % BANK) + 0x4000, 4)} ${name}`);
}
}
writeFileSync(`${root}/pokecrystal_${language}.sym`, out.join("\n"));
}
const check = checker(en, fr, symbols, refs, known, cover);
const counts = {},
unresolved = [],
+41 -23
View File
@@ -1,4 +1,5 @@
import { RomReader } from "../rom/reader";
import { european, metricMagikarp, trainerNameFirst } from "../rom/revision";
import { BATTLE, JOHTO, RAM, SYMBOLS } from "../rom/profile";
import { PokemonData } from "../rom/pokemon";
import type { Bag } from "../party/bag";
@@ -362,7 +363,7 @@ export function magikarpLength(
r: RomReader,
dvs: number,
playerId: number,
): { feet: number; inches: number } {
): { feet: number; inches: number; mm: number } {
const rrc = (value: number) => ((value >> 1) | (value << 7)) & 0xff;
const b = rrc(rrc(dvs >> 8)) ^ rrc((playerId >> 8) & 0xff),
c = rrc(rrc(dvs & 0xff)) ^ rrc(playerId & 0xff),
@@ -381,7 +382,15 @@ export function magikarpLength(
mm ??= (((bc - r.word(p - 3)) & 0xffff) + 1600) & 0xffff;
// Millimetres × 10 / 254 in a byte, then feet and inches.
const total = Math.floor(((mm * 10) & 0xffff) / 254) & 0xff;
return { feet: Math.floor(total / 12), inches: total % 12 };
return { feet: Math.floor(total / 12), inches: total % 12, mm };
}
/** wMagikarpLength's two bytes: feet and inches in English; the European
* releases' CalcMagikarpLength stores the millimetres themselves (high byte
* first) and skips the conversion. */
export function magikarpLengthBytes(r: RomReader, dvs: number, playerId: number): [number, number] {
const { feet, inches, mm } = magikarpLength(r, dvs, playerId);
return metricMagikarp() ? [mm >> 8, mm & 0xff] : [feet, inches];
}
export function calculateDamage(input: {
@@ -703,11 +712,15 @@ export class Battle {
? readString(this.reader, BATTLE["CatchTutorial.Dude"], base)
: base.player,
// PlaceEnemysName: a rival (RIVAL1, RIVAL2) is wRivalName alone,
// other trainers the class and the name.
// other trainers the class and the name (in French, Italian and
// Spanish the name, then the class).
trainer: this.options.trainer
? this.options.trainer.classId === C.RIVAL1 || this.options.trainer.classId === C.RIVAL2
? base.rival
: `${this.options.trainer.className} ${this.options.trainer.name}`.trim()
: (trainerNameFirst()
? `${this.options.trainer.name} ${this.options.trainer.className}`
: `${this.options.trainer.className} ${this.options.trainer.name}`
).trim()
: base.trainer,
strings: {
...base.strings,
@@ -949,27 +962,26 @@ export class Battle {
return moves;
}
/** LoadEnemyMon's .Magikarp filters, true when the DVs are drawn again.
* Their limits are in millimetres but CalcMagikarpLength gives feet and
* inches: the two size checks need 6 feet, which no Magikarp reaches
* (they only draw from Random), and the floor of 1024 mm compares
* feet with 4. The Lake of Rage test matches its map group or its map
* Their limits are in millimetres; English's CalcMagikarpLength gives feet
* and inches, so there the two size checks need 6 feet, which no Magikarp
* reaches (they only draw from Random), and the floor of 1024 mm compares
* feet with 4. The European releases measure in millimetres, so the
* limits work. The Lake of Rage test matches its map group or its map
* number on their own, and skips the floor there. */
private rerollMagikarp(dvs: number): boolean {
const { feet, inches } = magikarpLength(
this.reader,
dvs,
this.options.playerId,
);
if (feet === 1536 >> 8 && this.random() >= percent(5)) {
if (inches >= (1616 & 0xff)) return true;
if (this.random() >= percent(20) - 1 && inches >= (1600 & 0xff))
// wMagikarpLength's bytes: feet and inches, or the European releases'
// millimetres, for which these limits were written.
const [high, low] = magikarpLengthBytes(this.reader, dvs, this.options.playerId);
if (high === 1536 >> 8 && this.random() >= percent(5)) {
if (low >= (1616 & 0xff)) return true;
if (this.random() >= percent(20) - 1 && low >= (1600 & 0xff))
return true;
}
const [group, number] = (this.options.mapId ?? "0:0").split(":").map(Number);
if (group === LAKE_OF_RAGE.group || number === LAKE_OF_RAGE.number)
return false;
if (this.random() < percent(39) + 1) return false;
return feet < 1024 >> 8;
return high < 1024 >> 8;
}
/** CheckSleepingTreeMon: in a tree battle, the time of day's
* AsleepTreeMons list names the species that sleep. */
@@ -2004,12 +2016,18 @@ export class Battle {
return r.byte(r.address(bank, address));
};
while (at(pointer++) !== 0x50);
let hl = (at(pointer + 2) | (at(pointer + 3) << 8)) >> 1;
let bc = hl >> 4;
hl = (hl - bc) & 0xffff;
bc >>= 1;
hl = (hl - bc) & 0xffff;
const weight = hl >> 8;
let weight;
if (european()) {
// After the height byte, the weight's high byte: hectograms / 256.
weight = at(pointer + 2);
} else {
let hl = (at(pointer + 2) | (at(pointer + 3) << 8)) >> 1;
let bc = hl >> 4;
hl = (hl - bc) & 0xffff;
bc >>= 1;
hl = (hl - bc) & 0xffff;
weight = hl >> 8;
}
if (weight < 4) return rate >= 20 ? rate - 20 : 1;
let entry = BATTLE["HeavyBallMultiplier.WeightsTable"];
while (weight >= r.byte(entry)) entry += 2;
+13 -3
View File
@@ -1,4 +1,5 @@
import { RomReader } from "./reader";
import { european } from "./revision";
import { decompress } from "./lz";
import { NUM_POKEMON, POKEDEX } from "./profile";
import { defaultTextContext, readString } from "../scripts/text";
@@ -101,9 +102,12 @@ export class PokedexData {
const category = this.string(p, 16);
while (r.byte(p) !== 0x50) p++;
p++;
const height = r.word(p),
weight = r.word(p + 2);
p += 4;
// The European releases keep the height in one byte (decimetres) and
// the weight in hectograms; English a word of feet and inches.
const metric = european();
const height = metric ? r.byte(p) : r.word(p),
weight = r.word(p + (metric ? 1 : 2));
p += metric ? 3 : 4;
const page1 = p;
while (r.byte(p) !== 0x50) p++;
const page2 = p + 1;
@@ -159,6 +163,9 @@ export class PokedexData {
* point, which becomes the foot mark, written over the ".Height" string. */
export function dexHeight(template: string, height: number): string {
if (!height) return template;
// The European releases: PrintNum of the byte with two of three digits
// before the point, in metres, at hlcoord 13, 7.
if (european()) return template.slice(0, 4) + `${String(Math.floor(height / 10)).padStart(2, " ")}.${height % 10}` + template.slice(8);
const feet = String(Math.floor(height / 100)).padStart(2, " ");
const inches = String(height % 100).padStart(2, "0");
// The number starts three tiles into the string (hlcoord 12, 7 after 9, 7).
@@ -168,6 +175,9 @@ export function dexHeight(template: string, height: number): string {
* point, written over the ".Weight" string's question marks. */
export function dexWeight(template: string, weight: number): string {
if (!weight) return template;
// The European releases: three of four digits before the point, in
// kilograms, at hlcoord 12, 9.
if (european()) return template.slice(0, 3) + `${String(Math.floor(weight / 10)).padStart(3, " ")}.${weight % 10}` + template.slice(8);
const pounds = String(Math.floor(weight / 10)).padStart(4, " ");
// The number starts two tiles into the string (hlcoord 11, 9 after 9, 9).
return template.slice(0, 2) + `${pounds}.${weight % 10}` + template.slice(8);
+2
View File
@@ -1232,6 +1232,8 @@ export const EGGS = {
/** Johto's scripts, routines and tables from Route 32 on, keyed by their
* PRET labels for `npm run check:reference`. */
export const JOHTO = {
InitializeMagikarpHouse: 0x5cd3,
"InitializeMagikarpHouse.Ralph": 0x5ce3,
"_HallOfFamePC.TimeFamer": 0x8670c,
FontBattleExtra: 0xf8600,
CheckMagikarpLength: 0xfbb32,
+5 -5
View File
@@ -2,10 +2,10 @@
// each release: where it keeps each profile entry (table.key) whose label
// moved from 1.1; 0 where it did not, -1 where the label was not found
// there, which the port must not read in that release. Do not edit.
export const REVISION_KEYS = ["BATTLE.AlreadyAsleepText","BATTLE.AlreadyConfusedText","BATTLE.AlreadyParalyzedText","BATTLE.AlreadyPoisonedText","BATTLE.AskForgetMoveText","BATTLE.AskGiveNicknameText","BATTLE.AsleepTreeMonsDay","BATTLE.AsleepTreeMonsMorn","BATTLE.AsleepTreeMonsNite","BATTLE.AttackMissed2Text","BATTLE.AttackMissedText","BATTLE.BadgeTypeBoosts","BATTLE.BadlyPoisonedText","BATTLE.BallAlmostHadItText","BATTLE.BallAppearedCaughtText","BATTLE.BallBlockedText","BATTLE.BallBoxFullText","BATTLE.BallBrokeFreeText","BATTLE.BallDontBeAThiefText","BATTLE.BallSentToPCText","BATTLE.BallSoCloseText","BATTLE.BattleCommand_Charge.BattleDugText","BATTLE.BattleCommand_Charge.BattleFlewText","BATTLE.BattleCommand_Charge.BattleGlowingText","BATTLE.BattleCommand_Charge.BattleLoweredHeadText","BATTLE.BattleCommand_Charge.BattleMadeWhirlwindText","BATTLE.BattleCommand_Charge.BattleTookSunlightText","BATTLE.BattleCommand_Charge.UsedText","BATTLE.BattleMonNicknameText","BATTLE.BattleText_AnEGGCantBattle","BATTLE.BattleText_CantEscape","BATTLE.BattleText_CantEscape2","BATTLE.BattleText_EnemyIsAboutToUseWillPlayerChangeMon","BATTLE.BattleText_EnemyMonFainted","BATTLE.BattleText_EnemySentOut","BATTLE.BattleText_EnemyWasDefeated","BATTLE.BattleText_GotAwaySafely","BATTLE.BattleText_ItemHealedConfusion","BATTLE.BattleText_ItemsCantBeUsedHere","BATTLE.BattleText_MonCantBeRecalled","BATTLE.BattleText_MonFainted","BATTLE.BattleText_MonHasNoMovesLeft","BATTLE.BattleText_MonIsAlreadyOut","BATTLE.BattleText_MonsLightScreenFell","BATTLE.BattleText_MonsReflectFaded","BATTLE.BattleText_RainContinuesToFall","BATTLE.BattleText_SafeguardFaded","BATTLE.BattleText_StringBuffer1GrewToLevel","BATTLE.BattleText_TargetRecoveredWithItem","BATTLE.BattleText_TargetWasHitByFutureSight","BATTLE.BattleText_TargetsEncoreEnded","BATTLE.BattleText_TheMoveIsDisabled","BATTLE.BattleText_TheRainStopped","BATTLE.BattleText_TheSandstormRages","BATTLE.BattleText_TheSandstormSubsided","BATTLE.BattleText_TheSunlightFaded","BATTLE.BattleText_TheSunlightIsStrong","BATTLE.BattleText_TheresNoEscapeFromTrainerBattle","BATTLE.BattleText_TheresNoPPLeftForThisMove","BATTLE.BattleText_TheresNoWillToBattle","BATTLE.BattleText_UseNextMon","BATTLE.BattleText_UserFledUsingAStringBuffer1","BATTLE.BattleText_UserHurtBySpikes","BATTLE.BattleText_UserRecoveredPPUsing","BATTLE.BattleText_UserWasReleasedFromStringBuffer1","BATTLE.BattleText_UsersHurtByStringBuffer1","BATTLE.BattleText_UsersStringBuffer1Activated","BATTLE.BattleText_WildFled","BATTLE.BeatUpAttackText","BATTLE.BecameConfusedText","BATTLE.BeganToNapText","BATTLE.BellChimedText","BATTLE.BellyDrumText","BATTLE.BitterBerryEffect","BATTLE.BlewSpikesText","BATTLE.BlownAwayText","BATTLE.BoostedExpPointsText","BATTLE.BracedItselfText","BATTLE.BugContest_SetCaughtContestMon.ContestCaughtMonText","BATTLE.ButItFailedText","BATTLE.CantEscapeNowText","BATTLE.CatchTutorial.Dude","BATTLE.ChooseAMonString","BATTLE.ClampedByText","BATTLE.CoinsScatteredText","BATTLE.ComeBackText","BATTLE.ConfusedNoMoreText","BATTLE.ConsumableEffects","BATTLE.ContestAskSwitchText","BATTLE.CopiedStatsText","BATTLE.CoveredByVeilText","BATTLE.CrashedText","BATTLE.CriticalHitText","BATTLE.DefrostedOpponentText","BATTLE.DestinyBondEffectText","BATTLE.DidNotLearnMoveText","BATTLE.DidntAffect1Text","BATTLE.DidntAffect2Text","BATTLE.DireHitEffect","BATTLE.DisabledMoveText","BATTLE.DisabledNoMoreText","BATTLE.DisplayAlreadyCaughtText.ContestAlreadyCaughtText","BATTLE.DoItMonText","BATTLE.DoesntAffectText","BATTLE.DownpourText","BATTLE.DraggedOutText","BATTLE.DreamEatenText","BATTLE.EliminatedStatsText","BATTLE.EnduredText","BATTLE.EnemyHitTimesText","BATTLE.EnemyText","BATTLE.EnergyRootEffect","BATTLE.EnergypowderEffect","BATTLE.EvadedText","BATTLE.ExpPointsText","BATTLE.FastAsleepText","BATTLE.FellAsleepText","BATTLE.FellInLoveText","BATTLE.FireSpinTrapText","BATTLE.FledFromBattleText","BATTLE.FledInFearText","BATTLE.FlinchedText","BATTLE.ForesawAttackText","BATTLE.FrozenSolidText","BATTLE.FullRestoreEffect","BATTLE.FullyParalyzedText","BATTLE.GettingPumpedText","BATTLE.GoForItMonText","BATTLE.GoMonText","BATTLE.GoodComeBackText","BATTLE.GotAnEncoreText","BATTLE.GotMoneyForWinningText","BATTLE.GuardSpecEffect","BATTLE.HPIsFullText","BATTLE.HappinessChanges","BATTLE.HasANightmareText","BATTLE.HasNoPPLeftText","BATTLE.HasSubstituteText","BATTLE.HealPowderEffect","BATTLE.HealingHPAmounts","BATTLE.HeavyBallMultiplier.WeightsTable","BATTLE.HeavyBall_GetDexEntryBank.PokedexEntryBanks","BATTLE.HeldStatusHealingEffects","BATTLE.HookedPokemonAttackedText","BATTLE.HungOnText","BATTLE.HurtByBurnText","BATTLE.HurtByCurseText","BATTLE.HurtByPoisonText","BATTLE.HurtItselfText","BATTLE.IdentifiedText","BATTLE.IgnoredOrders2Text","BATTLE.IgnoredOrdersText","BATTLE.IgnoredSleepingText","BATTLE.InLoveWithText","BATTLE.InfatuationText","BATTLE.IsConfusedText","BATTLE.IsHMMove.HMMoves","BATTLE.ItFailedText","BATTLE.ItemAttributes","BATTLE.ItemCantUseOnEggText","BATTLE.IteLine truncated
export const REVISION_KEYS = ["BATTLE.AlreadyAsleepText","BATTLE.AlreadyConfusedText","BATTLE.AlreadyParalyzedText","BATTLE.AlreadyPoisonedText","BATTLE.AskForgetMoveText","BATTLE.AskGiveNicknameText","BATTLE.AsleepTreeMonsDay","BATTLE.AsleepTreeMonsMorn","BATTLE.AsleepTreeMonsNite","BATTLE.AttackMissed2Text","BATTLE.AttackMissedText","BATTLE.BadgeTypeBoosts","BATTLE.BadlyPoisonedText","BATTLE.BallAlmostHadItText","BATTLE.BallAppearedCaughtText","BATTLE.BallBlockedText","BATTLE.BallBoxFullText","BATTLE.BallBrokeFreeText","BATTLE.BallDontBeAThiefText","BATTLE.BallSentToPCText","BATTLE.BallSoCloseText","BATTLE.BattleCommand_Charge.BattleDugText","BATTLE.BattleCommand_Charge.BattleFlewText","BATTLE.BattleCommand_Charge.BattleGlowingText","BATTLE.BattleCommand_Charge.BattleLoweredHeadText","BATTLE.BattleCommand_Charge.BattleMadeWhirlwindText","BATTLE.BattleCommand_Charge.BattleTookSunlightText","BATTLE.BattleCommand_Charge.UsedText","BATTLE.BattleMonNicknameText","BATTLE.BattleText_AnEGGCantBattle","BATTLE.BattleText_CantEscape","BATTLE.BattleText_CantEscape2","BATTLE.BattleText_EnemyIsAboutToUseWillPlayerChangeMon","BATTLE.BattleText_EnemyMonFainted","BATTLE.BattleText_EnemySentOut","BATTLE.BattleText_EnemyWasDefeated","BATTLE.BattleText_GotAwaySafely","BATTLE.BattleText_ItemHealedConfusion","BATTLE.BattleText_ItemsCantBeUsedHere","BATTLE.BattleText_MonCantBeRecalled","BATTLE.BattleText_MonFainted","BATTLE.BattleText_MonHasNoMovesLeft","BATTLE.BattleText_MonIsAlreadyOut","BATTLE.BattleText_MonsLightScreenFell","BATTLE.BattleText_MonsReflectFaded","BATTLE.BattleText_RainContinuesToFall","BATTLE.BattleText_SafeguardFaded","BATTLE.BattleText_StringBuffer1GrewToLevel","BATTLE.BattleText_TargetRecoveredWithItem","BATTLE.BattleText_TargetWasHitByFutureSight","BATTLE.BattleText_TargetsEncoreEnded","BATTLE.BattleText_TheMoveIsDisabled","BATTLE.BattleText_TheRainStopped","BATTLE.BattleText_TheSandstormRages","BATTLE.BattleText_TheSandstormSubsided","BATTLE.BattleText_TheSunlightFaded","BATTLE.BattleText_TheSunlightIsStrong","BATTLE.BattleText_TheresNoEscapeFromTrainerBattle","BATTLE.BattleText_TheresNoPPLeftForThisMove","BATTLE.BattleText_TheresNoWillToBattle","BATTLE.BattleText_UseNextMon","BATTLE.BattleText_UserFledUsingAStringBuffer1","BATTLE.BattleText_UserHurtBySpikes","BATTLE.BattleText_UserRecoveredPPUsing","BATTLE.BattleText_UserWasReleasedFromStringBuffer1","BATTLE.BattleText_UsersHurtByStringBuffer1","BATTLE.BattleText_UsersStringBuffer1Activated","BATTLE.BattleText_WildFled","BATTLE.BeatUpAttackText","BATTLE.BecameConfusedText","BATTLE.BeganToNapText","BATTLE.BellChimedText","BATTLE.BellyDrumText","BATTLE.BitterBerryEffect","BATTLE.BlewSpikesText","BATTLE.BlownAwayText","BATTLE.BoostedExpPointsText","BATTLE.BracedItselfText","BATTLE.BugContest_SetCaughtContestMon.ContestCaughtMonText","BATTLE.ButItFailedText","BATTLE.CantEscapeNowText","BATTLE.CatchTutorial.Dude","BATTLE.ChooseAMonString","BATTLE.ClampedByText","BATTLE.CoinsScatteredText","BATTLE.ComeBackText","BATTLE.ConfusedNoMoreText","BATTLE.ConsumableEffects","BATTLE.ContestAskSwitchText","BATTLE.CopiedStatsText","BATTLE.CoveredByVeilText","BATTLE.CrashedText","BATTLE.CriticalHitText","BATTLE.DefrostedOpponentText","BATTLE.DestinyBondEffectText","BATTLE.DidNotLearnMoveText","BATTLE.DidntAffect1Text","BATTLE.DidntAffect2Text","BATTLE.DireHitEffect","BATTLE.DisabledMoveText","BATTLE.DisabledNoMoreText","BATTLE.DisplayAlreadyCaughtText.ContestAlreadyCaughtText","BATTLE.DoItMonText","BATTLE.DoesntAffectText","BATTLE.DownpourText","BATTLE.DraggedOutText","BATTLE.DreamEatenText","BATTLE.EliminatedStatsText","BATTLE.EnduredText","BATTLE.EnemyHitTimesText","BATTLE.EnemyText","BATTLE.EnergyRootEffect","BATTLE.EnergypowderEffect","BATTLE.EvadedText","BATTLE.ExpPointsText","BATTLE.FastAsleepText","BATTLE.FellAsleepText","BATTLE.FellInLoveText","BATTLE.FireSpinTrapText","BATTLE.FledFromBattleText","BATTLE.FledInFearText","BATTLE.FlinchedText","BATTLE.ForesawAttackText","BATTLE.FrozenSolidText","BATTLE.FullRestoreEffect","BATTLE.FullyParalyzedText","BATTLE.GettingPumpedText","BATTLE.GoForItMonText","BATTLE.GoMonText","BATTLE.GoodComeBackText","BATTLE.GotAnEncoreText","BATTLE.GotMoneyForWinningText","BATTLE.GuardSpecEffect","BATTLE.HPIsFullText","BATTLE.HappinessChanges","BATTLE.HasANightmareText","BATTLE.HasNoPPLeftText","BATTLE.HasSubstituteText","BATTLE.HealPowderEffect","BATTLE.HealingHPAmounts","BATTLE.HeavyBallMultiplier.WeightsTable","BATTLE.HeavyBall_GetDexEntryBank.PokedexEntryBanks","BATTLE.HeldStatusHealingEffects","BATTLE.HookedPokemonAttackedText","BATTLE.HungOnText","BATTLE.HurtByBurnText","BATTLE.HurtByCurseText","BATTLE.HurtByPoisonText","BATTLE.HurtItselfText","BATTLE.IdentifiedText","BATTLE.IgnoredOrders2Text","BATTLE.IgnoredOrdersText","BATTLE.IgnoredSleepingText","BATTLE.InLoveWithText","BATTLE.InfatuationText","BATTLE.IsConfusedText","BATTLE.IsHMMove.HMMoves","BATTLE.ItFailedText","BATTLE.ItemAttributes","BATTLE.ItemCantUseOnEggText","BATTLE.IteLine truncated
export const REVISION_ADDRESSES = {
fr: [528985,527975,530010,529047,26265,60826,256876,256882,256864,528585,528564,1031749,529018,60772,60767,63433,63453,60762,63438,60816,60777,224300,224295,224290,224285,224275,224280,224224,258802,527258,527410,527290,527163,526842,527214,526889,527359,527947,527492,527546,527068,527633,527521,526595,526633,526670,526565,527681,526477,526532,527660,527606,526760,526728,526811,526784,526700,527309,527573,527231,527082,527382,527429,526501,528020,527995,527473,526265,530720,527928,528323,528953,530605,61711,530538,529248,258351,530380,59122,529804,530108,321009,0,528119,529612,258910,527907,160233,835777,530653,530422,528606,528666,529136,528888,26260,529842,529862,62557,528278,527834,835791,258779,528646,530559,529910,529100,529662,528201,529285,4711,61749,61745,529565,258356,527763,528973,530405,528084,529217,529229,527801,530696,527788,61645,529982,529359,258786,258772,258901,528803,526868,62544,529882,29243,526373,528460,529421,61266,62292,60521,60449,253510,526176,528179,526340,526395,526318,527871,530286,530765,528381,528399,528229,528251,527856,13533,529823,26587,63413,59153,63408,63458,63428,26245,0,529725,528306,529403,1031277,227769,530477,226393,529531,530058,529306,26250,26292,160255,1072770,1072683,1072705,527819,60821,528427,528723,529780,258896,68338,528682,63198,529944,526441,529264,62516,279404,526201,530739,227596,329073,330662,529330,530032,530215,530234,530177,528775,529377,527449,529753,528539,530494,528501,61739,62820,63183,61518,61549,530444,530346,526410,527003,526971,526918,528819,530516,528867,530246,528925,530302,530134,222443,61462,61297,530080,26255,528142,529505,529470,529071,530586,528700,26270,26287,60782,258334,258891,529436,528858,528753,529698,529634,528361,528625,528159,328948,528045,1072652,1072659,1072577,1072674,60811,526246,529126,530162,529584,529151,528999,529549,1031653,1031640,528489,328961,528070,526223,526148,258813,63839,527772,529190,528344,529164,528098,62503,62570,62633,258793,95168,95260,1838551,1838589,1838560,1838562,75027,559274,592741,592735,592730,298334,0,560058,24813,24824,71596,592022,591995,1838283,1842383,1842495,1842550,1842664,1851420,1819420,1819423,1819452,1819455,1819500,1819412,1819390,1819444,1819313,1819475,924544,0,0,89755,89185,89730,89725,89750,89740,89745,89735,0,1942651,0,304732,29711,79408,79427,0,79803,0,920855,921647,920796,920823,920839,922259,920724,919938,29126,0,317577,317917,317912,0,1073943,317940,923196,12768,150408,80458,79669,79651,79692,79674,79715,79697,80489,29749,91984,91900,92508,92601,92616,92621,92522,92606,92611,95310,95341,95443,95433,95448,95438,95453,90668,0,0,568937,0,1950436,0,324090,923158,29095,1383442,0,79379,29471,29827,29809,29818,89690,89720,89700,89695,89715,89710,89705,568796,924208,922612,924976,95375,95380,0,1031319,1031341,569048,304773,0,181589,181732,181762,181752,181737,181757,181747,181742,181727,0,0,0,29739,568816,925216,0,89790,89770,89765,89760,89785,89780,89775,93684,93765,93750,93760,93745,0,919636,0,323792,92368,317922,923818,923286,923323,602939,602957,602975,0,29590,88830,88847,324325,324256,324286,324281,324261,324276,324251,324266,324271,80352,0,603233,603829,604437,602993,602457,602184,602170,29584,29578,150608,0,150621,150615,76035,1157816,1157710,1157748,1157854,0,0,171631,324116,1069249,256932,0,923360,923980,924044,569021,6834,58284,0,29744,1855399,1855487,1855377,1855419,1855430,1855355,1855448,1855479,550666,1823134,1823107,1854563,1854676,1854651,1854588,1854636,1854610,1854583,550187,29711,178723,1093143,0,1955881,1957679,551146,321750,560855,299449,-1,1955718,0,157167,0,0,0,760125,760205,760221,761237,761037,761301,761397,760941,760189,760181,761125,760469,760661,760277,760421,758535,760373,761005,760517,760229,760877,760325,760973,760141,760117,761365,761101,760149,761437,760845,760133,760173,1959834,760909,760197,761173,760157,68358,68328,68323,63217,60845,62772,62778,182482,182477,68353,63210,62783,62789,271486,182487,62452,60852,271491,271501,271804,0,76960,62798,63244,77012,61003,76997,62813,76388,63915,761487,62475,78690,66299,66262,0,0,0,66128,77334,77324,77319,77329,77344,77339,77297,0,150752,77605,63240,62794,63261,63188,63193,0,0,0,0,0,0,77007,76982,76992,76987,76977,77002,63178,61113,68348,62479,62498,63224,329751,63203,75508,61072,61008,271496,78224,62471,62802,182492,68333,60898,68343,90672,91868,91409,91404,91414,91424,91419,91429,91765,91785,91795,91760,91820,91745,91750,91755,91800,91790,91780,91805,91770,91810,91775,91815,91843,91851,91825,91691,91835,75056,75036,70628,79495,74497,934815,934811,934875,934868,0,0,935041,935049,935025,935017,935033,934939,934946,934723,934725,934727,159472,51586,53624,53641,79151,52907,51707,300206,79395,53660,51581,50956,621960,51167,51096,51249,158293,159726,159712,159631,159542,158611,52716,79268,79193,52213,52228,52218,51023,599199,754948,53307,51826,51866,597109,50901,53067,52854,12291,300285,172713,75170,75203,75190,598038,176422,176765,598399,178176,755092,754885,300507,300636,159457,9936,0,15536,0,300127,159467,15945Line truncated
de: [529315,528124,530410,529380,26272,60873,256874,256880,256862,528854,528828,1031749,529355,60819,60814,63475,63495,60809,63480,60863,60824,224296,224291,224286,224281,224271,224276,224220,258800,527293,527442,527321,527187,526817,527238,526864,527385,528085,527528,527593,527080,527708,527572,526610,526638,526664,526578,527765,526493,526550,527744,527680,526733,526715,526790,526762,526687,527340,527632,527269,527100,527405,527461,526519,528162,528146,527507,526259,531166,528068,528552,529280,531046,61753,530972,529589,258349,530813,59169,530224,530516,321001,328922,528313,530002,258908,528040,160233,835780,531101,530853,528880,528953,529458,529218,26267,530251,530282,62599,528511,527948,835794,258777,528930,530994,530349,529426,530077,528418,529635,4713,61791,61787,529956,258354,527841,529303,530835,528254,529557,529568,527898,531147,527877,61687,530390,529716,258784,258770,258899,529107,526845,62586,530311,29250,526401,528741,529784,61308,62334,60568,60496,253509,526168,528391,526338,526423,526317,527995,530725,531218,528621,528644,528452,528475,527978,13530,530241,26594,63455,59200,63450,63500,63470,26252,526366,530159,528537,529754,1031277,227765,530908,226389,529917,530457,529661,26257,26299,160255,1072761,1072674,1072696,527918,60868,528685,529023,530205,258894,68330,528967,63240,530370,526462,529609,62558,279404,0,531181,227592,329070,330663,529693,530431,530644,530668,530594,529083,529736,527482,530181,528812,530928,528784,61781,62862,63225,61560,61591,530875,530788,526441,526998,526958,526905,529128,530941,529176,530705,529253,530745,530539,222439,61504,61339,530489,26262,528353,529884,529848,529406,531021,528991,26277,26294,60829,258332,258889,529814,529161,529061,530121,530039,528600,528911,528371,328935,528189,1072643,1072650,1072568,1072665,60858,526240,529447,530574,529976,529476,529335,529936,1031653,1031640,528768,328946,528232,526221,526149,258811,63881,527858,529528,528579,529498,528276,62545,62612,62675,258791,95161,95253,1839014,1839055,1839023,1839025,75000,559270,592770,592760,592754,298334,557804,560054,24820,24831,71573,592033,592004,1838737,1843476,1843599,1843659,1843788,1851415,1819501,1819504,1819531,1819534,1819589,1819494,1819476,1819524,1819381,1819559,924163,150691,0,89750,89180,89725,89720,89745,89735,89740,89730,0,1943064,569910,304739,29721,79351,79370,0,79746,0,920856,921258,920797,920824,920840,921870,920725,919939,29133,0,317577,317917,317912,0,1073934,317940,922807,12765,150408,80401,79612,79594,79635,79617,79658,79640,80432,29759,91980,91896,92504,92597,92612,92617,92518,92602,92607,95303,95334,95436,95426,95441,95431,95446,90663,0,0,568933,569898,1950431,0,324092,922769,29102,569710,569794,79322,29478,29837,29819,29828,89685,89715,89695,89690,89710,89705,89700,568792,923827,922223,924595,95368,95373,0,1031319,1031341,569043,304780,0,181578,181721,181751,181741,181726,181746,181736,181731,181716,0,0,0,29749,568812,924835,569925,89785,89765,89760,89755,89780,89775,89770,93677,93758,93743,93753,93738,0,919637,0,323794,92364,317922,923429,922897,922934,602947,602965,602983,0,29600,88825,88842,324334,324265,324295,324290,324270,324285,324260,324275,324280,80295,0,603241,603837,604445,603001,602465,602192,602178,29594,29585,150612,150604,150625,150619,76014,1158014,1157891,1157954,1158128,569930,569935,171643,324122,1069240,256930,0,922971,923591,923655,569017,6843,58328,569940,29754,1857983,1858066,1857959,1858001,1858017,1857936,1858031,1858060,550657,1824151,1824128,1855878,1856008,1855977,1855904,1855963,1855928,1855896,550187,29721,178735,1093149,0,1955832,1957630,551137,321742,560851,299450,-1,1955677,0,157172,0,0,0,760137,760217,760233,761249,761049,761313,761409,760953,760201,760193,761137,760481,760673,760289,760433,758547,760385,761017,760529,760241,760889,760337,760985,760153,760129,761377,761113,760161,761449,760857,760145,760185,1959803,760921,760209,761185,760169,68350,68320,68315,63259,60892,62814,62820,182471,182466,68345,63252,62825,62831,271459,182476,62494,60899,271464,271474,271777,66693,76939,62840,63286,76985,61050,76970,62855,76367,63957,761499,62517,78661,66291,66254,66203,66225,66168,66126,77304,77294,77289,77299,77314,77309,77270,150706,150754,77575,63282,62836,63303,63230,63235,65858,328904,328349,328352,0,328228,76980,76955,76965,76960,76950,76975,63220,61155,68340,62521,62540,63266,329748,63245,75481,61114,61055,271469,78194,62513,62844,182481,68325,60945,68335,90667,91865,91404,91399,91409,91419,91414,91424,91760,91780,91790,91755,91815,91740,91745,91750,91795,91785,91775,91800,91765,91805,91770,91810,91840,91850,91820,91686,91832,75029,75009,70620,79438,74470,934786,934782,934847,934839,935147,935151,935026,935038,935002,934990,935014,934912,934919,934694,934696,934698,159472,0,0,0,79122,0,0,300207,79338,0,0,0,621960,0,0,0,158298,159726,159712,159631,159542,158616,0,0,79164,0,0,0,0,599207,754948,0,0,0,597116,0,0,0,12288,300286,172725,75143,75176,75163,598046,176434,176777,598407,178188,755092,754885,300508,300637,159457,9945,0,15561,0,30Line truncated
it: [529031,528005,530046,529086,26264,60871,256874,256880,256862,528623,528610,1031749,529065,60817,60812,63482,63502,60807,63487,60861,60822,224301,224296,224291,224286,224276,224281,224225,258800,527250,527386,527276,527149,526841,527196,526882,527342,527972,527475,527533,527053,527625,527512,526601,526640,526676,526576,527686,526494,526546,527654,527598,526758,526729,526811,526774,526697,527292,527565,527221,527069,527362,527402,526520,528045,528023,527452,526263,530732,527952,528369,528995,530629,61760,530548,529304,258349,530399,59167,529874,530145,320987,328935,528165,529672,258908,527930,160214,835781,530675,530436,528636,528704,529167,528930,26259,529899,529927,62606,528324,527843,835795,258777,528682,530569,529973,529129,529730,528254,529346,4709,61798,61794,529628,258354,527764,529010,530419,528115,529262,529283,527809,530712,527793,61694,530028,529414,258784,258770,258899,528821,526864,62593,529955,29242,526394,528514,529471,61315,62341,60566,60494,0,526175,528232,526332,526411,526304,527895,530314,530780,528429,528451,528266,528288,527881,13534,529888,26586,63462,59198,63457,63507,63477,26244,526361,529798,528347,529449,1031277,227770,530487,226394,529586,530092,529369,26249,26291,160236,1072764,1072677,1072699,527822,60866,528482,528756,529851,258894,68338,528719,63247,529993,526462,529323,62565,279404,526197,530751,227597,329090,330690,529391,530068,530252,530268,530213,528801,529429,527426,529829,528594,530506,528559,61788,62869,63232,61567,61598,530456,530369,526437,526994,526976,526930,528843,530525,528897,530293,528969,530331,530166,222444,61511,61346,530120,26254,528192,529563,529526,529107,530596,528738,26269,26286,60827,258332,258889,529491,528878,528779,529772,529698,528410,528667,528213,328951,528068,1072646,1072653,1072571,1072668,60856,526245,529152,530196,529649,529184,529048,529608,1031653,1031640,528542,328970,528096,526220,0,258811,63888,527774,529232,528390,529200,528134,62552,62619,62682,258791,95173,95265,1838500,1838534,1838507,1838509,75102,559278,592757,592752,592747,298334,557812,560062,24812,24823,71594,592034,592003,1838224,1842422,1842533,1842593,1842696,1851423,1819225,1819228,1819252,1819255,1819310,1819217,1819205,1819244,1819128,1819278,924146,0,0,89760,89190,89735,89730,89755,89745,89750,89740,0,1941607,569911,304739,29712,79478,79497,49995,79873,50049,920855,921257,920796,920823,920839,921869,920724,919938,29125,0,317573,317913,317908,50229,1073937,317936,922806,12769,150407,80528,79739,79721,79762,79744,79785,79767,80559,29750,91983,91899,92507,92600,92615,92620,92521,92605,92610,95315,95346,95448,95438,95453,95443,95458,90670,150307,150348,568941,569899,1950432,50297,323898,922768,29094,569711,569795,79449,29470,29828,29810,29819,89695,89725,89705,89700,89720,89715,89710,568800,923810,922222,924578,95380,95385,0,1031319,1031341,569048,304780,150401,181597,181740,181770,181760,181745,181765,181755,181750,181735,49850,0,0,29740,568820,924818,569926,89795,89775,89770,89765,89790,89785,89780,93689,93770,93755,93765,93750,150246,919636,50291,323600,92367,317918,923428,922896,922933,602935,602953,602971,50211,29591,88835,88852,324130,324061,324091,324086,324066,324081,324056,324071,324076,80422,50036,603229,603825,604433,602989,602453,602180,602166,29584,29577,150609,150602,150623,150615,76121,1157844,1157730,1157786,1157949,569931,569936,171613,323923,1069243,256930,50017,922970,923590,923654,569025,6837,58334,569941,29745,1855673,1855769,1855657,1855692,1855710,1855637,1855732,1855764,550666,1823011,1822993,1854702,1854824,1854797,1854730,1854786,1854759,1854724,550187,29712,178705,1093151,50336,1955866,1957664,551144,321727,560859,299452,-1,1955701,50349,157157,50238,50280,50362,760128,760208,760224,761240,761040,761304,761400,760944,760192,760184,761128,760472,760664,760280,760424,758538,760376,761008,760520,760232,760880,760328,760976,760144,760120,761368,761104,760152,761440,760848,760136,760176,1959808,760912,760200,761176,760160,68358,68328,68323,63266,60890,62821,62827,182490,182485,68353,63259,62832,62838,271474,182495,62501,60897,271479,271489,271792,66700,77046,62847,63293,77094,61048,77079,62862,76474,63964,761490,62524,78773,66297,66260,66208,66231,66171,66128,77414,77404,77399,77409,77424,77419,77379,0,150747,77685,63289,62843,63310,63237,63242,0,328917,0,328362,328223,0,77089,77064,77074,77069,77059,77084,63227,61162,68348,62528,62547,63273,329768,63252,75583,61121,61053,271484,78304,62520,62851,182500,68333,60943,68343,90674,91869,91411,91406,91416,91426,91421,91431,91767,91787,91797,91762,91822,91747,91752,91757,91802,91792,91782,91807,91772,91812,91777,91817,91843,91852,91827,91693,91836,75131,75111,70628,79565,74572,934806,934803,934865,934858,935149,935152,935034,935043,935016,935007,935025,934929,934936,934715,934717,934719,159453,51636,53674,53691,79234,52957,51757,300209,79465,53710,51631,51006,621958,51217,51146,51299,158281,159707,159693,159612,159523,158599,52766,79351,79276,52263,52278,52268,51073,599195,754948,53357,51876,51916,597104Line truncated
es: [529173,528047,530289,529245,26270,60823,256874,256880,256862,528742,528721,1031749,529214,60769,60764,63433,63453,60759,63438,60813,60774,224300,224295,224290,224285,224275,224280,224224,258800,527227,527378,527258,527134,526820,527189,526866,527326,528016,527470,527526,527022,527628,527503,526611,526650,526688,526576,527694,526493,526548,527668,527594,526754,526723,526790,526771,526706,527276,527557,527207,527043,527353,527396,526519,528090,528068,527447,526260,531030,527998,528434,529131,530932,61711,530855,529471,258349,530678,59119,530110,530399,320992,328934,528200,529901,258908,527977,160236,0,530970,530722,528763,528825,529329,529065,26265,530133,530150,62557,528385,527882,0,258777,528808,530872,530198,529289,529968,528298,529513,4710,61749,61745,529848,258354,527790,529158,530701,528158,529426,529448,527845,531008,527825,61645,530257,529604,258784,258770,258899,528953,526848,62544,530167,29248,0,528606,529670,61266,62292,60518,60446,0,526169,528274,0,526395,526312,527933,530582,531081,528510,528531,528320,528345,527915,13530,530124,26592,63413,59150,63408,63458,63428,26250,526341,530032,528416,529647,1031277,227769,530789,226393,529805,530343,529535,26255,26297,160258,1072761,1072674,1072696,527861,60818,528570,528883,530085,258894,68358,528845,63198,530218,526449,529491,62516,279404,526198,531049,227596,0,330685,529570,530313,530510,530531,530477,528921,529627,527417,530063,528698,530808,528656,61739,62820,63183,61518,61549,530749,530643,526421,526964,526940,526903,528989,530832,529039,530556,529098,530602,530421,222443,61462,61297,530372,26260,528225,529779,529734,529266,530907,528864,26275,26292,60779,258332,258889,529691,529027,528904,530004,529933,528484,528791,528254,328949,528117,1072643,1072650,1072568,1072665,60808,526242,529315,530455,529871,529351,529194,529829,1031653,1031640,528635,328966,528140,526222,526149,258811,63839,527808,529398,528460,529370,528176,62503,62570,62633,258791,95154,95246,1838736,1838776,1838745,1838747,75137,559287,592778,592774,592769,298334,557813,560071,24818,24829,71616,592043,592006,1838451,1842873,1842981,1843045,1843153,1851424,1819501,1819443,1819501,1819474,1819536,1819432,1819417,1819462,1819339,1819501,924543,150689,1510290,89752,89182,89727,89722,89747,89737,89742,89732,1509001,1942287,569921,304728,29717,79504,79523,49993,79899,50047,920856,921648,920797,920824,920840,922260,920725,919939,29131,1510357,317573,317913,317908,50227,1073934,317936,923197,12765,150407,80554,79765,79747,79788,79770,79811,79793,80585,29755,91975,91891,92499,92592,92607,92612,92513,92597,92602,95296,95327,95429,95419,95434,95424,95439,90670,150308,150349,568950,569909,1950435,50295,324089,923159,29100,569721,569805,79475,29476,29833,29815,29824,89687,89717,89697,89692,89712,89707,89702,568809,924207,922613,924975,95361,95366,1510214,1031319,1031341,569057,304769,150402,181585,181728,181758,181748,181733,181753,181743,181738,181723,49848,2078033,2078061,29745,568829,925215,569936,89787,89767,89762,89757,89782,89777,89772,93670,93751,93736,93746,93731,150247,919637,50289,323790,92359,317918,923819,923287,923324,602957,602975,602993,50209,29596,88827,88844,324321,324252,324282,324277,324257,324272,324247,324262,324267,80448,50034,603251,603823,604431,603011,602475,602202,602188,29589,29583,150609,0,150623,150615,76150,1158057,1157941,1157989,1158177,569941,569946,171629,324112,1069240,256930,50015,923361,923981,924045,569034,6833,58284,569951,29750,1857778,1857861,1857762,1857796,1857813,1857738,1857832,1857855,550664,1823861,1823842,1855709,1855852,1855817,1855739,1855798,1855768,1855727,550187,29717,178721,1093151,50334,1955868,1957666,551147,321732,560868,299448,-1,1955709,50347,0,50236,50278,50360,760135,760215,760231,761247,761047,761311,761407,760951,760199,760191,761135,760479,760671,760287,760431,758545,760383,761015,760527,760239,760887,760335,760983,760151,760127,761375,761111,760159,761447,760855,760143,760183,1959824,760919,760207,761183,760167,68378,68348,68343,63217,60842,62772,62778,182478,182473,68373,63210,62783,62789,271494,182483,62452,60849,271499,271509,271812,66717,77075,62798,63244,77123,61000,77108,62813,76503,63915,761497,62475,78811,66313,66274,66217,66242,66178,66132,77443,77433,77428,77438,77453,77448,77408,150704,150752,77714,63240,62794,63261,63188,63193,65861,328916,0,328361,328224,0,77118,77093,77103,77098,77088,77113,63178,61113,68368,62479,62498,63224,0,63203,75618,61072,61005,271504,78333,62471,62802,182488,68353,60895,68363,90674,91863,91411,91406,91416,91426,91421,91431,91767,91787,91797,91762,91822,91747,91752,91757,91802,91792,91782,91807,91772,91812,91777,91817,91842,91848,91827,91693,91836,75166,75146,70648,79591,74607,934808,934805,934869,934860,935167,935170,935048,935059,935026,935015,935037,934935,934943,934717,934719,0,159475,51585,53623,53640,79272,52906,51706,300205,79491,53659,51580,50955,621952,51166,51095,51248,158293,159729,159715,159634,159545,158611,52715,79391,79314,52212,52227,52217,51022,599217,754948,53306,51825,51Line truncated
fr: [528985,527975,530010,529047,26265,60826,256876,256882,256864,528585,528564,1031749,529018,60772,60767,63433,63453,60762,63438,60816,60777,224300,224295,224290,224285,224275,224280,224224,258802,527258,527410,527290,527163,526842,527214,526889,527359,527947,527492,527546,527068,527633,527521,526595,526633,526670,526565,527681,526477,526532,527660,527606,526760,526728,526811,526784,526700,527309,527573,527231,527082,527382,527429,526501,528020,527995,527473,526265,530720,527928,528323,528953,530605,61711,530538,529248,258351,530380,59122,529804,530108,321009,0,528119,529612,258910,527907,160233,835777,530653,530422,528606,528666,529136,528888,26260,529842,529862,62557,528278,527834,835791,258779,528646,530559,529910,529100,529662,528201,529285,4711,61749,61745,529565,258356,527763,528973,530405,528084,529217,529229,527801,530696,527788,61645,529982,529359,258786,258772,258901,528803,526868,62544,529882,29243,526373,528460,529421,61266,62292,60521,60449,253510,526176,528179,526340,526395,526318,527871,530286,530765,528381,528399,528229,528251,527856,13533,529823,26587,63413,59153,63408,63458,63428,26245,0,529725,528306,529403,1031277,227769,530477,226393,529531,530058,529306,26250,26292,160255,1072770,1072683,1072705,527819,60821,528427,528723,529780,258896,68338,528682,63198,529944,526441,529264,62516,279404,526201,530739,227596,329073,330662,529330,530032,530215,530234,530177,528775,529377,527449,529753,528539,530494,528501,61739,62820,63183,61518,61549,530444,530346,526410,527003,526971,526918,528819,530516,528867,530246,528925,530302,530134,222443,61462,61297,530080,26255,528142,529505,529470,529071,530586,528700,26270,26287,60782,258334,258891,529436,528858,528753,529698,529634,528361,528625,528159,328948,528045,1072652,1072659,1072577,1072674,60811,526246,529126,530162,529584,529151,528999,529549,1031653,1031640,528489,328961,528070,526223,526148,258813,63839,527772,529190,528344,529164,528098,62503,62570,62633,258793,95168,95260,1838551,1838589,1838560,1838562,75027,559274,592741,592735,592730,298334,0,560058,24813,24824,71596,592022,591995,1838283,1842383,1842495,1842550,1842664,1851420,1819420,1819423,1819452,1819455,1819500,1819412,1819390,1819444,1819313,1819475,924544,0,0,89755,89185,89730,89725,89750,89740,89745,89735,0,1942651,0,304732,29711,79408,79427,0,79803,0,920855,921647,920796,920823,920839,922259,920724,919938,29126,0,317577,317917,317912,0,1073943,317940,923196,12768,150408,80458,79669,79651,79692,79674,79715,79697,80489,29749,91984,91900,92508,92601,92616,92621,92522,92606,92611,95310,95341,95443,95433,95448,95438,95453,90668,0,0,568937,0,1950436,0,324090,923158,29095,1383442,0,79379,29471,29827,29809,29818,89690,89720,89700,89695,89715,89710,89705,568796,924208,922612,23778,23794,924976,95375,95380,0,1031319,1031341,569048,304773,0,181589,181732,181762,181752,181737,181757,181747,181742,181727,0,0,0,29739,568816,925216,0,89790,89770,89765,89760,89785,89780,89775,93684,93765,93750,93760,93745,0,919636,0,323792,92368,317922,923818,923286,923323,602939,602957,602975,0,29590,88830,88847,324325,324256,324286,324281,324261,324276,324251,324266,324271,80352,0,603233,603829,604437,602993,602457,602184,602170,29584,29578,150608,0,150621,150615,76035,1157816,1157710,1157748,1157854,0,0,171631,324116,1069249,256932,0,923360,923980,924044,569021,6834,58284,0,29744,1855399,1855487,1855377,1855419,1855430,1855355,1855448,1855479,550666,1823134,1823107,1854563,1854676,1854651,1854588,1854636,1854610,1854583,550187,29711,178723,1093143,0,1955881,1957679,551146,321750,560855,299449,1955726,1955718,0,157167,0,0,0,760125,760205,760221,761237,761037,761301,761397,760941,760189,760181,761125,760469,760661,760277,760421,758535,760373,761005,760517,760229,760877,760325,760973,760141,760117,761365,761101,760149,761437,760845,760133,760173,1959834,760909,760197,761173,760157,68358,68328,68323,63217,60845,62772,62778,182482,182477,68353,63210,62783,62789,271486,182487,62452,60852,271491,271501,271804,0,76960,62798,63244,77012,61003,76997,62813,76388,63915,761487,62475,78690,66299,66262,0,0,0,66128,77334,77324,77319,77329,77344,77339,77297,0,150752,77605,63240,62794,63261,63188,63193,0,0,0,0,0,0,77007,76982,76992,76987,76977,77002,63178,61113,68348,62479,62498,63224,329751,63203,75508,61072,61008,271496,78224,62471,62802,182492,68333,60898,68343,90672,91868,91409,91404,91414,91424,91419,91429,91765,91785,91795,91760,91820,91745,91750,91755,91800,91790,91780,91805,91770,91810,91775,91815,91843,91851,91825,91691,91835,75056,75036,70628,79495,74497,934815,934811,934875,934868,0,0,935041,935049,935025,935017,935033,934939,934946,934723,934725,934727,159472,51586,53624,53641,79151,52907,51707,300206,79395,53660,51581,50956,621960,51167,51096,51249,158293,159726,159712,159631,159542,158611,52716,79268,79193,52213,52228,52218,51023,599199,754948,53307,51826,51866,597109,50901,53067,52854,12291,300285,172713,75170,75203,75190,598038,176422,176765,598399,178176,755092,754885,300507,300636,159457,9936,0,15536,0,30Line truncated
de: [529315,528124,530410,529380,26272,60873,256874,256880,256862,528854,528828,1031749,529355,60819,60814,63475,63495,60809,63480,60863,60824,224296,224291,224286,224281,224271,224276,224220,258800,527293,527442,527321,527187,526817,527238,526864,527385,528085,527528,527593,527080,527708,527572,526610,526638,526664,526578,527765,526493,526550,527744,527680,526733,526715,526790,526762,526687,527340,527632,527269,527100,527405,527461,526519,528162,528146,527507,526259,531166,528068,528552,529280,531046,61753,530972,529589,258349,530813,59169,530224,530516,321001,328922,528313,530002,258908,528040,160233,835780,531101,530853,528880,528953,529458,529218,26267,530251,530282,62599,528511,527948,835794,258777,528930,530994,530349,529426,530077,528418,529635,4713,61791,61787,529956,258354,527841,529303,530835,528254,529557,529568,527898,531147,527877,61687,530390,529716,258784,258770,258899,529107,526845,62586,530311,29250,526401,528741,529784,61308,62334,60568,60496,253509,526168,528391,526338,526423,526317,527995,530725,531218,528621,528644,528452,528475,527978,13530,530241,26594,63455,59200,63450,63500,63470,26252,526366,530159,528537,529754,1031277,227765,530908,226389,529917,530457,529661,26257,26299,160255,1072761,1072674,1072696,527918,60868,528685,529023,530205,258894,68330,528967,63240,530370,526462,529609,62558,279404,0,531181,227592,329070,330663,529693,530431,530644,530668,530594,529083,529736,527482,530181,528812,530928,528784,61781,62862,63225,61560,61591,530875,530788,526441,526998,526958,526905,529128,530941,529176,530705,529253,530745,530539,222439,61504,61339,530489,26262,528353,529884,529848,529406,531021,528991,26277,26294,60829,258332,258889,529814,529161,529061,530121,530039,528600,528911,528371,328935,528189,1072643,1072650,1072568,1072665,60858,526240,529447,530574,529976,529476,529335,529936,1031653,1031640,528768,328946,528232,526221,526149,258811,63881,527858,529528,528579,529498,528276,62545,62612,62675,258791,95161,95253,1839014,1839055,1839023,1839025,75000,559270,592770,592760,592754,298334,557804,560054,24820,24831,71573,592033,592004,1838737,1843476,1843599,1843659,1843788,1851415,1819501,1819504,1819531,1819534,1819589,1819494,1819476,1819524,1819381,1819559,924163,150691,0,89750,89180,89725,89720,89745,89735,89740,89730,0,1943064,569910,304739,29721,79351,79370,0,79746,0,920856,921258,920797,920824,920840,921870,920725,919939,29133,0,317577,317917,317912,0,1073934,317940,922807,12765,150408,80401,79612,79594,79635,79617,79658,79640,80432,29759,91980,91896,92504,92597,92612,92617,92518,92602,92607,95303,95334,95436,95426,95441,95431,95446,90663,0,0,568933,569898,1950431,0,324092,922769,29102,569710,569794,79322,29478,29837,29819,29828,89685,89715,89695,89690,89710,89705,89700,568792,923827,922223,23787,23803,924595,95368,95373,0,1031319,1031341,569043,304780,0,181578,181721,181751,181741,181726,181746,181736,181731,181716,0,0,0,29749,568812,924835,569925,89785,89765,89760,89755,89780,89775,89770,93677,93758,93743,93753,93738,0,919637,0,323794,92364,317922,923429,922897,922934,602947,602965,602983,0,29600,88825,88842,324334,324265,324295,324290,324270,324285,324260,324275,324280,80295,0,603241,603837,604445,603001,602465,602192,602178,29594,29585,150612,150604,150625,150619,76014,1158014,1157891,1157954,1158128,569930,569935,171643,324122,1069240,256930,0,922971,923591,923655,569017,6843,58328,569940,29754,1857983,1858066,1857959,1858001,1858017,1857936,1858031,1858060,550657,1824151,1824128,1855878,1856008,1855977,1855904,1855963,1855928,1855896,550187,29721,178735,1093149,0,1955832,1957630,551137,321742,560851,299450,1955686,1955677,0,157172,0,0,0,760137,760217,760233,761249,761049,761313,761409,760953,760201,760193,761137,760481,760673,760289,760433,758547,760385,761017,760529,760241,760889,760337,760985,760153,760129,761377,761113,760161,761449,760857,760145,760185,1959803,760921,760209,761185,760169,68350,68320,68315,63259,60892,62814,62820,182471,182466,68345,63252,62825,62831,271459,182476,62494,60899,271464,271474,271777,66693,76939,62840,63286,76985,61050,76970,62855,76367,63957,761499,62517,78661,66291,66254,66203,66225,66168,66126,77304,77294,77289,77299,77314,77309,77270,150706,150754,77575,63282,62836,63303,63230,63235,65858,328904,328349,328352,0,328228,76980,76955,76965,76960,76950,76975,63220,61155,68340,62521,62540,63266,329748,63245,75481,61114,61055,271469,78194,62513,62844,182481,68325,60945,68335,90667,91865,91404,91399,91409,91419,91414,91424,91760,91780,91790,91755,91815,91740,91745,91750,91795,91785,91775,91800,91765,91805,91770,91810,91840,91850,91820,91686,91832,75029,75009,70620,79438,74470,934786,934782,934847,934839,935147,935151,935026,935038,935002,934990,935014,934912,934919,934694,934696,934698,159472,0,0,0,79122,0,0,300207,79338,0,0,0,621960,0,0,0,158298,159726,159712,159631,159542,158616,0,0,79164,0,0,0,0,599207,754948,0,0,0,597116,0,0,0,12288,300286,172725,75143,75176,75163,598046,176434,176777,598407,178188,755092,754885,300508,300637,159457,Line truncated
it: [529031,528005,530046,529086,26264,60871,256874,256880,256862,528623,528610,1031749,529065,60817,60812,63482,63502,60807,63487,60861,60822,224301,224296,224291,224286,224276,224281,224225,258800,527250,527386,527276,527149,526841,527196,526882,527342,527972,527475,527533,527053,527625,527512,526601,526640,526676,526576,527686,526494,526546,527654,527598,526758,526729,526811,526774,526697,527292,527565,527221,527069,527362,527402,526520,528045,528023,527452,526263,530732,527952,528369,528995,530629,61760,530548,529304,258349,530399,59167,529874,530145,320987,328935,528165,529672,258908,527930,160214,835781,530675,530436,528636,528704,529167,528930,26259,529899,529927,62606,528324,527843,835795,258777,528682,530569,529973,529129,529730,528254,529346,4709,61798,61794,529628,258354,527764,529010,530419,528115,529262,529283,527809,530712,527793,61694,530028,529414,258784,258770,258899,528821,526864,62593,529955,29242,526394,528514,529471,61315,62341,60566,60494,0,526175,528232,526332,526411,526304,527895,530314,530780,528429,528451,528266,528288,527881,13534,529888,26586,63462,59198,63457,63507,63477,26244,526361,529798,528347,529449,1031277,227770,530487,226394,529586,530092,529369,26249,26291,160236,1072764,1072677,1072699,527822,60866,528482,528756,529851,258894,68338,528719,63247,529993,526462,529323,62565,279404,526197,530751,227597,329090,330690,529391,530068,530252,530268,530213,528801,529429,527426,529829,528594,530506,528559,61788,62869,63232,61567,61598,530456,530369,526437,526994,526976,526930,528843,530525,528897,530293,528969,530331,530166,222444,61511,61346,530120,26254,528192,529563,529526,529107,530596,528738,26269,26286,60827,258332,258889,529491,528878,528779,529772,529698,528410,528667,528213,328951,528068,1072646,1072653,1072571,1072668,60856,526245,529152,530196,529649,529184,529048,529608,1031653,1031640,528542,328970,528096,526220,0,258811,63888,527774,529232,528390,529200,528134,62552,62619,62682,258791,95173,95265,1838500,1838534,1838507,1838509,75102,559278,592757,592752,592747,298334,557812,560062,24812,24823,71594,592034,592003,1838224,1842422,1842533,1842593,1842696,1851423,1819225,1819228,1819252,1819255,1819310,1819217,1819205,1819244,1819128,1819278,924146,0,0,89760,89190,89735,89730,89755,89745,89750,89740,0,1941607,569911,304739,29712,79478,79497,49995,79873,50049,920855,921257,920796,920823,920839,921869,920724,919938,29125,0,317573,317913,317908,50229,1073937,317936,922806,12769,150407,80528,79739,79721,79762,79744,79785,79767,80559,29750,91983,91899,92507,92600,92615,92620,92521,92605,92610,95315,95346,95448,95438,95453,95443,95458,90670,150307,150348,568941,569899,1950432,50297,323898,922768,29094,569711,569795,79449,29470,29828,29810,29819,89695,89725,89705,89700,89720,89715,89710,568800,923810,922222,23780,23796,924578,95380,95385,0,1031319,1031341,569048,304780,150401,181597,181740,181770,181760,181745,181765,181755,181750,181735,49850,0,0,29740,568820,924818,569926,89795,89775,89770,89765,89790,89785,89780,93689,93770,93755,93765,93750,150246,919636,50291,323600,92367,317918,923428,922896,922933,602935,602953,602971,50211,29591,88835,88852,324130,324061,324091,324086,324066,324081,324056,324071,324076,80422,50036,603229,603825,604433,602989,602453,602180,602166,29584,29577,150609,150602,150623,150615,76121,1157844,1157730,1157786,1157949,569931,569936,171613,323923,1069243,256930,50017,922970,923590,923654,569025,6837,58334,569941,29745,1855673,1855769,1855657,1855692,1855710,1855637,1855732,1855764,550666,1823011,1822993,1854702,1854824,1854797,1854730,1854786,1854759,1854724,550187,29712,178705,1093151,50336,1955866,1957664,551144,321727,560859,299452,1955710,1955701,50349,157157,50238,50280,50362,760128,760208,760224,761240,761040,761304,761400,760944,760192,760184,761128,760472,760664,760280,760424,758538,760376,761008,760520,760232,760880,760328,760976,760144,760120,761368,761104,760152,761440,760848,760136,760176,1959808,760912,760200,761176,760160,68358,68328,68323,63266,60890,62821,62827,182490,182485,68353,63259,62832,62838,271474,182495,62501,60897,271479,271489,271792,66700,77046,62847,63293,77094,61048,77079,62862,76474,63964,761490,62524,78773,66297,66260,66208,66231,66171,66128,77414,77404,77399,77409,77424,77419,77379,0,150747,77685,63289,62843,63310,63237,63242,0,328917,0,328362,328223,0,77089,77064,77074,77069,77059,77084,63227,61162,68348,62528,62547,63273,329768,63252,75583,61121,61053,271484,78304,62520,62851,182500,68333,60943,68343,90674,91869,91411,91406,91416,91426,91421,91431,91767,91787,91797,91762,91822,91747,91752,91757,91802,91792,91782,91807,91772,91812,91777,91817,91843,91852,91827,91693,91836,75131,75111,70628,79565,74572,934806,934803,934865,934858,935149,935152,935034,935043,935016,935007,935025,934929,934936,934715,934717,934719,159453,51636,53674,53691,79234,52957,51757,300209,79465,53710,51631,51006,621958,51217,51146,51299,158281,159707,159693,159612,159523,158599,52766,79351,79276,52263,52278,52268,51073,599195,754948,53357,5Line truncated
es: [529173,528047,530289,529245,26270,60823,256874,256880,256862,528742,528721,1031749,529214,60769,60764,63433,63453,60759,63438,60813,60774,224300,224295,224290,224285,224275,224280,224224,258800,527227,527378,527258,527134,526820,527189,526866,527326,528016,527470,527526,527022,527628,527503,526611,526650,526688,526576,527694,526493,526548,527668,527594,526754,526723,526790,526771,526706,527276,527557,527207,527043,527353,527396,526519,528090,528068,527447,526260,531030,527998,528434,529131,530932,61711,530855,529471,258349,530678,59119,530110,530399,320992,328934,528200,529901,258908,527977,160236,0,530970,530722,528763,528825,529329,529065,26265,530133,530150,62557,528385,527882,0,258777,528808,530872,530198,529289,529968,528298,529513,4710,61749,61745,529848,258354,527790,529158,530701,528158,529426,529448,527845,531008,527825,61645,530257,529604,258784,258770,258899,528953,526848,62544,530167,29248,0,528606,529670,61266,62292,60518,60446,0,526169,528274,0,526395,526312,527933,530582,531081,528510,528531,528320,528345,527915,13530,530124,26592,63413,59150,63408,63458,63428,26250,526341,530032,528416,529647,1031277,227769,530789,226393,529805,530343,529535,26255,26297,160258,1072761,1072674,1072696,527861,60818,528570,528883,530085,258894,68358,528845,63198,530218,526449,529491,62516,279404,526198,531049,227596,0,330685,529570,530313,530510,530531,530477,528921,529627,527417,530063,528698,530808,528656,61739,62820,63183,61518,61549,530749,530643,526421,526964,526940,526903,528989,530832,529039,530556,529098,530602,530421,222443,61462,61297,530372,26260,528225,529779,529734,529266,530907,528864,26275,26292,60779,258332,258889,529691,529027,528904,530004,529933,528484,528791,528254,328949,528117,1072643,1072650,1072568,1072665,60808,526242,529315,530455,529871,529351,529194,529829,1031653,1031640,528635,328966,528140,526222,526149,258811,63839,527808,529398,528460,529370,528176,62503,62570,62633,258791,95154,95246,1838736,1838776,1838745,1838747,75137,559287,592778,592774,592769,298334,557813,560071,24818,24829,71616,592043,592006,1838451,1842873,1842981,1843045,1843153,1851424,1819501,1819443,1819501,1819474,1819536,1819432,1819417,1819462,1819339,1819501,924543,150689,1510290,89752,89182,89727,89722,89747,89737,89742,89732,1509001,1942287,569921,304728,29717,79504,79523,49993,79899,50047,920856,921648,920797,920824,920840,922260,920725,919939,29131,1510357,317573,317913,317908,50227,1073934,317936,923197,12765,150407,80554,79765,79747,79788,79770,79811,79793,80585,29755,91975,91891,92499,92592,92607,92612,92513,92597,92602,95296,95327,95429,95419,95434,95424,95439,90670,150308,150349,568950,569909,1950435,50295,324089,923159,29100,569721,569805,79475,29476,29833,29815,29824,89687,89717,89697,89692,89712,89707,89702,568809,924207,922613,23778,23794,924975,95361,95366,1510214,1031319,1031341,569057,304769,150402,181585,181728,181758,181748,181733,181753,181743,181738,181723,49848,2078033,2078061,29745,568829,925215,569936,89787,89767,89762,89757,89782,89777,89772,93670,93751,93736,93746,93731,150247,919637,50289,323790,92359,317918,923819,923287,923324,602957,602975,602993,50209,29596,88827,88844,324321,324252,324282,324277,324257,324272,324247,324262,324267,80448,50034,603251,603823,604431,603011,602475,602202,602188,29589,29583,150609,0,150623,150615,76150,1158057,1157941,1157989,1158177,569941,569946,171629,324112,1069240,256930,50015,923361,923981,924045,569034,6833,58284,569951,29750,1857778,1857861,1857762,1857796,1857813,1857738,1857832,1857855,550664,1823861,1823842,1855709,1855852,1855817,1855739,1855798,1855768,1855727,550187,29717,178721,1093151,50334,1955868,1957666,551147,321732,560868,299448,1955718,1955709,50347,0,50236,50278,50360,760135,760215,760231,761247,761047,761311,761407,760951,760199,760191,761135,760479,760671,760287,760431,758545,760383,761015,760527,760239,760887,760335,760983,760151,760127,761375,761111,760159,761447,760855,760143,760183,1959824,760919,760207,761183,760167,68378,68348,68343,63217,60842,62772,62778,182478,182473,68373,63210,62783,62789,271494,182483,62452,60849,271499,271509,271812,66717,77075,62798,63244,77123,61000,77108,62813,76503,63915,761497,62475,78811,66313,66274,66217,66242,66178,66132,77443,77433,77428,77438,77453,77448,77408,150704,150752,77714,63240,62794,63261,63188,63193,65861,328916,0,328361,328224,0,77118,77093,77103,77098,77088,77113,63178,61113,68368,62479,62498,63224,0,63203,75618,61072,61005,271504,78333,62471,62802,182488,68353,60895,68363,90674,91863,91411,91406,91416,91426,91421,91431,91767,91787,91797,91762,91822,91747,91752,91757,91802,91792,91782,91807,91772,91812,91777,91817,91842,91848,91827,91693,91836,75166,75146,70648,79591,74607,934808,934805,934869,934860,935167,935170,935048,935059,935026,935015,935037,934935,934943,934717,934719,0,159475,51585,53623,53640,79272,52906,51706,300205,79491,53659,51580,50955,621952,51166,51095,51248,158293,159729,159715,159634,159545,158611,52715,79391,79314,52212,52227,52217,51022,599217,7549Line truncated
} as const;
+28
View File
@@ -23,6 +23,17 @@ export function romRevision(r: RomReader): Revision {
return revision;
}
/** Whether the ROM carries a known game code (a cartridge, not a test's
* synthetic ROM). */
export function hasRevision(r: RomReader) {
try {
romRevision(r);
return true;
} catch {
return false;
}
}
/** romRevision, or 1.1 for a ROM without a known game code. */
export function knownRevision(r: RomReader): Revision {
try {
@@ -58,6 +69,23 @@ for (const entry of REVISION_KEYS) {
}
let current: Revision = "1.1";
/** The cartridge useRevision last selected. */
export const currentRevision = () => current;
/** PlaceBattlersName.enemy: French and Italian place the enemy's nickname,
* then EnemyText (" ennemi", " nemico"); the others EnemyText first. */
export const enemyNameFirst = () => current === "fr" || current === "it";
/** PlaceEnemysName: French, Italian and Spanish print the trainer's name,
* a space and the class (Battle_GetTrainerName first); English and German
* the class first. */
export const trainerNameFirst = () => current === "fr" || current === "it" || current === "es";
/** The European releases: their own units (CalcMagikarpLength stores
* millimetres; the Pokédex shows metres and kilograms). */
export const european = () => current in REVISION_ADDRESSES;
export const metricMagikarp = european;
/** Point the profile at a cartridge's addresses and characters. The port
* reads one cartridge at a time: CrystalAssets calls this for its ROM. */
export function useRevision(revision: Revision) {
+28 -12
View File
@@ -1,5 +1,8 @@
import { JOHTO, RAM, WRAM } from "../rom/profile";
import { magikarpLength } from "../battle/battle";
import { magikarpLengthBytes } from "../battle/battle";
import { metricMagikarp } from "../rom/revision";
import type { RomReader } from "../rom/reader";
import { defaultTextContext, readString } from "./text";
import type { Gen, SpecialContext } from "./special-context";
const MAGIKARP = 129;
@@ -12,22 +15,35 @@ export const MAGIKARP_LENGTH = {
beatRecord: 3,
} as const;
/** wBestMagikarpLengthFeet/Inches and wMagikarpRecordHoldersName;
* InitializeMagikarpHouse starts a new game at 3′6″ by RALPH. */
/** wBestMagikarpLengthFeet/Inches and wMagikarpRecordHoldersName. The two
* bytes are wMagikarpLength's: feet and inches in English, the millimetres'
* high and low bytes in the European releases. */
export interface MagikarpRecord {
feet: number;
inches: number;
holder: string;
}
export const initialMagikarpRecord = (): MagikarpRecord => ({
feet: 3,
inches: 6,
holder: "RALPH",
});
/** InitializeMagikarpHouse: the bytes it loads (3′6″ in English, 1053 mm in
* the European releases) and its .Ralph name; English's without a ROM, for
* saves migrated from before the record was kept. */
export const initialMagikarpRecord = (r?: RomReader): MagikarpRecord =>
r
? {
feet: r.byte(JOHTO.InitializeMagikarpHouse + 4),
inches: r.byte(JOHTO.InitializeMagikarpHouse + 7),
holder: readString(r, JOHTO["InitializeMagikarpHouse.Ralph"], defaultTextContext(""), 11),
}
: { feet: 3, inches: 6, holder: "RALPH" };
/** PrintMagikarpLength: feet and inches, each a left-aligned number, with
* the feet and inches marks it loads into tiles $6e and $6f. */
const lengthString = (feet: number, inches: number) => `${feet}′${inches}″`;
/** PrintMagikarpLength: in English, feet and inches, each a left-aligned
* number, with the feet and inches marks it loads into tiles $6e and $6f.
* The European releases print the millimetres as four digits, put a "."
* before the last one and drop the leading zeros: 512 mm reads 51.2. */
const lengthString = (high: number, low: number) => {
if (!metricMagikarp()) return `${high}′${low}″`;
const digits = String((high << 8) | low).padStart(4, "0");
return `${digits.slice(0, 3)}.${digits[3]}`.replace(/^0+/, "");
};
/** FindThatSpecies: wPartySpecies holds EGG for an Egg, so an Egg never
* matches. */
@@ -47,7 +63,7 @@ export function* checkMagikarpLength(
const mon = c.state.party[slot];
// wCurPartySpecies comes from wPartySpecies, EGG for an Egg.
if (mon.egg || mon.species !== MAGIKARP) return MAGIKARP_LENGTH.notMagikarp;
const { feet, inches } = magikarpLength(c.reader, mon.dvs, mon.otId);
const [feet, inches] = magikarpLengthBytes(c.reader, mon.dvs, mon.otId);
c.strings[RAM.stringBuffer1] = lengthString(feet, inches);
c.write(JOHTO["CheckMagikarpLength.MagikarpGuruMeasureText"]);
// CompareBytes over wMagikarpLength and the record: carry when the new
+5 -2
View File
@@ -1,6 +1,7 @@
import { RomReader } from "../rom/reader";
import { RAM } from "../rom/profile";
import { releaseCharacter } from "../rom/charset";
import { enemyNameFirst } from "../rom/revision";
const CHARACTERS: Record<number, string> = {
0x1f: " ",
@@ -82,7 +83,8 @@ export interface TextContext {
/** Numbers that text_decimal reads from RAM, by address. */
numbers?: Readonly<Record<number, number>>;
/** Battle names for <USER> and <TARGET>: whose turn it is, and the
* enemy prefix the game prints before the enemy's nickname. */
* EnemyText the game prints with the enemy's nickname (before it, or
* after it in French and Italian). */
battle?: { turn: number; player: string; enemy: string; enemyPrefix: string };
/** Native handlers for text_asm, keyed by the command's ROM offset. They
* return where text continues, as the original routine returns in hl. */
@@ -135,7 +137,8 @@ export class UnsupportedText extends Error {
function battler(context: TextContext, enemy: boolean): string | undefined {
const names = context.battle;
if (!names) return undefined;
return enemy ? names.enemyPrefix + names.enemy : names.player;
if (!enemy) return names.player;
return enemyNameFirst() ? names.enemy + names.enemyPrefix : names.enemyPrefix + names.enemy;
}
function character(code: number, context: TextContext): string | undefined {
+4
View File
@@ -1,3 +1,4 @@
import { hasRevision } from "../rom/revision";
import {
DecorationData,
initialDecorations,
@@ -871,6 +872,9 @@ export class GameWorld {
) {
this.sound = new GameSound(assets.reader);
this.state.decorations = initialDecorations();
// _ResetWRAM's InitializeMagikarpHouse, from the cartridge (English's
// values for the synthetic ROMs of tests, which carry no game code).
this.state.magikarpRecord = initialMagikarpRecord(hasRevision(assets.reader) ? assets.reader : undefined);
this.playerId = (this.random() << 8) | this.random();
// A new game warps into the bedroom. Its NEWMAP callback runs the
// original InitializeEventsScript, which supplies initial NPC flags.
+59 -3
View File
@@ -1,11 +1,15 @@
import { describe, expect, it } from "vitest";
import { existsSync, readFileSync } from "node:fs";
import { CrystalAssets } from "../src/game/rom/assets";
import { JOHTO, MENU } from "../src/game/rom/profile";
import { revisionAddresses, romRevision } from "../src/game/rom/revision";
import { JOHTO, MENU, RAM } from "../src/game/rom/profile";
import { initialMagikarpRecord, magikarpHouseSign } from "../src/game/scripts/lake-of-rage";
import { magikarpLength, magikarpLengthBytes } from "../src/game/battle/battle";
import { revisionAddresses, romRevision, useRevision } from "../src/game/rom/revision";
import { RomReader } from "../src/game/rom/reader";
import { RELEASES_IN_PROGRESS, validateRom } from "../src/rom/validate";
import { readString } from "../src/game/scripts/text";
import { defaultTextContext, readString } from "../src/game/scripts/text";
import { textTiles } from "../src/game/rom/font";
import { dexHeight, dexWeight } from "../src/game/rom/pokedex";
import { Playthrough } from "./playthrough-driver";
/** The European releases at the repository root, each skipped when absent. */
@@ -78,3 +82,55 @@ for (const { language, rom, release } of releases)
expect(p.world.notice).toBe("");
});
});
describe("the European releases' word order", () => {
it("places the enemy's nickname before EnemyText in French and Italian", () => {
// <USER> on the enemy's turn ($5a), then the terminator.
const reader = new RomReader(new Uint8Array([0x5a, 0x50]));
const name = (revision: Parameters<typeof useRevision>[0], prefix: string) => {
useRevision(revision);
return readString(reader, 0, {
...defaultTextContext("KAWA"),
battle: { turn: 1, player: "CYNDAQUIL", enemy: "RATTATA", enemyPrefix: prefix },
});
};
expect(name("fr", " ennemi")).toBe("RATTATA ennemi");
expect(name("it", " nemico")).toBe("RATTATA nemico");
expect(name("de", "Gegn. ")).toBe("Gegn. RATTATA");
expect(name("1.1", "Enemy ")).toBe("Enemy RATTATA");
});
});
describe.skipIf(!existsSync(releases[0].rom))("the European releases' Magikarp", () => {
it("measure in millimetres and print a tenth of them, from 105.3 by the release's own holder", () => {
const bytes = new Uint8Array(readFileSync(releases[0].rom));
const assets = new CrystalAssets(bytes);
const record = initialMagikarpRecord(assets.reader);
// InitializeMagikarpHouse's bytes: 1053 mm.
expect([record.feet, record.inches]).toEqual([0x04, 0x1d]);
expect(record.holder).not.toBe("RALPH");
const strings: Record<number, string> = {};
magikarpHouseSign({ strings, write: () => {} } as never, record);
expect(strings[RAM.stringBuffer1]).toBe("105.3");
// CalcMagikarpLength stores the millimetres (English converts them).
const [high, low] = magikarpLengthBytes(assets.reader, 0x1234, 0x5678);
expect((high << 8) | low).toBe(magikarpLength(assets.reader, 0x1234, 0x5678).mm);
});
});
describe.skipIf(!existsSync(releases[0].rom))("the European releases' Pokédex", () => {
it("reads metric heights and weights and prints them in metres and kilograms", () => {
for (const { rom } of releases) {
if (!existsSync(rom)) continue;
const dex = new CrystalAssets(new Uint8Array(readFileSync(rom))).pokedex;
// PIKACHU: 0.4 m and 6.0 kg; its pages still follow.
const entry = dex.entry(25);
expect([entry.height, entry.weight]).toEqual([4, 60]);
expect(entry.pages[0].length).toBeGreaterThan(10);
const height = dexHeight(dex.dexString("Pokedex_DrawDexEntryScreenBG.Height"), entry.height);
const weight = dexWeight(dex.dexString("Pokedex_DrawDexEntryScreenBG.Weight"), entry.weight);
expect(height).toMatch(/^\S+ +0\.4m$/);
expect(weight).toMatch(/^\S+ +6\.0kg$/);
}
});
});
+4 -1
View File
@@ -236,10 +236,13 @@ test.describe("Day-Care routines against the cartridge", () => {
let text = "";
for (const byte of bytes) {
if (byte === 0x50) break;
// Capitals and small letters (a release's own names use both).
text +=
byte >= 0x80 && byte < 0x9a
? String.fromCharCode(65 + byte - 0x80)
: "?";
: byte >= 0xa0 && byte < 0xba
? String.fromCharCode(97 + byte - 0xa0)
: "?";
}
return text;
};
+4 -1
View File
@@ -6,7 +6,10 @@ 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 1.1 symbols, or CRYSTAL_SYMBOLS_PATH for another cartridge (a
* release's symbols mapped from 1.1's, as scripts/map-revision.mjs finds
* its labels). */
export const symbolsPath = process.env.CRYSTAL_SYMBOLS_PATH ?? ".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 = {
+6 -3
View File
@@ -6,7 +6,7 @@ import {
Battle,
applyTypeMatchups,
calculateDamage,
magikarpLength,
magikarpLengthBytes,
restoreHealth,
restoredPP,
sendOutText,
@@ -708,8 +708,11 @@ test("native Magikarp lengths match CalcMagikarpLength", async ({ page }) => {
cases.forEach((input, index) => {
const { returned, ...original } = results[index];
expect(returned, `case ${index} returned`).toBe(true);
expect(magikarpLength(reader, input.dvs, input.id), JSON.stringify(input)).toEqual(original);
// wMagikarpLength's bytes: feet and inches, or a European release's
// millimetres.
const [feet, inches] = magikarpLengthBytes(reader, input.dvs, input.id);
expect({ feet, inches }, JSON.stringify(input)).toEqual(original);
});
const lengths = new Set(results.map(({ feet, inches }) => feet * 12 + inches));
const lengths = new Set(results.map(({ feet, inches }) => feet * 256 + inches));
expect(lengths.size).toBeGreaterThan(30);
});
+2
View File
@@ -3,6 +3,8 @@ import { existsSync } from "node:fs";
import { romPath, symbolsPath, loadSymbols, openReference, revisionRoms } from "./reference-fixture";
test.skip(!existsSync(romPath) || !existsSync(symbolsPath), "Needs private ROM/reference.");
// The English cartridges share 1.1's symbols; not run with another's.
test.skip(Boolean(process.env.CRYSTAL_SYMBOLS_PATH), "Compares the English cartridges.");
/** BattleTowerText on each English cartridge, with PrintTextboxTextAt
* patched to keep the text pointer: for every BattleTowerTrainers entry,
+4
View File
@@ -15,6 +15,10 @@ test.skip(!existsSync(romPath) || !existsSync(symbolsPath), "Needs private ROM a
// and ObjectEventText's low byte ($f2), i.e. flag $f251. EventFlagAction's
// bit math (de >> 3 added to wEventFlags) overflows by $1e4a bytes into
// echo RAM, landing on wNumKeyItems (bank 1, $d8bc) bit 1.
// These pin English 1.1's data (ObjectEvent's bytes read as a header, its
// trainers and texts); another release's data differs.
test.skip(Boolean(process.env.CRYSTAL_SYMBOLS_PATH), "Checks English data.");
test("CheckTrainerBattle reads BurnedTower1F's rival as beaten only when wNumKeyItems' bit 1 is set", async ({ page }) => {
const { at, routine } = loadSymbols();
const a = {