From 0fbdb572100ecaabd2d86f5e4db0f3ee77943ac4 Mon Sep 17 00:00:00 2001 From: cecilarmitais Date: Tue, 18 Aug 2026 01:08:34 -0700 Subject: [PATCH] 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 --- asm/include/overlay_29_0234921C.inc | 2 +- asm/include/overlay_29_02349638.inc | 2 + asm/include/overlay_29_0234969C.inc | 2 + asm/include/overlay_29_023496EC.inc | 2 + asm/overlay_29_0234921C.s | 221 ---------------------------- asm/overlay_29_02349638.s | 34 +++++ asm/overlay_29_0234969C.s | 24 +++ asm/overlay_29_023496EC.s | 134 +++++++++++++++++ include/overlay_29_02349620.h | 9 ++ include/overlay_29_02349688.h | 9 ++ include/overlay_29_023496D8.h | 10 ++ main.lsf | 6 + src/overlay_29_02349620.c | 16 ++ src/overlay_29_02349688.c | 16 ++ src/overlay_29_023496D8.c | 21 +++ 15 files changed, 286 insertions(+), 222 deletions(-) create mode 100644 asm/include/overlay_29_02349638.inc create mode 100644 asm/include/overlay_29_0234969C.inc create mode 100644 asm/include/overlay_29_023496EC.inc create mode 100644 asm/overlay_29_02349638.s create mode 100644 asm/overlay_29_0234969C.s create mode 100644 asm/overlay_29_023496EC.s create mode 100644 include/overlay_29_02349620.h create mode 100644 include/overlay_29_02349688.h create mode 100644 include/overlay_29_023496D8.h create mode 100644 src/overlay_29_02349620.c create mode 100644 src/overlay_29_02349688.c create mode 100644 src/overlay_29_023496D8.c diff --git a/asm/include/overlay_29_0234921C.inc b/asm/include/overlay_29_0234921C.inc index f9ab8849..8ea4159d 100644 --- a/asm/include/overlay_29_0234921C.inc +++ b/asm/include/overlay_29_0234921C.inc @@ -1,5 +1,5 @@ #pragma once .public DUNGEON_PTR -.public GetAcceptedMission +.public FloorHasMissionMonster .public GetSpriteFileSize .public LoadMonsterSprite diff --git a/asm/include/overlay_29_02349638.inc b/asm/include/overlay_29_02349638.inc new file mode 100644 index 00000000..a00f434c --- /dev/null +++ b/asm/include/overlay_29_02349638.inc @@ -0,0 +1,2 @@ +#pragma once +.public DUNGEON_PTR diff --git a/asm/include/overlay_29_0234969C.inc b/asm/include/overlay_29_0234969C.inc new file mode 100644 index 00000000..a00f434c --- /dev/null +++ b/asm/include/overlay_29_0234969C.inc @@ -0,0 +1,2 @@ +#pragma once +.public DUNGEON_PTR diff --git a/asm/include/overlay_29_023496EC.inc b/asm/include/overlay_29_023496EC.inc new file mode 100644 index 00000000..fe5e849c --- /dev/null +++ b/asm/include/overlay_29_023496EC.inc @@ -0,0 +1,2 @@ +#pragma once +.public GetAcceptedMission diff --git a/asm/overlay_29_0234921C.s b/asm/overlay_29_0234921C.s index 043e7572..c5e15ddb 100644 --- a/asm/overlay_29_0234921C.s +++ b/asm/overlay_29_0234921C.s @@ -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 diff --git a/asm/overlay_29_02349638.s b/asm/overlay_29_02349638.s new file mode 100644 index 00000000..2a7a5c6f --- /dev/null +++ b/asm/overlay_29_02349638.s @@ -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 diff --git a/asm/overlay_29_0234969C.s b/asm/overlay_29_0234969C.s new file mode 100644 index 00000000..eb9e819c --- /dev/null +++ b/asm/overlay_29_0234969C.s @@ -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 diff --git a/asm/overlay_29_023496EC.s b/asm/overlay_29_023496EC.s new file mode 100644 index 00000000..8c1133f2 --- /dev/null +++ b/asm/overlay_29_023496EC.s @@ -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 diff --git a/include/overlay_29_02349620.h b/include/overlay_29_02349620.h new file mode 100644 index 00000000..dd1df3da --- /dev/null +++ b/include/overlay_29_02349620.h @@ -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 diff --git a/include/overlay_29_02349688.h b/include/overlay_29_02349688.h new file mode 100644 index 00000000..19e0443b --- /dev/null +++ b/include/overlay_29_02349688.h @@ -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 diff --git a/include/overlay_29_023496D8.h b/include/overlay_29_023496D8.h new file mode 100644 index 00000000..17888aae --- /dev/null +++ b/include/overlay_29_023496D8.h @@ -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 diff --git a/main.lsf b/main.lsf index 38dfabcd..34545fcf 100644 --- a/main.lsf +++ b/main.lsf @@ -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 diff --git a/src/overlay_29_02349620.c b/src/overlay_29_02349620.c new file mode 100644 index 00000000..21019de3 --- /dev/null +++ b/src/overlay_29_02349620.c @@ -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]; +} diff --git a/src/overlay_29_02349688.c b/src/overlay_29_02349688.c new file mode 100644 index 00000000..47cedfea --- /dev/null +++ b/src/overlay_29_02349688.c @@ -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; +} diff --git a/src/overlay_29_023496D8.c b/src/overlay_29_023496D8.c new file mode 100644 index 00000000..0ce7bac3 --- /dev/null +++ b/src/overlay_29_023496D8.c @@ -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; +}