Decomp sub_0206549C; make monster_id and a third field signed

Decompile sub_0206549C (0x0206549C), which completes the actor cluster. It calls
sub_02065050 to resolve the entity id in place, then maps the result to a
monster id written through its second argument: entity kinds of 3 resolve
against the loaded unit or adventure NPC list, and everything else dispatches
through a switch over the script entity ids, reading team members, script
variables or SPECIAL_ACTORS slots. It merges into src/main_02064FFC.c, which
removes the last of asm/main_0206549C.s; main.lsf drops the object.

enum monster_id gains MONSTER_INVALID = -1, for the same reason
enum script_entity_id gained ENTITY_NONE in the previous commit. This function
reads nine SPECIAL_ACTORS slots of that type with ldrsh, and an enum with no
negative enumerator is unsigned under -enum min, so those compiled to ldrh. The
name avoids MONSTER_NONE, which the _MONSTER_ID_GENDERED macro already defines
as 0. The sentinel was verified in isolation -- added alone, with nothing else
in the tree modified -- and the ROM still matches, so it is byte-neutral for all
existing code and only affects what reads such a field.

struct unk_020A7FF0 field_0x2 becomes s16 on the same evidence: the switch's
default case reads it with ldrsh. That is the third field corrected this way,
after field_0x0 and the script_entity_id slots, and the reason they all surfaced
late is that storing to a field cannot reveal its signedness.

struct unk_020B0A48 is declared for the 0x44-byte records that
TEAM_MEMBER_TABLE_PTR points at, named for that pointer's address, which is
derived by counting to the next label in the data. GetMainCharacter1,
GetMainCharacter2, GetMainCharacter3, GetHero, GetPartner and sub_02056914 all
return it, and none of them had a declaration.

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:45:20 -07:00
parent 580644e646
commit 39a8db1b00
7 changed files with 185 additions and 375 deletions

View File

@@ -1,18 +0,0 @@
#pragma once
.public ARM9_UNKNOWN_TABLE__NA_20A68BC
.public Debug_GetDebugFlag
.public ENTITIES
.public GetAdventureNpcIds
.public GetHero
.public GetMainCharacter1
.public GetMainCharacter2
.public GetMainCharacter3
.public GetPartner
.public GetUnitNpcIds
.public LoadScriptVariableValue
.public OverlayIsLoaded
.public SPECIAL_ACTORS
.public TEAM_MEMBER_TABLE_PTR
.public ov11_022E96E4
.public sub_02056914
.public sub_02065050

View File

