Decomp the fixed-point helper cluster at the end of main_020504BC.s

sub_02050EBC, SubFixedPoint, sub_02050F78, sub_02050FF8 and
BinToDecFixedPoint are the last five functions in asm/main_020504BC.s and
all operate on struct fixed_point (106 instructions). The next object in
main.lsf is src/number_util.o, which already holds their sibling
CeilFixedPoint, so extract_function.py merges rather than splits and
main.lsf is unchanged. They are landed in reverse address order so each
prepends above the last, leaving number_util.c in ascending address order
with CeilFixedPoint last.

sub_02050EBC and sub_02050F78 keep their sub_<addr> names - this is
decompilation, not identification.

A 4-byte struct fixed_point is passed and returned by value in r0, packed
as integer | fractional << 16. The stmdb sp!, {r0, r1, r2, r3} at entry is
MWCC giving the argument registers stack homes so a by-value struct
parameter can be addressed, and writing to the parameter reuses that home,
which is why SubFixedPoint and sub_02050EBC modify their first argument
and return it. The caller-side sub rX, sp, #4 idiom around these calls is
compiler-generated, not a source construct: src/dungeon_ai_movement.c
already emits it from a plain CeilFixedPoint(pokemon_info->belly).

None of the five blocks carries a region directive, so one source serves
all three regions.

Authored by Claude (Opus 5) under human direction. Confirmed by a matching
build: build/pmdsky.us/pmdsky.us.nds: OK.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
cecilarmitais
2026-09-06 12:46:31 -07:00
parent 9097cad39d
commit 33d90d0f8d
4 changed files with 70 additions and 130 deletions

View File

@@ -1,10 +1,8 @@
#pragma once
.public _0209E6BD
.public _022AB924
.public ADVENTURE_LOG_PTR
.public ARM9_UNKNOWN_DATA__NA_209E6BC
.public ComputeSpecialCounters
.public CONVERSION2_TYPE_TABLE
.public ComputeSpecialCounters
.public Copy16BitsFrom
.public Copy16BitsTo
.public CopyNStringFromId
@@ -16,3 +14,5 @@
.public StrncpySimpleNoPad
.public StrncpySimpleNoPadSafe
.public TEAM_NAME
.public _0209E6BD
.public _022AB924

View File

