Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
16 changes: 16 additions & 0 deletions base/src/get_npc_model_offset.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#include <stdint.h>

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 + (<return_value> * 0xC)
switch (item_id) {
case 0x1: // key
return 0xC;
case 0x3: // oshus sword
return 0xE3;
}
// TODO: calculate values for rest of items
}
48 changes: 47 additions & 1 deletion base/src/main.asm
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
25 changes: 12 additions & 13 deletions base/src/spawn_custom_freestanding_item.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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);
}