@@ -1,355 +0,0 @@
.include "asm/macros.inc"
.include "main_0206549C.inc"
.text
arm_func_start sub_0206549C
sub_0206549C: ; 0x0206549C
stmdb sp!, {r4, r5, r6, lr}
sub sp, sp, #0x10
mov r6, r0
mov r5, r1
bl sub_02065050
mov r4, r0
mov r0, #0
strh r0, [r5]
ldrsh lr, [r6]
sub r1, r0, #1
cmp lr, r1
subeq r0, r0, #1
beq _0206595C
mov r1, #0xc
smulbb r3, lr, r1
ldr ip, _02065964 ; =ENTITIES
ldrsh r2, [ip, r3]
add r3, ip, r3
cmp r2, #3
bne _020656B4
cmp lr, #0x16
blt _020655BC
cmp lr, #0x19
bgt _020655BC
mov r0, #0xd
sub r4, lr, #0x16
bl OverlayIsLoaded
cmp r0, #0
beq _02065540
bl ov11_022E96E4
cmp r0, #0
beq _02065540
ldr r0, _02065968 ; =ARM9_UNKNOWN_TABLE__NA_20A68BC
mov r1, r4, lsl #1
ldrsh r0, [r0, r1]
strh r0, [r5]
cmp r0, #0
mvneq r0, #0
streqh r0, [r6]
mvn r0, #0
b _0206595C
_02065540:
mov r0, #5
bl Debug_GetDebugFlag
cmp r0, #0
beq _02065580
ldrsh r0, [r6]
cmp r0, #0x16
moveq r0, #0x5f
streqh r0, [r5]
subeq r0, r0, #0x60
beq _0206595C
cmp r0, #0x17
bne _020656A8
mov r0, #0x22
strh r0, [r5]
sub r0, r0, #0x23
b _0206595C
_02065580:
add r0, sp, #8
bl GetUnitNpcIds
cmp r4, r0
bge _020656A8
ldr r0, _0206596C ; =TEAM_MEMBER_TABLE_PTR
add r1, sp, #8
mov r2, r4, lsl #1
ldrsh r2, [r1, r2]
ldr r3, [r0]
mov r1, #0x44
sub r0, r1, #0x45
smlabb r1, r2, r1, r3
ldrsh r1, [r1, #4]
strh r1, [r5]
b _0206595C
_020655BC:
cmp lr, #0x1a
blt _020656A8
cmp lr, #0x1d
bgt _020656A8
mov r0, #0xd
sub r4, lr, #0x1a
bl OverlayIsLoaded
cmp r0, #0
beq _02065610
bl ov11_022E96E4
cmp r0, #0
beq _02065610
ldr r0, _02065968 ; =ARM9_UNKNOWN_TABLE__NA_20A68BC
mov r1, r4, lsl #1
ldrsh r0, [r0, r1]
strh r0, [r5]
cmp r0, #0
mvneq r0, #0
streqh r0, [r6]
mvn r0, #0
b _0206595C
_02065610:
mov r0, #5
bl Debug_GetDebugFlag
cmp r0, #0
beq _0206566C
ldrsh r0, [r6]
cmp r0, #0x1a
bne _02065640
bl GetPartner
ldrsh r1, [r0, #4]
mvn r0, #0
strh r1, [r5]
b _0206595C
_02065640:
cmp r0, #0x1b
moveq r0, #0x5f
streqh r0, [r5]
subeq r0, r0, #0x60
beq _0206595C
cmp r0, #0x1c
bne _020656A8
mov r0, #0x22
strh r0, [r5]
sub r0, r0, #0x23
b _0206595C
_0206566C:
add r0, sp, #0
bl GetAdventureNpcIds
cmp r4, r0
bge _020656A8
ldr r0, _0206596C ; =TEAM_MEMBER_TABLE_PTR
add r1, sp, #0
mov r2, r4, lsl #1
ldrsh r2, [r1, r2]
ldr r3, [r0]
mov r1, #0x44
sub r0, r1, #0x45
smlabb r1, r2, r1, r3
ldrsh r1, [r1, #4]
strh r1, [r5]
b _0206595C
_020656A8:
mvn r0, #0
strh r0, [r6]
b _0206595C
_020656B4:
cmp lr, #0x35
bgt _02065734
bge _020658A0
cmp lr, #0x32
bgt _02065718
bge _02065860
cmp lr, #0xf
addls pc, pc, lr, lsl #2
b _02065948
_020656D8: ; jump table
b _02065948 ; case 0
b _02065798 ; case 1
b _020657A8 ; case 2
b _020657B8 ; case 3
b _020657C8 ; case 4
b _02065948 ; case 5
b _02065948 ; case 6
b _02065948 ; case 7
b _02065948 ; case 8
b _02065948 ; case 9
b _02065948 ; case 10
b _02065948 ; case 11
b _02065798 ; case 12
b _020657A8 ; case 13
b _020657B8 ; case 14
b _020657C8 ; case 15
_02065718:
cmp lr, #0x33
bgt _02065728
beq _02065880
b _02065948
_02065728:
cmp lr, #0x34
beq _02065920
b _02065948
_02065734:
cmp lr, #0x37
bgt _0206574C
bge _020658E0
cmp lr, #0x36
beq _020658C0
b _02065948
_0206574C:
cmp lr, #0x38
bgt _0206575C
beq _02065900
b _02065948
_0206575C:
sub r2, lr, #0x39
cmp r2, #0xa
addls pc, pc, r2, lsl #2
b _02065948
_0206576C: ; jump table
b _02065840 ; case 0
b _02065818 ; case 1
b _0206582C ; case 2
b _02065798 ; case 3
b _020657A8 ; case 4
b _020657B8 ; case 5
b _020657C8 ; case 6
b _020657D8 ; case 7
b _020657E8 ; case 8
b _020657F8 ; case 9
b _02065808 ; case 10
_02065798:
bl GetMainCharacter1
ldrsh r0, [r0, #4]
strh r0, [r5]
b _02065958
_020657A8:
bl GetMainCharacter2
ldrsh r0, [r0, #4]
strh r0, [r5]
b _02065958
_020657B8:
bl GetMainCharacter3
ldrsh r0, [r0, #4]
strh r0, [r5]
b _02065958
_020657C8:
bl sub_02056914
ldrsh r0, [r0, #4]
strh r0, [r5]
b _02065958
_020657D8:
bl GetHero
ldrsh r0, [r0, #4]
strh r0, [r5]
b _02065958
_020657E8:
bl GetPartner
ldrsh r0, [r0, #4]
strh r0, [r5]
b _02065958
_020657F8:
mov r1, #0x3e
bl LoadScriptVariableValue
strh r0, [r5]
b _02065958
_02065808:
mov r1, #0x40
bl LoadScriptVariableValue
strh r0, [r5]
b _02065958
_02065818:
ldr r2, _02065970 ; =SPECIAL_ACTORS
sub r0, r1, #0xd
ldrsh r1, [r2, #0xa]
strh r1, [r5]
b _0206595C
_0206582C:
ldr r2, _02065970 ; =SPECIAL_ACTORS
sub r0, r1, #0xd
ldrsh r1, [r2, #4]
strh r1, [r5]
b _0206595C
_02065840:
ldr r0, _02065970 ; =SPECIAL_ACTORS
ldrsh r0, [r0, #0xc]
cmp r0, #0
strneh r0, [r5]
subeq r0, r1, #0xd
streqh r0, [r6]
mvn r0, #0
b _0206595C
_02065860:
ldr r0, _02065970 ; =SPECIAL_ACTORS
ldrsh r0, [r0, #0x10]
strh r0, [r5]
cmp r0, #0
subeq r0, r1, #0xd
streqh r0, [r6]
mvn r0, #0
b _0206595C
_02065880:
ldr r0, _02065970 ; =SPECIAL_ACTORS
ldrsh r0, [r0, #0xe]
strh r0, [r5]
cmp r0, #0
mvneq r0, #0
streqh r0, [r6]
mvn r0, #0
b _0206595C
_020658A0:
ldr r0, _02065970 ; =SPECIAL_ACTORS
ldrsh r0, [r0, #2]
strh r0, [r5]
cmp r0, #0
subeq r0, r1, #0xd
streqh r0, [r6]
mvn r0, #0
b _0206595C
_020658C0:
ldr r0, _02065970 ; =SPECIAL_ACTORS
ldrsh r0, [r0]
strh r0, [r5]
cmp r0, #0
subeq r0, r1, #0xd
streqh r0, [r6]
mvn r0, #0
b _0206595C
_020658E0:
ldr r0, _02065970 ; =SPECIAL_ACTORS
ldrsh r0, [r0, #8]
strh r0, [r5]
cmp r0, #0
subeq r0, r1, #0xd
streqh r0, [r6]
mvn r0, #0
b _0206595C
_02065900:
ldr r0, _02065970 ; =SPECIAL_ACTORS
ldrsh r0, [r0, #6]
strh r0, [r5]
cmp r0, #0
subeq r0, r1, #0xd
streqh r0, [r6]
mvn r0, #0
b _0206595C
_02065920:
mov r0, #0
mov r1, #0x44
bl LoadScriptVariableValue
strh r0, [r5]
ldrsh r0, [r5]
cmp r0, #0
mvneq r0, #0
streqh r0, [r6]
mvn r0, #0
b _0206595C
_02065948:
ldrsh r0, [r5]
cmp r0, #0
ldreqsh r0, [r3, #2]
streqh r0, [r5]
_02065958:
mov r0, r4
_0206595C:
add sp, sp, #0x10
ldmia sp!, {r4, r5, r6, pc}
.align 2, 0
_02065964: .word ENTITIES
_02065968: .word ARM9_UNKNOWN_TABLE__NA_20A68BC
_0206596C: .word TEAM_MEMBER_TABLE_PTR
_02065970: .word SPECIAL_ACTORS
arm_func_end sub_0206549C

View File

@@ -1412,6 +1412,7 @@ enum shopkeeper_mode {
// Monster ID. Add 600 to the base value to get secondary genders (typically female).
enum monster_id {
MONSTER_INVALID = -1,
_MONSTER_ID_GENDERED(NONE, 0),
_MONSTER_ID_GENDERED(BULBASAUR, 1),
_MONSTER_ID_GENDERED(IVYSAUR, 2),

View File

@@ -20,8 +20,16 @@ struct unk_020A5488 {
char *field_0x8;
};
struct unk_020B0A48 {
u8 field_0x0[4];
s16 field_0x4;
u8 field_0x6[0x3e];
};
extern struct unk_020A5488 EVENTS[];
extern u8 *_020AFC70;
extern s16 ARM9_UNKNOWN_TABLE__NA_20A68BC[];
extern struct unk_020B0A48 *TEAM_MEMBER_TABLE_PTR;
void sub_0201E380(u8* a, u32* b, s16 c, s16 d);
@@ -35,11 +43,18 @@ int GetAdventureNpcIds(void* buf);
int sub_02055410(int a);
int sub_02055474(int a);
int sub_020554D8(int a);
struct unk_020B0A48* GetMainCharacter1(void);
struct unk_020B0A48* GetMainCharacter2(void);
struct unk_020B0A48* GetMainCharacter3(void);
struct unk_020B0A48* GetHero(void);
struct unk_020B0A48* GetPartner(void);
struct unk_020B0A48* sub_02056914(void);
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);
int sub_0206549C(s16* p, s16* out);
#endif

View File

@@ -5,7 +5,7 @@
struct unk_020A7FF0 {
s16 field_0x0;
u16 field_0x2;
s16 field_0x2;
char *field_0x4;
u16 field_0x8;
u8 field_0xa;

View File

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

View File

@@ -222,3 +222,171 @@ int sub_02065050(s16* p)
}
return ret;
}
int sub_0206549C(s16* p, s16* out)
{
int ret;
s16 id;
int i;
struct unk_020A7FF0 *e;
s16 unit_buf[4];
s16 adv_buf[4];
ret = sub_02065050(p);
*out = 0;
id = *p;
if (id == -1) {
return -1;
}
e = &ENTITIES[id];
if (e->field_0x0 == 3) {
if (id >= 0x16 && id <= 0x19) {
i = id - 0x16;
if (OverlayIsLoaded(0xd) && ov11_022E96E4()) {
*out = ARM9_UNKNOWN_TABLE__NA_20A68BC[i];
if (*out == 0) {
*p = -1;
}
return -1;
}
if (Debug_GetDebugFlag(DEBUG_FLAG_STAGE_NPC_DUMMY)) {
if (*p == 0x16) {
*out = 0x5f;
return -1;
}
if (*p == 0x17) {
*out = 0x22;
return -1;
}
} else if (i < GetUnitNpcIds(unit_buf)) {
*out = TEAM_MEMBER_TABLE_PTR[unit_buf[i]].field_0x4;
return -1;
}
} else if (id >= 0x1a && id <= 0x1d) {
i = id - 0x1a;
if (OverlayIsLoaded(0xd) && ov11_022E96E4()) {
*out = ARM9_UNKNOWN_TABLE__NA_20A68BC[i];
if (*out == 0) {
*p = -1;
}
return -1;
}
if (Debug_GetDebugFlag(DEBUG_FLAG_STAGE_NPC_DUMMY)) {
if (*p == 0x1a) {
*out = GetPartner()->field_0x4;
return -1;
}
if (*p == 0x1b) {
*out = 0x5f;
return -1;
}
if (*p == 0x1c) {
*out = 0x22;
return -1;
}
} else if (i < GetAdventureNpcIds(adv_buf)) {
*out = TEAM_MEMBER_TABLE_PTR[adv_buf[i]].field_0x4;
return -1;
}
}
*p = -1;
return -1;
}
switch (id) {
case 1:
case 12:
case 0x3c:
*out = GetMainCharacter1()->field_0x4;
break;
case 2:
case 13:
case 0x3d:
*out = GetMainCharacter2()->field_0x4;
break;
case 3:
case 14:
case 0x3e:
*out = GetMainCharacter3()->field_0x4;
break;
case 4:
case 15:
case 0x3f:
*out = sub_02056914()->field_0x4;
break;
case 0x40:
*out = GetHero()->field_0x4;
break;
case 0x41:
*out = GetPartner()->field_0x4;
break;
case 0x42:
*out = LoadScriptVariableValue(0, 0x3e);
break;
case 0x43:
*out = LoadScriptVariableValue(0, 0x40);
break;
case 0x3a:
*out = SPECIAL_ACTORS.demo_hero;
return -1;
case 0x3b:
*out = SPECIAL_ACTORS.demo_partner;
return -1;
case 0x39:
if (SPECIAL_ACTORS.new_friend != 0) {
*out = SPECIAL_ACTORS.new_friend;
} else {
*p = -1;
}
return -1;
case 0x32:
*out = SPECIAL_ACTORS.random_request_npc01;
if (*out == 0) {
*p = -1;
}
return -1;
case 0x33:
*out = SPECIAL_ACTORS.random_request_npc02;
if (*out == 0) {
*p = -1;
}
return -1;
case 0x35:
*out = SPECIAL_ACTORS.event_npc01;
if (*out == 0) {
*p = -1;
}
return -1;
case 0x36:
*out = SPECIAL_ACTORS.event_npc02;
if (*out == 0) {
*p = -1;
}
return -1;
case 0x37:
*out = SPECIAL_ACTORS.event_npc03;
if (*out == 0) {
*p = -1;
}
return -1;
case 0x38:
*out = SPECIAL_ACTORS.event_npc04;
if (*out == 0) {
*p = -1;
}
return -1;
case 0x34:
*out = LoadScriptVariableValue(0, 0x44);
if (*out == 0) {
*p = -1;
}
return -1;
default:
if (*out == 0) {
*out = e->field_0x2;
}
break;
}
return ret;
}