Decomp four more mission accessors; find the cause of the batch failure

Decompile from asm:

  ov29_02349688                 0x02349688
  SetTargetMonsterNotFoundFlag  0x023496C4
  GetTargetMonsterNotFoundFlag  0x023496D8
  GetMissionTargetEnemy         0x02349620

The first three read and write the two dungeon flags at 0x1 and 0x3;
GetMissionTargetEnemy returns enemy_species[0]. No new types.

The previous commit left thirteen functions unlanded because they failed four
checksums with no compile error, and recorded the elimination so far. Bisecting
found a one-function reproducer, GetMissionEnemyMinionGroup, and disassembling
the object the real build emits identifies the cause.

The scratch and the real build disagree, and the scratch was wrong. For
enemy_species[index + 1] the target computes the index first --
add r0, r0, #1, then add r0, r1, r0, lsl #1, then add #0x700 and ldrsh [r0,
#0x6e]. The real build folds the constant into the displacement instead, giving
add r0, r1, r0, lsl #1, add #0x700, ldrsh [r0, #0x70], one instruction shorter
and the same address. Same compiler, same flags, same C: the difference is the
context. The scratch used a cut-down struct dungeon carrying only the offsets
these functions touch, and against that struct the compiler emits the target's
form; against the real header it folds.

That invalidates the scratch verification for the whole cluster, not just this
function. Score 0 against an invented struct is not evidence about a build that
uses the real one, even when every offset and size matches -- and they do, which
was confirmed separately by compile-time assertions against the real headers.

So the thirteen are not near-matches to iterate on; they need re-verifying
against a faithful context before any C is judged. A preprocessed context is
obtainable -- mwccarm -E on a file including dungeon.h and mission.h, with
LM_LICENSE_FILE set, yields 9200 lines that reproduce the real build's view --
but that output does not yet compile as scratch context on its own, failing at a
typedef, so wiring it up is unfinished.

The four here were each verified by a matching build rather than by the scratch:
three of them alone, GetMissionTargetEnemy alone, and all four together.

No comments are added to any pmd-sky file.

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-08-18 01:08:34 -07:00
parent dfbb82363f
commit 0fbdb57210
15 changed files with 286 additions and 222 deletions

View File

@@ -1,5 +1,5 @@
#pragma once
.public DUNGEON_PTR
.public GetAcceptedMission
.public FloorHasMissionMonster
.public GetSpriteFileSize
.public LoadMonsterSprite

View File

@@ -0,0 +1,2 @@
#pragma once
.public DUNGEON_PTR

View File

@@ -0,0 +1,2 @@
#pragma once
.public DUNGEON_PTR

View File

@@ -0,0 +1,2 @@
#pragma once
.public GetAcceptedMission

View File

