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
2,956 changes: 1,495 additions & 1,461 deletions ASM/build/asm_symbols.txt

Large diffs are not rendered by default.

Binary file modified ASM/build/bundle.o
Binary file not shown.
1,204 changes: 615 additions & 589 deletions ASM/build/c_symbols.txt

Large diffs are not rendered by default.

235 changes: 235 additions & 0 deletions ASM/c/hints.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
#include <stdbool.h>
#include "dungeon_info.h"
#include "gfx.h"
#include "text.h"
#include "z64.h"
#include "dpad.h"
#include "hints.h"

bool update_first_time = false;
uint8_t current_hint_index = 0;
uint8_t menu_hint_cooldown = 20;
uint32_t hint_textbox_ids[40];
int8_t hint_textbox_types[40];

uint32_t *current_hints_array = NULL;
uint32_t hint_always_ids[10];
uint32_t hint_foolish_ids[10];
uint32_t hint_goals_ids[10];
uint32_t hint_sometimes_ids[10];
uint8_t hint_total_found[4];

menu_category_t menu_hints_categories[] = {
{ 0, "Always"},
{ 1, "Foolish"},
{ 2, "Goals"},
{ 3, "Sometimes"},
};

bool hint_menu_is_drawn() {
return show_hint_info;
}

void init_hints_ids() {
for (uint8_t i = 0; i < 40; i++) {
hint_textbox_ids[i] = CFG_HINTS_IDS_AND_TYPES[2*i] + 1000;
hint_textbox_types[i] = CFG_HINTS_IDS_AND_TYPES[2*i + 1];
}
}

bool flags_get_hint(int hint_index) {
return (extended_savectx.hints[hint_index / 8] & (1 << (hint_index % 8))) > 0;
}

void flags_set_hint(int hint_index) {
//draw_debug_int(4, hint_index);
extended_savectx.hints[hint_index / 8] |= 1 << (hint_index % 8);
}

void update_hints()
{
uint8_t iAlways = 0;
uint8_t iFoolish = 0;
uint8_t iGoals = 0;
uint8_t iSometimes = 0;
for (uint8_t i = 0; i < 40; i++) {
if (flags_get_hint(i) && hint_textbox_types[i] < 20) {
switch (hint_textbox_types[i]) {
case 2: {
hint_always_ids[iAlways] = hint_textbox_ids[i];
iAlways++;
break;
}
case 3: {
hint_foolish_ids[iFoolish] = hint_textbox_ids[i];
iFoolish++;
break;
}
case 4: {
hint_goals_ids[iGoals] = hint_textbox_ids[i];
iGoals++;
break;
}
case 5: {
hint_sometimes_ids[iSometimes] = hint_textbox_ids[i];
iSometimes++;
break;
}
}
}
}
hint_total_found[0] = iAlways;
hint_total_found[1] = iFoolish;
hint_total_found[2] = iGoals;
hint_total_found[3] = iSometimes;
}

void message_id_check(z64_game_t* play, uint16_t textId)
{
// Displaced code
Message_OpenText(play, textId);

//draw_debug_int(0, textId);
for (uint8_t i = 0; i < 40; i++) {
if (hint_textbox_ids[i] == textId && !(flags_get_hint(i))) {
flags_set_hint(i);
// Update the duplicate if there is one.
if (hint_textbox_types[i] > 20 && i > 0) {
flags_set_hint(i - 1);
}
if (i < 39 && hint_textbox_types[i + 1] > 20) {
flags_set_hint(i + 1);
}
update_hints();
break;
}
}
}

