From af3dc71a5cabe6e402e85bef2d445c3506a721fb Mon Sep 17 00:00:00 2001 From: Yanis <35189056+Yanis002@users.noreply.github.com> Date: Tue, 4 Nov 2025 17:23:27 +0100 Subject: [PATCH] New Inventory Editor (#107) * inventory editor * fixed a bug where the menu was usable in special pause screens * fixed most equipment screen issues * draw page number on upgrade screen and minor improvements * format * fix build issues * format * fix build issues * format * various improvements * fix build issues with non-debug * small cleanup * last improvements and bugfixes + cleanup and format --- include/config/config_debug_features.h | 2 +- include/debug.h | 4 + include/debug/inventory_editor.h | 207 +++ include/gfx_setupdl.h | 5 + include/item.h | 19 + include/pause.h | 2 +- spec/spec | 1 + src/code/z_bgcheck.c | 2 + src/code/z_kaleido_scope_call.c | 2 + src/code/z_kaleido_setup.c | 5 +- src/code/z_kankyo.c | 1 + src/code/z_lifemeter.c | 13 +- src/code/z_map_exp.c | 1 + src/code/z_parameter.c | 209 +-- src/code/z_play.c | 4 + src/code/z_rcp.c | 10 + src/debug/collider_view.c | 1 + src/debug/collision_view.c | 2 +- src/debug/inventory_editor.c | 1180 +++++++++++++++++ src/debug/menu.c | 1 + src/debug/print.c | 2 +- src/debug/utility.c | 2 +- .../ovl_debug_opening/debug_opening.c | 2 +- .../ovl_kaleido_scope/z_kaleido_collect.c | 5 +- .../misc/ovl_kaleido_scope/z_kaleido_debug.c | 2 +- .../ovl_kaleido_scope/z_kaleido_equipment.c | 101 +- .../misc/ovl_kaleido_scope/z_kaleido_item.c | 67 +- .../misc/ovl_kaleido_scope/z_kaleido_scope.c | 149 ++- 28 files changed, 1825 insertions(+), 176 deletions(-) create mode 100644 include/debug/inventory_editor.h create mode 100644 src/debug/inventory_editor.c diff --git a/include/config/config_debug_features.h b/include/config/config_debug_features.h index 66b6b6c17..fe2399e87 100644 --- a/include/config/config_debug_features.h +++ b/include/config/config_debug_features.h @@ -72,7 +72,7 @@ /**** [INVENTORY EDITOR] ****/ // ``IS_INV_EDITOR_ENABLED`` -#define ENABLE_INV_EDITOR false +#define ENABLE_INV_EDITOR true /**** [EVENT EDITOR] ****/ // ``IS_EVENT_EDITOR_ENABLED`` diff --git a/include/debug.h b/include/debug.h index a0c56a0cc..a1079faef 100644 --- a/include/debug.h +++ b/include/debug.h @@ -6,6 +6,7 @@ #include "padmgr.h" #include "debug/print.h" #include "debug/collision_view.h" +#include "debug/inventory_editor.h" #include "debug/menu.h" #include "debug/profiler.h" #include "z_math.h" @@ -19,11 +20,14 @@ #define COLOR_BLUE2 (0x0080FF) #define COLOR_BLUE3 (0x00BFFF) +#define IS_INV_EDITOR_ACTIVE (IS_INV_EDITOR_ENABLED && gDebug.invDebug.state != INVEDITOR_STATE_OFF) + typedef struct Debug { struct PlayState* play; Input* input; PrintUtils printer; Menu menu; + InventoryEditor invDebug; } Debug; void Debug_DrawColorRectangle(Vec2s rectLeft, Vec2s rectRight, Color_RGBA8 rgba); diff --git a/include/debug/inventory_editor.h b/include/debug/inventory_editor.h new file mode 100644 index 000000000..54e63d16f --- /dev/null +++ b/include/debug/inventory_editor.h @@ -0,0 +1,207 @@ +#ifndef INVENTORY_EDITOR_H +#define INVENTORY_EDITOR_H + +#include "config.h" +#include "pause.h" + +typedef enum InvEditorMagicState { + INVEDITOR_MAGIC_STATE_NONE, + INVEDITOR_MAGIC_STATE_NORMAL, + INVEDITOR_MAGIC_STATE_DOUBLE, +} InvEditorMagicState; + +typedef enum InvEditorInfosMiscTransState { + INVEDITOR_TRANS_STATE_DONE, + INVEDITOR_TRANS_STATE_INFO_REQUESTED, + INVEDITOR_TRANS_STATE_INFO_SWITCHING, + INVEDITOR_TRANS_STATE_MISC_REQUESTED, + INVEDITOR_TRANS_STATE_MISC_SWITCHING, +} InvEditorInfosMiscTransState; + +typedef enum InvEditorCursorPos { + INVEDITOR_CURSOR_POS_MIN = -1, + INVEDITOR_CURSOR_POS_HEARTS, + INVEDITOR_CURSOR_POS_MAGIC, + INVEDITOR_CURSOR_POS_RUPEES, + INVEDITOR_CURSOR_POS_SMALL_KEYS, + INVEDITOR_CURSOR_POS_BOSS_KEY, + INVEDITOR_CURSOR_POS_COMPASS, + INVEDITOR_CURSOR_POS_MAP, + INVEDITOR_CURSOR_POS_MAX +} InvEditorCursorPos; + +typedef enum InvEditorTitleState { + INVEDITOR_TITLE_STATE_MIN = -1, + INVEDITOR_TITLE_STATE_NAME, + INVEDITOR_TITLE_STATE_COMMANDS, + INVEDITOR_TITLE_STATE_MISCDBG +} InvEditorTitleState; + +typedef enum InvEditorCommonState { + INVEDITOR_COMMON_STATE_MIN = -1, + INVEDITOR_COMMON_STATE_UNREADY, + INVEDITOR_COMMON_STATE_READY +} InvEditorCommonState; + +typedef enum InvEditorState { + INVEDITOR_STATE_MIN = -1, + INVEDITOR_STATE_OFF, + INVEDITOR_STATE_INIT, + INVEDITOR_STATE_UPDATE, + INVEDITOR_STATE_DESTROY +} InvEditorState; + +typedef struct InventoryEditorCommon { + InvEditorCommonState state; + u8 selectedItem; + u8 selectedSlot; + s8 changeBy; +} InvEditorCommon; + +typedef struct InvEditorItems { + u8 childTradeItem; + u8 adultTradeItem; + u8 hookshotType; + u8 ocarinaType; + u8 bottleItems[4]; +} InvEditorItems; + +typedef struct InvEditorEquipment { + u8 showMiscUpgrades; + u8 upgradeSlots[8]; + u8 upgradeValues[8]; + u8 bgsFlag; + u16 swordHealth; +} InvEditorEquipment; + +typedef struct InvEditorMisc { + u8 showMiscScreen; + u8 stickMoved; + u8 updateDefenseHearts; + InvEditorCursorPos hudCursorPos; + s8 hudDungeonIconIndex; + s16 hudTopPosY; + s16 hudBottomPosY; + s16 invertVal; + s16 mapIndex; +} InvEditorMisc; + +struct GraphicsContext; + +typedef struct InventoryEditor { + InvEditorState state; + GraphicsContext* gfxCtx; + PauseContext* pauseCtx; + InvEditorCommon common; + InvEditorItems itemDebug; + InvEditorEquipment equipDebug; + InvEditorMisc miscDebug; + u8 titleTimer; + InvEditorTitleState titleState; + s16 titlePosY; + s16 backgroundPosY; + u8 showInfoScreen; + s16 elementsAlpha; + s16 miscElementsAlpha; +} InventoryEditor; + +Gfx* Gfx_TextureIA8(Gfx* displayListHead, void* texture, s16 textureWidth, s16 textureHeight, s16 rectLeft, s16 rectTop, + s16 rectWidth, s16 rectHeight, u16 dsdx, u16 dtdy); + +u8 InventoryEditor_GetUpgradeType(u16 slotIndex); +void InventoryEditor_SetItemFromSlot(InventoryEditor* this); +void InventoryEditor_SetHUDAlpha(InventoryEditor* this); +void InventoryEditor_UpdateMiscScreen(InventoryEditor* this); +void InventoryEditor_UpdateQuestScreen(InventoryEditor* this); +void InventoryEditor_UpdateEquipmentScreen(InventoryEditor* this); +void InventoryEditor_UpdateItemScreen(InventoryEditor* this); +void InventoryEditor_UpdateInformationScreen(InventoryEditor* this); +void InventoryEditor_DrawRectangle(InventoryEditor* this, s32 leftX, s32 leftY, s32 rightX, s32 rightY, + Color_RGBA8 rgba); +void InventoryEditor_DrawMiscScreen(InventoryEditor* this); +void InventoryEditor_DrawEquipmentUpgrades(InventoryEditor* this, u16 i, s16 alpha); +void InventoryEditor_DrawInformationScreen(InventoryEditor* this); +void InventoryEditor_Init(InventoryEditor* this); +void InventoryEditor_Update(InventoryEditor* this); +void InventoryEditor_Draw(InventoryEditor* this); +bool InventoryEditor_Destroy(InventoryEditor* this); +void InventoryEditor_Main(InventoryEditor* this); + +#define IS_IN_RANGE(val, min, max) ((val >= min) && (val <= max)) +#define TIMER_DECR(val, target, changeBy) \ + (((val - changeBy) < target) ? target : (val > target) ? (val - changeBy) : val) +#define TIMER_INCR(val, target, changeBy) \ + (((val + changeBy) > target) ? target : (val < target) ? (val + changeBy) : val) + +// General +#define INVEDITOR_PRINT_NEWLINE "\n " +#define INVEDITOR_ANIM_BASE_SPEED 16 + +#define INVEDITOR_BG_ANIM_SPEED INVEDITOR_ANIM_BASE_SPEED +#define INVEDITOR_BG_YPOS_TARGET 0 +#define INVEDITOR_BG_YPOS 220 + +#define INVEDITOR_TITLE_TIMER 70 // frames +#define INVEDITOR_TITLE_ANIM_SPEED (INVEDITOR_ANIM_BASE_SPEED / 8) +#define INVEDITOR_TITLE_YPOS_TARGET 2 +#define INVEDITOR_TITLE_YPOS 28 + +#define INVEDITOR_ALPHA_TRANS_SPEED (INVEDITOR_ANIM_BASE_SPEED * 2) + +// Items +#define INVEDITOR_GET_BOTTLE_ITEM(invDebug) \ + (IS_IN_RANGE((invDebug)->common.selectedSlot, SLOT_BOTTLE_1, SLOT_BOTTLE_4) \ + ? (invDebug)->itemDebug.bottleItems[(invDebug)->common.selectedSlot - SLOT_BOTTLE_1] \ + : ITEM_NONE) + +#define INVEDITOR_GET_CHILD_TRADE_ITEM(invDebug) \ + (((invDebug)->common.selectedSlot == SLOT_TRADE_CHILD) ? (invDebug)->itemDebug.childTradeItem : ITEM_NONE) + +#define INVEDITOR_GET_ADULT_TRADE_ITEM(invDebug) \ + (((invDebug)->common.selectedSlot == SLOT_TRADE_ADULT) ? (invDebug)->itemDebug.adultTradeItem : ITEM_NONE) + +#define INVEDITOR_GET_HOOKSHOT(invDebug) \ + (((invDebug)->common.selectedSlot == SLOT_HOOKSHOT) ? (invDebug)->itemDebug.hookshotType : ITEM_NONE) + +#define INVEDITOR_GET_OCARINA(invDebug) \ + (((invDebug)->common.selectedSlot == SLOT_OCARINA) ? (invDebug)->itemDebug.ocarinaType : ITEM_NONE) + +#define INVEDITOR_GET_VARIABLE_ITEM(invDebug) \ + ((INVEDITOR_GET_BOTTLE_ITEM(invDebug) != ITEM_NONE) ? INVEDITOR_GET_BOTTLE_ITEM(invDebug) \ + : (INVEDITOR_GET_CHILD_TRADE_ITEM(invDebug) != ITEM_NONE) ? INVEDITOR_GET_CHILD_TRADE_ITEM(invDebug) \ + : (INVEDITOR_GET_ADULT_TRADE_ITEM(invDebug) != ITEM_NONE) ? INVEDITOR_GET_ADULT_TRADE_ITEM(invDebug) \ + : (INVEDITOR_GET_HOOKSHOT(invDebug) != ITEM_NONE) ? INVEDITOR_GET_HOOKSHOT(invDebug) \ + : (INVEDITOR_GET_OCARINA(invDebug) != ITEM_NONE) ? INVEDITOR_GET_OCARINA(invDebug) \ + : ITEM_NONE) + +#define INVEDITOR_UPDATE_ITEM(invDbgCommon, min, max) \ + { \ + if (IS_IN_RANGE(invDbgCommon.selectedItem, min, max)) { \ + gSaveContext.save.info.inventory.items[invDbgCommon.selectedSlot] += invDbgCommon.changeBy; \ + if (gSaveContext.save.info.inventory.items[invDbgCommon.selectedSlot] > max) { \ + gSaveContext.save.info.inventory.items[invDbgCommon.selectedSlot] = min; \ + } \ + \ + if (gSaveContext.save.info.inventory.items[invDbgCommon.selectedSlot] < min) { \ + gSaveContext.save.info.inventory.items[invDbgCommon.selectedSlot] = max; \ + } \ + } \ + } + +// Equipment +#define INVEDITOR_IS_UPGRADE(invDbgCommon) \ + (((invDbgCommon).selectedSlot == SLOT_UPG_QUIVER) || ((invDbgCommon).selectedSlot == SLOT_UPG_BOMB_BAG) || \ + ((invDbgCommon).selectedSlot == SLOT_UPG_STRENGTH) || ((invDbgCommon).selectedSlot == SLOT_UPG_SCALE)) + +// Misc +#define INVEDITOR_HUD_TOP_ANIM_SPEED INVEDITOR_ANIM_BASE_SPEED / 5 +#define INVEDITOR_HUD_TOP_YPOS_TARGET 35 +#define INVEDITOR_HUD_TOP_YPOS 0 + +#define INVEDITOR_HUD_BOTTOM_ANIM_SPEED INVEDITOR_ANIM_BASE_SPEED / 2 +#define INVEDITOR_HUD_BOTTOM_YPOS_TARGET 100 +#define INVEDITOR_HUD_BOTTOM_YPOS 0 +#define INVEDITOR_HUD_BOTTOM_INVERT_SPEED INVEDITOR_ANIM_BASE_SPEED / 16 +#define INVEDITOR_HUD_BOTTOM_INVERT_TARGET 16 + +#endif diff --git a/include/gfx_setupdl.h b/include/gfx_setupdl.h index 1ba9ba06f..6e975b034 100644 --- a/include/gfx_setupdl.h +++ b/include/gfx_setupdl.h @@ -105,6 +105,11 @@ Gfx* Gfx_SetupDL_39(Gfx* gfx); void Gfx_SetupDL_39Opa(struct GraphicsContext* gfxCtx); void Gfx_SetupDL_39Overlay(struct GraphicsContext* gfxCtx); void Gfx_SetupDL_39Ptr(Gfx** gfxP); + +#if DEBUG_FEATURES +void Gfx_SetupDL_39Debug(struct GraphicsContext* gfxCtx); +#endif + void Gfx_SetupDL_40Opa(struct GraphicsContext* gfxCtx); void Gfx_SetupDL_41Opa(struct GraphicsContext* gfxCtx); void Gfx_SetupDL_47Xlu(struct GraphicsContext* gfxCtx); diff --git a/include/item.h b/include/item.h index f5d4a530a..cd5759723 100644 --- a/include/item.h +++ b/include/item.h @@ -151,6 +151,25 @@ typedef enum InventorySlot { /* 0xFF */ SLOT_NONE = 0xFF } InventorySlot; +typedef enum EquipmentSlot { + /* 0x00 */ SLOT_UPG_QUIVER, // also bullet bag slot + /* 0x01 */ SLOT_SWORD_KOKIRI, + /* 0x02 */ SLOT_SWORD_MASTER, + /* 0x03 */ SLOT_SWORD_BIGGORON, + /* 0x04 */ SLOT_UPG_BOMB_BAG, // also deku stick capacity slot (inventory editor only) + /* 0x05 */ SLOT_SHIELD_DEKU, + /* 0x06 */ SLOT_SHIELD_HYLIAN, + /* 0x07 */ SLOT_SHIELD_MIRROR, + /* 0x08 */ SLOT_UPG_STRENGTH, // also deku nut capacity slot (inventory editor only) + /* 0x09 */ SLOT_TUNIC_KOKIRI, + /* 0x0A */ SLOT_TUNIC_GORON, + /* 0x0B */ SLOT_TUNIC_ZORA, + /* 0x0C */ SLOT_UPG_SCALE, // also wallet capacity slot (inventory editor only) + /* 0x0D */ SLOT_BOOTS_KOKIRI, + /* 0x0E */ SLOT_BOOTS_IRON, + /* 0x0F */ SLOT_BOOTS_HOVER +} EquipmentSlot; + typedef enum ItemID { /* 0x00 */ ITEM_DEKU_STICK, /* 0x01 */ ITEM_DEKU_NUT, diff --git a/include/pause.h b/include/pause.h index 736e2cd6f..9c6829eef 100644 --- a/include/pause.h +++ b/include/pause.h @@ -93,7 +93,7 @@ typedef enum PauseDebugState { #if IS_INV_EDITOR_ENABLED || IS_EVENT_EDITOR_ENABLED #define IS_PAUSED(pauseCtx) \ - (((pauseCtx)->state != PAUSE_STATE_OFF) || ((pauseCtx)->debugState != PAUSE_DEBUG_STATE_CLOSED)) + (((pauseCtx)->state != PAUSE_STATE_OFF) || (IS_INV_EDITOR_ACTIVE && (pauseCtx)->debugState != PAUSE_DEBUG_STATE_CLOSED)) #else #define IS_PAUSED(pauseCtx) \ ((pauseCtx)->state != PAUSE_STATE_OFF) diff --git a/spec/spec b/spec/spec index f321bbe16..5df5149b6 100644 --- a/spec/spec +++ b/spec/spec @@ -876,6 +876,7 @@ beginseg #if ENABLE_PROFILER include "$(BUILD_DIR)/src/debug/profiler.o" #endif + include "$(BUILD_DIR)/src/debug/inventory_editor.o" endseg #endif diff --git a/src/code/z_bgcheck.c b/src/code/z_bgcheck.c index 6764a6512..ed560a2f1 100644 --- a/src/code/z_bgcheck.c +++ b/src/code/z_bgcheck.c @@ -13,6 +13,8 @@ #include "play_state.h" #include "player.h" #include "skin_matrix.h" +#include "gfx.h" +#include "debug.h" #pragma increment_block_number "ntsc-1.0:136 ntsc-1.1:136 ntsc-1.2:136" diff --git a/src/code/z_kaleido_scope_call.c b/src/code/z_kaleido_scope_call.c index ca7637214..744a30eed 100644 --- a/src/code/z_kaleido_scope_call.c +++ b/src/code/z_kaleido_scope_call.c @@ -9,6 +9,8 @@ #include "terminal.h" #include "translation.h" #include "play_state.h" +#include "gfx.h" +#include "debug.h" void (*sKaleidoScopeUpdateFunc)(PlayState* play); void (*sKaleidoScopeDrawFunc)(PlayState* play); diff --git a/src/code/z_kaleido_setup.c b/src/code/z_kaleido_setup.c index f48621ed3..3777781b2 100644 --- a/src/code/z_kaleido_setup.c +++ b/src/code/z_kaleido_setup.c @@ -8,6 +8,8 @@ #include "audio.h" #include "play_state.h" #include "save.h" +#include "gfx.h" +#include "debug.h" /* * The following three arrays are effectively unused. @@ -81,8 +83,9 @@ void KaleidoSetup_Update(PlayState* play) { if (IS_EVENT_EDITOR_ENABLED && BREG(0)) { pauseCtx->debugState = PAUSE_DEBUG_STATE_FLAG_SET_OPEN; } - } else if (CHECK_BTN_ALL(input->press.button, BTN_START)) { + } else if (CHECK_BTN_ALL(input->press.button, BTN_START) && !IS_INV_EDITOR_ACTIVE) { // The start button was pressed, pause + // doesn't run if the inventory editor is active gSaveContext.prevHudVisibilityMode = gSaveContext.hudVisibilityMode; R_PAUSE_BUTTON_LEFT_X = -175; diff --git a/src/code/z_kankyo.c b/src/code/z_kankyo.c index 8166f329b..2cc24c454 100644 --- a/src/code/z_kankyo.c +++ b/src/code/z_kankyo.c @@ -31,6 +31,7 @@ #include "play_state.h" #include "player.h" #include "save.h" +#include "debug.h" #include "assets/objects/gameplay_keep/gameplay_keep.h" #include "assets/objects/gameplay_field_keep/gameplay_field_keep.h" diff --git a/src/code/z_lifemeter.c b/src/code/z_lifemeter.c index a13b83207..5dc511d1f 100644 --- a/src/code/z_lifemeter.c +++ b/src/code/z_lifemeter.c @@ -8,6 +8,7 @@ #include "play_state.h" #include "player.h" #include "save.h" +#include "debug.h" #include "assets/textures/parameter_static/parameter_static.h" @@ -328,6 +329,14 @@ void Health_DrawMeter(PlayState* play) { u8* curBgImgLoaded = NULL; s32 ddHeartCountMinusOne = gSaveContext.save.info.inventory.defenseHearts - 1; + u8 posY = 0; + +#if IS_INV_EDITOR_ENABLED + if (IS_INV_EDITOR_ACTIVE) { + posY = gDebug.invDebug.miscDebug.hudTopPosY; + } +#endif + OPEN_DISPS(gfxCtx, "../z_lifemeter.c", 353); if (!(gSaveContext.save.info.playerData.health % 0x10)) { @@ -455,7 +464,7 @@ void Health_DrawMeter(PlayState* play) { } } - heartCenterY = 26.0f + offsetY; + heartCenterY = 26.0f + offsetY + posY; heartCenterX = 30.0f + offsetX; heartTexCoordPerPixel = 1.0f; heartTexCoordPerPixel /= 0.68f; @@ -489,7 +498,7 @@ void Health_DrawMeter(PlayState* play) { f32 wideOffsetX = USE_WIDESCREEN ? (offsetX - (30.f * WIDE_GET_16_9)) : offsetX; Matrix_SetTranslateScaleMtx2( matrix, 1.0f - (0.32f * beatingHeartPulsingSize), 1.0f - (0.32f * beatingHeartPulsingSize), - 1.0f - (0.32f * beatingHeartPulsingSize), -130.0f + wideOffsetX, 94.5f - offsetY, 0.0f); + 1.0f - (0.32f * beatingHeartPulsingSize), -130.0f + wideOffsetX, 94.5f - offsetY - posY, 0.0f); gSPMatrix(OVERLAY_DISP++, matrix, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); gSPVertex(OVERLAY_DISP++, beatingHeartVtx, 4, 0); gSP1Quadrangle(OVERLAY_DISP++, 0, 2, 3, 1, 0); diff --git a/src/code/z_map_exp.c b/src/code/z_map_exp.c index f7b3edbe3..93e2bfd91 100644 --- a/src/code/z_map_exp.c +++ b/src/code/z_map_exp.c @@ -17,6 +17,7 @@ #include "play_state.h" #include "player.h" #include "save.h" +#include "debug.h" #include "assets/objects/gameplay_keep/gameplay_keep.h" #include "assets/textures/parameter_static/parameter_static.h" diff --git a/src/code/z_parameter.c b/src/code/z_parameter.c index a06194fc9..7cfbf69c6 100644 --- a/src/code/z_parameter.c +++ b/src/code/z_parameter.c @@ -25,6 +25,7 @@ #include "play_state.h" #include "player.h" #include "save.h" +#include "debug.h" #include "assets/textures/parameter_static/parameter_static.h" #include "assets/textures/do_action_static/do_action_static.h" @@ -2345,10 +2346,12 @@ void Inventory_DeleteItem(u16 item, u16 invSlot) { PRINTF("\nItem_Register(%d)\n", invSlot, gSaveContext.save.info.inventory.items[invSlot]); - for (i = 1; i < 4; i++) { - if (gSaveContext.save.info.equips.buttonItems[i] == item) { - gSaveContext.save.info.equips.buttonItems[i] = ITEM_NONE; - gSaveContext.save.info.equips.cButtonSlots[i - 1] = SLOT_NONE; + if (!IS_INV_EDITOR_ACTIVE) { + for (i = 1; i < 4; i++) { + if (gSaveContext.save.info.equips.buttonItems[i] == item) { + gSaveContext.save.info.equips.buttonItems[i] = ITEM_NONE; + gSaveContext.save.info.equips.cButtonSlots[i - 1] = SLOT_NONE; + } } } } @@ -2996,20 +2999,31 @@ void Magic_DrawMeter(PlayState* play) { OPEN_DISPS(play->state.gfxCtx, "../z_parameter.c", 2650); - if (gSaveContext.save.info.playerData.magicLevel != 0) { + if (gSaveContext.save.info.playerData.magicLevel != 0 +#if IS_INV_EDITOR_ENABLED + || (gDebug.invDebug.miscDebug.showMiscScreen && gSaveContext.save.info.playerData.isMagicAcquired) +#endif + ) { + // NOLINTBEGIN if (gSaveContext.save.info.playerData.healthCapacity > 0xA0) magicMeterY = R_MAGIC_METER_Y_LOWER; // two rows of hearts else magicMeterY = R_MAGIC_METER_Y_HIGHER; // one row of hearts - // NOLINTEND + // NOLINTEND + +#if IS_INV_EDITOR_ENABLED + if (IS_INV_EDITOR_ACTIVE) { + magicMeterY += gDebug.invDebug.miscDebug.hudTopPosY; + } +#endif Gfx_SetupDL_39Overlay(play->state.gfxCtx); gDPSetPrimColor(OVERLAY_DISP++, 0, 0, sMagicBorderR, sMagicBorderG, sMagicBorderB, interfaceCtx->magicAlpha); gDPSetEnvColor(OVERLAY_DISP++, 100, 50, 50, 255); - // TODO: find something better + //! TODO: find something better { OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, gMagicMeterEndTex, 8, 16, WIDE_INCR(R_MAGIC_METER_X, -4), magicMeterY, WIDE_INCR(8, -2), 16, 1 << 10, 1 << 10); @@ -3041,7 +3055,7 @@ void Magic_DrawMeter(PlayState* play) { G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); - // TODO: find something better + //! TODO: find something better { s16 posX = WIDE_MULT(WIDE_INCR(R_MAGIC_FILL_X, 1), WIDE_GET_RATIO); s16 posRx = @@ -3056,7 +3070,7 @@ void Magic_DrawMeter(PlayState* play) { gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_MAGIC_FILL_COLOR(0), R_MAGIC_FILL_COLOR(1), R_MAGIC_FILL_COLOR(2), interfaceCtx->magicAlpha); - // TODO: find something better + //! TODO: find something better { s16 posX = WIDE_MULT(WIDE_INCR(R_MAGIC_FILL_X, 1), WIDE_GET_RATIO); s16 posRx = WIDE_MULT(WIDE_INCR((R_MAGIC_FILL_X + gSaveContext.magicTarget), 1), WIDE_GET_RATIO); @@ -3073,7 +3087,7 @@ void Magic_DrawMeter(PlayState* play) { G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); - // TODO: find something better + //! TODO: find something better { s16 posX = WIDE_MULT(WIDE_INCR(R_MAGIC_FILL_X, 1), WIDE_GET_RATIO); s16 posRx = @@ -3208,7 +3222,7 @@ void Interface_DrawItemButtons(PlayState* play) { (R_START_BTN_Y + 22) << 2, G_TX_RENDERTILE, 0, 0, (s32)(1.4277344 * (1 << 10)), (s32)(1.4277344 * (1 << 10))); #elif OOT_NTSC - // TODO: widescreen stuff for NTSC + //! TODO: widescreen stuff for NTSC gSPTextureRectangle(OVERLAY_DISP++, 132 << 2, 17 << 2, (132 + 22) << 2, (17 + 22) << 2, G_TX_RENDERTILE, 0, 0, (s32)(1.4277344 * (1 << 10)), (s32)(1.4277344 * (1 << 10))); #else @@ -3539,8 +3553,67 @@ void func_8008A994(InterfaceContext* interfaceCtx) { View_ApplyOrthoToOverlay(&interfaceCtx->view); } +void Interface_DrawSmallKeyCounter(PlayState* play) { + InterfaceContext* interfaceCtx = &play->interfaceCtx; + s16 svar3; + s16 smallKeyPosY = 0; + u16 mapIndex = gSaveContext.mapIndex; + +#if IS_INV_EDITOR_ENABLED + if (IS_INV_EDITOR_ACTIVE) { + smallKeyPosY = gDebug.invDebug.miscDebug.hudBottomPosY; + + if (smallKeyPosY > 0) { + smallKeyPosY -= gDebug.invDebug.miscDebug.invertVal; + } + + if (gDebug.invDebug.miscDebug.showMiscScreen) { + mapIndex = gDebug.invDebug.miscDebug.mapIndex; + } + } +#endif + OPEN_DISPS(play->state.gfxCtx, __FILE__, __LINE__); + + if (gSaveContext.save.info.inventory.dungeonKeys[mapIndex] >= 0) { + // Small Key Icon + gDPPipeSync(OVERLAY_DISP++); + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 200, 230, 255, interfaceCtx->magicAlpha); + gDPSetEnvColor(OVERLAY_DISP++, 0, 0, 20, 255); + OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, gSmallKeyCounterIconTex, 16, 16, WIDE_INCR(26, -7), + 190 - smallKeyPosY, WIDE_INCR(16, -4), 16, 1 << 10, 1 << 10); + + // Small Key Counter + gDPPipeSync(OVERLAY_DISP++); + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 255, 255, 255, interfaceCtx->magicAlpha); + gDPSetCombineLERP(OVERLAY_DISP++, 0, 0, 0, PRIMITIVE, TEXEL0, 0, PRIMITIVE, 0, 0, 0, 0, PRIMITIVE, TEXEL0, 0, + PRIMITIVE, 0); + + interfaceCtx->counterDigits[2] = 0; + interfaceCtx->counterDigits[3] = gSaveContext.save.info.inventory.dungeonKeys[mapIndex]; + + while (interfaceCtx->counterDigits[3] >= 10) { + interfaceCtx->counterDigits[2]++; + interfaceCtx->counterDigits[3] -= 10; + } + + svar3 = 42; + + if (interfaceCtx->counterDigits[2] != 0) { + OVERLAY_DISP = + Gfx_TextureI8(OVERLAY_DISP, ((u8*)gCounterDigit0Tex + (8 * 16 * interfaceCtx->counterDigits[2])), 8, 16, + svar3, 190 - smallKeyPosY, 8, 16, 1 << 10, 1 << 10); + svar3 += 8; + } + + OVERLAY_DISP = Gfx_TextureI8(OVERLAY_DISP, ((u8*)gCounterDigit0Tex + (8 * 16 * interfaceCtx->counterDigits[3])), + 8, 16, svar3, 190 - smallKeyPosY, 8, 16, 1 << 10, 1 << 10); + } + + CLOSE_DISPS(play->state.gfxCtx, __FILE__, __LINE__); +} + #if IS_INV_EDITOR_ENABLED || IS_EVENT_EDITOR_ENABLED -#define CAN_DRAW_INTERFACE (pauseCtx->debugState == PAUSE_DEBUG_STATE_CLOSED) +#define CAN_DRAW_INTERFACE (pauseCtx->debugState == PAUSE_DEBUG_STATE_CLOSED && !IS_INV_EDITOR_ACTIVE) #else #define CAN_DRAW_INTERFACE true #endif @@ -3576,6 +3649,16 @@ void Interface_Draw(PlayState* play) { s16 svar5; s16 timerId; + s16 rupeePosY = 0; +#if IS_INV_EDITOR_ENABLED + if (IS_INV_EDITOR_ACTIVE) { + rupeePosY = gDebug.invDebug.miscDebug.hudBottomPosY; + if (rupeePosY > 0) { + rupeePosY += gDebug.invDebug.miscDebug.invertVal; + } + } +#endif + OPEN_DISPS(play->state.gfxCtx, "../z_parameter.c", 3405); gSPSegment(OVERLAY_DISP++, 0x02, interfaceCtx->parameterSegment); @@ -3583,7 +3666,7 @@ void Interface_Draw(PlayState* play) { gSPSegment(OVERLAY_DISP++, 0x08, interfaceCtx->iconItemSegment); gSPSegment(OVERLAY_DISP++, 0x0B, interfaceCtx->mapSegment); - if (CAN_DRAW_INTERFACE) { + if (CAN_DRAW_INTERFACE || IS_INV_EDITOR_ACTIVE) { Interface_InitVertices(play); func_8008A994(interfaceCtx); Health_DrawMeter(play); @@ -3605,63 +3688,32 @@ void Interface_Draw(PlayState* play) { gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 200, 255, 100, interfaceCtx->magicAlpha); } gDPSetEnvColor(OVERLAY_DISP++, 0, 80, 0, 255); - OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, gRupeeCounterIconTex, 16, 16, WIDE_MULT(26, WIDE_GET_RATIO), 206, - 16, 16, WIDE_INCR(1, (u16)(WIDE_GET_RATIO)) << 10, 1 << 10); + OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, gRupeeCounterIconTex, 16, 16, WIDE_MULT(26, WIDE_GET_RATIO), + 206 - rupeePosY, 16, 16, WIDE_INCR(1, (u16)(WIDE_GET_RATIO)) << 10, 1 << 10); - switch (play->sceneId) { - case SCENE_FOREST_TEMPLE: - case SCENE_FIRE_TEMPLE: - case SCENE_WATER_TEMPLE: - case SCENE_SPIRIT_TEMPLE: - case SCENE_SHADOW_TEMPLE: - case SCENE_BOTTOM_OF_THE_WELL: - case SCENE_ICE_CAVERN: - case SCENE_GANONS_TOWER: - case SCENE_GERUDO_TRAINING_GROUND: - case SCENE_THIEVES_HIDEOUT: - case SCENE_INSIDE_GANONS_CASTLE: - case SCENE_GANONS_TOWER_COLLAPSE_INTERIOR: - case SCENE_INSIDE_GANONS_CASTLE_COLLAPSE: - case SCENE_TREASURE_BOX_SHOP: - if (gSaveContext.save.info.inventory.dungeonKeys[gSaveContext.mapIndex] >= 0) { - // Small Key Icon - gDPPipeSync(OVERLAY_DISP++); - gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 200, 230, 255, interfaceCtx->magicAlpha); - gDPSetEnvColor(OVERLAY_DISP++, 0, 0, 20, 255); - OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, gSmallKeyCounterIconTex, 16, 16, WIDE_INCR(26, -7), 190, - WIDE_INCR(16, -4), 16, 1 << 10, 1 << 10); - - // Small Key Counter - gDPPipeSync(OVERLAY_DISP++); - gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 255, 255, 255, interfaceCtx->magicAlpha); - gDPSetCombineLERP(OVERLAY_DISP++, 0, 0, 0, PRIMITIVE, TEXEL0, 0, PRIMITIVE, 0, 0, 0, 0, PRIMITIVE, - TEXEL0, 0, PRIMITIVE, 0); - - interfaceCtx->counterDigits[2] = 0; - interfaceCtx->counterDigits[3] = - gSaveContext.save.info.inventory.dungeonKeys[gSaveContext.mapIndex]; - - while (interfaceCtx->counterDigits[3] >= 10) { - interfaceCtx->counterDigits[2]++; - interfaceCtx->counterDigits[3] -= 10; - } - - svar3 = 42; - - if (interfaceCtx->counterDigits[2] != 0) { - OVERLAY_DISP = Gfx_TextureI8( - OVERLAY_DISP, ((u8*)gCounterDigit0Tex + (8 * 16 * interfaceCtx->counterDigits[2])), 8, 16, - svar3, 190, 8, 16, 1 << 10, 1 << 10); - svar3 += 8; - } - - OVERLAY_DISP = Gfx_TextureI8(OVERLAY_DISP, - ((u8*)gCounterDigit0Tex + (8 * 16 * interfaceCtx->counterDigits[3])), - 8, 16, svar3, 190, 8, 16, 1 << 10, 1 << 10); - } - break; - default: - break; + if (IS_INV_EDITOR_ACTIVE) { + Interface_DrawSmallKeyCounter(play); + } else { + switch (play->sceneId) { + case SCENE_FOREST_TEMPLE: + case SCENE_FIRE_TEMPLE: + case SCENE_WATER_TEMPLE: + case SCENE_SPIRIT_TEMPLE: + case SCENE_SHADOW_TEMPLE: + case SCENE_BOTTOM_OF_THE_WELL: + case SCENE_ICE_CAVERN: + case SCENE_GANONS_TOWER: + case SCENE_GERUDO_TRAINING_GROUND: + case SCENE_THIEVES_HIDEOUT: + case SCENE_INSIDE_GANONS_CASTLE: + case SCENE_GANONS_TOWER_COLLAPSE_INTERIOR: + case SCENE_INSIDE_GANONS_CASTLE_COLLAPSE: + case SCENE_TREASURE_BOX_SHOP: + Interface_DrawSmallKeyCounter(play); + break; + default: + break; + } } // Rupee Counter @@ -3701,11 +3753,18 @@ void Interface_Draw(PlayState* play) { for (svar1 = 0, svar3 = 42; svar1 < svar4; svar1++, svar2++, svar3 += 8) { OVERLAY_DISP = Gfx_TextureI8(OVERLAY_DISP, ((u8*)gCounterDigit0Tex + (8 * 16 * interfaceCtx->counterDigits[svar2])), 8, - 16, svar3, 206, 8, 16, 1 << 10, 1 << 10); + 16, svar3, 206 - rupeePosY, 8, 16, 1 << 10, 1 << 10); } Magic_DrawMeter(play); - Minimap_Draw(play); // TODO: fix the arrows + +#if IS_INV_EDITOR_ENABLED + if (gDebug.invDebug.miscDebug.showMiscScreen && gDebug.invDebug.elementsAlpha == 0) { + return; + } +#endif + + Minimap_Draw(play); //! TODO: fix the arrows if ((R_PAUSE_BG_PRERENDER_STATE != PAUSE_BG_PRERENDER_PROCESS) && (R_PAUSE_BG_PRERENDER_STATE != PAUSE_BG_PRERENDER_READY)) { @@ -4667,9 +4726,11 @@ void Interface_Update(PlayState* play) { WREG(7) = interfaceCtx->unk_1F4; // Update Magic - if (!IS_PAUSED(&play->pauseCtx) && (msgCtx->msgMode == MSGMODE_NONE) && - (play->transitionTrigger == TRANS_TRIGGER_OFF) && (play->gameOverCtx.state == GAMEOVER_INACTIVE) && - (play->transitionMode == TRANS_MODE_OFF) && ((play->csCtx.state == CS_STATE_IDLE) || !Player_InCsMode(play))) { + if ((!IS_PAUSED(&play->pauseCtx) && (msgCtx->msgMode == MSGMODE_NONE) && + (play->transitionTrigger == TRANS_TRIGGER_OFF) && (play->gameOverCtx.state == GAMEOVER_INACTIVE) && + (play->transitionMode == TRANS_MODE_OFF) && + ((play->csCtx.state == CS_STATE_IDLE) || !Player_InCsMode(play))) || + IS_INV_EDITOR_ACTIVE) { if (gSaveContext.save.info.playerData.isMagicAcquired && (gSaveContext.save.info.playerData.magicLevel == 0)) { gSaveContext.save.info.playerData.magicLevel = gSaveContext.save.info.playerData.isDoubleMagicAcquired + 1; diff --git a/src/code/z_play.c b/src/code/z_play.c index 30b2ba70c..4624f3443 100644 --- a/src/code/z_play.c +++ b/src/code/z_play.c @@ -335,6 +335,10 @@ void Play_Init(GameState* thisx) { #if ENABLE_HACKER_DEBUG gDebug.play = this; + gDebug.invDebug.state = INVEDITOR_STATE_OFF; + gDebug.invDebug.gfxCtx = this->state.gfxCtx; + gDebug.invDebug.pauseCtx = &this->pauseCtx; + gDebug.invDebug.elementsAlpha = 255; #endif if (gSaveContext.save.entranceIndex == ENTR_LOAD_OPENING) { diff --git a/src/code/z_rcp.c b/src/code/z_rcp.c index f3fd41f4d..98a9f9f17 100644 --- a/src/code/z_rcp.c +++ b/src/code/z_rcp.c @@ -1224,6 +1224,16 @@ void Gfx_SetupDL_39Overlay(GraphicsContext* gfxCtx) { CLOSE_DISPS(gfxCtx, "../z_rcp.c", 1811); } +#if DEBUG_FEATURES +void Gfx_SetupDL_39Debug(GraphicsContext* gfxCtx) { + OPEN_DISPS(gfxCtx, __FILE__, __LINE__); + + DEBUG_DISP = Gfx_SetupDL_39(DEBUG_DISP); + + CLOSE_DISPS(gfxCtx, __FILE__, __LINE__); +} +#endif + void Gfx_SetupDL_39Ptr(Gfx** gfxP) { Gfx* gfx = *gfxP; diff --git a/src/debug/collider_view.c b/src/debug/collider_view.c index 1ab53adff..0cba7599d 100644 --- a/src/debug/collider_view.c +++ b/src/debug/collider_view.c @@ -1,3 +1,4 @@ +#include "gfx.h" #include "debug.h" #include "collision_check.h" #include "play_state.h" diff --git a/src/debug/collision_view.c b/src/debug/collision_view.c index ca11ec7e3..15ee5d59a 100644 --- a/src/debug/collision_view.c +++ b/src/debug/collision_view.c @@ -1,8 +1,8 @@ +#include "gfx.h" #include "debug.h" #include "fault.h" #include "camera.h" #include "play_state.h" -#include "gfx.h" #include "sys_matrix.h" #if ENABLE_HACKER_DEBUG diff --git a/src/debug/inventory_editor.c b/src/debug/inventory_editor.c new file mode 100644 index 000000000..cb1c48ea3 --- /dev/null +++ b/src/debug/inventory_editor.c @@ -0,0 +1,1180 @@ +#include "config.h" + +#include "gfx.h" +#include "debug.h" +#include "scene.h" +#include "play_state.h" +#include "controller.h" +#include "save.h" +#include "attributes.h" +#include "build.h" +#include "array_count.h" +#include "printf.h" +#include "gfx_setupdl.h" + +#include "assets/textures/parameter_static/parameter_static.h" +#include "assets/textures/icon_item_24_static/icon_item_24_static.h" +#include "assets/textures/icon_item_static/icon_item_static.h" + +extern void Magic_Update(PlayState* play); + +static InvEditorMagicState sMagicState = INVEDITOR_MAGIC_STATE_NONE; + +u8 InventoryEditor_GetUpgradeType(u16 slotIndex) { + static u8 sUpgradeTypes[] = { + UPG_QUIVER, UPG_BOMB_BAG, UPG_STRENGTH, UPG_SCALE, UPG_BULLET_BAG, UPG_DEKU_STICKS, UPG_DEKU_NUTS, UPG_WALLET, + }; + + u8 upgradeType = sUpgradeTypes[slotIndex]; + + // make sure to show the correct upgrade for child link + if (gSaveContext.save.linkAge == LINK_AGE_CHILD) { + if (upgradeType == UPG_BULLET_BAG) { + upgradeType = UPG_QUIVER; + } else if (upgradeType == UPG_QUIVER) { + upgradeType = UPG_BULLET_BAG; + } + } + + return upgradeType; +} + +void InventoryEditor_SetItemFromSlot(InventoryEditor* this) { + // update the special items values, used for `INVEDITOR_GET_VARIABLE_ITEM` + + if (this->common.selectedSlot != SLOT_NONE && this->common.selectedItem != ITEM_NONE) { + if (IS_IN_RANGE(this->common.selectedSlot, SLOT_BOTTLE_1, SLOT_BOTTLE_4)) { + this->itemDebug.bottleItems[this->common.selectedSlot - SLOT_BOTTLE_1] = this->common.selectedItem; + } + + if (IS_IN_RANGE(this->common.selectedItem, ITEM_WEIRD_EGG, ITEM_SOLD_OUT)) { + this->itemDebug.childTradeItem = this->common.selectedItem; + } + + if (IS_IN_RANGE(this->common.selectedItem, ITEM_POCKET_EGG, ITEM_CLAIM_CHECK)) { + this->itemDebug.adultTradeItem = this->common.selectedItem; + } + + if (IS_IN_RANGE(this->common.selectedItem, ITEM_HOOKSHOT, ITEM_LONGSHOT)) { + this->itemDebug.hookshotType = this->common.selectedItem; + } + + if (IS_IN_RANGE(this->common.selectedItem, ITEM_OCARINA_FAIRY, ITEM_OCARINA_OF_TIME)) { + this->itemDebug.ocarinaType = this->common.selectedItem; + } + } +} + +void InventoryEditor_SetHUDAlpha(InventoryEditor* this) { + InterfaceContext* interfaceCtx = &gDebug.play->interfaceCtx; + + interfaceCtx->bAlpha = this->elementsAlpha; + interfaceCtx->aAlpha = this->elementsAlpha; + interfaceCtx->cLeftAlpha = this->elementsAlpha; + interfaceCtx->cDownAlpha = this->elementsAlpha; + interfaceCtx->cRightAlpha = this->elementsAlpha; + interfaceCtx->minimapAlpha = this->elementsAlpha; + interfaceCtx->startAlpha = this->elementsAlpha; + + if (!this->miscDebug.showMiscScreen) { + interfaceCtx->healthAlpha = this->elementsAlpha; + interfaceCtx->magicAlpha = this->elementsAlpha; + } +} + +void InventoryEditor_UpdateMiscScreen(InventoryEditor* this) { + s16 dgnIndexToMapIndex[] = { + SCENE_FOREST_TEMPLE, + SCENE_FIRE_TEMPLE, + SCENE_WATER_TEMPLE, + SCENE_SPIRIT_TEMPLE, + SCENE_SHADOW_TEMPLE, + -1, + SCENE_DEKU_TREE, + SCENE_DODONGOS_CAVERN, + SCENE_JABU_JABU, + SCENE_BOTTOM_OF_THE_WELL, + SCENE_ICE_CAVERN, + SCENE_GANONS_TOWER, + SCENE_GERUDO_TRAINING_GROUND, + SCENE_THIEVES_HIDEOUT, + SCENE_INSIDE_GANONS_CASTLE, + SCENE_TREASURE_BOX_SHOP, + }; + + // stick up or left + if (!this->miscDebug.stickMoved && (gDebug.input->rel.stick_y > 30 || gDebug.input->rel.stick_x < -30)) { + this->miscDebug.hudCursorPos--; + this->miscDebug.stickMoved = true; + } + + // stick down or right + if (!this->miscDebug.stickMoved && (gDebug.input->rel.stick_y < -30 || gDebug.input->rel.stick_x > 30)) { + this->miscDebug.hudCursorPos++; + this->miscDebug.stickMoved = true; + } + + if (gDebug.input->rel.stick_y == 0 && gDebug.input->rel.stick_x == 0) { + this->miscDebug.stickMoved = false; + } + + // make sure the value isn't out of bounds + if (this->miscDebug.hudCursorPos > INVEDITOR_CURSOR_POS_MAP) { + this->miscDebug.hudCursorPos = INVEDITOR_CURSOR_POS_HEARTS; + } + + if (this->miscDebug.hudCursorPos < INVEDITOR_CURSOR_POS_HEARTS) { + this->miscDebug.hudCursorPos = INVEDITOR_CURSOR_POS_MAP; + } + + // dungeon change + if (IS_IN_RANGE(this->miscDebug.hudCursorPos, INVEDITOR_CURSOR_POS_SMALL_KEYS, INVEDITOR_CURSOR_POS_MAP)) { + if (CHECK_BTN_ALL(gDebug.input->press.button, BTN_R)) { + this->miscDebug.hudDungeonIconIndex++; + if (this->miscDebug.hudDungeonIconIndex == 5) { // light medallion + this->miscDebug.hudDungeonIconIndex++; + } + } + + if (CHECK_BTN_ALL(gDebug.input->press.button, BTN_Z)) { + this->miscDebug.hudDungeonIconIndex--; + if (this->miscDebug.hudDungeonIconIndex == 5) { // light medallion + this->miscDebug.hudDungeonIconIndex--; + } + } + + // texture safeguards + if (this->miscDebug.hudDungeonIconIndex < 0) { + this->miscDebug.hudDungeonIconIndex = 15; + } + + if (this->miscDebug.hudDungeonIconIndex > 15) { + this->miscDebug.hudDungeonIconIndex = 0; + } + + this->miscDebug.mapIndex = dgnIndexToMapIndex[this->miscDebug.hudDungeonIconIndex]; + + if (this->miscDebug.mapIndex == -1) { + PRINTF("Something's wrong with the map index: %d\n", this->miscDebug.mapIndex); + return; + } + } + + switch (this->miscDebug.hudCursorPos) { + case INVEDITOR_CURSOR_POS_HEARTS: + if (CHECK_BTN_ALL(gDebug.input->press.button, BTN_A)) { + gSaveContext.save.info.playerData.isDoubleDefenseAcquired ^= 1; + this->miscDebug.updateDefenseHearts = true; + } + + if (this->miscDebug.updateDefenseHearts) { + if (gSaveContext.save.info.playerData.isDoubleDefenseAcquired) { + // 20 because 20 hearts in total + gSaveContext.save.info.inventory.defenseHearts = + TIMER_INCR(gSaveContext.save.info.inventory.defenseHearts, 20, 1); + } + + if (!gSaveContext.save.info.playerData.isDoubleDefenseAcquired) { + gSaveContext.save.info.inventory.defenseHearts = + TIMER_DECR(gSaveContext.save.info.inventory.defenseHearts, 0, 1); + } + + if (gSaveContext.save.info.inventory.defenseHearts == 20 || + gSaveContext.save.info.inventory.defenseHearts == 0) { + this->miscDebug.updateDefenseHearts = false; + } + } + + if (this->common.changeBy != 0) { + if (CHECK_BTN_ALL(gDebug.input->cur.button, BTN_Z)) { + gSaveContext.save.info.playerData.health += this->common.changeBy; + } else { + // heart counter increments by 0x10 for 1 heart + gSaveContext.save.info.playerData.healthCapacity += this->common.changeBy * 16; + gSaveContext.healthAccumulator = 0x140; // Refill 20 hearts + } + + if (gSaveContext.save.info.playerData.healthCapacity < 0) { + gSaveContext.save.info.playerData.healthCapacity = 0; + } + + if (gSaveContext.save.info.playerData.health < 0) { + gSaveContext.save.info.playerData.health = 0; + } + } + break; + case INVEDITOR_CURSOR_POS_MAGIC: + if (CHECK_BTN_ALL(gDebug.input->press.button, BTN_A)) { + // setup and switch to the next state when pressing A + switch (sMagicState) { + case INVEDITOR_MAGIC_STATE_NONE: + gSaveContext.save.info.playerData.isMagicAcquired = true; + gSaveContext.save.info.playerData.isDoubleMagicAcquired = false; + sMagicState = INVEDITOR_MAGIC_STATE_NORMAL; + break; + case INVEDITOR_MAGIC_STATE_NORMAL: + gSaveContext.save.info.playerData.isDoubleMagicAcquired = true; + sMagicState = INVEDITOR_MAGIC_STATE_DOUBLE; + break; + case INVEDITOR_MAGIC_STATE_DOUBLE: + gSaveContext.save.info.playerData.isMagicAcquired = false; + gSaveContext.save.info.playerData.isDoubleMagicAcquired = false; + gSaveContext.magicCapacity = 0; + gSaveContext.save.info.playerData.magic = 0; + sMagicState = INVEDITOR_MAGIC_STATE_NONE; + break; + default: + break; + } + + gSaveContext.save.info.playerData.magicLevel = 0; + + if (sMagicState != INVEDITOR_MAGIC_STATE_NONE) { + gSaveContext.magicFillTarget = gSaveContext.save.info.playerData.isDoubleMagicAcquired + ? MAGIC_DOUBLE_METER + : MAGIC_NORMAL_METER; + } + } + + // no need to increase the magic level if the magic meter isn't there + if (sMagicState != INVEDITOR_MAGIC_STATE_NONE && this->common.changeBy != 0) { + gSaveContext.save.info.playerData.magic += this->common.changeBy; + + if (gSaveContext.save.info.playerData.magic < 0) { + gSaveContext.save.info.playerData.magic = 0; + } + } + + break; + case INVEDITOR_CURSOR_POS_RUPEES: + if (this->common.changeBy != 0) { + gSaveContext.save.info.playerData.rupees += this->common.changeBy; + } + + if (gSaveContext.save.info.playerData.rupees < 0) { + gSaveContext.save.info.playerData.rupees = 0; + } + break; + case INVEDITOR_CURSOR_POS_SMALL_KEYS: + if (this->common.changeBy != 0 && this->common.changeBy != 100 && this->common.changeBy != -100) { + gSaveContext.save.info.inventory.dungeonKeys[this->miscDebug.mapIndex] += this->common.changeBy; + + if (gSaveContext.save.info.inventory.dungeonKeys[this->miscDebug.mapIndex] < 0) { + gSaveContext.save.info.inventory.dungeonKeys[this->miscDebug.mapIndex] = 0; + } + } + break; + case INVEDITOR_CURSOR_POS_BOSS_KEY: + case INVEDITOR_CURSOR_POS_COMPASS: + case INVEDITOR_CURSOR_POS_MAP: + if (CHECK_BTN_ALL(gDebug.input->press.button, BTN_A)) { + gSaveContext.save.info.inventory.dungeonItems[this->miscDebug.mapIndex] ^= + gBitFlags[this->miscDebug.hudCursorPos - INVEDITOR_CURSOR_POS_BOSS_KEY]; + } + break; + default: + break; + } +} + +void InventoryEditor_UpdateQuestScreen(InventoryEditor* this) { + // clang-format off + u8 slotToItem[] = { + ITEM_MEDALLION_FOREST, ITEM_MEDALLION_FIRE, ITEM_MEDALLION_WATER, ITEM_MEDALLION_SPIRIT, + ITEM_MEDALLION_SHADOW, ITEM_MEDALLION_LIGHT, ITEM_SONG_MINUET, ITEM_SONG_BOLERO, + ITEM_SONG_SERENADE, ITEM_SONG_REQUIEM, ITEM_SONG_NOCTURNE, ITEM_SONG_PRELUDE, + ITEM_SONG_LULLABY, ITEM_SONG_EPONA, ITEM_SONG_SARIA, ITEM_SONG_SUN, + ITEM_SONG_TIME, ITEM_SONG_STORMS, ITEM_KOKIRI_EMERALD, ITEM_GORON_RUBY, + ITEM_ZORA_SAPPHIRE, ITEM_STONE_OF_AGONY, ITEM_GERUDOS_CARD, ITEM_SKULL_TOKEN, + ITEM_HEART_PIECE + }; + // clang-format on + + this->common.selectedSlot = (this->common.selectedSlot == 231) ? 24 : this->common.selectedSlot; + + if (this->common.selectedSlot < ARRAY_COUNTU(slotToItem)) { + u8 item = slotToItem[this->common.selectedSlot]; + + // exclude heart pieces since it's not required + if (CHECK_BTN_ALL(gDebug.input->press.button, BTN_A) && item != ITEM_HEART_PIECE) { + u8 index = 0; + + if (IS_IN_RANGE(item, ITEM_MEDALLION_FOREST, ITEM_MEDALLION_LIGHT)) { + index = item - ITEM_MEDALLION_FOREST + QUEST_MEDALLION_FOREST; + } else if (IS_IN_RANGE(item, ITEM_SONG_MINUET, ITEM_SONG_STORMS)) { + index = item - ITEM_SONG_MINUET + QUEST_SONG_MINUET; + } else if (IS_IN_RANGE(item, ITEM_KOKIRI_EMERALD, ITEM_ZORA_SAPPHIRE)) { + index = item - ITEM_KOKIRI_EMERALD + QUEST_KOKIRI_EMERALD; + } else if (item == ITEM_STONE_OF_AGONY || item == ITEM_GERUDOS_CARD) { + index = item - ITEM_STONE_OF_AGONY + QUEST_STONE_OF_AGONY; + } else if (item == ITEM_SKULL_TOKEN) { + index = item - ITEM_SKULL_TOKEN + QUEST_SKULL_TOKEN; + } + + gSaveContext.save.info.inventory.questItems ^= gBitFlags[index]; + } + + if (this->common.changeBy != 0) { + switch (item) { + case ITEM_SKULL_TOKEN: + gSaveContext.save.info.inventory.gsTokens += this->common.changeBy; + + if (gSaveContext.save.info.inventory.gsTokens < 0) { + gSaveContext.save.info.inventory.gsTokens = 999; + } + + if (gSaveContext.save.info.inventory.gsTokens > 999) { + gSaveContext.save.info.inventory.gsTokens = 0; + } + break; + case ITEM_HEART_PIECE: + if (this->common.changeBy == 1 || this->common.changeBy == -1) { + gSaveContext.save.info.inventory.questItems += + (this->common.changeBy << QUEST_HEART_PIECE_COUNT); + } + + if (((gSaveContext.save.info.inventory.questItems & 0xF0000000) >> QUEST_HEART_PIECE_COUNT) > 3) { + u32 questItems = gSaveContext.save.info.inventory.questItems & 0x0FFFFFFF; + gSaveContext.save.info.inventory.questItems = (3 << QUEST_HEART_PIECE_COUNT) | questItems; + } + break; + default: + break; + } + } + } +} + +void InventoryEditor_UpdateEquipmentScreen(InventoryEditor* this) { + static u8 slotTo[] = { + ITEM_NONE, ITEM_SWORD_KOKIRI, ITEM_SWORD_MASTER, ITEM_SWORD_BIGGORON, + ITEM_NONE, ITEM_SHIELD_DEKU, ITEM_SHIELD_HYLIAN, ITEM_SHIELD_MIRROR, + ITEM_NONE, ITEM_TUNIC_KOKIRI, ITEM_TUNIC_GORON, ITEM_TUNIC_ZORA, + ITEM_NONE, ITEM_BOOTS_KOKIRI, ITEM_BOOTS_IRON, ITEM_BOOTS_HOVER, + }; + + if (this->pauseCtx->cursorX[PAUSE_EQUIP] > 0) { + this->common.selectedSlot = this->pauseCtx->cursorSlot[PAUSE_EQUIP]; + } else { + this->common.selectedSlot = this->pauseCtx->cursorY[PAUSE_EQUIP] * 4; + } + + if (CHECK_BTN_ALL(gDebug.input->press.button, BTN_CUP)) { + this->equipDebug.showMiscUpgrades ^= 1; + } + + if (CHECK_BTN_ALL(gDebug.input->press.button, BTN_A)) { + // equipment and upgrades are handled differently + if (!INVEDITOR_IS_UPGRADE(this->common) && slotTo[this->common.selectedSlot] != ITEM_NONE) { + u8 value = slotTo[this->common.selectedSlot] - ITEM_SWORD_KOKIRI; + u8 equip = value / 3; + u8 bgsEquipValue = EQUIP_INV_SWORD_BIGGORON; + + if (!CHECK_OWNED_EQUIP(equip, (value % 3))) { + // give equipment for selected slot + gSaveContext.save.info.inventory.equipment |= OWNED_EQUIP_FLAG(equip, (value % 3)); + + if (this->common.selectedSlot == SLOT_SWORD_BIGGORON) { + gSaveContext.save.info.playerData.bgsFlag = this->equipDebug.bgsFlag; + gSaveContext.save.info.playerData.swordHealth = this->equipDebug.swordHealth; + + if (!gSaveContext.save.info.playerData.bgsFlag && + gSaveContext.save.info.playerData.swordHealth == 0) { + bgsEquipValue = EQUIP_INV_SWORD_BROKENGIANTKNIFE; + } + + gSaveContext.save.info.inventory.equipment |= OWNED_EQUIP_FLAG(equip, bgsEquipValue); + } + } else { + // delete equipment for selected slot + gSaveContext.save.info.inventory.equipment &= ~OWNED_EQUIP_FLAG(equip, (value % 3)); + + if (this->common.selectedSlot == SLOT_SWORD_BIGGORON) { + this->equipDebug.bgsFlag = gSaveContext.save.info.playerData.bgsFlag; + this->equipDebug.swordHealth = gSaveContext.save.info.playerData.swordHealth; + + if (gSaveContext.save.info.playerData.bgsFlag) { + gSaveContext.save.info.playerData.bgsFlag = false; + } else if (gSaveContext.save.info.playerData.swordHealth == 0) { + bgsEquipValue = EQUIP_INV_SWORD_BROKENGIANTKNIFE; + } + + gSaveContext.save.info.inventory.equipment &= ~OWNED_EQUIP_FLAG(equip, bgsEquipValue); + } + } + } else { + u8 slotIndex = this->common.selectedSlot / 4; + u8 upgradeType; + s32 upgradeValue; + + if (this->equipDebug.showMiscUpgrades) { + slotIndex += 4; + } + + upgradeType = InventoryEditor_GetUpgradeType(slotIndex); + upgradeValue = CUR_UPG_VALUE(upgradeType); + + if (upgradeValue == 0) { + Inventory_ChangeUpgrade(upgradeType, this->equipDebug.upgradeSlots[slotIndex]); + } else { + this->equipDebug.upgradeSlots[slotIndex] = upgradeValue; + Inventory_ChangeUpgrade(upgradeType, 0); + } + } + } + + if (this->common.changeBy != 0) { + u8 upgradeType = InventoryEditor_GetUpgradeType(this->common.selectedSlot / 4); + u8 maxValue = 2; // there's only two diving scale/wallet upgrades + s8 value; + + switch (this->common.selectedSlot) { + case SLOT_UPG_BOMB_BAG: + case SLOT_UPG_STRENGTH: + case SLOT_UPG_QUIVER: + maxValue = 3; + FALLTHROUGH; + case SLOT_UPG_SCALE: + if (this->equipDebug.showMiscUpgrades) { + upgradeType = InventoryEditor_GetUpgradeType((this->common.selectedSlot / 4) + 4); + } + + value = CUR_UPG_VALUE(upgradeType) + this->common.changeBy; + if (value < 1) { + value = maxValue; + } else if (value > maxValue) { + value = 1; + } + + Inventory_ChangeUpgrade(upgradeType, value); + break; + case SLOT_SWORD_BIGGORON: { + u8 equipValue = EQUIP_INV_SWORD_KOKIRI; + u16 swordHealth = 1; + + if (gSaveContext.save.info.playerData.bgsFlag) { + gSaveContext.save.info.playerData.bgsFlag = false; + + if (this->common.changeBy > 0) { + swordHealth = 0; + equipValue = EQUIP_INV_SWORD_BROKENGIANTKNIFE; + } else { + swordHealth = 8; + equipValue = EQUIP_INV_SWORD_BIGGORON; + } + } else { + if (gSaveContext.save.info.playerData.swordHealth > 0) { + if (this->common.changeBy > 0) { + if (gSaveContext.save.info.playerData.swordHealth > 0) { + gSaveContext.save.info.playerData.bgsFlag = true; + } + } else { + swordHealth = 0; + equipValue = EQUIP_INV_SWORD_BROKENGIANTKNIFE; + } + } else { + if (this->common.changeBy < 0) { + gSaveContext.save.info.playerData.bgsFlag = true; + } else { + swordHealth = 8; + equipValue = EQUIP_INV_SWORD_BIGGORON; + } + } + } + + gSaveContext.save.info.playerData.swordHealth = + (swordHealth != 1) ? swordHealth : gSaveContext.save.info.playerData.swordHealth; + if (equipValue != EQUIP_INV_SWORD_KOKIRI) { + gSaveContext.save.info.inventory.equipment |= OWNED_EQUIP_FLAG(EQUIP_TYPE_SWORD, equipValue); + if (equipValue == EQUIP_INV_SWORD_BIGGORON) { + gSaveContext.save.info.inventory.equipment &= + ~OWNED_EQUIP_FLAG(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_BROKENGIANTKNIFE); + } + } + } break; + default: + break; + } + } +} + +void InventoryEditor_UpdateItemScreen(InventoryEditor* this) { + // Item ID corresponding to each slot, aside from bottles and trade items + static u8 sSlotToItems[] = { + ITEM_DEKU_STICK, ITEM_DEKU_NUT, ITEM_BOMB, ITEM_BOW, ITEM_ARROW_FIRE, ITEM_DINS_FIRE, + ITEM_SLINGSHOT, ITEM_OCARINA_FAIRY, ITEM_BOMBCHU, ITEM_HOOKSHOT, ITEM_ARROW_ICE, ITEM_FARORES_WIND, + ITEM_BOOMERANG, ITEM_LENS_OF_TRUTH, ITEM_MAGIC_BEAN, ITEM_HAMMER, ITEM_ARROW_LIGHT, ITEM_NAYRUS_LOVE, + }; + + InventoryEditor_SetItemFromSlot(this); + + // Delete and restore items + if (CHECK_BTN_ALL(gDebug.input->press.button, BTN_A)) { + if (gSaveContext.save.info.inventory.items[this->common.selectedSlot] == ITEM_NONE) { + u8 item = INVEDITOR_GET_VARIABLE_ITEM(this); // restore the special item + gSaveContext.save.info.inventory.items[this->common.selectedSlot] = + (item == ITEM_NONE) ? sSlotToItems[this->common.selectedSlot] : item; + } else { + // Delete the selected item + Inventory_DeleteItem(this->common.selectedItem, this->common.selectedSlot); + } + } + + // logic for the inventory screen + if (this->common.changeBy != 0 && this->common.selectedItem != ITEM_NONE) { + u8 item = this->common.selectedItem; + u8 slot = this->common.selectedSlot; + u8 min = ITEM_NONE, max = ITEM_NONE; + s8* pAmmo; + + switch (this->common.selectedSlot) { + case SLOT_DEKU_STICK: + case SLOT_DEKU_NUT: + case SLOT_BOMB: + case SLOT_BOW: + case SLOT_SLINGSHOT: + case SLOT_BOMBCHU: + case SLOT_MAGIC_BEAN: + //! TODO: separate this? the game increases both at the same time though + if (this->common.selectedSlot == SLOT_MAGIC_BEAN) { + BEANS_BOUGHT += this->common.changeBy; + + if (BEANS_BOUGHT > 99) { + BEANS_BOUGHT = 0; + } + + if (BEANS_BOUGHT < 0) { + BEANS_BOUGHT = 99; + } + } + + AMMO(this->common.selectedItem) += this->common.changeBy; + + if (AMMO(this->common.selectedItem) > 99) { + AMMO(this->common.selectedItem) = 0; + } + + if (AMMO(this->common.selectedItem) < 0) { + AMMO(this->common.selectedItem) = 99; + } + break; + case SLOT_BOTTLE_1: + case SLOT_BOTTLE_2: + case SLOT_BOTTLE_3: + case SLOT_BOTTLE_4: + min = ITEM_BOTTLE_EMPTY; + max = ITEM_BOTTLE_POE; + break; + case SLOT_TRADE_ADULT: + min = ITEM_POCKET_EGG; + max = ITEM_CLAIM_CHECK; + break; + case SLOT_TRADE_CHILD: + min = ITEM_WEIRD_EGG; + max = ITEM_SOLD_OUT; + break; + case SLOT_HOOKSHOT: + min = ITEM_HOOKSHOT; + max = ITEM_LONGSHOT; + case SLOT_OCARINA: + min = ITEM_OCARINA_FAIRY; + max = ITEM_OCARINA_OF_TIME; + default: + break; + } + + if (min != ITEM_NONE && max != ITEM_NONE) { + INVEDITOR_UPDATE_ITEM(this->common, min, max) + } + } +} + +void InventoryEditor_UpdateInformationScreen(InventoryEditor* this) { + // Background lifting/lowering animation + if (this->showInfoScreen || this->miscDebug.showMiscScreen) { + this->backgroundPosY = TIMER_DECR(this->backgroundPosY, INVEDITOR_BG_YPOS_TARGET, INVEDITOR_BG_ANIM_SPEED); + this->titlePosY = TIMER_DECR(this->titlePosY, INVEDITOR_TITLE_YPOS_TARGET, INVEDITOR_TITLE_ANIM_SPEED); + this->elementsAlpha = TIMER_DECR(this->elementsAlpha, 0, INVEDITOR_ALPHA_TRANS_SPEED); + } else { + this->backgroundPosY = TIMER_INCR(this->backgroundPosY, INVEDITOR_BG_YPOS, INVEDITOR_BG_ANIM_SPEED); + this->titlePosY = TIMER_INCR(this->titlePosY, INVEDITOR_TITLE_YPOS, INVEDITOR_TITLE_ANIM_SPEED); + this->elementsAlpha = TIMER_INCR(this->elementsAlpha, 255, INVEDITOR_ALPHA_TRANS_SPEED); + } + + // HUD lifting/lowering animation + if (this->miscDebug.showMiscScreen) { + this->miscDebug.hudTopPosY = + TIMER_INCR(this->miscDebug.hudTopPosY, INVEDITOR_HUD_TOP_YPOS_TARGET, INVEDITOR_HUD_TOP_ANIM_SPEED); + this->miscDebug.hudBottomPosY = TIMER_INCR(this->miscDebug.hudBottomPosY, INVEDITOR_HUD_BOTTOM_YPOS_TARGET, + INVEDITOR_HUD_BOTTOM_ANIM_SPEED); + this->miscDebug.invertVal = TIMER_INCR(this->miscDebug.invertVal, INVEDITOR_HUD_BOTTOM_INVERT_TARGET, + INVEDITOR_HUD_BOTTOM_INVERT_SPEED); + } else { + this->miscDebug.hudTopPosY = + TIMER_DECR(this->miscDebug.hudTopPosY, INVEDITOR_HUD_TOP_YPOS, INVEDITOR_HUD_TOP_ANIM_SPEED); + this->miscDebug.hudBottomPosY = + TIMER_DECR(this->miscDebug.hudBottomPosY, INVEDITOR_HUD_BOTTOM_YPOS, INVEDITOR_HUD_BOTTOM_ANIM_SPEED); + this->miscDebug.invertVal = + TIMER_DECR(this->miscDebug.invertVal, INVEDITOR_HUD_BOTTOM_YPOS, INVEDITOR_HUD_BOTTOM_INVERT_SPEED); + } + + if (!this->miscDebug.showMiscScreen) { + InventoryEditor_SetHUDAlpha(this); + } +} + +void InventoryEditor_DrawRectangle(InventoryEditor* this, s32 leftX, s32 leftY, s32 rightX, s32 rightY, + Color_RGBA8 rgba) { + Vec2s leftPos = { leftX, leftY }, rightPos = { rightX, rightY }; + Debug_DrawColorRectangle(leftPos, rightPos, rgba); +} + +void InventoryEditor_DrawMiscScreen(InventoryEditor* this) { + // Cursor + s32 leftX, leftY, rightX, rightY; + Color_RGBA8 rgba = { 0, 50, 220, 100 }; + s32 cursorPos[INVEDITOR_CURSOR_POS_MAX][4] = { + // { leftX, leftY, rightX, rightY }, + { 20, 55, 128, 77 }, // INVEDITOR_CURSOR_POS_HEARTS + { 20, 77, 128, 90 }, // INVEDITOR_CURSOR_POS_MAGIC + { 20, 90, 76, 106 }, // INVEDITOR_CURSOR_POS_RUPEES + { 20, 105, 66, 123 }, // INVEDITOR_CURSOR_POS_SMALL_KEYS + { 70, 105, 90, 123 }, // INVEDITOR_CURSOR_POS_BOSS_KEY + { 97, 105, 117, 123 }, // INVEDITOR_CURSOR_POS_COMPASS + { 124, 105, 144, 123 }, // INVEDITOR_CURSOR_POS_MAP + }; + + // Dungeon Icons + u8 index = this->miscDebug.hudDungeonIconIndex; + u8 width = ITEM_ICON_WIDTH; + u8 height = ITEM_ICON_HEIGHT; + u16 resizeFactor = 0; + void* dgnIconTextures[] = { + gQuestIconMedallionForestTex, gQuestIconMedallionFireTex, gQuestIconMedallionWaterTex, + gQuestIconMedallionSpiritTex, gQuestIconMedallionShadowTex, gQuestIconMedallionLightTex, + gQuestIconKokiriEmeraldTex, gQuestIconGoronRubyTex, gQuestIconZoraSapphireTex, + gItemIconLensOfTruthTex, gItemIconBottleBlueFireTex, gQuestIconDungeonBossKeyTex, + gQuestIconGerudosCardTex, gQuestIconSmallKeyTex, gQuestIconMedallionLightTex, + gQuestIconHeartPieceTex, + }; + const char noMagicStr[] = "(no magic meter)"; + + // Dungeon Items + u8 i; + u16 posX; + void* dgnItemTextures[] = { gQuestIconDungeonBossKeyTex, gQuestIconDungeonCompassTex, gQuestIconDungeonMapTex }; + + OPEN_DISPS(this->gfxCtx, __FILE__, __LINE__); + + // Cursor + if (this->miscDebug.hudCursorPos == INVEDITOR_CURSOR_POS_MAGIC) { + if (sMagicState == INVEDITOR_MAGIC_STATE_NORMAL) { + cursorPos[this->miscDebug.hudCursorPos][2] -= 48; + } else if (sMagicState == INVEDITOR_MAGIC_STATE_NONE) { + cursorPos[this->miscDebug.hudCursorPos][2] += strlen(noMagicStr) + 11; + } + } + + leftX = cursorPos[this->miscDebug.hudCursorPos][0]; + leftY = cursorPos[this->miscDebug.hudCursorPos][1]; + rightX = cursorPos[this->miscDebug.hudCursorPos][2]; + rightY = cursorPos[this->miscDebug.hudCursorPos][3]; + InventoryEditor_DrawRectangle(this, leftX, leftY, rightX, rightY, rgba); + Gfx_SetupDL_39Overlay(this->gfxCtx); + + // Dungeon Icons + if (index <= 8 || IS_IN_RANGE(index, 11, 15)) { + width = QUEST_ICON_WIDTH; + height = QUEST_ICON_HEIGHT; + } else { + resizeFactor = 400; + } + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 255, 255, 255, 255); + gDPLoadTextureBlock(OVERLAY_DISP++, dgnIconTextures[index], G_IM_FMT_RGBA, G_IM_SIZ_32b, width, height, 0, + G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, + G_TX_NOLOD); + gSPTextureRectangle(OVERLAY_DISP++, 26 + 64, 417 + 75, 100 + 64, 490 + 75, G_TX_RENDERTILE, 0, 0, + (1 << 10) + 270 + resizeFactor, (1 << 10) + 270 + resizeFactor); + + // Dungeon Items + for (posX = 258, i = 0; i < ARRAY_COUNTU(dgnItemTextures); posX += 110, i++) { + Color_RGBA8 rgba; + + if (CHECK_DUNGEON_ITEM(i, this->miscDebug.mapIndex)) { + rgba.r = rgba.g = rgba.b = rgba.a = 255; + } else { + rgba.r = rgba.g = rgba.b = rgba.a = 150; + } + + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, rgba.r, rgba.g, rgba.b, rgba.a); + + gDPLoadTextureBlock(OVERLAY_DISP++, dgnItemTextures[i], G_IM_FMT_RGBA, G_IM_SIZ_32b, QUEST_ICON_WIDTH, + QUEST_ICON_HEIGHT, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, + G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); + + gSPTextureRectangle(OVERLAY_DISP++, 26 + posX, 422, 95 + posX, 490, G_TX_RENDERTILE, 0, 0, (1 << 10) + 400, + (1 << 10) + 400); + } + + CLOSE_DISPS(this->gfxCtx, __FILE__, __LINE__); + + if (sMagicState == INVEDITOR_MAGIC_STATE_NONE) { + Print_Screen(&gDebug.printer, 3, 10, COLOR_WHITE, noMagicStr); + } +} + +void InventoryEditor_DrawDigit(InventoryEditor* this, void* texture, u8 posX, u8 posY, s16 alpha) { + static u8 drawDigit = true; + + // don't draw if it's the equipment screen and pressing Z or R + // since it will stay on the screen until the transition is over + if (CHECK_BTN_ALL(gDebug.input->press.button, BTN_Z) || CHECK_BTN_ALL(gDebug.input->press.button, BTN_R)) { + drawDigit = false; + } else if (this->pauseCtx->pageIndex != PAUSE_EQUIP) { + drawDigit = true; + } + + if (this->pauseCtx->pageIndex == PAUSE_EQUIP && drawDigit) { + OPEN_DISPS(this->gfxCtx, __FILE__, __LINE__); + + DEBUG_DISP = Gfx_TextureIA8(DEBUG_DISP, texture, 8, 8, posX, posY, 8, 8, 1 << 10, 1 << 10); + + CLOSE_DISPS(this->gfxCtx, __FILE__, __LINE__); + } +} + +void InventoryEditor_DrawEquipmentUpgrades(InventoryEditor* this, u16 i, s16 alpha) { + static u8 sUpgradeItems[] = { ITEM_QUIVER_30, ITEM_BOMB_BAG_20, ITEM_STRENGTH_GORONS_BRACELET, ITEM_SCALE_SILVER }; + static u8 sOtherUpgradeItem[] = { ITEM_BULLET_BAG_30, ITEM_DEKU_STICK, ITEM_DEKU_NUT, ITEM_ADULTS_WALLET }; + u8 upgradeValue; + void* texture = NULL; + void* ammoTexture = NULL; + u8 posY = 0; + + if (!this->equipDebug.showMiscUpgrades) { + upgradeValue = CUR_UPG_VALUE(InventoryEditor_GetUpgradeType(i)); + texture = gItemIcons[sUpgradeItems[i] + upgradeValue - 1]; + } else { + u8 item = sOtherUpgradeItem[i]; + + upgradeValue = CUR_UPG_VALUE(InventoryEditor_GetUpgradeType(i + 4)); + + if (item == ITEM_DEKU_STICK || item == ITEM_DEKU_NUT) { + texture = gItemIcons[item]; + posY = item == ITEM_DEKU_STICK ? 115 : 148; + + switch (upgradeValue) { + case 1: + ammoTexture = item == ITEM_DEKU_STICK ? gAmmoDigit1Tex : gAmmoDigit2Tex; + break; + case 2: + ammoTexture = item == ITEM_DEKU_STICK ? gAmmoDigit2Tex : gAmmoDigit3Tex; + break; + case 3: + ammoTexture = item == ITEM_DEKU_STICK ? gAmmoDigit3Tex : gAmmoDigit4Tex; + break; + default: + ammoTexture = NULL; + break; + } + } else { + texture = gItemIcons[item + upgradeValue - 1]; + } + } + + OPEN_DISPS(this->gfxCtx, __FILE__, __LINE__); + + if (upgradeValue != 0) { + if (texture != NULL) { + gDPLoadTextureBlock(POLY_OPA_DISP++, texture, G_IM_FMT_RGBA, G_IM_SIZ_32b, ITEM_ICON_WIDTH, + ITEM_ICON_HEIGHT, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, + G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); + gSP1Quadrangle(POLY_OPA_DISP++, 0, 2, 3, 1, 0); + } + + if (ammoTexture != NULL && posY != 0) { + Gfx_SetupDL_39Debug(this->gfxCtx); + gDPSetPrimColor(DEBUG_DISP++, 0, 0, 120, 255, 0, alpha); + InventoryEditor_DrawDigit(this, ammoTexture, 58, posY, alpha); + InventoryEditor_DrawDigit(this, gAmmoDigit0Tex, 64, posY, alpha); + } + } + + // draw page number + Gfx_SetupDL_39Debug(this->gfxCtx); + gDPSetPrimColor(DEBUG_DISP++, 0, 0, 255, 255, 255, alpha); + ammoTexture = this->equipDebug.showMiscUpgrades ? gAmmoDigit2Tex : gAmmoDigit1Tex; + InventoryEditor_DrawDigit(this, ammoTexture, 56, 191, alpha); + + CLOSE_DISPS(this->gfxCtx, __FILE__, __LINE__); +} + +void InventoryEditor_DrawInformationScreen(InventoryEditor* this) { + s16 posY = this->titlePosY + 2; + const char* ctrlsToPrint = NULL; + + // draw controls for the current inventory screen + if (!this->miscDebug.showMiscScreen) { + // clang-format off + switch (this->pauseCtx->pageIndex) { + case PAUSE_ITEM: + case PAUSE_QUEST: + ctrlsToPrint = ( + "[C-Left]: Decrement" INVEDITOR_PRINT_NEWLINE + "[C-Right]: Increment" INVEDITOR_PRINT_NEWLINE + "[C-Up]: Hold to change by 10" INVEDITOR_PRINT_NEWLINE + "[A]: Delete/Give item" INVEDITOR_PRINT_NEWLINE + ); + break; + case PAUSE_EQUIP: + ctrlsToPrint = ( + "[C-Left/C-Right]: Change Upgrade Type" INVEDITOR_PRINT_NEWLINE + "[C-Up]: Show Other Upgrades" INVEDITOR_PRINT_NEWLINE + "[A]: Delete/Give item\n" INVEDITOR_PRINT_NEWLINE + "Other Upgrades:" INVEDITOR_PRINT_NEWLINE + "- Bullet Bag" INVEDITOR_PRINT_NEWLINE + "- Deku Stick Capacity" INVEDITOR_PRINT_NEWLINE + "- Nut Capacity" INVEDITOR_PRINT_NEWLINE + "- Wallet" INVEDITOR_PRINT_NEWLINE + ); + break; + default: + ctrlsToPrint = NULL; + break; + } + // clang-format on + } else { + ctrlsToPrint = "[Z/R] Change dungeon" INVEDITOR_PRINT_NEWLINE; + } + + // draw build infos and controls for current inventory screen + Print_Screen(&gDebug.printer, 2, posY, COLOR_WHITE, "Build Version: %s", gBuildGitVersion); + + if (ctrlsToPrint != NULL) { + if (this->miscDebug.showMiscScreen) { + posY += 14; + } else { + posY += 3; + } + + Print_Screen(&gDebug.printer, 2, posY, COLOR_WHITE, ctrlsToPrint); + } + + Print_Screen(&gDebug.printer, 2, 28, COLOR_WHITE, "[B]: Misc Debug"); +} + +void InventoryEditor_Init(InventoryEditor* this) { + u8 upgradeSlots[] = { + ITEM_QUIVER_30, ITEM_BOMB_BAG_20, ITEM_STRENGTH_GORONS_BRACELET, + ITEM_SCALE_SILVER, ITEM_BULLET_BAG_30, ITEM_DEKU_STICK, + ITEM_DEKU_NUT, ITEM_ADULTS_WALLET, + }; + + // Init general variables + this->titleTimer = INVEDITOR_TITLE_TIMER; + this->titleState = INVEDITOR_TITLE_STATE_NAME; + this->showInfoScreen = false; + this->miscDebug.showMiscScreen = false; + this->backgroundPosY = INVEDITOR_BG_YPOS; + this->titlePosY = INVEDITOR_TITLE_YPOS; + this->common.changeBy = 0; + sMagicState = gSaveContext.save.info.playerData.isDoubleMagicAcquired ? INVEDITOR_MAGIC_STATE_DOUBLE + : gSaveContext.save.info.playerData.isMagicAcquired ? INVEDITOR_MAGIC_STATE_NORMAL + : INVEDITOR_MAGIC_STATE_NONE; + + if (this->common.state == INVEDITOR_COMMON_STATE_UNREADY) { + u8 i = 0; + + // Init item debug values + this->common.selectedItem = 0; + this->common.selectedSlot = 0; + this->itemDebug.childTradeItem = ITEM_WEIRD_EGG; + this->itemDebug.adultTradeItem = ITEM_POCKET_EGG; + this->itemDebug.hookshotType = ITEM_HOOKSHOT; + this->itemDebug.ocarinaType = ITEM_OCARINA_FAIRY; + + for (i = 0; i < ARRAY_COUNTU(this->itemDebug.bottleItems); i++) { + this->itemDebug.bottleItems[i] = ITEM_BOTTLE_EMPTY; + } + + // Init equipment debug values + this->equipDebug.showMiscUpgrades = false; + this->equipDebug.bgsFlag = gSaveContext.save.info.playerData.bgsFlag; + this->equipDebug.swordHealth = gSaveContext.save.info.playerData.swordHealth; + + for (i = 0; i < ARRAY_COUNTU(upgradeSlots); i++) { + this->equipDebug.upgradeSlots[i] = upgradeSlots[i]; + } + + // Init misc debug + this->miscDebug.hudTopPosY = INVEDITOR_HUD_TOP_YPOS; + this->miscDebug.hudBottomPosY = INVEDITOR_HUD_BOTTOM_YPOS; + this->miscDebug.invertVal = INVEDITOR_HUD_BOTTOM_YPOS; + this->miscDebug.hudCursorPos = INVEDITOR_CURSOR_POS_HEARTS; + this->miscDebug.hudDungeonIconIndex = 0; + this->miscDebug.mapIndex = SCENE_FOREST_TEMPLE; + this->miscDebug.stickMoved = false; + this->miscDebug.updateDefenseHearts = false; + + // Update state to ready + this->common.state = INVEDITOR_COMMON_STATE_READY; + } +} + +void InventoryEditor_Update(InventoryEditor* this) { + static u8 sTransitionState = INVEDITOR_TRANS_STATE_DONE; + u8 shouldUpdate = true; + + this->common.changeBy = 0; + + if (this->pauseCtx->pageIndex != PAUSE_MAP && this->pauseCtx->pageIndex != PAUSE_WORLD_MAP) { + this->common.selectedItem = this->pauseCtx->cursorItem[this->pauseCtx->pageIndex]; + this->common.selectedSlot = this->pauseCtx->cursorSlot[this->pauseCtx->pageIndex]; + } + + if (this->miscDebug.showMiscScreen && this->miscDebug.hudCursorPos == INVEDITOR_CURSOR_POS_MAGIC && + CHECK_BTN_ALL(gDebug.input->cur.button, BTN_Z)) { + if (CHECK_BTN_ALL(gDebug.input->cur.button, BTN_CLEFT)) { + this->common.changeBy = -1; + shouldUpdate = false; + } else if (CHECK_BTN_ALL(gDebug.input->cur.button, BTN_CRIGHT)) { + this->common.changeBy = 1; + shouldUpdate = false; + } + } + + if (shouldUpdate) { + if (CHECK_BTN_ALL(gDebug.input->press.button, BTN_CLEFT)) { + this->common.changeBy = -1; + } else if (CHECK_BTN_ALL(gDebug.input->press.button, BTN_CRIGHT)) { + this->common.changeBy = 1; + } + } + + if (CHECK_BTN_ALL(gDebug.input->cur.button, BTN_CUP) && CHECK_BTN_ALL(gDebug.input->press.button, BTN_CLEFT)) { + this->common.changeBy = -10; + } else if (CHECK_BTN_ALL(gDebug.input->cur.button, BTN_CUP) && + CHECK_BTN_ALL(gDebug.input->press.button, BTN_CRIGHT)) { + this->common.changeBy = 10; + } + + if (this->miscDebug.showMiscScreen) { + if (CHECK_BTN_ALL(gDebug.input->cur.button, BTN_R) && CHECK_BTN_ALL(gDebug.input->press.button, BTN_CLEFT)) { + this->common.changeBy = -100; + } else if (CHECK_BTN_ALL(gDebug.input->cur.button, BTN_R) && + CHECK_BTN_ALL(gDebug.input->press.button, BTN_CRIGHT)) { + this->common.changeBy = 100; + } + } + + // Toggle informations screen + if (CHECK_BTN_ALL(gDebug.input->press.button, BTN_CDOWN) && sTransitionState == INVEDITOR_TRANS_STATE_DONE) { + if (this->miscDebug.showMiscScreen) { + sTransitionState = INVEDITOR_TRANS_STATE_INFO_REQUESTED; + } else { + this->showInfoScreen ^= 1; + + if (this->titleState == INVEDITOR_TITLE_STATE_MISCDBG) { + this->titleState = INVEDITOR_TITLE_STATE_NAME; + } + } + } + + // Toggle Misc Debug + if (CHECK_BTN_ALL(gDebug.input->press.button, BTN_B) && sTransitionState == INVEDITOR_TRANS_STATE_DONE) { + if (this->showInfoScreen) { + sTransitionState = INVEDITOR_TRANS_STATE_MISC_REQUESTED; + } else { + this->miscDebug.showMiscScreen ^= 1; + + if (this->miscDebug.showMiscScreen) { + this->titleState = INVEDITOR_TITLE_STATE_MISCDBG; + } else { + this->titleState = INVEDITOR_TITLE_STATE_NAME; + } + } + } + + // handles the transition logic between infos and misc screens + // basically wait until the transition is over before starting the requested screen + switch (sTransitionState) { + case INVEDITOR_TRANS_STATE_INFO_REQUESTED: + this->showInfoScreen = false; + this->miscDebug.showMiscScreen = false; + sTransitionState = INVEDITOR_TRANS_STATE_INFO_SWITCHING; + break; + case INVEDITOR_TRANS_STATE_INFO_SWITCHING: + if (!this->miscDebug.showMiscScreen && this->backgroundPosY == INVEDITOR_BG_YPOS) { + this->showInfoScreen = true; + sTransitionState = INVEDITOR_TRANS_STATE_DONE; + } + break; + case INVEDITOR_TRANS_STATE_MISC_REQUESTED: + this->showInfoScreen = false; + this->miscDebug.showMiscScreen = false; + sTransitionState = INVEDITOR_TRANS_STATE_MISC_SWITCHING; + break; + case INVEDITOR_TRANS_STATE_MISC_SWITCHING: + if (!this->showInfoScreen && this->backgroundPosY == INVEDITOR_BG_YPOS) { + this->miscDebug.showMiscScreen = true; + sTransitionState = INVEDITOR_TRANS_STATE_DONE; + } + break; + default: + break; + } + + if (!this->showInfoScreen && this->miscDebug.showMiscScreen) { + this->miscElementsAlpha = TIMER_INCR(this->miscElementsAlpha, 255, INVEDITOR_ALPHA_TRANS_SPEED); + InventoryEditor_UpdateMiscScreen(this); + } else { + // Update the current screen if the cursor isn't on the L or R icons + if (this->pauseCtx->cursorSpecialPos != PAUSE_CURSOR_PAGE_LEFT && + this->pauseCtx->cursorSpecialPos != PAUSE_CURSOR_PAGE_RIGHT && !this->showInfoScreen) { + switch (this->pauseCtx->pageIndex) { + case PAUSE_ITEM: + InventoryEditor_UpdateItemScreen(this); + break; + case PAUSE_EQUIP: + InventoryEditor_UpdateEquipmentScreen(this); + break; + case PAUSE_QUEST: + InventoryEditor_UpdateQuestScreen(this); + break; + default: + break; + } + } + } + + InventoryEditor_UpdateInformationScreen(this); + + // Update the printing state, used to switch between several texts on-screen + this->titleTimer = TIMER_DECR(this->titleTimer, 0, 1); + if (this->titleTimer == 0) { + switch (this->titleState) { + case INVEDITOR_TITLE_STATE_NAME: + this->titleState = INVEDITOR_TITLE_STATE_COMMANDS; + break; + case INVEDITOR_TITLE_STATE_COMMANDS: + this->titleState = INVEDITOR_TITLE_STATE_NAME; + break; + default: + break; + } + + this->titleTimer = INVEDITOR_TITLE_TIMER; + } +} + +void InventoryEditor_Draw(InventoryEditor* this) { + // draw background for the "debug mode" text + Color_RGBA8 rgba = { 0, 0, 0, 150 }; + InventoryEditor_DrawRectangle(this, 0, this->backgroundPosY, SCREEN_WIDTH, SCREEN_HEIGHT, rgba); + + // draw bottom screen text, will be on top if in info mode + switch (this->titleState) { + case INVEDITOR_TITLE_STATE_NAME: + Print_Screen(&gDebug.printer, 14, this->titlePosY, COLOR_WHITE, "[DEBUG MODE]"); + break; + case INVEDITOR_TITLE_STATE_COMMANDS: + Print_Screen(&gDebug.printer, 9, this->titlePosY, COLOR_WHITE, "[C-DOWN: INFORMATIONS]"); + break; + case INVEDITOR_TITLE_STATE_MISCDBG: + Print_Screen(&gDebug.printer, 14, this->titlePosY, COLOR_WHITE, "[MISC DEBUG]"); + break; + default: + break; + } + + // draw the informations on the panel + if ((this->showInfoScreen || this->miscDebug.showMiscScreen) && this->titlePosY == INVEDITOR_TITLE_YPOS_TARGET) { + InventoryEditor_DrawInformationScreen(this); + + if (this->miscDebug.showMiscScreen) { + u8 mapIndex = this->miscDebug.hudDungeonIconIndex; + const char* dungeonNames[] = { + // clang-format off + "Forest Temple", "Fire Temple", "Water Temple", + "Spirit Temple", "Shadow Temple", NULL, + "Inside the Deku Tree", "Dodongo's Cavern", "Jabu-Jabu's Belly", + "Bottom of the Well", "Ice Cavern", "Ganon's Tower", + "Gerudo Training Grounds", "Thieves Hideout", "Ganon's Castle", + "Treasure Chest Minigame" + // clang-format on + }; + + if (dungeonNames[mapIndex] != NULL) { + Print_Screen(&gDebug.printer, 6, 16, COLOR_WHITE, dungeonNames[mapIndex]); + InventoryEditor_DrawMiscScreen(this); + } + } + + // draw separators (from top to bottom) + { + u8 i; + s32 positions[][4] = { + // { leftX, leftY, rightX, rightY }, + { 0, ((SCREEN_HEIGHT / 10) + 3), SCREEN_WIDTH, ((SCREEN_HEIGHT / 10) + 3) }, + { 0, ((SCREEN_HEIGHT / 5) + 4), SCREEN_WIDTH, ((SCREEN_HEIGHT / 5) + 5) }, + }; + + rgba.r = rgba.g = rgba.b = rgba.a = 255; + for (i = 0; i < ARRAY_COUNT(positions); i++) { + InventoryEditor_DrawRectangle(this, positions[i][0], positions[i][1], positions[i][2], positions[i][3], + rgba); + } + } + } +} + +bool InventoryEditor_Destroy(InventoryEditor* this) { + // Restore alpha values for the HUD/Inventory + if (this->showInfoScreen || this->miscDebug.showMiscScreen) { + this->showInfoScreen = false; + this->miscDebug.showMiscScreen = false; + } else { + // When the alpha hits 255 exit the inventory editor + if (this->elementsAlpha == 255 && this->backgroundPosY == INVEDITOR_BG_YPOS) { + this->pauseCtx->cursorSpecialPos = PAUSE_CURSOR_PAGE_LEFT; // avoids having the cursor on a blank slot + return true; + } + } + + // In order to make the transition properly we need to keep updating the info panel + // and draw stuff until everything's back to normal + InventoryEditor_UpdateInformationScreen(this); + InventoryEditor_Draw(this); + + return false; +} + +void InventoryEditor_Main(InventoryEditor* this) { + switch (this->state) { + case INVEDITOR_STATE_INIT: + PRINTF("[INVENTORY EDITOR]: Init Start!\n"); + this->state = INVEDITOR_STATE_UPDATE; + InventoryEditor_Init(this); + PRINTF("[INVENTORY EDITOR]: Init Complete!\n"); + break; + case INVEDITOR_STATE_UPDATE: + if (CHECK_BTN_ALL(gDebug.input->press.button, BTN_L)) { + this->state = INVEDITOR_STATE_DESTROY; + } + + if (this->common.state == INVEDITOR_COMMON_STATE_READY) { + InventoryEditor_Update(this); + InventoryEditor_Draw(this); + } + break; + case INVEDITOR_STATE_DESTROY: + if (InventoryEditor_Destroy(this)) { + this->state = INVEDITOR_STATE_OFF; + PRINTF("[INVENTORY EDITOR]: Quitting!\n"); + } + break; + default: + PRINTF("[INVENTORY EDITOR]: This state is not implemented yet.\n"); + break; + } +} diff --git a/src/debug/menu.c b/src/debug/menu.c index 99c231305..0efa3494d 100644 --- a/src/debug/menu.c +++ b/src/debug/menu.c @@ -1,3 +1,4 @@ +#include "gfx.h" #include "debug.h" #include "controller.h" #include "save.h" diff --git a/src/debug/print.c b/src/debug/print.c index 29a262627..3ae7e5e0b 100644 --- a/src/debug/print.c +++ b/src/debug/print.c @@ -1,7 +1,7 @@ #include "config.h" +#include "gfx.h" #include "debug.h" #include "controller.h" -#include "gfx.h" #include "gfxalloc.h" #include "printf.h" diff --git a/src/debug/utility.c b/src/debug/utility.c index 8cc708ebb..8ef40ae06 100644 --- a/src/debug/utility.c +++ b/src/debug/utility.c @@ -1,8 +1,8 @@ +#include "gfx.h" #include "debug.h" #include "config.h" #include "controller.h" #include "math.h" -#include "gfx.h" #if ENABLE_HACKER_DEBUG diff --git a/src/overlays/gamestates/ovl_debug_opening/debug_opening.c b/src/overlays/gamestates/ovl_debug_opening/debug_opening.c index 0a1e61fb0..7148e2175 100644 --- a/src/overlays/gamestates/ovl_debug_opening/debug_opening.c +++ b/src/overlays/gamestates/ovl_debug_opening/debug_opening.c @@ -17,8 +17,8 @@ #include "gfxalloc.h" #include "save.h" #include "sfx.h" -#include "debug.h" #include "gfx.h" +#include "debug.h" #include "letterbox.h" #include "build.h" #include "array_count.h" diff --git a/src/overlays/misc/ovl_kaleido_scope/z_kaleido_collect.c b/src/overlays/misc/ovl_kaleido_scope/z_kaleido_collect.c index aa6a4a017..91dc78e6a 100644 --- a/src/overlays/misc/ovl_kaleido_scope/z_kaleido_collect.c +++ b/src/overlays/misc/ovl_kaleido_scope/z_kaleido_collect.c @@ -9,6 +9,7 @@ #include "ocarina.h" #include "play_state.h" #include "save.h" +#include "debug.h" #include "assets/textures/parameter_static/parameter_static.h" #include "assets/textures/icon_item_static/icon_item_static.h" @@ -332,8 +333,8 @@ void KaleidoScope_DrawQuestStatus(PlayState* play, GraphicsContext* gfxCtx) { AudioOcarina_SetInstrument(OCARINA_INSTRUMENT_OFF); } } else if (pauseCtx->mainState == PAUSE_MAIN_STATE_IDLE_CURSOR_ON_SONG) { - if (CHECK_BTN_ALL(input->press.button, BTN_A) && (cursor >= QUEST_SONG_MINUET) && - (cursor < QUEST_KOKIRI_EMERALD)) { + if (!IS_INV_EDITOR_ACTIVE && CHECK_BTN_ALL(input->press.button, BTN_A) && + (cursor >= QUEST_SONG_MINUET) && (cursor < QUEST_KOKIRI_EMERALD)) { pauseCtx->mainState = PAUSE_MAIN_STATE_SONG_PLAYBACK_START; diff --git a/src/overlays/misc/ovl_kaleido_scope/z_kaleido_debug.c b/src/overlays/misc/ovl_kaleido_scope/z_kaleido_debug.c index 9ec189149..89d311233 100644 --- a/src/overlays/misc/ovl_kaleido_scope/z_kaleido_debug.c +++ b/src/overlays/misc/ovl_kaleido_scope/z_kaleido_debug.c @@ -794,7 +794,7 @@ void KaleidoScope_DrawInventoryEditor(PlayState* play) { if (pauseCtx->debugState == PAUSE_DEBUG_STATE_INVENTORY_EDITOR_OPENING) { pauseCtx->debugState = PAUSE_DEBUG_STATE_INVENTORY_EDITOR_OPEN; } else if ((pauseCtx->debugState == PAUSE_DEBUG_STATE_INVENTORY_EDITOR_OPEN) && - CHECK_BTN_ALL(input->press.button, BTN_L)) { + CHECK_BTN_ALL(input->press.button, BTN_CUP)) { pauseCtx->debugState = PAUSE_DEBUG_STATE_CLOSED; } diff --git a/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c b/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c index 1ac323712..48d5f64a7 100644 --- a/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c +++ b/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c @@ -10,6 +10,7 @@ #include "play_state.h" #include "player.h" #include "save.h" +#include "debug.h" #include "assets/textures/icon_item_static/icon_item_static.h" #include "assets/textures/parameter_static/parameter_static.h" @@ -81,12 +82,21 @@ void KaleidoScope_DrawEquipmentImage(PlayState* play, void* source, u32 width, u s32 pad; s32 i; + s16 alpha = pauseCtx->alpha; +#if IS_INV_EDITOR_ENABLED + if (gDebug.invDebug.showInfoScreen || gDebug.invDebug.miscDebug.showMiscScreen) { + alpha = gDebug.invDebug.elementsAlpha; + } else { + alpha = gDebug.invDebug.elementsAlpha < 255 ? gDebug.invDebug.elementsAlpha : pauseCtx->alpha; + } +#endif + OPEN_DISPS(play->state.gfxCtx, "../z_kaleido_equipment.c", 68); gDPPipeSync(POLY_OPA_DISP++); gDPSetCombineMode(POLY_OPA_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM); gDPSetTextureFilter(POLY_OPA_DISP++, G_TF_POINT); - gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, pauseCtx->alpha); + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, alpha); curTexture = source; remainingSize = width * height * G_IM_SIZ_16b_BYTES; @@ -193,10 +203,24 @@ void KaleidoScope_DrawEquipment(PlayState* play) { s16 oldCursorPoint; s16 cursorPoint; + s16 alpha = pauseCtx->alpha; + +#if IS_INV_EDITOR_ENABLED + if ((gDebug.invDebug.showInfoScreen || gDebug.invDebug.miscDebug.showMiscScreen)) { + alpha = gDebug.invDebug.elementsAlpha; + + if (alpha == 0) { + return; + } + } else { + alpha = gDebug.invDebug.elementsAlpha < 255 ? gDebug.invDebug.elementsAlpha : pauseCtx->alpha; + } +#endif + OPEN_DISPS(play->state.gfxCtx, "../z_kaleido_equipment.c", 219); gDPPipeSync(POLY_OPA_DISP++); - gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, ZREG(39), ZREG(40), ZREG(41), pauseCtx->alpha); + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, ZREG(39), ZREG(40), ZREG(41), alpha); gDPSetEnvColor(POLY_OPA_DISP++, ZREG(43), ZREG(44), ZREG(45), 0); // Draw EQUIP_QUAD_SELECTED_SWORD, EQUIP_QUAD_SELECTED_SHIELD, EQUIP_QUAD_SELECTED_TUNIC, EQUIP_QUAD_SELECTED_BOOTS @@ -239,17 +263,17 @@ void KaleidoScope_DrawEquipment(PlayState* play) { if (pauseCtx->cursorX[PAUSE_EQUIP] == EQUIP_CURSOR_X_UPG) { if (pauseCtx->cursorY[PAUSE_EQUIP] == EQUIP_CURSOR_Y_BULLETBAG_QUIVER) { //! @bug Assumes adult always has bullet bag (as adult this should rely on `UPG_QUIVER`) - if (CUR_UPG_VALUE(UPG_BULLET_BAG) != 0) { + if (IS_INV_EDITOR_ACTIVE || CUR_UPG_VALUE(UPG_BULLET_BAG) != 0) { cursorMoveResult = 1; } } else { - if (CUR_UPG_VALUE(pauseCtx->cursorY[PAUSE_EQUIP]) != 0) { + if (IS_INV_EDITOR_ACTIVE || CUR_UPG_VALUE(pauseCtx->cursorY[PAUSE_EQUIP]) != 0) { cursorMoveResult = 1; } } } else { - if (gBitFlags[pauseCtx->cursorPoint[PAUSE_EQUIP] - 1] & - gSaveContext.save.info.inventory.equipment) { + if (IS_INV_EDITOR_ACTIVE || gBitFlags[pauseCtx->cursorPoint[PAUSE_EQUIP] - 1] & + gSaveContext.save.info.inventory.equipment) { cursorMoveResult = 2; } } @@ -281,12 +305,12 @@ void KaleidoScope_DrawEquipment(PlayState* play) { pauseCtx->cursorPoint[PAUSE_EQUIP] += 1; if (pauseCtx->cursorX[PAUSE_EQUIP] == EQUIP_CURSOR_X_UPG) { - if (CUR_UPG_VALUE(pauseCtx->cursorY[PAUSE_EQUIP]) != 0) { + if (IS_INV_EDITOR_ACTIVE || CUR_UPG_VALUE(pauseCtx->cursorY[PAUSE_EQUIP]) != 0) { cursorMoveResult = 1; } } else { - if (gBitFlags[pauseCtx->cursorPoint[PAUSE_EQUIP] - 1] & - gSaveContext.save.info.inventory.equipment) { + if (IS_INV_EDITOR_ACTIVE || gBitFlags[pauseCtx->cursorPoint[PAUSE_EQUIP] - 1] & + gSaveContext.save.info.inventory.equipment) { cursorMoveResult = 2; } } @@ -329,17 +353,17 @@ void KaleidoScope_DrawEquipment(PlayState* play) { if (pauseCtx->cursorX[PAUSE_EQUIP] == EQUIP_CURSOR_X_UPG) { if (pauseCtx->cursorY[PAUSE_EQUIP] == EQUIP_CURSOR_Y_BULLETBAG_QUIVER) { - if (CUR_UPG_VALUE(UPG_BULLET_BAG) != 0) { + if (IS_INV_EDITOR_ACTIVE || CUR_UPG_VALUE(UPG_BULLET_BAG) != 0) { cursorMoveResult = 1; } } else { - if (CUR_UPG_VALUE(pauseCtx->cursorY[PAUSE_EQUIP]) != 0) { + if (IS_INV_EDITOR_ACTIVE || CUR_UPG_VALUE(pauseCtx->cursorY[PAUSE_EQUIP]) != 0) { cursorMoveResult = 1; } } } else { - if (gBitFlags[pauseCtx->cursorPoint[PAUSE_EQUIP] - 1] & - gSaveContext.save.info.inventory.equipment) { + if (IS_INV_EDITOR_ACTIVE || (gBitFlags[pauseCtx->cursorPoint[PAUSE_EQUIP] - 1] & + gSaveContext.save.info.inventory.equipment)) { cursorMoveResult = 2; } } @@ -354,12 +378,12 @@ void KaleidoScope_DrawEquipment(PlayState* play) { pauseCtx->cursorPoint[PAUSE_EQUIP] += 4; if (pauseCtx->cursorX[PAUSE_EQUIP] == EQUIP_CURSOR_X_UPG) { - if (CUR_UPG_VALUE(pauseCtx->cursorY[PAUSE_EQUIP]) != 0) { + if (IS_INV_EDITOR_ACTIVE || CUR_UPG_VALUE(pauseCtx->cursorY[PAUSE_EQUIP]) != 0) { cursorMoveResult = 1; } } else { - if (gBitFlags[pauseCtx->cursorPoint[PAUSE_EQUIP] - 1] & - gSaveContext.save.info.inventory.equipment) { + if (IS_INV_EDITOR_ACTIVE || (gBitFlags[pauseCtx->cursorPoint[PAUSE_EQUIP] - 1] & + gSaveContext.save.info.inventory.equipment)) { cursorMoveResult = 2; } } @@ -545,7 +569,8 @@ void KaleidoScope_DrawEquipment(PlayState* play) { if ((pauseCtx->cursorSpecialPos == 0) && (cursorItem != PAUSE_ITEM_NONE) && (pauseCtx->state == PAUSE_STATE_MAIN) && (pauseCtx->mainState == PAUSE_MAIN_STATE_IDLE) && - CHECK_BTN_ALL(input->press.button, BTN_A) && (pauseCtx->cursorX[PAUSE_EQUIP] != EQUIP_CURSOR_X_UPG)) { + CHECK_BTN_ALL(input->press.button, BTN_A) && !IS_INV_EDITOR_ACTIVE && + (pauseCtx->cursorX[PAUSE_EQUIP] != EQUIP_CURSOR_X_UPG)) { if (CHECK_AGE_REQ_EQUIP(pauseCtx->cursorY[PAUSE_EQUIP], pauseCtx->cursorX[PAUSE_EQUIP])) { Inventory_ChangeEquipment(pauseCtx->cursorY[PAUSE_EQUIP], pauseCtx->cursorX[PAUSE_EQUIP]); @@ -627,7 +652,7 @@ void KaleidoScope_DrawEquipment(PlayState* play) { Gfx_SetupDL_42Opa(play->state.gfxCtx); gDPSetCombineMode(POLY_OPA_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM); - gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, pauseCtx->alpha); + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, alpha); // for each row for (rowStart = 0, j = 0, temp = 0, i = 0; i < 4; i++, rowStart += 4, j += 4 * 4) { @@ -636,25 +661,31 @@ void KaleidoScope_DrawEquipment(PlayState* play) { // Draw upgrade `i` // EQUIP_QUAD_UPG_BULLETBAG_QUIVER, EQUIP_QUAD_UPG_BOMB_BAG, EQUIP_QUAD_UPG_STRENGTH, EQUIP_QUAD_UPG_SCALE - if (LINK_AGE_IN_YEARS == YEARS_CHILD) { - point = CUR_UPG_VALUE(sChildUpgrades[i]); - if (((u32)point != 0) && (CUR_UPG_VALUE(sChildUpgrades[i]) != 0)) { - KaleidoScope_DrawQuadTextureRGBA32(play->state.gfxCtx, - gItemIcons[sChildUpgradeItemBases[i] + point - 1], ITEM_ICON_WIDTH, - ITEM_ICON_HEIGHT, 0); + if (!IS_INV_EDITOR_ACTIVE) { + if (LINK_AGE_IN_YEARS == YEARS_CHILD) { + point = CUR_UPG_VALUE(sChildUpgrades[i]); + if (((u32)point != 0) && (CUR_UPG_VALUE(sChildUpgrades[i]) != 0)) { + KaleidoScope_DrawQuadTextureRGBA32(play->state.gfxCtx, + gItemIcons[sChildUpgradeItemBases[i] + point - 1], + ITEM_ICON_WIDTH, ITEM_ICON_HEIGHT, 0); + } + } else { + if ((i == 0) && (CUR_UPG_VALUE(sAdultUpgrades[i]) == 0)) { + // Show bullet bag instead of quiver if player has no quiver + //! @bug This assumes adult always has bullet bag + KaleidoScope_DrawQuadTextureRGBA32( + play->state.gfxCtx, + gItemIcons[sChildUpgradeItemBases[i] + CUR_UPG_VALUE(sChildUpgrades[i]) - 1], ITEM_ICON_WIDTH, + ITEM_ICON_HEIGHT, 0); + } else if (CUR_UPG_VALUE(sAdultUpgrades[i]) != 0) { + KaleidoScope_DrawQuadTextureRGBA32( + play->state.gfxCtx, + gItemIcons[sAdultUpgradeItemBases[i] + CUR_UPG_VALUE(sAdultUpgrades[i]) - 1], ITEM_ICON_WIDTH, + ITEM_ICON_HEIGHT, 0); + } } } else { - if ((i == 0) && (CUR_UPG_VALUE(sAdultUpgrades[i]) == 0)) { - // Show bullet bag instead of quiver if player has no quiver - //! @bug This assumes adult always has bullet bag - KaleidoScope_DrawQuadTextureRGBA32( - play->state.gfxCtx, gItemIcons[sChildUpgradeItemBases[i] + CUR_UPG_VALUE(sChildUpgrades[i]) - 1], - ITEM_ICON_WIDTH, ITEM_ICON_HEIGHT, 0); - } else if (CUR_UPG_VALUE(sAdultUpgrades[i]) != 0) { - KaleidoScope_DrawQuadTextureRGBA32( - play->state.gfxCtx, gItemIcons[sAdultUpgradeItemBases[i] + CUR_UPG_VALUE(sAdultUpgrades[i]) - 1], - ITEM_ICON_WIDTH, ITEM_ICON_HEIGHT, 0); - } + InventoryEditor_DrawEquipmentUpgrades(&gDebug.invDebug, i, alpha); } // Draw owned equips of type `i` diff --git a/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c b/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c index fd0f44c30..c89a83646 100644 --- a/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c +++ b/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c @@ -11,6 +11,7 @@ #include "widescreen.h" #include "play_state.h" #include "save.h" +#include "debug.h" #include "assets/textures/parameter_static/parameter_static.h" @@ -61,6 +62,19 @@ void KaleidoScope_DrawAmmoCount(PauseContext* pauseCtx, GraphicsContext* gfxCtx, s16 ammo; s16 ammoTens; + s16 alpha = pauseCtx->alpha; +#if IS_INV_EDITOR_ENABLED + if (gDebug.invDebug.showInfoScreen || gDebug.invDebug.miscDebug.showMiscScreen) { + alpha = gDebug.invDebug.elementsAlpha; + + if (alpha == 0) { + return; + } + } else { + alpha = gDebug.invDebug.elementsAlpha < 255 ? gDebug.invDebug.elementsAlpha : pauseCtx->alpha; + } +#endif + OPEN_DISPS(gfxCtx, "../z_kaleido_item.c", 69); ammo = AMMO(item); @@ -68,19 +82,19 @@ void KaleidoScope_DrawAmmoCount(PauseContext* pauseCtx, GraphicsContext* gfxCtx, gDPPipeSync(POLY_OPA_DISP++); if (!CHECK_AGE_REQ_SLOT(SLOT(item))) { - gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 100, 100, 100, pauseCtx->alpha); + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 100, 100, 100, alpha); } else { - gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, pauseCtx->alpha); + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, alpha); if (ammo == 0) { - gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 130, 130, 130, pauseCtx->alpha); + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 130, 130, 130, alpha); } else if ((item == ITEM_BOMB && AMMO(item) == CUR_CAPACITY(UPG_BOMB_BAG)) || (item == ITEM_BOW && AMMO(item) == CUR_CAPACITY(UPG_QUIVER)) || (item == ITEM_SLINGSHOT && AMMO(item) == CUR_CAPACITY(UPG_BULLET_BAG)) || (item == ITEM_DEKU_STICK && AMMO(item) == CUR_CAPACITY(UPG_DEKU_STICKS)) || (item == ITEM_DEKU_NUT && AMMO(item) == CUR_CAPACITY(UPG_DEKU_NUTS)) || (item == ITEM_BOMBCHU && ammo == 50) || (item == ITEM_MAGIC_BEAN && ammo == 15)) { - gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 120, 255, 0, pauseCtx->alpha); + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 120, 255, 0, alpha); } } @@ -144,6 +158,19 @@ void KaleidoScope_DrawItemSelect(PlayState* play) { s16 oldCursorPoint; s16 cursorMoveResult; + s16 alpha = pauseCtx->alpha; +#if IS_INV_EDITOR_ENABLED + if (gDebug.invDebug.showInfoScreen || gDebug.invDebug.miscDebug.showMiscScreen) { + alpha = gDebug.invDebug.elementsAlpha; + + if (alpha == 0) { + return; + } + } else { + alpha = gDebug.invDebug.elementsAlpha < 255 ? gDebug.invDebug.elementsAlpha : pauseCtx->alpha; + } +#endif + OPEN_DISPS(play->state.gfxCtx, "../z_kaleido_item.c", 234); Gfx_SetupDL_42Opa(play->state.gfxCtx); @@ -184,8 +211,9 @@ void KaleidoScope_DrawItemSelect(PlayState* play) { pauseCtx->cursorPoint[PAUSE_ITEM] -= 1; // if there's an item there, stop there - if (gSaveContext.save.info.inventory.items[pauseCtx->cursorPoint[PAUSE_ITEM]] != - ITEM_NONE) { + if (IS_INV_EDITOR_ACTIVE || + gSaveContext.save.info.inventory.items[pauseCtx->cursorPoint[PAUSE_ITEM]] != + ITEM_NONE) { cursorMoveResult = 1; } } else { @@ -221,8 +249,9 @@ void KaleidoScope_DrawItemSelect(PlayState* play) { pauseCtx->cursorX[PAUSE_ITEM]++; pauseCtx->cursorPoint[PAUSE_ITEM] += 1; - if (gSaveContext.save.info.inventory.items[pauseCtx->cursorPoint[PAUSE_ITEM]] != - ITEM_NONE) { + if (IS_INV_EDITOR_ACTIVE || + gSaveContext.save.info.inventory.items[pauseCtx->cursorPoint[PAUSE_ITEM]] != + ITEM_NONE) { cursorMoveResult = 1; } } else { @@ -269,7 +298,7 @@ void KaleidoScope_DrawItemSelect(PlayState* play) { cursorPoint = cursorX = cursorY = 0; while (true) { - if (gSaveContext.save.info.inventory.items[cursorPoint] != ITEM_NONE) { + if (IS_INV_EDITOR_ACTIVE || gSaveContext.save.info.inventory.items[cursorPoint] != ITEM_NONE) { pauseCtx->cursorPoint[PAUSE_ITEM] = cursorPoint; pauseCtx->cursorX[PAUSE_ITEM] = cursorX; pauseCtx->cursorY[PAUSE_ITEM] = cursorY; @@ -300,7 +329,7 @@ void KaleidoScope_DrawItemSelect(PlayState* play) { cursorPoint = cursorX = ITEM_GRID_COLS - 1; cursorY = 0; while (true) { - if (gSaveContext.save.info.inventory.items[cursorPoint] != ITEM_NONE) { + if (IS_INV_EDITOR_ACTIVE || gSaveContext.save.info.inventory.items[cursorPoint] != ITEM_NONE) { pauseCtx->cursorPoint[PAUSE_ITEM] = cursorPoint; pauseCtx->cursorX[PAUSE_ITEM] = cursorX; pauseCtx->cursorY[PAUSE_ITEM] = cursorY; @@ -336,8 +365,9 @@ void KaleidoScope_DrawItemSelect(PlayState* play) { pauseCtx->cursorY[PAUSE_ITEM]--; pauseCtx->cursorPoint[PAUSE_ITEM] -= ITEM_GRID_COLS; - if (gSaveContext.save.info.inventory.items[pauseCtx->cursorPoint[PAUSE_ITEM]] != - ITEM_NONE) { + if (IS_INV_EDITOR_ACTIVE || + gSaveContext.save.info.inventory.items[pauseCtx->cursorPoint[PAUSE_ITEM]] != + ITEM_NONE) { cursorMoveResult = 1; } } else { @@ -351,8 +381,9 @@ void KaleidoScope_DrawItemSelect(PlayState* play) { pauseCtx->cursorY[PAUSE_ITEM]++; pauseCtx->cursorPoint[PAUSE_ITEM] += ITEM_GRID_COLS; - if (gSaveContext.save.info.inventory.items[pauseCtx->cursorPoint[PAUSE_ITEM]] != - ITEM_NONE) { + if (IS_INV_EDITOR_ACTIVE || + gSaveContext.save.info.inventory.items[pauseCtx->cursorPoint[PAUSE_ITEM]] != + ITEM_NONE) { cursorMoveResult = 1; } } else { @@ -391,8 +422,8 @@ void KaleidoScope_DrawItemSelect(PlayState* play) { index = cursorSlot * 4; // required to match? KaleidoScope_SetCursorPos(pauseCtx, index, pauseCtx->itemVtx); - if ((pauseCtx->debugState == PAUSE_DEBUG_STATE_CLOSED) && (pauseCtx->state == PAUSE_STATE_MAIN) && - (pauseCtx->mainState == PAUSE_MAIN_STATE_IDLE)) { + if (!IS_INV_EDITOR_ACTIVE && (pauseCtx->debugState == PAUSE_DEBUG_STATE_CLOSED) && + (pauseCtx->state == PAUSE_STATE_MAIN) && (pauseCtx->mainState == PAUSE_MAIN_STATE_IDLE)) { if (CHECK_BTN_ANY(input->press.button, BTN_CLEFT | BTN_CDOWN | BTN_CRIGHT)) { if (CHECK_AGE_REQ_SLOT(cursorSlot) && (cursorItem != ITEM_SOLD_OUT)) { if (CHECK_BTN_ALL(input->press.button, BTN_CLEFT)) { @@ -457,7 +488,7 @@ void KaleidoScope_DrawItemSelect(PlayState* play) { gDPSetCombineLERP(OVERLAY_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0); - gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, pauseCtx->alpha); + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, alpha); gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 0); for (i = 0, j = ITEM_QUAD_GRID_SELECTED_C_LEFT * 4; i < 3; i++, j += 4) { @@ -471,7 +502,7 @@ void KaleidoScope_DrawItemSelect(PlayState* play) { gDPSetCombineMode(POLY_OPA_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM); for (i = j = 0; i < (ITEM_GRID_ROWS * ITEM_GRID_COLS); i++, j += 4) { - gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, pauseCtx->alpha); + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, alpha); if (gSaveContext.save.info.inventory.items[i] != ITEM_NONE) { if ((pauseCtx->mainState == PAUSE_MAIN_STATE_IDLE) && (pauseCtx->pageIndex == PAUSE_ITEM) && diff --git a/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope.c b/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope.c index f3327830e..0d3e33053 100644 --- a/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope.c +++ b/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope.c @@ -27,6 +27,7 @@ #include "play_state.h" #include "player.h" #include "save.h" +#include "debug.h" #include "assets/textures/icon_item_static/icon_item_static.h" #include "assets/textures/icon_item_24_static/icon_item_24_static.h" @@ -905,6 +906,9 @@ static s16 sCursorColors[][3] = { { 255, 255, 255 }, { 255, 255, 0 }, { KALEIDO_COLOR_CURSOR_UNK_R, KALEIDO_COLOR_CURSOR_UNK_G, KALEIDO_COLOR_CURSOR_UNK_B }, +#if IS_INV_EDITOR_ENABLED + { 255, 50, 0 }, // used for the inventory editor +#endif }; static void* sSavePromptMessageTexs[] = @@ -1102,13 +1106,20 @@ void KaleidoScope_SetupPageSwitch(PauseContext* pauseCtx, u8 pt) { } void KaleidoScope_HandlePageToggles(PauseContext* pauseCtx, Input* input) { - if ((pauseCtx->debugState == PAUSE_DEBUG_STATE_CLOSED) && CHECK_BTN_ALL(input->press.button, BTN_L)) { + if (!IS_INV_EDITOR_ACTIVE && pauseCtx->debugState == PAUSE_DEBUG_STATE_CLOSED && + CHECK_BTN_ALL(input->press.button, BTN_CUP)) { #if IS_INV_EDITOR_ENABLED pauseCtx->debugState = PAUSE_DEBUG_STATE_INVENTORY_EDITOR_OPENING; #endif return; } +#if IS_INV_EDITOR_ENABLED + if (gDebug.invDebug.miscDebug.showMiscScreen || gDebug.invDebug.showInfoScreen) { + return; + } +#endif + if (CHECK_BTN_ALL(input->press.button, BTN_R)) { KaleidoScope_SetupPageSwitch(pauseCtx, PAGE_SWITCH_PT_RIGHT); return; @@ -1154,6 +1165,13 @@ void KaleidoScope_DrawCursor(PlayState* play, u16 pageIndex) { (pauseCtx->mainState == PAUSE_MAIN_STATE_IDLE_CURSOR_ON_SONG)))) { s16 i; s16 j; + s16 cursorColorIndex = pauseCtx->cursorColorSet >> 2; + +#if IS_INV_EDITOR_ENABLED + if (IS_INV_EDITOR_ACTIVE) { + cursorColorIndex = 3; + } +#endif if (pauseCtx->pageIndex == pageIndex) { @@ -1162,9 +1180,8 @@ void KaleidoScope_DrawCursor(PlayState* play, u16 pageIndex) { gDPPipeSync(POLY_OPA_DISP++); gDPSetCombineLERP(POLY_OPA_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0); - gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, sCursorColors[pauseCtx->cursorColorSet >> 2][0], - sCursorColors[pauseCtx->cursorColorSet >> 2][1], - sCursorColors[pauseCtx->cursorColorSet >> 2][2], 255); + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, sCursorColors[cursorColorIndex][0], + sCursorColors[cursorColorIndex][1], sCursorColors[cursorColorIndex][2], 255); gDPSetEnvColor(POLY_OPA_DISP++, D_8082AB8C, D_8082AB90, D_8082AB94, 255); gSPVertex(POLY_OPA_DISP++, pauseCtx->cursorVtx, 16, 0); @@ -1224,8 +1241,9 @@ Gfx* KaleidoScope_DrawPageSections(Gfx* gfx, Vtx* vertices, void** textures) { void KaleidoScope_DrawPages(PlayState* play, GraphicsContext* gfxCtx) { #if N64_BTN_COLORS static s16 D_8082ACF4[][3] = { - { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 255, 255, 0 }, { 0, 0, 0 }, - { 0, 0, 0 }, { 255, 255, 0 }, { 0, 50, 255 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 50, 255 }, + { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 255, 255, 0 }, { 0, 0, 0 }, + { 0, 0, 0 }, { 255, 255, 0 }, { 0, 50, 255 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 50, 255 }, + { 255, 50, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 255, 50, 0 }, // used by the inventory editor }; #else static s16 D_8082ACF4[][3] = { @@ -1241,6 +1259,10 @@ void KaleidoScope_DrawPages(PlayState* play, GraphicsContext* gfxCtx) { { 0, 0, 0 }, { 0, 0, 0 }, { KALEIDO_COLOR_CURSOR_UNK_R, KALEIDO_COLOR_CURSOR_UNK_G, KALEIDO_COLOR_CURSOR_UNK_B }, + { 255, 50, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 255, 50, 0 }, // used by the inventory editor }; #endif static s16 D_8082AD3C = 20; @@ -1258,20 +1280,28 @@ void KaleidoScope_DrawPages(PlayState* play, GraphicsContext* gfxCtx) { if (!IS_PAUSE_STATE_GAMEOVER(pauseCtx)) { if (pauseCtx->state != PAUSE_STATE_SAVE_PROMPT) { - stepR = ABS(D_8082AB8C - D_8082ACF4[pauseCtx->cursorColorSet + D_8082AD40][0]) / D_8082AD3C; - stepG = ABS(D_8082AB90 - D_8082ACF4[pauseCtx->cursorColorSet + D_8082AD40][1]) / D_8082AD3C; - stepB = ABS(D_8082AB94 - D_8082ACF4[pauseCtx->cursorColorSet + D_8082AD40][2]) / D_8082AD3C; - if (D_8082AB8C >= D_8082ACF4[pauseCtx->cursorColorSet + D_8082AD40][0]) { + s16 cursorColorIndex = pauseCtx->cursorColorSet; + +#if IS_INV_EDITOR_ENABLED + if (IS_INV_EDITOR_ACTIVE) { + cursorColorIndex = 3 << 2; + } +#endif + + stepR = ABS(D_8082AB8C - D_8082ACF4[cursorColorIndex + D_8082AD40][0]) / D_8082AD3C; + stepG = ABS(D_8082AB90 - D_8082ACF4[cursorColorIndex + D_8082AD40][1]) / D_8082AD3C; + stepB = ABS(D_8082AB94 - D_8082ACF4[cursorColorIndex + D_8082AD40][2]) / D_8082AD3C; + if (D_8082AB8C >= D_8082ACF4[cursorColorIndex + D_8082AD40][0]) { D_8082AB8C -= stepR; } else { D_8082AB8C += stepR; } - if (D_8082AB90 >= D_8082ACF4[pauseCtx->cursorColorSet + D_8082AD40][1]) { + if (D_8082AB90 >= D_8082ACF4[cursorColorIndex + D_8082AD40][1]) { D_8082AB90 -= stepG; } else { D_8082AB90 += stepG; } - if (D_8082AB94 >= D_8082ACF4[pauseCtx->cursorColorSet + D_8082AD40][2]) { + if (D_8082AB94 >= D_8082ACF4[cursorColorIndex + D_8082AD40][2]) { D_8082AB94 -= stepB; } else { D_8082AB94 += stepB; @@ -1279,9 +1309,9 @@ void KaleidoScope_DrawPages(PlayState* play, GraphicsContext* gfxCtx) { D_8082AD3C--; if (D_8082AD3C == 0) { - D_8082AB8C = D_8082ACF4[pauseCtx->cursorColorSet + D_8082AD40][0]; - D_8082AB90 = D_8082ACF4[pauseCtx->cursorColorSet + D_8082AD40][1]; - D_8082AB94 = D_8082ACF4[pauseCtx->cursorColorSet + D_8082AD40][2]; + D_8082AB8C = D_8082ACF4[cursorColorIndex + D_8082AD40][0]; + D_8082AB90 = D_8082ACF4[cursorColorIndex + D_8082AD40][1]; + D_8082AB94 = D_8082ACF4[cursorColorIndex + D_8082AD40][2]; D_8082AD3C = ZREG(28 + D_8082AD40); D_8082AD40++; if (D_8082AD40 >= 4) { @@ -1658,6 +1688,14 @@ void KaleidoScope_DrawPages(PlayState* play, GraphicsContext* gfxCtx) { CLOSE_DISPS(gfxCtx, "../z_kaleido_scope_PAL.c", 1577); } +#if IS_INV_EDITOR_ENABLED +#define CHECK_ALPHA (gDebug.invDebug.elementsAlpha == 255) +#define CHECK_ALPHA2 ((pauseCtx->cursorItem[PAUSE_ITEM] != ITEM_NONE) && (gDebug.invDebug.elementsAlpha == 255)) +#else +#define CHECK_ALPHA (true) +#define CHECK_ALPHA2 (true) +#endif + /** * Draws the buttons for scrolling left/right, and the info plate. */ @@ -1900,7 +1938,7 @@ void KaleidoScope_DrawUIOverlay(PlayState* play) { gDPSetEnvColor(POLY_OPA_DISP++, 20, 30, 40, 0); if ((pauseCtx->state == PAUSE_STATE_MAIN) && (pauseCtx->namedItem != PAUSE_ITEM_NONE) && - (pauseCtx->nameDisplayTimer < WREG(89)) && + (pauseCtx->nameDisplayTimer < WREG(89)) && CHECK_ALPHA && (((u32)pauseCtx->mainState == PAUSE_MAIN_STATE_IDLE) || (pauseCtx->mainState == PAUSE_MAIN_STATE_SONG_PLAYBACK) || ((pauseCtx->mainState >= PAUSE_MAIN_STATE_SONG_PROMPT_INIT) && @@ -1923,10 +1961,21 @@ void KaleidoScope_DrawUIOverlay(PlayState* play) { gSPVertex(POLY_OPA_DISP++, &pauseCtx->uiOverlayVtx[16], 4, 0); - if (pauseCtx->nameColorSet == 1) { - gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 70, 70, 70, 255); - } else { - gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, 255); + { + u8 alpha = 255; + u8 colorIsGrey = pauseCtx->nameColorSet == 1 && !IS_INV_EDITOR_ACTIVE; + +#if IS_INV_EDITOR_ENABLED + if (IS_INV_EDITOR_ACTIVE) { + alpha = gDebug.invDebug.elementsAlpha; + } +#endif + + if (colorIsGrey) { + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 70, 70, 70, alpha); + } else { + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, alpha); + } } // Note that this is used to draw both item name and map name textures, it expects that the dimensions and @@ -2071,8 +2120,18 @@ void KaleidoScope_DrawUIOverlay(PlayState* play) { gSPDisplayList(POLY_OPA_DISP++, gCButtonIconsDL); - gDPPipeSync(POLY_OPA_DISP++); - gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, 255); + { + u8 alpha = 255; + +#if IS_INV_EDITOR_ENABLED + if (IS_INV_EDITOR_ACTIVE) { + alpha = gDebug.invDebug.elementsAlpha; + } +#endif + + gDPPipeSync(POLY_OPA_DISP++); + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, alpha); + } POLY_OPA_DISP = KaleidoScope_QuadTextureIA8(POLY_OPA_DISP, sToEquipTextTextures[gSaveContext.language], sToEquipTextWidths[gSaveContext.language], 16, 4); @@ -2168,7 +2227,7 @@ void KaleidoScope_UpdateNamePanel(PlayState* play) { osCreateMesgQueue(&pauseCtx->loadQueue, &pauseCtx->loadMsg, 1); - if (pauseCtx->namedItem != PAUSE_ITEM_NONE) { + if (pauseCtx->namedItem != PAUSE_ITEM_NONE && CHECK_ALPHA) { if ((pauseCtx->pageIndex == PAUSE_MAP) && !sInDungeonScene) { // `texIndex` is a `WorldMapPoint` enum value @@ -3429,7 +3488,7 @@ void KaleidoScope_DrawGameOver(PlayState* play) { } #if DEBUG_FEATURES && (ENABLE_INV_EDITOR || ENABLE_EVENT_EDITOR) -#define CAN_DRAW_PAUSE_MENU (pauseCtx->debugState == PAUSE_DEBUG_STATE_CLOSED) +#define CAN_DRAW_PAUSE_MENU (pauseCtx->debugState == PAUSE_DEBUG_STATE_CLOSED || IS_INV_EDITOR_ACTIVE) #else #define CAN_DRAW_PAUSE_MENU true #endif @@ -3475,8 +3534,8 @@ void KaleidoScope_Draw(PlayState* play) { } #if IS_INV_EDITOR_ENABLED - if ((pauseCtx->debugState == PAUSE_DEBUG_STATE_INVENTORY_EDITOR_OPENING) || - (pauseCtx->debugState == PAUSE_DEBUG_STATE_INVENTORY_EDITOR_OPEN)) { + if (!IS_INV_EDITOR_ACTIVE && (pauseCtx->debugState == PAUSE_DEBUG_STATE_INVENTORY_EDITOR_OPENING || + pauseCtx->debugState == PAUSE_DEBUG_STATE_INVENTORY_EDITOR_OPEN)) { KaleidoScope_DrawInventoryEditor(play); } #endif @@ -4134,7 +4193,7 @@ void KaleidoScope_Update(PlayState* play) { case PAUSE_STATE_MAIN: switch (pauseCtx->mainState) { case PAUSE_MAIN_STATE_IDLE: - if (CHECK_BTN_ALL(input->press.button, BTN_START)) { + if (CHECK_BTN_ALL(input->press.button, BTN_START) && !IS_INV_EDITOR_ACTIVE) { Interface_SetDoAction(play, DO_ACTION_NONE); pauseCtx->state = PAUSE_STATE_CLOSING; R_PAUSE_PAGES_Y_ORIGIN_2 = PAUSE_PAGES_Y_ORIGIN_2_LOWER; @@ -4142,7 +4201,7 @@ void KaleidoScope_Update(PlayState* play) { #if PLATFORM_GC && OOT_NTSC AudioOcarina_SetInstrument(OCARINA_INSTRUMENT_OFF); #endif - } else if (CHECK_BTN_ALL(input->press.button, BTN_B)) { + } else if (CHECK_BTN_ALL(input->press.button, BTN_B) && !IS_INV_EDITOR_ACTIVE) { pauseCtx->nextPageMode = 0; pauseCtx->promptChoice = 0; SFX_PLAY_CENTERED(NA_SE_SY_DECIDE); @@ -4179,7 +4238,7 @@ void KaleidoScope_Update(PlayState* play) { case PAUSE_MAIN_STATE_SONG_PROMPT: pauseCtx->ocarinaStaff = AudioOcarina_GetPlayingStaff(); - if (CHECK_BTN_ALL(input->press.button, BTN_START)) { + if (CHECK_BTN_ALL(input->press.button, BTN_START) && !IS_INV_EDITOR_ACTIVE) { AudioOcarina_SetInstrument(OCARINA_INSTRUMENT_OFF); Interface_SetDoAction(play, DO_ACTION_NONE); pauseCtx->state = PAUSE_STATE_CLOSING; @@ -4187,7 +4246,7 @@ void KaleidoScope_Update(PlayState* play) { func_800F64E0(0); pauseCtx->mainState = PAUSE_MAIN_STATE_IDLE; break; - } else if (CHECK_BTN_ALL(input->press.button, BTN_B)) { + } else if (CHECK_BTN_ALL(input->press.button, BTN_B) && !IS_INV_EDITOR_ACTIVE) { AudioOcarina_SetInstrument(OCARINA_INSTRUMENT_OFF); pauseCtx->mainState = PAUSE_MAIN_STATE_IDLE; pauseCtx->nextPageMode = 0; @@ -4231,14 +4290,14 @@ void KaleidoScope_Update(PlayState* play) { break; case PAUSE_MAIN_STATE_IDLE_CURSOR_ON_SONG: - if (CHECK_BTN_ALL(input->press.button, BTN_START)) { + if (CHECK_BTN_ALL(input->press.button, BTN_START) && !IS_INV_EDITOR_ACTIVE) { AudioOcarina_SetInstrument(OCARINA_INSTRUMENT_OFF); Interface_SetDoAction(play, DO_ACTION_NONE); pauseCtx->state = PAUSE_STATE_CLOSING; R_PAUSE_PAGES_Y_ORIGIN_2 = PAUSE_PAGES_Y_ORIGIN_2_LOWER; func_800F64E0(0); pauseCtx->mainState = PAUSE_MAIN_STATE_IDLE; - } else if (CHECK_BTN_ALL(input->press.button, BTN_B)) { + } else if (CHECK_BTN_ALL(input->press.button, BTN_B) && !IS_INV_EDITOR_ACTIVE) { AudioOcarina_SetInstrument(OCARINA_INSTRUMENT_OFF); pauseCtx->mainState = PAUSE_MAIN_STATE_IDLE; pauseCtx->nextPageMode = 0; @@ -4303,8 +4362,9 @@ void KaleidoScope_Update(PlayState* play) { sDelayTimer = 3; #endif } - } else if (CHECK_BTN_ALL(input->press.button, BTN_START) || - CHECK_BTN_ALL(input->press.button, BTN_B)) { + } else if ((CHECK_BTN_ALL(input->press.button, BTN_START) || + CHECK_BTN_ALL(input->press.button, BTN_B)) && + !IS_INV_EDITOR_ACTIVE) { Interface_SetDoAction(play, DO_ACTION_NONE); pauseCtx->savePromptState = PAUSE_SAVE_PROMPT_STATE_CLOSING; R_PAUSE_PAGES_Y_ORIGIN_2 = PAUSE_PAGES_Y_ORIGIN_2_LOWER; @@ -4321,8 +4381,9 @@ void KaleidoScope_Update(PlayState* play) { break; case PAUSE_SAVE_PROMPT_STATE_SAVED: - if (CHECK_BTN_ALL(input->press.button, BTN_B) || CHECK_BTN_ALL(input->press.button, BTN_A) || - CHECK_BTN_ALL(input->press.button, BTN_START) || (--sDelayTimer == 0)) { + if ((CHECK_BTN_ALL(input->press.button, BTN_B) || CHECK_BTN_ALL(input->press.button, BTN_A) || + CHECK_BTN_ALL(input->press.button, BTN_START) || (--sDelayTimer == 0)) && + !IS_INV_EDITOR_ACTIVE) { Interface_SetDoAction(play, DO_ACTION_NONE); gSaveContext.buttonStatus[0] = gSaveContext.buttonStatus[1] = gSaveContext.buttonStatus[2] = gSaveContext.buttonStatus[3] = BTN_ENABLED; @@ -4578,7 +4639,8 @@ void KaleidoScope_Update(PlayState* play) { pauseCtx->state = PAUSE_STATE_GAME_OVER_CONTINUE_PROMPT; gameOverCtx->state++; } else if ((sDelayTimer <= 80) && - (CHECK_BTN_ALL(input->press.button, BTN_A) || CHECK_BTN_ALL(input->press.button, BTN_START))) { + (CHECK_BTN_ALL(input->press.button, BTN_A) || CHECK_BTN_ALL(input->press.button, BTN_START)) && + !IS_INV_EDITOR_ACTIVE) { pauseCtx->state = PAUSE_STATE_GAME_OVER_CONTINUE_PROMPT; gameOverCtx->state++; func_800F64E0(0); @@ -4765,4 +4827,17 @@ void KaleidoScope_Update(PlayState* play) { PRINTF_RST(); break; } + +#if IS_INV_EDITOR_ENABLED + if (pauseCtx->state != PAUSE_STATE_SAVE_PROMPT && !IS_PAUSE_STATE_GAMEOVER(pauseCtx)) { + if (!IS_INV_EDITOR_ACTIVE && CHECK_BTN_ALL(play->state.input[0].press.button, BTN_L) && + (pauseCtx->debugState == PAUSE_DEBUG_STATE_CLOSED)) { + gDebug.invDebug.state = INVEDITOR_STATE_INIT; + } + + if (IS_INV_EDITOR_ACTIVE) { + InventoryEditor_Main(&gDebug.invDebug); + } + } +#endif }