@@ -879,130 +879,3 @@ sub_02050E8C: ; 0x02050E8C
bl CopyBitsFrom
ldmia sp!, {r3, r4, r5, pc}
arm_func_end sub_02050E8C
arm_func_start sub_02050EBC
sub_02050EBC: ; 0x02050EBC
stmdb sp!, {r0, r1, r2, r3}
ldrsh r3, [sp, #2]
ldrsh r0, [sp, #6]
ldrsh r2, [sp]
ldrsh r1, [sp, #4]
add r0, r3, r0
strh r0, [sp, #2]
ldrsh r0, [sp, #2]
add r1, r2, r1
strh r1, [sp]
cmp r0, #0x3e8
subge r0, r0, #0x3e8
ldrgesh r1, [sp]
strgeh r0, [sp, #2]
addge r0, r1, #1
strgeh r0, [sp]
ldrh r1, [sp, #2]
ldrh r0, [sp]
orr r0, r0, r1, lsl #16
add sp, sp, #0x10
bx lr
arm_func_end sub_02050EBC
arm_func_start SubFixedPoint
SubFixedPoint: ; 0x02050F10
stmdb sp!, {r0, r1, r2, r3}
ldrsh r3, [sp, #2]
ldrsh r0, [sp, #6]
ldrsh r2, [sp]
ldrsh r1, [sp, #4]
sub r0, r3, r0
strh r0, [sp, #2]
ldrsh r0, [sp, #2]
sub r1, r2, r1
strh r1, [sp]
cmp r0, #0
addlt r0, r0, #0x3e8
ldrltsh r1, [sp]
strlth r0, [sp, #2]
sublt r0, r1, #1
strlth r0, [sp]
ldrsh r0, [sp]
cmp r0, #0
movlt r0, #0
strlth r0, [sp, #2]
strlth r0, [sp]
ldrh r1, [sp, #2]
ldrh r0, [sp]
orr r0, r0, r1, lsl #16
add sp, sp, #0x10
bx lr
arm_func_end SubFixedPoint
arm_func_start sub_02050F78
sub_02050F78: ; 0x02050F78
stmdb sp!, {r0, r1, r2, r3}
stmdb sp!, {r3}
sub sp, sp, #4
ldrsh r1, [sp, #8]
ldrsh r0, [sp, #0xc]
cmp r1, r0
ldrgth r1, [sp, #0xe]
ldrgth r0, [sp, #0xc]
orrgt r0, r0, r1, lsl #16
bgt _02050FE8
ldrlth r1, [sp, #0xa]
ldrlth r0, [sp, #8]
orrlt r0, r0, r1, lsl #16
blt _02050FE8
ldrsh r1, [sp, #0xa]
ldrsh r0, [sp, #0xe]
cmp r1, r0
ldrgth r1, [sp, #0xc]
ldrgth r0, [sp, #0xe]
strgth r1, [sp]
strgth r0, [sp, #2]
ldrleh r1, [sp, #8]
ldrleh r0, [sp, #0xa]
strleh r1, [sp]
strleh r0, [sp, #2]
ldrh r1, [sp, #2]
ldrh r0, [sp]
orr r0, r0, r1, lsl #16
_02050FE8:
add sp, sp, #4
ldmia sp!, {r3}
add sp, sp, #0x10
bx lr
arm_func_end sub_02050F78
arm_func_start sub_02050FF8
sub_02050FF8: ; 0x02050FF8
stmdb sp!, {r3}
sub sp, sp, #4
strh r0, [sp]
ldrh r0, [sp]
mov r1, #0
strh r1, [sp, #2]
orr r0, r0, r1, lsl #16
add sp, sp, #4
ldmia sp!, {r3}
bx lr
arm_func_end sub_02050FF8
arm_func_start BinToDecFixedPoint
BinToDecFixedPoint: ; 0x02051020
stmdb sp!, {r3}
sub sp, sp, #4
ldr r2, [r0, #4]
mov r1, #0x3e8
mov r0, r2, lsl #0x10
mov r0, r0, lsr #0x10
mul r1, r0, r1
mov r2, r2, lsr #0x10
mov r0, r1, lsr #0x10
strh r2, [sp]
strh r0, [sp, #2]
ldrh r1, [sp, #2]
ldrh r0, [sp]
orr r0, r0, r1, lsl #16
add sp, sp, #4
ldmia sp!, {r3}
bx lr
arm_func_end BinToDecFixedPoint

View File

@@ -3,6 +3,11 @@
#include "util.h"
struct fixed_point sub_02050EBC(struct fixed_point a, struct fixed_point b);
struct fixed_point SubFixedPoint(struct fixed_point a, struct fixed_point b);
struct fixed_point sub_02050F78(struct fixed_point a, struct fixed_point b);
struct fixed_point sub_02050FF8(s16 value);
struct fixed_point BinToDecFixedPoint(struct fixed_point_64 *val);
s32 CeilFixedPoint(struct fixed_point val_fp);
#endif //PMDSKY_NUMBER_UTIL_H

View File

@@ -1,5 +1,67 @@
#include "number_util.h"
struct fixed_point sub_02050EBC(struct fixed_point a, struct fixed_point b)
{
a.fractional += b.fractional;
a.integer += b.integer;
if (a.fractional >= 1000)
{
a.integer++;
a.fractional -= 1000;
}
return a;
}
struct fixed_point SubFixedPoint(struct fixed_point a, struct fixed_point b)
{
a.fractional -= b.fractional;
a.integer -= b.integer;
if (a.fractional < 0)
{
a.integer--;
a.fractional += 1000;
}
if (a.integer < 0)
{
a.fractional = 0;
a.integer = 0;
}
return a;
}
struct fixed_point sub_02050F78(struct fixed_point a, struct fixed_point b)
{
struct fixed_point result;
if (a.integer > b.integer)
return b;
if (a.integer < b.integer)
return a;
if (a.fractional > b.fractional)
result = b;
else
result = a;
return result;
}
struct fixed_point sub_02050FF8(s16 value)
{
struct fixed_point result;
result.integer = value;
result.fractional = 0;
return result;
}
struct fixed_point BinToDecFixedPoint(struct fixed_point_64 *val)
{
struct fixed_point result;
result.integer = val->lower >> 16;
result.fractional = ((val->lower & 0xFFFF) * 1000) >> 16;
return result;
}
s32 CeilFixedPoint(struct fixed_point val_fp)
{
if (val_fp.integer == 0)