void draw_hints(z64_disp_buf_t* db) {

db->p = db->buf;
if ((z64_game.common.input[0].raw.pad.du || z64_game.common.input[0].raw.pad.l) && z64_game.common.input[0].raw.pad.a) {
if (menu_hint_cooldown == 20) {
show_hint_info = show_hint_info ? false : true;
}

if (menu_hint_cooldown > 0) {
menu_hint_cooldown--;
}
}
if (menu_hint_cooldown < 20) {
menu_hint_cooldown--;
if (menu_hint_cooldown == 0) {
menu_hint_cooldown = 20;
}
}

gSPDisplayList(db->p++, &setup_db);
if (show_hint_info) {

if (!update_first_time) {
update_hints();
update_first_time = true;
}

if (z64_game.common.input[0].pad_pressed.dr) {
current_hint_cat_index++;
if (current_hint_cat_index > 3) {
current_hint_cat_index = 0;
}
}
if (z64_game.common.input[0].pad_pressed.dl) {
if (current_hint_cat_index == 0) {
current_hint_cat_index = 3;
} else {
current_hint_cat_index--;
}
}

switch (current_hint_cat_index) {
case 0: {
current_hints_array = hint_always_ids;
break;
}
case 1: {
current_hints_array = hint_foolish_ids;
break;
}
case 2: {
current_hints_array = hint_goals_ids;
break;
}
case 3: {
current_hints_array = hint_sometimes_ids;
break;
}
}

// Set up dimensions
int font_width = 6;
int font_height = 11;
int padding = 2;
int rows = 7;
int bg_width = 30 * font_width;
int bg_height = (rows * font_height) + ((rows + 1) * padding);
int bg_left = 30;
int bg_top = 30;

int start_top = bg_top + padding + 1;
uint16_t left = bg_left + padding;

// Draw background
gDPSetCombineMode(db->p++, G_CC_PRIMITIVE, G_CC_PRIMITIVE);
for (int i = 0; i < rows; i++) {
uint16_t line_top = bg_top + i * (font_height + padding) + padding;
gDPPipeSync(db->p++);
if (i % 2) {
gDPSetPrimColor(db->p++, 0, 0, 0x00, 0x00, 0x00, 0xD0);
}
else {
gDPSetPrimColor(db->p++, 0, 0, 0x00, 0x00, 0x00, 0xDA);
}
gSPTextureRectangle(db->p++,
bg_left<<2, line_top<<2,
(bg_left + bg_width)<<2, (line_top + font_height + padding)<<2,
0,
0, 0,
1<<10, 1<<10);
}

gDPPipeSync(db->p++);
gDPSetCombineMode(db->p++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
gDPSetPrimColor(db->p++, 0, 0, 120, 255, 100, 0xFF);

text_print_size(db, "HINTS", left + bg_width / 2 - 3 * font_width, start_top, font_width, font_height);
gDPSetPrimColor(db->p++, 0, 0, 255, 255, 255, 255);
colorRGBA8_t white = { 255, 255, 255, 255};
for (int i = 0; i < 4; i++) {
menu_category_t *d = &(menu_hints_categories[i]);
int top = start_top + ((font_height + padding) * (i + 1)) + 1;
if (i != current_hint_cat_index) {
text_print_size(db, d->name, left, top + 5, font_width, font_height);
text_print_size(db, "Found : ", left + 10 * font_width, top + 5, font_width, font_height);
draw_int_size(db, hint_total_found[i], left + 20*font_width, top + 5, white, font_width, font_height);
}
}
menu_category_t* d = &(menu_hints_categories[current_hint_cat_index]);
int top = start_top + ((font_height + padding) * (current_hint_cat_index + 1)) + 1;
gDPSetPrimColor(db->p++, 0, 0, 0xE0, 0xE0, 0x10, 255);
colorRGBA8_t yellow = { 0xE0, 0xE0, 0x10, 255};
text_print_size(db, d->name, left, top + 5, font_width, font_height);
text_print_size(db, "Found : ", left + 10 * font_width, top + 5, font_width, font_height);
draw_int_size(db, hint_total_found[current_hint_cat_index], left + 20 * font_width, top + 5, yellow, font_width, font_height);

if (current_hints_array != NULL && hint_total_found[current_hint_cat_index] > 0) {
if (z64_ctxt.input[0].pad_pressed.dd) {
current_hint_index++;
if (current_hint_index > hint_total_found[current_hint_cat_index] - 1) {
current_hint_index = 0;
}
z64_DisplayTextbox(&z64_game, current_hints_array[current_hint_index], 0);
}
}
}
}
22 changes: 22 additions & 0 deletions ASM/c/hints.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#ifndef HINTS_H
#define HINTS_H

#include "debug.h"
#include "util.h"
#include "z64.h"

extern uint8_t CFG_HINTS_IDS_AND_TYPES[80];

static uint8_t current_hint_cat_index = 0;
static bool show_hint_info = 0;

void init_hints_ids();
void update_hints();

void draw_hints(z64_disp_buf_t* db);
bool hint_menu_is_drawn();
void message_id_check(z64_game_t* play, uint16_t textId);

void Message_OpenText(z64_game_t* play, uint16_t textId);

#endif
3 changes: 3 additions & 0 deletions ASM/c/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "uninvertYaxis.h"
#include "debug.h"
#include "inputviewer.h"
#include "hints.h"
#include "message.h"

void Gameplay_InitSkybox(z64_game_t* globalCtx, int16_t skyboxId);
Expand All @@ -34,6 +35,7 @@ void c_init() {
override_flags_init();
models_init();
init_textures();
init_hints_ids();
#if DEBUG_MODE
SKIP_N64_LOGO = 1;
#endif
Expand All @@ -49,6 +51,7 @@ void before_game_state_update() {
manage_music_changes();
manage_uninvert_yaxis();
display_misc_messages();
draw_hints(&rando_overlay_db);
}

void after_game_state_update() {
Expand Down
1 change: 1 addition & 0 deletions ASM/c/save.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ typedef struct {
bool collected_dungeon_rewards[8];
override_t incoming_queue[3];
uint8_t password[6];
uint8_t hints[6];
} extended_savecontext_static_t __attribute__ ((aligned (8)));


Expand Down
1 change: 1 addition & 0 deletions ASM/ootSymbols.ld
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ CutsceneFlags_Get = 0x8005991C;
z64_Gfx_SetupDL_42Opa = 0x8007E868;
Audio_StopCurrentMusic = 0x800C7684;
sprintf = 0x800CE7b4;
Message_OpenText = 0x800DC838;
Fault_AddHungupAndCrashImpl = 0x800AF564;
z64_ItemIcons = 0x800F8D2C;
z64_SfxDefaultPos = 0x80104394;
Expand Down
4 changes: 4 additions & 0 deletions ASM/src/config.asm
Original file line number Diff line number Diff line change
Expand Up @@ -347,4 +347,8 @@ CFG_BOSSES:
.endarea
; Bosses are listed twice, first 12 are sorted by the same order as the dungeon entrances (including the 3 with no bosses), then 9 in the usual dungeon order.

.area 80, 0x00
CFG_HINTS_IDS_AND_TYPES:
.endarea

.align 4
1 change: 1 addition & 0 deletions ASM/src/hacks.asm
Original file line number Diff line number Diff line change
Expand Up @@ -4159,3 +4159,4 @@ DemoEffect_DrawJewel_AfterHook:
.include "hacks/ovl_en_changer.asm"
.include "hacks/ovl_en_ssh.asm"
.include "hacks/ovl_en_okarina_tag.asm"
.include "hacks/message.asm"
5 changes: 5 additions & 0 deletions ASM/src/hacks/message.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.headersize(0x800D5EF0 - 0x00B4BE50)

.org 0x800DCE38
; Replaces jal func_800DC838
jal message_id_check
9 changes: 7 additions & 2 deletions Hints.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,10 +255,15 @@ def add_hint(spoiler: Spoiler, world: World, groups: list[list[int]], gossip_tex
for location in locations:
location.add_rule(world.parser.parse_rule(repr(event_item.name)))

total -= 1
first = False
for id in group:
spoiler.hints[world.id][id] = gossip_text
if first:
spoiler.hints_ids.setdefault(hint_type, []).append(id)
else:
# We want to know the duplicates somehow, store them as negative to know the previous id was the first.
spoiler.hints_ids.setdefault(hint_type, []).append(-id)
total -= 1
first = False
# Immediately start choosing duplicates from stones we passed up earlier
while duplicates and total:
group = duplicates.pop(0)
Expand Down
39 changes: 39 additions & 0 deletions Patches.py
Original file line number Diff line number Diff line change
Expand Up @@ -1230,6 +1230,45 @@ def calculate_traded_flags(world):
rom.write_int32(symbol, 0)
else:
write_gossip_stone_hints(spoiler, world, messages)
hints_ids_and_types = []
hints_starting = []
# Negative stone ids are duplicates from the previous stone.
for idx, hint_category in enumerate(spoiler.hints_ids):
if 'always' in hint_category:
for stone_id in spoiler.hints_ids[hint_category]:
#save_context.write_byte(save_context.addresses['hints'].address, 0xFF)
if stone_id > 0:
hints_ids_and_types.append(stone_id - 1000)
hints_ids_and_types.append(2)
else:
hints_ids_and_types.append(-stone_id - 1000)
hints_ids_and_types.append(2 + 20)
if 'barren' in hint_category:
for stone_id in spoiler.hints_ids[hint_category]:
if stone_id > 0:
hints_ids_and_types.append(stone_id - 1000)
hints_ids_and_types.append(3)
else:
hints_ids_and_types.append(-stone_id - 1000)
hints_ids_and_types.append(3 + 20)
if 'goal' in hint_category:
for stone_id in spoiler.hints_ids[hint_category]:
if stone_id > 0:
hints_ids_and_types.append(stone_id - 1000)
hints_ids_and_types.append(4)
else:
hints_ids_and_types.append(-stone_id - 1000)
hints_ids_and_types.append(4 + 20)
if 'sometimes' in hint_category or 'dual' in hint_category or 'song' in hint_category:
for stone_id in spoiler.hints_ids[hint_category]:
if stone_id > 0:
hints_ids_and_types.append(stone_id - 1000)
hints_ids_and_types.append(5)
else:
hints_ids_and_types.append(-stone_id - 1000)
hints_ids_and_types.append(5 + 20)
#raise Exception(hints_starting)
rom.write_bytes(rom.sym('CFG_HINTS_IDS_AND_TYPES'), hints_ids_and_types)

if world.settings.hints == 'mask':
rom.write_int32(symbol, 0)
Expand Down
2 changes: 1 addition & 1 deletion SaveContext.py
Original file line number Diff line number Diff line change
Expand Up @@ -921,7 +921,7 @@ def get_save_context_addresses() -> AddressesDict:
'trials_forest': Address(extended=True, size=1),
},
'password' : Address(extended=True, size=6),

'hints': Address(extended=True, size=6),
}

item_id_map: dict[str, int] = {
Expand Down
1 change: 1 addition & 0 deletions Spoiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ def __init__(self, worlds: list[World]) -> None:
self.hints: dict[int, dict[int, GossipText]] = {world.id: {} for world in worlds}
self.file_hash: list[int] = []
self.password: list[int] = []
self.hints_ids: dict[str, list[int]] = {}

def build_file_hash(self) -> None:
dist_file_hash = self.settings.distribution.file_hash
Expand Down
Loading