diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8a913e05..932cc72a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -77,3 +77,15 @@ repos: rev: v14.0.6 hooks: - id: clang-format + +ci: + autofix_commit_msg: | + [pre-commit.ci] auto fixes from pre-commit.com hooks + + for more information, see https://pre-commit.ci + autofix_prs: true + autoupdate_branch: '' + autoupdate_commit_msg: '[pre-commit.ci] pre-commit autoupdate' + autoupdate_schedule: weekly + skip: [] + submodules: false diff --git a/base/src/get_npc_model_offset.c b/base/src/get_npc_model_offset.c new file mode 100644 index 00000000..0ffab603 --- /dev/null +++ b/base/src/get_npc_model_offset.c @@ -0,0 +1,16 @@ +#include + +uint32_t get_npc_model_offset(uint32_t item_id) { + // These values are offsets that are used to calculate the char* that contains + // the name of the .bin + // file (see: Npc/ directory in the rom) of the NPC being spawned. The exact + // way it is used is: + // char *npc = 20ddf40 + ( * 0xC) + switch (item_id) { + case 0x1: // key + return 0xC; + case 0x3: // oshus sword + return 0xE3; + } + // TODO: calculate values for rest of items +} diff --git a/base/src/main.asm b/base/src/main.asm index a944c541..d4644ba9 100644 --- a/base/src/main.asm +++ b/base/src/main.asm @@ -14,9 +14,46 @@ .arm .importobj "src/faster_boat.o" .importobj "src/fixed_random_treasure_in_shop.o" - .importobj "src/progressive_sword_check.o" + .importobj "src/progressive_sword_check.o + .importobj "src/get_npc_model_offset.o" .importobj "src/rando_settings.o" .include "_island_shop_files.asm" + + .align + @spawn_custom_item_with_nkey: + ldr r0, =0x21608a8 + ldr r0, [r0] + ldr r0, [r0] + add r0, r0, 0x2a0 + + ; Dynamically determine pointer to string of + ; nsbmd/nsbtx model. + push r0, r1, r4, r5 + mov r5, r0 + ldr r0, [r4, 0x20] + bl get_npc_model_offset + str r0, [r5, 0x10] + pop r0, r1, r4, r5 + mov r1, 0x0 + str r1, [r0] + bl 0x20c4528 + + mov r1, r0 + add r0, r4, 0x158 + ldr r2, [r0] + ldr r2, [r2, 0xc] + blx r2 + + ; Note, this instruction differs from the original code. + ; Instead of a `mov r0, 0x1` (i.e. always setting the item id + ; to 0x1 for a small key), we're loading the item id dynamically + ; from the value given in the ITGE actor in the ZMB. See + ; `spawn_custom_freestanding_item.c` for more info. + ldr r0, [r4, 0x20] + + str r0, [r4, 0x1b4] + b 0x2160798 + .endarea .org 0x54894 + 0x2004000 @@ -220,6 +257,15 @@ .close +.open "../overlay/overlay_0035.bin", 0x0215b400 + .arm + .org 0x216072c + .area 0x24, 0x00 + beq @spawn_custom_item_with_nkey + .endarea +.close + + .open "../overlay/overlay_0037.bin", 0x0215b400 .arm .org 0x216278c diff --git a/base/src/spawn_custom_freestanding_item.c b/base/src/spawn_custom_freestanding_item.c index 0823228b..221a77c3 100644 --- a/base/src/spawn_custom_freestanding_item.c +++ b/base/src/spawn_custom_freestanding_item.c @@ -2,6 +2,16 @@ #define RUPY 0x52555059 +static uint16_t get_item_id() { + uint16_t *item_id_address; + // Pull the base address of the NPCA entry's item_id off of the stack. + // This value is set in the NPCA section of the + // ZMB file in byte 0xC of an ITGE actor. + asm volatile("ldr %0, [sp, #0x4]" : "=r"(item_id_address) :); + // return the item id + return item_id_address[0x10]; +} + /** * @param param_1 - original function arg, don't modify * @param npc_type - 4 character string representing NPC type. @@ -14,19 +24,8 @@ uint16_t spawn_custom_freestanding_item(void *param_1, uint32_t npc_type, uint16_t (*spawn_npc)(void *, uint32_t, void *, uint16_t *) = (void *)0x20C3FE8; - uint16_t *item_id_address; - // pull the base address of the NPCA entry's item_id off of the stack - asm volatile("ldr %0, [sp, #0x4]" : "=r"(item_id_address) :); - - // get the item id - uint16_t item_id = item_id_address[0x10]; + uint16_t item_id = get_item_id(); - // if item_id is 0x1, continue as the vanilla game does. - if (item_id == 0x1) { - return (*spawn_npc)(param_1, npc_type, param_3, param_4); - } - // Otherwise, set rupy_type to the item_id and spawn a RUPY NPC: - // (see `extend_RUPY_npc.c` to see how this value is used) *param_4 = item_id; - return (*spawn_npc)(param_1, RUPY, param_3, param_4); + return (*spawn_npc)(param_1, npc_type, param_3, param_4); }