Decomp sub_02065050; make two script-entity fields signed

Decompile sub_02065050 (0x02065050), the resolver that rewrites a script entity
id in place and reports which storage it maps to. It redirects the four special
ids 0x2E-0x31 through SPECIAL_ACTORS, then dispatches on the entity's kind
field: kind 1 resolves the player slot from script variable 0x34, kind 2
resolves a team member from variables 0x35 and 0x36, kind 3 range-checks against
the loaded unit or adventure NPC list, and anything else handles the appointed
leader. It merges into src/main_02064FFC.c; asm/main_02065050.s splits, with
sub_0206549C moving verbatim into asm/main_0206549C.s.

Two type declarations are corrected, both diagnosed from the load instruction
rather than assumed. Storing to a field cannot reveal its signedness -- strh is
the same either way -- so neither error was observable until something read
these fields, and this is the first decompiled function that does.

enum script_entity_id gains ENTITY_NONE = -1. Under -enum min an enum with no
negative enumerator is unsigned, so the SPECIAL_ACTORS redirect slots compiled
to ldrh where the target has ldrsh. An explicit (s16) cast does not help: the
destination store is 16-bit, so the compiler folds the conversion away. The name
follows EPISODE_NONE = -1, already in this file. The sentinel was verified in
isolation, with no other change in the tree, and the ROM still matches -- it is
byte-neutral everywhere else and only affects code that reads such a field.

struct unk_020A7FF0 field_0x0 becomes s16 for the same reason. It was declared
u16 when the struct was introduced for sub_02065B14, which only reads field_0x8
-- genuinely unsigned, ldrh. Both resolvers read field_0x0 with ldrsh.

sub_02055410 is declared as taking the member index rather than void. The
argument is already in r0 from GetAppointedLeaderMemberIdx, so the call needs no
register move, which is what leaves r0 occupied across the sentinel comparison.
Declared void, the function is otherwise identical but allocates that constant
to r0 instead of r1.

The nine functions this calls that had no declaration are declared alongside;
parameter names are positional where only the call site is understood.

No comments are added to any pmd-sky file.

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

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
cecilarmitais
2026-07-22 14:26:26 -07:00
parent 4463a320b6
commit 580644e646
7 changed files with 209 additions and 323 deletions

View File

@@ -3,12 +3,9 @@
.public Debug_GetDebugFlag
.public ENTITIES
.public GetAdventureNpcIds
.public GetAppointedLeaderMemberIdx
.public GetHero
.public GetMainCharacter1
.public GetMainCharacter1MemberIdx
.public GetMainCharacter2
.public GetMainCharacter2MemberIdx
.public GetMainCharacter3
.public GetPartner
.public GetUnitNpcIds
@@ -17,7 +14,5 @@
.public SPECIAL_ACTORS
.public TEAM_MEMBER_TABLE_PTR
.public ov11_022E96E4
.public sub_02055410
.public sub_02055474
.public sub_020554D8
.public sub_02056914
.public sub_02065050

View File

