Skip to content

Commit

Permalink
Merge 'New cosmetic option : Display d-pad on the left of the screen' (
Browse files Browse the repository at this point in the history
  • Loading branch information
cjohnson57 committed Jul 31, 2023
2 parents 7709f58 + 0acefeb commit 4710b3c
Show file tree
Hide file tree
Showing 13 changed files with 24,320 additions and 24,270 deletions.
972 changes: 487 additions & 485 deletions ASM/build/asm_symbols.txt

Large diffs are not rendered by default.

Binary file modified ASM/build/bundle.o
Binary file not shown.
573 changes: 287 additions & 286 deletions ASM/build/c_symbols.txt

Large diffs are not rendered by default.

110 changes: 71 additions & 39 deletions ASM/c/dpad.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,50 +67,59 @@ void handle_dpad() {
}
}

void draw_dpad() {
void draw_dpad_and_menu_utilities() {
z64_disp_buf_t *db = &(z64_ctxt.gfx->overlay);
if (CAN_DRAW_DUNGEON_INFO || (DISPLAY_DPAD && CFG_DISPLAY_DPAD) || CAN_DRAW_TRADE_DPAD) {
if (CAN_DRAW_DUNGEON_INFO || (DISPLAY_DPAD && CFG_DISPLAY_DPAD) || CAN_DRAW_TRADE_DPAD || CAN_DRAW_OCARINA_BUTTONS) {

gSPDisplayList(db->p++, &setup_db);
gDPPipeSync(db->p++);
gDPSetCombineMode(db->p++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
uint16_t alpha = z64_game.hud_alpha_channels.rupees_keys_magic;

gDPSetPrimColor(db->p++, 0, 0, 0xFF, 0xFF, 0xFF, alpha);
sprite_load(db, &dpad_sprite, 0, 1);
int left = 271;

// Trade items switch in the menu. Shows a dpad and trade items if you hover on the trade item slot.
if (CAN_DRAW_TRADE_DPAD) {

uint8_t current_trade_item = z64_file.items[z64_game.pause_ctxt.item_cursor];
// D-pad under selected trade item slot, if more than one trade item
int left_trade_dpad = (z64_game.pause_ctxt.item_cursor == Z64_SLOT_ADULT_TRADE) ? 197 : 230;
int top_trade_dpad = 190;

if (IsTradeItem(current_trade_item)) {
uint8_t prev_trade_item = SaveFile_PrevOwnedTradeItem(current_trade_item);
uint8_t next_trade_item = SaveFile_NextOwnedTradeItem(current_trade_item);

if (current_trade_item != next_trade_item) {
// D-pad under selected trade item slot, if more than one trade item
left = (z64_game.pause_ctxt.item_cursor == Z64_SLOT_ADULT_TRADE) ? 197 : 230;
sprite_draw(db, &dpad_sprite, 0, left, 190, 24, 24);
sprite_draw(db, &dpad_sprite, 0, left_trade_dpad, top_trade_dpad, 24, 24);

// Previous trade quest item
gDPSetPrimColor(db->p++, 0, 0, 0xFF, 0xFF, 0xFF, alpha);
sprite_load(db, &items_sprite, prev_trade_item, 1);
sprite_draw(db, &items_sprite, 0, left - 16, 194, 16, 16);
sprite_draw(db, &items_sprite, 0, left_trade_dpad - 16, top_trade_dpad + 4, 16, 16);

// Next trade quest item
gDPSetPrimColor(db->p++, 0, 0, 0xFF, 0xFF, 0xFF, alpha);
sprite_load(db, &items_sprite, next_trade_item, 1);
sprite_draw(db, &items_sprite, 0, left + 24, 194, 16, 16);
sprite_draw(db, &items_sprite, 0, left_trade_dpad + 24, top_trade_dpad + 4, 16, 16);
}
}
gDPPipeSync(db->p++);
return;
}

// Shows Ocarina buttons preview when you hover on the Ocarina slot in the menu.
if (CAN_DRAW_OCARINA_BUTTONS) {
left = 70;
int top = 125;

int left_ocarina_buttons = 70;
int top_ocarina_buttons = 125;
int icon_width = 16;
int icon_height = 16;

// Draw background
int bg_width = 5 * icon_width;
int bg_left = left;
int bg_top = top;
int bg_left = left_ocarina_buttons;
int bg_top = top_ocarina_buttons;

gDPSetCombineMode(db->p++, G_CC_PRIMITIVE, G_CC_PRIMITIVE);
gDPSetPrimColor(db->p++, 0, 0, 0x00, 0x00, 0x00, 0xD0);
Expand All @@ -130,88 +139,111 @@ void draw_dpad() {
gDPSetPrimColor(db->p++, 0, 0, CFG_A_BUTTON_COLOR.r, CFG_A_BUTTON_COLOR.g, CFG_A_BUTTON_COLOR.b, alpha);
}
if (z64_file.scene_flags[0x50].unk_00_ & 1 << 0) { // A
sprite_draw(db, &button_sprite, 0, left, top, icon_width, icon_height);
sprite_draw(db, &button_sprite, 0, left_ocarina_buttons, top_ocarina_buttons, icon_width, icon_height);
}

gDPSetPrimColor(db->p++, 0, 0, 0xF4, 0xEC, 0x30, alpha); // yellow
if (CFG_CORRECT_MODEL_COLORS) {
gDPSetPrimColor(db->p++, 0, 0, CFG_C_BUTTON_COLOR.r, CFG_C_BUTTON_COLOR.g, CFG_C_BUTTON_COLOR.b, alpha);
}
if (z64_file.scene_flags[0x50].unk_00_ & 1 << 2) { // C Down
sprite_draw(db, &button_sprite, 1, left + icon_width, top, icon_width, icon_height);
sprite_draw(db, &button_sprite, 1, left_ocarina_buttons + icon_width, top_ocarina_buttons, icon_width, icon_height);
}
if (z64_file.scene_flags[0x50].unk_00_ & 1 << 4) { // C right
sprite_draw(db, &button_sprite, 2, left + 2*icon_width, top, icon_width, icon_height);
sprite_draw(db, &button_sprite, 2, left_ocarina_buttons + 2*icon_width, top_ocarina_buttons, icon_width, icon_height);
}
if (z64_file.scene_flags[0x50].unk_00_ & 1 << 3) { // C left
sprite_draw(db, &button_sprite, 3, left + 3*icon_width, top, icon_width, icon_height);
sprite_draw(db, &button_sprite, 3, left_ocarina_buttons + 3*icon_width, top_ocarina_buttons, icon_width, icon_height);
}
if (z64_file.scene_flags[0x50].unk_00_ & 1 << 1) { // C up
sprite_draw(db, &button_sprite, 4, left + 4*icon_width, top, icon_width, icon_height);
sprite_draw(db, &button_sprite, 4, left_ocarina_buttons + 4*icon_width, top_ocarina_buttons, icon_width, icon_height);
}

gDPPipeSync(db->p++);
return;
}

if (left == 271) {
// D-pad under C buttons, if trade slot selector not drawn
sprite_draw(db, &dpad_sprite, 0, left, 64, 16, 16);
// Main dpad sprite both on menu screen and regular game.
int left_main_dpad = CFG_DPAD_ON_THE_LEFT ? 32 : 271;
int top_main_dpad = CFG_DPAD_ON_THE_LEFT ? 51 : 64;
// If it's on the left, the top coordinate will change whether if there is a timer on screen,
// or if there is a second row of hearts.
// Always let room for magic bar, same behaviour as timers.
if (CFG_DPAD_ON_THE_LEFT) {
if (z64_file.timer_1_state > 2)
top_main_dpad += 15;

if (z64_file.energy_capacity > 10 * 0x10)
top_main_dpad += 8;
}
sprite_draw(db, &dpad_sprite, 0, left_main_dpad, top_main_dpad, 16, 16);

if (CAN_DRAW_DUNGEON_INFO && CFG_DPAD_DUNGEON_INFO_ENABLE && left == 271) {
// Menu dpad
if (CAN_DRAW_DUNGEON_INFO && CFG_DPAD_DUNGEON_INFO_ENABLE) {
// Zora sapphire on D-down
sprite_load(db, &stones_sprite, 2, 1);
sprite_draw(db, &stones_sprite, 0, 273, 77, 12, 12);
sprite_draw(db, &stones_sprite, 0, left_main_dpad + 2, top_main_dpad + 13, 12, 12);

// small key on D-right
sprite_load(db, &quest_items_sprite, 17, 1);
sprite_draw(db, &quest_items_sprite, 0, 285, 66, 12, 12);
sprite_draw(db, &quest_items_sprite, 0, left_main_dpad + 14, top_main_dpad + 2, 12, 12);

// map on D-left
sprite_load(db, &quest_items_sprite, 16, 1);
sprite_draw(db, &quest_items_sprite, 0, 260, 66, 12, 12);
} else if (left == 271) {
if (!CAN_USE_DPAD)
sprite_draw(db, &quest_items_sprite, 0, left_main_dpad - 11, top_main_dpad + 2, 12, 12);

} else { // Main game dpad
if (!CAN_USE_DPAD) {
gDPSetPrimColor(db->p++, 0, 0, 0xFF, 0xFF, 0xFF, alpha * 0x46 / 0xFF);
}

if (z64_file.iron_boots && z64_file.link_age==0) {
sprite_load(db, &items_sprite, 69, 1);
if (z64_file.equip_boots == 2) {
sprite_draw(db, &items_sprite, 0, 258, 64, 16, 16);
sprite_draw(db, &items_sprite, 0, left_main_dpad - 13, top_main_dpad, 16, 16);
}
else {
sprite_draw(db, &items_sprite, 0, 260, 66, 12, 12);
sprite_draw(db, &items_sprite, 0, left_main_dpad - 11, top_main_dpad + 2, 12, 12);
}
}

if (z64_file.hover_boots && z64_file.link_age == 0) {
sprite_load(db, &items_sprite, 70, 1);
if (z64_file.equip_boots == 3) {
sprite_draw(db, &items_sprite, 0, 283, 64, 16, 16);
sprite_draw(db, &items_sprite, 0, left_main_dpad + 12, top_main_dpad, 16, 16);
}
else {
sprite_draw(db, &items_sprite, 0, 285, 66, 12, 12);
sprite_draw(db, &items_sprite, 0, left_main_dpad + 14, top_main_dpad + 2, 12, 12);
}
}

if (z64_file.items[Z64_SLOT_CHILD_TRADE] >= Z64_ITEM_WEIRD_EGG && z64_file.items[Z64_SLOT_CHILD_TRADE] <= Z64_ITEM_MASK_OF_TRUTH && z64_file.link_age == 1) {
if(!CAN_USE_DPAD || !CAN_USE_CHILD_TRADE) gDPSetPrimColor(db->p++, 0, 0, 0xFF, 0xFF, 0xFF, alpha * 0x46 / 0xFF);
else gDPSetPrimColor(db->p++, 0, 0, 0xFF, 0xFF, 0xFF, alpha);
if (!CAN_USE_DPAD || !CAN_USE_CHILD_TRADE) {
gDPSetPrimColor(db->p++, 0, 0, 0xFF, 0xFF, 0xFF, alpha * 0x46 / 0xFF);
}
else {
gDPSetPrimColor(db->p++, 0, 0, 0xFF, 0xFF, 0xFF, alpha);
}
sprite_load(db, &items_sprite, z64_file.items[Z64_SLOT_CHILD_TRADE], 1);
if (z64_link.current_mask >= 1 && z64_link.current_mask <= 9) {
sprite_draw(db, &items_sprite, 0, 283, 64, 16, 16);
sprite_draw(db, &items_sprite, 0, left_main_dpad + 12, top_main_dpad, 16, 16);
}
else {
sprite_draw(db, &items_sprite, 0, 285, 66, 12, 12);
sprite_draw(db, &items_sprite, 0, left_main_dpad + 14, top_main_dpad + 2, 12, 12);
}
}

if (z64_file.items[Z64_SLOT_OCARINA] == Z64_ITEM_FAIRY_OCARINA || z64_file.items[Z64_SLOT_OCARINA] == Z64_ITEM_OCARINA_OF_TIME) {
if(!CAN_USE_DPAD || !CAN_USE_OCARINA) gDPSetPrimColor(db->p++, 0, 0, 0xFF, 0xFF, 0xFF, alpha * 0x46 / 0xFF);
else gDPSetPrimColor(db->p++, 0, 0, 0xFF, 0xFF, 0xFF, alpha);
if (!CAN_USE_DPAD || !CAN_USE_OCARINA) {
gDPSetPrimColor(db->p++, 0, 0, 0xFF, 0xFF, 0xFF, alpha * 0x46 / 0xFF);
}
else {
gDPSetPrimColor(db->p++, 0, 0, 0xFF, 0xFF, 0xFF, alpha);
}
sprite_load(db, &items_sprite, z64_file.items[Z64_SLOT_OCARINA], 1);
sprite_draw(db, &items_sprite, 0, 273, 77, 12,12);
sprite_draw(db, &items_sprite, 0, left_main_dpad + 2, top_main_dpad + 13, 12,12);
}
}

gDPPipeSync(db->p++);
}
}
Expand Down
3 changes: 2 additions & 1 deletion ASM/c/dpad.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <stdbool.h>
#include "ocarina_buttons.h"
#include "item_draw_functions.h"
extern uint8_t CFG_DPAD_ON_THE_LEFT;

// PLAYER_STATE1_0 : Scene transition
// PLAYER_STATE1_SWINGING_BOTTLE
Expand Down Expand Up @@ -73,6 +74,6 @@ extern uint16_t CFG_CHILD_TRADE_SHUFFLE;
#define CAN_USE_CHILD_TRADE (z64_game.pause_ctxt.state == 0 && z64_file.items[Z64_SLOT_CHILD_TRADE] >= Z64_ITEM_WEIRD_EGG && z64_file.items[Z64_SLOT_CHILD_TRADE] <= Z64_ITEM_MASK_OF_TRUTH && !z64_game.restriction_flags.trade_items && ((z64_link.state_flags_1 & BLOCK_ITEMS) == 0))

void handle_dpad();
void draw_dpad();
void draw_dpad_and_menu_utilities();

#endif
4 changes: 3 additions & 1 deletion ASM/src/config.asm
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
COSMETIC_CONTEXT:

COSMETIC_FORMAT_VERSION:
.word 0x1F073FDF
.word 0x1F073FE0
CFG_MAGIC_COLOR:
.halfword 0x0000, 0x00C8, 0x0000
CFG_HEART_COLOR:
Expand Down Expand Up @@ -84,6 +84,8 @@ CFG_CORRECT_MODEL_COLORS:
.byte 0x00
CFG_UNINVERT_YAXIS_IN_FIRST_PERSON_CAMERA:
.byte 0x00
CFG_DPAD_ON_THE_LEFT:
.byte 0x00

CFG_SHOW_SETTING_INFO:
.byte 0x00
Expand Down
2 changes: 1 addition & 1 deletion ASM/src/dpad.asm
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
dpad_draw:
addiu sp, sp, -0x10
sw ra, 0(sp)
jal draw_dpad
jal draw_dpad_and_menu_utilities
nop
lw t6, 0x1C44(s6)
lui t8, 0xDB06
Expand Down
20 changes: 19 additions & 1 deletion Cosmetics.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def patch_targeting(rom: Rom, settings: Settings, log: CosmeticsLog, symbols: di

def patch_dpad(rom: Rom, settings: Settings, log: CosmeticsLog, symbols: dict[str, int]) -> None:
# Display D-Pad HUD
if settings.display_dpad:
if settings.display_dpad != 'off':
rom.write_byte(symbols['CFG_DISPLAY_DPAD'], 0x01)
else:
rom.write_byte(symbols['CFG_DISPLAY_DPAD'], 0x00)
Expand Down Expand Up @@ -962,6 +962,13 @@ def patch_yaxis(rom: Rom, settings: Settings, log: CosmeticsLog, symbols: dict[s
rom.write_byte(symbols['CFG_UNINVERT_YAXIS_IN_FIRST_PERSON_CAMERA'], 0x00)
log.uninvert_y_axis_in_first_person_camera = settings.uninvert_y_axis_in_first_person_camera

def patch_dpad_left(rom: Rom, settings: Settings, log: CosmeticsLog, symbols: dict[str, int]) -> None:
if settings.display_dpad == 'left':
rom.write_byte(symbols['CFG_DPAD_ON_THE_LEFT'], 0x01)
else:
rom.write_byte(symbols['CFG_DPAD_ON_THE_LEFT'], 0x00)
log.display_dpad = settings.display_dpad

legacy_cosmetic_data_headers: list[int] = [
0x03481000,
0x03480810,
Expand Down Expand Up @@ -1146,6 +1153,17 @@ def patch_yaxis(rom: Rom, settings: Settings, log: CosmeticsLog, symbols: dict[s
}
}

# 7.1.144
patch_sets[0x1F073FE0] = {
"patches": patch_sets[0x1F073FDF]["patches"] + [
patch_dpad_left,
],
"symbols": {
**patch_sets[0x1F073FDF]["symbols"],
"CFG_DPAD_ON_THE_LEFT": 0x006A,
}
}

def patch_cosmetics(settings: Settings, rom: Rom) -> CosmeticsLog:
# re-seed for aesthetic effects. They shouldn't be affected by the generation seed
random.seed()
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ issue. You should always Hard Reset to avoid this issue entirely.
* New setting `Key Appearance Matches Dungeon` which changes the models for small keys and boss keys to indicate which dungeon the key belongs to.
* New setting `Shuffle Individual Ocarina Notes`, which shuffles items representing each of the 5 ocarina notes into the item pool. You cannot play any note on the ocarina until you find its corresponding item.
* New cosmetic setting `Uninvert Y-Axis in First Person Camera` which makes tilting the joystick up or down in first person look those respective directions, instead of the opposite direction.
* The setting `Display D-Pad HUD` has been expanded so that the D-Pad can be set to the left of the screen.
* **Hints**
* New `Important Checks` hint type which hints at how many major items are in a given region.
* Double Defense and Biggoron's Sword are counted as major for this hint type.
Expand Down
9 changes: 7 additions & 2 deletions SettingsList.py
Original file line number Diff line number Diff line change
Expand Up @@ -3702,15 +3702,20 @@ class SettingInfos:
},
)

display_dpad = Checkbutton(
display_dpad = Combobox(
gui_text = 'Display D-Pad HUD',
shared = False,
cosmetic = True,
gui_tooltip = '''\
Shows an additional HUD element displaying
current available options on the D-Pad.
''',
default = True,
default = 'right',
choices = {
'off': 'Off',
'left': 'On the left',
'right': 'On the right',
},
)

dpad_dungeon_menu = Checkbutton(
Expand Down
Loading

0 comments on commit 4710b3c

Please sign in to comment.