Skip to content
JelleJurre edited this page Apr 7, 2026 · 7 revisions

In this section I invite anyone to put tricks they have found work during getting the last few % of a function.

Stack padding with an inline

If you need 8 fewer bytes in your stack size and your function contains an inline such as GET_JOBJ, you can get those 8 bytes by manually inlining

Example:

gobj->hsd_obj instead of GET_JOBJ



Switching the register order of arithmetic operations

If you have an arithmetic operation such as a * (b - c), and you want to swap the register order of the *, you will have to store b - c in a variable. This will take up stack space, but is required to swap the register order.

Example:

tmp = b - c
result = tmp * a


Two branches in a row

This can be two things:

  • If it is after a comparison with a number, it is likely a switch statement
  • If it is after a comparison with another variable (and is of the format bgt b or something like that), it is likely a ternary. Try using the MIN, MAX or CLAMP defines, but if these don't work, create your own ternary

Examples:

Switch Statement:

Instead of:

if (lbl_80479A98.x4 < 3) {
    if (lbl_80479A98.x4 < 0) {
    } else {
        lbl_80479A98.x18 = 1;
    }
}

It is

switch (lbl_80479A98.x4) {
    case 0:
    case 1:
    case 2:
        lbl_80479A98.x18 = 1;
}

Ternary:

Instead of:

var_r4 = lbl_80479A98.xC;
temp_r0 = lbl_80479A98.x8 - lbl_80479A98.x10;
if (temp_r0 < var_r4) {
} else {
var_r4 = temp_r0;
}
lbl_80479A98.x8 = var_r4;

It is

lbl_80479A98.x8 =
    ((lbl_80479A98.x8 - lbl_80479A98.x10) < (lbl_80479A98.xC))
       ? (lbl_80479A98.xC)
       : (lbl_80479A98.x8 - lbl_80479A98.x10);

Clone this wiki locally