@@ -1,322 +1,8 @@
.include "asm/macros.inc"
.include "main_02065050.inc"
.include "main_0206549C.inc"
.text
arm_func_start sub_02065050
sub_02065050: ; 0x02065050
stmdb sp!, {r4, r5, r6, lr}
sub sp, sp, #0x10
mov r5, r0
ldrsh r0, [r5]
mvn r4, #0
cmp r0, #0x2e
ldreq r0, _02065494 ; =SPECIAL_ACTORS
ldreqsh r0, [r0, #0x18]
streqh r0, [r5]
beq _020650B0
cmp r0, #0x2f
ldreq r0, _02065494 ; =SPECIAL_ACTORS
ldreqsh r0, [r0, #0x16]
streqh r0, [r5]
beq _020650B0
cmp r0, #0x30
ldreq r0, _02065494 ; =SPECIAL_ACTORS
ldreqsh r0, [r0, #0x14]
streqh r0, [r5]
beq _020650B0
cmp r0, #0x31
ldreq r0, _02065494 ; =SPECIAL_ACTORS
ldreqsh r0, [r0, #0x12]
streqh r0, [r5]
_020650B0:
ldrsh r2, [r5]
mvn r0, #0
cmp r2, r0
beq _0206548C
mov r0, #0xc
smulbb r1, r2, r0
ldr r0, _02065498 ; =ENTITIES
ldrsh r0, [r0, r1]
cmp r0, #1
bne _020651AC
cmp r2, #0
bne _020651A4
mov r0, #0
mov r1, #0x34
bl LoadScriptVariableValue
cmp r0, #8
addls pc, pc, r0, lsl #2
b _02065198
_020650F8: ; jump table
b _0206511C ; case 0
b _02065128 ; case 1
b _02065198 ; case 2
b _02065134 ; case 3
b _02065180 ; case 4
b _02065180 ; case 5
b _02065180 ; case 6
b _02065180 ; case 7
b _02065180 ; case 8
_0206511C:
mov r0, #1
strh r0, [r5]
b _020651A4
_02065128:
mov r0, #2
strh r0, [r5]
b _020651A4
_02065134:
bl GetAppointedLeaderMemberIdx
mov r4, r0
mvn r0, #0
cmp r4, r0
moveq r0, #1
streqh r0, [r5]
beq _020651A4
bl GetMainCharacter1MemberIdx
cmp r4, r0
moveq r0, #1
streqh r0, [r5]
beq _020651A4
bl GetMainCharacter2MemberIdx
cmp r4, r0
moveq r0, #2
streqh r0, [r5]
movne r0, #4
strneh r0, [r5]
b _020651A4
_02065180:
mov r0, #0
mov r1, #0x34
bl LoadScriptVariableValue
add r0, r0, #1
strh r0, [r5]
b _020651A4
_02065198:
mvn r0, #0
strh r0, [r5]
b _0206548C
_020651A4:
mov r4, #0
b _02065488
_020651AC:
cmp r0, #2
bne _02065330
mov r0, #0
mov r1, #0x35
bl LoadScriptVariableValue
mov r4, r0
mov r0, #0
mov r1, #0x36
bl LoadScriptVariableValue
ldrsh r2, [r5]
sub r1, r2, #0xa
mov r1, r1, lsl #0x10
mov r1, r1, asr #0x10
mov r1, r1, lsl #0x10
mov r1, r1, lsr #0x10
cmp r1, #1
bhi _020652D0
cmp r2, #0xa
bne _02065204
cmp r4, #0
moveq r4, r0
b _02065210
_02065204:
cmp r4, #0
moveq r0, #0
mov r4, r0
_02065210:
cmp r4, #0xa
addls pc, pc, r4, lsl #2
b _020652C4
_0206521C: ; jump table
b _020652C4 ; case 0
b _02065248 ; case 1
b _02065254 ; case 2
b _020652C4 ; case 3
b _02065260 ; case 4
b _020652AC ; case 5
b _020652AC ; case 6
b _020652AC ; case 7
b _020652AC ; case 8
b _020652AC ; case 9
b _020652B8 ; case 10
_02065248:
mov r0, #0xc
strh r0, [r5]
b _020652D0
_02065254:
mov r0, #0xd
strh r0, [r5]
b _020652D0
_02065260:
bl GetAppointedLeaderMemberIdx
mov r4, r0
mvn r0, #0
cmp r4, r0
moveq r0, #0xc
streqh r0, [r5]
beq _020652D0
bl GetMainCharacter1MemberIdx
cmp r4, r0
moveq r0, #0xc
streqh r0, [r5]
beq _020652D0
bl GetMainCharacter2MemberIdx
cmp r4, r0
moveq r0, #0xd
streqh r0, [r5]
movne r0, #0xf
strneh r0, [r5]
b _020652D0
_020652AC:
add r0, r4, #0xb
strh r0, [r5]
b _020652D0
_020652B8:
mov r0, #0x15
strh r0, [r5]
b _020652D0
_020652C4:
mvn r0, #0
strh r0, [r5]
b _0206548C
_020652D0:
ldrsh r0, [r5]
sub r0, r0, #0xc
cmp r0, #9
addls pc, pc, r0, lsl #2
b _02065324
_020652E4: ; jump table
b _0206530C ; case 0
b _02065314 ; case 1
b _02065324 ; case 2
b _0206531C ; case 3
b _02065324 ; case 4
b _02065324 ; case 5
b _02065324 ; case 6
b _02065324 ; case 7
b _02065324 ; case 8
b _0206531C ; case 9
_0206530C:
mov r4, #2
b _02065488
_02065314:
mov r4, #1
b _02065488
_0206531C:
mov r4, #2
b _02065488
_02065324:
mvn r0, #0
strh r0, [r5]
b _0206548C
_02065330:
cmp r0, #3
bne _02065420
cmp r2, #0x16
blt _020653A8
cmp r2, #0x19
bgt _020653A8
mov r0, #0xd
sub r4, r2, #0x16
bl OverlayIsLoaded
cmp r0, #0
beq _0206536C
bl ov11_022E96E4
cmp r0, #0
mvnne r0, #0
bne _0206548C
_0206536C:
mov r0, #5
bl Debug_GetDebugFlag
cmp r0, #0
beq _02065390
ldrsh r0, [r5]
cmp r0, #0x17
bgt _02065414
mvn r0, #0
b _0206548C
_02065390:
add r0, sp, #8
bl GetUnitNpcIds
cmp r4, r0
bge _02065414
mvn r0, #0
b _0206548C
_020653A8:
cmp r2, #0x1a
blt _02065414
cmp r2, #0x1d
bgt _02065414
mov r0, #0xd
sub r4, r2, #0x1a
bl OverlayIsLoaded
cmp r0, #0
beq _020653DC
bl ov11_022E96E4
cmp r0, #0
mvnne r0, #0
bne _0206548C
_020653DC:
mov r0, #5
bl Debug_GetDebugFlag
cmp r0, #0
beq _02065400
ldrsh r0, [r5]
cmp r0, #0x1c
bgt _02065414
mvn r0, #0
b _0206548C
_02065400:
add r0, sp, #0
bl GetAdventureNpcIds
cmp r4, r0
mvnlt r0, #0
blt _0206548C
_02065414:
mvn r0, #0
strh r0, [r5]
b _0206548C
_02065420:
bl GetAppointedLeaderMemberIdx
ldrsh r1, [r5]
mov r6, r0
cmp r1, #0x3f
bne _02065488
mvn r1, #0
cmp r6, r1
moveq r0, #0x3c
streqh r0, [r5]
beq _02065488
bl sub_02055410
cmp r0, #0
movne r0, #0x3c
strneh r0, [r5]
bne _02065488
mov r0, r6
bl sub_02055474
cmp r0, #0
movne r0, #0x3d
strneh r0, [r5]
bne _02065488
mov r0, r6
bl sub_020554D8
cmp r0, #0
movne r0, #0x3e
strneh r0, [r5]
_02065488:
mov r0, r4
_0206548C:
add sp, sp, #0x10
ldmia sp!, {r4, r5, r6, pc}
.align 2, 0
_02065494: .word SPECIAL_ACTORS
_02065498: .word ENTITIES
arm_func_end sub_02065050
arm_func_start sub_0206549C
sub_0206549C: ; 0x0206549C
stmdb sp!, {r4, r5, r6, lr}

View File

@@ -2017,6 +2017,7 @@ enum monster_id {
// Script entity IDs. While a few script entities differ between versions, the IDs are the same.
enum script_entity_id {
ENTITY_NONE = -1,
ENTITY_PLAYER = 0,
ENTITY_PLAYER_HERO = 1,
ENTITY_PLAYER_PARTNER = 2,

View File

@@ -25,9 +25,21 @@ extern u8 *_020AFC70;
void sub_0201E380(u8* a, u32* b, s16 c, s16 d);
int GetAppointedLeaderMemberIdx(void);
int GetMainCharacter1MemberIdx(void);
int GetMainCharacter2MemberIdx(void);
int OverlayIsLoaded(s32 overlay_id);
int ov11_022E96E4(void);
int GetUnitNpcIds(void* buf);
int GetAdventureNpcIds(void* buf);
int sub_02055410(int a);
int sub_02055474(int a);
int sub_020554D8(int a);
void sub_02064F94(struct unk_02064F94* a, u32* data, int count);
void sub_02064FE4(struct unk_02064F94* a, struct unk_02064FE4* b);
char* sub_02064FFC(s16 id);
int sub_02065014(s16 id);
int sub_02065050(s16* p);
#endif

View File

@@ -4,7 +4,7 @@
#include "enums.h"
struct unk_020A7FF0 {
u16 field_0x0;
s16 field_0x0;
u16 field_0x2;
char *field_0x4;
u16 field_0x8;

View File

@@ -213,7 +213,7 @@ Static main
Object src/main_0205ED84.o
Object asm/main_0205EDA4.o
Object src/main_02064FFC.o
Object asm/main_02065050.o
Object asm/main_0206549C.o
Object src/main_02065974.o
Object asm/main_02065998.o
Object src/main_02065B3C.o

View File

@@ -1,4 +1,7 @@
#include "main_02064FFC.h"
#include "main_02065B3C.h"
#include "script_variable.h"
#include "debug.h"
void sub_02064F94(struct unk_02064F94* a, u32* data, int count)
{
@@ -30,3 +33,192 @@ int sub_02065014(s16 id)
}
return 1;
}
int sub_02065050(s16* p)
{
s16 id;
int ret;
int a;
int b;
int member;
u8 unit_buf[8];
u8 adv_buf[8];
id = *p;
ret = -1;
if (id == 0x2e) {
*p = SPECIAL_ACTORS.talk_main;
} else if (id == 0x2f) {
*p = SPECIAL_ACTORS.talk_sub;
} else if (id == 0x30) {
*p = SPECIAL_ACTORS.event_npc_main;
} else if (id == 0x31) {
*p = SPECIAL_ACTORS.event_npc_sub;
}
id = *p;
if (id == -1) {
return -1;
}
if (ENTITIES[id].field_0x0 == 1) {
if (id == 0) {
switch (LoadScriptVariableValue(0, 0x34)) {
case 0:
*p = 1;
break;
case 1:
*p = 2;
break;
case 3:
member = GetAppointedLeaderMemberIdx();
if (member == -1) {
*p = 1;
break;
}
if (member == GetMainCharacter1MemberIdx()) {
*p = 1;
break;
}
if (member == GetMainCharacter2MemberIdx()) {
*p = 2;
} else {
*p = 4;
}
break;
case 4:
case 5:
case 6:
case 7:
case 8:
*p = LoadScriptVariableValue(0, 0x34) + 1;
break;
default:
*p = -1;
return -1;
}
}
ret = 0;
} else if (ENTITIES[id].field_0x0 == 2) {
a = LoadScriptVariableValue(0, 0x35);
b = LoadScriptVariableValue(0, 0x36);
id = *p;
if ((u16)(s16)(id - 0xa) <= 1) {
if (id == 0xa) {
if (a == 0) {
a = b;
}
} else {
if (a == 0) {
b = 0;
}
a = b;
}
switch (a) {
case 1:
*p = 0xc;
break;
case 2:
*p = 0xd;
break;
case 4:
member = GetAppointedLeaderMemberIdx();
if (member == -1) {
*p = 0xc;
break;
}
if (member == GetMainCharacter1MemberIdx()) {
*p = 0xc;
break;
}
if (member == GetMainCharacter2MemberIdx()) {
*p = 0xd;
} else {
*p = 0xf;
}
break;
case 5:
case 6:
case 7:
case 8:
case 9:
*p = a + 0xb;
break;
case 10:
*p = 0x15;
break;
default:
*p = -1;
return -1;
}
}
switch (*p - 0xc) {
case 0:
ret = 2;
break;
case 1:
ret = 1;
break;
case 3:
case 9:
ret = 2;
break;
case 2:
case 4:
case 5:
case 6:
case 7:
case 8:
default:
*p = -1;
return -1;
}
} else if (ENTITIES[id].field_0x0 == 3) {
if (id >= 0x16 && id <= 0x19) {
member = id - 0x16;
if (OverlayIsLoaded(0xd)) {
if (ov11_022E96E4()) {
return -1;
}
}
if (Debug_GetDebugFlag(DEBUG_FLAG_STAGE_NPC_DUMMY)) {
if (*p <= 0x17) {
return -1;
}
} else if (member < GetUnitNpcIds(unit_buf)) {
return -1;
}
} else if (id >= 0x1a && id <= 0x1d) {
member = id - 0x1a;
if (OverlayIsLoaded(0xd)) {
if (ov11_022E96E4()) {
return -1;
}
}
if (Debug_GetDebugFlag(DEBUG_FLAG_STAGE_NPC_DUMMY)) {
if (*p <= 0x1c) {
return -1;
}
} else if (member < GetAdventureNpcIds(adv_buf)) {
return -1;
}
}
*p = -1;
return -1;
} else {
member = GetAppointedLeaderMemberIdx();
if (*p == 0x3f) {
if (member == -1) {
*p = 0x3c;
} else if (sub_02055410(member)) {
*p = 0x3c;
} else if (sub_02055474(member)) {
*p = 0x3d;
} else if (sub_020554D8(member)) {
*p = 0x3e;
}
}
}
return ret;
}