Simplify QFT config

This commit is contained in:
sup39 2022-04-22 19:23:15 +09:00
parent 912a8b067c
commit df449cc97c
9 changed files with 99 additions and 95 deletions

View file

@ -51,8 +51,8 @@ Some codes store some states in the games memory starting from address 0x817F000
| ![](./docs/buffer.svg) | `0x10D` | `0x10F` | Buffer (Ingame Timer) |
| ![](./docs/reserved.svg) | `0x110` | `0x237` | QF Timer: Timer Textbox |
| ![](./docs/reserved.svg) | `0x238` | `0x347` | General Function (`drawText`) |
| ![](./docs/buffer.svg) | `0x348` | `0x3BF` | Buffer (QF Timer) |
| ![](./docs/unallocated.svg) | `0x3C0` | `0xFFF` | Not Allocated |
| ![](./docs/buffer.svg) | `0x348` | `0x39B` | Buffer (QF Timer) |
| ![](./docs/unallocated.svg) | `0x39C` | `0xFFF` | Not Allocated |
### Adding translations

View file

@ -1,9 +1,11 @@
# Changelog
## Apr 22, 2022
### Shortened QFT
- Shortened QFT's freeze code by replacing C2 with 04(bl@event) and 07.
- Reserve `817F0348`~`817F03BF` (120 bytes)
### Shortened QFT and simplified config
- Shorten QFT's freeze code by replacing C2 with 04(bl@event) and 07.
- Reserve `817F0348`~`817F039B` (84 bytes)
- Change freezing config from [duration for each event] to [one duration + toggle for each event]
## Apr 21, 2022
### Reduced code size of Pattern Selector
Reduce 240 bytes of PS by replacing switch case with lookup table.

View file

@ -1,11 +1,11 @@
export const r13off = -0x6048;
/**
* @type {{[key: string]: [addr: number, orig: number]}}
* @type {{[key: string]: {addr: number, orig: number}}}
*/
export const freezeCodeInfo = {
redCoin: [0x801be474, 0x38a00000],
blueCoin: [0x801be288, 0x7c030378], // TODO QF+3 &0xfffffffc
redCoin: { addr: 0x801be474, orig: 0x38a00000 },
blueCoin: { addr: 0x801be288, orig: 0x7c030378 },
};
export const baseCode = `

View file

@ -1,17 +1,17 @@
export const r13off = -0x6818;
/**
* @type {{[key: string]: [addr: number, orig: number]}}
* @type {{[key: string]: {addr: number, orig: number}}}
*/
export const freezeCodeInfo = {
yellowCoin: [0x80196b54, 0x8805000e],
redCoin: [0x80196314, 0x38a00000],
blueCoin: [0x80196128, 0x7c030378], // TODO QF+3 &0xfffffffc
item: [0x801971f8, 0x8001001c],
talk: [0x800eb6e4, 0x807f00b0],
demo: [0x800eb74c, 0x806da8b0],
cleaned: [0x8017a3c0, 0x80010044],
bowser: [0x801d3c78, 0x2c1d0003],
yellowCoin: { addr: 0x80196b54, orig: 0x8805000e },
redCoin: { addr: 0x80196314, orig: 0x38a00000 },
blueCoin: { addr: 0x80196128, orig: 0x7c030378 },
item: { addr: 0x801971f8, orig: 0x8001001c },
talk: { addr: 0x800eb6e4, orig: 0x807f00b0 },
demo: { addr: 0x800eb74c, orig: 0x806da8b0 },
cleaned: { addr: 0x8017a3c0, orig: 0x80010044 },
bowser: { addr: 0x801d3c78, orig: 0x2c1d0003 },
};
export const baseCode = `

View file

@ -1,11 +1,11 @@
export const r13off = -0x6188;
/**
* @type {{[key: string]: [addr: number, orig: number]}}
* @type {{[key: string]: {addr: number, orig: number}}}
*/
export const freezeCodeInfo = {
redCoin: [0x8019e1fc, 0x38a00000],
blueCoin: [0x8019e010, 0x7c030378], // TODO QF+3 &0xfffffffc
redCoin: { addr: 0x8019e1fc, orig: 0x38a00000 },
blueCoin: { addr: 0x8019e010, orig: 0x7c030378 },
};
export const baseCode = `

View file

@ -1,11 +1,11 @@
export const r13off = -0x6120;
/**
* @type {{[key: string]: [addr: number, orig: number]}}
* @type {{[key: string]: {addr: number, orig: number}}}
*/
export const freezeCodeInfo = {
redCoin: [0x801b632c, 0x38a00000],
blueCoin: [0x801b6140, 0x7c030378], // TODO QF+3 &0xfffffffc
redCoin: { addr: 0x801b632c, orig: 0x38a00000 },
blueCoin: { addr: 0x801b6140, orig: 0x7c030378 },
};
export const baseCode = `

