This commit is contained in:
1 parent
2127f5f459
commit
8b80d05ca2
56 files changed
+6910
-1
No files matched your search
@@ -0,0 +1,127 @@
|
||||
import { RomReader } from "../rom/reader";
|
||||
|
||||
const CHARACTERS: Record<number, string> = {
|
||||
0x1f: " ",
|
||||
0x22: "\n",
|
||||
0x25: "",
|
||||
0x49: "MOM",
|
||||
0x4a: "Pokémon",
|
||||
0x4b: "\n",
|
||||
0x4c: "\n",
|
||||
0x4e: "\n",
|
||||
0x4f: "\n",
|
||||
0x51: "\n\n",
|
||||
0x53: "???",
|
||||
0x54: "POKé",
|
||||
0x55: "\n",
|
||||
0x56: "……",
|
||||
0x5b: "PC",
|
||||
0x5c: "TM",
|
||||
0x5d: "TRAINER",
|
||||
0x5e: "ROCKET",
|
||||
0x70: "PO",
|
||||
0x71: "Ké",
|
||||
0x72: "“",
|
||||
0x73: "”",
|
||||
0x74: "·",
|
||||
0x75: "…",
|
||||
0x7f: " ",
|
||||
0x9a: "(",
|
||||
0x9b: ")",
|
||||
0x9c: ":",
|
||||
0x9d: ";",
|
||||
0x9e: "[",
|
||||
0x9f: "]",
|
||||
0xc0: "Ä",
|
||||
0xc1: "Ö",
|
||||
0xc2: "Ü",
|
||||
0xc3: "ä",
|
||||
0xc4: "ö",
|
||||
0xc5: "ü",
|
||||
0xd0: "'d",
|
||||
0xd1: "'l",
|
||||
0xd2: "'m",
|
||||
0xd3: "'r",
|
||||
0xd4: "'s",
|
||||
0xd5: "'t",
|
||||
0xd6: "'v",
|
||||
0xdf: "←",
|
||||
0xe0: "'",
|
||||
0xe1: "POKé",
|
||||
0xe2: "MON",
|
||||
0xe3: "-",
|
||||
0xe6: "?",
|
||||
0xe7: "!",
|
||||
0xe8: ".",
|
||||
0xe9: "&",
|
||||
0xea: "é",
|
||||
0xeb: "→",
|
||||
0xec: "▷",
|
||||
0xed: "▶",
|
||||
0xee: "▼",
|
||||
0xef: "♂",
|
||||
0xf0: "¥",
|
||||
0xf1: "×",
|
||||
0xf2: ".",
|
||||
0xf3: "/",
|
||||
0xf4: ",",
|
||||
0xf5: "♀",
|
||||
};
|
||||
|
||||
export class UnsupportedText extends Error {
|
||||
constructor(
|
||||
readonly offset: number,
|
||||
readonly opcode: number,
|
||||
) {
|
||||
super(
|
||||
`Text command 0x${opcode.toString(16)} at 0x${offset.toString(16)} is not ported.`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export function readText(
|
||||
reader: RomReader,
|
||||
start: number,
|
||||
playerName: string,
|
||||
depth = 0,
|
||||
): string {
|
||||
if (depth > 8) throw new Error("Text calls exceed the recursion limit.");
|
||||
let p = start,
|
||||
output = "";
|
||||
for (let count = 0; count < 8192; count++) {
|
||||
const commandOffset = p,
|
||||
command = reader.byte(p++);
|
||||
if (command === 0x50) return output.trim();
|
||||
if (command === 0x16) {
|
||||
output += readText(
|
||||
reader,
|
||||
reader.near(p, reader.byte(p + 2)),
|
||||
playerName,
|
||||
depth + 1,
|
||||
);
|
||||
p += 3;
|
||||
continue;
|
||||
}
|
||||
if (command !== 0) throw new UnsupportedText(commandOffset, command);
|
||||
let ended = false;
|
||||
for (let length = 0; length < 8192; length++) {
|
||||
const offset = p,
|
||||
code = reader.byte(p++);
|
||||
if (code === 0x57 || code === 0x58) return output.trim();
|
||||
if (code === 0x50) {
|
||||
ended = true;
|
||||
break;
|
||||
}
|
||||
if (code === 0x52 || code === 0x14) output += playerName;
|
||||
else if (code >= 0x80 && code <= 0x99)
|
||||
output += String.fromCharCode(65 + code - 0x80);
|
||||
else if (code >= 0xa0 && code <= 0xb9)
|
||||
output += String.fromCharCode(97 + code - 0xa0);
|
||||
else if (code >= 0xf6) output += String(code - 0xf6);
|
||||
else if (CHARACTERS[code] !== undefined) output += CHARACTERS[code];
|
||||
else throw new UnsupportedText(offset, code);
|
||||
}
|
||||
if (!ended) throw new Error("Unterminated text.");
|
||||
}
|
||||
throw new Error("Text command limit exceeded.");
|
||||
}
|
||||
Reference in new issue
Block a user