@@ -363,224 +363,3 @@ _02349618:
mov r0, #1
ldmia sp!, {r3, pc}
arm_func_end IsDestinationFloorWithFleeingOutlaw
arm_func_start GetMissionTargetEnemy
GetMissionTargetEnemy: ; 0x02349620
ldr r0, _02349634 ; =DUNGEON_PTR
ldr r0, [r0]
add r0, r0, #0x700
ldrsh r0, [r0, #0x6e]
bx lr
.align 2, 0
_02349634: .word DUNGEON_PTR
arm_func_end GetMissionTargetEnemy
arm_func_start GetMissionEnemyMinionGroup
GetMissionEnemyMinionGroup: ; 0x02349638
ldr r1, _02349654 ; =DUNGEON_PTR
add r0, r0, #1
ldr r1, [r1]
add r0, r1, r0, lsl #1
add r0, r0, #0x700
ldrsh r0, [r0, #0x6e]
bx lr
.align 2, 0
_02349654: .word DUNGEON_PTR
arm_func_end GetMissionEnemyMinionGroup
arm_func_start ov29_02349658
ov29_02349658: ; 0x02349658
ldr r0, _02349684 ; =DUNGEON_PTR
mov r2, #0
ldr r1, [r0]
strb r2, [r1]
ldr r1, [r0]
strb r2, [r1, #1]
ldr r1, [r0]
strb r2, [r1, #2]
ldr r0, [r0]
strb r2, [r0, #3]
bx lr
.align 2, 0
_02349684: .word DUNGEON_PTR
arm_func_end ov29_02349658
arm_func_start ov29_02349688
ov29_02349688: ; 0x02349688
ldr r1, _02349698 ; =DUNGEON_PTR
ldr r1, [r1]
strb r0, [r1, #1]
bx lr
.align 2, 0
_02349698: .word DUNGEON_PTR
arm_func_end ov29_02349688
arm_func_start ov29_0234969C
ov29_0234969C: ; 0x0234969C
ldr r1, _023496AC ; =DUNGEON_PTR
ldr r1, [r1]
strb r0, [r1, #2]
bx lr
.align 2, 0
_023496AC: .word DUNGEON_PTR
arm_func_end ov29_0234969C
arm_func_start ov29_023496B0
ov29_023496B0: ; 0x023496B0
ldr r0, _023496C0 ; =DUNGEON_PTR
ldr r0, [r0]
ldrb r0, [r0, #2]
bx lr
.align 2, 0
_023496C0: .word DUNGEON_PTR
arm_func_end ov29_023496B0
arm_func_start SetTargetMonsterNotFoundFlag
SetTargetMonsterNotFoundFlag: ; 0x023496C4
ldr r1, _023496D4 ; =DUNGEON_PTR
ldr r1, [r1]
strb r0, [r1, #3]
bx lr
.align 2, 0
_023496D4: .word DUNGEON_PTR
arm_func_end SetTargetMonsterNotFoundFlag
arm_func_start GetTargetMonsterNotFoundFlag
GetTargetMonsterNotFoundFlag: ; 0x023496D8
ldr r0, _023496E8 ; =DUNGEON_PTR
ldr r0, [r0]
ldrb r0, [r0, #3]
bx lr
.align 2, 0
_023496E8: .word DUNGEON_PTR
arm_func_end GetTargetMonsterNotFoundFlag
arm_func_start ClearMissionDestinationInfo
ClearMissionDestinationInfo: ; 0x023496EC
mov ip, #0
strb ip, [r0]
strb ip, [r0, #0x18]
strb ip, [r0, #0x17]
strb ip, [r0, #0x1a]
strh ip, [r0, #4]
strh ip, [r0, #6]
strh ip, [r0, #8]
strb ip, [r0, #0x16]
strh ip, [r0, #0xa]
strb ip, [r0, #0x1b]
strb ip, [r0, #0x1c]
strh ip, [r0, #0xc]
mov r3, ip
_02349724:
add r1, ip, #1
mov r1, r1, lsl #0x10
add r2, r0, ip, lsl #1
mov ip, r1, asr #0x10
strh r3, [r2, #0xe]
cmp ip, #3
blt _02349724
strh r3, [r0, #0x14]
bx lr
arm_func_end ClearMissionDestinationInfo
arm_func_start FloorHasMissionMonster
FloorHasMissionMonster: ; 0x02349748
ldrb r1, [r0]
cmp r1, #0
moveq r0, #0
bxeq lr
ldrb r0, [r0, #1]
cmp r0, #7
cmpne r0, #0
cmpne r0, #2
cmpne r0, #1
beq _02349780
add r0, r0, #0xf8
and r0, r0, #0xff
cmp r0, #3
bhi _02349788
_02349780:
mov r0, #1
bx lr
_02349788:
mov r0, #0
bx lr
arm_func_end FloorHasMissionMonster
#ifndef JAPAN
arm_func_start GetMissionIfActiveOnFloor
GetMissionIfActiveOnFloor: ; 0x02349790
stmdb sp!, {r4, lr}
mov r4, r0
mov r0, r1
bl GetAcceptedMission
ldrb r1, [r0]
cmp r1, #5
ldreqb r2, [r4]
ldreqb r1, [r0, #4]
cmpeq r2, r1
ldreqb r2, [r4, #1]
ldreqb r1, [r0, #5]
cmpeq r2, r1
movne r0, #0
ldmia sp!, {r4, pc}
arm_func_end GetMissionIfActiveOnFloor
#endif
arm_func_start ov29_023497C8
ov29_023497C8: ; 0x023497C8
stmdb sp!, {r4, lr}
mov ip, #0
mov r4, ip
b _02349804
_023497D8:
mov r3, r4, lsl #1
ldrsh lr, [r1, r3]
cmp lr, #0
addne r3, ip, #1
addne ip, r0, ip, lsl #1
movne r3, r3, lsl #0x10
strneh lr, [ip, #0xe]
movne ip, r3, asr #0x10
add r3, r4, #1
mov r3, r3, lsl #0x10
mov r4, r3, asr #0x10
_02349804:
cmp r4, #2
cmplt ip, r2
blt _023497D8
strh ip, [r0, #0x14]
ldmia sp!, {r4, pc}
arm_func_end ov29_023497C8
arm_func_start ov29_02349818
ov29_02349818: ; 0x02349818
stmdb sp!, {r4, lr}
mov r4, #0
add ip, r4, #1
mov ip, ip, lsl #0x10
strh r1, [r0, #0xe]
cmp r2, #0
mov ip, ip, asr #0x10
beq _02349874
b _02349868
_0234983C:
mov r1, r4, lsl #1
ldrsh lr, [r2, r1]
cmp lr, #0
addne r1, ip, #1
addne ip, r0, ip, lsl #1
movne r1, r1, lsl #0x10
strneh lr, [ip, #0xe]
movne ip, r1, asr #0x10
add r1, r4, #1
mov r1, r1, lsl #0x10
mov r4, r1, asr #0x10
_02349868:
cmp r4, #2
cmplt ip, r3
blt _0234983C
_02349874:
strh ip, [r0, #0x14]
ldmia sp!, {r4, pc}
arm_func_end ov29_02349818

34
asm/overlay_29_02349638.s Normal file
View File

@@ -0,0 +1,34 @@
.include "asm/macros.inc"
.include "overlay_29_02349638.inc"
.text
arm_func_start GetMissionEnemyMinionGroup
GetMissionEnemyMinionGroup: ; 0x02349638
ldr r1, _02349654 ; =DUNGEON_PTR
add r0, r0, #1
ldr r1, [r1]
add r0, r1, r0, lsl #1
add r0, r0, #0x700
ldrsh r0, [r0, #0x6e]
bx lr
.align 2, 0
_02349654: .word DUNGEON_PTR
arm_func_end GetMissionEnemyMinionGroup
arm_func_start ov29_02349658
ov29_02349658: ; 0x02349658
ldr r0, _02349684 ; =DUNGEON_PTR
mov r2, #0
ldr r1, [r0]
strb r2, [r1]
ldr r1, [r0]
strb r2, [r1, #1]
ldr r1, [r0]
strb r2, [r1, #2]
ldr r0, [r0]
strb r2, [r0, #3]
bx lr
.align 2, 0
_02349684: .word DUNGEON_PTR
arm_func_end ov29_02349658

24
asm/overlay_29_0234969C.s Normal file
View File

@@ -0,0 +1,24 @@
.include "asm/macros.inc"
.include "overlay_29_0234969C.inc"
.text
arm_func_start ov29_0234969C
ov29_0234969C: ; 0x0234969C
ldr r1, _023496AC ; =DUNGEON_PTR
ldr r1, [r1]
strb r0, [r1, #2]
bx lr
.align 2, 0
_023496AC: .word DUNGEON_PTR
arm_func_end ov29_0234969C
arm_func_start ov29_023496B0
ov29_023496B0: ; 0x023496B0
ldr r0, _023496C0 ; =DUNGEON_PTR
ldr r0, [r0]
ldrb r0, [r0, #2]
bx lr
.align 2, 0
_023496C0: .word DUNGEON_PTR
arm_func_end ov29_023496B0

134
asm/overlay_29_023496EC.s Normal file
View File

@@ -0,0 +1,134 @@
.include "asm/macros.inc"
.include "overlay_29_023496EC.inc"
.text
arm_func_start ClearMissionDestinationInfo
ClearMissionDestinationInfo: ; 0x023496EC
mov ip, #0
strb ip, [r0]
strb ip, [r0, #0x18]
strb ip, [r0, #0x17]
strb ip, [r0, #0x1a]
strh ip, [r0, #4]
strh ip, [r0, #6]
strh ip, [r0, #8]
strb ip, [r0, #0x16]
strh ip, [r0, #0xa]
strb ip, [r0, #0x1b]
strb ip, [r0, #0x1c]
strh ip, [r0, #0xc]
mov r3, ip
_02349724:
add r1, ip, #1
mov r1, r1, lsl #0x10
add r2, r0, ip, lsl #1
mov ip, r1, asr #0x10
strh r3, [r2, #0xe]
cmp ip, #3
blt _02349724
strh r3, [r0, #0x14]
bx lr
arm_func_end ClearMissionDestinationInfo
arm_func_start FloorHasMissionMonster
FloorHasMissionMonster: ; 0x02349748
ldrb r1, [r0]
cmp r1, #0
moveq r0, #0
bxeq lr
ldrb r0, [r0, #1]
cmp r0, #7
cmpne r0, #0
cmpne r0, #2
cmpne r0, #1
beq _02349780
add r0, r0, #0xf8
and r0, r0, #0xff
cmp r0, #3
bhi _02349788
_02349780:
mov r0, #1
bx lr
_02349788:
mov r0, #0
bx lr
arm_func_end FloorHasMissionMonster
#ifndef JAPAN
arm_func_start GetMissionIfActiveOnFloor
GetMissionIfActiveOnFloor: ; 0x02349790
stmdb sp!, {r4, lr}
mov r4, r0
mov r0, r1
bl GetAcceptedMission
ldrb r1, [r0]
cmp r1, #5
ldreqb r2, [r4]
ldreqb r1, [r0, #4]
cmpeq r2, r1
ldreqb r2, [r4, #1]
ldreqb r1, [r0, #5]
cmpeq r2, r1
movne r0, #0
ldmia sp!, {r4, pc}
arm_func_end GetMissionIfActiveOnFloor
#endif
arm_func_start ov29_023497C8
ov29_023497C8: ; 0x023497C8
stmdb sp!, {r4, lr}
mov ip, #0
mov r4, ip
b _02349804
_023497D8:
mov r3, r4, lsl #1
ldrsh lr, [r1, r3]
cmp lr, #0
addne r3, ip, #1
addne ip, r0, ip, lsl #1
movne r3, r3, lsl #0x10
strneh lr, [ip, #0xe]
movne ip, r3, asr #0x10
add r3, r4, #1
mov r3, r3, lsl #0x10
mov r4, r3, asr #0x10
_02349804:
cmp r4, #2
cmplt ip, r2
blt _023497D8
strh ip, [r0, #0x14]
ldmia sp!, {r4, pc}
arm_func_end ov29_023497C8
arm_func_start ov29_02349818
ov29_02349818: ; 0x02349818
stmdb sp!, {r4, lr}
mov r4, #0
add ip, r4, #1
mov ip, ip, lsl #0x10
strh r1, [r0, #0xe]
cmp r2, #0
mov ip, ip, asr #0x10
beq _02349874
b _02349868
_0234983C:
mov r1, r4, lsl #1
ldrsh lr, [r2, r1]
cmp lr, #0
addne r1, ip, #1
addne ip, r0, ip, lsl #1
movne r1, r1, lsl #0x10
strneh lr, [ip, #0xe]
movne ip, r1, asr #0x10
add r1, r4, #1
mov r1, r1, lsl #0x10
mov r4, r1, asr #0x10
_02349868:
cmp r4, #2
cmplt ip, r3
blt _0234983C
_02349874:
strh ip, [r0, #0x14]
ldmia sp!, {r4, pc}
arm_func_end ov29_02349818

View File

@@ -0,0 +1,9 @@
#ifndef PMDSKY_OVERLAY_29_02349620_H
#define PMDSKY_OVERLAY_29_02349620_H
#include "dungeon.h"
#include "util.h"
enum monster_id GetMissionTargetEnemy(void);
#endif

View File

@@ -0,0 +1,9 @@
#ifndef PMDSKY_OVERLAY_29_02349688_H
#define PMDSKY_OVERLAY_29_02349688_H
#include "dungeon.h"
#include "util.h"
void ov29_02349688(bool8 value);
#endif

View File

@@ -0,0 +1,10 @@
#ifndef PMDSKY_OVERLAY_29_023496D8_H
#define PMDSKY_OVERLAY_29_023496D8_H
#include "dungeon.h"
#include "util.h"
void SetTargetMonsterNotFoundFlag(bool8 value);
bool8 GetTargetMonsterNotFoundFlag(void);
#endif

View File

@@ -1038,6 +1038,12 @@ Overlay OVY_29
Object asm/overlay_29_023491C4.o
Object src/overlay_29_02349208.o
Object asm/overlay_29_0234921C.o
Object src/overlay_29_02349620.o
Object asm/overlay_29_02349638.o
Object src/overlay_29_02349688.o
Object asm/overlay_29_0234969C.o
Object src/overlay_29_023496D8.o
Object asm/overlay_29_023496EC.o
Object src/overlay_29_0234987C.o
Object asm/overlay_29_023498A0.o
Object src/overlay_29_0234AEA4.o

16
src/overlay_29_02349620.c Normal file
View File

@@ -0,0 +1,16 @@
#include "overlay_29_02349620.h"
#include "dungeon.h"
#include "mission.h"
extern struct dungeon *DUNGEON_PTR;
void ClearMissionDestinationInfo(struct mission_destination_info *info);
s32 GetFirstExperienceLockedTeamMember(void);
bool8 FloorHasMissionMonster(struct mission_destination_info *info);
bool8 IsCurrentMissionType(enum mission_type type);
bool8 IsCurrentMissionTypeExact(enum mission_type type, u8 subtype);
enum monster_id GetMissionTargetEnemy(void)
{
return DUNGEON_PTR->mission_destination.enemy_species[0];
}

16
src/overlay_29_02349688.c Normal file
View File

@@ -0,0 +1,16 @@
#include "overlay_29_02349688.h"
#include "dungeon.h"
#include "mission.h"
extern struct dungeon *DUNGEON_PTR;
void ClearMissionDestinationInfo(struct mission_destination_info *info);
s32 GetFirstExperienceLockedTeamMember(void);
bool8 FloorHasMissionMonster(struct mission_destination_info *info);
bool8 IsCurrentMissionType(enum mission_type type);
bool8 IsCurrentMissionTypeExact(enum mission_type type, u8 subtype);
void ov29_02349688(bool8 value)
{
DUNGEON_PTR->target_enemy_defeated_message = value;
}

21
src/overlay_29_023496D8.c Normal file
View File

@@ -0,0 +1,21 @@
#include "overlay_29_023496D8.h"
#include "dungeon.h"
#include "mission.h"
extern struct dungeon *DUNGEON_PTR;
void ClearMissionDestinationInfo(struct mission_destination_info *info);
s32 GetFirstExperienceLockedTeamMember(void);
bool8 FloorHasMissionMonster(struct mission_destination_info *info);
bool8 IsCurrentMissionType(enum mission_type type);
bool8 IsCurrentMissionTypeExact(enum mission_type type, u8 subtype);
void SetTargetMonsterNotFoundFlag(bool8 value)
{
DUNGEON_PTR->target_monster_not_found_flag = value;
}
bool8 GetTargetMonsterNotFoundFlag(void)
{
return DUNGEON_PTR->target_monster_not_found_flag;
}