2022-10-15 19:31:18 +09:00
|
|
|
import { parseJSON } from '../codegen.js';
|
2023-01-31 22:06:41 +09:00
|
|
|
import { ASM, liDX, str2inst, makeProgram, inst2gecko, getFillRectParams } from '../asm.js';
|
2023-01-29 04:39:18 +09:00
|
|
|
import { measureText } from '../text.js';
|
2023-01-31 22:06:41 +09:00
|
|
|
import { addrs } from '../addrs.js';
|
|
|
|
import { parseFormat } from './format.js';
|
|
|
|
import { assemble } from './assembler.js';
|
|
|
|
import { drawText, fillRect } from './functions.js';
|
2022-10-15 19:31:18 +09:00
|
|
|
export const lskey = 'config/CustomizedDisplay';
|
|
|
|
|
2023-01-29 04:39:18 +09:00
|
|
|
import configDB from './configDB.js';
|
|
|
|
export const defaultConfig = [configDB.PAS];
|
2022-10-15 19:31:18 +09:00
|
|
|
|
2023-01-31 22:06:41 +09:00
|
|
|
/** @type {(...args: Parameters<typeof parseFormat>) => string} */
|
|
|
|
export const format2previewText = (input, version) => parseFormat(input, version).preview;
|
|
|
|
|
|
|
|
/** @typedef {'GMSJ01'|'GMSJ0A'|'GMSE01'|'GMSP01'} GameVersion */
|
2022-10-15 19:31:18 +09:00
|
|
|
/** @param {GameVersion} version */
|
|
|
|
export function getConfig(version) {
|
|
|
|
/** @type {typeof defaultConfig} */
|
|
|
|
const config = typeof localStorage !== 'undefined' && parseJSON(localStorage.getItem(lskey));
|
|
|
|
return (config instanceof Array ? config : defaultConfig).map(({ fmt, ...o }) => ({
|
2023-01-29 04:39:18 +09:00
|
|
|
...defaultConfig[0],
|
2022-10-15 19:31:18 +09:00
|
|
|
...o,
|
|
|
|
fmt,
|
|
|
|
text: format2previewText(fmt, version),
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2023-01-31 22:06:41 +09:00
|
|
|
* @typedef {Parameters<assemble>[0][number]} ASMInst
|
2022-10-15 19:31:18 +09:00
|
|
|
* @param {GameVersion} version
|
|
|
|
*/
|
|
|
|
export default function codegen(version) {
|
2023-01-29 04:39:18 +09:00
|
|
|
const configs = getConfig(version);
|
2022-10-15 19:31:18 +09:00
|
|
|
|
2023-01-31 22:06:41 +09:00
|
|
|
let stackFrameSize = 0;
|
|
|
|
|
|
|
|
/** @type {ASMInst[]} */
|
|
|
|
const asm = [];
|
2022-10-15 19:31:18 +09:00
|
|
|
|
2023-01-29 04:39:18 +09:00
|
|
|
for (const config of configs) {
|
2023-01-31 22:06:41 +09:00
|
|
|
const { fmt, bgA } = config;
|
|
|
|
const { preview, format, fields } = parseFormat(fmt, version);
|
|
|
|
|
|
|
|
// fill_rect
|
2023-01-29 04:39:18 +09:00
|
|
|
if (bgA) {
|
2023-01-31 22:06:41 +09:00
|
|
|
asm.push(...fillRect(version, config, measureText(preview, version)));
|
2023-01-29 04:39:18 +09:00
|
|
|
}
|
2022-10-15 19:31:18 +09:00
|
|
|
|
2023-01-31 22:06:41 +09:00
|
|
|
// drawText
|
|
|
|
if (fmt.trim()) {
|
|
|
|
const { insts, sp } = drawText(version, config, format, fields);
|
|
|
|
stackFrameSize = Math.max(stackFrameSize, sp);
|
|
|
|
asm.push(...insts);
|
|
|
|
}
|
2022-10-15 19:31:18 +09:00
|
|
|
}
|
|
|
|
|
2023-01-31 22:06:41 +09:00
|
|
|
let body = assemble(asm, stackFrameSize);
|
|
|
|
// align code
|
|
|
|
if (body.length % 16 === 0) body += '60000000';
|
|
|
|
body += '00000000';
|
|
|
|
|
|
|
|
const addrDst = addrs.drawWater[version] - 0x2c; // [-0x30, -0x18]
|
|
|
|
return (
|
|
|
|
[
|
|
|
|
0xc2000000 | (addrDst & 0x1fffffff),
|
|
|
|
body.length >>> 4, // 16 hex-digits per line
|
|
|
|
]
|
|
|
|
.flatMap((e) => e)
|
|
|
|
.map(inst2gecko)
|
|
|
|
.join('') + body
|
|
|
|
);
|
2022-10-15 19:31:18 +09:00
|
|
|
}
|