Port the trainer card and the play time
The player's name in the start menu opens TrainerCard: page 1 with the name, ID, money, Pokédex count and play time, page 2 with the Johto leaders and the badges owned, turned and closed with the original buttons. The card picture, leader faces and animated badges come from the ROM with _CGB_TrainerCard's palettes. GameTimer now counts the play time from the end of the introduction, capped at 999:59:59, and saves keep it. Closes #23 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
38b9562bd3
commit
47698565ab
24 files changed
+954
-30
No files matched your search
@@ -202,8 +202,8 @@ for (const [key, symbol] of Object.entries(ramNames)) {
|
||||
if (!match || Number(match[1]) !== ram.get(symbol))
|
||||
throw new Error(`Profile RAM mismatch: ${key} / ${symbol}`);
|
||||
}
|
||||
// BATTLE, OVERWORLD, PC, INTRO, STATS, MENU, POKEGEAR and MOM entries are keyed by their PRET labels.
|
||||
for (const table of ["BATTLE", "OVERWORLD", "PC", "INTRO", "STATS", "MENU", "POKEGEAR", "MOM"]) {
|
||||
// BATTLE, OVERWORLD, PC, INTRO, STATS, MENU, POKEGEAR, MOM and TRAINER_CARD entries are keyed by their PRET labels.
|
||||
for (const table of ["BATTLE", "OVERWORLD", "PC", "INTRO", "STATS", "MENU", "POKEGEAR", "MOM", "TRAINER_CARD"]) {
|
||||
const block = new RegExp(`export const ${table} = \\{([\\s\\S]*?)\\} as const;`).exec(profile)?.[1];
|
||||
if (!block) throw new Error(`${table} symbol table is missing.`);
|
||||
for (const [, quoted, bare, literal] of block.matchAll(/^\s+(?:"([^"]+)"|(\w+)):\s*(0x[0-9a-f]+),/gm)) {
|
||||
@@ -265,8 +265,9 @@ for (const [name, file] of [
|
||||
])
|
||||
if (!profile.includes(`${name} = ${constantCount(file, name)};`))
|
||||
throw new Error(`${name} does not match the reference.`);
|
||||
// PRET constants: const_def/const/const_skip/const_next/shift_const and
|
||||
// numeric or aliased DEF ... EQU, plus the battle command macro list.
|
||||
// PRET constants: const_def/const/const_skip/const_next/shift_const,
|
||||
// trainerclass and numeric or aliased DEF ... EQU, plus the battle command
|
||||
// macro list.
|
||||
const pretConstants = new Map();
|
||||
{
|
||||
const number = (text) =>
|
||||
@@ -284,7 +285,8 @@ const pretConstants = new Map();
|
||||
];
|
||||
for (const file of files) {
|
||||
let value = 0,
|
||||
step = 1;
|
||||
step = 1,
|
||||
trainerClass = 0;
|
||||
for (const raw of readFileSync(file, "utf8").split("\n")) {
|
||||
const line = raw.split(";")[0].trim();
|
||||
let match;
|
||||
@@ -293,7 +295,13 @@ const pretConstants = new Map();
|
||||
step = match[2] ? Number(match[2]) : 1;
|
||||
} else if ((match = /^const_next\s+([$%]?[0-9a-fA-F]+)$/.exec(line))) value = number(match[1]);
|
||||
else if ((match = /^const_skip(?:\s+(\d+))?$/.exec(line))) value += step * Number(match[1] ?? 1);
|
||||
else if ((match = /^(const|shift_const|command)\s+(\w+)$/.exec(line))) {
|
||||
else if ((match = /^DEF __trainer_class__ = (\d+)$/.exec(line))) trainerClass = Number(match[1]);
|
||||
else if ((match = /^trainerclass\s+(\w+)$/.exec(line))) {
|
||||
// DEF \1 EQU __trainer_class__, then const_def 1 for its trainers.
|
||||
pretConstants.set(match[1], trainerClass++);
|
||||
value = 1;
|
||||
step = 1;
|
||||
} else if ((match = /^(const|shift_const|command)\s+(\w+)$/.exec(line))) {
|
||||
const stored = match[1] === "shift_const" ? 1 << value : value;
|
||||
pretConstants.set(match[2], stored);
|
||||
if (match[1] === "shift_const") pretConstants.set(`${match[2]}_F`, value);
|
||||
|
||||
Reference in new issue
Block a user