diff --git a/config/regions.tsv b/config/regions.tsv index 7270f4a..9180103 100644 --- a/config/regions.tsv +++ b/config/regions.tsv @@ -184,6 +184,7 @@ 0x8007049C 0x800704BC src/func_8007049C.c 0x80072BA8 0x80072BDC src/func_80072BA8.c 0x80073250 0x80073284 src/func_80073250.c +0x80073364 0x800733C4 src/func_80073364.c 0x800734A4 0x800734DC src/func_800734A4.c 0x8007A404 0x8007A428 src/func_8007A404.c 0x8007C4A8 0x8007C4EC src/func_8007C4A8.c @@ -277,6 +278,7 @@ 0x800B2534 0x800B255C src/func_800B2534.c 0x800B3474 0x800B34A4 src/func_800B3474.c 0x800B34FC 0x800B3554 src/func_800B34FC.c +0x800B58C8 0x800B5924 src/func_800B58C8.c 0x800B5AF0 0x800B5AF8 src/func_80042088.c 0x800B5CB4 0x800B5CF8 src/func_800B5CB4.c 0x800B6BDC 0x800B6C14 src/func_800B6BDC.c diff --git a/src/func_80073364.c b/src/func_80073364.c new file mode 100644 index 0000000..d3604c7 --- /dev/null +++ b/src/func_80073364.c @@ -0,0 +1,55 @@ +/* + * func_80073364 — 96 bytes at 0x80073364..0x800733C4 + * + * Sets a flag bit on the argument, sign-extends it, resolves it to an object + * through a call, and returns whether a masked field of that object, minus one, + * is at or below a threshold. A null object returns zero. + * + * The observed instructions are: + * addiu sp,sp,-24 + * sw s0,16(sp) + * move s0,zero ; result = 0 + * ori a0,a0,0x4000 ; argument |= 0x4000 + * sll a0,a0,0x10 + * sw ra,20(sp) + * jal 0x80072D0C + * sra a0,a0,0x10 ; a0 = (short)a0 (delay slot) + * move v1,v0 ; v1 = result + * beqz v1,0x800733AC ; if (v1 == 0) return 0 + * lui v0,0xff ; v0 = 0x00FF0000 (delay slot) + * lw v1,4(v1) ; v1 = v1->word_04 + * ori v0,v0,0xff00 ; v0 = 0x00FF00FF... wait, 0xFF000000 | 0xFF00 + * and v1,v1,v0 ; v1 &= mask + * addiu v1,v1,-1 ; v1 -= 1 + * li v0,0xfeff + * sltu v0,v0,v1 ; 0xFEFF < v1 <- UNSIGNED + * xori s0,v0,0x1 ; result = !(0xFEFF < v1) + * AC: move v0,s0 + * lw ra,20(sp) + * lw s0,16(sp) + * addiu sp,sp,24 + * jr ra + * nop + * + * The `sltu`/`xori` pair is the branchless form of `!(a < b)`, so the result is + * `v1 <= 0xFEFF` after the decrement. The mask is built as `lui 0xff` ORed with + * `0xff00`, i.e. 0xFF00FF00 — note the `lui` alone is 0xFF000000, not 0xFF00. + * + * LIMITS: the flag bit (0x4000), the mask (0x00FFFF00), the threshold (0xFEFF), + * the field offset (4) and the callee are hypotheses read from the instruction + * shape; what the value means is unknown and is not guessed here. Only the compiled + * bytes are evidence. + */ + +int func_80073364(int a0) { + int result = 0; + char *p = (char *)func_80072D0C((short)(a0 | 0x4000)); + + if (p != 0) { + unsigned int v = (*(unsigned int *)(p + 4) & 0x00FFFF00u) - 1; + + result = !(0xFEFFu < v); + } + + return result; +} diff --git a/src/func_800B58C8.c b/src/func_800B58C8.c new file mode 100644 index 0000000..5ea8b56 --- /dev/null +++ b/src/func_800B58C8.c @@ -0,0 +1,51 @@ +/* + * func_800B58C8 — 92 bytes at 0x800B58C8..0x800B5924 + * + * Sign-extends two 16-bit arguments, converts each into a 16-byte scratch through + * a call, passes both scratch buffers and a third to a routine, and returns that + * routine's result. + * + * The observed instructions are: + * addiu sp,sp,-64 + * sw s0,56(sp) + * move s0,a1 ; s0 = second argument + * sll a0,a0,0x10 + * sra a0,a0,0x10 ; a0 = (short)a0 <- SIGNED 16-bit + * sw ra,60(sp) + * jal 0x80044FA4 + * addiu a1,sp,16 ; first buffer (delay slot) + * sll s0,s0,0x10 + * sra a0,s0,0x10 ; a0 = (short)s0 + * addiu s0,sp,32 ; second buffer + * jal 0x80044FA4 + * move a1,s0 ; second buffer (delay slot) + * addiu a0,sp,16 + * move a1,s0 + * jal 0x80027D00 + * addiu a2,sp,48 ; third scratch = result (delay slot) + * lw v0,48(sp) ; return the result word + * lw ra,60(sp) + * lw s0,56(sp) + * addiu sp,sp,64 + * jr ra + * nop + * + * The two `sll`/`sra` pairs show both arguments are SIGNED 16-bit values. The frame + * is 64 bytes: two 16-byte buffers at sp+16 and sp+32, a result word at sp+48, and + * `ra`/`s0` above them. + * + * LIMITS: the buffer sizes (16 each) and the two callees are hypotheses read from + * the instruction shape; what the buffers hold is unknown and is not guessed here. + * Only the compiled bytes are evidence. + */ + +int func_800B58C8(short first, short second) { + char buf1[16]; + char buf2[16]; + int result; + + func_80044FA4(first, buf1); + func_80044FA4(second, buf2); + func_80027D00(buf1, buf2, &result); + return result; +}