diff --git a/config/regions.tsv b/config/regions.tsv index 2e6cca8..bea4544 100644 --- a/config/regions.tsv +++ b/config/regions.tsv @@ -155,9 +155,12 @@ 0x80057798 0x800577E8 src/func_80057798.c 0x8005784C 0x8005789C src/func_8005784C.c 0x8005789C 0x800578EC src/func_8005789C.c +0x80057950 0x800579A0 src/func_80057950.c 0x800579A0 0x800579F0 src/func_800579A0.c 0x800579F0 0x80057A40 src/func_800579F0.c +0x80057A40 0x80057A90 src/func_80057A40.c 0x80057AE0 0x80057B30 src/func_80057AE0.c +0x80057B30 0x80057B84 src/func_80057B30.c 0x80057B84 0x80057BE8 src/func_80057B84.c 0x80057BE8 0x80057C30 src/func_80057BE8.c 0x80057C30 0x80057C80 src/func_80057C30.c diff --git a/src/func_80057950.c b/src/func_80057950.c new file mode 100644 index 0000000..2f0235e --- /dev/null +++ b/src/func_80057950.c @@ -0,0 +1,27 @@ +/* func_80057950 — eighth/ninth member of the 0x80057xxx argument-block family (selector 9). + * + * Structurally identical to the already matched members: a 48-byte frame whose six words at + * 16-36(sp) are the outgoing argument area, a branchless 0-or--1 mask built with sltu+negu so + * that exactly ONE value is conditionally selected, the narrowed second argument placed in + * outgoing arg 9 and the other narrowed argument in arg 10, and the selector in the second + * register argument. + * + * Because the branchless form is present, the family's discriminator says exactly one distinct + * value is selected here — as against 0x80057B84, which selects two and needs a real branch. + * + * LIMITS: the selector 9, the mask 0xff and the frame layout are read from the bytes; what + * the selector selects is not observable from this body. That it IS a selector follows from the + * family's byte-identical siblings differing only in this constant — now several such pairs. + * The callee is named for its address. + */ + +void func_80057664(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7, + int a8, int a9); + +void func_80057950(int a0, int a1, int a2) +{ + int narrowed1 = a1 & 0xff; + int narrowed2 = a2 & 0xff; + + func_80057664(a0, 9, -1, narrowed1 ? a0 : 0, 0, 0, 0, 0, narrowed1, narrowed2); +} diff --git a/src/func_80057A40.c b/src/func_80057A40.c new file mode 100644 index 0000000..a606ea4 --- /dev/null +++ b/src/func_80057A40.c @@ -0,0 +1,27 @@ +/* func_80057A40 — eighth/ninth member of the 0x80057xxx argument-block family (selector 12). + * + * Structurally identical to the already matched members: a 48-byte frame whose six words at + * 16-36(sp) are the outgoing argument area, a branchless 0-or--1 mask built with sltu+negu so + * that exactly ONE value is conditionally selected, the narrowed second argument placed in + * outgoing arg 9 and the other narrowed argument in arg 10, and the selector in the second + * register argument. + * + * Because the branchless form is present, the family's discriminator says exactly one distinct + * value is selected here — as against 0x80057B84, which selects two and needs a real branch. + * + * LIMITS: the selector 12, the mask 0xff and the frame layout are read from the bytes; what + * the selector selects is not observable from this body. That it IS a selector follows from the + * family's byte-identical siblings differing only in this constant — now several such pairs. + * The callee is named for its address. + */ + +void func_80057664(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7, + int a8, int a9); + +void func_80057A40(int a0, int a1, int a2) +{ + int narrowed1 = a1 & 0xff; + int narrowed2 = a2 & 0xff; + + func_80057664(a0, 12, -1, narrowed1 ? a0 : 0, 0, 0, 0, 0, narrowed1, narrowed2); +} diff --git a/src/func_80057B30.c b/src/func_80057B30.c new file mode 100644 index 0000000..6cb2076 --- /dev/null +++ b/src/func_80057B30.c @@ -0,0 +1,50 @@ +/* func_80057B30 — 0x80057B30..0x80057B84 (84 bytes). Tenth member of the 0x80057xxx family + * (selector 13), and a variant whose REGISTER argument positions differ from the standard form. + * + * Original words: + * 27BDFFD0 addiu sp,sp,-48 + * 8FA20040 lw v0,64(sp) fifth incoming parameter (a WORD) + * 93A30044 lbu v1,68(sp) sixth incoming parameter (a BYTE) + * 30A500FF andi a1,a1,0xff + * AFA50020 sw a1,32(sp) outgoing arg 9 = narrowed a1 + * 0005282B sltu a1,zero,a1 + * 00052823 negu a1,a1 + * AFA70014 sw a3,20(sp) outgoing arg 6 = a3 + * 00C53824 and a3,a2,a1 outgoing arg 4 = a2 & mask + * 2405000D li a1,13 the selector + * 2406FFFF li a2,-1 + * AFBF0028 sw ra,40(sp) + * AFA00010 sw zero,16(sp) outgoing arg 5 = 0 + * AFA00018 sw zero,24(sp) outgoing arg 7 = 0 + * AFA2001C sw v0,28(sp) outgoing arg 8 = the fifth parameter + * 0C015D99 jal 0x80057664 + * AFA30024 _sw v1,36(sp) (delay slot) outgoing arg 10 = the sixth parameter + * + * Two incoming stack parameters, one a word and one an unsigned byte, and a masked argument + * whose **value is `a2` rather than `a0`** — so this member forwards a different source into + * arg 4 than the standard form does, while keeping the narrowed `a1` at arg 9 and the extra + * parameter at arg 10. + * + * The argument map therefore has **stable** positions (narrowed `a1` -> arg 9, the extra + * parameter -> arg 10, the selector -> arg 2, the sentinel -> arg 3) and **per-row** positions + * for everything else. That is the scope limit on the family-set lever, and it is why each + * member's register arguments are read rather than assumed even though the derivation method + * transfers. + * + * The `lw`/`lbu` pair at 64 and 68(sp) are the fifth and sixth incoming arguments, read before + * anything else — the frame is 48 bytes so the incoming area begins at 64(sp). + * + * LIMITS: the selector 13, the mask 0xff, the displacements and the frame layout are read from + * the bytes. The sixth parameter is `unsigned char` by the single `lbu`; the fifth is a word by + * `lw`. Nothing establishes what the selector selects. + */ + +void func_80057664(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7, + int a8, int a9); + +void func_80057B30(int a0, int a1, int a2, int a3, int a4, unsigned char a5) +{ + int narrowed1 = a1 & 0xff; + + func_80057664(a0, 13, -1, narrowed1 ? a2 : 0, 0, a3, 0, a4, narrowed1, a5); +}