Map the French, German, Italian and Spanish releases' addresses (#84)
PRET builds none of these releases, so scripts/map-revision.mjs derives where each keeps the profile's labels from the 1.1 build: a bank-by-bank alignment, then the exact references RGBDS recorded while linking 1.1, read at the matching place in the release, each result checked against its bytes. All but 1-3 labels per release are found; the rest, in code the release changed, are -1 so reading them refuses. check:reference verifies the generated file when the ROMs are present. CrystalAssets now points the profile at the cartridge's addresses, and the releases' characters (from their own fonts) and two European text codes decode. The introduction and Mom's scene play in each language and every map sweeps as in English, but the releases stay refused until the logic they localize (units, word order, layouts) is ported. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
3c480a28f0
commit
627f87d8b5
17 files changed
+1202
-190
No files matched your search
@@ -1,5 +1,6 @@
|
||||
import { RomReader } from "./reader";
|
||||
import { decompress } from "./lz";
|
||||
import { knownRevision, useRevision } from "./revision";
|
||||
import {
|
||||
LAST_MAP_GROUP_SIZE,
|
||||
MAP_GROUP_COUNT,
|
||||
@@ -43,6 +44,8 @@ export class CrystalAssets {
|
||||
private sceneOwners?: Map<string, string>;
|
||||
constructor(bytes: Uint8Array) {
|
||||
this.reader = new RomReader(bytes);
|
||||
// Synthetic ROMs in tests carry no game code: they read as 1.1.
|
||||
useRevision(knownRevision(this.reader));
|
||||
this.pokemon = new PokemonData(this.reader);
|
||||
this.pokedex = new PokedexData(this.reader);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
/** PlaceNextChar's own codes in every European release: $1d places "-"
|
||||
* and breaks the line (a word hyphenated at a line's end), $1e prints
|
||||
* nothing (a word break, where the Town Map wraps a long name). */
|
||||
const EUROPE: Record<number, string> = { 0x1d: "-\n", 0x1e: "" };
|
||||
/** The characters the European releases add to the English charmap
|
||||
* (constants/charmap.asm), identified from each release's own 1bpp font
|
||||
* (Font, $80-$ff). French and German share one font, Italian and Spanish
|
||||
* another; neither keeps English's apostrophe ligatures at $d0-$d6. */
|
||||
const NORTH: Record<number, string> = {
|
||||
...EUROPE,
|
||||
0xba: "à",
|
||||
0xbb: "è",
|
||||
0xbc: "é",
|
||||
0xbd: "ù",
|
||||
0xbe: "ß",
|
||||
0xbf: "ç",
|
||||
0xc6: "ë",
|
||||
0xc7: "ï",
|
||||
0xc8: "â",
|
||||
0xc9: "ô",
|
||||
0xca: "û",
|
||||
0xcb: "ê",
|
||||
0xcc: "î",
|
||||
0xcf: "←",
|
||||
0xd4: "c'",
|
||||
0xd5: "d'",
|
||||
0xd6: "j'",
|
||||
0xd7: "l'",
|
||||
0xd8: "m'",
|
||||
0xd9: "n'",
|
||||
0xda: "p'",
|
||||
0xdb: "s'",
|
||||
0xdc: "'s",
|
||||
0xdd: "t'",
|
||||
0xde: "u'",
|
||||
0xdf: "y'",
|
||||
0xe4: "+",
|
||||
};
|
||||
const SOUTH: Record<number, string> = {
|
||||
...EUROPE,
|
||||
0xba: "à",
|
||||
0xbb: "è",
|
||||
0xbc: "é",
|
||||
0xbd: "ù",
|
||||
0xbe: "À",
|
||||
0xbf: "Á",
|
||||
0xc6: "È",
|
||||
0xc7: "É",
|
||||
0xc8: "Ì",
|
||||
0xc9: "Í",
|
||||
0xca: "Ñ",
|
||||
0xcb: "Ò",
|
||||
0xcc: "Ó",
|
||||
0xcd: "Ù",
|
||||
0xce: "Ú",
|
||||
0xcf: "á",
|
||||
0xd0: "ì",
|
||||
0xd1: "í",
|
||||
0xd2: "ñ",
|
||||
0xd3: "ò",
|
||||
0xd4: "ó",
|
||||
0xd5: "ú",
|
||||
0xd6: "º",
|
||||
0xd7: "&",
|
||||
0xd8: "'d",
|
||||
0xd9: "'l",
|
||||
0xda: "'m",
|
||||
0xdb: "'r",
|
||||
0xdc: "'s",
|
||||
0xdd: "'t",
|
||||
0xde: "'v",
|
||||
0xe4: "¿",
|
||||
0xe5: "¡",
|
||||
};
|
||||
export const LANGUAGE_CHARACTERS = { fr: NORTH, de: NORTH, it: SOUTH, es: SOUTH } as const;
|
||||
|
||||
/** Every letter a supported release can store in a name: English's
|
||||
* umlauts ($c0-$c5) and the releases' own. */
|
||||
export const NAME_LETTERS = [...new Set(
|
||||
[..."ÄÖÜäöü", ...Object.values(NORTH), ...Object.values(SOUTH)].filter(
|
||||
(value) => value.length === 1 && /\p{L}/u.test(value),
|
||||
),
|
||||
)].join("");
|
||||
|
||||
let active: Record<number, string> = {};
|
||||
let codes = new Map<string, number>();
|
||||
|
||||
/** Use a release's characters (none for the English cartridges). */
|
||||
export function useCharacters(language?: keyof typeof LANGUAGE_CHARACTERS) {
|
||||
active = language ? LANGUAGE_CHARACTERS[language] : {};
|
||||
codes = new Map();
|
||||
for (const [code, value] of Object.entries(active))
|
||||
if (value.length === 1 && !codes.has(value)) codes.set(value, Number(code));
|
||||
}
|
||||
|
||||
/** The active release's character for a code (undefined when it keeps
|
||||
* English's). French and German leave $d0-$d3 blank. */
|
||||
export function releaseCharacter(code: number): string | null | undefined {
|
||||
if (code in active) return active[code];
|
||||
if (active === NORTH && code >= 0xd0 && code <= 0xd3) return null;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/** The active release's code for a character it adds. */
|
||||
export const releaseCode = (character: string) => codes.get(character);
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { RomReader } from "./reader";
|
||||
import { JOHTO } from "./profile";
|
||||
import { releaseCode } from "./charset";
|
||||
|
||||
/** TEXTBOX_FRAME_TILES and NUM_FRAMES (constants/text_constants.asm). */
|
||||
const TEXTBOX_FRAME_TILES = 6,
|
||||
@@ -51,6 +52,12 @@ const CODES: Record<string, number> = {
|
||||
";": 0x9d,
|
||||
"[": 0x9e,
|
||||
"]": 0x9f,
|
||||
Ä: 0xc0,
|
||||
Ö: 0xc1,
|
||||
Ü: 0xc2,
|
||||
ä: 0xc3,
|
||||
ö: 0xc4,
|
||||
ü: 0xc5,
|
||||
"'": 0xe0,
|
||||
"-": 0xe3,
|
||||
"?": 0xe6,
|
||||
@@ -81,7 +88,7 @@ export function textTiles(text: string): number[] {
|
||||
if (character >= "A" && character <= "Z") return 0x80 + code - 65;
|
||||
if (character >= "a" && character <= "z") return 0xa0 + code - 97;
|
||||
if (character >= "0" && character <= "9") return 0xf6 + code - 48;
|
||||
const mapped = CODES[character];
|
||||
const mapped = CODES[character] ?? releaseCode(character);
|
||||
if (mapped === undefined) throw new Error(`No tile for "${character}".`);
|
||||
return mapped;
|
||||
});
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
// Generated by scripts/map-revision.mjs from PRET's English 1.1 build and
|
||||
// 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_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
|
||||
} as const;
|
||||
+64
-10
@@ -1,17 +1,71 @@
|
||||
import type { RomReader } from "./reader";
|
||||
import * as PROFILE from "./profile";
|
||||
import { useCharacters } from "./charset";
|
||||
import { REVISION_ADDRESSES, REVISION_KEYS } from "./revision-addresses";
|
||||
|
||||
/** The cartridges the port reads, as PRET builds them (`make crystal`,
|
||||
* `crystal11` and `crystal_au`): the English US/Europe revisions 1.0 and
|
||||
* 1.1, and the Australian release, which is 1.1 with the Game Corners'
|
||||
* gambling texts rewritten. All three keep every label the port reads at the
|
||||
* same address; only the routines `romRevision` callers check differ. */
|
||||
export type Revision = "1.0" | "1.1" | "au";
|
||||
/** The cartridges the port reads: the English US/Europe revisions 1.0 and
|
||||
* 1.1 and the Australian release (PRET's `crystal`, `crystal11` and
|
||||
* `crystal_au`, which keep every label the port reads at the same address),
|
||||
* and the French, German, Italian and Spanish releases, whose addresses
|
||||
* scripts/map-revision.mjs derives from 1.1 (revision-addresses.ts). */
|
||||
export type Revision = "1.0" | "1.1" | "au" | Language;
|
||||
export type Language = keyof typeof REVISION_ADDRESSES;
|
||||
|
||||
const CODES: Record<string, Revision> = { BYTU: "au", BYTF: "fr", BYTD: "de", BYTI: "it", BYTS: "es" };
|
||||
|
||||
/** The revision from the cartridge header (rgbfix's -i and -n): game code
|
||||
* BYTU for the Australian release, else BYTE with mask ROM version 0 or 1. */
|
||||
* BYTE with mask ROM version 0 or 1, or a release's own code. */
|
||||
export function romRevision(r: RomReader): Revision {
|
||||
const code = String.fromCharCode(r.byte(0x13f), r.byte(0x140), r.byte(0x141), r.byte(0x142));
|
||||
if (code === "BYTU") return "au";
|
||||
if (code !== "BYTE") throw new Error("Unknown cartridge game code.");
|
||||
return r.byte(0x14c) === 0 ? "1.0" : "1.1";
|
||||
if (code === "BYTE") return r.byte(0x14c) === 0 ? "1.0" : "1.1";
|
||||
const revision = CODES[code];
|
||||
if (!revision) throw new Error("Unknown cartridge game code.");
|
||||
return revision;
|
||||
}
|
||||
|
||||
/** romRevision, or 1.1 for a ROM without a known game code. */
|
||||
export function knownRevision(r: RomReader): Revision {
|
||||
try {
|
||||
return romRevision(r);
|
||||
} catch {
|
||||
return "1.1";
|
||||
}
|
||||
}
|
||||
|
||||
type Table = Record<string, number>;
|
||||
const tables = PROFILE as unknown as Record<string, Table>;
|
||||
/** A release's profile entries that differ from 1.1: table -> key -> address
|
||||
* (-1 where the label was not found there). */
|
||||
export function revisionAddresses(language: Language): Record<string, Table> {
|
||||
const out: Record<string, Table> = {};
|
||||
REVISION_ADDRESSES[language].forEach((address, i) => {
|
||||
if (!address) return;
|
||||
const entry = REVISION_KEYS[i],
|
||||
dot = entry.indexOf(".");
|
||||
(out[entry.slice(0, dot)] ??= {})[entry.slice(dot + 1)] = address;
|
||||
});
|
||||
return out;
|
||||
}
|
||||
/** 1.1's values of every entry a release overrides. */
|
||||
const english = new Map<string, Table>();
|
||||
for (const entry of REVISION_KEYS) {
|
||||
const dot = entry.indexOf("."),
|
||||
table = entry.slice(0, dot),
|
||||
key = entry.slice(dot + 1);
|
||||
const saved = english.get(table) ?? {};
|
||||
saved[key] = tables[table][key];
|
||||
english.set(table, saved);
|
||||
}
|
||||
let current: Revision = "1.1";
|
||||
|
||||
/** 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) {
|
||||
if (revision === current) return;
|
||||
for (const [table, saved] of english) Object.assign(tables[table], saved);
|
||||
const language = revision in REVISION_ADDRESSES ? (revision as Language) : undefined;
|
||||
if (language)
|
||||
for (const [table, entries] of Object.entries(revisionAddresses(language))) Object.assign(tables[table], entries);
|
||||
useCharacters(language);
|
||||
current = revision;
|
||||
}
|
||||
Reference in new issue
Block a user