View file

@ -12,15 +12,16 @@ export const defaultConfig = {
fgA2: null,
bgRGB: 0x000000,
bgA: 0x80,
freezeDuration: 30,
freeze: {
yellowCoin: 0,
redCoin: 30,
blueCoin: 30,
item: 30,
talk: 30,
demo: 30,
cleaned: 30,
bowser: 30, // onBathhubGripDestroyed
yellowCoin: false,
redCoin: true,
blueCoin: true,
item: true,
talk: true,
demo: true,
cleaned: true,
bowser: true, // onBathhubGripDestroyed
},
};
@ -36,8 +37,10 @@ export function getConfig() {
};
}
const int16 = (x) => (x < 0 ? x + 0x10000 : x).toString(16).padStart(4, '0').slice(-4);
const int32 = (x) => (x < 0 ? x + 0x100000000 : x).toString(16).padStart(8, '0').slice(-8);
const int16 = (x) =>
(x < 0 ? x + 0x10000 : x).toString(16).padStart(4, '0').slice(-4).toUpperCase();
const int32 = (x) =>
(x < 0 ? x + 0x100000000 : x).toString(16).padStart(8, '0').slice(-8).toUpperCase();
import * as GMSJ01 from './code/GMSJ01.js';
import * as GMSE01 from './code/GMSE01.js';
@ -71,78 +74,81 @@ export default function codegen(version) {
if (baseCode == null) return '';
let code = baseCode;
const { freezeDuration: frame } = config;
// 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 });
const freezeEnableds = [];
if (frame > 0) {
for (const [key, enabled] of Object.entries(config.freeze)) {
const info = freezeCodeInfo[key];
if (enabled && 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
freezeEnableds.push(info);
}
}
}
}
// handle regular freezing code
if (freezeConfigs.length <= 1) {
if (freezeEnableds.length <= 1) {
// use C2 directly
code += freezeConfigs
.flatMap(({ frame, addr, orig }) => [
code += freezeEnableds
.flatMap(({ addr, orig }) => [
0xc2000000 + (addr & 0x1ffffff),
0x00000004,
0x39600000 | (frame & 0xffff), // li r11, frame
0x3d80817f, // lis r12, 0x817F
0x916c00bc, // stw r11, 0xBC(r12)
orig,
0x816d0000 | (r13off & 0xffff), // lwz r11, r13off(r13)
0x3d80817f, // lis r12, 0x817F
0x816b005c, // lwz r11, 0x5C(r11)
0x916c00b8, // stw r11, 0xB8(r12)
orig,
0x39600000 | (frame & 0xffff), // li r11, frame
0x916c00bc, // stw r11, 0xBC(r12)
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)
0x3d80817f, // lis r12, 0x817F
0x816b005c, // lwz r11, 0x5C(r11)
0x916c00b8, // stw r11, 0xB8(r12)
0x39600000 | (frame & 0xffff), // li r11, frame
0x916c00bc, // stw r11, 0xBC(r12)
0x4e800020, // blr
];
let dst = freezeCodeAddr + code07.length * 4;
// put code together
for (const { frame, addr, orig } of freezeConfigs) {
for (const { addr, orig } of freezeEnableds) {
code07.push(
orig, // [dst] original instruction
0x39600000 | (frame & 0xffff), // li r11, $frame
0x4c000000 + (freezeCodeAddr - dst - 8), // b freezeCode
0x4c000000 + (freezeCodeAddr - dst - 4), // b freezeCode
);
code04.push(
0x04000000 | (addr & 0x1ffffff), // 04 addr
0x48000001 | (dst - addr), // bl dst
);
dst += 12;
dst += 8;
}
// make 07 code
code07.unshift(

View file

@ -41,15 +41,15 @@
</section>
<section class="freeze">
<h3>{{l.freeze.h3}}</h3>
<div>
{{l.freeze.duration}}<input type="number" min="0" max="32767" v-model="freezeDuration"> {{l.freeze.frame}}
= {{(freezeDuration*1001/30000).toFixed(2)}} {{l.freeze.sec}}
</div>
<table>
<thead>
<th v-for="s in l.freeze.th" :key="s">{{s}}</th>
</thead>
<tbody>
<tr v-for="key in freezeKeys" :key="key">
<td>{{l.freeze.rows[key]}}</td>
<td><input type="number" :value="freeze[key]" @change="onChangeFreeze($event, key)"></td>
<td class="right">{{(freeze[key]*1001/30000).toFixed(2)}}</td>
<td><input type="checkbox" :checked="freeze[key]" @change="onChangeFreeze($event, key)"></td>
</tr>
</tbody>
</table>
@ -63,9 +63,9 @@ import labels from './labels.json';
import {getLabels} from '../codegen.js';
function updateConfig() {
const {x, y, fontSize, width, fgRGB, fgA, fgRGB2, fgA2, bgRGB, bgA, freeze} = this;
const {x, y, fontSize, width, fgRGB, fgA, fgRGB2, fgA2, bgRGB, bgA, freeze, freezeDuration} = this;
localStorage.setItem(lskey, JSON.stringify({
x, y, fontSize, width, fgRGB, fgA, fgRGB2, fgA2, bgRGB, bgA, freeze,
x, y, fontSize, width, fgRGB, fgA, fgRGB2, fgA2, bgRGB, bgA, freeze, freezeDuration
}));
}
@ -76,7 +76,7 @@ export default {
methods: {
updateConfig,
onChangeFreeze($event, key) {
this.freeze[key] = parseInt($event.target.value);
this.freeze[key] = $event.target.checked;
this.updateConfig();
},
toggleGradient($event) {
@ -93,11 +93,11 @@ export default {
rgbaI2S: (rgb, a) => '#'+rgb.toString(16).padStart(6, '0')+a.toString(16).padStart(2, '0'),
},
data() {
const {x, y, fontSize, width, fgRGB, fgA, fgRGB2, fgA2, bgRGB, bgA, freeze} = getConfig();
const {x, y, fontSize, width, fgRGB, fgA, fgRGB2, fgA2, bgRGB, bgA, freeze, freezeDuration} = getConfig();
return {
x, y, fontSize, width,
fgRGB, fgA, fgRGB2, fgA2, bgRGB, bgA,
freeze,
freeze, freezeDuration,
// const
freezeKeys: Object.keys(codes[this.version]?.freezeCodeInfo ?? {}),
};
@ -118,6 +118,7 @@ export default {
fgA2: updateConfig,
bgRGB: updateConfig,
bgA: updateConfig,
freezeDuration: updateConfig,
},
}
</script>
@ -126,7 +127,7 @@ export default {
input[type=number], td.right {
text-align: right;
}
.appearance input[type="number"] {
input[type="number"] {
width: 3em;
margin: 0 2px;
}
@ -134,15 +135,6 @@ input[type=number], td.right {
padding: 0 0 4px;
}
th {
text-align: center;
}
td > input[type=number] {
width: 8em;
max-width: 100%;
box-sizing: border-box;
}
input[type=number] {
-moz-appearance: textfield;
}

View file

@ -13,7 +13,9 @@
"previewNote": "※ x座標の範囲は0~600、y座標の範囲は16~464です\n※ ゲーム内のフォントはプレビューのより幅が広いです",
"freeze": {
"h3": "一時停止",
"th": ["タイミング", "停止フレーム数", "停止秒数"],
"duration": "長さ:",
"frame": "(フレーム)",
"sec": "(秒)",
"rows": {
"yellowCoin": "黄コインを取った時",
"redCoin": "赤コインを取った時",
@ -40,7 +42,9 @@
"previewNote": "※ x ranges from 0 to 600, and y ranges from 16 to 464.\n※ The font is wider in the game compared to the preview.",
"freeze": {
"h3": "Freezing the timer",
"th": ["Timing", "Duration(frame)", "Duration(sec)"],
"duration": "Duration: ",
"frame": "(frame)",
"sec": "(sec)",
"rows": {
"yellowCoin": "When collected a yellow coin",
"redCoin": "When collected a red coin",