Handle freezing code of blue coin properly

Also fix gpMarDirector r13 offset for all versions
This commit is contained in:
sup39 2022-04-22 18:03:49 +09:00
parent d9bb06f3ba
commit 912a8b067c
6 changed files with 73 additions and 14 deletions

View file

@ -1,5 +1,5 @@
# Changelog
## Apr 21, 2022
## Apr 22, 2022
### Shortened QFT
- Shortened QFT's freeze code by replacing C2 with 04(bl@event) and 07.
- Reserve `817F0348`~`817F03BF` (120 bytes)

View file

@ -1,3 +1,5 @@
export const r13off = -0x6048;
/**
* @type {{[key: string]: [addr: number, orig: number]}}
*/

View file

@ -1,3 +1,5 @@
export const r13off = -0x6818;
/**
* @type {{[key: string]: [addr: number, orig: number]}}
*/

View file

@ -1,3 +1,5 @@
export const r13off = -0x6188;
/**
* @type {{[key: string]: [addr: number, orig: number]}}
*/

View file

@ -1,3 +1,5 @@
export const r13off = -0x6120;
/**
* @type {{[key: string]: [addr: number, orig: number]}}
*/

View file

@ -65,44 +65,95 @@ export const codes = { GMSJ01, GMSE01, GMSP01, GMSJ0A };
bl 817fxxxx
****/
const freezeCodeAddr = 0x817f0348;
const freezeCode = [0x3d80817f, 0x916c00bc, 0x816d97e8, 0x816b005c, 0x916c00b8, 0x4e800020];
export default function codegen(version) {
const config = getConfig();
const { freezeCodeInfo, baseCode } = codes[version] ?? {};
const { freezeCodeInfo, baseCode, r13off } = codes[version] ?? {};
if (baseCode == null) return '';
let code = baseCode;
// freeze code
const code04 = [];
const code07 = [...freezeCode];
let dst = freezeCodeAddr + 24;
// freezing code
const freezeConfigs = [];
for (const [key, frame] of Object.entries(config.freeze)) {
const info = freezeCodeInfo[key];
if (frame > 0 && info) {
const [addr, orig] = info;
if (key === 'blueCoin') {
// special: needs to adjust QF -> use separate C2 instead
code += [
0xc2000000 + (addr & 0x1ffffff),
0x00000005,
orig,
0x80a3005c,
0x38a50003,
0x54a0003a,
0x3ca0817f,
0x900500b8,
0x38000000 | (frame & 0xffff),
0x900500bc,
0x60000000,
0x00000000,
]
.map(int32)
.join('');
} else {
// handle regular freezing code later
freezeConfigs.push({ frame, addr, orig });
}
}
}
// handle regular freezing code
if (freezeConfigs.length <= 1) {
// use C2 directly
code += freezeConfigs
.flatMap(({ frame, addr, orig }) => [
0xc2000000 + (addr & 0x1ffffff),
0x00000004,
0x39600000 | (frame & 0xffff), // li r11, frame
0x3d80817f, // lis r12, 0x817F
0x916c00bc, // stw r11, 0xBC(r12)
0x816d0000 | (r13off & 0xffff), // lwz r11, r13off(r13)
0x816b005c, // lwz r11, 0x5C(r11)
0x916c00b8, // stw r11, 0xB8(r12)
orig,
0x00000000,
])
.map(int32)
.join('');
} else {
let dst = freezeCodeAddr + 24;
const code04 = [];
const code07 = [
0x3d80817f, // lis r12, 0x817F
0x916c00bc, // stw r11, 0xBC(r12)
0x816d0000 | (r13off & 0xffff), // lwz r11, r13off(r13)
0x816b005c, // lwz r11, 0x5C(r11)
0x916c00b8, // stw r11, 0xB8(r12)
0x4e800020, // blr
];
// put code together
for (const { frame, addr, orig } of freezeConfigs) {
code07.push(
orig, // [dst] original instruction
0x39600000 | (frame & 0xffff), // li r11, $frame
0x4c000000 + (freezeCodeAddr - dst - 8), // b freezeCode
);
code04.push(
0x04000000 | (addr & 0x1ffffff), // 04xxxxxx
0x48000001 | (dst - addr), // bl
0x04000000 | (addr & 0x1ffffff), // 04 addr
0x48000001 | (dst - addr), // bl dst
);
dst += 12;
}
}
if (code04.length) {
// make 07 code
code07.unshift(
0x06000000 | (freezeCodeAddr & 0x1ffffff), // 07xxxxxx
0x06000000 | (freezeCodeAddr & 0x1ffffff), // 07 freezeCodeAddr
code07.length * 4,
);
if (code07.length & 1) {
// odd -> add 0
// odd => pad with 0
code07.push(0);
}
// apply code
code += [...code04, ...code07].map(int32).join('');
}