Skip to content
Closed
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
970 changes: 489 additions & 481 deletions ASM/build/asm_symbols.txt

Large diffs are not rendered by default.

Binary file modified ASM/build/bundle.o
Binary file not shown.
404 changes: 205 additions & 199 deletions ASM/build/c_symbols.txt

Large diffs are not rendered by default.

9 changes: 6 additions & 3 deletions ASM/c/get_items.c
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ override_key_t resolve_alternative_override(override_key_t override_key)
void activate_override(override_t override) {
uint16_t resolved_item_id = resolve_upgrades(override.value.item_id);
item_row_t *item_row = get_item_row(resolved_item_id);
uint16_t resolved_text_id = resolve_text_id(item_row);

active_override = override;
if (resolved_item_id == 0xCA)
Expand All @@ -190,7 +191,7 @@ void activate_override(override_t override) {
active_override_is_outgoing = override.value.player != PLAYER_ID;
active_item_row = item_row;
active_item_action_id = item_row->action_id;
active_item_text_id = item_row->text_id;
active_item_text_id = resolved_text_id;
active_item_object_id = item_row->object_id;
active_item_graphic_id = item_row->graphic_id;
if (override.value.looks_like_item_id) {
Expand Down Expand Up @@ -743,6 +744,7 @@ uint8_t item_give_collectible(uint8_t item, z64_link_t *link, z64_actor_t *from_
uint16_t item_id = collectible_override.value.item_id;
uint16_t resolved_item_id = resolve_upgrades(item_id);
item_row_t *item_row = get_item_row(resolved_item_id);
uint16_t resolved_text_id = resolve_text_id(item_row);

// Set the collectible flag
Set_CollectibleOverrideFlag(pItem);
Expand Down Expand Up @@ -771,7 +773,7 @@ uint8_t item_give_collectible(uint8_t item, z64_link_t *link, z64_actor_t *from_
// draw message box and play get item sound (like when a skull is picked up)
z64_Audio_PlayFanFare(NA_BGM_SMALL_ITEM_GET);

z64_DisplayTextbox(&z64_game, item_row->text_id, 0);
z64_DisplayTextbox(&z64_game, resolved_text_id, 0);

// Set up
pItem->timeToLive = 15; // unk_15A is a frame timer that is decremented each frame by the main actor code.
Expand Down Expand Up @@ -801,11 +803,12 @@ void get_skulltula_token(z64_actor_t *token_actor) {

uint16_t resolved_item_id = resolve_upgrades(item_id);
item_row_t *item_row = get_item_row(resolved_item_id);
uint16_t resolved_text_id = resolve_text_id(item_row);

token_actor->draw_proc = NULL;

PLAYER_NAME_ID = player;
z64_DisplayTextbox(&z64_game, item_row->text_id, 0);
z64_DisplayTextbox(&z64_game, resolved_text_id, 0);
dispatch_item(resolved_item_id, player, &override, item_row);
}

Expand Down
434 changes: 221 additions & 213 deletions ASM/c/item_table.c

Large diffs are not rendered by default.

7 changes: 6 additions & 1 deletion ASM/c/item_table.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,13 @@ typedef enum {
/* 15 */ SKULL_CHEST_BIG,
} ChestType;

struct item_row_t;

typedef uint16_t (*upgrade_fn)(z64_file_t *save, uint16_t item_id);
typedef void (*effect_fn)(z64_file_t *save, int16_t arg1, int16_t arg2);
typedef uint16_t (*alt_text_fn)(struct item_row_t* this);

typedef struct {
typedef struct item_row_t{
int8_t base_item_id;
uint8_t action_id;
uint16_t text_id;
Expand All @@ -37,10 +40,12 @@ typedef struct {
int16_t effect_arg1;
int16_t effect_arg2;
int8_t collectible;
alt_text_fn alt_text_func;
} item_row_t;

uint16_t resolve_upgrades(uint16_t item_id);
item_row_t *get_item_row(uint16_t item_id);
void call_effect_function(item_row_t *item_row);
uint16_t resolve_text_id(item_row_t* item_row);

#endif
71 changes: 71 additions & 0 deletions ASM/c/message.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#include "z64.h"
#include "stdbool.h"

// Helper function for adding characters to the decoded message buffer
void Message_AddCharacter(MessageContext* msgCtx, void* pFont, uint32_t* pDecodedBufPos, uint32_t* pCharTexIdx, uint8_t charToAdd) {
uint32_t decodedBufPosVal = *pDecodedBufPos;
uint32_t charTexIdx = *pCharTexIdx;
msgCtx->msgBufDecoded[decodedBufPosVal++] = charToAdd; // Add the character to the output buffer, increment the output position
if(charToAdd != ' ') // Only load the character texture if it's not a space.
{
Font_LoadChar(pFont, charToAdd - ' ', charTexIdx); // Load the character texture
charTexIdx += 0x80; // Increment the texture pointer
}

// Copy our locals back to their pointers
*pDecodedBufPos = decodedBufPosVal;
*pCharTexIdx = charTexIdx;
}

// Helper function for adding integer numbers to the decoded message buffer
void Message_AddInteger(MessageContext * msgCtx, void* pFont, uint32_t* pDecodedBufPos, uint32_t* pCharTexIdx, uint32_t numToAdd) {
uint8_t digits[10];
uint8_t i = 0;

// Extract each digit. They are added, in reverse order, to digits[]
do {
digits[i] = numToAdd % 10;
numToAdd = numToAdd / 10;
i++;
}

// Loop through each digit in digits[] and add the character to the decoded buffer.
while ( numToAdd > 0 );
for(uint8_t c = i; c > 0; c--) {
Message_AddCharacter(msgCtx, pFont, pDecodedBufPos, pCharTexIdx, '0' + digits[c - 1]);
}
}

// Helper function for adding simple strings to the decoded message buffer. Does not support additional control codes.
void Message_AddString(MessageContext * msgCtx, void* pFont, uint32_t* pDecodedBufPos, uint32_t* pCharTexIdx, char* stringToAdd) {
while(*stringToAdd != 0)
{
Message_AddCharacter(msgCtx, pFont, pDecodedBufPos, pCharTexIdx, *stringToAdd);
stringToAdd++;
}
}

// Hack to add additional text control codes.
// If additional codes need to be read after the primary code, increment msgCtx->msgBufPos and index msgRaw
// To add a new control code:
// Compare currChar to the control code.
// Add text to the output buffer by performing the following:
// Call one of the above functions to add the text.
// Subtract 1 from *pDecodedBufPos
// Return true
bool Message_Decode_Additional_Control_Codes(uint8_t currChar, uint32_t* pDecodedBufPos, uint32_t* pCharTexIdx) {
MessageContext* msgCtx = &(z64_game.msgContext);
Font* pFont = &(msgCtx->font); // Get a reference to the font.
char* msgRaw = (char*)&(pFont->msgBuf); // Get a reference to the start of the raw message. Index using msgCtx->msgBufPos.

/*
// Example new control code that replaces code 0xF0 w/ a number
if(currChar == 0xF0) {
uint32_t val = 20;
Message_AddInteger(msgCtx, pFont, pDecodedBufPos, pCharTexIdx, val);
(*pDecodedBufPos)--;
return true;
}
*/
return false;
}
83 changes: 76 additions & 7 deletions ASM/c/z64.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
#define NA_SE_SY_GET_RUPY 0x4803
#define NA_SE_SY_GET_ITEM 0x4824

#define FONT_CHAR_TEX_SIZE ((16 * 16) / 2) // 16x16 I4 texture

#define OFFSETOF(structure, member) ((size_t)&(((structure *)0)->member))

typedef struct
Expand Down Expand Up @@ -1067,6 +1069,73 @@ typedef struct
char unk_04_[0x04]; /* 0x0004 */
} z64_actor_ctxt_t;

typedef struct {
/* 0x0000 */ uint32_t msgOffset;
/* 0x0004 */ uint32_t msgLength;
/* 0x0008 */ uint8_t charTexBuf[FONT_CHAR_TEX_SIZE * 120];
/* 0x3C08 */ uint8_t iconBuf[FONT_CHAR_TEX_SIZE];
/* 0x3C88 */ uint8_t fontBuf[FONT_CHAR_TEX_SIZE * 320];
union {
/* 0xDC88 */ char msgBuf[1280];
/* 0xDC88 */ uint16_t msgBufWide[640];
};
} Font; // size = 0xE188

typedef struct {
/* 0x0000 */ uint8_t view[0x128];
/* 0x0128 */ Font font;
/* 0xE2B0 */ void* textboxSegment; // original name: "fukidashiSegment"
/* 0xE2B4 */ char unk_E2B4[0x4];
/* 0xE2B8 */ void* ocarinaStaff; // original name : "info"
/* 0xE2BC */ char unk_E2BC[0x3C];
/* 0xE2F8 */ uint16_t textId;
/* 0xE2FA */ uint16_t choiceTextId;
/* 0xE2FC */ uint8_t textBoxProperties; // original name : "msg_disp_type"
/* 0xE2FD */ uint8_t textBoxType; // "Text Box Type"
/* 0xE2FE */ uint8_t textBoxPos; // text box position
/* 0xE300 */ int32_t msgLength; // original name : "msg_data"
/* 0xE304 */ uint8_t msgMode; // original name: "msg_mode"
/* 0xE305 */ char unk_E305[0x1];
/* 0xE306 */ uint8_t msgBufDecoded[200]; // decoded message buffer, may be smaller than this
/* 0xE3CE */ uint16_t msgBufPos; // original name : "rdp"
/* 0xE3D0 */ uint16_t unk_E3D0; // unused, only ever set to 0
/* 0xE3D2 */ uint16_t textDrawPos; // draw all decoded characters up to this buffer position
/* 0xE3D4 */ uint16_t decodedTextLen; // decoded message buffer length
/* 0xE3D6 */ uint16_t textUnskippable;
/* 0xE3D8 */ int16_t textPosX;
/* 0xE3DA */ int16_t textPosY;
/* 0xE3DC */ int16_t textColorR;
/* 0xE3DE */ int16_t textColorG;
/* 0xE3E0 */ int16_t textColorB;
/* 0xE3E2 */ int16_t textColorAlpha;
/* 0xE3E4 */ uint8_t textboxEndType; // original name : "select"
/* 0xE3E5 */ uint8_t choiceIndex;
/* 0xE3E6 */ uint8_t choiceNum; // textboxes that are not choice textboxes have a choiceNum of 1
/* 0xE3E7 */ uint8_t stateTimer;
/* 0xE3E8 */ uint16_t textDelayTimer;
/* 0xE3EA */ uint16_t textDelay;
/* 0xE3EA */ uint16_t lastPlayedSong; // original references : "Ocarina_Flog" , "Ocarina_Free"
/* 0xE3EE */ uint16_t ocarinaMode; // original name : "ocarina_mode"
/* 0xE3F0 */ uint16_t ocarinaAction; // original name : "ocarina_no"
/* 0xE3F2 */ uint16_t unk_E3F2; // this is like "lastPlayedSong" but set less often, original name : "chk_ocarina_no"
/* 0xE3F4 */ uint16_t unk_E3F4; // unused, only set to 0 in z_actor
/* 0xE3F6 */ uint16_t textboxBackgroundIdx;
/* 0xE3F8 */ uint8_t textboxBackgroundForeColorIdx;
/* 0xE3F8 */ uint8_t textboxBackgroundBackColorIdx;
/* 0xE3F8 */ uint8_t textboxBackgroundYOffsetIdx;
/* 0xE3F8 */ uint8_t textboxBackgroundUnkArg; // unused, set by the textbox background control character arguments
/* 0xE3FC */ char unk_E3FC[0x2];
/* 0xE3FE */ int16_t textboxColorRed;
/* 0xE400 */ int16_t textboxColorGreen;
/* 0xE402 */ int16_t textboxColorBlue;
/* 0xE404 */ int16_t textboxColorAlphaTarget;
/* 0xE406 */ int16_t textboxColorAlphaCurrent;
/* 0xE408 */ z64_actor_t* talkActor;
/* 0xE40C */ int16_t disableWarpSongs; // warp song flag set by scene commands
/* 0xE40E */ int16_t unk_E40E; // ocarina related
/* 0xE410 */ uint8_t lastOcaNoteIdx;
} MessageContext; // size = 0xE414

/* game context */
typedef struct
{
Expand Down Expand Up @@ -1135,13 +1204,9 @@ typedef struct
char unk_0E_[0x0010]; /* 0x01D58 */
void *cutscene_ptr; /* 0x01D68 */
int8_t cutscene_state; /* 0x01D6C */
char unk_0F_[0xE66F]; /* 0x01D6D */
uint8_t textbox_state_1; /* 0x103DC */
char unk_10_[0x00DF]; /* 0x103DD */
uint8_t textbox_state_2; /* 0x104BC */
char unk_11_[0x0002]; /* 0x104BD */
uint8_t textbox_state_3; /* 0x104BF */
char unk_12_[0x0272]; /* 0x104C0 */
char unk_0F_[0x036B]; /* 0x01D6D */
MessageContext msgContext; /* 0x020D8 */
char unk_12_[0x0246]; /* 0x104EC */
struct {
uint16_t unk_00_;
uint16_t fadeout;
Expand Down Expand Up @@ -1202,6 +1267,7 @@ typedef struct
/* 0x11E5F */
} z64_game_t;


typedef struct
{
char unk_00_[0x01D8]; /* 0x00000 */
Expand Down Expand Up @@ -1662,6 +1728,7 @@ typedef struct EnGSwitch
#define z64_Rand_ZeroOne_addr 0x800CDCCC
#define z64_RandSeed_addr 0x800CDCC0
#define z64_Rand_ZeroOne_addr 0x800CDCCC
#define Font_LoadChar_addr 0x8005BCE4

/* rom addresses */
#define z64_icon_item_static_vaddr 0x007BD000
Expand Down Expand Up @@ -1733,6 +1800,7 @@ typedef int32_t(*z64_ActorSetLinkIncomingItemId_proc) (z64_actor_t *actor, z64_g
typedef float (*z64_Rand_ZeroOne_proc)();
typedef void(*z64_RandSeed_proc) (uint32_t seed);
typedef float(*z64_Rand_ZeroOne_proc)();
typedef void(*Font_LoadChar_proc)(void* font, uint8_t character, uint16_t codePointIndex);

/* data */
#define z64_file_mq (*(OSMesgQueue*) z64_file_mq_addr)
Expand Down Expand Up @@ -1811,5 +1879,6 @@ typedef float(*z64_Rand_ZeroOne_proc)();
#define z64_Gfx_DrawDListOpa ((z64_Gfx_DrawDListOpa_proc)z64_Gfx_DrawDListOpa_addr)
#define z64_Math_SinS ((z64_Math_SinS_proc)z64_Math_SinS_addr)
#define z64_Rand_ZeroOne ((z64_Rand_ZeroOne_proc)z64_Rand_ZeroOne_addr)
#define Font_LoadChar ((Font_LoadChar_proc)Font_LoadChar_addr)

#endif
14 changes: 14 additions & 0 deletions ASM/src/hacks.asm
Original file line number Diff line number Diff line change
Expand Up @@ -3185,3 +3185,17 @@ skip_GS_BGS_text:
; Replaces: addiu t9, $zero, 0x3033
.orga 0xED31B8
addiu t9, $zero, 0x3036


;=========================================================================================
; Add custom message control characters
;=========================================================================================

; In Message_Decode at the last control code check (0x01 for new line)
; Replaces
; addiu at, r0, 0x0001
; bne v0, at, 0x800DC580
.headersize (0x800110A0 - 0xA87000)
.org 0x800DC568
j Message_Decode_Control_Code_Hook
nop
51 changes: 51 additions & 0 deletions ASM/src/messages.asm
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,54 @@ load_correct_message_segment:
sw t7, 0x0000(v0)
jr $ra
sw t8, 0x0004(v0)

Message_Decode_Control_Code_Hook:
; Replaced code
addiu at, r0, 0x0001
bne v0, at, @not_newline
lh t6, 0x008C(sp)
addiu t4, t6, 0x0001
j 0x800DC7E4
sh t4, 0x008C(sp)

; New Control Codes go here

; V0 = Current character
; 0x54(sp) = MessageContext
; s5 = decodedBufPos
; s4 = charTexIdx
@not_newline:
addiu sp, sp, -0x60
sw a0, 0x10(sp)
sw a1, 0x14(sp)
sw a2, 0x18(sp)
sw v0, 0x1C(sp)
sw a3, 0x20(sp)

addiu sp, sp, -0x20
sw s5, 0x10(sp) ; store decoded buffer position on the stack
sw s4, 0x14(sp) ; store charTexIdx on the stack
; lw a0, 0xD4(sp) ; load message context pointer into a0
or a0, r0, v0 ; load current character into a1
addiu a1, sp, 0x10
addiu a2, sp, 0x14
jal Message_Decode_Additional_Control_Codes
nop
lw s5, 0x10(sp) ; store decoded buffer position back into s5
lw s4, 0x14(sp)
addiu sp, sp, 0x20

lw a0, 0x10(sp)
lw a1, 0x14(sp)
lw a2, 0x18(sp)
lw a3, 0x20(sp)

beqz v0, @no_match
lw v0, 0x1C(sp)

j 0x800DC7E4
addiu sp, sp, 0x60

@no_match:
j 0x800DC580
addiu sp, sp, 0x60
4 changes: 2 additions & 2 deletions Patches.py
Original file line number Diff line number Diff line change
Expand Up @@ -2329,10 +2329,10 @@ def add_to_extended_object_table(rom, object_id, object_file):
rom.write_int32s(extended_object_table + extended_id * 8, [object_file.start, object_file.end])


item_row_struct = struct.Struct('>BBHHBBIIhhBxxx') # Match item_row_t in item_table.h
item_row_struct = struct.Struct('>BBHHBBIIhhBxxxI') # Match item_row_t in item_table.h
item_row_fields = [
'base_item_id', 'action_id', 'text_id', 'object_id', 'graphic_id', 'chest_type',
'upgrade_fn', 'effect_fn', 'effect_arg1', 'effect_arg2', 'collectible',
'upgrade_fn', 'effect_fn', 'effect_arg1', 'effect_arg2', 'collectible', 'alt_text_fn',
]

def read_rom_item(rom, item_id):
Expand Down
Loading