From 4e15f0b3d181c871876ba0de19ea3cbe42d65caf Mon Sep 17 00:00:00 2001 From: KennyT <47287125+KennyDevT@users.noreply.github.com> Date: Sun, 15 May 2022 14:55:37 -0400 Subject: [PATCH 01/30] Add The Jenkins Link to the readme (#303) * Update README.md * Update README.md * Update README.md Fix Build --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 8a4538e2a..92fca0615 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,9 @@ Refer to the [building instructions](BUILDING.md) to compile SoH. - Affirm that you have an `/assets` folder filled with XMLs in the same directory as OTRGui.exe - Affirm that `zapd.exe` exists in the `/assets/extractor` folder +## Nightly Builds +Nightly builds of Ship of Harkinian are available at [https://builds.shipofharkinian.com/job/SoH_Multibranch/job/develop] + ## The Harbour Masters Are... From f217b9bb973e334ffc88e37b167cfffa45b4bd3f Mon Sep 17 00:00:00 2001 From: Sirius902 <10891979+Sirius902@users.noreply.github.com> Date: Sun, 15 May 2022 11:56:09 -0700 Subject: [PATCH 02/30] Workaround for rumble duration being too long (#284) --- soh/src/code/graph.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/soh/src/code/graph.c b/soh/src/code/graph.c index 4b1887c18..651d405d5 100644 --- a/soh/src/code/graph.c +++ b/soh/src/code/graph.c @@ -478,7 +478,10 @@ static void RunFrame() Graph_StartFrame(); - PadMgr_ThreadEntry(&gPadMgr); + // TODO: Workaround for rumble being too long. Implement os thread functions. + for (int i = 0; i < 3; i++) { + PadMgr_ThreadEntry(&gPadMgr); + } Graph_Update(&runFrameContext.gfxCtx, runFrameContext.gameState); ticksB = GetPerfCounter(); From 3e01b25573e2f8a70a2abd2829d0ea7c0a7f30da Mon Sep 17 00:00:00 2001 From: earthcrafterman Date: Sun, 15 May 2022 15:04:04 -0400 Subject: [PATCH 03/30] Add a toggle for muting the low HP alarm (#310) * Removes the code that plays the low health alarm sound effect, by removing that instead of making HealthMeter_IsCritical always return false, Link will still play the tired animation when low on health. * Made the low health alarm an enhancement toggle --- libultraship/libultraship/SohImGuiImpl.cpp | 1 + soh/src/code/z_lifemeter.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libultraship/libultraship/SohImGuiImpl.cpp b/libultraship/libultraship/SohImGuiImpl.cpp index 8e4becaab..45b305eb1 100644 --- a/libultraship/libultraship/SohImGuiImpl.cpp +++ b/libultraship/libultraship/SohImGuiImpl.cpp @@ -667,6 +667,7 @@ namespace SohImGui { EnhancementSliderInt("Text Speed: %dx", "##TEXTSPEED", "gTextSpeed", 1, 5, ""); EnhancementSliderInt("King Zora Speed: %dx", "##WEEPSPEED", "gMweepSpeed", 1, 5, ""); + EnhancementCheckbox("Mute Low HP Alarm", "gLowHpAlarm"); EnhancementCheckbox("Skip Text", "gSkipText"); Tooltip("Holding down B skips text"); EnhancementCheckbox("Minimal UI", "gMinimalUI"); diff --git a/soh/src/code/z_lifemeter.c b/soh/src/code/z_lifemeter.c index 344022505..5f1863440 100644 --- a/soh/src/code/z_lifemeter.c +++ b/soh/src/code/z_lifemeter.c @@ -498,8 +498,8 @@ void HealthMeter_HandleCriticalAlarm(GlobalContext* globalCtx) { if (interfaceCtx->unk_22A <= 0) { interfaceCtx->unk_22A = 0; interfaceCtx->unk_22C = 0; - if (!Player_InCsMode(globalCtx) && (globalCtx->pauseCtx.state == 0) && - (globalCtx->pauseCtx.debugState == 0) && HealthMeter_IsCritical() && !Gameplay_InCsMode(globalCtx)) { + if (CVar_GetS32("gLowHpAlarm", 0) == 0 && !Player_InCsMode(globalCtx) && (globalCtx->pauseCtx.state == 0) && + (globalCtx->pauseCtx.debugState == 0) && HealthMeter_IsCritical() && !Gameplay_InCsMode(globalCtx)) { func_80078884(NA_SE_SY_HITPOINT_ALARM); } } From a72ebbe84de7bf5f5c91f56ebe2dd963fd915513 Mon Sep 17 00:00:00 2001 From: Baoulettes Date: Sun, 15 May 2022 21:14:43 +0200 Subject: [PATCH 04/30] ACTOR_EN_FLOORMAS splitting fix (#311) * Fix infinite split * Update z_en_floormas.c --- soh/src/overlays/actors/ovl_En_Floormas/z_en_floormas.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/soh/src/overlays/actors/ovl_En_Floormas/z_en_floormas.c b/soh/src/overlays/actors/ovl_En_Floormas/z_en_floormas.c index 9e9e8f988..bc059daad 100644 --- a/soh/src/overlays/actors/ovl_En_Floormas/z_en_floormas.c +++ b/soh/src/overlays/actors/ovl_En_Floormas/z_en_floormas.c @@ -427,7 +427,8 @@ void EnFloormas_SetupFreeze(EnFloormas* this) { } void EnFloormas_Die(EnFloormas* this, GlobalContext* globalCtx) { - if (this->actor.scale.x > 0.004f) { + //Originally was doing > 0.004f, better fix thanks Gary :D + if (this->actor.scale.x > (f32)0.004f) { // split this->actor.shape.rot.y = this->actor.yawTowardsPlayer + 0x8000; EnFloormas_SetupSplit((EnFloormas*)this->actor.child); From b9c5b34eba9f83d22693630608d0200d4729b5e7 Mon Sep 17 00:00:00 2001 From: Emill Date: Sun, 15 May 2022 21:20:32 +0200 Subject: [PATCH 05/30] Fix strict aliasing issues (#342) Should fix linux build on -O2. --- libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp | 12 ++++++------ libultraship/libultraship/Lib/Fast3D/gfx_pc.h | 11 +++++------ 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp b/libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp index 6f7e8c271..c1a130b19 100644 --- a/libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp +++ b/libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp @@ -88,7 +88,7 @@ struct LoadedVertex { static struct { TextureCacheMap map; - list lru; + list lru; vector free_texture_ids; } gfx_texture_cache; @@ -527,18 +527,18 @@ static bool gfx_texture_cache_lookup(int i, int tile) { key = { orig_addr, { }, fmt, siz, palette_index }; } - auto it = gfx_texture_cache.map.find(key); + TextureCacheMap::iterator it = gfx_texture_cache.map.find(key); if (it != gfx_texture_cache.map.end()) { gfx_rapi->select_texture(i, it->second.texture_id); *n = &*it; - gfx_texture_cache.lru.splice(gfx_texture_cache.lru.end(), gfx_texture_cache.lru, *(list::iterator*)&it->second.lru_location); // move to back + gfx_texture_cache.lru.splice(gfx_texture_cache.lru.end(), gfx_texture_cache.lru, it->second.lru_location); // move to back return true; } if (gfx_texture_cache.map.size() >= TEXTURE_CACHE_MAX_SIZE) { // Remove the texture that was least recently used - it = gfx_texture_cache.lru.front(); + it = gfx_texture_cache.lru.front().it; gfx_texture_cache.free_texture_ids.push_back(it->second.texture_id); gfx_texture_cache.map.erase(it); gfx_texture_cache.lru.pop_front(); @@ -555,7 +555,7 @@ static bool gfx_texture_cache_lookup(int i, int tile) { it = gfx_texture_cache.map.insert(make_pair(key, TextureCacheValue())).first; TextureCacheNode* node = &*it; node->second.texture_id = texture_id; - *(list::iterator*)&node->second.lru_location = gfx_texture_cache.lru.insert(gfx_texture_cache.lru.end(), it); + node->second.lru_location = gfx_texture_cache.lru.insert(gfx_texture_cache.lru.end(), { it }); gfx_rapi->select_texture(i, texture_id); gfx_rapi->set_sampler_parameters(i, false, 0, 0); @@ -571,7 +571,7 @@ static void gfx_texture_cache_delete(const uint8_t* orig_addr) bool again = false; for (auto it = gfx_texture_cache.map.begin(bucket); it != gfx_texture_cache.map.end(bucket); ++it) { if (it->first.texture_addr == orig_addr) { - gfx_texture_cache.lru.erase(*(list::iterator*)&it->second.lru_location); + gfx_texture_cache.lru.erase(it->second.lru_location); gfx_texture_cache.free_texture_ids.push_back(it->second.texture_id); gfx_texture_cache.map.erase(it->first); again = true; diff --git a/libultraship/libultraship/Lib/Fast3D/gfx_pc.h b/libultraship/libultraship/Lib/Fast3D/gfx_pc.h index 62f80ab3c..2ecb68898 100644 --- a/libultraship/libultraship/Lib/Fast3D/gfx_pc.h +++ b/libultraship/libultraship/Lib/Fast3D/gfx_pc.h @@ -46,12 +46,11 @@ struct TextureCacheValue { uint8_t cms, cmt; bool linear_filter; - // Old versions of libstdc++ fail to compile this -#ifdef _MSC_VER - std::list::iterator lru_location; -#else - std::list::iterator lru_location; -#endif + std::list::iterator lru_location; +}; + +struct TextureCacheMapIter { + TextureCacheMap::iterator it; }; extern "C" { From 6dbb085a82cde19352919606f5c4e77f97439505 Mon Sep 17 00:00:00 2001 From: Rozelette Date: Sun, 15 May 2022 14:26:54 -0500 Subject: [PATCH 06/30] Add equipable tunics/boots (#328) --- libultraship/libultraship/SohImGuiImpl.cpp | 2 + soh/include/z64item.h | 6 ++ soh/include/z64player.h | 11 ++- soh/src/code/z_parameter.c | 10 ++- soh/src/code/z_player_lib.c | 3 +- .../actors/ovl_player_actor/z_player.c | 45 +++++++++- .../ovl_kaleido_scope/z_kaleido_equipment.c | 77 ++++++++++++----- .../misc/ovl_kaleido_scope/z_kaleido_item.c | 84 ++++++++++--------- .../misc/ovl_kaleido_scope/z_kaleido_scope.h | 1 + .../ovl_kaleido_scope/z_kaleido_scope_PAL.c | 16 ++++ 10 files changed, 191 insertions(+), 64 deletions(-) diff --git a/libultraship/libultraship/SohImGuiImpl.cpp b/libultraship/libultraship/SohImGuiImpl.cpp index 45b305eb1..78532d85b 100644 --- a/libultraship/libultraship/SohImGuiImpl.cpp +++ b/libultraship/libultraship/SohImGuiImpl.cpp @@ -676,6 +676,8 @@ namespace SohImGui { Tooltip("Wearing the Bunny Hood grants a speed increase like in Majora's Mask"); EnhancementCheckbox("Visual Stone of Agony", "gVisualAgony"); Tooltip("Displays an icon and plays a sound when Stone of Agony should be activated, for those without rumble"); + EnhancementCheckbox("Assignable Tunics and Boots", "gAssignableTunicsAndBoots"); + Tooltip("Allows equiping the tunic and boots to c-buttons"); ImGui::Text("Graphics"); ImGui::Separator(); diff --git a/soh/include/z64item.h b/soh/include/z64item.h index 05b2a24b2..6cb5ec2a4 100644 --- a/soh/include/z64item.h +++ b/soh/include/z64item.h @@ -78,6 +78,12 @@ typedef enum { /* 0x15 */ SLOT_BOTTLE_4, /* 0x16 */ SLOT_TRADE_ADULT, /* 0x17 */ SLOT_TRADE_CHILD, + /* 0x18 */ SLOT_TUNIC_KOKIRI, + /* 0x19 */ SLOT_TUNIC_GORON, + /* 0x1A */ SLOT_TUNIC_ZORA, + /* 0x1B */ SLOT_BOOTS_KOKIRI, + /* 0x1C */ SLOT_BOOTS_IRON, + /* 0x1D */ SLOT_BOOTS_HOVER, /* 0xFF */ SLOT_NONE = 0xFF } InventorySlot; diff --git a/soh/include/z64player.h b/soh/include/z64player.h index 6771ef5c6..9bce60ffe 100644 --- a/soh/include/z64player.h +++ b/soh/include/z64player.h @@ -128,7 +128,16 @@ typedef enum { /* 0x40 */ PLAYER_AP_MASK_GERUDO, /* 0x41 */ PLAYER_AP_MASK_TRUTH, /* 0x42 */ PLAYER_AP_LENS, - /* 0x43 */ PLAYER_AP_MAX + /* 0x43 */ PLAYER_AP_SHIELD_DEKU, + /* 0x44 */ PLAYER_AP_SHIELD_HYLIAN, + /* 0x45 */ PLAYER_AP_SHIELD_MIRROR, + /* 0x46 */ PLAYER_AP_TUNIC_KOKIRI, + /* 0x47 */ PLAYER_AP_TUNIC_GORON, + /* 0x48 */ PLAYER_AP_TUNIC_ZORA, + /* 0x49 */ PLAYER_AP_BOOTS_KOKIRI, + /* 0x4A */ PLAYER_AP_BOOTS_IRON, + /* 0x4B */ PLAYER_AP_BOOTS_HOVER, + /* 0x4C */ PLAYER_AP_MAX } PlayerActionParam; typedef enum { diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index edc4348b9..8cfcccbf5 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -753,7 +753,15 @@ void func_80083108(GlobalContext* globalCtx) { gSaveContext.buttonStatus[0] = BTN_DISABLED; for (i = 1; i < 4; i++) { - if (func_8008F2F8(globalCtx) == 2) { + if ((gSaveContext.equips.buttonItems[i] >= ITEM_SHIELD_DEKU) && + (gSaveContext.equips.buttonItems[i] <= ITEM_BOOTS_HOVER)) { + // Equipment on c-buttons is always enabled + if (gSaveContext.buttonStatus[i] == BTN_DISABLED) { + sp28 = 1; + } + + gSaveContext.buttonStatus[i] = BTN_ENABLED; + } else if (func_8008F2F8(globalCtx) == 2) { if ((gSaveContext.equips.buttonItems[i] != ITEM_HOOKSHOT) && (gSaveContext.equips.buttonItems[i] != ITEM_LONGSHOT)) { if (gSaveContext.buttonStatus[i] == BTN_ENABLED) { diff --git a/soh/src/code/z_player_lib.c b/soh/src/code/z_player_lib.c index 355d323e0..4e4e1ff70 100644 --- a/soh/src/code/z_player_lib.c +++ b/soh/src/code/z_player_lib.c @@ -29,7 +29,8 @@ s16 sBootData[PLAYER_BOOTS_MAX][17] = { // Used to map action params to model groups u8 sActionModelGroups[] = { 3, 15, 10, 2, 2, 5, 10, 11, 6, 6, 6, 6, 6, 6, 6, 6, 9, 9, 7, 7, 8, 3, 3, 6, 3, 3, 3, 3, 12, 13, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3 }; TextTriggerEntry sTextTriggers[] = { diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index 24ad28c4a..733bdee2d 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -898,6 +898,15 @@ static s8 sItemActionParams[] = { PLAYER_AP_SWORD_KOKIRI, PLAYER_AP_SWORD_MASTER, PLAYER_AP_SWORD_BGS, + PLAYER_AP_SHIELD_DEKU, + PLAYER_AP_SHIELD_HYLIAN, + PLAYER_AP_SHIELD_MIRROR, + PLAYER_AP_TUNIC_KOKIRI, + PLAYER_AP_TUNIC_GORON, + PLAYER_AP_TUNIC_ZORA, + PLAYER_AP_BOOTS_KOKIRI, + PLAYER_AP_BOOTS_IRON, + PLAYER_AP_BOOTS_HOVER, }; static s32(*D_80853EDC[])(Player* this, GlobalContext* globalCtx) = { @@ -910,7 +919,8 @@ static s32(*D_80853EDC[])(Player* this, GlobalContext* globalCtx) = { func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C, - func_8083485C, func_8083485C, func_8083485C, func_8083485C, + func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C, + func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C, }; static void (*D_80853FE8[])(GlobalContext* globalCtx, Player* this) = { @@ -923,7 +933,8 @@ static void (*D_80853FE8[])(GlobalContext* globalCtx, Player* this) = { func_80833770, func_80833770, func_80833770, func_80833770, func_80833770, func_80833770, func_80833770, func_80833770, func_80833770, func_80833770, func_80833770, func_80833770, func_80833770, func_80833770, func_80833770, func_80833770, func_80833770, func_80833770, func_80833770, func_80833770, func_80833770, - func_80833770, func_80833770, func_80833770, func_80833770, + func_80833770, func_80833770, func_80833770, func_80833770, func_80833770, func_80833770, func_80833770, + func_80833770, func_80833770, func_80833770, func_80833770, func_80833770, func_80833770, }; typedef enum { @@ -2752,7 +2763,8 @@ void func_80835F44(GlobalContext* globalCtx, Player* this, s32 item) { if ((actionParam == PLAYER_AP_NONE) || !(this->stateFlags1 & PLAYER_STATE1_27) || ((this->actor.bgCheckFlags & 1) && - ((actionParam == PLAYER_AP_HOOKSHOT) || (actionParam == PLAYER_AP_LONGSHOT)))) { + ((actionParam == PLAYER_AP_HOOKSHOT) || (actionParam == PLAYER_AP_LONGSHOT))) || + ((actionParam >= PLAYER_AP_SHIELD_DEKU) && (actionParam <= PLAYER_AP_BOOTS_HOVER))) { if ((globalCtx->bombchuBowlingStatus == 0) && (((actionParam == PLAYER_AP_STICK) && (AMMO(ITEM_STICK) == 0)) || @@ -2764,6 +2776,33 @@ void func_80835F44(GlobalContext* globalCtx, Player* this, s32 item) { return; } + if (actionParam >= PLAYER_AP_BOOTS_KOKIRI) { + u16 bootsValue = actionParam - PLAYER_AP_BOOTS_KOKIRI + 1; + if (CUR_EQUIP_VALUE(EQUIP_BOOTS) == bootsValue) { + Inventory_ChangeEquipment(EQUIP_BOOTS, 1); + } else { + Inventory_ChangeEquipment(EQUIP_BOOTS, bootsValue); + } + Player_SetEquipmentData(globalCtx, this); + return; + } + + if (actionParam >= PLAYER_AP_TUNIC_KOKIRI) { + u16 tunicValue = actionParam - PLAYER_AP_TUNIC_KOKIRI + 1; + if (CUR_EQUIP_VALUE(EQUIP_TUNIC) == tunicValue) { + Inventory_ChangeEquipment(EQUIP_TUNIC, 1); + } else { + Inventory_ChangeEquipment(EQUIP_TUNIC, tunicValue); + } + Player_SetEquipmentData(globalCtx, this); + return; + } + + if (actionParam >= PLAYER_AP_SHIELD_DEKU) { + // Changing shields through action commands is unimplemented + return; + } + if (actionParam == PLAYER_AP_LENS) { if (func_80087708(globalCtx, 0, 3)) { if (globalCtx->actorCtx.unk_03 != 0) { diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c index 27575c3b6..719eaa3f3 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c @@ -471,39 +471,76 @@ void KaleidoScope_DrawEquipment(GlobalContext* globalCtx) { KaleidoScope_SetCursorVtx(pauseCtx, cursorSlot * 4, pauseCtx->equipVtx); if ((pauseCtx->cursorSpecialPos == 0) && (cursorItem != PAUSE_ITEM_NONE) && (pauseCtx->state == 6) && - (pauseCtx->unk_1E4 == 0) && CHECK_BTN_ALL(input->press.button, BTN_A) && + (pauseCtx->unk_1E4 == 0) && + CHECK_BTN_ANY(input->press.button, BTN_A | BTN_CLEFT | BTN_CDOWN | BTN_CRIGHT) && (pauseCtx->cursorX[PAUSE_EQUIP] != 0)) { if ((gEquipAgeReqs[pauseCtx->cursorY[PAUSE_EQUIP]][pauseCtx->cursorX[PAUSE_EQUIP]] == 9) || (gEquipAgeReqs[pauseCtx->cursorY[PAUSE_EQUIP]][pauseCtx->cursorX[PAUSE_EQUIP]] == ((void)0, gSaveContext.linkAge))) { - Inventory_ChangeEquipment(pauseCtx->cursorY[PAUSE_EQUIP], pauseCtx->cursorX[PAUSE_EQUIP]); + if (CHECK_BTN_ALL(input->press.button, BTN_A)) { + Inventory_ChangeEquipment(pauseCtx->cursorY[PAUSE_EQUIP], pauseCtx->cursorX[PAUSE_EQUIP]); - if (pauseCtx->cursorY[PAUSE_EQUIP] == 0) { - gSaveContext.infTable[29] = 0; - gSaveContext.equips.buttonItems[0] = cursorItem; + if (pauseCtx->cursorY[PAUSE_EQUIP] == 0) { + gSaveContext.infTable[29] = 0; + gSaveContext.equips.buttonItems[0] = cursorItem; - if ((pauseCtx->cursorX[PAUSE_EQUIP] == 3) && (gSaveContext.bgsFlag != 0)) { - gSaveContext.equips.buttonItems[0] = ITEM_SWORD_BGS; - gSaveContext.swordHealth = 8; - } else { - if (gSaveContext.equips.buttonItems[0] == ITEM_HEART_PIECE_2) { + if ((pauseCtx->cursorX[PAUSE_EQUIP] == 3) && (gSaveContext.bgsFlag != 0)) { gSaveContext.equips.buttonItems[0] = ITEM_SWORD_BGS; + gSaveContext.swordHealth = 8; + } else { + if (gSaveContext.equips.buttonItems[0] == ITEM_HEART_PIECE_2) { + gSaveContext.equips.buttonItems[0] = ITEM_SWORD_BGS; + } + if ((gSaveContext.equips.buttonItems[0] == ITEM_SWORD_BGS) && (gSaveContext.bgsFlag == 0) && + (gBitFlags[3] & gSaveContext.inventory.equipment)) { + gSaveContext.equips.buttonItems[0] = ITEM_SWORD_KNIFE; + } } - if ((gSaveContext.equips.buttonItems[0] == ITEM_SWORD_BGS) && (gSaveContext.bgsFlag == 0) && - (gBitFlags[3] & gSaveContext.inventory.equipment)) { - gSaveContext.equips.buttonItems[0] = ITEM_SWORD_KNIFE; - } + + Interface_LoadItemIcon1(globalCtx, 0); } - Interface_LoadItemIcon1(globalCtx, 0); + Audio_PlaySoundGeneral(NA_SE_SY_DECIDE, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); + pauseCtx->unk_1E4 = 7; + sEquipTimer = 10; + } else if (CVar_GetS32("gAssignableTunicsAndBoots", 0) != 0) { + // Only allow assigning tunic and boots to c-buttons + if (pauseCtx->cursorY[PAUSE_EQUIP] > 1) { + u16 slot = 0; + switch (cursorItem) { + case ITEM_TUNIC_KOKIRI: + slot = SLOT_TUNIC_KOKIRI; + break; + case ITEM_TUNIC_GORON: + slot = SLOT_TUNIC_GORON; + break; + case ITEM_TUNIC_ZORA: + slot = SLOT_TUNIC_ZORA; + break; + case ITEM_BOOTS_KOKIRI: + slot = SLOT_BOOTS_KOKIRI; + break; + case ITEM_BOOTS_IRON: + slot = SLOT_BOOTS_IRON; + break; + case ITEM_BOOTS_HOVER: + slot = SLOT_BOOTS_HOVER; + break; + default: + break; + } + KaleidoScope_SetupItemEquip(globalCtx, cursorItem, slot, + pauseCtx->equipVtx[cursorSlot * 4].v.ob[0] * 10, + pauseCtx->equipVtx[cursorSlot * 4].v.ob[1] * 10); + } } - - Audio_PlaySoundGeneral(NA_SE_SY_DECIDE, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); - pauseCtx->unk_1E4 = 7; - sEquipTimer = 10; } else { - Audio_PlaySoundGeneral(NA_SE_SY_ERROR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); + if (CHECK_BTN_ALL(input->press.button, BTN_A)) { + Audio_PlaySoundGeneral(NA_SE_SY_ERROR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); + } else if ((CVar_GetS32("gAssignableTunicsAndBoots", 0) != 0) && (pauseCtx->cursorY[PAUSE_EQUIP] > 1)) { + Audio_PlaySoundGeneral(NA_SE_SY_ERROR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); + } } } diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c index 52c04908f..705d1461e 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c @@ -351,43 +351,9 @@ void KaleidoScope_DrawItemSelect(GlobalContext* globalCtx) { if (((gSlotAgeReqs[cursorSlot] == 9) || (gSlotAgeReqs[cursorSlot] == ((void)0, gSaveContext.linkAge))) && (cursorItem != ITEM_SOLD_OUT)) { - if (CHECK_BTN_ALL(input->press.button, BTN_CLEFT)) { - pauseCtx->equipTargetCBtn = 0; - } else if (CHECK_BTN_ALL(input->press.button, BTN_CDOWN)) { - pauseCtx->equipTargetCBtn = 1; - } else if (CHECK_BTN_ALL(input->press.button, BTN_CRIGHT)) { - pauseCtx->equipTargetCBtn = 2; - } - - pauseCtx->equipTargetItem = cursorItem; - pauseCtx->equipTargetSlot = cursorSlot; - pauseCtx->unk_1E4 = 3; - pauseCtx->equipAnimX = pauseCtx->itemVtx[index].v.ob[0] * 10; - pauseCtx->equipAnimY = pauseCtx->itemVtx[index].v.ob[1] * 10; - pauseCtx->equipAnimAlpha = 255; - sEquipAnimTimer = 0; - sEquipState = 3; - sEquipMoveTimer = 10; - if ((pauseCtx->equipTargetItem == ITEM_ARROW_FIRE) || - (pauseCtx->equipTargetItem == ITEM_ARROW_ICE) || - (pauseCtx->equipTargetItem == ITEM_ARROW_LIGHT)) { - index = 0; - if (pauseCtx->equipTargetItem == ITEM_ARROW_ICE) { - index = 1; - } - if (pauseCtx->equipTargetItem == ITEM_ARROW_LIGHT) { - index = 2; - } - Audio_PlaySoundGeneral(NA_SE_SY_SET_FIRE_ARROW + index, &D_801333D4, 4, &D_801333E0, - &D_801333E0, &D_801333E8); - pauseCtx->equipTargetItem = 0xBF + index; - sEquipState = 0; - pauseCtx->equipAnimAlpha = 0; - sEquipMoveTimer = 6; - } else { - Audio_PlaySoundGeneral(NA_SE_SY_DECIDE, &D_801333D4, 4, &D_801333E0, &D_801333E0, - &D_801333E8); - } + KaleidoScope_SetupItemEquip(globalCtx, cursorItem, cursorSlot, + pauseCtx->itemVtx[index].v.ob[0] * 10, + pauseCtx->itemVtx[index].v.ob[1] * 10); } else { Audio_PlaySoundGeneral(NA_SE_SY_ERROR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); @@ -419,7 +385,9 @@ void KaleidoScope_DrawItemSelect(GlobalContext* globalCtx) { gDPSetEnvColor(POLY_KAL_DISP++, 0, 0, 0, 0); for (i = 0, j = 24 * 4; i < 3; i++, j += 4) { - if (gSaveContext.equips.buttonItems[i + 1] != ITEM_NONE) { + if ((gSaveContext.equips.buttonItems[i + 1] != ITEM_NONE) && + !((gSaveContext.equips.buttonItems[i + 1] >= ITEM_SHIELD_DEKU) && + (gSaveContext.equips.buttonItems[i + 1] <= ITEM_BOOTS_HOVER))) { gSPVertex(POLY_KAL_DISP++, &pauseCtx->itemVtx[j], 4, 0); POLY_KAL_DISP = KaleidoScope_QuadTextureIA8(POLY_KAL_DISP, gEquippedItemOutlineTex, 32, 32, 0); } @@ -496,6 +464,46 @@ void KaleidoScope_DrawItemSelect(GlobalContext* globalCtx) { CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_kaleido_item.c", 516); } +void KaleidoScope_SetupItemEquip(GlobalContext* globalCtx, u16 item, u16 slot, s16 animX, s16 animY) { + Input* input = &globalCtx->state.input[0]; + PauseContext* pauseCtx = &globalCtx->pauseCtx; + + if (CHECK_BTN_ALL(input->press.button, BTN_CLEFT)) { + pauseCtx->equipTargetCBtn = 0; + } else if (CHECK_BTN_ALL(input->press.button, BTN_CDOWN)) { + pauseCtx->equipTargetCBtn = 1; + } else if (CHECK_BTN_ALL(input->press.button, BTN_CRIGHT)) { + pauseCtx->equipTargetCBtn = 2; + } + + pauseCtx->equipTargetItem = item; + pauseCtx->equipTargetSlot = slot; + pauseCtx->unk_1E4 = 3; + pauseCtx->equipAnimX = animX; + pauseCtx->equipAnimY = animY; + pauseCtx->equipAnimAlpha = 255; + sEquipAnimTimer = 0; + sEquipState = 3; + sEquipMoveTimer = 10; + if ((pauseCtx->equipTargetItem == ITEM_ARROW_FIRE) || (pauseCtx->equipTargetItem == ITEM_ARROW_ICE) || + (pauseCtx->equipTargetItem == ITEM_ARROW_LIGHT)) { + u16 index = 0; + if (pauseCtx->equipTargetItem == ITEM_ARROW_ICE) { + index = 1; + } + if (pauseCtx->equipTargetItem == ITEM_ARROW_LIGHT) { + index = 2; + } + Audio_PlaySoundGeneral(NA_SE_SY_SET_FIRE_ARROW + index, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); + pauseCtx->equipTargetItem = 0xBF + index; + sEquipState = 0; + pauseCtx->equipAnimAlpha = 0; + sEquipMoveTimer = 6; + } else { + Audio_PlaySoundGeneral(NA_SE_SY_DECIDE, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); + } +} + static s16 sCButtonPosX[] = { 66, 90, 114 }; static s16 sCButtonPosY[] = { 110, 92, 110 }; diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope.h b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope.h index 928ceadd7..fa1d88fec 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope.h +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope.h @@ -18,6 +18,7 @@ void KaleidoScope_DrawPlayerWork(GlobalContext* globalCtx); void KaleidoScope_DrawEquipment(GlobalContext* globalCtx); void KaleidoScope_SetCursorVtx(PauseContext* pauseCtx, u16 index, Vtx* vtx); void KaleidoScope_DrawItemSelect(GlobalContext* globalCtx); +void KaleidoScope_SetupItemEquip(GlobalContext* globalCtx, u16 item, u16 slot, s16 animX, s16 animY); void KaleidoScope_UpdateItemEquip(GlobalContext* globalCtx); void KaleidoScope_DrawDungeonMap(GlobalContext* globalCtx, GraphicsContext* gfxCtx); void KaleidoScope_DrawWorldMap(GlobalContext* globalCtx, GraphicsContext* gfxCtx); diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c index 4dbb1b20f..c057c9876 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c @@ -916,6 +916,13 @@ void KaleidoScope_SwitchPage(PauseContext* pauseCtx, u8 pt) { gSaveContext.buttonStatus[3] = D_8082AB6C[pauseCtx->pageIndex + pt][3]; gSaveContext.buttonStatus[4] = D_8082AB6C[pauseCtx->pageIndex + pt][4]; + if ((CVar_GetS32("gAssignableTunicsAndBoots", 0) != 0) && (D_8082ABEC[pauseCtx->mode] == PAUSE_EQUIP)) { + gSaveContext.buttonStatus[1] = BTN_ENABLED; + gSaveContext.buttonStatus[2] = BTN_ENABLED; + gSaveContext.buttonStatus[3] = BTN_ENABLED; + gSaveContext.buttonStatus[4] = BTN_ENABLED; + } + osSyncPrintf("kscope->kscp_pos+pt = %d\n", pauseCtx->pageIndex + pt); gSaveContext.unk_13EA = 0; @@ -2902,7 +2909,16 @@ void func_808265BC(GlobalContext* globalCtx) { gSaveContext.buttonStatus[2] = D_8082AB6C[pauseCtx->pageIndex][2]; gSaveContext.buttonStatus[3] = D_8082AB6C[pauseCtx->pageIndex][3]; gSaveContext.buttonStatus[4] = D_8082AB6C[pauseCtx->pageIndex][4]; + pauseCtx->pageIndex = D_8082ABEC[pauseCtx->mode]; + + if ((CVar_GetS32("gAssignableTunicsAndBoots", 0) != 0) && (pauseCtx->pageIndex == PAUSE_EQUIP)) { + gSaveContext.buttonStatus[1] = BTN_ENABLED; + gSaveContext.buttonStatus[2] = BTN_ENABLED; + gSaveContext.buttonStatus[3] = BTN_ENABLED; + gSaveContext.buttonStatus[4] = BTN_ENABLED; + } + pauseCtx->unk_1E4 = 0; pauseCtx->state++; pauseCtx->alpha = 255; From bd6e637fee6f6eb3e4c20bf25ec56e6eb25c5101 Mon Sep 17 00:00:00 2001 From: MegaMech Date: Sun, 15 May 2022 13:28:27 -0600 Subject: [PATCH 07/30] Readme/building.md changes (#262) * add python version requirement to BUILDING.md extract_assets uses match statements which were added in python version 3.10 * update wording/version on python requirement https://github.com/HarbourMasters/Shipwright/pull/251 removes the 3.10 specific match statements, dropping the python version requirement to 3.6. * Update BUILDING.md * Update BUILDING.md * Update BUILDING.md * Update BUILDING.md * switch python link to download page * Fixed SHA-1 for retail ROM * Added discord link Co-authored-by: briaguya <70942617+briaguya-ai@users.noreply.github.com> Co-authored-by: InfoManiac742 --- BUILDING.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/BUILDING.md b/BUILDING.md index 3e4d7b21a..726b8a99c 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -2,7 +2,7 @@ ## Windows - 1. Install [Python](https://www.python.org/downloads/) >= 3.6. + 1. Requires [Python](https://www.python.org/downloads/) >= 3.6. 2. Install [Visual Studio 2022 Community Edition](https://visualstudio.microsoft.com/vs/community/) 3. In the Visual Studio Installer, install `MSVC v142 - VS 2019 C++`. 4. Clone the Ship of Harkinian repository. @@ -57,10 +57,10 @@ OOT_PAL_GC_DBG1 checksum 0x871E1C92 (debug non-master quest) The OTRExporter exports an `oot.otr` archive file which Ship of Harkinian requires to play. Use the `extract_assets.py` script file to run the exporter using any of the following methods: +1) Double click on the script after placing one or more roms in the directory. +2) Drag & Drop a rom onto the script. +3) In a terminal run `python3 extract_assets.py` after placing one or more roms in the directory. +4) In a terminal run `python3 extract_assets.py ` -1. Double click on the script after placing one or more roms in the directory. -2. Drag & Drop a rom onto the script. -3. In a terminal run `python3 extract_assets.py` after placing one or more roms in the directory. -4. In a terminal run `python3 extract_assets.py ` +If the script finds multiple roms the user is prompted which to use. Selection is done using the number keys and then pressing the carriage return key. -If the script finds multiple roms the user is prompted which to use. Selection is done using the number keys and then pressing the carriage return key. \ No newline at end of file From d8d1388ec68acfb8bc1f0c0b8e977b4f3c824930 Mon Sep 17 00:00:00 2001 From: Emill Date: Sun, 15 May 2022 21:32:05 +0200 Subject: [PATCH 08/30] Optimize away memory allocations (#340) --- libultraship/libultraship/Archive.cpp | 9 ++-- libultraship/libultraship/Archive.h | 6 +-- .../libultraship/Lib/Fast3D/gfx_pc.cpp | 14 +++--- libultraship/libultraship/Resource.cpp | 7 ++- libultraship/libultraship/ResourceMgr.cpp | 48 +++++++++++-------- libultraship/libultraship/ResourceMgr.h | 12 +++-- libultraship/libultraship/Window.cpp | 39 ++++++++------- 7 files changed, 74 insertions(+), 61 deletions(-) diff --git a/libultraship/libultraship/Archive.cpp b/libultraship/libultraship/Archive.cpp index 1e8f8d597..e4646c305 100644 --- a/libultraship/libultraship/Archive.cpp +++ b/libultraship/libultraship/Archive.cpp @@ -204,7 +204,7 @@ namespace Ship { return true; } - std::vector Archive::ListFiles(const std::string& searchMask) { + std::vector Archive::ListFiles(const std::string& searchMask) const { auto fileList = std::vector(); SFILE_FIND_DATA findContext; HANDLE hFind; @@ -248,7 +248,7 @@ namespace Ship { return fileList; } - bool Archive::HasFile(const std::string& filename) { + bool Archive::HasFile(const std::string& filename) const { bool result = false; auto start = std::chrono::steady_clock::now(); @@ -267,8 +267,9 @@ namespace Ship { return result; } - std::string Archive::HashToString(uint64_t hash) { - return hashes[hash]; + const std::string* Archive::HashToString(uint64_t hash) const { + auto it = hashes.find(hash); + return it != hashes.end() ? &it->second : nullptr; } bool Archive::Load(bool enableWriting, bool genCRCMap) { diff --git a/libultraship/libultraship/Archive.h b/libultraship/libultraship/Archive.h index f8fe3e0fd..b21ad9c73 100644 --- a/libultraship/libultraship/Archive.h +++ b/libultraship/libultraship/Archive.h @@ -34,9 +34,9 @@ namespace Ship bool AddFile(const std::string& path, uintptr_t fileData, DWORD dwFileSize); bool RemoveFile(const std::string& path); bool RenameFile(const std::string& oldPath, const std::string& newPath); - std::vector ListFiles(const std::string& searchMask); - bool HasFile(const std::string& searchMask); - std::string HashToString(uint64_t hash); + std::vector ListFiles(const std::string& searchMask) const; + bool HasFile(const std::string& searchMask) const; + const std::string* HashToString(uint64_t hash) const; protected: bool Load(bool enableWriting, bool genCRCMap); bool Unload(); diff --git a/libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp b/libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp index c1a130b19..6738f28fa 100644 --- a/libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp +++ b/libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp @@ -36,7 +36,7 @@ // OTRTODO: fix header files for these extern "C" { - char* ResourceMgr_GetNameByCRC(uint64_t crc, char* alloc); + const char* ResourceMgr_GetNameByCRC(uint64_t crc); int32_t* ResourceMgr_LoadMtxByCRC(uint64_t crc); Vtx* ResourceMgr_LoadVtxByCRC(uint64_t crc); Gfx* ResourceMgr_LoadGfxByCRC(uint64_t crc); @@ -134,14 +134,14 @@ static struct RDP { const uint8_t *addr; uint8_t siz; uint32_t width; - char* otr_path; + const char* otr_path; } texture_to_load; struct { const uint8_t *addr; uint32_t size_bytes; uint32_t full_image_line_size_bytes; uint32_t line_size_bytes; - char* otr_path; + const char* otr_path; } loaded_texture[2]; struct { uint8_t fmt; @@ -1636,11 +1636,11 @@ static void gfx_dp_set_scissor(uint32_t mode, uint32_t ulx, uint32_t uly, uint32 rdp.viewport_or_scissor_changed = true; } -static void gfx_dp_set_texture_image(uint32_t format, uint32_t size, uint32_t width, const void* addr, char* otr_path) { +static void gfx_dp_set_texture_image(uint32_t format, uint32_t size, uint32_t width, const void* addr, const char* otr_path) { rdp.texture_to_load.addr = (const uint8_t*)addr; rdp.texture_to_load.siz = size; rdp.texture_to_load.width = width; - if ( otr_path != nullptr && !strncmp(otr_path, "__OTR__", 7)) otr_path = otr_path + 7; + if (otr_path != nullptr && !strncmp(otr_path, "__OTR__", 7)) otr_path = otr_path + 7; rdp.texture_to_load.otr_path = otr_path; } @@ -2114,7 +2114,7 @@ static void gfx_run_dl(Gfx* cmd) { //puts("dl"); int dummy = 0; char dlName[128]; - char fileName[128]; + const char* fileName; Gfx* dListStart = cmd; uint64_t ourHash = -1; @@ -2437,7 +2437,7 @@ static void gfx_run_dl(Gfx* cmd) { uintptr_t addr = cmd->words.w1; cmd++; uint64_t hash = ((uint64_t)cmd->words.w0 << 32) + (uint64_t)cmd->words.w1; - ResourceMgr_GetNameByCRC(hash, fileName); + fileName = ResourceMgr_GetNameByCRC(hash); #if _DEBUG && 0 char* tex = ResourceMgr_LoadTexByCRC(hash); ResourceMgr_GetNameByCRC(hash, fileName); diff --git a/libultraship/libultraship/Resource.cpp b/libultraship/libultraship/Resource.cpp index 04fc2bfbb..66a1f4199 100644 --- a/libultraship/libultraship/Resource.cpp +++ b/libultraship/libultraship/Resource.cpp @@ -40,8 +40,11 @@ namespace Ship for (size_t i = 0; i < patches.size(); i++) { - std::string hashStr = resMgr->HashToString(patches[i].crc); - auto resShared = resMgr->GetCachedFile(hashStr); + const std::string* hashStr = resMgr->HashToString(patches[i].crc); + if (hashStr == nullptr) + continue; + + auto resShared = resMgr->GetCachedFile(hashStr->c_str()); if (resShared != nullptr) { auto res = (Ship::DisplayList*)resShared.get(); diff --git a/libultraship/libultraship/ResourceMgr.cpp b/libultraship/libultraship/ResourceMgr.cpp index de0296d12..0033ef442 100644 --- a/libultraship/libultraship/ResourceMgr.cpp +++ b/libultraship/libultraship/ResourceMgr.cpp @@ -215,7 +215,7 @@ namespace Ship { return ToLoad; } - std::shared_ptr ResourceMgr::GetCachedFile(std::string FilePath) { + std::shared_ptr ResourceMgr::GetCachedFile(const char* FilePath) const { auto resCacheFind = ResourceCache.find(FilePath); if (resCacheFind != ResourceCache.end() && @@ -227,8 +227,13 @@ namespace Ship { return nullptr; } - std::shared_ptr ResourceMgr::LoadResource(std::string FilePath) { - auto Promise = LoadResourceAsync(FilePath); + std::shared_ptr ResourceMgr::LoadResource(const char* FilePath) { + auto Res = LoadResourceAsync(FilePath); + + if (std::holds_alternative>(Res)) + return std::get>(Res); + + auto& Promise = std::get>(Res); if (!Promise->bHasResourceLoaded) { @@ -241,21 +246,18 @@ namespace Ship { return Promise->resource; } - std::shared_ptr ResourceMgr::LoadResourceAsync(std::string FilePath) { - StringHelper::ReplaceOriginal(FilePath, "\\", "/"); - - if (StringHelper::StartsWith(FilePath, "__OTR__")) - FilePath = StringHelper::Split(FilePath, "__OTR__")[1]; - - std::shared_ptr Promise = std::make_shared(); + std::variant, std::shared_ptr> ResourceMgr::LoadResourceAsync(const char* FilePath) { + if (FilePath[0] == '_' && FilePath[1] == '_' && FilePath[2] == 'O' && FilePath[3] == 'T' && FilePath[4] == 'R' && FilePath[5] == '_' && FilePath[6] == '_') + FilePath += 7; const std::lock_guard ResLock(ResourceLoadMutex); auto resCacheFind = ResourceCache.find(FilePath); if (resCacheFind == ResourceCache.end() || resCacheFind->second->isDirty/* || !FileData->bIsLoaded*/) { if (resCacheFind == ResourceCache.end()) { - SPDLOG_TRACE("Cache miss on Resource load: {}", FilePath.c_str()); + SPDLOG_TRACE("Cache miss on Resource load: {}", FilePath); } + std::shared_ptr Promise = std::make_shared(); std::shared_ptr FileData = LoadFile(FilePath); Promise->file = FileData; @@ -269,12 +271,13 @@ namespace Ship { ResourceLoadQueue.push(Promise); ResourceLoadNotifier.notify_all(); } - } else { - Promise->bHasResourceLoaded = true; - Promise->resource = resCacheFind->second; - } - return Promise; + return Promise; + } + else + { + return resCacheFind->second; + } } std::shared_ptr>> ResourceMgr::CacheDirectoryAsync(std::string SearchMask) { @@ -282,10 +285,15 @@ namespace Ship { auto fileList = OTR->ListFiles(SearchMask); for (DWORD i = 0; i < fileList.size(); i++) { - auto file = LoadResourceAsync(fileList.operator[](i).cFileName); - if (file != nullptr) { - loadedList->push_back(file); + auto resource = LoadResourceAsync(fileList.operator[](i).cFileName); + if (std::holds_alternative>(resource)) + { + auto promise = std::make_shared(); + promise->bHasResourceLoaded = true; + promise->resource = std::get>(resource); + resource = promise; } + loadedList->push_back(std::get>(resource)); } return loadedList; @@ -335,7 +343,7 @@ namespace Ship { ResourceCache.clear(); } - std::string ResourceMgr::HashToString(uint64_t Hash) { + const std::string* ResourceMgr::HashToString(uint64_t Hash) const { return OTR->HashToString(Hash); } } \ No newline at end of file diff --git a/libultraship/libultraship/ResourceMgr.h b/libultraship/libultraship/ResourceMgr.h index 28e77e537..e76d5b521 100644 --- a/libultraship/libultraship/ResourceMgr.h +++ b/libultraship/libultraship/ResourceMgr.h @@ -4,6 +4,7 @@ #include #include #include +#include #include "Resource.h" #include "GlobalCtx2.h" @@ -25,7 +26,7 @@ namespace Ship std::shared_ptr GetArchive() { return OTR; } std::shared_ptr GetContext() { return Context.lock(); } - std::string HashToString(uint64_t Hash); + const std::string* HashToString(uint64_t Hash) const; void InvalidateResourceCache(); @@ -33,9 +34,10 @@ namespace Ship void SetGameVersion(uint32_t newGameVersion); std::shared_ptr LoadFileAsync(std::string FilePath); std::shared_ptr LoadFile(std::string FilePath); - std::shared_ptr GetCachedFile(std::string FilePath); - std::shared_ptr LoadResource(std::string FilePath); - std::shared_ptr LoadResourceAsync(std::string FilePath); + std::shared_ptr GetCachedFile(const char* FilePath) const; + std::shared_ptr LoadResource(const char* FilePath); + std::shared_ptr LoadResource(const std::string& FilePath) { return LoadResource(FilePath.c_str()); } + std::variant, std::shared_ptr> LoadResourceAsync(const char* FilePath); std::shared_ptr>> CacheDirectory(std::string SearchMask); std::shared_ptr>> CacheDirectoryAsync(std::string SearchMask); std::shared_ptr>> DirtyDirectory(std::string SearchMask); @@ -50,7 +52,7 @@ namespace Ship std::weak_ptr Context; volatile bool bIsRunning; std::map> FileCache; - std::map> ResourceCache; + std::map, std::less<>> ResourceCache; std::queue> FileLoadQueue; std::queue> ResourceLoadQueue; std::shared_ptr OTR; diff --git a/libultraship/libultraship/Window.cpp b/libultraship/libultraship/Window.cpp index 588e3af50..bbd906c76 100644 --- a/libultraship/libultraship/Window.cpp +++ b/libultraship/libultraship/Window.cpp @@ -119,17 +119,16 @@ extern "C" { ModInternal::callBindHook(0); } - char* ResourceMgr_GetNameByCRC(uint64_t crc, char* alloc) { - std::string hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc); - strcpy(alloc, hashStr.c_str()); - return (char*)hashStr.c_str(); + const char* ResourceMgr_GetNameByCRC(uint64_t crc) { + const std::string* hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc); + return hashStr != nullptr ? hashStr->c_str() : nullptr; } Vtx* ResourceMgr_LoadVtxByCRC(uint64_t crc) { - std::string hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc); + const std::string* hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc); - if (hashStr != "") { - auto res = std::static_pointer_cast(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr)); + if (hashStr != nullptr) { + auto res = std::static_pointer_cast(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr->c_str())); //if (res != nullptr) return (Vtx*)res->vertices.data(); @@ -142,10 +141,10 @@ extern "C" { } int32_t* ResourceMgr_LoadMtxByCRC(uint64_t crc) { - std::string hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc); + const std::string* hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc); - if (hashStr != "") { - auto res = std::static_pointer_cast(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr)); + if (hashStr != nullptr) { + auto res = std::static_pointer_cast(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr->c_str())); return (int32_t*)res->mtx.data(); } else { return nullptr; @@ -153,10 +152,10 @@ extern "C" { } Gfx* ResourceMgr_LoadGfxByCRC(uint64_t crc) { - std::string hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc); + const std::string* hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc); - if (hashStr != "") { - auto res = std::static_pointer_cast(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr)); + if (hashStr != nullptr) { + auto res = std::static_pointer_cast(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr->c_str())); return (Gfx*)&res->instructions[0]; } else { return nullptr; @@ -164,14 +163,14 @@ extern "C" { } char* ResourceMgr_LoadTexByCRC(uint64_t crc) { - const std::string hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc); + const std::string* hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc); - if (!hashStr.empty()) { - const auto res = static_cast(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr).get()); + if (hashStr != nullptr) { + const auto res = static_cast(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr->c_str()).get()); ModInternal::bindHook(LOAD_TEXTURE); ModInternal::initBindHook(2, - HookParameter({.name = "path", .parameter = (void*)hashStr.c_str() }), + HookParameter({.name = "path", .parameter = (void*)hashStr->c_str() }), HookParameter({.name = "texture", .parameter = static_cast(&res->imageData) }) ); ModInternal::callBindHook(0); @@ -184,11 +183,11 @@ extern "C" { void ResourceMgr_RegisterResourcePatch(uint64_t hash, uint32_t instrIndex, uintptr_t origData) { - std::string hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(hash); + const std::string* hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(hash); - if (hashStr != "") + if (hashStr != nullptr) { - auto res = (Ship::Texture*)Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr).get(); + auto res = (Ship::Texture*)Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr->c_str()).get(); Ship::Patch patch; patch.crc = hash; From 076887e71f52d4258aa8fc77d3efeafe09d234d8 Mon Sep 17 00:00:00 2001 From: PurpleHato <47987542+PurpleHato@users.noreply.github.com> Date: Sun, 15 May 2022 21:51:58 +0200 Subject: [PATCH 09/30] TWEAK: Submenus for the enhancement menu (#343) * TWEAK: Submenus for the enhancement menu original PR was #322 closed it because I messed it * Fix for Assignable Tunics and Boots --- libultraship/libultraship/SohImGuiImpl.cpp | 113 +++++++++++---------- 1 file changed, 60 insertions(+), 53 deletions(-) diff --git a/libultraship/libultraship/SohImGuiImpl.cpp b/libultraship/libultraship/SohImGuiImpl.cpp index 78532d85b..d17d6ccee 100644 --- a/libultraship/libultraship/SohImGuiImpl.cpp +++ b/libultraship/libultraship/SohImGuiImpl.cpp @@ -363,7 +363,7 @@ namespace SohImGui { ModInternal::registerHookListener({ CONTROLLER_READ, [](const HookEvent ev) { pads = static_cast(ev->baseArgs["cont_pad"]); - }}); + } }); Game::InitSettings(); } @@ -402,7 +402,7 @@ namespace SohImGui { EnhancementRadioButton("French", "gLanguages", 2); */ int val = CVar_GetS32(cvarName.c_str(), 0); - if (ImGui::RadioButton(text.c_str(), id==val)) { + if (ImGui::RadioButton(text.c_str(), id == val)) { CVar_SetS32(cvarName.c_str(), (int)id); needs_save = true; } @@ -505,12 +505,12 @@ namespace SohImGui { } } - void Tooltip(std::string text){ + void Tooltip(std::string text) { if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", text.c_str()); } - void DrawMainMenuAndCalculateGameSize() { + void DrawMainMenuAndCalculateGameSize() { console->Update(); ImGuiBackendNewFrame(); ImGuiWMNewFrame(); @@ -626,10 +626,10 @@ namespace SohImGui { if (ImGui::BeginMenu("Graphics")) { EnhancementSliderInt("Internal Resolution: %dx", "##IMul", "gInternalResolution", 1, 8, ""); - Tooltip("Increases the render resolution of the game, up to 8x your output resolution,\nas a more intensive but effective form of anti-aliasing"); + Tooltip("Increases the render resolution of the game, up to 8x your output resolution,\nas a more intensive but effective form of anti-aliasing"); gfx_current_dimensions.internal_mul = CVar_GetS32("gInternalResolution", 1); EnhancementSliderInt("MSAA: %d", "##IMSAA", "gMSAAValue", 1, 8, ""); - Tooltip("Activates anti-aliasing when above 1, up to 8x for 8 samples for every pixel"); + Tooltip("Activates anti-aliasing when above 1, up to 8x for 8 samples for every pixel"); gfx_msaa_level = CVar_GetS32("gMSAAValue", 1); EXPERIMENTAL(); @@ -641,7 +641,7 @@ namespace SohImGui { INFO("New Filter: %s", filters[fId]); gapi->set_texture_filter((FilteringMode)fId); - CVar_SetS32("gTextureFilter", (int) fId); + CVar_SetS32("gTextureFilter", (int)fId); needs_save = true; } @@ -661,50 +661,57 @@ namespace SohImGui { if (ImGui::BeginMenu("Enhancements")) { - ImGui::Text("Gameplay"); - ImGui::Separator(); + if (ImGui::BeginMenu("Gameplay")) + { + EnhancementSliderInt("Text Speed: %dx", "##TEXTSPEED", "gTextSpeed", 1, 5, ""); + EnhancementSliderInt("King Zora Speed: %dx", "##WEEPSPEED", "gMweepSpeed", 1, 5, ""); - EnhancementSliderInt("Text Speed: %dx", "##TEXTSPEED", "gTextSpeed", 1, 5, ""); - EnhancementSliderInt("King Zora Speed: %dx", "##WEEPSPEED", "gMweepSpeed", 1, 5, ""); + EnhancementCheckbox("Skip Text", "gSkipText"); + Tooltip("Holding down B skips text"); + EnhancementCheckbox("Mute Low HP Alarm", "gLowHpAlarm"); + Tooltip("Disable the low HP beeping sound"); + EnhancementCheckbox("Minimal UI", "gMinimalUI"); + Tooltip("Hides most of the UI when not needed"); + EnhancementCheckbox("Visual Stone of Agony", "gVisualAgony"); + Tooltip("Displays an icon and plays a sound when Stone of Agony should be activated, for those without rumble"); + EnhancementCheckbox("Faster Block Push", "gFasterBlockPush"); + EnhancementCheckbox("Assignable Tunics and Boots", "gAssignableTunicsAndBoots"); + Tooltip("Allows equiping the tunic and boots to c-buttons"); + EnhancementCheckbox("MM Bunny Hood", "gMMBunnyHood"); + Tooltip("Wearing the Bunny Hood grants a speed increase like in Majora's Mask"); - EnhancementCheckbox("Mute Low HP Alarm", "gLowHpAlarm"); - EnhancementCheckbox("Skip Text", "gSkipText"); - Tooltip("Holding down B skips text"); - EnhancementCheckbox("Minimal UI", "gMinimalUI"); - Tooltip("Hides most of the UI when not needed"); - EnhancementCheckbox("MM Bunny Hood", "gMMBunnyHood"); - Tooltip("Wearing the Bunny Hood grants a speed increase like in Majora's Mask"); - EnhancementCheckbox("Visual Stone of Agony", "gVisualAgony"); - Tooltip("Displays an icon and plays a sound when Stone of Agony should be activated, for those without rumble"); - EnhancementCheckbox("Assignable Tunics and Boots", "gAssignableTunicsAndBoots"); - Tooltip("Allows equiping the tunic and boots to c-buttons"); + ImGui::EndMenu(); + } - ImGui::Text("Graphics"); - ImGui::Separator(); + if (ImGui::BeginMenu("Graphics")) + { + EnhancementCheckbox("N64 Mode", "gN64Mode"); + Tooltip("Sets aspect ratio to 4:3 and lowers resolution to 240p, the N64's native resolution"); + EnhancementCheckbox("Animated Link in Pause Menu", "gPauseLiveLink"); + EnhancementCheckbox("Enable 3D Dropped items", "gNewDrops"); + EnhancementCheckbox("Dynamic Wallet Icon", "gDynamicWalletIcon"); + Tooltip("Changes the rupee in the wallet icon to match the wallet size you currently have"); + EnhancementCheckbox("Always show dungeon entrances", "gAlwaysShowDungeonMinimapIcon"); + Tooltip("Always shows dungeon entrance icons on the minimap"); - EnhancementCheckbox("N64 Mode", "gN64Mode"); - Tooltip("Sets aspect ratio to 4:3 and lowers resolution to 240p, the N64's native resolution"); + ImGui::EndMenu(); + } - EnhancementCheckbox("Animated Link in Pause Menu", "gPauseLiveLink"); - EnhancementCheckbox("Enable 3D Dropped items", "gNewDrops"); - EnhancementCheckbox("Faster Block Push", "gFasterBlockPush"); - EnhancementCheckbox("Dynamic Wallet Icon", "gDynamicWalletIcon"); - Tooltip("Changes the rupee in the wallet icon to match the wallet size you currently have"); - EnhancementCheckbox("Always show dungeon entrances", "gAlwaysShowDungeonMinimapIcon"); - Tooltip("Always shows dungeon entrance icons on the minimap"); + if (ImGui::BeginMenu("Fixes")) + { + EnhancementCheckbox("Fix L&R Pause menu", "gUniformLR"); + Tooltip("Makes the L and R buttons in the pause menu the same color"); + EnhancementCheckbox("Fix Dungeon entrances", "gFixDungeonMinimapIcon"); + Tooltip("Show dungeon entrances icon only when it should be"); + EnhancementCheckbox("Fix Two Handed idle animations", "gTwoHandedIdle"); + Tooltip("Makes two handed idle animation play, a seemingly finished animation that was disabled on accident in the original game"); - ImGui::Text("Fixes"); - ImGui::Separator(); - EnhancementCheckbox("Fix L&R Pause menu", "gUniformLR"); - Tooltip("Makes the L and R buttons in the pause menu the same color"); - EnhancementCheckbox("Fix Dungeon entrances", "gFixDungeonMinimapIcon"); - Tooltip("Show dungeon entrances icon only when it should be"); - EnhancementCheckbox("Fix Two Handed idle animations", "gTwoHandedIdle"); - Tooltip("Makes two handed idle animation play, a seemingly finished animation that was disabled on accident in the original game"); + ImGui::EndMenu(); + } EXPERIMENTAL(); - EnhancementCheckbox("60 fps interpolation", "g60FPS"); + EnhancementCheckbox("60FPS Interpolation", "g60FPS"); EnhancementCheckbox("Disable LOD", "gDisableLOD"); Tooltip("Turns off the level of detail setting, making models always use their higher poly variants"); @@ -748,19 +755,19 @@ namespace SohImGui { } EnhancementCheckbox("No Clip", "gNoClip"); - Tooltip("Allows you to walk through walls"); + Tooltip("Allows you to walk through walls"); EnhancementCheckbox("Climb Everything", "gClimbEverything"); - Tooltip("Makes every surface in the game climbable"); + Tooltip("Makes every surface in the game climbable"); EnhancementCheckbox("Moon Jump on L", "gMoonJumpOnL"); - Tooltip("Holding L makes you float into the air"); + Tooltip("Holding L makes you float into the air"); EnhancementCheckbox("Super Tunic", "gSuperTunic"); - Tooltip("Makes every tunic have the effects of every other tunic"); + Tooltip("Makes every tunic have the effects of every other tunic"); EnhancementCheckbox("Easy ISG", "gEzISG"); - Tooltip("Automatically activates the Infinite Sword glitch, making you constantly swing your sword"); + Tooltip("Automatically activates the Infinite Sword glitch, making you constantly swing your sword"); EnhancementCheckbox("Unrestricted Items", "gNoRestrictItems"); - Tooltip("Allows you to use all items at any age"); + Tooltip("Allows you to use any item at any location"); EnhancementCheckbox("Freeze Time", "gFreezeTime"); - Tooltip("Freezes the time of day"); + Tooltip("Freezes the time of day"); ImGui::EndMenu(); } @@ -768,12 +775,12 @@ namespace SohImGui { if (ImGui::BeginMenu("Developer Tools")) { EnhancementCheckbox("OoT Debug Mode", "gDebugEnabled"); - Tooltip("Enables Debug Mode, allowing you to select maps with L + R + Z, noclip with L + D-pad Right,\nand open the debug menu with L on the pause screen"); + Tooltip("Enables Debug Mode, allowing you to select maps with L + R + Z, noclip with L + D-pad Right,\nand open the debug menu with L on the pause screen"); ImGui::Separator(); EnhancementCheckbox("Stats", "gStatsEnabled"); - Tooltip("Shows the stats window, with your FPS and frametimes, and the OS you're playing on"); + Tooltip("Shows the stats window, with your FPS and frametimes, and the OS you're playing on"); EnhancementCheckbox("Console", "gConsoleEnabled"); - Tooltip("Enables the console window, allowing you to input commands, type help for some examples"); + Tooltip("Enables the console window, allowing you to input commands, type help for some examples"); console->opened = CVar_GetS32("gConsoleEnabled", 0); ImGui::EndMenu(); @@ -783,7 +790,7 @@ namespace SohImGui { if (ImGui::BeginMenu(category.first.c_str())) { for (const std::string& name : category.second) { std::string varName(name); - varName.erase(std::ranges::remove_if(varName, isspace).begin(), varName.end()); + varName.erase(std::ranges::remove_if(varName, isspace).begin(), varName.end()); std::string toggleName = "g" + varName + "Enabled"; EnhancementCheckbox(name, toggleName); From 226dd3a82825c8cc913acb736509ab9fbde86448 Mon Sep 17 00:00:00 2001 From: Baoulettes Date: Sat, 21 May 2022 19:14:53 +0200 Subject: [PATCH 10/30] add gSPInvalidateTexCache(); (#274) --- soh/src/code/z_message_PAL.c | 1 + 1 file changed, 1 insertion(+) diff --git a/soh/src/code/z_message_PAL.c b/soh/src/code/z_message_PAL.c index ffb0581c7..b6d6b792b 100644 --- a/soh/src/code/z_message_PAL.c +++ b/soh/src/code/z_message_PAL.c @@ -1841,6 +1841,7 @@ void Message_DrawTextBox(GlobalContext* globalCtx, Gfx** p) { MessageContext* msgCtx = &globalCtx->msgCtx; Gfx* gfx = *p; + gSPInvalidateTexCache(gfx++, msgCtx->textboxSegment); gDPPipeSync(gfx++); gDPSetPrimColor(gfx++, 0, 0, msgCtx->textboxColorRed, msgCtx->textboxColorGreen, msgCtx->textboxColorBlue, msgCtx->textboxColorAlphaCurrent); From a3cf8522676ec7855da4869be775e81014eb70ec Mon Sep 17 00:00:00 2001 From: vaguerant Date: Sun, 22 May 2022 03:15:41 +1000 Subject: [PATCH 11/30] Fix vanilla Deku Nut upgrade bug (#333) --- libultraship/libultraship/SohImGuiImpl.cpp | 2 ++ soh/soh/Enhancements/bootcommands.c | 1 + soh/src/code/z_parameter.c | 2 +- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/libultraship/libultraship/SohImGuiImpl.cpp b/libultraship/libultraship/SohImGuiImpl.cpp index d17d6ccee..76f3b863b 100644 --- a/libultraship/libultraship/SohImGuiImpl.cpp +++ b/libultraship/libultraship/SohImGuiImpl.cpp @@ -705,6 +705,8 @@ namespace SohImGui { Tooltip("Show dungeon entrances icon only when it should be"); EnhancementCheckbox("Fix Two Handed idle animations", "gTwoHandedIdle"); Tooltip("Makes two handed idle animation play, a seemingly finished animation that was disabled on accident in the original game"); + EnhancementCheckbox("Fix Deku Nut upgrade", "gDekuNutUpgradeFix"); + Tooltip("Prevents the Forest Stage Deku Nut upgrade from becoming unobtainable after receiving the Poacher's Saw"); ImGui::EndMenu(); } diff --git a/soh/soh/Enhancements/bootcommands.c b/soh/soh/Enhancements/bootcommands.c index 71bd00cac..ffe3c70d0 100644 --- a/soh/soh/Enhancements/bootcommands.c +++ b/soh/soh/Enhancements/bootcommands.c @@ -28,6 +28,7 @@ void BootCommands_Init() CVar_RegisterS32("gRumbleEnabled", 0); CVar_RegisterS32("gUniformLR", 1); CVar_RegisterS32("gTwoHandedIdle", 0); + CVar_RegisterS32("gDekuNutUpgradeFix", 1); CVar_RegisterS32("gNewDrops", 0); CVar_RegisterS32("gVisualAgony", 0); CVar_RegisterS32("gLanguages", 0); //0 = English / 1 = German / 2 = French diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index 8cfcccbf5..127fb0cbb 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -1803,7 +1803,7 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) { } } } else if ((item >= ITEM_WEIRD_EGG) && (item <= ITEM_CLAIM_CHECK)) { - if (item == ITEM_SAW) { + if ((item == ITEM_SAW) && CVar_GetS32("gDekuNutUpgradeFix", 0) == 0) { gSaveContext.itemGetInf[1] |= 0x8000; } From 09933377219f602f33a0f8538f5a09fe1b652a6a Mon Sep 17 00:00:00 2001 From: Baoulettes Date: Sat, 21 May 2022 19:16:28 +0200 Subject: [PATCH 12/30] [Mod]HUD Editor - Color Scheme incl. N64 colors. (#202) * Update SohImGuiImpl.cpp * Add int variant of CVar_ Get/Set/Register * Add variant of CVar_ Get/Set/Register * Add LoadHUDColors() * Added temporary menu for custom colors * vars added * added section load * variables save/load * register boolean for colors radiobox * Minimap recolor * Hearts (top left) color, incl. DD variant * Add A/B/C/Start btn colors and rupee * A & C button icon and save prompt cursor. * A & C notes and cursor * Some notes I forgot tbh was open since hours. * Shops cursor color with included pulse * Wrong section was added * Fixed some logic there and removed an unused if * Moved a condition to make it better. * That what happen when you left it open for hours * Update z_message_PAL.c * Added color array for A button * Get/Set/Register Int not needed anymore * Update Cvar.h * Update Cvar.cpp * Removed HUDCOLOR_SECTION moved it to cosmetics Updated Tunics and navi mod too. * changed categorie name and updated * Updated Cosmetics menu and add colors there * Update GameSettings.cpp * Update GameSettings.h * A more generic name * Update SohImGuiImpl.cpp * Update bootcommands.c * update var name * var name update * var name update (creative name I know...) * Updated variables names to match gHudColors * to lazy to name this one * gHudColors renaming stuff there too * guess what, variable renaming. * Update Tunic/Navi mods with new variable name. * Updated Links tunic variable names * Fix condition for Right C button * Add condition to check if the button is on * Added system to check if color tunics is turned on. * Added empty C button colors * Add ability to move Hearts * Ability to move minimap (incl. dgn one) Add Dungeon icon fix requirement. once merged I will fix conflict with this one. * Compass icon move with the minimap * Added several button move function * stone of agony folly the interface too. * fix minimap alpha * Fixes notes env color (was showing incorrectly) * PR repo mass update, cleaning incoming * Clean_PR stuff * useless there ... * Properly load the function. Imagine creating a pseudo function to load load of colour and you actually forgot to add it, could not be me right , RIGHT ? * fix conflict and useless edit * Fix default color for A/B and C btns * Fix Rupee default color in ImGUI * Reworked Tunics handling, much better this way * Fix minimap default color * C button default color fix * better behavior and default color fix * Fixed every default color to match gamecube style * Fix dungeon entrance icon n.2 it was not using margin and always show icon system * This need a scene else it show everywhere oof --- libultraship/libultraship/SohImGuiImpl.cpp | 331 +++++++++++++----- libultraship/libultraship/SohImGuiImpl.h | 2 + soh/soh/Enhancements/bootcommands.c | 3 + soh/src/code/z_actor.c | 83 +++-- soh/src/code/z_lifemeter.c | 198 ++++++++--- soh/src/code/z_map_exp.c | 76 ++-- soh/src/code/z_map_mark.c | 20 +- soh/src/code/z_message_PAL.c | 58 ++- soh/src/code/z_parameter.c | 246 +++++++++---- soh/src/code/z_player_lib.c | 37 +- .../overlays/actors/ovl_En_Ossan/z_en_ossan.c | 16 +- .../actors/ovl_player_actor/z_player.c | 8 + .../ovl_kaleido_scope/z_kaleido_collect.c | 48 ++- .../ovl_kaleido_scope/z_kaleido_scope_PAL.c | 93 ++++- 14 files changed, 919 insertions(+), 300 deletions(-) diff --git a/libultraship/libultraship/SohImGuiImpl.cpp b/libultraship/libultraship/SohImGuiImpl.cpp index 76f3b863b..530c3707d 100644 --- a/libultraship/libultraship/SohImGuiImpl.cpp +++ b/libultraship/libultraship/SohImGuiImpl.cpp @@ -65,19 +65,28 @@ namespace SohImGui { bool needs_save = false; std::vector CustomTexts; int SelectedLanguage = CVar_GetS32("gLanguages", 0); //Default Language to 0=English 1=German 2=French + int SelectedHUD = CVar_GetS32("gHudColors", 1); //Default colors to Gamecube. + float hearts_colors[3] = {0,0,0}; + float hearts_dd_colors[3] = {0,0,0}; + float a_btn_colors[3] = {0,0,0}; + float b_btn_colors[3] = {0,0,0}; + float c_btn_colors[3] = {0,0,0}; + float start_btn_colors[3] = {0,0,0}; + float magic_border_colors[3] = {0,0,0}; + float magic_remaining_colors[3] = {0,0,0}; + float magic_use_colors[3] = {0,0,0}; + float minimap_colors[3] = {0,0,0}; + float rupee_colors[3] = {0,0,0}; + float smolekey_colors[3] = {0,0,0}; float kokiri_col[3] = { 0.118f, 0.41f, 0.106f }; float goron_col[3] = { 0.392f, 0.078f, 0.0f }; float zora_col[3] = { 0.0f, 0.235f, 0.392f }; - float navi_idle_i_col[3] = { 0.0f, 0.0f, 0.0f }; float navi_idle_o_col[3] = { 0.0f, 0.0f, 0.0f }; - float navi_npc_i_col[3] = { 0.0f, 0.0f, 0.0f }; float navi_npc_o_col[3] = { 0.0f, 0.0f, 0.0f }; - float navi_enemy_i_col[3] = { 0.0f, 0.0f, 0.0f }; float navi_enemy_o_col[3] = { 0.0f, 0.0f, 0.0f }; - float navi_prop_i_col[3] = { 0.0f, 0.0f, 0.0f }; float navi_prop_o_col[3] = { 0.0f, 0.0f, 0.0f }; @@ -104,50 +113,6 @@ namespace SohImGui { break; } - // OTRTODO: This gameplay specific stuff should not be in libultraship. This needs to be moved to soh and use sTunicColors - kokiri_col[0] = 30 / 255.0f; - kokiri_col[1] = 105 / 255.0f; - kokiri_col[2] = 27 / 255.0f; - - goron_col[0] = 100 / 255.0f; - goron_col[1] = 20 / 255.0f; - goron_col[2] = 0; - - zora_col[0] = 0; - zora_col[1] = 60 / 255.0f; - zora_col[2] = 100 / 255.0f; - - navi_idle_i_col[0] = 0; - navi_idle_i_col[1] = 0; - navi_idle_i_col[2] = 0; - - navi_idle_o_col[0] = 0; - navi_idle_o_col[1] = 0; - navi_idle_o_col[2] = 0; - - navi_npc_i_col[0] = 0; - navi_npc_i_col[1] = 0; - navi_npc_i_col[2] = 0; - - navi_npc_o_col[0] = 0; - navi_npc_o_col[1] = 0; - navi_npc_o_col[2] = 0; - - navi_enemy_i_col[0] = 0; - navi_enemy_i_col[1] = 0; - navi_enemy_i_col[2] = 0; - - navi_enemy_o_col[0] = 0; - navi_enemy_o_col[1] = 0; - navi_enemy_o_col[2] = 0; - - navi_prop_i_col[0] = 0; - navi_prop_i_col[1] = 0; - navi_prop_i_col[2] = 0; - - navi_prop_o_col[0] = 0; - navi_prop_o_col[1] = 0; - navi_prop_o_col[2] = 0; } void ImGuiBackendInit() { @@ -275,6 +240,85 @@ namespace SohImGui { stbi_image_free(img_data); } + void LoadInterfaceEditor(){//This function is necessary as without it IMGui wont load the updated float array. + hearts_colors[0] = (float)CVar_GetS32("gCCHeartsPrimR", 255)/255; + hearts_colors[1] = (float)CVar_GetS32("gCCHeartsPrimG", 70)/255; + hearts_colors[2] = (float)CVar_GetS32("gCCHeartsPrimB", 50)/255; + hearts_dd_colors[0] = (float)CVar_GetS32("gDDCCHeartsPrimR", 255)/255; + hearts_dd_colors[1] = (float)CVar_GetS32("gDDCCHeartsPrimG", 255)/255; + hearts_dd_colors[2] = (float)CVar_GetS32("gDDCCHeartsPrimB", 255)/255; + a_btn_colors[0] = (float)CVar_GetS32("gCCABtnPrimR", 90)/255; + a_btn_colors[1] = (float)CVar_GetS32("gCCABtnPrimG", 90)/255; + a_btn_colors[2] = (float)CVar_GetS32("gCCABtnPrimB", 255)/255; + b_btn_colors[0] = (float)CVar_GetS32("gCCBBtnPrimR", 0)/255; + b_btn_colors[1] = (float)CVar_GetS32("gCCBBtnPrimG", 150)/255; + b_btn_colors[2] = (float)CVar_GetS32("gCCBBtnPrimB", 0)/255; + c_btn_colors[0] = (float)CVar_GetS32("gCCCBtnPrimR", 255)/255; + c_btn_colors[1] = (float)CVar_GetS32("gCCCBtnPrimG", 160)/255; + c_btn_colors[2] = (float)CVar_GetS32("gCCCBtnPrimB", 0)/255; + start_btn_colors[0] = (float)CVar_GetS32("gCCStartBtnPrimR", 120)/255; + start_btn_colors[1] = (float)CVar_GetS32("gCCStartBtnPrimG", 120)/255; + start_btn_colors[2] = (float)CVar_GetS32("gCCStartBtnPrimB", 120)/255; + magic_border_colors[0] = (float)CVar_GetS32("gCCMagicBorderPrimR", 255)/255; + magic_border_colors[1] = (float)CVar_GetS32("gCCMagicBorderPrimG", 255)/255; + magic_border_colors[2] = (float)CVar_GetS32("gCCMagicBorderPrimB", 255)/255; + magic_use_colors[0] = (float)CVar_GetS32("gCCMagicPrimR", 250)/255; + magic_use_colors[1] = (float)CVar_GetS32("gCCMagicPrimG", 250)/255; + magic_use_colors[2] = (float)CVar_GetS32("gCCMagicPrimB", 0)/255; + magic_remaining_colors[0] = (float)CVar_GetS32("gCCMagicUsePrimR", 0)/255; + magic_remaining_colors[1] = (float)CVar_GetS32("gCCMagicUsePrimG", 200)/255; + magic_remaining_colors[2] = (float)CVar_GetS32("gCCMagicUsePrimB", 0)/255; + minimap_colors[0] = (float)CVar_GetS32("gCCMinimapPrimR", 0)/255; + minimap_colors[1] = (float)CVar_GetS32("gCCMinimapPrimG", 255)/255; + minimap_colors[2] = (float)CVar_GetS32("gCCMinimapPrimB", 255)/255; + rupee_colors[0] = (float)CVar_GetS32("gCCRupeePrimR", 200)/255; + rupee_colors[1] = (float)CVar_GetS32("gCCRupeePrimG", 255)/255; + rupee_colors[2] = (float)CVar_GetS32("gCCRupeePrimB", 100)/255; + smolekey_colors[0] = (float)CVar_GetS32("gCCKeysPrimR", 200)/255; + smolekey_colors[1] = (float)CVar_GetS32("gCCKeysPrimG", 230)/255; + smolekey_colors[2] = (float)CVar_GetS32("gCCKeysPrimB", 255)/255; + kokiri_col[0] = (float)CVar_GetS32("gTunic_Kokiri_R", 30)/255; + kokiri_col[1] = (float)CVar_GetS32("gTunic_Kokiri_G", 105)/255; + kokiri_col[2] = (float)CVar_GetS32("gTunic_Kokiri_B", 27)/255; + goron_col[0] = (float)CVar_GetS32("gTunic_Goron_R", 100)/255; + goron_col[1] = (float)CVar_GetS32("gTunic_Goron_G", 20)/255; + goron_col[2] = (float)CVar_GetS32("gTunic_Goron_B", 0)/255; + zora_col[0] = (float)CVar_GetS32("gTunic_Zora_R", 0)/255; + zora_col[1] = (float)CVar_GetS32("gTunic_Zora_G", 60)/255; + zora_col[2] = (float)CVar_GetS32("gTunic_Zora_B", 100)/255; + navi_idle_i_col[0] = (float)CVar_GetS32("gNavi_Idle_Inner_R", 255)/255; + navi_idle_i_col[1] = (float)CVar_GetS32("gNavi_Idle_Inner_G", 255)/255; + navi_idle_i_col[2] = (float)CVar_GetS32("gNavi_Idle_Inner_B", 255)/255; + navi_idle_o_col[0] = (float)CVar_GetS32("gNavi_Idle_Outer_R", 115)/255; + navi_idle_o_col[1] = (float)CVar_GetS32("gNavi_Idle_Outer_G", 230)/255; + navi_idle_o_col[2] = (float)CVar_GetS32("gNavi_Idle_Outer_B", 255)/255; + navi_npc_i_col[0] = (float)CVar_GetS32("gNavi_NPC_Inner_R", 100)/255; + navi_npc_i_col[1] = (float)CVar_GetS32("gNavi_NPC_Inner_G", 100)/255; + navi_npc_i_col[2] = (float)CVar_GetS32("gNavi_NPC_Inner_B", 255)/255; + navi_npc_o_col[0] = (float)CVar_GetS32("gNavi_NPC_Outer_R", 90)/255; + navi_npc_o_col[1] = (float)CVar_GetS32("gNavi_NPC_Outer_G", 90)/255; + navi_npc_o_col[2] = (float)CVar_GetS32("gNavi_NPC_Outer_B", 255)/255; + navi_enemy_i_col[0] = (float)CVar_GetS32("gNavi_Enemy_Inner_R", 255)/255; + navi_enemy_i_col[1] = (float)CVar_GetS32("gNavi_Enemy_Inner_G", 255)/255; + navi_enemy_i_col[2] = (float)CVar_GetS32("gNavi_Enemy_Inner_B", 0)/255; + navi_enemy_o_col[0] = (float)CVar_GetS32("gNavi_Enemy_Outer_R", 220)/255; + navi_enemy_o_col[1] = (float)CVar_GetS32("gNavi_Enemy_Outer_G", 220)/255; + navi_enemy_o_col[2] = (float)CVar_GetS32("gNavi_Enemy_Outer_B", 0)/255; + navi_prop_i_col[0] = (float)CVar_GetS32("gNavi_Prop_Inner_R", 0)/255; + navi_prop_i_col[1] = (float)CVar_GetS32("gNavi_Prop_Inner_G", 255)/255; + navi_prop_i_col[2] = (float)CVar_GetS32("gNavi_Prop_Inner_B", 0)/255; + navi_prop_o_col[0] = (float)CVar_GetS32("gNavi_Prop_Outer_R", 0)/255; + navi_prop_o_col[1] = (float)CVar_GetS32("gNavi_Prop_Outer_G", 220)/255; + navi_prop_o_col[2] = (float)CVar_GetS32("gNavi_Prop_Outer_B", 0)/255; + if (CVar_GetS32("gHudColors", 1) ==0) { + SelectedHUD = 0; + } else if (CVar_GetS32("gHudColors", 1) == 1) { + SelectedHUD = 1; + } else if (CVar_GetS32("gHudColors", 1) == 2) { + SelectedHUD = 2; + } + } + void LoadResource(const std::string& name, const std::string& path, const ImVec4& tint) { GfxRenderingAPI* api = gfx_get_current_rendering_api(); const auto res = static_cast(GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(path).get()); @@ -483,25 +527,22 @@ namespace SohImGui { } } - void EnhancementColor3(std::string text, std::string cvarName, float defaultColors[3]) - { - int r = CVar_GetS32((cvarName + "_Red").c_str(), (defaultColors[0] * 255.0f)); - int g = CVar_GetS32((cvarName + "_Green").c_str(), (defaultColors[1] * 255.0f)); - int b = CVar_GetS32((cvarName + "_Blue").c_str(), (defaultColors[2] * 255.0f)); + int ClampFloatToInt(float value, int min, int max){ + return fmin(fmax(value,min),max); + } - float colors[3]; - colors[0] = r / 255.0f; - colors[1] = g / 255.0f; - colors[2] = b / 255.0f; - - { - if (ImGui::ColorEdit3(text.c_str(), colors)) - { - CVar_SetS32((cvarName + "_Red").c_str(), (int)(colors[0] * 255)); - CVar_SetS32((cvarName + "_Green").c_str(), (int)(colors[1] * 255)); - CVar_SetS32((cvarName + "_Blue").c_str(), (int)(colors[2] * 255)); - needs_save = true; - } + void EnhancementColor3(std::string text, std::string cvarName, float ColorRGB[3], bool TitleSameLine) { + //Simplified. + ImGuiColorEditFlags flags = ImGuiColorEditFlags_None; + if (!TitleSameLine){ + ImGui::Text("%s", text.c_str()); + flags = ImGuiColorEditFlags_NoLabel; + } + if (ImGui::ColorEdit3(text.c_str(), ColorRGB, flags)) { + CVar_SetS32((cvarName+"R").c_str(), ClampFloatToInt(ColorRGB[0]*255,0,255)); + CVar_SetS32((cvarName+"G").c_str(), ClampFloatToInt(ColorRGB[1]*255,0,255)); + CVar_SetS32((cvarName+"B").c_str(), ClampFloatToInt(ColorRGB[2]*255,0,255)); + needs_save = true; } } @@ -515,6 +556,7 @@ namespace SohImGui { ImGuiBackendNewFrame(); ImGuiWMNewFrame(); ImGui::NewFrame(); + LoadInterfaceEditor(); const std::shared_ptr wnd = GlobalCtx2::GetInstance()->GetWindow(); ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoBackground | @@ -720,28 +762,21 @@ namespace SohImGui { ImGui::EndMenu(); } - if (ImGui::BeginMenu("Cosmetics")) - { - ImGui::Text("Tunics"); - ImGui::Separator(); - - EnhancementColor3("Kokiri Tunic", "gTunic_Kokiri", kokiri_col); - EnhancementColor3("Goron Tunic", "gTunic_Goron", goron_col); - EnhancementColor3("Zora Tunic", "gTunic_Zora", zora_col); - - ImGui::Text("Navi"); - ImGui::Separator(); - - EnhancementColor3("Navi Idle Inner", "gNavi_Idle_Inner", navi_idle_i_col); - EnhancementColor3("Navi Idle Outer", "gNavi_Idle_Outer", navi_idle_o_col); - EnhancementColor3("Navi NPC Inner", "gNavi_NPC_Inner", navi_npc_i_col); - EnhancementColor3("Navi NPC Outer", "gNavi_NPC_Outer", navi_npc_o_col); - EnhancementColor3("Navi Enemy Inner", "gNavi_Enemy_Inner", navi_enemy_i_col); - EnhancementColor3("Navi Enemy Outer", "gNavi_Enemy_Outer", navi_enemy_o_col); - EnhancementColor3("Navi Prop Inner", "gNavi_Prop_Inner", navi_prop_i_col); - EnhancementColor3("Navi Prop Outer", "gNavi_Prop_Outer", navi_prop_o_col); - - ImGui::EndMenu(); + if (ImGui::BeginMenu("Cosmetics")) { + EnhancementCheckbox("Cosmetics editor", "gCosmticsEditor"); + Tooltip("Edit Navi and Link's Tunics color."); + EnhancementCheckbox("HUD Margins editor", "gUseMargins"); + EnhancementRadioButton("N64 interface", "gHudColors", 0); + Tooltip("Change interface color to N64 style."); + EnhancementRadioButton("Gamecube interface", "gHudColors", 1); + Tooltip("Change interface color to Gamecube style."); + EnhancementRadioButton("Custom interface", "gHudColors", 2); + Tooltip("Change interface color to your own made style."); + if (CVar_GetS32("gHudColors", 1) == 2) { + EnhancementCheckbox("Interface editor", "gColorsEditor"); + Tooltip("Edit the colors used for your own interface"); + } + ImGui::EndMenu(); } if (ImGui::BeginMenu("Cheats")) @@ -788,6 +823,126 @@ namespace SohImGui { ImGui::EndMenu(); } + bool Margins_isOpen = CVar_GetS32("gUseMargins", 0); + bool Cosmetics_isOpen = CVar_GetS32("gCosmticsEditor", 0); + bool Interface_isOpen = CVar_GetS32("gColorsEditor", 0); + + if (Margins_isOpen) { + if (!Margins_isOpen) { + return; + } + ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0, 0, 0, 0)); + ImGui::Begin("Margins Editor", nullptr, ImGuiWindowFlags_NoFocusOnAppearing); + if (ImGui::BeginTabBar("Margins Editor", ImGuiTabBarFlags_NoCloseWithMiddleMouseButton)) { + if (ImGui::BeginTabItem("Interface margins")) { + EnhancementCheckbox("Use margins", "gHUDMargins"); + Tooltip("Enable/Disable custom margins. \nIf disabled you will have original margins"); + EnhancementSliderInt("Top : %dx", "##UIMARGINT", "gHUDMargin_T", -20, 20, ""); + EnhancementSliderInt("Left: %dx", "##UIMARGINL", "gHUDMargin_L", -25, 25, ""); + EnhancementSliderInt("Right: %dx", "##UIMARGINR", "gHUDMargin_R", -25, 25, ""); + EnhancementSliderInt("Bottom: %dx", "##UIMARGINB", "gHUDMargin_B", -20, 20, ""); + ImGui::EndTabItem(); + } + ImGui::EndTabBar(); + } + ImGui::PopStyleColor(); + ImGui::End(); + } + if (Cosmetics_isOpen) { + if (!Cosmetics_isOpen) { + return; + } + ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0, 0, 0, 0)); + ImGui::Begin("Cosmetics Editor", nullptr, ImGuiWindowFlags_NoFocusOnAppearing); + if (ImGui::BeginTabBar("Cosmetics Editor", ImGuiTabBarFlags_NoCloseWithMiddleMouseButton)) { + if (ImGui::BeginTabItem("Navi")) { + EnhancementCheckbox("Custom colors for Navi", "gUseNaviCol"); + Tooltip("Enable/Disable custom Navi's colors. \nIf disabled you will have original colors for Navi.\nColors are refreshed when Navi goes back in your pockets"); + EnhancementColor3("Navi Idle Inner", "gNavi_Idle_Inner_", navi_idle_i_col, false); + Tooltip("Inner color for Navi (idle flying around)"); + EnhancementColor3("Navi Idle Outer", "gNavi_Idle_Outer_", navi_idle_o_col, false); + Tooltip("Outer color for Navi (idle flying around)"); + ImGui::Separator(); + EnhancementColor3("Navi NPC Inner", "gNavi_NPC_Inner_", navi_npc_i_col, false); + Tooltip("Inner color for Navi (when Navi fly around NPCs)"); + EnhancementColor3("Navi NPC Outer", "gNavi_NPC_Outer_", navi_npc_o_col, false); + Tooltip("Outer color for Navi (when Navi fly around NPCs)"); + ImGui::Separator(); + EnhancementColor3("Navi Enemy Inner", "gNavi_Enemy_Inner_", navi_enemy_i_col, false); + Tooltip("Inner color for Navi (when Navi fly around Enemies or Bosses)"); + EnhancementColor3("Navi Enemy Outer", "gNavi_Enemy_Outer_", navi_enemy_o_col, false); + Tooltip("Outer color for Navi (when Navi fly around Enemies or Bosses)"); + ImGui::Separator(); + EnhancementColor3("Navi Prop Inner", "gNavi_Prop_Inner_", navi_prop_i_col, false); + Tooltip("Inner color for Navi (when Navi fly around props (signs etc))"); + EnhancementColor3("Navi Prop Outer", "gNavi_Prop_Outer_", navi_prop_o_col, false); + Tooltip("Outer color for Navi (when Navi fly around props (signs etc))"); + ImGui::EndTabItem(); + } + if (ImGui::BeginTabItem("Tunics")) { + EnhancementCheckbox("Custom colors on tunics", "gUseTunicsCol"); + Tooltip("Enable/Disable custom Link's tunics colors. \nIf disabled you will have original colors for Link's tunics"); + EnhancementColor3("Kokiri Tunic", "gTunic_Kokiri_", kokiri_col, false); + ImGui::Separator(); + EnhancementColor3("Goron Tunic", "gTunic_Goron_", goron_col, false); + ImGui::Separator(); + EnhancementColor3("Zora Tunic", "gTunic_Zora_", zora_col, false); + ImGui::EndTabItem(); + } + ImGui::EndTabBar(); + } + ImGui::PopStyleColor(); + ImGui::End(); + } + if (Interface_isOpen) { + if (!Interface_isOpen) { + return; + } + ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0, 0, 0, 0)); + ImGui::Begin("Interface Editor", nullptr, ImGuiWindowFlags_NoFocusOnAppearing); + if (ImGui::BeginTabBar("Interface Editor", ImGuiTabBarFlags_NoCloseWithMiddleMouseButton)) { + if (ImGui::BeginTabItem("Hearts")) { + EnhancementColor3("Hearts inner", "gCCHeartsPrim", hearts_colors, false); + Tooltip("Hearts inner color (red in original)\nAffect both Normal Hearts and the ones in Double Defense"); + EnhancementColor3("Hearts double def", "gDDCCHeartsPrim", hearts_dd_colors, false); + Tooltip("Hearts outline color (white in original)\nAffect Double Defense outline only"); + ImGui::EndTabItem(); + } + if (ImGui::BeginTabItem("Buttons")) { + EnhancementColor3("A Buttons", "gCCABtnPrim", a_btn_colors, false); + Tooltip("A Buttons colors (Green in original Gamecube)\nAffect A buttons colors on interface, in shops, messages boxes, ocarina notes and inventory cursors"); + EnhancementColor3("B Buttons", "gCCBBtnPrim", b_btn_colors, false); + Tooltip("B Button colors (Red in original Gamecube)\nAffect B button colors on interface"); + EnhancementColor3("C Buttons", "gCCCBtnPrim", c_btn_colors, false); + Tooltip("C Buttons colors (Yellowish / Oranges in originals)\nAffect C buttons colors on interface, in inventory and ocarina notes"); + EnhancementColor3("Start Buttons", "gCCStartBtnPrim", start_btn_colors, false); + Tooltip("Start Button colors (gray in Gamecube)\nAffect Start button colors in inventory"); + ImGui::EndTabItem(); + } + if (ImGui::BeginTabItem("Magic Bar")) { + EnhancementColor3("Magic bar borders", "gCCMagicBorderPrim", magic_border_colors, false); + Tooltip("Affect the border of the magic bar when being used\nWhite flash in original game"); + EnhancementColor3("Magic bar main color", "gCCMagicPrim", magic_remaining_colors, false); + Tooltip("Affect the magic bar color\nGreen in original game"); + EnhancementColor3("Magic bar being used", "gCCMagicUsePrim", magic_use_colors, false); + Tooltip("Affect the magic bar when being used\nYellow in original game"); + ImGui::EndTabItem(); + } + if (ImGui::BeginTabItem("Misc")) { + EnhancementColor3("Minimap color", "gCCMinimapPrim", minimap_colors, false); + Tooltip("Affect the Dungeon and Overworld minimaps"); + EnhancementColor3("Rupee icon color", "gCCRupeePrim", rupee_colors, false); + Tooltip("Affect the Rupee icon on interface\nGreen by default"); + EnhancementColor3("Small Keys icon color", "gCCKeysPrim", smolekey_colors, false); + Tooltip("Affect the Small keys icon on interface\nGray by default"); + ImGui::EndTabItem(); + } + ImGui::EndTabBar(); + } + ImGui::PopStyleColor(); + ImGui::End(); + } + for (const auto& category : windowCategories) { if (ImGui::BeginMenu(category.first.c_str())) { for (const std::string& name : category.second) { diff --git a/libultraship/libultraship/SohImGuiImpl.h b/libultraship/libultraship/SohImGuiImpl.h index dd0ec9fd3..210a26db9 100644 --- a/libultraship/libultraship/SohImGuiImpl.h +++ b/libultraship/libultraship/SohImGuiImpl.h @@ -68,6 +68,7 @@ namespace SohImGui { void EnhancementCheckbox(std::string text, std::string cvarName); void EnhancementSliderInt(std::string text, std::string id, std::string cvarName, int min, int max, std::string format); void EnhancementSliderFloat(std::string text, std::string id, std::string cvarName, float min, float max, std::string format, float defaultValue); + void EnhancementColor3(std::string text, std::string cvarName, float ColorRGB[3], bool TitleSameLine); void DrawMainMenuAndCalculateGameSize(void); @@ -78,6 +79,7 @@ namespace SohImGui { void BindCmd(const std::string& cmd, CommandEntry entry); void AddWindow(const std::string& category, const std::string& name, WindowDrawFunc drawFunc); void LoadResource(const std::string& name, const std::string& path, const ImVec4& tint = ImVec4(1, 1, 1, 1)); + void LoadInterfaceEditor(); ImTextureID GetTextureByID(int id); ImTextureID GetTextureByName(const std::string& name); } diff --git a/soh/soh/Enhancements/bootcommands.c b/soh/soh/Enhancements/bootcommands.c index ffe3c70d0..fa6db7487 100644 --- a/soh/soh/Enhancements/bootcommands.c +++ b/soh/soh/Enhancements/bootcommands.c @@ -32,6 +32,9 @@ void BootCommands_Init() CVar_RegisterS32("gNewDrops", 0); CVar_RegisterS32("gVisualAgony", 0); CVar_RegisterS32("gLanguages", 0); //0 = English / 1 = German / 2 = French + CVar_RegisterS32("gHudColors", 1); //0 = N64 / 1 = NGC / 2 = Custom + CVar_RegisterS32("gUseNaviCol", 0); + CVar_RegisterS32("gUseTunicsCol", 0); } //void BootCommands_ParseBootArgs(char* str) diff --git a/soh/src/code/z_actor.c b/soh/src/code/z_actor.c index caa16a7ec..ba5d4dcd6 100644 --- a/soh/src/code/z_actor.c +++ b/soh/src/code/z_actor.c @@ -335,38 +335,59 @@ void func_8002BE98(TargetContext* targetCtx, s32 actorCategory, GlobalContext* g void func_8002BF60(TargetContext* targetCtx, Actor* actor, s32 actorCategory, GlobalContext* globalCtx) { NaviColor* naviColor = &sNaviColorList[actorCategory]; - if (actorCategory == ACTORCAT_PLAYER) { - naviColor->inner.r = CVar_GetS32("gNavi_Idle_Inner_Red", naviColor->inner.r); - naviColor->inner.g = CVar_GetS32("gNavi_Idle_Inner_Green", naviColor->inner.g); - naviColor->inner.b = CVar_GetS32("gNavi_Idle_Inner_Blue", naviColor->inner.b); - naviColor->outer.r = CVar_GetS32("gNavi_Idle_Outer_Red", naviColor->outer.r); - naviColor->outer.g = CVar_GetS32("gNavi_Idle_Outer_Green", naviColor->outer.g); - naviColor->outer.b = CVar_GetS32("gNavi_Idle_Outer_Blue", naviColor->outer.b); - } - if (actorCategory == ACTORCAT_NPC) { - naviColor->inner.r = CVar_GetS32("gNavi_NPC_Inner_Red", naviColor->inner.r); - naviColor->inner.g = CVar_GetS32("gNavi_NPC_Inner_Green", naviColor->inner.g); - naviColor->inner.b = CVar_GetS32("gNavi_NPC_Inner_Blue", naviColor->inner.b); - naviColor->outer.r = CVar_GetS32("gNavi_NPC_Outer_Red", naviColor->outer.r); - naviColor->outer.g = CVar_GetS32("gNavi_NPC_Outer_Green", naviColor->outer.g); - naviColor->outer.b = CVar_GetS32("gNavi_NPC_Outer_Blue", naviColor->outer.b); - } - if (actorCategory == ACTORCAT_BOSS || actorCategory == ACTORCAT_ENEMY) { - naviColor->inner.r = CVar_GetS32("gNavi_Enemy_Inner_Red", naviColor->inner.r); - naviColor->inner.g = CVar_GetS32("gNavi_Enemy_Inner_Green", naviColor->inner.g); - naviColor->inner.b = CVar_GetS32("gNavi_Enemy_Inner_Blue", naviColor->inner.b); - naviColor->outer.r = CVar_GetS32("gNavi_Enemy_Outer_Red", naviColor->outer.r); - naviColor->outer.g = CVar_GetS32("gNavi_Enemy_Outer_Green", naviColor->outer.g); - naviColor->outer.b = CVar_GetS32("gNavi_Enemy_Outer_Blue", naviColor->outer.b); - } - if (actorCategory == ACTORCAT_PROP) { - naviColor->inner.r = CVar_GetS32("gNavi_Prop_Inner_Red", naviColor->inner.r); - naviColor->inner.g = CVar_GetS32("gNavi_Prop_Inner_Green", naviColor->inner.g); - naviColor->inner.b = CVar_GetS32("gNavi_Prop_Inner_Blue", naviColor->inner.b); - naviColor->outer.r = CVar_GetS32("gNavi_Prop_Outer_Red", naviColor->outer.r); - naviColor->outer.g = CVar_GetS32("gNavi_Prop_Outer_Green", naviColor->outer.g); - naviColor->outer.b = CVar_GetS32("gNavi_Prop_Outer_Blue", naviColor->outer.b); + + if (CVar_GetS32("gUseNaviCol",0) != 1 ) { + if (actorCategory == ACTORCAT_PLAYER) { + naviColor->inner.r = 255; naviColor->inner.g = 255; naviColor->inner.b = 255; + naviColor->outer.r = 115; naviColor->outer.g = 230; naviColor->outer.b = 255; + } + if (actorCategory == ACTORCAT_NPC) { + naviColor->inner.r = 100; naviColor->inner.g = 100; naviColor->inner.b = 255; + naviColor->outer.r = 90; naviColor->outer.g = 90; naviColor->outer.b = 255; + } + if (actorCategory == ACTORCAT_BOSS || actorCategory == ACTORCAT_ENEMY) { + naviColor->inner.r = 255; naviColor->inner.g = 255; naviColor->inner.b = 0; + naviColor->outer.r = 220; naviColor->outer.g = 220; naviColor->outer.b = 0; + } + if (actorCategory == ACTORCAT_PROP) { + naviColor->inner.r = 0; naviColor->inner.g = 255; naviColor->inner.b = 90; + naviColor->outer.r = 0; naviColor->outer.g = 220; naviColor->outer.b = 0; + } + } else { + if (actorCategory == ACTORCAT_PLAYER) { + naviColor->inner.r = CVar_GetS32("gNavi_Idle_Inner_R", naviColor->inner.r); + naviColor->inner.g = CVar_GetS32("gNavi_Idle_Inner_G", naviColor->inner.g); + naviColor->inner.b = CVar_GetS32("gNavi_Idle_Inner_B", naviColor->inner.b); + naviColor->outer.r = CVar_GetS32("gNavi_Idle_Outer_R", naviColor->outer.r); + naviColor->outer.g = CVar_GetS32("gNavi_Idle_Outer_G", naviColor->outer.g); + naviColor->outer.b = CVar_GetS32("gNavi_Idle_Outer_B", naviColor->outer.b); + } + if (actorCategory == ACTORCAT_NPC) { + naviColor->inner.r = CVar_GetS32("gNavi_NPC_Inner_R", naviColor->inner.r); + naviColor->inner.g = CVar_GetS32("gNavi_NPC_Inner_G", naviColor->inner.g); + naviColor->inner.b = CVar_GetS32("gNavi_NPC_Inner_B", naviColor->inner.b); + naviColor->outer.r = CVar_GetS32("gNavi_NPC_Outer_R", naviColor->outer.r); + naviColor->outer.g = CVar_GetS32("gNavi_NPC_Outer_G", naviColor->outer.g); + naviColor->outer.b = CVar_GetS32("gNavi_NPC_Outer_B", naviColor->outer.b); + } + if (actorCategory == ACTORCAT_BOSS || actorCategory == ACTORCAT_ENEMY) { + naviColor->inner.r = CVar_GetS32("gNavi_Enemy_Inner_R", naviColor->inner.r); + naviColor->inner.g = CVar_GetS32("gNavi_Enemy_Inner_G", naviColor->inner.g); + naviColor->inner.b = CVar_GetS32("gNavi_Enemy_Inner_B", naviColor->inner.b); + naviColor->outer.r = CVar_GetS32("gNavi_Enemy_Outer_R", naviColor->outer.r); + naviColor->outer.g = CVar_GetS32("gNavi_Enemy_Outer_G", naviColor->outer.g); + naviColor->outer.b = CVar_GetS32("gNavi_Enemy_Outer_B", naviColor->outer.b); + } + if (actorCategory == ACTORCAT_PROP) { + naviColor->inner.r = CVar_GetS32("gNavi_Prop_Inner_R", naviColor->inner.r); + naviColor->inner.g = CVar_GetS32("gNavi_Prop_Inner_G", naviColor->inner.g); + naviColor->inner.b = CVar_GetS32("gNavi_Prop_Inner_B", naviColor->inner.b); + naviColor->outer.r = CVar_GetS32("gNavi_Prop_Outer_R", naviColor->outer.r); + naviColor->outer.g = CVar_GetS32("gNavi_Prop_Outer_G", naviColor->outer.g); + naviColor->outer.b = CVar_GetS32("gNavi_Prop_Outer_B", naviColor->outer.b); + } } + targetCtx->naviRefPos.x = actor->focus.pos.x; targetCtx->naviRefPos.y = actor->focus.pos.y + (actor->targetArrowOffset * actor->scale.y); targetCtx->naviRefPos.z = actor->focus.pos.z; diff --git a/soh/src/code/z_lifemeter.c b/soh/src/code/z_lifemeter.c index 5f1863440..30b18683f 100644 --- a/soh/src/code/z_lifemeter.c +++ b/soh/src/code/z_lifemeter.c @@ -1,6 +1,11 @@ #include "global.h" #include "textures/parameter_static/parameter_static.h" +s16 Top_LM_Margin = 0; +s16 Left_LM_Margin = 0; +s16 Right_LM_Margin = 0; +s16 Bottom_LM_Margin = 0; + static s16 sHeartsPrimColors[3][3] = { { HEARTS_PRIM_R, HEARTS_PRIM_G, HEARTS_PRIM_B }, { HEARTS_BURN_PRIM_R, HEARTS_BURN_PRIM_G, HEARTS_BURN_PRIM_B }, // unused @@ -106,6 +111,9 @@ static s16 sHeartsDDEnvFactors[3][3] = { }; // Current colors for the double defense hearts +s16 HeartInner[3] = {HEARTS_PRIM_R,HEARTS_PRIM_G,HEARTS_PRIM_B}; +s16 HeartDDOutline[3] = {HEARTS_DD_PRIM_R,HEARTS_DD_PRIM_G,HEARTS_DD_PRIM_B}; +s16 HeartDDInner[3] = {HEARTS_DD_ENV_R,HEARTS_DD_ENV_G,HEARTS_DD_ENV_B}; s16 sBeatingHeartsDDPrim[3]; s16 sBeatingHeartsDDEnv[3]; s16 sHeartsDDPrim[2][3]; @@ -113,35 +121,47 @@ s16 sHeartsDDEnv[2][3]; void HealthMeter_Init(GlobalContext* globalCtx) { InterfaceContext* interfaceCtx = &globalCtx->interfaceCtx; - + if (CVar_GetS32("gHudColors", 1) == 2) { + HeartInner[0] = CVar_GetS32("gCCHeartsPrimR", 90); + HeartInner[1] = CVar_GetS32("gCCHeartsPrimG", 90); + HeartInner[2] = CVar_GetS32("gCCHeartsPrimB", 90); + HeartDDOutline[0] = CVar_GetS32("gDDCCHeartsPrimR", 90); + HeartDDOutline[1] = CVar_GetS32("gDDCCHeartsPrimG", 90); + HeartDDOutline[2] = CVar_GetS32("gDDCCHeartsPrimB", 90); + } + interfaceCtx->unk_228 = 0x140; interfaceCtx->unk_226 = gSaveContext.health; interfaceCtx->unk_22A = interfaceCtx->unk_1FE = 0; interfaceCtx->unk_22C = interfaceCtx->unk_200 = 0; - interfaceCtx->heartsPrimR[0] = HEARTS_PRIM_R; - interfaceCtx->heartsPrimG[0] = HEARTS_PRIM_G; - interfaceCtx->heartsPrimB[0] = HEARTS_PRIM_B; + interfaceCtx->heartsPrimR[0] = HeartInner[0]; + interfaceCtx->heartsPrimG[0] = HeartInner[1]; + interfaceCtx->heartsPrimB[0] = HeartInner[2]; interfaceCtx->heartsEnvR[0] = HEARTS_ENV_R; interfaceCtx->heartsEnvG[0] = HEARTS_ENV_G; interfaceCtx->heartsEnvB[0] = HEARTS_ENV_B; - interfaceCtx->heartsPrimR[1] = HEARTS_PRIM_R; - interfaceCtx->heartsPrimG[1] = HEARTS_PRIM_G; - interfaceCtx->heartsPrimB[1] = HEARTS_PRIM_B; + interfaceCtx->heartsPrimR[1] = HeartInner[0]; + interfaceCtx->heartsPrimG[1] = HeartInner[1]; + interfaceCtx->heartsPrimB[1] = HeartInner[2]; interfaceCtx->heartsEnvR[1] = HEARTS_ENV_R; interfaceCtx->heartsEnvG[1] = HEARTS_ENV_G; interfaceCtx->heartsEnvB[1] = HEARTS_ENV_B; - sHeartsDDPrim[0][0] = sHeartsDDPrim[1][0] = HEARTS_DD_PRIM_R; - sHeartsDDPrim[0][1] = sHeartsDDPrim[1][1] = HEARTS_DD_PRIM_G; - sHeartsDDPrim[0][2] = sHeartsDDPrim[1][2] = HEARTS_DD_PRIM_B; + sHeartsDDPrim[0][0] = sHeartsDDPrim[1][0] = HeartDDOutline[0]; + sHeartsDDPrim[0][1] = sHeartsDDPrim[1][1] = HeartDDOutline[1]; + sHeartsDDPrim[0][2] = sHeartsDDPrim[1][2] = HeartDDOutline[2]; - sHeartsDDEnv[0][0] = sHeartsDDEnv[1][0] = HEARTS_DD_ENV_R; - sHeartsDDEnv[0][1] = sHeartsDDEnv[1][1] = HEARTS_DD_ENV_G; - sHeartsDDEnv[0][2] = sHeartsDDEnv[1][2] = HEARTS_DD_ENV_B; + sHeartsDDPrim[2][0] = HeartInner[0]; + sHeartsDDPrim[2][1] = HeartInner[1]; + sHeartsDDPrim[2][2] = HeartInner[2]; + + sHeartsDDEnv[0][0] = sHeartsDDEnv[1][0] = HeartDDInner[0]; + sHeartsDDEnv[0][1] = sHeartsDDEnv[1][1] = HeartDDInner[1]; + sHeartsDDEnv[0][2] = sHeartsDDEnv[1][2] = HeartDDInner[2]; } void HealthMeter_Update(GlobalContext* globalCtx) { @@ -154,7 +174,33 @@ void HealthMeter_Update(GlobalContext* globalCtx) { s16 gFactor; s16 bFactor; - if (interfaceCtx) {} + if (CVar_GetS32("gHUDMargins", 0) != 0) { + Top_LM_Margin = CVar_GetS32("gHUDMargin_T", 0); + Left_LM_Margin = CVar_GetS32("gHUDMargin_L", 0); + Right_LM_Margin = CVar_GetS32("gHUDMargin_R", 0); + Bottom_LM_Margin = CVar_GetS32("gHUDMargin_B", 0); + } else { + Top_LM_Margin = 0; + Left_LM_Margin = 0; + Right_LM_Margin = 0; + Bottom_LM_Margin = 0; + } + + if (CVar_GetS32("gHudColors", 1) == 2) { + HeartInner[0] = CVar_GetS32("gCCHeartsPrimR", sHeartsPrimColors[0][0]); + HeartInner[1] = CVar_GetS32("gCCHeartsPrimG", sHeartsPrimColors[0][1]); + HeartInner[2] = CVar_GetS32("gCCHeartsPrimB", sHeartsPrimColors[0][2]); + HeartDDOutline[0] = CVar_GetS32("gDDCCHeartsPrimR", sHeartsDDPrim[0][0]); + HeartDDOutline[1] = CVar_GetS32("gDDCCHeartsPrimG", sHeartsDDPrim[0][1]); + HeartDDOutline[2] = CVar_GetS32("gDDCCHeartsPrimB", sHeartsDDPrim[0][2]); + } else { + HeartInner[0] = sHeartsPrimColors[0][0]; + HeartInner[1] = sHeartsPrimColors[0][1]; + HeartInner[2] = sHeartsPrimColors[0][2]; + HeartDDOutline[0] = sHeartsDDPrim[0][0]; + HeartDDOutline[1] = sHeartsDDPrim[0][1]; + HeartDDOutline[2] = sHeartsDDPrim[0][2]; + } if (interfaceCtx->unk_200 != 0) { interfaceCtx->unk_1FE--; @@ -172,17 +218,23 @@ void HealthMeter_Update(GlobalContext* globalCtx) { ddFactor = factor; - interfaceCtx->heartsPrimR[0] = HEARTS_PRIM_R; - interfaceCtx->heartsPrimG[0] = HEARTS_PRIM_G; - interfaceCtx->heartsPrimB[0] = HEARTS_PRIM_B; + interfaceCtx->heartsPrimR[0] = HeartInner[0]; + interfaceCtx->heartsPrimG[0] = HeartInner[1]; + interfaceCtx->heartsPrimB[0] = HeartInner[2]; interfaceCtx->heartsEnvR[0] = HEARTS_ENV_R; interfaceCtx->heartsEnvG[0] = HEARTS_ENV_G; interfaceCtx->heartsEnvB[0] = HEARTS_ENV_B; - interfaceCtx->heartsPrimR[1] = sHeartsPrimColors[type][0]; - interfaceCtx->heartsPrimG[1] = sHeartsPrimColors[type][1]; - interfaceCtx->heartsPrimB[1] = sHeartsPrimColors[type][2]; + if (CVar_GetS32("gHudColors", 1) == 2) { + interfaceCtx->heartsPrimR[1] = HeartInner[0]; + interfaceCtx->heartsPrimG[1] = HeartInner[1]; + interfaceCtx->heartsPrimB[1] = HeartInner[2]; + } else { + interfaceCtx->heartsPrimR[1] = sHeartsPrimColors[type][0]; + interfaceCtx->heartsPrimG[1] = sHeartsPrimColors[type][1]; + interfaceCtx->heartsPrimB[1] = sHeartsPrimColors[type][2]; + } interfaceCtx->heartsEnvR[1] = sHeartsEnvColors[type][0]; interfaceCtx->heartsEnvG[1] = sHeartsEnvColors[type][1]; @@ -192,52 +244,90 @@ void HealthMeter_Update(GlobalContext* globalCtx) { gFactor = sHeartsPrimFactors[0][1] * factor; bFactor = sHeartsPrimFactors[0][2] * factor; - interfaceCtx->beatingHeartPrim[0] = (u8)(rFactor + HEARTS_PRIM_R) & 0xFF; - interfaceCtx->beatingHeartPrim[1] = (u8)(gFactor + HEARTS_PRIM_G) & 0xFF; - interfaceCtx->beatingHeartPrim[2] = (u8)(bFactor + HEARTS_PRIM_B) & 0xFF; + interfaceCtx->beatingHeartPrim[0] = (u8)(rFactor + HeartInner[0]) & 0xFF; + interfaceCtx->beatingHeartPrim[1] = (u8)(gFactor + HeartInner[1]) & 0xFF; + interfaceCtx->beatingHeartPrim[2] = (u8)(bFactor + HeartInner[2]) & 0xFF; rFactor = sHeartsEnvFactors[0][0] * factor; gFactor = sHeartsEnvFactors[0][1] * factor; bFactor = sHeartsEnvFactors[0][2] * factor; - if (1) {} - ddType = type; - interfaceCtx->beatingHeartEnv[0] = (u8)(rFactor + HEARTS_ENV_R) & 0xFF; interfaceCtx->beatingHeartEnv[1] = (u8)(gFactor + HEARTS_ENV_G) & 0xFF; interfaceCtx->beatingHeartEnv[2] = (u8)(bFactor + HEARTS_ENV_B) & 0xFF; - sHeartsDDPrim[0][0] = HEARTS_DD_PRIM_R; - sHeartsDDPrim[0][1] = HEARTS_DD_PRIM_G; - sHeartsDDPrim[0][2] = HEARTS_DD_PRIM_B; + ddType = type; - sHeartsDDEnv[0][0] = HEARTS_DD_ENV_R; - sHeartsDDEnv[0][1] = HEARTS_DD_ENV_G; - sHeartsDDEnv[0][2] = HEARTS_DD_ENV_B; + sHeartsDDPrim[0][0] = HeartDDOutline[0]; + sHeartsDDPrim[0][1] = HeartDDOutline[1]; + sHeartsDDPrim[0][2] = HeartDDOutline[2]; - sHeartsDDPrim[1][0] = sHeartsDDPrimColors[ddType][0]; - sHeartsDDPrim[1][1] = sHeartsDDPrimColors[ddType][1]; - sHeartsDDPrim[1][2] = sHeartsDDPrimColors[ddType][2]; + sHeartsDDEnv[0][0] = HeartDDInner[0]; + sHeartsDDEnv[0][1] = HeartDDInner[1]; + sHeartsDDEnv[0][2] = HeartDDInner[2]; - sHeartsDDEnv[1][0] = sHeartsDDEnvColors[ddType][0]; - sHeartsDDEnv[1][1] = sHeartsDDEnvColors[ddType][1]; - sHeartsDDEnv[1][2] = sHeartsDDEnvColors[ddType][2]; + if (CVar_GetS32("gHudColors", 1) == 2) { + sHeartsDDPrim[2][0] = HeartInner[0]; + sHeartsDDPrim[2][1] = HeartInner[1]; + sHeartsDDPrim[2][2] = HeartInner[2]; - rFactor = sHeartsDDPrimFactors[ddType][0] * ddFactor; - gFactor = sHeartsDDPrimFactors[ddType][1] * ddFactor; - bFactor = sHeartsDDPrimFactors[ddType][2] * ddFactor; + sHeartsDDPrim[1][0] = HeartDDOutline[0]; + sHeartsDDPrim[1][1] = HeartDDOutline[1]; + sHeartsDDPrim[1][2] = HeartDDOutline[2]; - sBeatingHeartsDDPrim[0] = (u8)(rFactor + HEARTS_DD_PRIM_R) & 0xFF; - sBeatingHeartsDDPrim[1] = (u8)(gFactor + HEARTS_DD_PRIM_G) & 0xFF; - sBeatingHeartsDDPrim[2] = (u8)(bFactor + HEARTS_DD_PRIM_B) & 0xFF; + sHeartsDDEnv[1][0] = HeartDDInner[0]; + sHeartsDDEnv[1][1] = HeartDDInner[1]; + sHeartsDDEnv[1][2] = HeartDDInner[2]; - rFactor = sHeartsDDEnvFactors[ddType][0] * ddFactor; - gFactor = sHeartsDDEnvFactors[ddType][1] * ddFactor; - bFactor = sHeartsDDEnvFactors[ddType][2] * ddFactor; + HeartDDInner[0] = HeartInner[0]; + HeartDDInner[1] = HeartInner[1]; + HeartDDInner[2] = HeartInner[2]; + + rFactor = sHeartsDDPrimFactors[ddType][0] * ddFactor; + gFactor = sHeartsDDPrimFactors[ddType][1] * ddFactor; + bFactor = sHeartsDDPrimFactors[ddType][2] * ddFactor; + + sBeatingHeartsDDPrim[0] = (u8)(rFactor + HeartDDOutline[0]) & 0xFF; + sBeatingHeartsDDPrim[1] = (u8)(gFactor + HeartDDOutline[1]) & 0xFF; + sBeatingHeartsDDPrim[2] = (u8)(bFactor + HeartDDOutline[2]) & 0xFF; + + rFactor = sHeartsDDEnvFactors[ddType][0] * ddFactor; + gFactor = sHeartsDDEnvFactors[ddType][1] * ddFactor; + bFactor = sHeartsDDEnvFactors[ddType][2] * ddFactor; + + sBeatingHeartsDDEnv[0] = (u8)(rFactor + HeartDDInner[0]) & 0xFF; + sBeatingHeartsDDEnv[1] = (u8)(gFactor + HeartDDInner[1]) & 0xFF; + sBeatingHeartsDDEnv[2] = (u8)(bFactor + HeartDDInner[2]) & 0xFF; + } else { + sHeartsDDPrim[2][0] = HeartInner[0]; + sHeartsDDPrim[2][1] = HeartInner[1]; + sHeartsDDPrim[2][2] = HeartInner[2]; + + sHeartsDDPrim[1][0] = sHeartsDDPrimColors[ddType][0]; + sHeartsDDPrim[1][1] = sHeartsDDPrimColors[ddType][1]; + sHeartsDDPrim[1][2] = sHeartsDDPrimColors[ddType][2]; + + sHeartsDDEnv[1][0] = sHeartsDDEnvColors[ddType][0]; + sHeartsDDEnv[1][1] = sHeartsDDEnvColors[ddType][1]; + sHeartsDDEnv[1][2] = sHeartsDDEnvColors[ddType][2]; + + rFactor = sHeartsDDPrimFactors[ddType][0] * ddFactor; + gFactor = sHeartsDDPrimFactors[ddType][1] * ddFactor; + bFactor = sHeartsDDPrimFactors[ddType][2] * ddFactor; + + sBeatingHeartsDDPrim[0] = (u8)(rFactor + HeartDDOutline[0]) & 0xFF; + sBeatingHeartsDDPrim[1] = (u8)(gFactor + HeartDDOutline[1]) & 0xFF; + sBeatingHeartsDDPrim[2] = (u8)(bFactor + HeartDDOutline[2]) & 0xFF; + + rFactor = sHeartsDDEnvFactors[ddType][0] * ddFactor; + gFactor = sHeartsDDEnvFactors[ddType][1] * ddFactor; + bFactor = sHeartsDDEnvFactors[ddType][2] * ddFactor; + + sBeatingHeartsDDEnv[0] = (u8)(rFactor + HeartDDInner[0]) & 0xFF; + sBeatingHeartsDDEnv[1] = (u8)(gFactor + HeartDDInner[1]) & 0xFF; + sBeatingHeartsDDEnv[2] = (u8)(bFactor + HeartDDInner[2]) & 0xFF; + } - sBeatingHeartsDDEnv[0] = (u8)(rFactor + HEARTS_DD_ENV_R) & 0xFF; - sBeatingHeartsDDEnv[1] = (u8)(gFactor + HEARTS_DD_ENV_G) & 0xFF; - sBeatingHeartsDDEnv[2] = (u8)(bFactor + HEARTS_DD_ENV_B) & 0xFF; } s32 func_80078E18(GlobalContext* globalCtx) { @@ -322,8 +412,8 @@ void HealthMeter_Draw(GlobalContext* globalCtx) { } curColorSet = -1; - offsetY = 0.0f; - offsetX = OTRGetDimensionFromLeftEdge(0.0f); + offsetY = 0.0f+(Top_LM_Margin*-1); + offsetX = OTRGetDimensionFromLeftEdge(0.0f)+(Left_LM_Margin*-1); for (i = 0; i < totalHeartCount; i++) { if ((ddHeartCountMinusOne < 0) || (i > ddHeartCountMinusOne)) { @@ -483,7 +573,7 @@ void HealthMeter_Draw(GlobalContext* globalCtx) { offsetX += 10.0f; if (i == 9) { offsetY += 10.0f; - offsetX = OTRGetDimensionFromLeftEdge(0.0f); + offsetX = OTRGetDimensionFromLeftEdge(0.0f)+(Left_LM_Margin*-1); } } @@ -530,4 +620,4 @@ u32 HealthMeter_IsCritical(void) { } else { return false; } -} +} \ No newline at end of file diff --git a/soh/src/code/z_map_exp.c b/soh/src/code/z_map_exp.c index e97a1a1a5..5402cee44 100644 --- a/soh/src/code/z_map_exp.c +++ b/soh/src/code/z_map_exp.c @@ -12,6 +12,11 @@ s16 sPlayerInitialPosZ = 0; s16 sPlayerInitialDirection = 0; s16 sEntranceIconMapIndex = 0; +s16 Top_MM_Margin = 0; +s16 Left_MM_Margin = 0; +s16 Right_MM_Margin = 0; +s16 Bottom_MM_Margin = 0; + void Map_SavePlayerInitialInfo(GlobalContext* globalCtx) { Player* player = GET_PLAYER(globalCtx); @@ -604,11 +609,11 @@ void Minimap_DrawCompassIcons(GlobalContext* globalCtx) { PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0); gDPSetEnvColor(OVERLAY_DISP++, 0, 0, 0, 255); gDPSetCombineMode(OVERLAY_DISP++, G_CC_PRIMITIVE, G_CC_PRIMITIVE); - tempX = player->actor.world.pos.x; - tempZ = player->actor.world.pos.z; + tempX = player->actor.world.pos.x+Right_MM_Margin; + tempZ = player->actor.world.pos.z+Bottom_MM_Margin; tempX /= R_COMPASS_SCALE_X; tempZ /= R_COMPASS_SCALE_Y; - Matrix_Translate(OTRGetDimensionFromRightEdge((R_COMPASS_OFFSET_X + tempX) / 10.0f), (R_COMPASS_OFFSET_Y - tempZ) / 10.0f, 0.0f, MTXMODE_NEW); + Matrix_Translate(OTRGetDimensionFromRightEdge((R_COMPASS_OFFSET_X+(Right_MM_Margin*10) + tempX) / 10.0f), (R_COMPASS_OFFSET_Y+((Bottom_MM_Margin*10)*-1) - tempZ) / 10.0f, 0.0f, MTXMODE_NEW); Matrix_Scale(0.4f, 0.4f, 0.4f, MTXMODE_APPLY); Matrix_RotateX(-1.6f, MTXMODE_APPLY); tempX = (0x7FFF - player->actor.shape.rot.y) / 0x400; @@ -619,11 +624,11 @@ void Minimap_DrawCompassIcons(GlobalContext* globalCtx) { gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 200, 255, 0, 255); gSPDisplayList(OVERLAY_DISP++, gCompassArrowDL); - tempX = sPlayerInitialPosX; - tempZ = sPlayerInitialPosZ; + tempX = sPlayerInitialPosX+Right_MM_Margin; + tempZ = sPlayerInitialPosZ+Bottom_MM_Margin; tempX /= R_COMPASS_SCALE_X; tempZ /= R_COMPASS_SCALE_Y; - Matrix_Translate(OTRGetDimensionFromRightEdge((R_COMPASS_OFFSET_X + tempX) / 10.0f), (R_COMPASS_OFFSET_Y - tempZ) / 10.0f, 0.0f, MTXMODE_NEW); + Matrix_Translate(OTRGetDimensionFromRightEdge((R_COMPASS_OFFSET_X+(Right_MM_Margin*10) + tempX) / 10.0f), (R_COMPASS_OFFSET_Y+((Bottom_MM_Margin*10)*-1) - tempZ) / 10.0f, 0.0f, MTXMODE_NEW); Matrix_Scale(VREG(9) / 100.0f, VREG(9) / 100.0f, VREG(9) / 100.0f, MTXMODE_APPLY); Matrix_RotateX(VREG(52) / 10.0f, MTXMODE_APPLY); Matrix_RotateY(sPlayerInitialDirection / 10.0f, MTXMODE_APPLY); @@ -662,17 +667,22 @@ void Minimap_Draw(GlobalContext* globalCtx) { TEXEL0, 0, PRIMITIVE, 0); if (CHECK_DUNGEON_ITEM(DUNGEON_MAP, mapIndex)) { - gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 100, 255, 255, interfaceCtx->minimapAlpha); + if (CVar_GetS32("gHudColors", 1) == 2) { //Dungeon minimap + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetS32("gCCMinimapPrimR", R_MINIMAP_COLOR(0)), CVar_GetS32("gCCMinimapPrimG", R_MINIMAP_COLOR(1)), CVar_GetS32("gCCMinimapPrimB", R_MINIMAP_COLOR(2)), interfaceCtx->minimapAlpha); + } else { + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 100, 255, 255, interfaceCtx->minimapAlpha); + } gSPInvalidateTexCache(OVERLAY_DISP++, interfaceCtx->mapSegment); gDPLoadTextureBlock_4b(OVERLAY_DISP++, interfaceCtx->mapSegment, G_IM_FMT_I, 96, 85, 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); - const s16 dgnMiniMapX = OTRGetRectDimensionFromRightEdge(R_DGN_MINIMAP_X); + const s16 dgnMiniMapX = OTRGetRectDimensionFromRightEdge(R_DGN_MINIMAP_X + Right_MM_Margin); + const s16 dgnMiniMapY = R_DGN_MINIMAP_Y + Bottom_MM_Margin; - gSPWideTextureRectangle(OVERLAY_DISP++, dgnMiniMapX << 2, R_DGN_MINIMAP_Y << 2, - (dgnMiniMapX + 96) << 2, (R_DGN_MINIMAP_Y + 85) << 2, G_TX_RENDERTILE, + gSPWideTextureRectangle(OVERLAY_DISP++, dgnMiniMapX << 2, dgnMiniMapY << 2, + (dgnMiniMapX + 96) << 2, (dgnMiniMapY + 85) << 2, G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10); } @@ -719,27 +729,35 @@ void Minimap_Draw(GlobalContext* globalCtx) { func_80094520(globalCtx->state.gfxCtx); gDPSetCombineMode(OVERLAY_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM); - gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_MINIMAP_COLOR(0), R_MINIMAP_COLOR(1), R_MINIMAP_COLOR(2), - interfaceCtx->minimapAlpha); + if (CVar_GetS32("gHudColors", 1) == 2) {//Overworld minimap + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetS32("gCCMinimapPrimR", R_MINIMAP_COLOR(0)), CVar_GetS32("gCCMinimapPrimG", R_MINIMAP_COLOR(1)), CVar_GetS32("gCCMinimapPrimB", R_MINIMAP_COLOR(2)), interfaceCtx->minimapAlpha); + } else { + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_MINIMAP_COLOR(0), R_MINIMAP_COLOR(1), R_MINIMAP_COLOR(2), interfaceCtx->minimapAlpha); + } gDPLoadTextureBlock_4b(OVERLAY_DISP++, interfaceCtx->mapSegment, G_IM_FMT_IA, gMapData->owMinimapWidth[mapIndex], gMapData->owMinimapHeight[mapIndex], 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); - const s16 oWMiniMapX = OTRGetRectDimensionFromRightEdge(R_OW_MINIMAP_X); + const s16 oWMiniMapX = OTRGetRectDimensionFromRightEdge(R_OW_MINIMAP_X + Right_MM_Margin); + const s16 oWMiniMapY = R_OW_MINIMAP_Y + Bottom_MM_Margin; - gSPWideTextureRectangle(OVERLAY_DISP++, oWMiniMapX << 2, R_OW_MINIMAP_Y << 2, + gSPWideTextureRectangle(OVERLAY_DISP++, oWMiniMapX << 2, oWMiniMapY << 2, (oWMiniMapX + gMapData->owMinimapWidth[mapIndex]) << 2, - (R_OW_MINIMAP_Y + gMapData->owMinimapHeight[mapIndex]) << 2, G_TX_RENDERTILE, 0, + (oWMiniMapY + gMapData->owMinimapHeight[mapIndex]) << 2, G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10); + if (CVar_GetS32("gHudColors", 1) != 2) {//This need to be added else it will color dungeon entrance icon too. (it re-init prim color to default color) + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_MINIMAP_COLOR(0), R_MINIMAP_COLOR(1), R_MINIMAP_COLOR(2), interfaceCtx->minimapAlpha); + } + if (((globalCtx->sceneNum != SCENE_SPOT01) && (globalCtx->sceneNum != SCENE_SPOT04) && (globalCtx->sceneNum != SCENE_SPOT08)) || (LINK_AGE_IN_YEARS != YEARS_ADULT)) { s16 IconSize = 8; - s16 PosX = gMapData->owEntranceIconPosX[sEntranceIconMapIndex]; - s16 PosY = gMapData->owEntranceIconPosY[sEntranceIconMapIndex]; + s16 PosX = gMapData->owEntranceIconPosX[sEntranceIconMapIndex]+Right_MM_Margin; + s16 PosY = gMapData->owEntranceIconPosY[sEntranceIconMapIndex]+Bottom_MM_Margin; //gFixDungeonMinimapIcon fix both Y position of visible icon and hide these non needed. if (CVar_GetS32("gFixDungeonMinimapIcon", 1) != 0){ //No idea why and how Original value work but this does actually fix them all. @@ -766,14 +784,20 @@ void Minimap_Draw(GlobalContext* globalCtx) { } } + const s16 entranceX = OTRGetRectDimensionFromRightEdge(270 + Right_MM_Margin); + const s16 entranceY = 154 + Bottom_MM_Margin; if ((globalCtx->sceneNum == SCENE_SPOT08) && (gSaveContext.infTable[26] & gBitFlags[9])) { + gDPLoadTextureBlock(OVERLAY_DISP++, gMapDungeonEntranceIconTex, G_IM_FMT_RGBA, G_IM_SIZ_16b, 8, + 8, 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); + gSPWideTextureRectangle(OVERLAY_DISP++, entranceX << 2, entranceY << 2, (entranceX + 32) << 2, (entranceY + 8) << 2, + G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10); + } else if ((globalCtx->sceneNum == SCENE_SPOT08) && CVar_GetS32("gAlwaysShowDungeonMinimapIcon", 0) != 0){ gDPLoadTextureBlock(OVERLAY_DISP++, gMapDungeonEntranceIconTex, G_IM_FMT_RGBA, G_IM_SIZ_16b, 8, 8, 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); - const s16 entranceX = OTRGetRectDimensionFromRightEdge(270); - - gSPWideTextureRectangle(OVERLAY_DISP++, entranceX << 2, 154 << 2, (entranceX + 32) << 2, (154 + 8) << 2, + gSPWideTextureRectangle(OVERLAY_DISP++, entranceX << 2, entranceY << 2, (entranceX + 32) << 2, (entranceY + 8) << 2, G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10); } @@ -809,6 +833,18 @@ void Map_Update(GlobalContext* globalCtx) { s16 floor; s16 i; + if (CVar_GetS32("gHUDMargins", 0) != 0) { + Top_MM_Margin = CVar_GetS32("gHUDMargin_T", 0); + Left_MM_Margin = CVar_GetS32("gHUDMargin_L", 0); + Right_MM_Margin = CVar_GetS32("gHUDMargin_R", 0); + Bottom_MM_Margin = CVar_GetS32("gHUDMargin_B", 0); + } else { + Top_MM_Margin = 0; + Left_MM_Margin = 0; + Right_MM_Margin = 0; + Bottom_MM_Margin = 0; + } + if ((globalCtx->pauseCtx.state == 0) && (globalCtx->pauseCtx.debugState == 0)) { switch (globalCtx->sceneNum) { case SCENE_YDAN: diff --git a/soh/src/code/z_map_mark.c b/soh/src/code/z_map_mark.c index 8d43a33a0..894daeb2d 100644 --- a/soh/src/code/z_map_mark.c +++ b/soh/src/code/z_map_mark.c @@ -108,6 +108,22 @@ void MapMark_DrawForDungeon(GlobalContext* globalCtx) { gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 255, 255, 255, interfaceCtx->minimapAlpha); gDPSetEnvColor(OVERLAY_DISP++, 0, 0, 0, interfaceCtx->minimapAlpha); + s16 Top_MC_Margin = 0; + s16 Left_MC_Margin = 0; + s16 Right_MC_Margin = 0; + s16 Bottom_MC_Margin = 0; + if (CVar_GetS32("gHUDMargins", 0) != 0) { + Top_MC_Margin = CVar_GetS32("gHUDMargin_T", 0); + Left_MC_Margin = CVar_GetS32("gHUDMargin_L", 0); + Right_MC_Margin = CVar_GetS32("gHUDMargin_R", 0); + Bottom_MC_Margin = CVar_GetS32("gHUDMargin_B", 0); + } else { + Top_MC_Margin = 0; + Left_MC_Margin = 0; + Right_MC_Margin = 0; + Bottom_MC_Margin = 0; + } + markPoint = &mapMarkIconData->points[0]; for (i = 0; i < mapMarkIconData->count; i++) { if ((mapMarkIconData->markType != MAP_MARK_CHEST) || !Flags_GetTreasure(globalCtx, markPoint->chestFlag)) { @@ -118,8 +134,8 @@ void MapMark_DrawForDungeon(GlobalContext* globalCtx) { markInfo->textureWidth, markInfo->textureHeight, 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); - rectLeft = (GREG(94) + OTRGetRectDimensionFromRightEdge(markPoint->x) + 204) << 2; - rectTop = (GREG(95) + markPoint->y + 140) << 2; + rectLeft = (GREG(94) + OTRGetRectDimensionFromRightEdge(markPoint->x+Right_MC_Margin) + 204) << 2; + rectTop = (GREG(95) + markPoint->y + Bottom_MC_Margin + 140) << 2; gSPTextureRectangle(OVERLAY_DISP++, rectLeft, rectTop, markInfo->rectWidth + rectLeft, rectTop + markInfo->rectHeight, G_TX_RENDERTILE, 0, 0, markInfo->dsdx, markInfo->dtdy); diff --git a/soh/src/code/z_message_PAL.c b/soh/src/code/z_message_PAL.c index b6d6b792b..33bc9a95e 100644 --- a/soh/src/code/z_message_PAL.c +++ b/soh/src/code/z_message_PAL.c @@ -446,6 +446,46 @@ void Message_DrawTextboxIcon(GlobalContext* globalCtx, Gfx** p, s16 x, s16 y) { static s16 sIconEnvR = 0; static s16 sIconEnvG = 0; static s16 sIconEnvB = 0; + if (CVar_GetS32("gHudColors", 1) == 0) { + sIconPrimColors[0][0] = 4; + sIconPrimColors[0][1] = 84; + sIconPrimColors[0][2] = 204; + sIconPrimColors[1][0] = 45; + sIconPrimColors[1][1] = 125; + sIconPrimColors[1][2] = 255; + sIconEnvColors[0][0] = 0; + sIconEnvColors[0][1] = 0; + sIconEnvColors[0][2] = 0; + sIconEnvColors[1][0] = 0; + sIconEnvColors[1][1] = 70; + sIconEnvColors[1][2] = 255; + } else if (CVar_GetS32("gHudColors", 1) == 1) { + sIconPrimColors[0][0] = 4; + sIconPrimColors[0][1] = 200; + sIconPrimColors[0][2] = 80; + sIconPrimColors[1][0] = 50; + sIconPrimColors[1][1] = 255; + sIconPrimColors[1][2] = 130; + sIconEnvColors[0][0] = 0; + sIconEnvColors[0][1] = 0; + sIconEnvColors[0][2] = 0; + sIconEnvColors[1][0] = 0; + sIconEnvColors[1][1] = 255; + sIconEnvColors[1][2] = 130; + } else if (CVar_GetS32("gHudColors", 1) == 2) { + sIconPrimColors[0][0] = (CVar_GetS32("gCCABtnPrimR", 50)/255)*95; + sIconPrimColors[0][1] = (CVar_GetS32("gCCABtnPrimG", 255)/255)*95; + sIconPrimColors[0][2] = (CVar_GetS32("gCCABtnPrimB", 130)/255)*95; + sIconPrimColors[1][0] = CVar_GetS32("gCCABtnPrimR", 50); + sIconPrimColors[1][1] = CVar_GetS32("gCCABtnPrimG", 255); + sIconPrimColors[1][2] = CVar_GetS32("gCCABtnPrimB", 130); + sIconEnvColors[0][0] = 0; + sIconEnvColors[0][1] = 0; + sIconEnvColors[0][2] = 0; + sIconEnvColors[1][0] = 10; + sIconEnvColors[1][1] = 10; + sIconEnvColors[1][2] = 10; + } MessageContext* msgCtx = &globalCtx->msgCtx; Font* font = &msgCtx->font; Gfx* gfx = *p; @@ -2827,12 +2867,22 @@ void Message_DrawMain(GlobalContext* globalCtx, Gfx** p) { gDPPipeSync(gfx++); if (sOcarinaNoteBuf[i] == OCARINA_NOTE_A) { - gDPSetPrimColor(gfx++, 0, 0, sOcarinaNoteAPrimR, sOcarinaNoteAPrimG, sOcarinaNoteAPrimB, - sOcarinaNotesAlphaValues[i]); + if (CVar_GetS32("gHudColors", 1) == 0) { //A buttons :) + gDPSetPrimColor(gfx++, 0, 0, 80, 150, 255, sOcarinaNotesAlphaValues[i]); + } else if (CVar_GetS32("gHudColors", 1) == 1) { + gDPSetPrimColor(gfx++, 0, 0, sOcarinaNoteAPrimR, sOcarinaNoteAPrimG, sOcarinaNoteAPrimB, sOcarinaNotesAlphaValues[i]); + } else if (CVar_GetS32("gHudColors", 1) == 2) { + gDPSetPrimColor(gfx++, 0, 0, CVar_GetS32("gCCABtnPrimR", 0), CVar_GetS32("gCCABtnPrimG", 0), CVar_GetS32("gCCABtnPrimB", 0), sOcarinaNotesAlphaValues[i]); + } gDPSetEnvColor(gfx++, sOcarinaNoteAEnvR, sOcarinaNoteAEnvG, sOcarinaNoteAEnvB, 0); } else { - gDPSetPrimColor(gfx++, 0, 0, sOcarinaNoteCPrimR, sOcarinaNoteCPrimG, sOcarinaNoteCPrimB, - sOcarinaNotesAlphaValues[i]); + if (CVar_GetS32("gHudColors", 1) == 0) { //C buttons :) + gDPSetPrimColor(gfx++, 0, 0, sOcarinaNoteCPrimR, sOcarinaNoteCPrimG, sOcarinaNoteCPrimB, sOcarinaNotesAlphaValues[i]); + } else if (CVar_GetS32("gHudColors", 1) == 1) { + gDPSetPrimColor(gfx++, 0, 0, sOcarinaNoteCPrimR, sOcarinaNoteCPrimG, sOcarinaNoteCPrimB, sOcarinaNotesAlphaValues[i]); + } else if (CVar_GetS32("gHudColors", 1) == 2) { + gDPSetPrimColor(gfx++, 0, 0, CVar_GetS32("gCCCBtnPrimR", 0), CVar_GetS32("gCCCBtnPrimG", 0), CVar_GetS32("gCCCBtnPrimB", 0), sOcarinaNotesAlphaValues[i]); + } gDPSetEnvColor(gfx++, sOcarinaNoteCEnvR, sOcarinaNoteCEnvG, sOcarinaNoteCEnvB, 0); } diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index 127fb0cbb..8c901ed8a 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -15,6 +15,11 @@ #define DO_ACTION_TEX_HEIGHT 16 #define DO_ACTION_TEX_SIZE ((DO_ACTION_TEX_WIDTH * DO_ACTION_TEX_HEIGHT) / 2) // (sizeof(gCheckDoActionENGTex)) +s16 Top_HUD_Margin = 0; +s16 Left_HUD_Margin = 0; +s16 Right_HUD_Margin = 0; +s16 Bottom_HUD_Margin = 0; + typedef struct { /* 0x00 */ u8 scene; /* 0x01 */ u8 flags1; @@ -2441,6 +2446,25 @@ void Interface_UpdateMagicBar(GlobalContext* globalCtx) { { 255, 255, 150 }, { 255, 255, 50 }, }; + + if (CVar_GetS32("gHudColors", 1) == 2) { //This will make custom color based on users selected colors. + sMagicBorderColors[0][0] = CVar_GetS32("gCCMagicBorderPrimR", 255); + sMagicBorderColors[0][1] = CVar_GetS32("gCCMagicBorderPrimG", 255); + sMagicBorderColors[0][2] = CVar_GetS32("gCCMagicBorderPrimB", 255); + + sMagicBorderColors[1][0] = CVar_GetS32("gCCMagicBorderPrimR", 255)/2; + sMagicBorderColors[1][1] = CVar_GetS32("gCCMagicBorderPrimG", 255)/2; + sMagicBorderColors[1][2] = CVar_GetS32("gCCMagicBorderPrimB", 255)/2; + + sMagicBorderColors[2][0] = CVar_GetS32("gCCMagicBorderPrimR", 255)/3; + sMagicBorderColors[2][1] = CVar_GetS32("gCCMagicBorderPrimG", 255)/3; + sMagicBorderColors[2][2] = CVar_GetS32("gCCMagicBorderPrimB", 255)/3; + + sMagicBorderColors[3][0] = CVar_GetS32("gCCMagicBorderPrimR", 255)/2; + sMagicBorderColors[3][1] = CVar_GetS32("gCCMagicBorderPrimG", 255)/2; + sMagicBorderColors[3][2] = CVar_GetS32("gCCMagicBorderPrimB", 255)/2; + } + static s16 sMagicBorderIndexes[] = { 0, 1, 1, 0 }; static s16 sMagicBorderRatio = 2; static s16 sMagicBorderStep = 1; @@ -2631,27 +2655,31 @@ void Interface_DrawMagicBar(GlobalContext* globalCtx) { if (gSaveContext.magicLevel != 0) { if (gSaveContext.healthCapacity > 0xA0) { - magicBarY = R_MAGIC_BAR_LARGE_Y; + magicBarY = R_MAGIC_BAR_LARGE_Y + (Top_HUD_Margin*-1); } else { - magicBarY = R_MAGIC_BAR_SMALL_Y; + magicBarY = R_MAGIC_BAR_SMALL_Y + (Top_HUD_Margin*-1); } func_80094520(globalCtx->state.gfxCtx); gDPSetPrimColor(OVERLAY_DISP++, 0, 0, sMagicBorderR, sMagicBorderG, sMagicBorderB, interfaceCtx->magicAlpha); - gDPSetEnvColor(OVERLAY_DISP++, 100, 50, 50, 255); + if (CVar_GetS32("gHudColors", 1) == 2) {//Original game add color there so to prevent miss match we make it all white :) + gDPSetEnvColor(OVERLAY_DISP++, 0, 0, 0, 255); + } else { + gDPSetEnvColor(OVERLAY_DISP++, 100, 50, 50, 255); + } OVERLAY_DISP = - Gfx_TextureIA8(OVERLAY_DISP, gMagicBarEndTex, 8, 16, OTRGetRectDimensionFromLeftEdge(R_MAGIC_BAR_X), + Gfx_TextureIA8(OVERLAY_DISP, gMagicBarEndTex, 8, 16, OTRGetRectDimensionFromLeftEdge(R_MAGIC_BAR_X + (Left_HUD_Margin*-1)), magicBarY, 8, 16, 1 << 10, 1 << 10); - OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, gMagicBarMidTex, 24, 16, OTRGetRectDimensionFromLeftEdge(R_MAGIC_BAR_X) + 8, magicBarY, + OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, gMagicBarMidTex, 24, 16, OTRGetRectDimensionFromLeftEdge(R_MAGIC_BAR_X + (Left_HUD_Margin*-1)) + 8, magicBarY, gSaveContext.unk_13F4, 16, 1 << 10, 1 << 10); gDPLoadTextureBlock(OVERLAY_DISP++, gMagicBarEndTex, G_IM_FMT_IA, G_IM_SIZ_8b, 8, 16, 0, G_TX_MIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, 3, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); - const s16 rMagicBarX = OTRGetRectDimensionFromLeftEdge(R_MAGIC_BAR_X); + const s16 rMagicBarX = OTRGetRectDimensionFromLeftEdge(R_MAGIC_BAR_X + (Left_HUD_Margin*-1)); gSPWideTextureRectangle(OVERLAY_DISP++, ((rMagicBarX + gSaveContext.unk_13F4) + 8) << 2, magicBarY << 2, ((rMagicBarX + gSaveContext.unk_13F4) + 16) << 2, (magicBarY + 16) << 2, G_TX_RENDERTILE, @@ -2662,11 +2690,15 @@ void Interface_DrawMagicBar(GlobalContext* globalCtx) { ENVIRONMENT, TEXEL0, ENVIRONMENT, 0, 0, 0, PRIMITIVE); gDPSetEnvColor(OVERLAY_DISP++, 0, 0, 0, 255); - const s16 rMagicFillX = OTRGetRectDimensionFromLeftEdge(R_MAGIC_FILL_X); + const s16 rMagicFillX = OTRGetRectDimensionFromLeftEdge(R_MAGIC_FILL_X + (Left_HUD_Margin*-1)); if (gSaveContext.unk_13F0 == 4) { // Yellow part of the bar indicating the amount of magic to be subtracted - gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 250, 250, 0, interfaceCtx->magicAlpha); + if (CVar_GetS32("gHudColors", 1) == 2) { + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetS32("gCCMagicUsePrimR", 250), CVar_GetS32("gCCMagicUsePrimG", 250), CVar_GetS32("gCCMagicUsePrimB", 0), interfaceCtx->magicAlpha); + } else { + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 250, 250, 0, interfaceCtx->magicAlpha); + } gDPLoadMultiBlock_4b(OVERLAY_DISP++, gMagicBarFillTex, 0, G_TX_RENDERTILE, G_IM_FMT_I, 16, 16, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, @@ -2678,16 +2710,22 @@ void Interface_DrawMagicBar(GlobalContext* globalCtx) { // Fill the rest of the bar with the normal magic color gDPPipeSync(OVERLAY_DISP++); - gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_MAGIC_FILL_COLOR(0), R_MAGIC_FILL_COLOR(1), R_MAGIC_FILL_COLOR(2), - interfaceCtx->magicAlpha); + if (CVar_GetS32("gHudColors", 1) == 2) { + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetS32("gCCMagicPrimR", 0), CVar_GetS32("gCCMagicPrimG", 200), CVar_GetS32("gCCMagicPrimB", 0), interfaceCtx->magicAlpha); + } else { + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_MAGIC_FILL_COLOR(0), R_MAGIC_FILL_COLOR(1), R_MAGIC_FILL_COLOR(2), interfaceCtx->magicAlpha); + } gSPWideTextureRectangle(OVERLAY_DISP++, rMagicFillX << 2, (magicBarY + 3) << 2, (rMagicFillX + gSaveContext.unk_13F8) << 2, (magicBarY + 10) << 2, G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10); } else { // Fill the whole bar with the normal magic color - gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_MAGIC_FILL_COLOR(0), R_MAGIC_FILL_COLOR(1), R_MAGIC_FILL_COLOR(2), - interfaceCtx->magicAlpha); + if (CVar_GetS32("gHudColors", 1) == 2) { + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetS32("gCCMagicPrimR", 0), CVar_GetS32("gCCMagicPrimG", 200), CVar_GetS32("gCCMagicPrimB", 0), interfaceCtx->magicAlpha); + } else { + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_MAGIC_FILL_COLOR(0), R_MAGIC_FILL_COLOR(1), R_MAGIC_FILL_COLOR(2), interfaceCtx->magicAlpha); + } gDPLoadMultiBlock_4b(OVERLAY_DISP++, gMagicBarFillTex, 0, G_TX_RENDERTILE, G_IM_FMT_I, 16, 16, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, @@ -2761,51 +2799,83 @@ void Interface_DrawItemButtons(GlobalContext* globalCtx) { s16 width; s16 height; + s16 C_Left_BTN_Pos[] = { C_LEFT_BUTTON_X+Right_HUD_Margin, C_LEFT_BUTTON_Y+(Top_HUD_Margin*-1) }; //(X,Y) + s16 C_Right_BTN_Pos[] = { C_RIGHT_BUTTON_X+Right_HUD_Margin, C_RIGHT_BUTTON_Y+(Top_HUD_Margin*-1) }; + s16 C_Up_BTN_Pos[] = { C_UP_BUTTON_X+Right_HUD_Margin, C_UP_BUTTON_Y+(Top_HUD_Margin*-1) }; + s16 C_Down_BTN_Pos[] = { C_DOWN_BUTTON_X+Right_HUD_Margin, C_DOWN_BUTTON_Y+(Top_HUD_Margin*-1) }; + OPEN_DISPS(globalCtx->state.gfxCtx, "../z_parameter.c", 2900); // B Button Color & Texture // Also loads the Item Button Texture reused by other buttons afterwards gDPPipeSync(OVERLAY_DISP++); gDPSetCombineMode(OVERLAY_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM); - gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_B_BTN_COLOR(0), R_B_BTN_COLOR(1), R_B_BTN_COLOR(2), interfaceCtx->bAlpha); + if (CVar_GetS32("gHudColors", 1) == 0) { + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 0, 150, 0, interfaceCtx->bAlpha); + } else if (CVar_GetS32("gHudColors", 1) == 1) { + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_B_BTN_COLOR(0), R_B_BTN_COLOR(1), R_B_BTN_COLOR(2), interfaceCtx->bAlpha); + } else if (CVar_GetS32("gHudColors", 1) == 2) { + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetS32("gCCBBtnPrimR", R_B_BTN_COLOR(0)), CVar_GetS32("gCCBBtnPrimG", R_B_BTN_COLOR(1)), CVar_GetS32("gCCBBtnPrimB", R_B_BTN_COLOR(2)), interfaceCtx->bAlpha); + } gDPSetEnvColor(OVERLAY_DISP++, 0, 0, 0, 255); OVERLAY_DISP = - Gfx_TextureIA8(OVERLAY_DISP, gButtonBackgroundTex, 32, 32, OTRGetRectDimensionFromRightEdge(R_ITEM_BTN_X(0)), R_ITEM_BTN_Y(0), + Gfx_TextureIA8(OVERLAY_DISP, gButtonBackgroundTex, 32, 32, OTRGetRectDimensionFromRightEdge(R_ITEM_BTN_X(0)+Right_HUD_Margin), R_ITEM_BTN_Y(0)+(Top_HUD_Margin*-1), R_ITEM_BTN_WIDTH(0), R_ITEM_BTN_WIDTH(0), R_ITEM_BTN_DD(0) << 1, R_ITEM_BTN_DD(0) << 1); // C-Left Button Color & Texture gDPPipeSync(OVERLAY_DISP++); - gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_C_BTN_COLOR(0), R_C_BTN_COLOR(1), R_C_BTN_COLOR(2), - interfaceCtx->cLeftAlpha); - gSPWideTextureRectangle(OVERLAY_DISP++, OTRGetRectDimensionFromRightEdge(R_ITEM_BTN_X(1)) << 2, R_ITEM_BTN_Y(1) << 2, - (OTRGetRectDimensionFromRightEdge(R_ITEM_BTN_X(1)) + R_ITEM_BTN_WIDTH(1)) << 2, - (R_ITEM_BTN_Y(1) + R_ITEM_BTN_WIDTH(1)) << 2, + if (CVar_GetS32("gHudColors", 1) == 0) { + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_C_BTN_COLOR(0), R_C_BTN_COLOR(1), R_C_BTN_COLOR(2), interfaceCtx->cLeftAlpha); + } else if (CVar_GetS32("gHudColors", 1) == 1) { + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_C_BTN_COLOR(0), R_C_BTN_COLOR(1), R_C_BTN_COLOR(2), interfaceCtx->cLeftAlpha); + } else if (CVar_GetS32("gHudColors", 1) == 2) { + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetS32("gCCCBtnPrimR", R_C_BTN_COLOR(0)), CVar_GetS32("gCCCBtnPrimG", R_C_BTN_COLOR(1)), CVar_GetS32("gCCCBtnPrimB", R_C_BTN_COLOR(2)), interfaceCtx->cLeftAlpha); + } + gSPWideTextureRectangle(OVERLAY_DISP++, OTRGetRectDimensionFromRightEdge(C_Left_BTN_Pos[0]) << 2, C_Left_BTN_Pos[1] << 2, + (OTRGetRectDimensionFromRightEdge(C_Left_BTN_Pos[0]) + R_ITEM_BTN_WIDTH(1)) << 2, + (C_Left_BTN_Pos[1] + R_ITEM_BTN_WIDTH(1)) << 2, G_TX_RENDERTILE, 0, 0, R_ITEM_BTN_DD(1) << 1, R_ITEM_BTN_DD(1) << 1); // C-Down Button Color & Texture - gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_C_BTN_COLOR(0), R_C_BTN_COLOR(1), R_C_BTN_COLOR(2), - interfaceCtx->cDownAlpha); - gSPWideTextureRectangle(OVERLAY_DISP++, OTRGetRectDimensionFromRightEdge(R_ITEM_BTN_X(2)) << 2, R_ITEM_BTN_Y(2) << 2, - (OTRGetRectDimensionFromRightEdge(R_ITEM_BTN_X(2)) + R_ITEM_BTN_WIDTH(2)) << 2, - (R_ITEM_BTN_Y(2) + R_ITEM_BTN_WIDTH(2)) << 2, + if (CVar_GetS32("gHudColors", 1) == 0) { + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_C_BTN_COLOR(0), R_C_BTN_COLOR(1), R_C_BTN_COLOR(2), interfaceCtx->cDownAlpha); + } else if (CVar_GetS32("gHudColors", 1) == 1) { + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_C_BTN_COLOR(0), R_C_BTN_COLOR(1), R_C_BTN_COLOR(2), interfaceCtx->cDownAlpha); + } else if (CVar_GetS32("gHudColors", 1) == 2) { + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetS32("gCCCBtnPrimR", R_C_BTN_COLOR(0)), CVar_GetS32("gCCCBtnPrimG", R_C_BTN_COLOR(1)), CVar_GetS32("gCCCBtnPrimB", R_C_BTN_COLOR(2)), interfaceCtx->cDownAlpha); + } + gSPWideTextureRectangle(OVERLAY_DISP++, OTRGetRectDimensionFromRightEdge(C_Down_BTN_Pos[0]) << 2, C_Down_BTN_Pos[1] << 2, + (OTRGetRectDimensionFromRightEdge(C_Down_BTN_Pos[0]) + R_ITEM_BTN_WIDTH(2)) << 2, + (C_Down_BTN_Pos[1] + R_ITEM_BTN_WIDTH(2)) << 2, G_TX_RENDERTILE, 0, 0, R_ITEM_BTN_DD(2) << 1, R_ITEM_BTN_DD(2) << 1); // C-Right Button Color & Texture - gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_C_BTN_COLOR(0), R_C_BTN_COLOR(1), R_C_BTN_COLOR(2), - interfaceCtx->cRightAlpha); - gSPWideTextureRectangle(OVERLAY_DISP++, OTRGetRectDimensionFromRightEdge(R_ITEM_BTN_X(3)) << 2, R_ITEM_BTN_Y(3) << 2, - (OTRGetRectDimensionFromRightEdge(R_ITEM_BTN_X(3)) + R_ITEM_BTN_WIDTH(3)) << 2, - (R_ITEM_BTN_Y(3) + R_ITEM_BTN_WIDTH(3)) << 2, + if (CVar_GetS32("gHudColors", 1) == 0) { + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_C_BTN_COLOR(0), R_C_BTN_COLOR(1), R_C_BTN_COLOR(2), interfaceCtx->cRightAlpha); + } else if (CVar_GetS32("gHudColors", 1) == 1) { + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_C_BTN_COLOR(0), R_C_BTN_COLOR(1), R_C_BTN_COLOR(2), interfaceCtx->cRightAlpha); + } else if (CVar_GetS32("gHudColors", 1) == 2) { + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetS32("gCCCBtnPrimR", R_C_BTN_COLOR(0)), CVar_GetS32("gCCCBtnPrimG", R_C_BTN_COLOR(1)), CVar_GetS32("gCCCBtnPrimB", R_C_BTN_COLOR(2)), interfaceCtx->cRightAlpha); + } + gSPWideTextureRectangle(OVERLAY_DISP++, OTRGetRectDimensionFromRightEdge(C_Right_BTN_Pos[0]) << 2, C_Right_BTN_Pos[1] << 2, + (OTRGetRectDimensionFromRightEdge(C_Right_BTN_Pos[0]) + R_ITEM_BTN_WIDTH(3)) << 2, + (C_Right_BTN_Pos[1] + R_ITEM_BTN_WIDTH(3)) << 2, G_TX_RENDERTILE, 0, 0, R_ITEM_BTN_DD(3) << 1, R_ITEM_BTN_DD(3) << 1); if ((pauseCtx->state < 8) || (pauseCtx->state >= 18)) { if ((globalCtx->pauseCtx.state != 0) || (globalCtx->pauseCtx.debugState != 0)) { // Start Button Texture, Color & Label gDPPipeSync(OVERLAY_DISP++); - gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 120, 120, 120, interfaceCtx->startAlpha); - gSPWideTextureRectangle(OVERLAY_DISP++, OTRGetRectDimensionFromRightEdge(startButtonLeftPos[gSaveContext.language]) << 2, 68, - (OTRGetRectDimensionFromRightEdge(startButtonLeftPos[gSaveContext.language]) + 22) << 2, 156, + if (CVar_GetS32("gHudColors", 1) == 0) { + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 200, 0, 0, interfaceCtx->startAlpha); + } else if (CVar_GetS32("gHudColors", 1) == 1) { + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 120, 120, 120, interfaceCtx->startAlpha); + } else if (CVar_GetS32("gHudColors", 1) == 2) { + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetS32("gCCStartBtnPrimR", 120), CVar_GetS32("gCCStartBtnPrimG", 120), CVar_GetS32("gCCStartBtnPrimB", 120), interfaceCtx->startAlpha); + } + gSPWideTextureRectangle(OVERLAY_DISP++, OTRGetRectDimensionFromRightEdge(startButtonLeftPos[gSaveContext.language]+Right_HUD_Margin) << 2, 68+((Top_HUD_Margin*-1)*4), + (OTRGetRectDimensionFromRightEdge(startButtonLeftPos[gSaveContext.language]+Right_HUD_Margin) + 22) << 2, 156+((Top_HUD_Margin*-1)*4), G_TX_RENDERTILE, 0, 0, 1462, 1462); gDPPipeSync(OVERLAY_DISP++); gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 255, 255, 255, interfaceCtx->startAlpha); @@ -2820,11 +2890,11 @@ void Interface_DrawItemButtons(GlobalContext* globalCtx) { dxdy = (1 << 10) / (R_START_LABEL_DD(gSaveContext.language) / 100.0f); width = DO_ACTION_TEX_WIDTH / (R_START_LABEL_DD(gSaveContext.language) / 100.0f); height = DO_ACTION_TEX_HEIGHT / (R_START_LABEL_DD(gSaveContext.language) / 100.0f); - const s16 rStartLabelX = OTRGetRectDimensionFromRightEdge(R_START_LABEL_X(gSaveContext.language)); + const s16 rStartLabelX = OTRGetRectDimensionFromRightEdge(R_START_LABEL_X(gSaveContext.language)+Right_HUD_Margin); gSPWideTextureRectangle( OVERLAY_DISP++, rStartLabelX << 2, - R_START_LABEL_Y(gSaveContext.language) << 2, (rStartLabelX + width) << 2, - (R_START_LABEL_Y(gSaveContext.language) + height) << 2, G_TX_RENDERTILE, 0, 0, dxdy, dxdy); + R_START_LABEL_Y(gSaveContext.language)+(Top_HUD_Margin*-1) << 2, (rStartLabelX + width) << 2, + (R_START_LABEL_Y(gSaveContext.language)+(Top_HUD_Margin*-1) + height) << 2, G_TX_RENDERTILE, 0, 0, dxdy, dxdy); } } @@ -2843,12 +2913,18 @@ void Interface_DrawItemButtons(GlobalContext* globalCtx) { temp = interfaceCtx->healthAlpha; } - const s16 rCUpBtnX = OTRGetRectDimensionFromRightEdge(R_C_UP_BTN_X); - const s16 rCUPIconX = OTRGetRectDimensionFromRightEdge(R_C_UP_ICON_X); - gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_C_BTN_COLOR(0), R_C_BTN_COLOR(1), R_C_BTN_COLOR(2), temp); + const s16 rCUpBtnX = OTRGetRectDimensionFromRightEdge(R_C_UP_BTN_X+Right_HUD_Margin); + const s16 rCUPIconX = OTRGetRectDimensionFromRightEdge(R_C_UP_ICON_X+Right_HUD_Margin); + if (CVar_GetS32("gHudColors", 1) == 0) { + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_C_BTN_COLOR(0), R_C_BTN_COLOR(1), R_C_BTN_COLOR(2), temp); + } else if (CVar_GetS32("gHudColors", 1) == 1) { + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_C_BTN_COLOR(0), R_C_BTN_COLOR(1), R_C_BTN_COLOR(2), temp); + } else if (CVar_GetS32("gHudColors", 1) == 2) { + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetS32("gCCCBtnPrimR", R_C_BTN_COLOR(0)), CVar_GetS32("gCCCBtnPrimG", R_C_BTN_COLOR(1)), CVar_GetS32("gCCCBtnPrimB", R_C_BTN_COLOR(2)), temp); + } gDPSetCombineMode(OVERLAY_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM); - gSPWideTextureRectangle(OVERLAY_DISP++, rCUpBtnX << 2, R_C_UP_BTN_Y << 2, (rCUpBtnX + 16) << 2, - (R_C_UP_BTN_Y + 16) << 2, G_TX_RENDERTILE, 0, 0, 2 << 10, 2 << 10); + gSPWideTextureRectangle(OVERLAY_DISP++, rCUpBtnX << 2, R_C_UP_BTN_Y+(Top_HUD_Margin*-1) << 2, (rCUpBtnX + 16) << 2, + (R_C_UP_BTN_Y+(Top_HUD_Margin*-1) + 16) << 2, G_TX_RENDERTILE, 0, 0, 2 << 10, 2 << 10); gDPPipeSync(OVERLAY_DISP++); gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 255, 255, 255, temp); gDPSetEnvColor(OVERLAY_DISP++, 0, 0, 0, 0); @@ -2859,8 +2935,8 @@ void Interface_DrawItemButtons(GlobalContext* globalCtx) { G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); - gSPWideTextureRectangle(OVERLAY_DISP++, rCUPIconX << 2, R_C_UP_ICON_Y << 2, (rCUPIconX + 32) << 2, - (R_C_UP_ICON_Y + 8) << 2, G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10); + gSPWideTextureRectangle(OVERLAY_DISP++, rCUPIconX << 2, R_C_UP_ICON_Y+(Top_HUD_Margin*-1) << 2, (rCUPIconX + 32) << 2, + (R_C_UP_ICON_Y+(Top_HUD_Margin*-1) + 8) << 2, G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10); } sCUpTimer--; @@ -2886,8 +2962,13 @@ void Interface_DrawItemButtons(GlobalContext* globalCtx) { interfaceCtx->cRightAlpha); } + if (CVar_GetS32("gHudColors", 1) == 2) { + //This later will feature color per C button right now that it. + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetS32("gCCCBtnPrimR", R_C_BTN_COLOR(0)), CVar_GetS32("gCCCBtnPrimG", R_C_BTN_COLOR(1)), CVar_GetS32("gCCCBtnPrimB", R_C_BTN_COLOR(2)), interfaceCtx->cRightAlpha); + } + OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, ((u8*)gButtonBackgroundTex), 32, 32, - OTRGetRectDimensionFromRightEdge(R_ITEM_BTN_X(temp)), R_ITEM_BTN_Y(temp), R_ITEM_BTN_WIDTH(temp), + OTRGetRectDimensionFromRightEdge(R_ITEM_BTN_X(temp)+Right_HUD_Margin), R_ITEM_BTN_Y(temp)+(Top_HUD_Margin*-1), R_ITEM_BTN_WIDTH(temp), R_ITEM_BTN_WIDTH(temp), R_ITEM_BTN_DD(temp) << 1, R_ITEM_BTN_DD(temp) << 1); const char* cButtonIcons[] = { gButtonBackgroundTex, gEquippedItemOutlineTex, gEmptyCLeftArrowTex, @@ -2895,7 +2976,7 @@ void Interface_DrawItemButtons(GlobalContext* globalCtx) { }; OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, cButtonIcons[(temp + 1)], 32, 32, - OTRGetRectDimensionFromRightEdge(R_ITEM_BTN_X(temp)), R_ITEM_BTN_Y(temp), R_ITEM_BTN_WIDTH(temp), + OTRGetRectDimensionFromRightEdge(R_ITEM_BTN_X(temp)+Right_HUD_Margin), R_ITEM_BTN_Y(temp)+(Top_HUD_Margin*-1), R_ITEM_BTN_WIDTH(temp), R_ITEM_BTN_WIDTH(temp), R_ITEM_BTN_DD(temp) << 1, R_ITEM_BTN_DD(temp) << 1); } } @@ -2909,9 +2990,9 @@ void Interface_DrawItemIconTexture(GlobalContext* globalCtx, void* texture, s16 gDPLoadTextureBlock(OVERLAY_DISP++, texture, G_IM_FMT_RGBA, G_IM_SIZ_32b, 32, 32, 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); - gSPWideTextureRectangle(OVERLAY_DISP++, OTRGetRectDimensionFromRightEdge(R_ITEM_ICON_X(button)) << 2, R_ITEM_ICON_Y(button) << 2, - (OTRGetRectDimensionFromRightEdge(R_ITEM_ICON_X(button)) + R_ITEM_ICON_WIDTH(button)) << 2, - (R_ITEM_ICON_Y(button) + R_ITEM_ICON_WIDTH(button)) << 2, G_TX_RENDERTILE, 0, 0, + gSPWideTextureRectangle(OVERLAY_DISP++, OTRGetRectDimensionFromRightEdge(R_ITEM_ICON_X(button)+Right_HUD_Margin) << 2, R_ITEM_ICON_Y(button)+(Top_HUD_Margin*-1) << 2, + (OTRGetRectDimensionFromRightEdge(R_ITEM_ICON_X(button)+Right_HUD_Margin) + R_ITEM_ICON_WIDTH(button)) << 2, + (R_ITEM_ICON_Y(button)+(Top_HUD_Margin*-1) + R_ITEM_ICON_WIDTH(button)) << 2, G_TX_RENDERTILE, 0, 0, R_ITEM_ICON_DD(button) << 1, R_ITEM_ICON_DD(button) << 1); CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_parameter.c", 3094); @@ -2972,11 +3053,11 @@ void Interface_DrawAmmoCount(GlobalContext* globalCtx, s16 button, s16 alpha) { if (i != 0) { OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, (u8*)_gAmmoDigit0Tex[i], 8, 8, - OTRGetRectDimensionFromRightEdge(R_ITEM_AMMO_X(button)), R_ITEM_AMMO_Y(button), 8, 8, 1 << 10, 1 << 10); + OTRGetRectDimensionFromRightEdge(R_ITEM_AMMO_X(button)+Right_HUD_Margin), R_ITEM_AMMO_Y(button)+(Top_HUD_Margin*-1), 8, 8, 1 << 10, 1 << 10); } OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, (u8*)_gAmmoDigit0Tex[ammo], 8, 8, - OTRGetRectDimensionFromRightEdge(R_ITEM_AMMO_X(button)) + 6, R_ITEM_AMMO_Y(button), 8, 8, 1 << 10, 1 << 10); + OTRGetRectDimensionFromRightEdge(R_ITEM_AMMO_X(button)+Right_HUD_Margin) + 6, R_ITEM_AMMO_Y(button)+(Top_HUD_Margin*-1), 8, 8, 1 << 10, 1 << 10); } CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_parameter.c", 3158); @@ -3195,10 +3276,16 @@ void Interface_Draw(GlobalContext* globalCtx) { rColor = &rupeeWalletColors[0]; } - gDPSetPrimColor(OVERLAY_DISP++, 0, 0, rColor[0], rColor[1], rColor[2], interfaceCtx->magicAlpha); - gDPSetEnvColor(OVERLAY_DISP++, 0, 80, 0, 255); - OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, gRupeeCounterIconTex, 16, 16, OTRGetRectDimensionFromLeftEdge(26), - 206, 16, 16, 1 << 10, 1 << 10); + if (CVar_GetS32("gHudColors", 1) == 2) { + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetS32("gCCRupeePrimR", rColor[0]), CVar_GetS32("gCCRupeePrimG", rColor[1]), CVar_GetS32("gCCRupeePrimB", rColor[2]), interfaceCtx->magicAlpha); + gDPSetEnvColor(OVERLAY_DISP++, 0, 0, 0, 255); //We reset this here so it match user color :) + } else { + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, rColor[0], rColor[1], rColor[2], interfaceCtx->magicAlpha); + gDPSetEnvColor(OVERLAY_DISP++, 0, 80, 0, 255); + } + + OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, gRupeeCounterIconTex, 16, 16, OTRGetRectDimensionFromLeftEdge(26+(Left_HUD_Margin*-1)), + 206+(Bottom_HUD_Margin), 16, 16, 1 << 10, 1 << 10); switch (globalCtx->sceneNum) { case SCENE_BMORI1: @@ -3218,9 +3305,15 @@ void Interface_Draw(GlobalContext* globalCtx) { if (gSaveContext.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, OTRGetRectDimensionFromLeftEdge(26), 190, 16, 16, + + if (CVar_GetS32("gHudColors", 1) == 2) { + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetS32("gCCKeysPrimR", 200), CVar_GetS32("gCCKeysPrimG", 230), CVar_GetS32("gCCKeysPrimB", 255), interfaceCtx->magicAlpha); + gDPSetEnvColor(OVERLAY_DISP++, 0, 0, 0, 255); //We reset this here so it match user color :) + } else { + 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, OTRGetRectDimensionFromLeftEdge(26+(Left_HUD_Margin*-1)), 190+(Bottom_HUD_Margin), 16, 16, 1 << 10, 1 << 10); // Small Key Counter @@ -3237,17 +3330,17 @@ void Interface_Draw(GlobalContext* globalCtx) { interfaceCtx->counterDigits[3] -= 10; } - svar3 = OTRGetRectDimensionFromLeftEdge(42); + svar3 = OTRGetRectDimensionFromLeftEdge(42+(Left_HUD_Margin*-1)); if (interfaceCtx->counterDigits[2] != 0) { OVERLAY_DISP = Gfx_TextureI8(OVERLAY_DISP, ((u8*)((u8*)digitTextures[interfaceCtx->counterDigits[2]])), 8, - 16, svar3, 190, 8, 16, 1 << 10, 1 << 10); + 16, svar3, 190+(Bottom_HUD_Margin), 8, 16, 1 << 10, 1 << 10); svar3 += 8; } OVERLAY_DISP = Gfx_TextureI8(OVERLAY_DISP, ((u8*)digitTextures[interfaceCtx->counterDigits[3]]), 8, 16, - svar3, 190, 8, 16, 1 << 10, 1 << 10); + svar3, 190+(Bottom_HUD_Margin), 8, 16, 1 << 10, 1 << 10); } break; default: @@ -3291,7 +3384,7 @@ void Interface_Draw(GlobalContext* globalCtx) { for (svar1 = 0, svar3 = 42; svar1 < svar5; svar1++, svar2++, svar3 += 8) { OVERLAY_DISP = Gfx_TextureI8(OVERLAY_DISP, ((u8*)digitTextures[interfaceCtx->counterDigits[svar2]]), 8, 16, - OTRGetRectDimensionFromLeftEdge(svar3), 206, 8, 16, 1 << 10, 1 << 10); + OTRGetRectDimensionFromLeftEdge(svar3+(Left_HUD_Margin*-1)), 206+(Bottom_HUD_Margin), 8, 16, 1 << 10, 1 << 10); } } else { @@ -3353,8 +3446,8 @@ void Interface_Draw(GlobalContext* globalCtx) { G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); R_B_LABEL_DD = (1 << 10) / (WREG(37 + gSaveContext.language) / 100.0f); - const s16 rBLabelX = OTRGetRectDimensionFromRightEdge(R_B_LABEL_X(gSaveContext.language)); - gSPWideTextureRectangle(OVERLAY_DISP++, rBLabelX << 2, R_B_LABEL_Y(gSaveContext.language) << 2, + const s16 rBLabelX = OTRGetRectDimensionFromRightEdge(R_B_LABEL_X(gSaveContext.language)+Right_HUD_Margin); + gSPWideTextureRectangle(OVERLAY_DISP++, rBLabelX << 2, R_B_LABEL_Y(gSaveContext.language)+(Top_HUD_Margin*-1) << 2, (rBLabelX + DO_ACTION_TEX_WIDTH) << 2, (R_B_LABEL_Y(gSaveContext.language) + DO_ACTION_TEX_HEIGHT) << 2, G_TX_RENDERTILE, 0, 0, R_B_LABEL_DD, R_B_LABEL_DD); @@ -3401,24 +3494,29 @@ void Interface_Draw(GlobalContext* globalCtx) { // A Button func_80094A14(globalCtx->state.gfxCtx); - const f32 rABtnX = OTRGetDimensionFromRightEdge(R_A_BTN_X); + const f32 rABtnX = OTRGetDimensionFromRightEdge(R_A_BTN_X+Right_HUD_Margin); //func_8008A8B8(globalCtx, R_A_BTN_Y, R_A_BTN_Y + 45, rABtnX, rABtnX + 45); gSPClearGeometryMode(OVERLAY_DISP++, G_CULL_BOTH); gDPSetCombineMode(OVERLAY_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM); - gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_A_BTN_COLOR(0), R_A_BTN_COLOR(1), R_A_BTN_COLOR(2), - interfaceCtx->aAlpha); + if (CVar_GetS32("gHudColors", 1) == 0) { + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 90, 90, 255, interfaceCtx->aAlpha); + } else if (CVar_GetS32("gHudColors", 1) == 1) { + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_A_BTN_COLOR(0), R_A_BTN_COLOR(1), R_A_BTN_COLOR(2), interfaceCtx->aAlpha); + } else if (CVar_GetS32("gHudColors", 1) == 2) { + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetS32("gCCABtnPrimR", R_A_BTN_COLOR(0)), CVar_GetS32("gCCABtnPrimG", R_A_BTN_COLOR(1)), CVar_GetS32("gCCABtnPrimB", R_A_BTN_COLOR(2)), interfaceCtx->aAlpha); + } if (fullUi) { - Interface_DrawActionButton(globalCtx, rABtnX, R_A_BTN_Y); + Interface_DrawActionButton(globalCtx, rABtnX, R_A_BTN_Y+(Top_HUD_Margin*-1)); } gDPPipeSync(OVERLAY_DISP++); - const f32 rAIconX = OTRGetDimensionFromRightEdge(R_A_ICON_X); + const f32 rAIconX = OTRGetDimensionFromRightEdge(R_A_ICON_X+Right_HUD_Margin); //func_8008A8B8(globalCtx, R_A_ICON_Y, R_A_ICON_Y + 45, rAIconX, rAIconX + 45); gSPSetGeometryMode(OVERLAY_DISP++, G_CULL_BACK); gDPSetCombineLERP(OVERLAY_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0); gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 255, 255, 255, interfaceCtx->aAlpha); gDPSetEnvColor(OVERLAY_DISP++, 0, 0, 0, 0); - Matrix_Translate(-138.0f + rAIconX, 98.0f - R_A_ICON_Y, WREG(46 + gSaveContext.language) / 10.0f, MTXMODE_NEW); + Matrix_Translate(-138.0f + rAIconX, 98.0f - (R_A_ICON_Y+(Top_HUD_Margin*-1)), WREG(46 + gSaveContext.language) / 10.0f, MTXMODE_NEW); Matrix_Scale(1.0f, 1.0f, 1.0f, MTXMODE_APPLY); Matrix_RotateX(interfaceCtx->unk_1F4 / 10000.0f, MTXMODE_APPLY); gSPMatrix(OVERLAY_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx, "../z_parameter.c", 3701), @@ -3987,6 +4085,18 @@ void Interface_Update(GlobalContext* globalCtx) { u16 action; Input* debugInput = &globalCtx->state.input[2]; + if (CVar_GetS32("gHUDMargins", 0) != 0) { + Top_HUD_Margin = CVar_GetS32("gHUDMargin_T", 0); + Left_HUD_Margin = CVar_GetS32("gHUDMargin_L", 0); + Right_HUD_Margin = CVar_GetS32("gHUDMargin_R", 0); + Bottom_HUD_Margin = CVar_GetS32("gHUDMargin_B", 0); + } else { + Top_HUD_Margin = 0; + Left_HUD_Margin = 0; + Right_HUD_Margin = 0; + Bottom_HUD_Margin = 0; + } + if (CHECK_BTN_ALL(debugInput->press.button, BTN_DLEFT)) { gSaveContext.language = LANGUAGE_ENG; osSyncPrintf("J_N=%x J_N=%x\n", gSaveContext.language, &gSaveContext.language); diff --git a/soh/src/code/z_player_lib.c b/soh/src/code/z_player_lib.c index 4e4e1ff70..af95f26df 100644 --- a/soh/src/code/z_player_lib.c +++ b/soh/src/code/z_player_lib.c @@ -744,24 +744,25 @@ void func_8008F470(GlobalContext* globalCtx, void** skeleton, Vec3s* jointTable, #else gSPSegment(POLY_OPA_DISP++, 0x09, SEGMENTED_TO_VIRTUAL(sMouthTextures[eyeIndex])); #endif - Color_RGB8 sTemp; - color = &sTemp; - if (tunic == PLAYER_TUNIC_KOKIRI) { - color->r = CVar_GetS32("gTunic_Kokiri_Red", sTunicColors[PLAYER_TUNIC_KOKIRI].r); - color->g = CVar_GetS32("gTunic_Kokiri_Green", sTunicColors[PLAYER_TUNIC_KOKIRI].g); - color->b = CVar_GetS32("gTunic_Kokiri_Blue", sTunicColors[PLAYER_TUNIC_KOKIRI].b); - } else if (tunic == PLAYER_TUNIC_GORON) { - color->r = CVar_GetS32("gTunic_Goron_Red", sTunicColors[PLAYER_TUNIC_GORON].r); - color->g = CVar_GetS32("gTunic_Goron_Green", sTunicColors[PLAYER_TUNIC_GORON].g); - color->b = CVar_GetS32("gTunic_Goron_Blue", sTunicColors[PLAYER_TUNIC_GORON].b); - } else if (tunic == PLAYER_TUNIC_ZORA) { - color->r = CVar_GetS32("gTunic_Zora_Red", sTunicColors[PLAYER_TUNIC_ZORA].r); - color->g = CVar_GetS32("gTunic_Zora_Green", sTunicColors[PLAYER_TUNIC_ZORA].g); - color->b = CVar_GetS32("gTunic_Zora_Blue", sTunicColors[PLAYER_TUNIC_ZORA].b); - } else { - color->r = CVar_GetS32("gTunic_Kokiri_Red", sTunicColors[PLAYER_TUNIC_KOKIRI].r); - color->g = CVar_GetS32("gTunic_Kokiri_Green", sTunicColors[PLAYER_TUNIC_KOKIRI].g); - color->b = CVar_GetS32("gTunic_Kokiri_Blue", sTunicColors[PLAYER_TUNIC_KOKIRI].b); + Color_RGB8 NewColor[3]; + color = &sTunicColors[tunic]; + if (CVar_GetS32("gUseTunicsCol",0) == 1) { + if (tunic == PLAYER_TUNIC_KOKIRI || tunic == PLAYER_TUNIC_GORON || tunic == PLAYER_TUNIC_ZORA) { + NewColor[PLAYER_TUNIC_KOKIRI].r = CVar_GetS32("gTunic_Kokiri_R", sTunicColors[PLAYER_TUNIC_KOKIRI].r); + NewColor[PLAYER_TUNIC_KOKIRI].g = CVar_GetS32("gTunic_Kokiri_G", sTunicColors[PLAYER_TUNIC_KOKIRI].g); + NewColor[PLAYER_TUNIC_KOKIRI].b = CVar_GetS32("gTunic_Kokiri_B", sTunicColors[PLAYER_TUNIC_KOKIRI].b); + NewColor[PLAYER_TUNIC_GORON].r = CVar_GetS32("gTunic_Goron_R", sTunicColors[PLAYER_TUNIC_GORON].r); + NewColor[PLAYER_TUNIC_GORON].g = CVar_GetS32("gTunic_Goron_G", sTunicColors[PLAYER_TUNIC_GORON].g); + NewColor[PLAYER_TUNIC_GORON].b = CVar_GetS32("gTunic_Goron_B", sTunicColors[PLAYER_TUNIC_GORON].b); + NewColor[PLAYER_TUNIC_ZORA].r = CVar_GetS32("gTunic_Zora_R", sTunicColors[PLAYER_TUNIC_ZORA].r); + NewColor[PLAYER_TUNIC_ZORA].g = CVar_GetS32("gTunic_Zora_G", sTunicColors[PLAYER_TUNIC_ZORA].g); + NewColor[PLAYER_TUNIC_ZORA].b = CVar_GetS32("gTunic_Zora_B", sTunicColors[PLAYER_TUNIC_ZORA].b); + } else { + NewColor[PLAYER_TUNIC_KOKIRI].r = CVar_GetS32("gTunic_Kokiri_R", sTunicColors[PLAYER_TUNIC_KOKIRI].r); + NewColor[PLAYER_TUNIC_KOKIRI].g = CVar_GetS32("gTunic_Kokiri_G", sTunicColors[PLAYER_TUNIC_KOKIRI].g); + NewColor[PLAYER_TUNIC_KOKIRI].b = CVar_GetS32("gTunic_Kokiri_B", sTunicColors[PLAYER_TUNIC_KOKIRI].b); + } + color = NewColor; } gDPSetEnvColor(POLY_OPA_DISP++, color->r, color->g, color->b, 0); diff --git a/soh/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c b/soh/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c index 4d5fefec6..62704b516 100644 --- a/soh/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c +++ b/soh/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c @@ -1887,9 +1887,19 @@ void EnOssan_UpdateCursorAnim(EnOssan* this) { this->cursorAnimState = 0; } } - this->cursorColorR = ColChanMix(0, 0.0f, t); - this->cursorColorG = ColChanMix(255, 80.0f, t); - this->cursorColorB = ColChanMix(80, 0.0f, t); + if (CVar_GetS32("gHudColors", 1) == 0) { + this->cursorColorR = ColChanMix(0, 0.0f, t); + this->cursorColorG = ColChanMix(80, 80.0f, t); + this->cursorColorB = ColChanMix(255, 0.0f, t); + } else if (CVar_GetS32("gHudColors", 1) == 1) { + this->cursorColorR = ColChanMix(0, 0.0f, t); + this->cursorColorG = ColChanMix(255, 80.0f, t); + this->cursorColorB = ColChanMix(80, 0.0f, t); + } else if (CVar_GetS32("gHudColors", 1) == 2) { + this->cursorColorR = ColChanMix(CVar_GetS32("gCCABtnPrimR", 90), ((CVar_GetS32("gCCABtnPrimR", 90)/255)*100), t); + this->cursorColorG = ColChanMix(CVar_GetS32("gCCABtnPrimG", 90), ((CVar_GetS32("gCCABtnPrimG", 90)/255)*100), t); + this->cursorColorB = ColChanMix(CVar_GetS32("gCCABtnPrimB", 90), ((CVar_GetS32("gCCABtnPrimB", 90)/255)*100), t); + } this->cursorColorA = ColChanMix(255, 0.0f, t); this->cursorAnimTween = t; } diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index 733bdee2d..d6154bfde 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -10324,6 +10324,14 @@ void func_80848EF8(Player* this, GlobalContext* globalCtx) { int rectHeight = 24; //Texture Heigh int DefaultIconA= 50; //Default icon alphe (55 on 255) + if (CVar_GetS32("gHUDMargins", 0) != 0) { + rectLeft = OTRGetRectDimensionFromLeftEdge(26+(CVar_GetS32("gHUDMargin_L", 0)*-1)); + rectTop = 60+(CVar_GetS32("gHUDMargin_T", 0)*-1); + } else { + rectTop = 60; + rectLeft = OTRGetRectDimensionFromLeftEdge(26); + } + OPEN_DISPS(globalCtx->state.gfxCtx, "../z_player.c", 2824); gDPPipeSync(OVERLAY_DISP++); gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 255, 255, 255, DefaultIconA); diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_collect.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_collect.c index 80ffe8d4a..97c62c97d 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_collect.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_collect.c @@ -494,9 +494,21 @@ void KaleidoScope_DrawQuestStatus(GlobalContext* globalCtx, GraphicsContext* gfx gDPPipeSync(POLY_KAL_DISP++); if (D_8082A124[sp218] == 0) { - gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 80, 255, 150, D_8082A150[sp218]); + if (CVar_GetS32("gHudColors", 1) == 0) { // A Button notes + gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 80, 150, 255, D_8082A150[sp218]); + } else if (CVar_GetS32("gHudColors", 1) == 1) { + gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 80, 255, 150, D_8082A150[sp218]); + } else if (CVar_GetS32("gHudColors", 1) == 2) { + gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, CVar_GetS32("gCCABtnPrimR", 80), CVar_GetS32("gCCABtnPrimG", 255), CVar_GetS32("gCCABtnPrimB", 150), D_8082A150[sp218]); + } } else { - gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 255, 255, 50, D_8082A150[sp218]); + if (CVar_GetS32("gHudColors", 1) == 0) { // C Buttons notes + gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 255, 255, 50, D_8082A150[sp218]); + } else if (CVar_GetS32("gHudColors", 1) == 1) { + gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 255, 255, 50, D_8082A150[sp218]); + } else if (CVar_GetS32("gHudColors", 1) == 2) { + gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, CVar_GetS32("gCCCBtnPrimR", 255), CVar_GetS32("gCCCBtnPrimG", 255), CVar_GetS32("gCCCBtnPrimB", 50), D_8082A150[sp218]); + } } gDPSetEnvColor(POLY_KAL_DISP++, 10, 10, 10, 0); @@ -524,9 +536,21 @@ void KaleidoScope_DrawQuestStatus(GlobalContext* globalCtx, GraphicsContext* gfx if (pauseCtx->unk_1E4 == 8) { if (gOcarinaSongNotes[sp224].notesIdx[phi_s3] == 0) { - gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 80, 255, 150, 200); + if (CVar_GetS32("gHudColors", 1) == 0) { + gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 80, 150, 255, 200); + } else if (CVar_GetS32("gHudColors", 1) == 1) { + gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 80, 255, 150, 200); + } else if (CVar_GetS32("gHudColors", 1) == 2) { + gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, CVar_GetS32("gCCABtnPrimR", 80), CVar_GetS32("gCCABtnPrimG", 255), CVar_GetS32("gCCABtnPrimB", 150), 200); + } } else { - gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 255, 255, 50, 200); + if (CVar_GetS32("gHudColors", 1) == 0) { + gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 255, 255, 50, 200); + } else if (CVar_GetS32("gHudColors", 1) == 1) { + gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 255, 255, 50, 200); + } else if (CVar_GetS32("gHudColors", 1) == 2) { + gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, CVar_GetS32("gCCCBtnPrimR", 255), CVar_GetS32("gCCCBtnPrimG", 255), CVar_GetS32("gCCCBtnPrimB", 50), 200); + } } } else { gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 150, 150, 150, 150); @@ -579,9 +603,21 @@ void KaleidoScope_DrawQuestStatus(GlobalContext* globalCtx, GraphicsContext* gfx gDPPipeSync(POLY_KAL_DISP++); if (D_8082A124[phi_s3] == 0) { - gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 80, 255, 150, D_8082A150[phi_s3]); + if (CVar_GetS32("gHudColors", 1) == 0) { + gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 80, 150, 255, D_8082A150[phi_s3]); + } else if (CVar_GetS32("gHudColors", 1) == 1) { + gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 80, 255, 150, D_8082A150[phi_s3]); + } else if (CVar_GetS32("gHudColors", 1) == 2) { + gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, CVar_GetS32("gCCABtnPrimR", 80), CVar_GetS32("gCCABtnPrimG", 255), CVar_GetS32("gCCABtnPrimB", 150), D_8082A150[phi_s3]); + } } else { - gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 255, 255, 50, D_8082A150[phi_s3]); + if (CVar_GetS32("gHudColors", 1) == 0) { + gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 255, 255, 50, D_8082A150[phi_s3]); + } else if (CVar_GetS32("gHudColors", 1) == 1) { + gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 255, 255, 50, D_8082A150[phi_s3]); + } else if (CVar_GetS32("gHudColors", 1) == 2) { + gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, CVar_GetS32("gCCCBtnPrimR", 255), CVar_GetS32("gCCCBtnPrimG", 160), CVar_GetS32("gCCCBtnPrimB", 0), D_8082A150[phi_s3]); + } } gDPSetEnvColor(POLY_KAL_DISP++, 10, 10, 10, 0); diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c index c057c9876..86201719a 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c @@ -975,6 +975,20 @@ void KaleidoScope_DrawCursor(GlobalContext* globalCtx, u16 pageIndex) { temp = pauseCtx->unk_1E4; + if (CVar_GetS32("gHudColors", 1) == 0) { + sCursorColors[2][0] = 0; + sCursorColors[2][1] = 50; + sCursorColors[2][2] = 255; + } else if (CVar_GetS32("gHudColors", 1) == 1) { + sCursorColors[2][0] = 0; + sCursorColors[2][1] = 255; + sCursorColors[2][2] = 50; + } else if (CVar_GetS32("gHudColors", 1) == 2) { + sCursorColors[2][0] = CVar_GetS32("gCCABtnPrimR", 0); + sCursorColors[2][1] = CVar_GetS32("gCCABtnPrimG", 255); + sCursorColors[2][2] = CVar_GetS32("gCCABtnPrimB", 50); + } + if ((((pauseCtx->unk_1E4 == 0) || (temp == 8)) && (pauseCtx->state == 6)) || ((pauseCtx->pageIndex == PAUSE_QUEST) && ((temp < 3) || (temp == 5) || (temp == 8)))) { @@ -1045,6 +1059,28 @@ void KaleidoScope_DrawPages(GlobalContext* globalCtx, GraphicsContext* gfxCtx) { { 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, 255, 50 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 255, 50 }, }; + if (CVar_GetS32("gHudColors", 1) == 0) { + D_8082ACF4[8][0] = 0; + D_8082ACF4[8][1] = 50; + D_8082ACF4[8][2] = 255; + D_8082ACF4[11][0] = 0; + D_8082ACF4[11][1] = 50; + D_8082ACF4[11][2] = 255; + } else if (CVar_GetS32("gHudColors", 1) == 1) { + D_8082ACF4[8][0] = 0; + D_8082ACF4[8][1] = 255; + D_8082ACF4[8][2] = 50; + D_8082ACF4[11][0] = 0; + D_8082ACF4[11][1] = 255; + D_8082ACF4[11][2] = 50; + } else if (CVar_GetS32("gHudColors", 1) == 2) { + D_8082ACF4[8][0] = CVar_GetS32("gCCABtnPrimR", 0); + D_8082ACF4[8][1] = CVar_GetS32("gCCABtnPrimG", 255); + D_8082ACF4[8][2] = CVar_GetS32("gCCABtnPrimB", 50); + D_8082ACF4[11][0] = CVar_GetS32("gCCABtnPrimR", 0); + D_8082ACF4[11][1] = CVar_GetS32("gCCABtnPrimG", 255); + D_8082ACF4[11][2] = CVar_GetS32("gCCABtnPrimB", 50); + } static s16 D_8082AD3C = 20; static s16 D_8082AD40 = 0; static s16 D_8082AD44 = 0; @@ -1373,7 +1409,13 @@ void KaleidoScope_DrawPages(GlobalContext* globalCtx, GraphicsContext* gfxCtx) { gDPSetCombineLERP(POLY_KAL_DISP++, 1, 0, PRIMITIVE, 0, TEXEL0, 0, PRIMITIVE, 0, 1, 0, PRIMITIVE, 0, TEXEL0, 0, PRIMITIVE, 0); - gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 100, 255, 100, VREG(61)); + if (CVar_GetS32("gHudColors", 1) == 0) {//Save prompt cursor colour + gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 100, 100, 255, VREG(61)); + } else if (CVar_GetS32("gHudColors", 1) == 1) { + gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 100, 255, 100, VREG(61)); + } else if (CVar_GetS32("gHudColors", 1) == 2) { + gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, CVar_GetS32("gCCABtnPrimR", 100), CVar_GetS32("gCCABtnPrimG", 255), CVar_GetS32("gCCABtnPrimB", 100), VREG(61)); //Save prompt cursor colour + } if (pauseCtx->promptChoice == 0) { gSPDisplayList(POLY_KAL_DISP++, gPromptCursorLeftDL); @@ -1432,6 +1474,10 @@ void KaleidoScope_DrawPages(GlobalContext* globalCtx, GraphicsContext* gfxCtx) { } void KaleidoScope_DrawInfoPanel(GlobalContext* globalCtx) { + static s16 gABtnTexColour[][4] = { //A button colors + { 0, 255, 100, 255 },//Gamecube + { 0, 100, 255, 255 },//Original N64 + }; static void* D_8082AD54[3] = { gPauseToEquipENGTex, gPauseToEquipGERTex, @@ -1757,8 +1803,16 @@ void KaleidoScope_DrawInfoPanel(GlobalContext* globalCtx) { pauseCtx->infoPanelVtx[21].v.tc[0] = pauseCtx->infoPanelVtx[23].v.tc[0] = D_8082ADE0[gSaveContext.language] << 5; - - gSPDisplayList(POLY_KAL_DISP++, gAButtonIconDL); + if (CVar_GetS32("gHudColors", 1) == 0) {//A icon to decide in save prompt + gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, gABtnTexColour[1][0], gABtnTexColour[1][1], gABtnTexColour[1][2], gABtnTexColour[1][3]); + } else if (CVar_GetS32("gHudColors", 1) == 1) { + gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, gABtnTexColour[0][0], gABtnTexColour[0][1], gABtnTexColour[0][2], gABtnTexColour[0][3]); + } else if (CVar_GetS32("gHudColors", 1) == 2) { + gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, CVar_GetS32("gCCABtnPrimR", gABtnTexColour[0][0]), CVar_GetS32("gCCABtnPrimG", gABtnTexColour[0][1]), CVar_GetS32("gCCABtnPrimB", gABtnTexColour[0][2]), gABtnTexColour[0][3]); + } + //gSPDisplayList(POLY_KAL_DISP++, gAButtonIconDL);//This is changed to load the texture only so we can prim color it. + gDPLoadTextureBlock(POLY_KAL_DISP++, gABtnSymbolTex, G_IM_FMT_IA, G_IM_SIZ_8b, 24, 16, 0, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMIRROR | G_TX_CLAMP, 4, 4, G_TX_NOLOD, G_TX_NOLOD); + gSP1Quadrangle(POLY_KAL_DISP++, 0, 2, 3, 1, 0); gDPPipeSync(POLY_KAL_DISP++); gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 255, 255, 255, 255); @@ -1804,7 +1858,16 @@ void KaleidoScope_DrawInfoPanel(GlobalContext* globalCtx) { pauseCtx->infoPanelVtx[21].v.tc[0] = pauseCtx->infoPanelVtx[23].v.tc[0] = D_8082ADD8[gSaveContext.language] << 5; - gSPDisplayList(POLY_KAL_DISP++, gCButtonIconsDL); + if (CVar_GetS32("gHudColors", 1) == 0) {//To equip text C button icon + gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, R_C_BTN_COLOR(0), R_C_BTN_COLOR(1), R_C_BTN_COLOR(2), 255); + } else if (CVar_GetS32("gHudColors", 1) == 1) { + gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, R_C_BTN_COLOR(0), R_C_BTN_COLOR(1), R_C_BTN_COLOR(2), 255); + } else if (CVar_GetS32("gHudColors", 1) == 2) { + gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, CVar_GetS32("gCCCBtnPrimR", R_C_BTN_COLOR(0)), CVar_GetS32("gCCCBtnPrimG", R_C_BTN_COLOR(1)), CVar_GetS32("gCCCBtnPrimB", R_C_BTN_COLOR(2)), 255); + } + //gSPDisplayList(POLY_KAL_DISP++, gCButtonIconsDL); //Same reason for every A button, to be able to recolor them. + gDPLoadTextureBlock(POLY_KAL_DISP++, gCBtnSymbolsTex, G_IM_FMT_IA, G_IM_SIZ_8b, 48, 16, 0, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMIRROR | G_TX_CLAMP, 4, 4, G_TX_NOLOD, G_TX_NOLOD); + gSP1Quadrangle(POLY_KAL_DISP++, 0, 2, 3, 1, 0); gDPPipeSync(POLY_KAL_DISP++); gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 255, 255, 255, 255); @@ -1838,7 +1901,16 @@ void KaleidoScope_DrawInfoPanel(GlobalContext* globalCtx) { pauseCtx->infoPanelVtx[21].v.tc[0] = pauseCtx->infoPanelVtx[23].v.tc[0] = D_8082ADE8[gSaveContext.language] << 5; - gSPDisplayList(POLY_KAL_DISP++, gAButtonIconDL); + if (CVar_GetS32("gHudColors", 1) == 0) {//To play melody A button + gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, gABtnTexColour[1][0], gABtnTexColour[1][1], gABtnTexColour[1][2], gABtnTexColour[1][3]); + } else if (CVar_GetS32("gHudColors", 1) == 1) { + gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, gABtnTexColour[0][0], gABtnTexColour[0][1], gABtnTexColour[0][2], gABtnTexColour[0][3]); + } else if (CVar_GetS32("gHudColors", 1) == 2) { + gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, CVar_GetS32("gCCABtnPrimR", gABtnTexColour[0][0]), CVar_GetS32("gCCABtnPrimG", gABtnTexColour[0][1]), CVar_GetS32("gCCABtnPrimB", gABtnTexColour[0][2]), gABtnTexColour[0][3]); + } + //gSPDisplayList(POLY_KAL_DISP++, gAButtonIconDL); + gDPLoadTextureBlock(POLY_KAL_DISP++, gABtnSymbolTex, G_IM_FMT_IA, G_IM_SIZ_8b, 24, 16, 0, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMIRROR | G_TX_CLAMP, 4, 4, G_TX_NOLOD, G_TX_NOLOD); + gSP1Quadrangle(POLY_KAL_DISP++, 0, 2, 3, 1, 0); gDPPipeSync(POLY_KAL_DISP++); gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 255, 255, 255, 255); @@ -1864,7 +1936,16 @@ void KaleidoScope_DrawInfoPanel(GlobalContext* globalCtx) { pauseCtx->infoPanelVtx[21].v.tc[0] = pauseCtx->infoPanelVtx[23].v.tc[0] = D_8082ADD8[gSaveContext.language] << 5; - gSPDisplayList(POLY_KAL_DISP++, gAButtonIconDL); + //gSPDisplayList(POLY_KAL_DISP++, gAButtonIconDL); + if (CVar_GetS32("gHudColors", 1) == 0) {//To equip A button + gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, gABtnTexColour[1][0], gABtnTexColour[1][1], gABtnTexColour[1][2], gABtnTexColour[1][3]); + } else if (CVar_GetS32("gHudColors", 1) == 1) { + gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, gABtnTexColour[0][0], gABtnTexColour[0][1], gABtnTexColour[0][2], gABtnTexColour[0][3]); + } else if (CVar_GetS32("gHudColors", 1) == 2) { + gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, CVar_GetS32("gCCABtnPrimR", gABtnTexColour[0][0]), CVar_GetS32("gCCABtnPrimG", gABtnTexColour[0][1]), CVar_GetS32("gCCABtnPrimB", gABtnTexColour[0][2]), gABtnTexColour[0][3]); + } + gDPLoadTextureBlock(POLY_KAL_DISP++, gABtnSymbolTex, G_IM_FMT_IA, G_IM_SIZ_8b, 24, 16, 0, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMIRROR | G_TX_CLAMP, 4, 4, G_TX_NOLOD, G_TX_NOLOD); + gSP1Quadrangle(POLY_KAL_DISP++, 0, 2, 3, 1, 0); gDPPipeSync(POLY_KAL_DISP++); gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 255, 255, 255, 255); From 0b2c264a6093cd5af0390d8b475da20e393fa502 Mon Sep 17 00:00:00 2001 From: iheemskerk Date: Sat, 21 May 2022 13:16:48 -0400 Subject: [PATCH 13/30] Add toggle to disable navi call voice audio (#336) Co-authored-by: genegrey --- libultraship/libultraship/SohImGuiImpl.cpp | 4 +++- soh/src/code/z_parameter.c | 14 ++++++++------ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/libultraship/libultraship/SohImGuiImpl.cpp b/libultraship/libultraship/SohImGuiImpl.cpp index 530c3707d..f80ad4e0a 100644 --- a/libultraship/libultraship/SohImGuiImpl.cpp +++ b/libultraship/libultraship/SohImGuiImpl.cpp @@ -721,7 +721,9 @@ namespace SohImGui { Tooltip("Allows equiping the tunic and boots to c-buttons"); EnhancementCheckbox("MM Bunny Hood", "gMMBunnyHood"); Tooltip("Wearing the Bunny Hood grants a speed increase like in Majora's Mask"); - + EnhancementCheckbox("Disable Navi Call Audio", "gDisableNaviCallAudio"); + Tooltip("Disables the voice audio when Navi calls you"); + ImGui::EndMenu(); } diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index 8c901ed8a..dcfcdb05b 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -2164,13 +2164,15 @@ void Interface_SetNaviCall(GlobalContext* globalCtx, u16 naviCallState) { if (((naviCallState == 0x1D) || (naviCallState == 0x1E)) && !interfaceCtx->naviCalling && (globalCtx->csCtx.state == CS_STATE_IDLE)) { - // clang-format off - if (naviCallState == 0x1E) { Audio_PlaySoundGeneral(NA_SE_VO_NAVY_CALL, &D_801333D4, 4, - &D_801333E0, &D_801333E0, &D_801333E8); } - // clang-format on + if (!CVar_GetS32("gDisableNaviCallAudio", 0)) { + // clang-format off + if (naviCallState == 0x1E) { Audio_PlaySoundGeneral(NA_SE_VO_NAVY_CALL, &D_801333D4, 4, + &D_801333E0, &D_801333E0, &D_801333E8); } + // clang-format on - if (naviCallState == 0x1D) { - func_800F4524(&D_801333D4, NA_SE_VO_NA_HELLO_2, 32); + if (naviCallState == 0x1D) { + func_800F4524(&D_801333D4, NA_SE_VO_NA_HELLO_2, 32); + } } interfaceCtx->naviCalling = 1; From 2192ae0a252ae158f7a7fb5e8739374bbbda4ea4 Mon Sep 17 00:00:00 2001 From: Ada <60364512+GreatArgorath@users.noreply.github.com> Date: Sat, 21 May 2022 18:21:14 +0100 Subject: [PATCH 14/30] Adds notification telling people how to activate menubar (#351) * Adds notification telling people how to activate menubar * Makes it longer and only show when menu bar isn't active --- libultraship/libultraship/SohImGuiImpl.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libultraship/libultraship/SohImGuiImpl.cpp b/libultraship/libultraship/SohImGuiImpl.cpp index f80ad4e0a..dd345124b 100644 --- a/libultraship/libultraship/SohImGuiImpl.cpp +++ b/libultraship/libultraship/SohImGuiImpl.cpp @@ -371,6 +371,9 @@ namespace SohImGui { io = &ImGui::GetIO(); io->ConfigFlags |= ImGuiConfigFlags_DockingEnable; io->Fonts->AddFontDefault(); + if (CVar_GetS32("gOpenMenuBar", 0) != 1) { + SohImGui::overlay->TextDrawNotification(30.0f, true, "Press F1 to access enhancements menu"); + } if (UseViewports()) { io->ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; From b359d642f481e45c103709e26b31d0209e5daaf9 Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Sat, 21 May 2022 13:21:36 -0400 Subject: [PATCH 15/30] Fix nightly build link formatting (#345) Not sure if "here" is good text for the link, but that can be easily changed before merging --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 92fca0615..c99f8f4d0 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,7 @@ Refer to the [building instructions](BUILDING.md) to compile SoH. - Affirm that `zapd.exe` exists in the `/assets/extractor` folder ## Nightly Builds -Nightly builds of Ship of Harkinian are available at [https://builds.shipofharkinian.com/job/SoH_Multibranch/job/develop] +Nightly builds of Ship of Harkinian are available [here](https://builds.shipofharkinian.com/job/SoH_Multibranch/job/develop) ## The Harbour Masters Are... @@ -111,4 +111,4 @@ Nightly builds of Ship of Harkinian are available at [https://builds.shipofharki Amphibibro | Link AceHeart | Zelda -###### Lemons \ No newline at end of file +###### Lemons From e56af6a7a3e9d10b3c55296e6983d53ad536f71e Mon Sep 17 00:00:00 2001 From: Emill Date: Sat, 21 May 2022 19:22:25 +0200 Subject: [PATCH 16/30] Redesign hooks mechanism (#352) * Redesign hooks mechanism * Use reference instead of copy --- libultraship/libultraship/GameSettings.cpp | 8 +- .../libultraship/Lib/Fast3D/gfx_pc.cpp | 4 +- libultraship/libultraship/SohHooks.cpp | 119 +----------------- libultraship/libultraship/SohHooks.h | 104 ++++++--------- libultraship/libultraship/SohImGuiImpl.cpp | 11 +- libultraship/libultraship/TextureMod.cpp | 6 +- libultraship/libultraship/TextureMod.h | 6 +- libultraship/libultraship/Window.cpp | 20 +-- soh/src/code/audioMgr.c | 4 +- .../ovl_kaleido_scope/z_kaleido_scope_PAL.c | 8 -- 10 files changed, 62 insertions(+), 228 deletions(-) diff --git a/libultraship/libultraship/GameSettings.cpp b/libultraship/libultraship/GameSettings.cpp index 0cd9aa2f4..51c7034c8 100644 --- a/libultraship/libultraship/GameSettings.cpp +++ b/libultraship/libultraship/GameSettings.cpp @@ -54,14 +54,12 @@ namespace Game { } void InitSettings() { - ModInternal::registerHookListener({ AUDIO_INIT, [](HookEvent ev) { - UpdateAudio(); - }}); - ModInternal::registerHookListener({ GFX_INIT, [](HookEvent ev) { + ModInternal::RegisterHook(UpdateAudio); + ModInternal::RegisterHook([] { gfx_get_current_rendering_api()->set_texture_filter((FilteringMode) CVar_GetS32("gTextureFilter", THREE_POINT)); SohImGui::console->opened = CVar_GetS32("gConsoleEnabled", 0); UpdateAudio(); - }}); + }); } void SetSeqPlayerVolume(SeqPlayers playerId, float volume) { diff --git a/libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp b/libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp index 6738f28fa..98bab7f78 100644 --- a/libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp +++ b/libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp @@ -2710,9 +2710,7 @@ void gfx_init(struct GfxWindowManagerAPI *wapi, struct GfxRenderingAPI *rapi, co //gfx_lookup_or_create_shader_program(precomp_shaders[i]); } - ModInternal::bindHook(GFX_INIT); - ModInternal::initBindHook(0); - ModInternal::callBindHook(0); + ModInternal::ExecuteHooks(); } struct GfxRenderingAPI *gfx_get_current_rendering_api(void) { diff --git a/libultraship/libultraship/SohHooks.cpp b/libultraship/libultraship/SohHooks.cpp index 7ede525d7..c11745e84 100644 --- a/libultraship/libultraship/SohHooks.cpp +++ b/libultraship/libultraship/SohHooks.cpp @@ -5,121 +5,6 @@ #include #include -std::map> listeners; -std::string hookName; -std::map initArgs; -std::map hookArgs; - -/* -############################# - Module: Hook C++ Handle -############################# -*/ - -namespace ModInternal { - - void registerHookListener(HookListener listener) { - listeners[listener.hookName].push_back(listener.callback); - } - - bool handleHook(std::shared_ptr call) { - std::string hookName = std::string(call->name); - for (size_t l = 0; l < listeners[hookName].size(); l++) { - (listeners[hookName][l])(call); - } - return call->cancelled; - } - - void bindHook(std::string name) { - hookName = name; - } - - void initBindHook(int length, ...) { - if (length > 0) { - va_list args; - va_start(args, length); - for (int i = 0; i < length; i++) { - HookParameter currentParam = va_arg(args, struct HookParameter); - initArgs[currentParam.name] = currentParam.parameter; - } - va_end(args); - } - } - - bool callBindHook(int length, ...) { - if (length > 0) { - va_list args; - va_start(args, length); - for (int i = 0; i < length; i++) { - HookParameter currentParam = va_arg(args, struct HookParameter); - hookArgs[currentParam.name] = currentParam.parameter; - } - va_end(args); - } - - HookCall call = { - .name = hookName, - .baseArgs = initArgs, - .hookedArgs = hookArgs - }; - const bool cancelled = handleHook(std::make_shared(call)); - - hookName = ""; - initArgs.clear(); - hookArgs.clear(); - - return cancelled; - } +void ModInternal_ExecuteAudioInitHooks() { + ModInternal::ExecuteHooks(); } - -/* -############################# - Module: Hook C Handle -############################# -*/ - -extern "C" { - - void bind_hook(char* name) { - hookName = std::string(name); - } - - void init_hook(int length, ...) { - if (length > 0) { - va_list args; - va_start(args, length); - for (int i = 0; i < length; i++) { - HookParameter currentParam = va_arg(args, struct HookParameter); - initArgs[currentParam.name] = currentParam.parameter; - } - va_end(args); - } - } - - bool call_hook(int length, ...) { - if (length > 0) { - va_list args; - va_start(args, length); - for (int i = 0; i < length; i++) { - HookParameter currentParam = va_arg(args, struct HookParameter); - hookArgs[currentParam.name] = currentParam.parameter; - } - va_end(args); - } - - HookCall call = { - .name = hookName, - .baseArgs = initArgs, - .hookedArgs = hookArgs - }; - - const bool cancelled = ModInternal::handleHook(std::make_shared(call)); - - hookName = ""; - initArgs.clear(); - hookArgs.clear(); - - return cancelled; - } - -} \ No newline at end of file diff --git a/libultraship/libultraship/SohHooks.h b/libultraship/libultraship/SohHooks.h index 9a41eeb0e..b5dec8159 100644 --- a/libultraship/libultraship/SohHooks.h +++ b/libultraship/libultraship/SohHooks.h @@ -1,80 +1,50 @@ #pragma once -struct HookParameter { - const char* name; - void* parameter; -}; - -#define LOOKUP_TEXTURE "F3D::LookupCacheTexture" -#define GRAYOUT_TEXTURE "Kaleido::GrayOutTexture" -#define INVALIDATE_TEXTURE "GBI::gSPInvalidateTexCache" -#define CONTROLLER_READ "N64::ControllerRead" - -#define AUDIO_INIT "AudioMgr::Init" - -#define LOAD_TEXTURE "ResourceMgr::LoadTexByName" - -#define UPDATE_VOLUME "AudioVolume::Bind" - -#define IMGUI_API_INIT "ImGuiApiInit" -#define IMGUI_API_DRAW "ImGuiApiDraw" - -#define WINDOW_API_INIT "WApiInit" -#define WINDOW_API_HANDLE_EVENTS "WApiHandleEvents" -#define WINDOW_API_START_FRAME "WApiStartFrame" - -// Graphics API Hooks -#define GFX_PRE_START_FRAME "GFXApiPreStartFrame" -#define GFX_POST_START_FRAME "GFXApiPostStartFrame" - -#define GFX_PRE_END_FRAME "GFXApiPreEndFrame" -#define GFX_POST_END_FRAME "GFXApiPostEndFrame" - -#define GFX_ON_REZISE "GFXApiOnResize" -#define GFX_INIT "GFXApiInit" -#define GFX_SHUTDOWN "GFXApiShutdown" - -// End - #ifdef __cplusplus -#define HOOK_PARAMETER(name, ptr) HookParameter({ name, static_cast(ptr) }) -#define BIND_HOOK(name, func) ModInternal::registerHookListener({ name, [this](HookEvent call) { func(call); }}) -#define BIND_PTR(name, type) static_cast(call->baseArgs[name]) -#define BIND_VAR(name, type) *BIND_PTR(name, type) - - #include -#include -#include -#include -struct HookCall { - std::string name; - std::map baseArgs; - std::map hookedArgs; - bool cancelled = false; -}; +#include "UltraController.h" -typedef std::shared_ptr HookEvent; -typedef std::function HookFunc; -struct HookListener { - std::string hookName; - HookFunc callback; - int priority = 0; -}; +#define DEFINE_HOOK(name, type) struct name { typedef std::function fn; } namespace ModInternal { - void registerHookListener(HookListener listener); - void bindHook(std::string name); - void initBindHook(int length, ...); - bool callBindHook(int length, ...); + + template + struct RegisteredHooks { + inline static std::vector functions; + }; + + template + void RegisterHook(typename H::fn h) { + RegisteredHooks::functions.push_back(h); + } + + template + void ExecuteHooks(Args&&... args) { + for (auto& fn : RegisteredHooks::functions) { + fn(std::forward(args)...); + } + } + + DEFINE_HOOK(ControllerRead, void(OSContPad* cont_pad)); + + DEFINE_HOOK(AudioInit, void()); + + DEFINE_HOOK(LoadTexture, void(const char* path, uint8_t** texture)); + + DEFINE_HOOK(GfxInit, void()); + } -#else +#endif -void bind_hook(char* name); -void init_hook(int length, ...); -bool call_hook(int length, ...); +#ifdef __cplusplus +extern "C" { +#endif -#endif \ No newline at end of file +void ModInternal_ExecuteAudioInitHooks(); + +#ifdef __cplusplus +} +#endif diff --git a/libultraship/libultraship/SohImGuiImpl.cpp b/libultraship/libultraship/SohImGuiImpl.cpp index dd345124b..ab967cbca 100644 --- a/libultraship/libultraship/SohImGuiImpl.cpp +++ b/libultraship/libultraship/SohImGuiImpl.cpp @@ -383,8 +383,7 @@ namespace SohImGui { ImGuiWMInit(); ImGuiBackendInit(); - ModInternal::registerHookListener({ GFX_INIT, [](const HookEvent ev) { - + ModInternal::RegisterHook([] { if (GlobalCtx2::GetInstance()->GetWindow()->IsFullscreen()) ShowCursor(CVar_GetS32("gOpenMenuBar", 0), Dialogues::dLoadSettings); @@ -399,7 +398,7 @@ namespace SohImGui { LoadTexture("C-Right", "assets/ship_of_harkinian/buttons/CRight.png"); LoadTexture("C-Up", "assets/ship_of_harkinian/buttons/CUp.png"); LoadTexture("C-Down", "assets/ship_of_harkinian/buttons/CDown.png"); - } }); + }); for (const auto& [i, controllers] : Ship::Window::Controllers) { @@ -408,9 +407,9 @@ namespace SohImGui { needs_save = true; } - ModInternal::registerHookListener({ CONTROLLER_READ, [](const HookEvent ev) { - pads = static_cast(ev->baseArgs["cont_pad"]); - } }); + ModInternal::RegisterHook([](OSContPad* cont_pad) { + pads = cont_pad; + }); Game::InitSettings(); } diff --git a/libultraship/libultraship/TextureMod.cpp b/libultraship/libultraship/TextureMod.cpp index b44987a62..87f17ed2c 100644 --- a/libultraship/libultraship/TextureMod.cpp +++ b/libultraship/libultraship/TextureMod.cpp @@ -1,5 +1,7 @@ #include "TextureMod.h" +#if 0 + #include #include #include @@ -121,4 +123,6 @@ namespace Ship { TexturePool.clear(); LoadedOTRS.clear(); } -} \ No newline at end of file +} + +#endif diff --git a/libultraship/libultraship/TextureMod.h b/libultraship/libultraship/TextureMod.h index 8dac99387..5f41873ca 100644 --- a/libultraship/libultraship/TextureMod.h +++ b/libultraship/libultraship/TextureMod.h @@ -3,6 +3,8 @@ #include #include "Lib/Fast3D/gfx_pc.h" +#if 0 + namespace Ship { enum TextureMod { GRAYSCALE, @@ -48,4 +50,6 @@ namespace Ship { data[x + 2] = gray; } } -} \ No newline at end of file +} + +#endif diff --git a/libultraship/libultraship/Window.cpp b/libultraship/libultraship/Window.cpp index bbd906c76..5c2cf3cae 100644 --- a/libultraship/libultraship/Window.cpp +++ b/libultraship/libultraship/Window.cpp @@ -112,11 +112,7 @@ extern "C" { } } - ModInternal::bindHook(CONTROLLER_READ); - ModInternal::initBindHook(1, - HookParameter({ .name = "cont_pad", .parameter = (void*)pad }) - ); - ModInternal::callBindHook(0); + ModInternal::ExecuteHooks(pad); } const char* ResourceMgr_GetNameByCRC(uint64_t crc) { @@ -168,12 +164,7 @@ extern "C" { if (hashStr != nullptr) { const auto res = static_cast(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr->c_str()).get()); - ModInternal::bindHook(LOAD_TEXTURE); - ModInternal::initBindHook(2, - HookParameter({.name = "path", .parameter = (void*)hashStr->c_str() }), - HookParameter({.name = "texture", .parameter = static_cast(&res->imageData) }) - ); - ModInternal::callBindHook(0); + ModInternal::ExecuteHooks(hashStr->c_str(), &res->imageData); return reinterpret_cast(res->imageData); } else { @@ -200,12 +191,7 @@ extern "C" { char* ResourceMgr_LoadTexByName(char* texPath) { const auto res = static_cast(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(texPath).get()); - ModInternal::bindHook(LOAD_TEXTURE); - ModInternal::initBindHook(2, - HookParameter({ .name = "path", .parameter = (void*)texPath }), - HookParameter({ .name = "texture", .parameter = static_cast(&res->imageData) }) - ); - ModInternal::callBindHook(0); + ModInternal::ExecuteHooks(texPath, &res->imageData); return (char*)res->imageData; } diff --git a/soh/src/code/audioMgr.c b/soh/src/code/audioMgr.c index 5b46ad8eb..e8c7be032 100644 --- a/soh/src/code/audioMgr.c +++ b/soh/src/code/audioMgr.c @@ -108,9 +108,7 @@ void AudioMgr_Init(AudioMgr* audioMgr, void* stack, OSPri pri, OSId id, SchedCon AudioLoad_SetDmaHandler(DmaMgr_DmaHandler); Audio_InitSound(); osSendMesg(&audioMgr->unk_C8, NULL, OS_MESG_BLOCK); - bind_hook(AUDIO_INIT); - init_hook(0); - call_hook(0); + ModInternal_ExecuteAudioInitHooks(); // Removed due to crash //IrqMgr_AddClient(audioMgr->irqMgr, &irqClient, &audioMgr->unk_74); hasInitialized = true; diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c index 86201719a..d9f038059 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c @@ -2948,14 +2948,6 @@ void KaleidoScope_GrayOutTextureRGBA32(u32* texture, u16 pixelCount) { u16 gray; u16 i; - bind_hook( GRAYOUT_TEXTURE); - init_hook(2, - (struct HookParameter){ .name = "texture", .parameter = &texture }, - (struct HookParameter){ .name = "pixelCount", .parameter = &pixelCount } - ); - if (!call_hook(0)) - return; - texture = ResourceMgr_LoadTexByName(texture); for (i = 0; i < pixelCount; i++) { From 0ce37a4126d2cb5cd32808dd322d5a44913809de Mon Sep 17 00:00:00 2001 From: mightypanders Date: Sat, 21 May 2022 19:22:56 +0200 Subject: [PATCH 17/30] Clarify recommended ROM Option in README.md (#321) * Update README.md with ROM recommendation * Clarify recommendation wording in README.md * Revert auto formatting --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c99f8f4d0..d31123105 100644 --- a/README.md +++ b/README.md @@ -12,13 +12,15 @@ The Ship does not include assets and as such requires a prior copy of the game t 4) Launch `soh.exe` ### Supported Games -Ocarina of Time Debug (not Master Quest) +#### Ocarina of Time Debug (not Master Quest) +> Currently the recommended option ``` Build team: `zelda@srd022j` Build date: `03-02-21 00:49:18` (year-month-day) sha1: cee6bc3c2a634b41728f2af8da54d9bf8cc14099 ``` -Ocarina of Time PAL GameCube +#### Ocarina of Time PAL GameCube +> May lead to crashes and instability ``` sha1: 0227d7c0074f2d0ac935631990da8ec5914597b4 ``` From d1357b902d6a9a1038e6e4b572ed0824a93592f4 Mon Sep 17 00:00:00 2001 From: Baoulettes Date: Sat, 21 May 2022 19:32:21 +0200 Subject: [PATCH 18/30] DEV Tool : Fast Save Loading (#369) * Add the whole loading system there * Add Cvar checkbox * Add support for ID:0 = FileSelect * Add 0 in range for slider. --- libultraship/libultraship/SohImGuiImpl.cpp | 7 +- .../overlays/gamestates/ovl_title/z_title.c | 66 +++++++++++++++++++ 2 files changed, 72 insertions(+), 1 deletion(-) diff --git a/libultraship/libultraship/SohImGuiImpl.cpp b/libultraship/libultraship/SohImGuiImpl.cpp index ab967cbca..5ea017173 100644 --- a/libultraship/libultraship/SohImGuiImpl.cpp +++ b/libultraship/libultraship/SohImGuiImpl.cpp @@ -817,7 +817,12 @@ namespace SohImGui { { EnhancementCheckbox("OoT Debug Mode", "gDebugEnabled"); Tooltip("Enables Debug Mode, allowing you to select maps with L + R + Z, noclip with L + D-pad Right,\nand open the debug menu with L on the pause screen"); - ImGui::Separator(); + EnhancementCheckbox("Fast File Select", "gSkipLogoTitle"); + Tooltip("Directly load the game to selected slot bellow\nUse slot number 4 to load directly in Zelda Map Select\n(Do not require debug menu but you will be unable to save there)\n(you can also load Zelda map select with Debug mod + slot 0).\nWith Slot : 0 you can go directly in File Select menu\nAttention, Loading an empty save will result in crash"); + if (CVar_GetS32("gSkipLogoTitle",0)) { + EnhancementSliderInt("Loading %d", "##SaveFileID", "gSaveFileID", 0, 4, ""); + } + ImGui::Separator(); EnhancementCheckbox("Stats", "gStatsEnabled"); Tooltip("Shows the stats window, with your FPS and frametimes, and the OS you're playing on"); EnhancementCheckbox("Console", "gConsoleEnabled"); diff --git a/soh/src/overlays/gamestates/ovl_title/z_title.c b/soh/src/overlays/gamestates/ovl_title/z_title.c index 18996f15e..c2657f345 100644 --- a/soh/src/overlays/gamestates/ovl_title/z_title.c +++ b/soh/src/overlays/gamestates/ovl_title/z_title.c @@ -222,6 +222,72 @@ void Title_Draw(TitleContext* this) { void Title_Main(GameState* thisx) { TitleContext* this = (TitleContext*)thisx; + if (CVar_GetS32("gSkipLogoTitle",0)!=0) { + gSaveContext.language = CVar_GetS32("gLanguages", 0); + Sram_InitSram(&this->state, &this->sramCtx); + s16 selectedfile = CVar_GetS32("gSaveFileID", 0); + if (selectedfile == 4) { + selectedfile = 0xFF; + } else if(selectedfile == 0){ + gSaveContext.fileNum = selectedfile; + gSaveContext.gameMode = 0; + this->state.running = false; + SET_NEXT_GAMESTATE(&this->state, FileChoose_Init, SelectContext); + return; + } else { + selectedfile--; + if (selectedfile < 0) { + selectedfile = 0xFF; + } + } + if (selectedfile == 0xFF) { + gSaveContext.fileNum = selectedfile; + Sram_OpenSave(&this->sramCtx); + gSaveContext.gameMode = 0; + this->state.running = false; + SET_NEXT_GAMESTATE(&this->state, Select_Init, SelectContext); + } else { + gSaveContext.fileNum = selectedfile; + Sram_OpenSave(&this->sramCtx); + gSaveContext.gameMode = 0; + this->state.running = false; + //return; + SET_NEXT_GAMESTATE(&this->state, Gameplay_Init, GlobalContext); + } + gSaveContext.respawn[0].entranceIndex = -1; + gSaveContext.respawnFlag = 0; + gSaveContext.seqId = (u8)NA_BGM_DISABLED; + gSaveContext.natureAmbienceId = 0xFF; + gSaveContext.showTitleCard = true; + gSaveContext.dogParams = 0; + gSaveContext.timer1State = 0; + gSaveContext.timer2State = 0; + gSaveContext.eventInf[0] = 0; + gSaveContext.eventInf[1] = 0; + gSaveContext.eventInf[2] = 0; + gSaveContext.eventInf[3] = 0; + gSaveContext.unk_13EE = 0x32; + gSaveContext.nayrusLoveTimer = 0; + gSaveContext.healthAccumulator = 0; + gSaveContext.unk_13F0 = 0; + gSaveContext.unk_13F2 = 0; + gSaveContext.forcedSeqId = NA_BGM_GENERAL_SFX; + gSaveContext.skyboxTime = 0; + gSaveContext.nextTransition = 0xFF; + gSaveContext.nextCutsceneIndex = 0xFFEF; + gSaveContext.cutsceneTrigger = 0; + gSaveContext.chamberCutsceneNum = 0; + gSaveContext.nextDayTime = 0xFFFF; + gSaveContext.unk_13C3 = 0; + gSaveContext.buttonStatus[0] = gSaveContext.buttonStatus[1] = gSaveContext.buttonStatus[2] = gSaveContext.buttonStatus[3] = gSaveContext.buttonStatus[4] = BTN_ENABLED; + gSaveContext.unk_13E7 = gSaveContext.unk_13E8 = gSaveContext.unk_13EA = gSaveContext.unk_13EC = gSaveContext.unk_13F4 = 0; + gSaveContext.unk_13F6 = gSaveContext.magic; + gSaveContext.magic = 0; + gSaveContext.magicLevel = gSaveContext.magic; + gSaveContext.naviTimer = 0; + return; + } + OPEN_DISPS(this->state.gfxCtx, "../z_title.c", 494); gSPSegment(POLY_OPA_DISP++, 0, NULL); From 40f13ff2e6467e9c2e5d802d8b91e88cb9dbdadd Mon Sep 17 00:00:00 2001 From: GreenSwede <42186507+GreenSwede@users.noreply.github.com> Date: Sat, 21 May 2022 19:37:46 +0200 Subject: [PATCH 19/30] Update BUILDING.md (#364) Add -O2 flag to text instructions since it was fixed in #342 commit db2fa61 --- BUILDING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/BUILDING.md b/BUILDING.md index 726b8a99c..0a444ca4a 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -41,9 +41,9 @@ cp /usr/local/lib/libGLEW.a external cd soh # Extract the assets/Compile the exporter/Run the exporter -make setup -j$(nproc) OPTFLAGS=-O0 DEBUG=0 +make setup -j$(nproc) OPTFLAGS=-O2 DEBUG=0 # Compile the code -make -j $(nproc) OPTFLAGS=-O0 DEBUG=0 +make -j $(nproc) OPTFLAGS=-O2 DEBUG=0 ``` # Compatible Roms From 78b3c1ae47b3177072fbd1f728a301494ba8396b Mon Sep 17 00:00:00 2001 From: Baoulettes Date: Sun, 29 May 2022 17:43:58 +0200 Subject: [PATCH 20/30] Return button translation for GER/FRA (#287) --- soh/src/code/z_parameter.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index dcfcdb05b..a9e9e4f9e 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -2884,7 +2884,26 @@ void Interface_DrawItemButtons(GlobalContext* globalCtx) { gDPSetEnvColor(OVERLAY_DISP++, 0, 0, 0, 0); gDPSetCombineLERP(OVERLAY_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0); - + + //There is probably a more elegant way to do it. + char* doAction = actionsTbl[3]; + char newName[512]; + if (gSaveContext.language != LANGUAGE_ENG) { + size_t length = strlen(doAction); + strcpy(newName, doAction); + if (gSaveContext.language == LANGUAGE_FRA) { + newName[length - 6] = 'F'; + newName[length - 5] = 'R'; + newName[length - 4] = 'A'; + } else if (gSaveContext.language == LANGUAGE_GER) { + newName[length - 6] = 'G'; + newName[length - 5] = 'E'; + newName[length - 4] = 'R'; + } + doAction = newName; + } + memcpy(interfaceCtx->doActionSegment + DO_ACTION_TEX_SIZE * 2, ResourceMgr_LoadTexByName(doAction), DO_ACTION_TEX_SIZE); + gDPLoadTextureBlock_4b(OVERLAY_DISP++, interfaceCtx->doActionSegment + DO_ACTION_TEX_SIZE * 2, G_IM_FMT_IA, DO_ACTION_TEX_WIDTH, DO_ACTION_TEX_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); From 4669235f62bf387062b63f5cd8253d18784c31b9 Mon Sep 17 00:00:00 2001 From: earthcrafterman Date: Sun, 29 May 2022 11:46:47 -0400 Subject: [PATCH 21/30] Spammable kaepora (#354) * Players can now spam their way through Kaepora Gaebora dialogue * Turned the Owl Text Inversion into a toggle Instead of replacing the Kokiri Owl Text at boot, a new Text Entry is added for it * Attempt to make it compile on Linux * Added multilingual support * Commented the code to clear up confusion --- libultraship/libultraship/SohImGuiImpl.cpp | 3 +- soh/soh/z_message_OTR.cpp | 43 ++++++++++++++++++- soh/src/code/z_message_PAL.c | 13 ++++-- soh/src/overlays/actors/ovl_En_Owl/z_en_owl.c | 32 ++++++++++---- 4 files changed, 78 insertions(+), 13 deletions(-) diff --git a/libultraship/libultraship/SohImGuiImpl.cpp b/libultraship/libultraship/SohImGuiImpl.cpp index 5ea017173..f9f5d9b7b 100644 --- a/libultraship/libultraship/SohImGuiImpl.cpp +++ b/libultraship/libultraship/SohImGuiImpl.cpp @@ -723,9 +723,10 @@ namespace SohImGui { Tooltip("Allows equiping the tunic and boots to c-buttons"); EnhancementCheckbox("MM Bunny Hood", "gMMBunnyHood"); Tooltip("Wearing the Bunny Hood grants a speed increase like in Majora's Mask"); + EnhancementCheckbox("Better Owl", "gBetterOwl"); + Tooltip("The default response to Kaepora Gaebora is always that you understood what he said"); EnhancementCheckbox("Disable Navi Call Audio", "gDisableNaviCallAudio"); Tooltip("Disables the voice audio when Navi calls you"); - ImGui::EndMenu(); } diff --git a/soh/soh/z_message_OTR.cpp b/soh/soh/z_message_OTR.cpp index ac1f013c2..8c1d26a75 100644 --- a/soh/soh/z_message_OTR.cpp +++ b/soh/soh/z_message_OTR.cpp @@ -19,9 +19,50 @@ MessageTableEntry* OTRMessage_LoadTable(const char* filePath, bool isNES) { if (file == nullptr) return nullptr; - MessageTableEntry* table = (MessageTableEntry*)malloc(sizeof(MessageTableEntry) * file->messages.size()); + // Allocate room for an additional message + MessageTableEntry* table = (MessageTableEntry*)malloc(sizeof(MessageTableEntry) * (file->messages.size() + 1)); for (int i = 0; i < file->messages.size(); i++) { + // Look for Owl Text + if (file->messages[i].id == 0x2066) { + // Create a new message based on the Owl Text + char* kaeporaPatch = (char*)malloc(sizeof(char) * file->messages[i].msg.size()); + file->messages[i].msg.copy(kaeporaPatch, file->messages[i].msg.size(), 0); + + // Swap the order of yes and no in this new message + if (filePath == "text/nes_message_data_static/nes_message_data_static") { + kaeporaPatch[26] = 'Y'; + kaeporaPatch[27] = 'e'; + kaeporaPatch[28] = 's'; + kaeporaPatch[29] = 1; + kaeporaPatch[30] = 'N'; + kaeporaPatch[31] = 'o'; + } else if (filePath == "text/ger_message_data_static/ger_message_data_static") { + kaeporaPatch[30] = 'J'; + kaeporaPatch[31] = 'a'; + kaeporaPatch[32] = '!'; + kaeporaPatch[33] = 1; + kaeporaPatch[34] = 'N'; + kaeporaPatch[35] = 'e'; + kaeporaPatch[36] = 'i'; + kaeporaPatch[37] = 'n'; + } else { + kaeporaPatch[26] = 'O'; + kaeporaPatch[27] = 'u'; + kaeporaPatch[28] = 'i'; + kaeporaPatch[29] = 1; + kaeporaPatch[30] = 'N'; + kaeporaPatch[31] = 'o'; + kaeporaPatch[32] = 'n'; + } + + // load data into message + table[file->messages.size()].textId = 0x71B3; + table[file->messages.size()].typePos = (file->messages[i].textboxType << 4) | file->messages[i].textboxYPos; + table[file->messages.size()].segment = kaeporaPatch; + table[file->messages.size()].msgSize = file->messages[i].msg.size(); + } + table[i].textId = file->messages[i].id; table[i].typePos = (file->messages[i].textboxType << 4) | file->messages[i].textboxYPos; table[i].segment = file->messages[i].msg.c_str(); diff --git a/soh/src/code/z_message_PAL.c b/soh/src/code/z_message_PAL.c index 33bc9a95e..84cf20e71 100644 --- a/soh/src/code/z_message_PAL.c +++ b/soh/src/code/z_message_PAL.c @@ -272,6 +272,13 @@ void Message_FindMessage(GlobalContext* globalCtx, u16 textId) { const char** languageSegmentTable; Font* font; const char* seg; + u16 bufferId = textId; + // Use the better owl message if better owl is enabled + if (CVar_GetS32("gBetterOwl", 0) != 0 && (bufferId == 0x2066 || bufferId == 0x607B || + bufferId == 0x10C2 || bufferId == 0x10C6 || bufferId == 0x206A)) + { + bufferId = 0x71B3; + } if (gSaveContext.language == LANGUAGE_GER) messageTableEntry = sGerMessageEntryTablePtr; @@ -287,7 +294,7 @@ void Message_FindMessage(GlobalContext* globalCtx, u16 textId) { while (messageTableEntry->textId != 0xFFFF) { font = &globalCtx->msgCtx.font; - if (messageTableEntry->textId == textId) { + if (messageTableEntry->textId == bufferId) { foundSeg = messageTableEntry->segment; font->charTexBuf[0] = messageTableEntry->typePos; @@ -298,14 +305,14 @@ void Message_FindMessage(GlobalContext* globalCtx, u16 textId) { // "Message found!!!" osSyncPrintf(" メッセージが,見つかった!!! = %x " "(data=%x) (data0=%x) (data1=%x) (data2=%x) (data3=%x)\n", - textId, font->msgOffset, font->msgLength, foundSeg, seg, nextSeg); + bufferId, font->msgOffset, font->msgLength, foundSeg, seg, nextSeg); return; } messageTableEntry++; } // "Message not found!!!" - osSyncPrintf(" メッセージが,見つからなかった!!! = %x\n", textId); + osSyncPrintf(" メッセージが,見つからなかった!!! = %x\n", bufferId); font = &globalCtx->msgCtx.font; messageTableEntry = sNesMessageEntryTablePtr; diff --git a/soh/src/overlays/actors/ovl_En_Owl/z_en_owl.c b/soh/src/overlays/actors/ovl_En_Owl/z_en_owl.c index 054f00b4d..aef838499 100644 --- a/soh/src/overlays/actors/ovl_En_Owl/z_en_owl.c +++ b/soh/src/overlays/actors/ovl_En_Owl/z_en_owl.c @@ -366,7 +366,9 @@ void func_80ACA7E0(EnOwl* this, GlobalContext* globalCtx) { void EnOwl_ConfirmKokiriMessage(EnOwl* this, GlobalContext* globalCtx) { if (Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_CHOICE && Message_ShouldAdvance(globalCtx)) { - switch (globalCtx->msgCtx.choiceIndex) { + // swap the order of the responses if better owl is enabled + uint8_t index = CVar_GetS32("gBetterOwl", 0) == 0 ? globalCtx->msgCtx.choiceIndex : (1 - globalCtx->msgCtx.choiceIndex); + switch (index) { case OWL_REPEAT: Message_ContinueTextbox(globalCtx, 0x2065); break; @@ -393,7 +395,9 @@ void EnOwl_WaitOutsideKokiri(EnOwl* this, GlobalContext* globalCtx) { void func_80ACA998(EnOwl* this, GlobalContext* globalCtx) { if (Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_CHOICE && Message_ShouldAdvance(globalCtx)) { - switch (globalCtx->msgCtx.choiceIndex) { + // swap the order of the responses if better owl is enabled + uint8_t index = CVar_GetS32("gBetterOwl", 0) == 0 ? globalCtx->msgCtx.choiceIndex : (1 - globalCtx->msgCtx.choiceIndex); + switch (index) { case OWL_REPEAT: Message_ContinueTextbox(globalCtx, 0x2069); this->actionFunc = func_80ACAA54; @@ -437,7 +441,9 @@ void EnOwl_WaitHyruleCastle(EnOwl* this, GlobalContext* globalCtx) { void func_80ACAB88(EnOwl* this, GlobalContext* globalCtx) { if (Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_CHOICE && Message_ShouldAdvance(globalCtx)) { - switch (globalCtx->msgCtx.choiceIndex) { + // swap the order of the responses if better owl is enabled + uint8_t index = CVar_GetS32("gBetterOwl", 0) == 0 ? globalCtx->msgCtx.choiceIndex : (1 - globalCtx->msgCtx.choiceIndex); + switch (index) { case OWL_REPEAT: // obtained zelda's letter if (gSaveContext.eventChkInf[4] & 1) { @@ -478,7 +484,9 @@ void EnOwl_WaitKakariko(EnOwl* this, GlobalContext* globalCtx) { void func_80ACAD34(EnOwl* this, GlobalContext* globalCtx) { if (Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_CHOICE && Message_ShouldAdvance(globalCtx)) { - switch (globalCtx->msgCtx.choiceIndex) { + // swap the order of the responses if better owl is enabled + uint8_t index = CVar_GetS32("gBetterOwl", 0) == 0 ? globalCtx->msgCtx.choiceIndex : (1 - globalCtx->msgCtx.choiceIndex); + switch (index) { case OWL_REPEAT: Message_ContinueTextbox(globalCtx, 0x206F); this->actionFunc = func_80ACADF0; @@ -514,7 +522,9 @@ void EnOwl_WaitGerudo(EnOwl* this, GlobalContext* globalCtx) { void func_80ACAEB8(EnOwl* this, GlobalContext* globalCtx) { if (Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_CHOICE && Message_ShouldAdvance(globalCtx)) { - switch (globalCtx->msgCtx.choiceIndex) { + // swap the order of the responses if better owl is enabled + uint8_t index = CVar_GetS32("gBetterOwl", 0) == 0 ? globalCtx->msgCtx.choiceIndex : (1 - globalCtx->msgCtx.choiceIndex); + switch (index) { case OWL_REPEAT: Message_ContinueTextbox(globalCtx, 0x2071); this->actionFunc = func_80ACAF74; @@ -634,7 +644,9 @@ void EnOwl_WaitDeathMountainShortcut(EnOwl* this, GlobalContext* globalCtx) { void func_80ACB344(EnOwl* this, GlobalContext* globalCtx) { if (Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_CHOICE && Message_ShouldAdvance(globalCtx)) { - switch (globalCtx->msgCtx.choiceIndex) { + // swap the order of the responses if better owl is enabled + uint8_t index = CVar_GetS32("gBetterOwl", 0) == 0 ? globalCtx->msgCtx.choiceIndex : (1 - globalCtx->msgCtx.choiceIndex); + switch (index) { case OWL_REPEAT: Message_ContinueTextbox(globalCtx, 0x607A); break; @@ -657,7 +669,9 @@ void func_80ACB3E0(EnOwl* this, GlobalContext* globalCtx) { void func_80ACB440(EnOwl* this, GlobalContext* globalCtx) { if (Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_CHOICE && Message_ShouldAdvance(globalCtx)) { - switch (globalCtx->msgCtx.choiceIndex) { + // swap the order of the responses if better owl is enabled + uint8_t index = CVar_GetS32("gBetterOwl", 0) == 0 ? globalCtx->msgCtx.choiceIndex : (1 - globalCtx->msgCtx.choiceIndex); + switch (index) { case OWL_REPEAT: Message_ContinueTextbox(globalCtx, 0x10C1); this->actionFunc = func_80ACB4FC; @@ -692,7 +706,9 @@ void EnOwl_WaitLWPreSaria(EnOwl* this, GlobalContext* globalCtx) { void func_80ACB5C4(EnOwl* this, GlobalContext* globalCtx) { if (Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_CHOICE && Message_ShouldAdvance(globalCtx)) { - switch (globalCtx->msgCtx.choiceIndex) { + // swap the order of the responses if better owl is enabled + uint8_t index = CVar_GetS32("gBetterOwl", 0) == 0 ? globalCtx->msgCtx.choiceIndex : (1 - globalCtx->msgCtx.choiceIndex); + switch (index) { case OWL_REPEAT: Message_ContinueTextbox(globalCtx, 0x10C5); this->actionFunc = func_80ACB680; From 533c216ad3a95b102830edc670adfa313a3cf346 Mon Sep 17 00:00:00 2001 From: louist103 <35883445+louist103@users.noreply.github.com> Date: Sun, 29 May 2022 11:47:09 -0400 Subject: [PATCH 22/30] Cleanup ImGui strings (#359) * Cleanup * Emills suggestion * fixes --- libultraship/libultraship/SohImGuiImpl.cpp | 122 +++++++++++---------- libultraship/libultraship/SohImGuiImpl.h | 14 ++- 2 files changed, 72 insertions(+), 64 deletions(-) diff --git a/libultraship/libultraship/SohImGuiImpl.cpp b/libultraship/libultraship/SohImGuiImpl.cpp index f9f5d9b7b..2a897437f 100644 --- a/libultraship/libultraship/SohImGuiImpl.cpp +++ b/libultraship/libultraship/SohImGuiImpl.cpp @@ -46,9 +46,9 @@ bool oldCursorState = true; #define EXPERIMENTAL() \ ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(255, 50, 50, 255)); \ - ImGui::Text("Experimental"); \ - ImGui::PopStyleColor(); \ - ImGui::Separator(); + ImGui::Text("Experimental"); \ + ImGui::PopStyleColor(); \ + ImGui::Separator(); #define TOGGLE_BTN ImGuiKey_F1 #define HOOK(b) if(b) needs_save = true; OSContPad* pads; @@ -348,10 +348,10 @@ namespace SohImGui { } for (size_t pixel = 0; pixel < texBuffer.size() / 4; pixel++) { - texBuffer[pixel * 4 + 0] *= tint.x; - texBuffer[pixel * 4 + 1] *= tint.y; - texBuffer[pixel * 4 + 2] *= tint.z; - texBuffer[pixel * 4 + 3] *= tint.w; + texBuffer[pixel * 4 + 0] *= (uint8_t)tint.x; + texBuffer[pixel * 4 + 1] *= (uint8_t)tint.y; + texBuffer[pixel * 4 + 2] *= (uint8_t)tint.z; + texBuffer[pixel * 4 + 3] *= (uint8_t)tint.w; } const auto asset = new GameAsset{ api->new_texture() }; @@ -436,7 +436,7 @@ namespace SohImGui { } } - void EnhancementRadioButton(std::string text, std::string cvarName, int id) { + void EnhancementRadioButton(const char* text, const char* cvarName, int id) { /*Usage : EnhancementRadioButton("My Visible Name","gMyCVarName", MyID); First arg is the visible name of the Radio button @@ -447,113 +447,117 @@ namespace SohImGui { EnhancementRadioButton("German", "gLanguages", 1); EnhancementRadioButton("French", "gLanguages", 2); */ - int val = CVar_GetS32(cvarName.c_str(), 0); - if (ImGui::RadioButton(text.c_str(), id == val)) { - CVar_SetS32(cvarName.c_str(), (int)id); + int val = CVar_GetS32(cvarName, 0); + if (ImGui::RadioButton(text, id == val)) { + CVar_SetS32(cvarName, id); needs_save = true; } } - void EnhancementCheckbox(std::string text, std::string cvarName) + void EnhancementCheckbox(const char* text, const char* cvarName) { - bool val = (bool)CVar_GetS32(cvarName.c_str(), 0); - if (ImGui::Checkbox(text.c_str(), &val)) { - CVar_SetS32(cvarName.c_str(), val); + bool val = (bool)CVar_GetS32(cvarName, 0); + if (ImGui::Checkbox(text, &val)) { + CVar_SetS32(cvarName, val); needs_save = true; } } - void EnhancementButton(std::string text, std::string cvarName) + void EnhancementButton(const char* text, const char* cvarName) { - bool val = (bool)CVar_GetS32(cvarName.c_str(), 0); - if (ImGui::Button(text.c_str())) { - CVar_SetS32(cvarName.c_str(), !val); + bool val = (bool)CVar_GetS32(cvarName, 0); + if (ImGui::Button(text)) { + CVar_SetS32(cvarName, !val); + CVar_SetS32(cvarName, !val); needs_save = true; } } - void EnhancementSliderInt(std::string text, std::string id, std::string cvarName, int min, int max, std::string format) + void EnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format) { - int val = CVar_GetS32(cvarName.c_str(), 0); + int val = CVar_GetS32(cvarName, 0); - ImGui::Text(text.c_str(), val); + ImGui::Text(text, val); - if (ImGui::SliderInt(id.c_str(), &val, min, max, format.c_str())) + if (ImGui::SliderInt(id, &val, min, max, format)) { - CVar_SetS32(cvarName.c_str(), val); + CVar_SetS32(cvarName, val); needs_save = true; } if (val < min) { val = min; - CVar_SetS32(cvarName.c_str(), val); + CVar_SetS32(cvarName, val); needs_save = true; } if (val > max) { val = max; - CVar_SetS32(cvarName.c_str(), val); + CVar_SetS32(cvarName, val); needs_save = true; } } - void EnhancementSliderFloat(std::string text, std::string id, std::string cvarName, float min, float max, std::string format, float defaultValue, bool isPercentage) + void EnhancementSliderFloat(const char* text, const char* id, const char* cvarName, float min, float max, const char* format, float defaultValue, bool isPercentage) { - float val = CVar_GetFloat(cvarName.c_str(), defaultValue); + float val = CVar_GetFloat(cvarName, defaultValue); if (!isPercentage) - ImGui::Text(text.c_str(), val); + ImGui::Text(text, val); else - ImGui::Text(text.c_str(), static_cast(100 * val)); + ImGui::Text(text, static_cast(100 * val)); - if (ImGui::SliderFloat(id.c_str(), &val, min, max, format.c_str())) + if (ImGui::SliderFloat(id, &val, min, max, format)) { - CVar_SetFloat(cvarName.c_str(), val); + CVar_SetFloat(cvarName, val); needs_save = true; } if (val < min) { val = min; - CVar_SetFloat(cvarName.c_str(), val); + CVar_SetFloat(cvarName, val); needs_save = true; } if (val > max) { val = max; - CVar_SetFloat(cvarName.c_str(), val); + CVar_SetFloat(cvarName, val); needs_save = true; } } - int ClampFloatToInt(float value, int min, int max){ - return fmin(fmax(value,min),max); + int ClampFloatToInt(float value, int min, int max) { + return fmin(fmax(value, min), max); } - void EnhancementColor3(std::string text, std::string cvarName, float ColorRGB[3], bool TitleSameLine) { + void EnhancementColor3(const char* text, const char* cvarName, float ColorRGB[3], bool TitleSameLine) { //Simplified. + std::string cvarNameString(cvarName); ImGuiColorEditFlags flags = ImGuiColorEditFlags_None; - if (!TitleSameLine){ - ImGui::Text("%s", text.c_str()); + + if (!TitleSameLine) { + ImGui::Text("%s", text); flags = ImGuiColorEditFlags_NoLabel; } - if (ImGui::ColorEdit3(text.c_str(), ColorRGB, flags)) { - CVar_SetS32((cvarName+"R").c_str(), ClampFloatToInt(ColorRGB[0]*255,0,255)); - CVar_SetS32((cvarName+"G").c_str(), ClampFloatToInt(ColorRGB[1]*255,0,255)); - CVar_SetS32((cvarName+"B").c_str(), ClampFloatToInt(ColorRGB[2]*255,0,255)); + if (ImGui::ColorEdit3(text, ColorRGB, flags)) { + CVar_SetS32((cvarNameString + "R").c_str(), ClampFloatToInt(ColorRGB[0] * 255, 0, 255)); + CVar_SetS32((cvarNameString + "G").c_str(), ClampFloatToInt(ColorRGB[1] * 255, 0, 255)); + CVar_SetS32((cvarNameString + "B").c_str(), ClampFloatToInt(ColorRGB[2] * 255, 0, 255)); needs_save = true; } } - void Tooltip(std::string text) { + + void Tooltip(const char* text) { if (ImGui::IsItemHovered()) - ImGui::SetTooltip("%s", text.c_str()); + ImGui::SetTooltip("%s", text); } - void DrawMainMenuAndCalculateGameSize() { + void DrawMainMenuAndCalculateGameSize(void) { console->Update(); ImGuiBackendNewFrame(); ImGuiWMNewFrame(); @@ -633,7 +637,7 @@ namespace SohImGui { auto menuLabel = "Controller " + std::to_string(i + 1); if (ImGui::BeginMenu(menuLabel.c_str())) { - EnhancementSliderFloat("Gyro Sensitivity: %d %%", "##GYROSCOPE", StringHelper::Sprintf("gCont%i_GyroSensitivity", i), 0.0f, 1.0f, "", 1.0f, true); + EnhancementSliderFloat("Gyro Sensitivity: %d %%", "##GYROSCOPE", StringHelper::Sprintf("gCont%i_GyroSensitivity", i).c_str(), 0.0f, 1.0f, "", 1.0f, true); if (ImGui::Button("Recalibrate Gyro")) { @@ -644,7 +648,7 @@ namespace SohImGui { ImGui::Separator(); - EnhancementSliderFloat("Rumble Strength: %d %%", "##RUMBLE", StringHelper::Sprintf("gCont%i_RumbleStrength", i), 0.0f, 1.0f, "", 1.0f, true); + EnhancementSliderFloat("Rumble Strength: %d %%", "##RUMBLE", StringHelper::Sprintf("gCont%i_RumbleStrength", i).c_str(), 0.0f, 1.0f, "", 1.0f, true); ImGui::EndMenu(); } @@ -960,7 +964,7 @@ namespace SohImGui { varName.erase(std::ranges::remove_if(varName, isspace).begin(), varName.end()); std::string toggleName = "g" + varName + "Enabled"; - EnhancementCheckbox(name, toggleName); + EnhancementCheckbox(name.c_str(), toggleName.c_str()); customWindows[name].enabled = CVar_GetS32(toggleName.c_str(), 0); } ImGui::EndMenu(); @@ -1011,19 +1015,19 @@ namespace SohImGui { main_pos.y -= top_left_pos.y; ImVec2 size = ImGui::GetContentRegionAvail(); ImVec2 pos = ImVec2(0, 0); - gfx_current_dimensions.width = size.x * gfx_current_dimensions.internal_mul; - gfx_current_dimensions.height = size.y * gfx_current_dimensions.internal_mul; - gfx_current_game_window_viewport.x = main_pos.x; - gfx_current_game_window_viewport.y = main_pos.y; - gfx_current_game_window_viewport.width = size.x; - gfx_current_game_window_viewport.height = size.y; + gfx_current_dimensions.width = (uint32_t)(size.x * gfx_current_dimensions.internal_mul); + gfx_current_dimensions.height = (uint32_t)(size.y * gfx_current_dimensions.internal_mul); + gfx_current_game_window_viewport.x = (int16_t)main_pos.x; + gfx_current_game_window_viewport.y = (int16_t)main_pos.y; + gfx_current_game_window_viewport.width = (int16_t)size.x; + gfx_current_game_window_viewport.height = (int16_t)size.y; if (CVar_GetS32("gN64Mode", 0)) { gfx_current_dimensions.width = 320; gfx_current_dimensions.height = 240; const int sw = size.y * 320 / 240; - gfx_current_game_window_viewport.x += (size.x - sw) / 2; + gfx_current_game_window_viewport.x += ((int)size.x - sw) / 2; gfx_current_game_window_viewport.width = sw; pos = ImVec2(size.x / 2 - sw / 2, 0); size = ImVec2(sw, size.y); @@ -1032,12 +1036,12 @@ namespace SohImGui { overlay->Draw(); } - void DrawFramebufferAndGameInput() { - ImVec2 main_pos = ImGui::GetWindowPos(); + void DrawFramebufferAndGameInput(void) { + const ImVec2 main_pos = ImGui::GetWindowPos(); ImVec2 size = ImGui::GetContentRegionAvail(); ImVec2 pos = ImVec2(0, 0); if (CVar_GetS32("gN64Mode", 0)) { - const int sw = size.y * 320 / 240; + const float sw = size.y * 320.0f / 240.0f; pos = ImVec2(size.x / 2 - sw / 2, 0); size = ImVec2(sw, size.y); } diff --git a/libultraship/libultraship/SohImGuiImpl.h b/libultraship/libultraship/SohImGuiImpl.h index 210a26db9..2a192802d 100644 --- a/libultraship/libultraship/SohImGuiImpl.h +++ b/libultraship/libultraship/SohImGuiImpl.h @@ -64,11 +64,15 @@ namespace SohImGui { void Init(WindowImpl window_impl); void Update(EventImpl event); - void EnhancementRadioButton(std::string text, std::string cvarName, int value); - void EnhancementCheckbox(std::string text, std::string cvarName); - void EnhancementSliderInt(std::string text, std::string id, std::string cvarName, int min, int max, std::string format); - void EnhancementSliderFloat(std::string text, std::string id, std::string cvarName, float min, float max, std::string format, float defaultValue); - void EnhancementColor3(std::string text, std::string cvarName, float ColorRGB[3], bool TitleSameLine); + void EnhancementRadioButton(const char* text, const char* cvarName, int id); + void EnhancementCheckbox(const char* text, const char* cvarName); + void EnhancementButton(const char* text, const char* cvarName); + void EnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format); + void EnhancementSliderFloat(const char* text, const char* id, const char* cvarName, float min, float max, const char* format, float defaultValue, bool isPercentage); + + void Tooltip(const char* text); + + void EnhancementColor3(const char* text, const char* cvarName, float defaultColors[3], bool TitleSameLine); void DrawMainMenuAndCalculateGameSize(void); From 83c07645f477eaa15c7f8736301d4945973c6852 Mon Sep 17 00:00:00 2001 From: Martin Molina <64887017+Megadash452@users.noreply.github.com> Date: Sun, 29 May 2022 11:55:00 -0400 Subject: [PATCH 23/30] Fixed crash when showing Triforce during lore cutscene after defeating Ghoma (#384) --- soh/assets/xml/GC_NMQ_PAL_F/objects/object_triforce_spot.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soh/assets/xml/GC_NMQ_PAL_F/objects/object_triforce_spot.xml b/soh/assets/xml/GC_NMQ_PAL_F/objects/object_triforce_spot.xml index a9d52dd96..87d449458 100644 --- a/soh/assets/xml/GC_NMQ_PAL_F/objects/object_triforce_spot.xml +++ b/soh/assets/xml/GC_NMQ_PAL_F/objects/object_triforce_spot.xml @@ -1,6 +1,6 @@ - + From aaa1fafd511d250ea4b94c6ec93bbd84ac490f32 Mon Sep 17 00:00:00 2001 From: Baoulettes Date: Sun, 29 May 2022 17:55:50 +0200 Subject: [PATCH 24/30] Init desired languages CVar on InitSram (#385) * Properly init desired languages * Fix typos --- soh/src/code/z_sram.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/soh/src/code/z_sram.c b/soh/src/code/z_sram.c index a774636f7..16835d7ad 100644 --- a/soh/src/code/z_sram.c +++ b/soh/src/code/z_sram.c @@ -836,7 +836,7 @@ void Sram_InitSram(GameState* gameState, SramContext* sramCtx) { for (i = 0; i < ARRAY_COUNTU(sZeldaMagic) - 3; i++) { if (sZeldaMagic[i + SRAM_HEADER_MAGIC] != sramCtx->readBuff[i + SRAM_HEADER_MAGIC]) { osSyncPrintf("SRAM破壊!!!!!!\n"); // "SRAM destruction! ! ! ! ! !" - gSaveContext.language = sramCtx->readBuff[SRAM_HEADER_LANGUAGE]; + gSaveContext.language = CVar_GetS32("gLanguages", 0); memcpy(sramCtx->readBuff, sZeldaMagic, sizeof(sZeldaMagic)); sramCtx->readBuff[SRAM_HEADER_LANGUAGE] = gSaveContext.language; Sram_WriteSramHeader(sramCtx); @@ -845,7 +845,7 @@ void Sram_InitSram(GameState* gameState, SramContext* sramCtx) { gSaveContext.audioSetting = sramCtx->readBuff[SRAM_HEADER_SOUND] & 3; gSaveContext.zTargetSetting = sramCtx->readBuff[SRAM_HEADER_ZTARGET] & 1; - gSaveContext.language = sramCtx->readBuff[SRAM_HEADER_LANGUAGE]; + gSaveContext.language = CVar_GetS32("gLanguages", 0); if (gSaveContext.language >= LANGUAGE_MAX) { gSaveContext.language = LANGUAGE_ENG; From 90a33e9756388a2d5cefd2c9d30f010e622799fe Mon Sep 17 00:00:00 2001 From: GreenSwede <42186507+GreenSwede@users.noreply.github.com> Date: Sun, 29 May 2022 18:14:46 +0200 Subject: [PATCH 25/30] [LINUX] Add compiler flags to fix floating point precision error (#399) These flags are known to fix one known issue exclusive to Linux: the Volvagia boss battle sequence. The softlock that occurs points towards a possible floating point precision error, possibly tied to the camera/Volvagia movement. This does not occur for the Windows build. It's possible that there are more issues that gets fixed by these flags. These flags will ensure that the compiler follows the IEEE 754 standard, which so happens to be the same behaviour that Windows uses. For more details, read this informative stackoverflow post: https://stackoverflow.com/a/16395650 --- soh/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/soh/Makefile b/soh/Makefile index be46f55e7..74a112ecb 100644 --- a/soh/Makefile +++ b/soh/Makefile @@ -18,8 +18,8 @@ WARN := \ -funsigned-char \ -m32 -mhard-float -fno-stack-protector -fno-common -fno-zero-initialized-in-bss -fno-strict-aliasing -fno-inline-functions -fno-inline-small-functions -fno-toplevel-reorder -ffreestanding -fwrapv \ -CXXFLAGS := $(WARN) -std=c++20 -D_GNU_SOURCE -fpermissive -no-pie -nostdlib -march=i386 -CFLAGS := $(WARN) -std=c99 -D_GNU_SOURCE -no-pie -nostdlib -march=i386 +CXXFLAGS := $(WARN) -std=c++20 -D_GNU_SOURCE -fpermissive -no-pie -nostdlib -march=i386 -msse2 -mfpmath=sse +CFLAGS := $(WARN) -std=c99 -D_GNU_SOURCE -no-pie -nostdlib -march=i386 -msse2 -mfpmath=sse LDFLAGS := -m32 CPPFLAGS := -MMD From ccab94c765c5518e9ed8aa3a04b10c2d6a2d9159 Mon Sep 17 00:00:00 2001 From: Emill Date: Sun, 29 May 2022 18:16:23 +0200 Subject: [PATCH 26/30] Implement AnyFPS + option to queue one rendered frame (#401) --- .../Lib/Fast3D/gfx_direct3d11.cpp | 37 +++-- .../libultraship/Lib/Fast3D/gfx_dxgi.cpp | 145 ++++++++++++------ .../libultraship/Lib/Fast3D/gfx_dxgi.h | 8 +- .../libultraship/Lib/Fast3D/gfx_pc.cpp | 15 +- libultraship/libultraship/Lib/Fast3D/gfx_pc.h | 4 +- .../libultraship/Lib/Fast3D/gfx_sdl2.cpp | 39 +++-- .../Lib/Fast3D/gfx_window_manager_api.h | 4 +- libultraship/libultraship/SohImGuiImpl.cpp | 69 ++++++++- libultraship/libultraship/Window.cpp | 11 +- libultraship/libultraship/Window.h | 3 +- soh/soh/OTRGlobals.cpp | 40 ++++- soh/soh/frame_interpolation.cpp | 2 +- soh/src/code/z_actor.c | 2 +- .../ovl_file_choose/z_file_choose.c | 8 + 14 files changed, 298 insertions(+), 89 deletions(-) diff --git a/libultraship/libultraship/Lib/Fast3D/gfx_direct3d11.cpp b/libultraship/libultraship/Lib/Fast3D/gfx_direct3d11.cpp index 4664a0faa..f1661f426 100644 --- a/libultraship/libultraship/Lib/Fast3D/gfx_direct3d11.cpp +++ b/libultraship/libultraship/Lib/Fast3D/gfx_direct3d11.cpp @@ -96,7 +96,6 @@ static struct { uint32_t msaa_num_quality_levels[D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT]; ComPtr device; - ComPtr swap_chain; ComPtr context; ComPtr rasterizer_state; ComPtr depth_stencil_state; @@ -252,7 +251,24 @@ static void gfx_d3d11_init(void) { }); // Create the swap chain - d3d.swap_chain = gfx_dxgi_create_swap_chain(d3d.device.Get()); + gfx_dxgi_create_swap_chain(d3d.device.Get(), []() { + d3d.framebuffers[0].render_target_view.Reset(); + d3d.textures[d3d.framebuffers[0].texture_id].texture.Reset(); + d3d.context->ClearState(); + d3d.context->Flush(); + + d3d.last_shader_program = nullptr; + d3d.last_vertex_buffer_stride = 0; + d3d.last_blend_state.Reset(); + d3d.last_resource_views[0].Reset(); + d3d.last_resource_views[1].Reset(); + d3d.last_sampler_states[0].Reset(); + d3d.last_sampler_states[1].Reset(); + d3d.last_depth_test = -1; + d3d.last_depth_mask = -1; + d3d.last_zmode_decal = -1; + d3d.last_primitive_topology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED; + }); // Create D3D Debug device if in debug mode @@ -266,7 +282,7 @@ static void gfx_d3d11_init(void) { // Check the size of the window DXGI_SWAP_CHAIN_DESC1 swap_chain_desc; - ThrowIfFailed(d3d.swap_chain->GetDesc1(&swap_chain_desc)); + ThrowIfFailed(gfx_dxgi_get_swap_chain()->GetDesc1(&swap_chain_desc)); d3d.textures[fb.texture_id].width = swap_chain_desc.Width; d3d.textures[fb.texture_id].height = swap_chain_desc.Height; fb.msaa_level = 1; @@ -303,8 +319,6 @@ static void gfx_d3d11_init(void) { ThrowIfFailed(d3d.device->CreateBuffer(&constant_buffer_desc, nullptr, d3d.per_frame_cb.GetAddressOf()), gfx_dxgi_get_h_wnd(), "Failed to create per-frame constant buffer."); - d3d.context->PSSetConstantBuffers(0, 1, d3d.per_frame_cb.GetAddressOf()); - // Create per-draw constant buffer constant_buffer_desc.Usage = D3D11_USAGE_DYNAMIC; @@ -316,8 +330,6 @@ static void gfx_d3d11_init(void) { ThrowIfFailed(d3d.device->CreateBuffer(&constant_buffer_desc, nullptr, d3d.per_draw_cb.GetAddressOf()), gfx_dxgi_get_h_wnd(), "Failed to create per-draw constant buffer."); - d3d.context->PSSetConstantBuffers(1, 1, d3d.per_draw_cb.GetAddressOf()); - // Create compute shader that can be used to retrieve depth buffer values const char* shader_source = R"( @@ -737,6 +749,8 @@ static void gfx_d3d11_on_resize(void) { static void gfx_d3d11_start_frame(void) { // Set per-frame constant buffer + ID3D11Buffer* buffers[2] = { d3d.per_frame_cb.Get(), d3d.per_draw_cb.Get() }; + d3d.context->PSSetConstantBuffers(0, 2, buffers); d3d.per_frame_cb_data.noise_frame++; if (d3d.per_frame_cb_data.noise_frame > 150) { @@ -803,15 +817,16 @@ static void gfx_d3d11_update_framebuffer_parameters(int fb_id, uint32_t width, u if (msaa_level <= 1) { ThrowIfFailed(d3d.device->CreateShaderResourceView(tex.texture.Get(), nullptr, tex.resource_view.ReleaseAndGetAddressOf())); } - } else if (diff) { + } else if (diff || (render_target && tex.texture.Get() == nullptr)) { DXGI_SWAP_CHAIN_DESC1 desc1; - ThrowIfFailed(d3d.swap_chain->GetDesc1(&desc1)); + IDXGISwapChain1* swap_chain = gfx_dxgi_get_swap_chain(); + ThrowIfFailed(swap_chain->GetDesc1(&desc1)); if (desc1.Width != width || desc1.Height != height) { fb.render_target_view.Reset(); tex.texture.Reset(); - ThrowIfFailed(d3d.swap_chain->ResizeBuffers(0, 0, 0, DXGI_FORMAT_UNKNOWN, desc1.Flags)); + ThrowIfFailed(swap_chain->ResizeBuffers(0, 0, 0, DXGI_FORMAT_UNKNOWN, desc1.Flags)); } - ThrowIfFailed(d3d.swap_chain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID *)tex.texture.ReleaseAndGetAddressOf())); + ThrowIfFailed(swap_chain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID *)tex.texture.ReleaseAndGetAddressOf())); } if (render_target) { ThrowIfFailed(d3d.device->CreateRenderTargetView(tex.texture.Get(), nullptr, fb.render_target_view.ReleaseAndGetAddressOf())); diff --git a/libultraship/libultraship/Lib/Fast3D/gfx_dxgi.cpp b/libultraship/libultraship/Lib/Fast3D/gfx_dxgi.cpp index 49abe0b28..d257d7b08 100644 --- a/libultraship/libultraship/Lib/Fast3D/gfx_dxgi.cpp +++ b/libultraship/libultraship/Lib/Fast3D/gfx_dxgi.cpp @@ -34,15 +34,8 @@ #define WINCLASS_NAME L"N64GAME" #define GFX_API_NAME "DirectX" -#ifdef VERSION_EU -#define FRAME_INTERVAL_US_NUMERATOR_ 60000 -#define FRAME_INTERVAL_US_DENOMINATOR 3 -#else -#define FRAME_INTERVAL_US_NUMERATOR_ 50000 -#define FRAME_INTERVAL_US_DENOMINATOR 3 -#endif - -#define FRAME_INTERVAL_US_NUMERATOR (FRAME_INTERVAL_US_NUMERATOR_ * dxgi.frame_divisor) +#define FRAME_INTERVAL_NS_NUMERATOR 1000000000 +#define FRAME_INTERVAL_NS_DENOMINATOR (dxgi.target_fps) using namespace Microsoft::WRL; // For ComPtr @@ -66,14 +59,19 @@ static struct { ComPtr factory; ComPtr swap_chain; HANDLE waitable_object; + ComPtr swap_chain_device; // D3D11 Device or D3D12 Command Queue + std::function before_destroy_swap_chain_fn; uint64_t qpc_init, qpc_freq; - uint64_t frame_timestamp; // in units of 1/FRAME_INTERVAL_US_DENOMINATOR microseconds + uint64_t frame_timestamp; // in units of 1/FRAME_INTERVAL_NS_DENOMINATOR nanoseconds std::map frame_stats; std::set> pending_frame_stats; bool dropped_frame; bool zero_latency; + float detected_hz; UINT length_in_vsync_frames; - uint32_t frame_divisor; + uint32_t target_fps; + uint32_t maximum_frame_latency; + uint32_t applied_maximum_frame_latency; HANDLE timer; bool use_timer; LARGE_INTEGER previous_present_time; @@ -143,6 +141,22 @@ static void run_as_dpi_aware(Fun f) { } } +static void apply_maximum_frame_latency(bool first) { + ComPtr swap_chain2; + if (dxgi.swap_chain->QueryInterface(__uuidof(IDXGISwapChain2), &swap_chain2) == S_OK) { + ThrowIfFailed(swap_chain2->SetMaximumFrameLatency(dxgi.maximum_frame_latency)); + if (first) { + dxgi.waitable_object = swap_chain2->GetFrameLatencyWaitableObject(); + WaitForSingleObject(dxgi.waitable_object, INFINITE); + } + } else { + ComPtr device1; + ThrowIfFailed(dxgi.swap_chain->GetDevice(__uuidof(IDXGIDevice1), &device1)); + ThrowIfFailed(device1->SetMaximumFrameLatency(dxgi.maximum_frame_latency)); + } + dxgi.applied_maximum_frame_latency = dxgi.maximum_frame_latency; +} + static void toggle_borderless_window_full_screen(bool enable, bool call_callback) { // Windows 7 + flip mode + waitable object can't go to exclusive fullscreen, // so do borderless instead. If DWM is enabled, this means we get one monitor @@ -271,7 +285,8 @@ void gfx_dxgi_init(const char *game_name, bool start_in_fullscreen) { dxgi.qpc_init = qpc_init.QuadPart; dxgi.qpc_freq = qpc_freq.QuadPart; - dxgi.frame_divisor = 1; + dxgi.target_fps = 60; + dxgi.maximum_frame_latency = 1; dxgi.timer = CreateWaitableTimer(nullptr, false, nullptr); // Prepare window title @@ -367,8 +382,8 @@ static void gfx_dxgi_handle_events(void) { }*/ } -static uint64_t qpc_to_us(uint64_t qpc) { - return qpc / dxgi.qpc_freq * 1000000 + qpc % dxgi.qpc_freq * 1000000 / dxgi.qpc_freq; +static uint64_t qpc_to_ns(uint64_t qpc) { + return qpc / dxgi.qpc_freq * 1000000000 + qpc % dxgi.qpc_freq * 1000000000 / dxgi.qpc_freq; } static uint64_t qpc_to_100ns(uint64_t qpc) { @@ -406,7 +421,7 @@ static bool gfx_dxgi_start_frame(void) { dxgi.use_timer = false; - dxgi.frame_timestamp += FRAME_INTERVAL_US_NUMERATOR; + dxgi.frame_timestamp += FRAME_INTERVAL_NS_NUMERATOR; if (dxgi.frame_stats.size() >= 2) { DXGI_FRAME_STATISTICS *first = &dxgi.frame_stats.begin()->second; @@ -421,14 +436,16 @@ static bool gfx_dxgi_start_frame(void) { } double estimated_vsync_interval = (double)sync_qpc_diff / (double)sync_vsync_diff; - uint64_t estimated_vsync_interval_us = qpc_to_us(estimated_vsync_interval); - //printf("Estimated vsync_interval: %d\n", (int)estimated_vsync_interval_us); - if (estimated_vsync_interval_us < 2 || estimated_vsync_interval_us > 1000000) { + uint64_t estimated_vsync_interval_ns = qpc_to_ns(estimated_vsync_interval); + //printf("Estimated vsync_interval: %d\n", (int)estimated_vsync_interval_ns); + if (estimated_vsync_interval_ns < 2000 || estimated_vsync_interval_ns > 1000000000) { // Unreasonable, maybe a monitor change - estimated_vsync_interval_us = 16666; - estimated_vsync_interval = estimated_vsync_interval_us * dxgi.qpc_freq / 1000000; + estimated_vsync_interval_ns = 16666666; + estimated_vsync_interval = estimated_vsync_interval_ns * dxgi.qpc_freq / 1000000000; } + dxgi.detected_hz = (float)((double)1000000000 / (double)estimated_vsync_interval_ns); + UINT queued_vsyncs = 0; bool is_first = true; for (const std::pair& p : dxgi.pending_frame_stats) { @@ -440,21 +457,21 @@ static bool gfx_dxgi_start_frame(void) { } uint64_t last_frame_present_end_qpc = (last->SyncQPCTime.QuadPart - dxgi.qpc_init) + estimated_vsync_interval * queued_vsyncs; - uint64_t last_end_us = qpc_to_us(last_frame_present_end_qpc); + uint64_t last_end_ns = qpc_to_ns(last_frame_present_end_qpc); - double vsyncs_to_wait = (double)(int64_t)(dxgi.frame_timestamp / FRAME_INTERVAL_US_DENOMINATOR - last_end_us) / estimated_vsync_interval_us; - //printf("ts: %llu, last_end_us: %llu, Init v: %f\n", dxgi.frame_timestamp / 3, last_end_us, vsyncs_to_wait); + double vsyncs_to_wait = (double)(int64_t)(dxgi.frame_timestamp / FRAME_INTERVAL_NS_DENOMINATOR - last_end_ns) / estimated_vsync_interval_ns; + //printf("ts: %llu, last_end_ns: %llu, Init v: %f\n", dxgi.frame_timestamp / 3, last_end_ns, vsyncs_to_wait); if (vsyncs_to_wait <= 0) { // Too late - if ((int64_t)(dxgi.frame_timestamp / FRAME_INTERVAL_US_DENOMINATOR - last_end_us) < -66666) { + if ((int64_t)(dxgi.frame_timestamp / FRAME_INTERVAL_NS_DENOMINATOR - last_end_ns) < -66666666) { // The application must have been paused or similar - vsyncs_to_wait = round(((double)FRAME_INTERVAL_US_NUMERATOR / FRAME_INTERVAL_US_DENOMINATOR) / estimated_vsync_interval_us); + vsyncs_to_wait = round(((double)FRAME_INTERVAL_NS_NUMERATOR / FRAME_INTERVAL_NS_DENOMINATOR) / estimated_vsync_interval_ns); if (vsyncs_to_wait < 1) { vsyncs_to_wait = 1; } - dxgi.frame_timestamp = FRAME_INTERVAL_US_DENOMINATOR * (last_end_us + vsyncs_to_wait * estimated_vsync_interval_us); + dxgi.frame_timestamp = FRAME_INTERVAL_NS_DENOMINATOR * (last_end_ns + vsyncs_to_wait * estimated_vsync_interval_ns); } else { // Drop frame //printf("Dropping frame\n"); @@ -464,9 +481,9 @@ static bool gfx_dxgi_start_frame(void) { } double orig_wait = vsyncs_to_wait; if (floor(vsyncs_to_wait) != vsyncs_to_wait) { - uint64_t left = last_end_us + floor(vsyncs_to_wait) * estimated_vsync_interval_us; - uint64_t right = last_end_us + ceil(vsyncs_to_wait) * estimated_vsync_interval_us; - uint64_t adjusted_desired_time = dxgi.frame_timestamp / FRAME_INTERVAL_US_DENOMINATOR + (last_end_us + (FRAME_INTERVAL_US_NUMERATOR / FRAME_INTERVAL_US_DENOMINATOR) > dxgi.frame_timestamp / FRAME_INTERVAL_US_DENOMINATOR ? 2000 : -2000); + uint64_t left = last_end_ns + floor(vsyncs_to_wait) * estimated_vsync_interval_ns; + uint64_t right = last_end_ns + ceil(vsyncs_to_wait) * estimated_vsync_interval_ns; + uint64_t adjusted_desired_time = dxgi.frame_timestamp / FRAME_INTERVAL_NS_DENOMINATOR + (last_end_ns + (FRAME_INTERVAL_NS_NUMERATOR / FRAME_INTERVAL_NS_DENOMINATOR) > dxgi.frame_timestamp / FRAME_INTERVAL_NS_DENOMINATOR ? 2000000 : -2000000); int64_t diff_left = adjusted_desired_time - left; int64_t diff_right = right - adjusted_desired_time; if (diff_left < 0) { @@ -506,7 +523,7 @@ static void gfx_dxgi_swap_buffers_begin(void) { LARGE_INTEGER t; if (dxgi.use_timer) { QueryPerformanceCounter(&t); - int64_t next = qpc_to_100ns(dxgi.previous_present_time.QuadPart) + 10 * FRAME_INTERVAL_US_NUMERATOR / FRAME_INTERVAL_US_DENOMINATOR; + int64_t next = qpc_to_100ns(dxgi.previous_present_time.QuadPart) + FRAME_INTERVAL_NS_NUMERATOR / (FRAME_INTERVAL_NS_DENOMINATOR * 100); int64_t left = next - qpc_to_100ns(t.QuadPart); if (left > 0) { LARGE_INTEGER li; @@ -531,6 +548,32 @@ static void gfx_dxgi_swap_buffers_end(void) { QueryPerformanceCounter(&t0); QueryPerformanceCounter(&t1); + if (dxgi.applied_maximum_frame_latency > dxgi.maximum_frame_latency) { + // There seems to be a bug that if latency is decreased, there is no effect of that operation, so recreate swap chain + if (dxgi.waitable_object != nullptr) { + if (!dxgi.dropped_frame) { + // Wait the last time on this swap chain + WaitForSingleObject(dxgi.waitable_object, INFINITE); + } + CloseHandle(dxgi.waitable_object); + dxgi.waitable_object = nullptr; + } + + dxgi.before_destroy_swap_chain_fn(); + + dxgi.swap_chain.Reset(); + + gfx_dxgi_create_swap_chain(dxgi.swap_chain_device.Get(), move(dxgi.before_destroy_swap_chain_fn)); + + dxgi.frame_timestamp = 0; + dxgi.frame_stats.clear(); + dxgi.pending_frame_stats.clear(); + + return; // Make sure we don't wait a second time on the waitable object, since that would hang the program + } else if (dxgi.applied_maximum_frame_latency != dxgi.maximum_frame_latency) { + apply_maximum_frame_latency(false); + } + if (!dxgi.dropped_frame) { if (dxgi.waitable_object != nullptr) { WaitForSingleObject(dxgi.waitable_object, INFINITE); @@ -554,8 +597,20 @@ static double gfx_dxgi_get_time(void) { return (double)(t.QuadPart - dxgi.qpc_init) / dxgi.qpc_freq; } -static void gfx_dxgi_set_frame_divisor(int divisor) { - dxgi.frame_divisor = divisor; +static void gfx_dxgi_set_target_fps(int fps) { + uint32_t old_fps = dxgi.target_fps; + uint64_t t0 = dxgi.frame_timestamp / old_fps; + uint32_t t1 = dxgi.frame_timestamp % old_fps; + dxgi.target_fps = fps; + dxgi.frame_timestamp = t0 * dxgi.target_fps + t1 * dxgi.target_fps / old_fps; +} + +static void gfx_dxgi_set_maximum_frame_latency(int latency) { + dxgi.maximum_frame_latency = latency; +} + +static float gfx_dxgi_get_detected_hz() { + return dxgi.detected_hz; } void gfx_dxgi_create_factory_and_device(bool debug, int d3d_version, bool (*create_device_fn)(IDXGIAdapter1 *adapter, bool test_only)) { @@ -592,12 +647,12 @@ void gfx_dxgi_create_factory_and_device(bool debug, int d3d_version, bool (*crea SetWindowTextW(dxgi.h_wnd, w_title); } -ComPtr gfx_dxgi_create_swap_chain(IUnknown *device) { +void gfx_dxgi_create_swap_chain(IUnknown *device, std::function&& before_destroy_fn) { bool win8 = IsWindows8OrGreater(); // DXGI_SCALING_NONE is only supported on Win8 and beyond bool dxgi_13 = dxgi.CreateDXGIFactory2 != nullptr; // DXGI 1.3 introduced waitable object DXGI_SWAP_CHAIN_DESC1 swap_chain_desc = {}; - swap_chain_desc.BufferCount = 2; + swap_chain_desc.BufferCount = 3; swap_chain_desc.Width = 0; swap_chain_desc.Height = 0; swap_chain_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; @@ -617,28 +672,24 @@ ComPtr gfx_dxgi_create_swap_chain(IUnknown *device) { }); ThrowIfFailed(dxgi.factory->MakeWindowAssociation(dxgi.h_wnd, DXGI_MWA_NO_ALT_ENTER)); - ComPtr swap_chain2; - if (dxgi.swap_chain->QueryInterface(__uuidof(IDXGISwapChain2), &swap_chain2) == S_OK) { - ThrowIfFailed(swap_chain2->SetMaximumFrameLatency(1)); - dxgi.waitable_object = swap_chain2->GetFrameLatencyWaitableObject(); - WaitForSingleObject(dxgi.waitable_object, INFINITE); - } else { - ComPtr device1; - ThrowIfFailed(device->QueryInterface(IID_PPV_ARGS(&device1))); - ThrowIfFailed(device1->SetMaximumFrameLatency(1)); - } + apply_maximum_frame_latency(true); ThrowIfFailed(dxgi.swap_chain->GetDesc1(&swap_chain_desc)); dxgi.current_width = swap_chain_desc.Width; dxgi.current_height = swap_chain_desc.Height; - return dxgi.swap_chain; + dxgi.swap_chain_device = device; + dxgi.before_destroy_swap_chain_fn = std::move(before_destroy_fn); } HWND gfx_dxgi_get_h_wnd(void) { return dxgi.h_wnd; } +IDXGISwapChain1* gfx_dxgi_get_swap_chain() { + return dxgi.swap_chain.Get(); +} + void ThrowIfFailed(HRESULT res) { if (FAILED(res)) { fprintf(stderr, "Error: 0x%08X\n", res); @@ -668,7 +719,9 @@ extern "C" struct GfxWindowManagerAPI gfx_dxgi_api = { gfx_dxgi_swap_buffers_begin, gfx_dxgi_swap_buffers_end, gfx_dxgi_get_time, - gfx_dxgi_set_frame_divisor, + gfx_dxgi_set_target_fps, + gfx_dxgi_set_maximum_frame_latency, + gfx_dxgi_get_detected_hz, }; #endif diff --git a/libultraship/libultraship/Lib/Fast3D/gfx_dxgi.h b/libultraship/libultraship/Lib/Fast3D/gfx_dxgi.h index d590daa66..134ebed64 100644 --- a/libultraship/libultraship/Lib/Fast3D/gfx_dxgi.h +++ b/libultraship/libultraship/Lib/Fast3D/gfx_dxgi.h @@ -4,9 +4,15 @@ #include "gfx_rendering_api.h" #ifdef DECLARE_GFX_DXGI_FUNCTIONS + +#include + +#include + void gfx_dxgi_create_factory_and_device(bool debug, int d3d_version, bool (*create_device_fn)(IDXGIAdapter1 *adapter, bool test_only)); -Microsoft::WRL::ComPtr gfx_dxgi_create_swap_chain(IUnknown *device); +void gfx_dxgi_create_swap_chain(IUnknown *device, std::function&& before_destroy_fn); HWND gfx_dxgi_get_h_wnd(void); +IDXGISwapChain1* gfx_dxgi_get_swap_chain(); void ThrowIfFailed(HRESULT res); void ThrowIfFailed(HRESULT res, HWND h_wnd, const char *message); #endif diff --git a/libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp b/libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp index 98bab7f78..452b511d8 100644 --- a/libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp +++ b/libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp @@ -2789,6 +2789,9 @@ void gfx_run(Gfx *commands, const std::unordered_map& mtx_replaceme gfx_rapi->start_frame(); gfx_rapi->start_draw_to_framebuffer(game_renders_to_framebuffer ? game_framebuffer : 0, (float)gfx_current_dimensions.height / SCREEN_HEIGHT); gfx_rapi->clear_framebuffer(); + rdp.viewport_or_scissor_changed = true; + rendering_state.viewport = {}; + rendering_state.scissor = {}; gfx_run_dl(commands); gfx_flush(); SohUtils::saveEnvironmentVar("framebuffer", string()); @@ -2825,8 +2828,16 @@ void gfx_end_frame(void) { } } -void gfx_set_framedivisor(int divisor) { - gfx_wapi->set_frame_divisor(divisor); +void gfx_set_target_fps(int fps) { + gfx_wapi->set_target_fps(fps); +} + +void gfx_set_maximum_frame_latency(int latency) { + gfx_wapi->set_maximum_frame_latency(latency); +} + +float gfx_get_detected_hz(void) { + return gfx_wapi->get_detected_hz(); } int gfx_create_framebuffer(uint32_t width, uint32_t height) { diff --git a/libultraship/libultraship/Lib/Fast3D/gfx_pc.h b/libultraship/libultraship/Lib/Fast3D/gfx_pc.h index 2ecb68898..65a6b57ba 100644 --- a/libultraship/libultraship/Lib/Fast3D/gfx_pc.h +++ b/libultraship/libultraship/Lib/Fast3D/gfx_pc.h @@ -67,7 +67,9 @@ struct GfxRenderingAPI* gfx_get_current_rendering_api(void); void gfx_start_frame(void); void gfx_run(Gfx* commands, const std::unordered_map& mtx_replacements); void gfx_end_frame(void); -void gfx_set_framedivisor(int); +void gfx_set_target_fps(int); +void gfx_set_maximum_frame_latency(int latency); +float gfx_get_detected_hz(void); void gfx_texture_cache_clear(); extern "C" int gfx_create_framebuffer(uint32_t width, uint32_t height); void gfx_get_pixel_depth_prepare(float x, float y); diff --git a/libultraship/libultraship/Lib/Fast3D/gfx_sdl2.cpp b/libultraship/libultraship/Lib/Fast3D/gfx_sdl2.cpp index e80097c81..94c3ef5ca 100644 --- a/libultraship/libultraship/Lib/Fast3D/gfx_sdl2.cpp +++ b/libultraship/libultraship/Lib/Fast3D/gfx_sdl2.cpp @@ -123,11 +123,10 @@ static uint64_t previous_time; static HANDLE timer; #endif -static int frameDivisor = 1; +static int target_fps = 60; -#define FRAME_INTERVAL_US_NUMERATOR_ 50000 -#define FRAME_INTERVAL_US_DENOMINATOR 3 -#define FRAME_INTERVAL_US_NUMERATOR (FRAME_INTERVAL_US_NUMERATOR_ * frameDivisor) +#define FRAME_INTERVAL_US_NUMERATOR 1000000 +#define FRAME_INTERVAL_US_DENOMINATOR (target_fps) static void gfx_sdl_init(const char *game_name, bool start_in_fullscreen) { SDL_Init(SDL_INIT_VIDEO); @@ -266,15 +265,16 @@ static uint64_t qpc_to_100ns(uint64_t qpc) { static inline void sync_framerate_with_timer(void) { uint64_t t; - t = SDL_GetPerformanceCounter(); + t = qpc_to_100ns(SDL_GetPerformanceCounter()); - const int64_t next = qpc_to_100ns(previous_time) + 10 * FRAME_INTERVAL_US_NUMERATOR / FRAME_INTERVAL_US_DENOMINATOR; - const int64_t left = next - qpc_to_100ns(t); + const int64_t next = previous_time + 10 * FRAME_INTERVAL_US_NUMERATOR / FRAME_INTERVAL_US_DENOMINATOR; + const int64_t left = next - t; if (left > 0) { #ifdef __linux__ const timespec spec = { 0, left * 100 }; nanosleep(&spec, nullptr); #else + // The accuracy of this timer seems to usually be within +- 1.0 ms LARGE_INTEGER li; li.QuadPart = -left; SetWaitableTimer(timer, &li, 0, nullptr, nullptr, false); @@ -282,7 +282,13 @@ static inline void sync_framerate_with_timer(void) { #endif } - t = SDL_GetPerformanceCounter(); + t = qpc_to_100ns(SDL_GetPerformanceCounter()); + if (left > 0 && t - next < 10000) { + // In case it takes some time for the application to wake up after sleep, + // or inaccurate timer, + // don't let that slow down the framerate. + t = next; + } previous_time = t; } @@ -299,9 +305,16 @@ static double gfx_sdl_get_time(void) { return 0.0; } -static void gfx_sdl_set_framedivisor(int divisor) -{ - frameDivisor = divisor; +static void gfx_sdl_set_target_fps(int fps) { + target_fps = fps; +} + +static void gfx_sdl_set_maximum_frame_latency(int latency) { + // Not supported by SDL :( +} + +static float gfx_sdl_get_detected_hz(void) { + return 0; } struct GfxWindowManagerAPI gfx_sdl = { @@ -317,7 +330,9 @@ struct GfxWindowManagerAPI gfx_sdl = { gfx_sdl_swap_buffers_begin, gfx_sdl_swap_buffers_end, gfx_sdl_get_time, - gfx_sdl_set_framedivisor + gfx_sdl_set_target_fps, + gfx_sdl_set_maximum_frame_latency, + gfx_sdl_get_detected_hz }; #endif diff --git a/libultraship/libultraship/Lib/Fast3D/gfx_window_manager_api.h b/libultraship/libultraship/Lib/Fast3D/gfx_window_manager_api.h index 5d7442390..bd45ccdf4 100644 --- a/libultraship/libultraship/Lib/Fast3D/gfx_window_manager_api.h +++ b/libultraship/libultraship/Lib/Fast3D/gfx_window_manager_api.h @@ -17,7 +17,9 @@ struct GfxWindowManagerAPI { void (*swap_buffers_begin)(void); void (*swap_buffers_end)(void); double (*get_time)(void); // For debug - void (*set_frame_divisor)(int); + void (*set_target_fps)(int fps); + void (*set_maximum_frame_latency)(int latency); + float (*get_detected_hz)(void); }; #endif diff --git a/libultraship/libultraship/SohImGuiImpl.cpp b/libultraship/libultraship/SohImGuiImpl.cpp index 2a897437f..35643838f 100644 --- a/libultraship/libultraship/SohImGuiImpl.cpp +++ b/libultraship/libultraship/SohImGuiImpl.cpp @@ -680,6 +680,34 @@ namespace SohImGui { Tooltip("Activates anti-aliasing when above 1, up to 8x for 8 samples for every pixel"); gfx_msaa_level = CVar_GetS32("gMSAAValue", 1); + if (impl.backend == Backend::DX11) + { + const char* cvar = "gExtraLatencyThreshold"; + int val = CVar_GetS32(cvar, 80); + val = MAX(MIN(val, 250), 0); + int fps = val; + + if (fps == 0) + { + ImGui::Text("Jitter fix: Off"); + } + else + { + ImGui::Text("Jitter fix: >= %d FPS", fps); + } + + if (ImGui::SliderInt("##ExtraLatencyThreshold", &val, 0, 250, "", ImGuiSliderFlags_AlwaysClamp)) + { + CVar_SetS32(cvar, val); + needs_save = true; + } + + Tooltip("When Interpolation FPS setting is at least this threshold,\n" + "add one frame of input lag (e.g. 16.6 ms for 60 FPS) in order to avoid jitter.\n" + "This setting allows the CPU to work on one frame while GPU works on the previous frame.\n" + "This setting should be used when your computer is too slow to do CPU + GPU work in time."); + } + EXPERIMENTAL(); ImGui::Text("Texture Filter (Needs reload)"); GfxRenderingAPI* gapi = gfx_get_current_rendering_api(); @@ -764,7 +792,46 @@ namespace SohImGui { EXPERIMENTAL(); - EnhancementCheckbox("60FPS Interpolation", "g60FPS"); + const char* fps_cvar = "gInterpolationFPS"; + { + int val = CVar_GetS32(fps_cvar, 20); + val = MAX(MIN(val, 250), 20); + int fps = val; + + if (fps == 20) + { + ImGui::Text("Frame interpolation: Off"); + } + else + { + ImGui::Text("Frame interpolation: %d FPS", fps); + } + + if (ImGui::SliderInt("##FPSInterpolation", &val, 20, 250, "", ImGuiSliderFlags_AlwaysClamp)) + { + CVar_SetS32(fps_cvar, val); + needs_save = true; + } + + Tooltip("Interpolate extra frames to get smoother graphics.\n" + "Set to match your monitor's refresh rate, or a divisor of it.\n" + "A higher target FPS than your monitor's refresh rate will just waste resources,\n" + "and might give a worse result.\n" + "For consistent input lag, set this value and your monitor's refresh rate to a multiple of 20.\n" + "Ctrl+Click for keyboard input."); + } + if (impl.backend == Backend::DX11) + { + if (ImGui::Button("Match Refresh Rate")) + { + int hz = roundf(gfx_get_detected_hz()); + if (hz >= 20 && hz <= 250) + { + CVar_SetS32(fps_cvar, hz); + needs_save = true; + } + } + } EnhancementCheckbox("Disable LOD", "gDisableLOD"); Tooltip("Turns off the level of detail setting, making models always use their higher poly variants"); diff --git a/libultraship/libultraship/Window.cpp b/libultraship/libultraship/Window.cpp index 5c2cf3cae..8319332ad 100644 --- a/libultraship/libultraship/Window.cpp +++ b/libultraship/libultraship/Window.cpp @@ -272,13 +272,14 @@ namespace Ship { gfx_run(Commands, m); gfx_end_frame(); } - gfx_run(Commands, {}); - gfx_end_frame(); } - void Window::SetFrameDivisor(int divisor) { - gfx_set_framedivisor(divisor); - //gfx_set_framedivisor(0); + void Window::SetTargetFps(int fps) { + gfx_set_target_fps(fps); + } + + void Window::SetMaximumFrameLatency(int latency) { + gfx_set_maximum_frame_latency(latency); } void Window::GetPixelDepthPrepare(float x, float y) { diff --git a/libultraship/libultraship/Window.h b/libultraship/libultraship/Window.h index 04886c53e..a3087bf0c 100644 --- a/libultraship/libultraship/Window.h +++ b/libultraship/libultraship/Window.h @@ -20,7 +20,8 @@ namespace Ship { void Init(); void StartFrame(); void RunCommands(Gfx* Commands, const std::vector>& mtx_replacements); - void SetFrameDivisor(int divisor); + void SetTargetFps(int fps); + void SetMaximumFrameLatency(int latency); void GetPixelDepthPrepare(float x, float y); uint16_t GetPixelDepth(float x, float y); void ToggleFullscreen(); diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index e8e1b31c1..9401d514a 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -175,8 +175,6 @@ extern "C" void Graph_StartFrame() { // C->C++ Bridge extern "C" void Graph_ProcessGfxCommands(Gfx* commands) { - OTRGlobals::Instance->context->GetWindow()->SetFrameDivisor(CVar_GetS32("g60FPS", 0) == 0 ? R_UPDATE_RATE : 1); - if (!audio.initialized) { audio.initialized = true; std::thread([]() { @@ -226,15 +224,45 @@ extern "C" void Graph_ProcessGfxCommands(Gfx* commands) { audio.cv_to_thread.notify_one(); std::vector> mtx_replacements; - if (CVar_GetS32("g60FPS", 0) != 0) { - int to = R_UPDATE_RATE; - for (int i = 1; i < to; i++) { - mtx_replacements.push_back(FrameInterpolation_Interpolate(i / (float)to)); + int target_fps = CVar_GetS32("gInterpolationFPS", 20); + static int last_fps; + static int last_update_rate; + static int time; + int fps = target_fps; + int original_fps = 60 / R_UPDATE_RATE; + + if (target_fps == 20 || original_fps > target_fps) { + fps = original_fps; + } + + if (last_fps != fps || last_update_rate != R_UPDATE_RATE) { + time = 0; + } + + // time_base = fps * original_fps (one second) + int next_original_frame = fps; + + while (time + original_fps <= next_original_frame) { + time += original_fps; + if (time != next_original_frame) { + mtx_replacements.push_back(FrameInterpolation_Interpolate((float)time / next_original_frame)); + } else { + mtx_replacements.emplace_back(); } } + time -= fps; + + OTRGlobals::Instance->context->GetWindow()->SetTargetFps(fps); + + int threshold = CVar_GetS32("gExtraLatencyThreshold", 80); + OTRGlobals::Instance->context->GetWindow()->SetMaximumFrameLatency(threshold > 0 && target_fps >= threshold ? 2 : 1); + OTRGlobals::Instance->context->GetWindow()->RunCommands(commands, mtx_replacements); + last_fps = fps; + last_update_rate = R_UPDATE_RATE; + { std::unique_lock Lock(audio.mutex); while (audio.processing) { diff --git a/soh/soh/frame_interpolation.cpp b/soh/soh/frame_interpolation.cpp index bd85d41ce..44c255db1 100644 --- a/soh/soh/frame_interpolation.cpp +++ b/soh/soh/frame_interpolation.cpp @@ -451,7 +451,7 @@ void FrameInterpolation_StartRecord(void) { current_recording = {}; current_path.clear(); current_path.push_back(¤t_recording.root_path); - if (CVar_GetS32("g60FPS", 0) != 0) { + if (CVar_GetS32("gInterpolationFPS", 20) != 20) { is_recording = true; } } diff --git a/soh/src/code/z_actor.c b/soh/src/code/z_actor.c index ba5d4dcd6..bdb2fe78c 100644 --- a/soh/src/code/z_actor.c +++ b/soh/src/code/z_actor.c @@ -2290,8 +2290,8 @@ void Actor_DrawFaroresWindPointer(GlobalContext* globalCtx) { ((void)0, gSaveContext.respawn[RESPAWN_MODE_TOP].pos.y) + yOffset, ((void)0, gSaveContext.respawn[RESPAWN_MODE_TOP].pos.z), 255, 255, 255, lightRadius); - CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_actor.c", 5474); } + CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_actor.c", 5474); } void func_80030488(GlobalContext* globalCtx) { diff --git a/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c b/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c index 570eedd1f..03a93e949 100644 --- a/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c +++ b/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c @@ -5,6 +5,8 @@ #include "textures/title_static/title_static.h" #include "textures/parameter_static/parameter_static.h" +#include "soh/frame_interpolation.h" + static s16 sUnused = 106; static s16 sScreenFillAlpha = 255; @@ -1136,6 +1138,8 @@ void FileChoose_ConfigModeDraw(GameState* thisx) { FileChoose_SetWindowVtx(&this->state); FileChoose_SetWindowContentVtx(&this->state); + FrameInterpolation_RecordOpenChild(this, this->configMode); + if ((this->configMode != CM_NAME_ENTRY) && (this->configMode != CM_START_NAME_ENTRY)) { gDPPipeSync(POLY_OPA_DISP++); gDPSetCombineMode(POLY_OPA_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM); @@ -1227,6 +1231,8 @@ void FileChoose_ConfigModeDraw(GameState* thisx) { gDPPipeSync(POLY_OPA_DISP++); FileChoose_SetView(this, 0.0f, 0.0f, 64.0f); + FrameInterpolation_RecordCloseChild(); + CLOSE_DISPS(this->state.gfxCtx, "../z_file_choose.c", 2352); } @@ -1669,7 +1675,9 @@ void FileChoose_Main(GameState* thisx) { FileChoose_PulsateCursor(&this->state); gFileSelectUpdateFuncs[this->menuMode](&this->state); + FrameInterpolation_StartRecord(); gFileSelectDrawFuncs[this->menuMode](&this->state); + FrameInterpolation_StopRecord(); // do not draw controls text in the options menu if ((this->configMode <= CM_NAME_ENTRY_TO_MAIN) || (this->configMode >= CM_UNUSED_DELAY)) { From 79133981104e2dedcdce5b941353babfaa55bd45 Mon Sep 17 00:00:00 2001 From: Baoulettes Date: Sun, 29 May 2022 18:57:09 +0200 Subject: [PATCH 27/30] EnhancementColor3 tweak SohImGui Clean (#400) * HUD Logic fix and cleaning * array revert it was just fo rme to read it better * Fix tunic logic seem like my cleaning was not good * I had declared default in CPP It resulted to overwrite what user would make oof. Also a ! was missing. * There, Default here is better. * magic bar and used bar what switched while updating EnhancementColor * hud mod update * Update SohImGuiImpl.h * should fix build --- libultraship/libultraship/SohImGuiImpl.cpp | 393 +++++++++++------- libultraship/libultraship/SohImGuiImpl.h | 13 +- soh/src/code/z_lifemeter.c | 49 ++- soh/src/code/z_player_lib.c | 46 +- .../ovl_kaleido_scope/z_kaleido_scope_PAL.c | 27 ++ 5 files changed, 334 insertions(+), 194 deletions(-) diff --git a/libultraship/libultraship/SohImGuiImpl.cpp b/libultraship/libultraship/SohImGuiImpl.cpp index 35643838f..c91f31750 100644 --- a/libultraship/libultraship/SohImGuiImpl.cpp +++ b/libultraship/libultraship/SohImGuiImpl.cpp @@ -66,29 +66,38 @@ namespace SohImGui { std::vector CustomTexts; int SelectedLanguage = CVar_GetS32("gLanguages", 0); //Default Language to 0=English 1=German 2=French int SelectedHUD = CVar_GetS32("gHudColors", 1); //Default colors to Gamecube. - float hearts_colors[3] = {0,0,0}; - float hearts_dd_colors[3] = {0,0,0}; - float a_btn_colors[3] = {0,0,0}; - float b_btn_colors[3] = {0,0,0}; - float c_btn_colors[3] = {0,0,0}; - float start_btn_colors[3] = {0,0,0}; - float magic_border_colors[3] = {0,0,0}; - float magic_remaining_colors[3] = {0,0,0}; - float magic_use_colors[3] = {0,0,0}; - float minimap_colors[3] = {0,0,0}; - float rupee_colors[3] = {0,0,0}; - float smolekey_colors[3] = {0,0,0}; - float kokiri_col[3] = { 0.118f, 0.41f, 0.106f }; - float goron_col[3] = { 0.392f, 0.078f, 0.0f }; - float zora_col[3] = { 0.0f, 0.235f, 0.392f }; - float navi_idle_i_col[3] = { 0.0f, 0.0f, 0.0f }; - float navi_idle_o_col[3] = { 0.0f, 0.0f, 0.0f }; - float navi_npc_i_col[3] = { 0.0f, 0.0f, 0.0f }; - float navi_npc_o_col[3] = { 0.0f, 0.0f, 0.0f }; - float navi_enemy_i_col[3] = { 0.0f, 0.0f, 0.0f }; - float navi_enemy_o_col[3] = { 0.0f, 0.0f, 0.0f }; - float navi_prop_i_col[3] = { 0.0f, 0.0f, 0.0f }; - float navi_prop_o_col[3] = { 0.0f, 0.0f, 0.0f }; + ImVec4 hearts_colors; + ImVec4 hearts_dd_colors; + ImVec4 a_btn_colors; + ImVec4 b_btn_colors; + ImVec4 c_btn_colors; + ImVec4 start_btn_colors; + ImVec4 magic_border_colors; + ImVec4 magic_remaining_colors; + ImVec4 magic_use_colors; + ImVec4 minimap_colors; + ImVec4 rupee_colors; + ImVec4 smolekey_colors; + ImVec4 kokiri_col; + ImVec4 goron_col; + ImVec4 zora_col; + ImVec4 navi_idle_i_col; + ImVec4 navi_idle_o_col; + ImVec4 navi_npc_i_col; + ImVec4 navi_npc_o_col; + ImVec4 navi_enemy_i_col; + ImVec4 navi_enemy_o_col; + ImVec4 navi_prop_i_col; + ImVec4 navi_prop_o_col; + + const char* RainbowColorCvarList[] = { + //This is the list of possible CVars that has rainbow effect. + "gTunic_Kokiri_","gTunic_Goron_","gTunic_Zora_", + "gCCHeartsPrim","gDDCCHeartsPrim", + "gCCABtnPrim","gCCBBtnPrim","gCCCBtnPrim","gCCStartBtnPrim", + "gCCMagicBorderPrim","gCCMagicPrim","gCCMagicUsePrim", + "gCCMinimapPrim","gCCRupeePrim","gCCKeysPrim" + }; const char* filters[3] = { "Three-Point", @@ -99,6 +108,15 @@ namespace SohImGui { std::map> windowCategories; std::map customWindows; + int ClampFloatToInt(float value, int min, int max){ + return fmin(fmax(value,min),max); + } + + void Tooltip(const char* text) { + if (ImGui::IsItemHovered()) + ImGui::SetTooltip("%s", text); + } + void ImGuiWMInit() { switch (impl.backend) { case Backend::SDL: @@ -240,82 +258,64 @@ namespace SohImGui { stbi_image_free(img_data); } - void LoadInterfaceEditor(){//This function is necessary as without it IMGui wont load the updated float array. - hearts_colors[0] = (float)CVar_GetS32("gCCHeartsPrimR", 255)/255; - hearts_colors[1] = (float)CVar_GetS32("gCCHeartsPrimG", 70)/255; - hearts_colors[2] = (float)CVar_GetS32("gCCHeartsPrimB", 50)/255; - hearts_dd_colors[0] = (float)CVar_GetS32("gDDCCHeartsPrimR", 255)/255; - hearts_dd_colors[1] = (float)CVar_GetS32("gDDCCHeartsPrimG", 255)/255; - hearts_dd_colors[2] = (float)CVar_GetS32("gDDCCHeartsPrimB", 255)/255; - a_btn_colors[0] = (float)CVar_GetS32("gCCABtnPrimR", 90)/255; - a_btn_colors[1] = (float)CVar_GetS32("gCCABtnPrimG", 90)/255; - a_btn_colors[2] = (float)CVar_GetS32("gCCABtnPrimB", 255)/255; - b_btn_colors[0] = (float)CVar_GetS32("gCCBBtnPrimR", 0)/255; - b_btn_colors[1] = (float)CVar_GetS32("gCCBBtnPrimG", 150)/255; - b_btn_colors[2] = (float)CVar_GetS32("gCCBBtnPrimB", 0)/255; - c_btn_colors[0] = (float)CVar_GetS32("gCCCBtnPrimR", 255)/255; - c_btn_colors[1] = (float)CVar_GetS32("gCCCBtnPrimG", 160)/255; - c_btn_colors[2] = (float)CVar_GetS32("gCCCBtnPrimB", 0)/255; - start_btn_colors[0] = (float)CVar_GetS32("gCCStartBtnPrimR", 120)/255; - start_btn_colors[1] = (float)CVar_GetS32("gCCStartBtnPrimG", 120)/255; - start_btn_colors[2] = (float)CVar_GetS32("gCCStartBtnPrimB", 120)/255; - magic_border_colors[0] = (float)CVar_GetS32("gCCMagicBorderPrimR", 255)/255; - magic_border_colors[1] = (float)CVar_GetS32("gCCMagicBorderPrimG", 255)/255; - magic_border_colors[2] = (float)CVar_GetS32("gCCMagicBorderPrimB", 255)/255; - magic_use_colors[0] = (float)CVar_GetS32("gCCMagicPrimR", 250)/255; - magic_use_colors[1] = (float)CVar_GetS32("gCCMagicPrimG", 250)/255; - magic_use_colors[2] = (float)CVar_GetS32("gCCMagicPrimB", 0)/255; - magic_remaining_colors[0] = (float)CVar_GetS32("gCCMagicUsePrimR", 0)/255; - magic_remaining_colors[1] = (float)CVar_GetS32("gCCMagicUsePrimG", 200)/255; - magic_remaining_colors[2] = (float)CVar_GetS32("gCCMagicUsePrimB", 0)/255; - minimap_colors[0] = (float)CVar_GetS32("gCCMinimapPrimR", 0)/255; - minimap_colors[1] = (float)CVar_GetS32("gCCMinimapPrimG", 255)/255; - minimap_colors[2] = (float)CVar_GetS32("gCCMinimapPrimB", 255)/255; - rupee_colors[0] = (float)CVar_GetS32("gCCRupeePrimR", 200)/255; - rupee_colors[1] = (float)CVar_GetS32("gCCRupeePrimG", 255)/255; - rupee_colors[2] = (float)CVar_GetS32("gCCRupeePrimB", 100)/255; - smolekey_colors[0] = (float)CVar_GetS32("gCCKeysPrimR", 200)/255; - smolekey_colors[1] = (float)CVar_GetS32("gCCKeysPrimG", 230)/255; - smolekey_colors[2] = (float)CVar_GetS32("gCCKeysPrimB", 255)/255; - kokiri_col[0] = (float)CVar_GetS32("gTunic_Kokiri_R", 30)/255; - kokiri_col[1] = (float)CVar_GetS32("gTunic_Kokiri_G", 105)/255; - kokiri_col[2] = (float)CVar_GetS32("gTunic_Kokiri_B", 27)/255; - goron_col[0] = (float)CVar_GetS32("gTunic_Goron_R", 100)/255; - goron_col[1] = (float)CVar_GetS32("gTunic_Goron_G", 20)/255; - goron_col[2] = (float)CVar_GetS32("gTunic_Goron_B", 0)/255; - zora_col[0] = (float)CVar_GetS32("gTunic_Zora_R", 0)/255; - zora_col[1] = (float)CVar_GetS32("gTunic_Zora_G", 60)/255; - zora_col[2] = (float)CVar_GetS32("gTunic_Zora_B", 100)/255; - navi_idle_i_col[0] = (float)CVar_GetS32("gNavi_Idle_Inner_R", 255)/255; - navi_idle_i_col[1] = (float)CVar_GetS32("gNavi_Idle_Inner_G", 255)/255; - navi_idle_i_col[2] = (float)CVar_GetS32("gNavi_Idle_Inner_B", 255)/255; - navi_idle_o_col[0] = (float)CVar_GetS32("gNavi_Idle_Outer_R", 115)/255; - navi_idle_o_col[1] = (float)CVar_GetS32("gNavi_Idle_Outer_G", 230)/255; - navi_idle_o_col[2] = (float)CVar_GetS32("gNavi_Idle_Outer_B", 255)/255; - navi_npc_i_col[0] = (float)CVar_GetS32("gNavi_NPC_Inner_R", 100)/255; - navi_npc_i_col[1] = (float)CVar_GetS32("gNavi_NPC_Inner_G", 100)/255; - navi_npc_i_col[2] = (float)CVar_GetS32("gNavi_NPC_Inner_B", 255)/255; - navi_npc_o_col[0] = (float)CVar_GetS32("gNavi_NPC_Outer_R", 90)/255; - navi_npc_o_col[1] = (float)CVar_GetS32("gNavi_NPC_Outer_G", 90)/255; - navi_npc_o_col[2] = (float)CVar_GetS32("gNavi_NPC_Outer_B", 255)/255; - navi_enemy_i_col[0] = (float)CVar_GetS32("gNavi_Enemy_Inner_R", 255)/255; - navi_enemy_i_col[1] = (float)CVar_GetS32("gNavi_Enemy_Inner_G", 255)/255; - navi_enemy_i_col[2] = (float)CVar_GetS32("gNavi_Enemy_Inner_B", 0)/255; - navi_enemy_o_col[0] = (float)CVar_GetS32("gNavi_Enemy_Outer_R", 220)/255; - navi_enemy_o_col[1] = (float)CVar_GetS32("gNavi_Enemy_Outer_G", 220)/255; - navi_enemy_o_col[2] = (float)CVar_GetS32("gNavi_Enemy_Outer_B", 0)/255; - navi_prop_i_col[0] = (float)CVar_GetS32("gNavi_Prop_Inner_R", 0)/255; - navi_prop_i_col[1] = (float)CVar_GetS32("gNavi_Prop_Inner_G", 255)/255; - navi_prop_i_col[2] = (float)CVar_GetS32("gNavi_Prop_Inner_B", 0)/255; - navi_prop_o_col[0] = (float)CVar_GetS32("gNavi_Prop_Outer_R", 0)/255; - navi_prop_o_col[1] = (float)CVar_GetS32("gNavi_Prop_Outer_G", 220)/255; - navi_prop_o_col[2] = (float)CVar_GetS32("gNavi_Prop_Outer_B", 0)/255; - if (CVar_GetS32("gHudColors", 1) ==0) { - SelectedHUD = 0; - } else if (CVar_GetS32("gHudColors", 1) == 1) { - SelectedHUD = 1; - } else if (CVar_GetS32("gHudColors", 1) == 2) { - SelectedHUD = 2; + void LoadRainbowColor() { + for (uint16_t s=0; s <= sizeof(RainbowColorCvarList); s++) { + std::string cvarName = RainbowColorCvarList[s]; + std::string Cvar_Red = cvarName; + Cvar_Red += "R"; + std::string Cvar_Green = cvarName; + Cvar_Green += "G"; + std::string Cvar_Blue = cvarName; + Cvar_Blue += "B"; + std::string Cvar_RBM = cvarName; + Cvar_RBM += "RBM"; + std::string RBM_HUE = cvarName; + RBM_HUE+="Hue"; + f32 Canon = 10.f*s; + ImVec4 NewColor; + const f32 deltaTime = 1.0f / ImGui::GetIO().Framerate; + f32 hue = CVar_GetFloat(RBM_HUE.c_str(), 0.0f); + f32 newHue = hue + CVar_GetS32("gColorRainbowSpeed", 1) * 36.0f * deltaTime; + if (newHue >= 360) + newHue = 0; + CVar_SetFloat(RBM_HUE.c_str(), newHue); + f32 current_hue = CVar_GetFloat(RBM_HUE.c_str(), 0); + u8 i = current_hue / 60 + 1; + u8 a = (-current_hue / 60.0f + i) * 255; + u8 b = (current_hue / 60.0f + (1 - i)) * 255; + + switch (i) { + case 1: NewColor.x = 255; NewColor.y = b; NewColor.z = 0; break; + case 2: NewColor.x = a; NewColor.y = 255; NewColor.z = 0; break; + case 3: NewColor.x = 0; NewColor.y = 255; NewColor.z = b; break; + case 4: NewColor.x = 0; NewColor.y = a; NewColor.z = 255; break; + case 5: NewColor.x = b; NewColor.y = 0; NewColor.z = 255; break; + case 6: NewColor.x = 255; NewColor.y = 0; NewColor.z = a; break; + } + + if(CVar_GetS32(Cvar_RBM.c_str(), 0) != 0) { + CVar_SetS32(Cvar_Red.c_str(), ClampFloatToInt(NewColor.x,0,255)); + CVar_SetS32(Cvar_Green.c_str(), ClampFloatToInt(NewColor.y,0,255)); + CVar_SetS32(Cvar_Blue.c_str(), ClampFloatToInt(NewColor.z,0,255)); + } + } + } + + void LoadPickersColors(ImVec4& ColorArray, const char* cvarname, const ImVec4& default_colors, bool has_alpha) { + std::string Cvar_Red = cvarname; + Cvar_Red += "R"; + std::string Cvar_Green = cvarname; + Cvar_Green += "G"; + std::string Cvar_Blue = cvarname; + Cvar_Blue += "B"; + std::string Cvar_Alpha = cvarname; + Cvar_Alpha += "A"; + + ColorArray.x = (float)CVar_GetS32(Cvar_Red.c_str(), default_colors.x)/255; + ColorArray.y = (float)CVar_GetS32(Cvar_Green.c_str(), default_colors.y)/255; + ColorArray.z = (float)CVar_GetS32(Cvar_Blue.c_str(), default_colors.z)/255; + if (has_alpha) { + ColorArray.w = (float)CVar_GetS32(Cvar_Alpha.c_str(), default_colors.w)/255; } } @@ -530,31 +530,123 @@ namespace SohImGui { } } - int ClampFloatToInt(float value, int min, int max) { - return fmin(fmax(value, min), max); + void RandomizeColor(const char* cvarName, ImVec4* colors) { + std::string Cvar_Red = cvarName; + Cvar_Red += "R"; + std::string Cvar_Green = cvarName; + Cvar_Green += "G"; + std::string Cvar_Blue = cvarName; + Cvar_Blue += "B"; + std::string Cvar_RBM = cvarName; + Cvar_RBM += "RBM"; + std::string MakeInvisible = "##"; + MakeInvisible += cvarName; + MakeInvisible += "Random"; + std::string FullName = "Random"; + FullName+=MakeInvisible; + if (ImGui::Button(FullName.c_str())) { + s16 RND_R = rand() % (255 - 0); + s16 RND_G = rand() % (255 - 0); + s16 RND_B = rand() % (255 - 0); + colors->x = (float)RND_R/255; + colors->y = (float)RND_G/255; + colors->z = (float)RND_B/255; + CVar_SetS32(Cvar_Red.c_str(), ClampFloatToInt(colors->x*255,0,255)); + CVar_SetS32(Cvar_Green.c_str(), ClampFloatToInt(colors->y*255,0,255)); + CVar_SetS32(Cvar_Blue.c_str(), ClampFloatToInt(colors->z*255,0,255)); + CVar_SetS32(Cvar_RBM.c_str(), 0); //On click disable rainbow mode. + needs_save = true; + } + Tooltip("Clicking this button will make a random color for the colors at it's right.\nPrevious color will be overwrite and will not be recoverable"); } - void EnhancementColor3(const char* text, const char* cvarName, float ColorRGB[3], bool TitleSameLine) { - //Simplified. - std::string cvarNameString(cvarName); + void RainbowColor(const char* cvarName, ImVec4* colors) { + std::string Cvar_RBM = cvarName; + Cvar_RBM += "RBM"; + std::string MakeInvisible = "Rainbow"; + MakeInvisible += "##"; + MakeInvisible += cvarName; + MakeInvisible += "Rainbow"; + + EnhancementCheckbox(MakeInvisible.c_str(), Cvar_RBM.c_str()); + Tooltip("Clicking this button will make color cycling\nPrevious color will be overwrite and will not be recoverable"); + } + + void ResetColor(const char* cvarName, ImVec4* colors, ImVec4 defaultcolors, bool has_alpha) { + std::string Cvar_Red = cvarName; + Cvar_Red += "R"; + std::string Cvar_Green = cvarName; + Cvar_Green += "G"; + std::string Cvar_Blue = cvarName; + Cvar_Blue += "B"; + std::string Cvar_Alpha = cvarName; + Cvar_Alpha += "A"; + std::string Cvar_RBM = cvarName; + Cvar_RBM += "RBM"; + std::string MakeInvisible = "Reset"; + MakeInvisible += "##"; + MakeInvisible += cvarName; + MakeInvisible += "Reset"; + if (ImGui::Button(MakeInvisible.c_str())) { + colors->x = defaultcolors.x/255; + colors->y = defaultcolors.y/255; + colors->z = defaultcolors.z/255; + if (has_alpha) { colors->w = defaultcolors.w/255;}; + CVar_SetS32(Cvar_Red.c_str(), ClampFloatToInt(colors->x*255,0,255)); + CVar_SetS32(Cvar_Green.c_str(), ClampFloatToInt(colors->y*255,0,255)); + CVar_SetS32(Cvar_Blue.c_str(), ClampFloatToInt(colors->z*255,0,255)); + if (has_alpha) { CVar_SetS32(Cvar_Alpha.c_str(), ClampFloatToInt(colors->w*255,0,255)); }; + CVar_SetS32(Cvar_RBM.c_str(), 0); //On click disable rainbow mode. + needs_save = true; + } + Tooltip("Clicking this button will to the game original color (GameCube version)\nPrevious color will be overwrite and will not be recoverable"); + } + + void EnhancementColor(const char* text, const char* cvarName, ImVec4 ColorRGBA, ImVec4 default_colors, bool allow_rainbow, bool has_alpha, bool TitleSameLine) { + std::string Cvar_Red = cvarName; + Cvar_Red += "R"; + std::string Cvar_Green = cvarName; + Cvar_Green += "G"; + std::string Cvar_Blue = cvarName; + Cvar_Blue += "B"; + std::string Cvar_Alpha = cvarName; + Cvar_Alpha += "A"; + std::string Cvar_RBM = cvarName; + Cvar_RBM += "RBM"; + + LoadPickersColors(ColorRGBA, cvarName, default_colors, has_alpha); ImGuiColorEditFlags flags = ImGuiColorEditFlags_None; - if (!TitleSameLine) { + if (!TitleSameLine){ ImGui::Text("%s", text); flags = ImGuiColorEditFlags_NoLabel; } - if (ImGui::ColorEdit3(text, ColorRGB, flags)) { - CVar_SetS32((cvarNameString + "R").c_str(), ClampFloatToInt(ColorRGB[0] * 255, 0, 255)); - CVar_SetS32((cvarNameString + "G").c_str(), ClampFloatToInt(ColorRGB[1] * 255, 0, 255)); - CVar_SetS32((cvarNameString + "B").c_str(), ClampFloatToInt(ColorRGB[2] * 255, 0, 255)); - needs_save = true; + if (!has_alpha) { + if (ImGui::ColorEdit3(text, (float *)&ColorRGBA, flags)) { + CVar_SetS32(Cvar_Red.c_str(), ClampFloatToInt(ColorRGBA.x*255,0,255)); + CVar_SetS32(Cvar_Green.c_str(), ClampFloatToInt(ColorRGBA.y*255,0,255)); + CVar_SetS32(Cvar_Blue.c_str(), ClampFloatToInt(ColorRGBA.z*255,0,255)); + needs_save = true; + } + } else { + if (ImGui::ColorEdit4(text, (float *)&ColorRGBA, flags)) { + CVar_SetS32(Cvar_Red.c_str(), ClampFloatToInt(ColorRGBA.x*255,0,255)); + CVar_SetS32(Cvar_Green.c_str(), ClampFloatToInt(ColorRGBA.y*255,0,255)); + CVar_SetS32(Cvar_Blue.c_str(), ClampFloatToInt(ColorRGBA.z*255,0,255)); + CVar_SetS32(Cvar_Alpha.c_str(), ClampFloatToInt(ColorRGBA.w*255,0,255)); + needs_save = true; + } + + } + ImGui::SameLine(); + ResetColor(cvarName, &ColorRGBA, default_colors, has_alpha); + ImGui::SameLine(); + RandomizeColor(cvarName, &ColorRGBA); + if (allow_rainbow) { + //Not all draw support rainbow, like Navi. + ImGui::SameLine(); + RainbowColor(cvarName, &ColorRGBA); } - } - - - void Tooltip(const char* text) { - if (ImGui::IsItemHovered()) - ImGui::SetTooltip("%s", text); } void DrawMainMenuAndCalculateGameSize(void) { @@ -562,7 +654,6 @@ namespace SohImGui { ImGuiBackendNewFrame(); ImGuiWMNewFrame(); ImGui::NewFrame(); - LoadInterfaceEditor(); const std::shared_ptr wnd = GlobalCtx2::GetInstance()->GetWindow(); ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoBackground | @@ -938,36 +1029,36 @@ namespace SohImGui { if (ImGui::BeginTabBar("Cosmetics Editor", ImGuiTabBarFlags_NoCloseWithMiddleMouseButton)) { if (ImGui::BeginTabItem("Navi")) { EnhancementCheckbox("Custom colors for Navi", "gUseNaviCol"); - Tooltip("Enable/Disable custom Navi's colors. \nIf disabled you will have original colors for Navi.\nColors are refreshed when Navi goes back in your pockets"); - EnhancementColor3("Navi Idle Inner", "gNavi_Idle_Inner_", navi_idle_i_col, false); + Tooltip("Enable/Disable custom Navi's colors. \nIf disabled you will have original colors for Navi.\nColors are refreshed when Navi goes back in your pockets."); + EnhancementColor("Navi Idle Inner", "gNavi_Idle_Inner_", navi_idle_i_col, ImVec4(255,255,255,255), false); Tooltip("Inner color for Navi (idle flying around)"); - EnhancementColor3("Navi Idle Outer", "gNavi_Idle_Outer_", navi_idle_o_col, false); + EnhancementColor("Navi Idle Outer", "gNavi_Idle_Outer_", navi_idle_o_col, ImVec4(115,230,255,255), false); Tooltip("Outer color for Navi (idle flying around)"); ImGui::Separator(); - EnhancementColor3("Navi NPC Inner", "gNavi_NPC_Inner_", navi_npc_i_col, false); + EnhancementColor("Navi NPC Inner", "gNavi_NPC_Inner_", navi_npc_i_col, ImVec4(100,100,255,255), false); Tooltip("Inner color for Navi (when Navi fly around NPCs)"); - EnhancementColor3("Navi NPC Outer", "gNavi_NPC_Outer_", navi_npc_o_col, false); + EnhancementColor("Navi NPC Outer", "gNavi_NPC_Outer_", navi_npc_o_col, ImVec4(90,90,255,255), false); Tooltip("Outer color for Navi (when Navi fly around NPCs)"); ImGui::Separator(); - EnhancementColor3("Navi Enemy Inner", "gNavi_Enemy_Inner_", navi_enemy_i_col, false); + EnhancementColor("Navi Enemy Inner", "gNavi_Enemy_Inner_", navi_enemy_i_col, ImVec4(255,255,0,255), false); Tooltip("Inner color for Navi (when Navi fly around Enemies or Bosses)"); - EnhancementColor3("Navi Enemy Outer", "gNavi_Enemy_Outer_", navi_enemy_o_col, false); + EnhancementColor("Navi Enemy Outer", "gNavi_Enemy_Outer_", navi_enemy_o_col, ImVec4(220,220,0,255), false); Tooltip("Outer color for Navi (when Navi fly around Enemies or Bosses)"); ImGui::Separator(); - EnhancementColor3("Navi Prop Inner", "gNavi_Prop_Inner_", navi_prop_i_col, false); + EnhancementColor("Navi Prop Inner", "gNavi_Prop_Inner_", navi_prop_i_col, ImVec4(0,255,0,255), false); Tooltip("Inner color for Navi (when Navi fly around props (signs etc))"); - EnhancementColor3("Navi Prop Outer", "gNavi_Prop_Outer_", navi_prop_o_col, false); + EnhancementColor("Navi Prop Outer", "gNavi_Prop_Outer_", navi_prop_o_col, ImVec4(0,220,0,255), false); Tooltip("Outer color for Navi (when Navi fly around props (signs etc))"); ImGui::EndTabItem(); } if (ImGui::BeginTabItem("Tunics")) { EnhancementCheckbox("Custom colors on tunics", "gUseTunicsCol"); - Tooltip("Enable/Disable custom Link's tunics colors. \nIf disabled you will have original colors for Link's tunics"); - EnhancementColor3("Kokiri Tunic", "gTunic_Kokiri_", kokiri_col, false); + Tooltip("Enable/Disable custom Link's tunics colors. \nIf disabled you will have original colors for Link's tunics."); + EnhancementColor("Kokiri Tunic", "gTunic_Kokiri_", kokiri_col, ImVec4(30,105,27,255)); ImGui::Separator(); - EnhancementColor3("Goron Tunic", "gTunic_Goron_", goron_col, false); + EnhancementColor("Goron Tunic", "gTunic_Goron_", goron_col, ImVec4(100,20,0,255)); ImGui::Separator(); - EnhancementColor3("Zora Tunic", "gTunic_Zora_", zora_col, false); + EnhancementColor("Zora Tunic", "gTunic_Zora_", zora_col, ImVec4(0,60,100,255)); ImGui::EndTabItem(); } ImGui::EndTabBar(); @@ -983,39 +1074,39 @@ namespace SohImGui { ImGui::Begin("Interface Editor", nullptr, ImGuiWindowFlags_NoFocusOnAppearing); if (ImGui::BeginTabBar("Interface Editor", ImGuiTabBarFlags_NoCloseWithMiddleMouseButton)) { if (ImGui::BeginTabItem("Hearts")) { - EnhancementColor3("Hearts inner", "gCCHeartsPrim", hearts_colors, false); + EnhancementColor("Hearts inner", "gCCHeartsPrim", hearts_colors, ImVec4(255,70,50,255)); Tooltip("Hearts inner color (red in original)\nAffect both Normal Hearts and the ones in Double Defense"); - EnhancementColor3("Hearts double def", "gDDCCHeartsPrim", hearts_dd_colors, false); - Tooltip("Hearts outline color (white in original)\nAffect Double Defense outline only"); + EnhancementColor("Hearts double def", "gDDCCHeartsPrim", hearts_dd_colors, ImVec4(255,255,255,255)); + Tooltip("Hearts outline color (white in original)\nAffect Double Defense outline only."); ImGui::EndTabItem(); } if (ImGui::BeginTabItem("Buttons")) { - EnhancementColor3("A Buttons", "gCCABtnPrim", a_btn_colors, false); - Tooltip("A Buttons colors (Green in original Gamecube)\nAffect A buttons colors on interface, in shops, messages boxes, ocarina notes and inventory cursors"); - EnhancementColor3("B Buttons", "gCCBBtnPrim", b_btn_colors, false); + EnhancementColor("A Buttons", "gCCABtnPrim", a_btn_colors, ImVec4(90,90,255,255)); + Tooltip("A Buttons colors (Green in original Gamecube)\nAffect A buttons colors on interface, in shops, messages boxes, ocarina notes and inventory cursors."); + EnhancementColor("B Buttons", "gCCBBtnPrim", b_btn_colors, ImVec4(0,150,0,255)); Tooltip("B Button colors (Red in original Gamecube)\nAffect B button colors on interface"); - EnhancementColor3("C Buttons", "gCCCBtnPrim", c_btn_colors, false); + EnhancementColor("C Buttons", "gCCCBtnPrim", c_btn_colors, ImVec4(255,160,0,255)); Tooltip("C Buttons colors (Yellowish / Oranges in originals)\nAffect C buttons colors on interface, in inventory and ocarina notes"); - EnhancementColor3("Start Buttons", "gCCStartBtnPrim", start_btn_colors, false); + EnhancementColor("Start Buttons", "gCCStartBtnPrim", start_btn_colors, ImVec4(120,120,120,255)); Tooltip("Start Button colors (gray in Gamecube)\nAffect Start button colors in inventory"); ImGui::EndTabItem(); } if (ImGui::BeginTabItem("Magic Bar")) { - EnhancementColor3("Magic bar borders", "gCCMagicBorderPrim", magic_border_colors, false); - Tooltip("Affect the border of the magic bar when being used\nWhite flash in original game"); - EnhancementColor3("Magic bar main color", "gCCMagicPrim", magic_remaining_colors, false); - Tooltip("Affect the magic bar color\nGreen in original game"); - EnhancementColor3("Magic bar being used", "gCCMagicUsePrim", magic_use_colors, false); - Tooltip("Affect the magic bar when being used\nYellow in original game"); + EnhancementColor("Magic bar borders", "gCCMagicBorderPrim", magic_border_colors, ImVec4(255,255,255,255)); + Tooltip("Affect the border of the magic bar when being used\nWhite flash in original game."); + EnhancementColor("Magic bar main color", "gCCMagicPrim", magic_remaining_colors, ImVec4(0,200,0,255)); + Tooltip("Affect the magic bar color\nGreen in original game."); + EnhancementColor("Magic bar being used", "gCCMagicUsePrim", magic_use_colors, ImVec4(250,250,0,255)); + Tooltip("Affect the magic bar when being used\nYellow in original game."); ImGui::EndTabItem(); } if (ImGui::BeginTabItem("Misc")) { - EnhancementColor3("Minimap color", "gCCMinimapPrim", minimap_colors, false); - Tooltip("Affect the Dungeon and Overworld minimaps"); - EnhancementColor3("Rupee icon color", "gCCRupeePrim", rupee_colors, false); - Tooltip("Affect the Rupee icon on interface\nGreen by default"); - EnhancementColor3("Small Keys icon color", "gCCKeysPrim", smolekey_colors, false); - Tooltip("Affect the Small keys icon on interface\nGray by default"); + EnhancementColor("Minimap color", "gCCMinimapPrim", minimap_colors, ImVec4(0,255,255,255)); + Tooltip("Affect the Dungeon and Overworld minimaps."); + EnhancementColor("Rupee icon color", "gCCRupeePrim", rupee_colors, ImVec4(120,120,120,255)); + Tooltip("Affect the Rupee icon on interface\nGreen by default."); + EnhancementColor("Small Keys icon color", "gCCKeysPrim", smolekey_colors, ImVec4(200,230,255,255)); + Tooltip("Affect the Small keys icon on interface\nGray by default."); ImGui::EndTabItem(); } ImGui::EndTabBar(); @@ -1180,6 +1271,8 @@ namespace SohImGui { ImGui::UpdatePlatformWindows(); ImGui::RenderPlatformWindowsDefault(); } + //Placed here so it does the rainbow effects even if menu is not on. + LoadRainbowColor(); } void CancelFrame() { diff --git a/libultraship/libultraship/SohImGuiImpl.h b/libultraship/libultraship/SohImGuiImpl.h index 2a192802d..421c71778 100644 --- a/libultraship/libultraship/SohImGuiImpl.h +++ b/libultraship/libultraship/SohImGuiImpl.h @@ -63,16 +63,14 @@ namespace SohImGui { extern bool needs_save; void Init(WindowImpl window_impl); void Update(EventImpl event); - + void Tooltip(const char* text); + void EnhancementRadioButton(const char* text, const char* cvarName, int id); void EnhancementCheckbox(const char* text, const char* cvarName); void EnhancementButton(const char* text, const char* cvarName); void EnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format); void EnhancementSliderFloat(const char* text, const char* id, const char* cvarName, float min, float max, const char* format, float defaultValue, bool isPercentage); - - void Tooltip(const char* text); - - void EnhancementColor3(const char* text, const char* cvarName, float defaultColors[3], bool TitleSameLine); + void EnhancementColor(const char* text, const char* cvarName, ImVec4 ColorRGBA, ImVec4 default_colors, bool allow_rainbow = true, bool has_alpha=false, bool TitleSameLine=false); void DrawMainMenuAndCalculateGameSize(void); @@ -83,7 +81,10 @@ namespace SohImGui { void BindCmd(const std::string& cmd, CommandEntry entry); void AddWindow(const std::string& category, const std::string& name, WindowDrawFunc drawFunc); void LoadResource(const std::string& name, const std::string& path, const ImVec4& tint = ImVec4(1, 1, 1, 1)); - void LoadInterfaceEditor(); + void LoadPickersColors(ImVec4& ColorArray, const char* cvarname, const ImVec4& default_colors, bool has_alpha=false); + void RandomizeColor(const char* cvarName, ImVec4* colors); + void RainbowColor(const char* cvarName, ImVec4* colors); + void ResetColor(const char* cvarName, ImVec4* colors, ImVec4 defaultcolors, bool has_alpha); ImTextureID GetTextureByID(int id); ImTextureID GetTextureByName(const std::string& name); } diff --git a/soh/src/code/z_lifemeter.c b/soh/src/code/z_lifemeter.c index 30b18683f..e45850a73 100644 --- a/soh/src/code/z_lifemeter.c +++ b/soh/src/code/z_lifemeter.c @@ -128,6 +128,13 @@ void HealthMeter_Init(GlobalContext* globalCtx) { HeartDDOutline[0] = CVar_GetS32("gDDCCHeartsPrimR", 90); HeartDDOutline[1] = CVar_GetS32("gDDCCHeartsPrimG", 90); HeartDDOutline[2] = CVar_GetS32("gDDCCHeartsPrimB", 90); + } else { + HeartInner[0] = HEARTS_PRIM_R; + HeartInner[1] = HEARTS_PRIM_G; + HeartInner[2] = HEARTS_PRIM_B; + HeartDDOutline[0] = HEARTS_DD_PRIM_R; + HeartDDOutline[1] = HEARTS_DD_PRIM_G; + HeartDDOutline[2] = HEARTS_DD_PRIM_B; } interfaceCtx->unk_228 = 0x140; @@ -194,12 +201,12 @@ void HealthMeter_Update(GlobalContext* globalCtx) { HeartDDOutline[1] = CVar_GetS32("gDDCCHeartsPrimG", sHeartsDDPrim[0][1]); HeartDDOutline[2] = CVar_GetS32("gDDCCHeartsPrimB", sHeartsDDPrim[0][2]); } else { - HeartInner[0] = sHeartsPrimColors[0][0]; - HeartInner[1] = sHeartsPrimColors[0][1]; - HeartInner[2] = sHeartsPrimColors[0][2]; - HeartDDOutline[0] = sHeartsDDPrim[0][0]; - HeartDDOutline[1] = sHeartsDDPrim[0][1]; - HeartDDOutline[2] = sHeartsDDPrim[0][2]; + HeartInner[0] = HEARTS_PRIM_R; + HeartInner[1] = HEARTS_PRIM_G; + HeartInner[2] = HEARTS_PRIM_B; + HeartDDOutline[0] = HEARTS_DD_PRIM_R; + HeartDDOutline[1] = HEARTS_DD_PRIM_G; + HeartDDOutline[2] = HEARTS_DD_PRIM_B; } if (interfaceCtx->unk_200 != 0) { @@ -299,33 +306,33 @@ void HealthMeter_Update(GlobalContext* globalCtx) { sBeatingHeartsDDEnv[1] = (u8)(gFactor + HeartDDInner[1]) & 0xFF; sBeatingHeartsDDEnv[2] = (u8)(bFactor + HeartDDInner[2]) & 0xFF; } else { - sHeartsDDPrim[2][0] = HeartInner[0]; - sHeartsDDPrim[2][1] = HeartInner[1]; - sHeartsDDPrim[2][2] = HeartInner[2]; + sHeartsDDPrim[2][0] = HEARTS_PRIM_R; + sHeartsDDPrim[2][1] = HEARTS_PRIM_G; + sHeartsDDPrim[2][2] = HEARTS_PRIM_B; - sHeartsDDPrim[1][0] = sHeartsDDPrimColors[ddType][0]; - sHeartsDDPrim[1][1] = sHeartsDDPrimColors[ddType][1]; - sHeartsDDPrim[1][2] = sHeartsDDPrimColors[ddType][2]; + sHeartsDDPrim[1][0] = HEARTS_DD_PRIM_R; + sHeartsDDPrim[1][1] = HEARTS_DD_PRIM_G; + sHeartsDDPrim[1][2] = HEARTS_DD_PRIM_B; - sHeartsDDEnv[1][0] = sHeartsDDEnvColors[ddType][0]; - sHeartsDDEnv[1][1] = sHeartsDDEnvColors[ddType][1]; - sHeartsDDEnv[1][2] = sHeartsDDEnvColors[ddType][2]; + sHeartsDDEnv[1][0] = HEARTS_PRIM_R; + sHeartsDDEnv[1][1] = HEARTS_PRIM_G; + sHeartsDDEnv[1][2] = HEARTS_PRIM_B; rFactor = sHeartsDDPrimFactors[ddType][0] * ddFactor; gFactor = sHeartsDDPrimFactors[ddType][1] * ddFactor; bFactor = sHeartsDDPrimFactors[ddType][2] * ddFactor; - sBeatingHeartsDDPrim[0] = (u8)(rFactor + HeartDDOutline[0]) & 0xFF; - sBeatingHeartsDDPrim[1] = (u8)(gFactor + HeartDDOutline[1]) & 0xFF; - sBeatingHeartsDDPrim[2] = (u8)(bFactor + HeartDDOutline[2]) & 0xFF; + sBeatingHeartsDDPrim[0] = (u8)(rFactor + HEARTS_DD_PRIM_R) & 0xFF; + sBeatingHeartsDDPrim[1] = (u8)(gFactor + HEARTS_DD_PRIM_G) & 0xFF; + sBeatingHeartsDDPrim[2] = (u8)(bFactor + HEARTS_DD_PRIM_B) & 0xFF; rFactor = sHeartsDDEnvFactors[ddType][0] * ddFactor; gFactor = sHeartsDDEnvFactors[ddType][1] * ddFactor; bFactor = sHeartsDDEnvFactors[ddType][2] * ddFactor; - sBeatingHeartsDDEnv[0] = (u8)(rFactor + HeartDDInner[0]) & 0xFF; - sBeatingHeartsDDEnv[1] = (u8)(gFactor + HeartDDInner[1]) & 0xFF; - sBeatingHeartsDDEnv[2] = (u8)(bFactor + HeartDDInner[2]) & 0xFF; + sBeatingHeartsDDEnv[0] = (u8)(rFactor + HEARTS_PRIM_R) & 0xFF; + sBeatingHeartsDDEnv[1] = (u8)(gFactor + HEARTS_PRIM_G) & 0xFF; + sBeatingHeartsDDEnv[2] = (u8)(bFactor + HEARTS_PRIM_B) & 0xFF; } } diff --git a/soh/src/code/z_player_lib.c b/soh/src/code/z_player_lib.c index af95f26df..83fae7ff1 100644 --- a/soh/src/code/z_player_lib.c +++ b/soh/src/code/z_player_lib.c @@ -744,26 +744,38 @@ void func_8008F470(GlobalContext* globalCtx, void** skeleton, Vec3s* jointTable, #else gSPSegment(POLY_OPA_DISP++, 0x09, SEGMENTED_TO_VIRTUAL(sMouthTextures[eyeIndex])); #endif - Color_RGB8 NewColor[3]; - color = &sTunicColors[tunic]; - if (CVar_GetS32("gUseTunicsCol",0) == 1) { - if (tunic == PLAYER_TUNIC_KOKIRI || tunic == PLAYER_TUNIC_GORON || tunic == PLAYER_TUNIC_ZORA) { - NewColor[PLAYER_TUNIC_KOKIRI].r = CVar_GetS32("gTunic_Kokiri_R", sTunicColors[PLAYER_TUNIC_KOKIRI].r); - NewColor[PLAYER_TUNIC_KOKIRI].g = CVar_GetS32("gTunic_Kokiri_G", sTunicColors[PLAYER_TUNIC_KOKIRI].g); - NewColor[PLAYER_TUNIC_KOKIRI].b = CVar_GetS32("gTunic_Kokiri_B", sTunicColors[PLAYER_TUNIC_KOKIRI].b); - NewColor[PLAYER_TUNIC_GORON].r = CVar_GetS32("gTunic_Goron_R", sTunicColors[PLAYER_TUNIC_GORON].r); - NewColor[PLAYER_TUNIC_GORON].g = CVar_GetS32("gTunic_Goron_G", sTunicColors[PLAYER_TUNIC_GORON].g); - NewColor[PLAYER_TUNIC_GORON].b = CVar_GetS32("gTunic_Goron_B", sTunicColors[PLAYER_TUNIC_GORON].b); - NewColor[PLAYER_TUNIC_ZORA].r = CVar_GetS32("gTunic_Zora_R", sTunicColors[PLAYER_TUNIC_ZORA].r); - NewColor[PLAYER_TUNIC_ZORA].g = CVar_GetS32("gTunic_Zora_G", sTunicColors[PLAYER_TUNIC_ZORA].g); - NewColor[PLAYER_TUNIC_ZORA].b = CVar_GetS32("gTunic_Zora_B", sTunicColors[PLAYER_TUNIC_ZORA].b); + + Color_RGB8 sTemp; + Color_RGB8 sOriginalTunicColors[] = { + { 30, 105, 27 }, + { 100, 20, 0 }, + { 0, 60, 100 }, + }; + color = &sTemp; + if (tunic == PLAYER_TUNIC_KOKIRI && CVar_GetS32("gUseTunicsCol",0)) { + color->r = CVar_GetS32("gTunic_Kokiri_R", sTunicColors[PLAYER_TUNIC_KOKIRI].r); + color->g = CVar_GetS32("gTunic_Kokiri_G", sTunicColors[PLAYER_TUNIC_KOKIRI].g); + color->b = CVar_GetS32("gTunic_Kokiri_B", sTunicColors[PLAYER_TUNIC_KOKIRI].b); + } else if (tunic == PLAYER_TUNIC_GORON && CVar_GetS32("gUseTunicsCol",0)) { + color->r = CVar_GetS32("gTunic_Goron_R", sTunicColors[PLAYER_TUNIC_GORON].r); + color->g = CVar_GetS32("gTunic_Goron_G", sTunicColors[PLAYER_TUNIC_GORON].g); + color->b = CVar_GetS32("gTunic_Goron_B", sTunicColors[PLAYER_TUNIC_GORON].b); + } else if (tunic == PLAYER_TUNIC_ZORA && CVar_GetS32("gUseTunicsCol",0)) { + color->r = CVar_GetS32("gTunic_Zora_R", sTunicColors[PLAYER_TUNIC_ZORA].r); + color->g = CVar_GetS32("gTunic_Zora_G", sTunicColors[PLAYER_TUNIC_ZORA].g); + color->b = CVar_GetS32("gTunic_Zora_B", sTunicColors[PLAYER_TUNIC_ZORA].b); + } else if (!CVar_GetS32("gUseTunicsCol",0)){ + if (tunic >= 3) { + color->r = sOriginalTunicColors[0].r; + color->g = sOriginalTunicColors[0].g; + color->b = sOriginalTunicColors[0].b; } else { - NewColor[PLAYER_TUNIC_KOKIRI].r = CVar_GetS32("gTunic_Kokiri_R", sTunicColors[PLAYER_TUNIC_KOKIRI].r); - NewColor[PLAYER_TUNIC_KOKIRI].g = CVar_GetS32("gTunic_Kokiri_G", sTunicColors[PLAYER_TUNIC_KOKIRI].g); - NewColor[PLAYER_TUNIC_KOKIRI].b = CVar_GetS32("gTunic_Kokiri_B", sTunicColors[PLAYER_TUNIC_KOKIRI].b); + color->r = sOriginalTunicColors[tunic].r; + color->g = sOriginalTunicColors[tunic].g; + color->b = sOriginalTunicColors[tunic].b; } - color = NewColor; } + gDPSetEnvColor(POLY_OPA_DISP++, color->r, color->g, color->b, 0); sDListsLodOffset = lod * 2; diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c index d9f038059..43ae671e6 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c @@ -976,14 +976,23 @@ void KaleidoScope_DrawCursor(GlobalContext* globalCtx, u16 pageIndex) { temp = pauseCtx->unk_1E4; if (CVar_GetS32("gHudColors", 1) == 0) { + sCursorColors[1][0] = 255; + sCursorColors[1][1] = 255; + sCursorColors[1][2] = 0; sCursorColors[2][0] = 0; sCursorColors[2][1] = 50; sCursorColors[2][2] = 255; } else if (CVar_GetS32("gHudColors", 1) == 1) { + sCursorColors[1][0] = 255; + sCursorColors[1][1] = 255; + sCursorColors[1][2] = 0; sCursorColors[2][0] = 0; sCursorColors[2][1] = 255; sCursorColors[2][2] = 50; } else if (CVar_GetS32("gHudColors", 1) == 2) { + sCursorColors[1][0] = CVar_GetS32("gCCCBtnPrimR", 255); + sCursorColors[1][1] = CVar_GetS32("gCCCBtnPrimG", 255); + sCursorColors[1][2] = CVar_GetS32("gCCCBtnPrimB", 0); sCursorColors[2][0] = CVar_GetS32("gCCABtnPrimR", 0); sCursorColors[2][1] = CVar_GetS32("gCCABtnPrimG", 255); sCursorColors[2][2] = CVar_GetS32("gCCABtnPrimB", 50); @@ -1060,6 +1069,12 @@ void KaleidoScope_DrawPages(GlobalContext* globalCtx, GraphicsContext* gfxCtx) { { 0, 0, 0 }, { 255, 255, 0 }, { 0, 255, 50 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 255, 50 }, }; if (CVar_GetS32("gHudColors", 1) == 0) { + D_8082ACF4[4][0] = 255; + D_8082ACF4[4][1] = 255; + D_8082ACF4[4][2] = 0; + D_8082ACF4[7][0] = 255; + D_8082ACF4[7][1] = 255; + D_8082ACF4[7][2] = 0; D_8082ACF4[8][0] = 0; D_8082ACF4[8][1] = 50; D_8082ACF4[8][2] = 255; @@ -1067,6 +1082,12 @@ void KaleidoScope_DrawPages(GlobalContext* globalCtx, GraphicsContext* gfxCtx) { D_8082ACF4[11][1] = 50; D_8082ACF4[11][2] = 255; } else if (CVar_GetS32("gHudColors", 1) == 1) { + D_8082ACF4[4][0] = 255; + D_8082ACF4[4][1] = 255; + D_8082ACF4[4][2] = 0; + D_8082ACF4[7][0] = 255; + D_8082ACF4[7][1] = 255; + D_8082ACF4[7][2] = 0; D_8082ACF4[8][0] = 0; D_8082ACF4[8][1] = 255; D_8082ACF4[8][2] = 50; @@ -1074,6 +1095,12 @@ void KaleidoScope_DrawPages(GlobalContext* globalCtx, GraphicsContext* gfxCtx) { D_8082ACF4[11][1] = 255; D_8082ACF4[11][2] = 50; } else if (CVar_GetS32("gHudColors", 1) == 2) { + D_8082ACF4[4][0] = CVar_GetS32("gCCCBtnPrimR", 255); + D_8082ACF4[4][1] = CVar_GetS32("gCCCBtnPrimG", 255); + D_8082ACF4[4][2] = CVar_GetS32("gCCCBtnPrimB", 0); + D_8082ACF4[7][0] = CVar_GetS32("gCCCBtnPrimR", 255); + D_8082ACF4[7][1] = CVar_GetS32("gCCCBtnPrimG", 255); + D_8082ACF4[7][2] = CVar_GetS32("gCCCBtnPrimB", 0); D_8082ACF4[8][0] = CVar_GetS32("gCCABtnPrimR", 0); D_8082ACF4[8][1] = CVar_GetS32("gCCABtnPrimG", 255); D_8082ACF4[8][2] = CVar_GetS32("gCCABtnPrimB", 50); From 29d4cd27c46af4c31b15980518647c9cb47a5eeb Mon Sep 17 00:00:00 2001 From: Baoulettes Date: Sun, 29 May 2022 22:38:21 +0200 Subject: [PATCH 28/30] Fix Radiobutton uniqueness issues (#397) * Fix Radiobox uniqueness issues * C++ ? and build fix I think * To match the edit made in .c --- libultraship/libultraship/SohImGuiImpl.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libultraship/libultraship/SohImGuiImpl.cpp b/libultraship/libultraship/SohImGuiImpl.cpp index c91f31750..c03cd8e78 100644 --- a/libultraship/libultraship/SohImGuiImpl.cpp +++ b/libultraship/libultraship/SohImGuiImpl.cpp @@ -447,11 +447,17 @@ namespace SohImGui { EnhancementRadioButton("German", "gLanguages", 1); EnhancementRadioButton("French", "gLanguages", 2); */ + std::string make_invisible = "##"; + make_invisible += text; + make_invisible += cvarName; + int val = CVar_GetS32(cvarName, 0); - if (ImGui::RadioButton(text, id == val)) { + if (ImGui::RadioButton(make_invisible.c_str(), id == val)) { CVar_SetS32(cvarName, id); needs_save = true; } + ImGui::SameLine(); + ImGui::Text("%s", text); } void EnhancementCheckbox(const char* text, const char* cvarName) From 08c161fd13836b34bb3257d8361add14e967eac8 Mon Sep 17 00:00:00 2001 From: PurpleHato <47987542+PurpleHato@users.noreply.github.com> Date: Sun, 29 May 2022 22:40:50 +0200 Subject: [PATCH 29/30] Enhancement: More options for Kaleido Link (#394) * Enhancement: More options for Kaleido Link ADDED: 14 animations to use ADDED: 2 random mode ADDED: Link rotation on the menu with DPAD-Left and Right ADDED: Reset position with DPAD-Up and Down * ADDED/ Choice to use C-Button or D-pad --- libultraship/libultraship/SohImGuiImpl.cpp | 41 ++++++- soh/src/code/z_player_lib.c | 108 ++++++++++++++++-- .../ovl_kaleido_scope/z_kaleido_equipment.c | 32 +++++- 3 files changed, 168 insertions(+), 13 deletions(-) diff --git a/libultraship/libultraship/SohImGuiImpl.cpp b/libultraship/libultraship/SohImGuiImpl.cpp index c03cd8e78..3c3ca9c6c 100644 --- a/libultraship/libultraship/SohImGuiImpl.cpp +++ b/libultraship/libultraship/SohImGuiImpl.cpp @@ -861,9 +861,48 @@ namespace SohImGui { if (ImGui::BeginMenu("Graphics")) { + if (ImGui::BeginMenu("Animated Link in Pause Menu")) { + ImGui::Text("Rotation"); + EnhancementRadioButton("Disabled", "gPauseLiveRotation", 0); + EnhancementRadioButton("Rotate Link with D-pad", "gPauseLiveRotation", 1); + Tooltip("Allow you to rotate Link on the Equipment menu with the DPAD\nUse DPAD-Up or DPAD-Down to reset Link's rotation"); + EnhancementRadioButton("Rotate Link with C-buttons", "gPauseLiveRotation", 2); + Tooltip("Allow you to rotate Link on the Equipment menu with the C-buttons\nUse C-Up or C-Down to reset Link's rotation"); + + if (CVar_GetS32("gPauseLiveRotation", 0) != 0) { + EnhancementSliderInt("Rotation Speed: %d", "##MinRotationSpeed", "gPauseLiveLinkRotationSpeed", 1, 20, ""); + } + ImGui::Separator(); + ImGui::Text("Static loop"); + EnhancementRadioButton("Disabled", "gPauseLiveLink", 0); + EnhancementRadioButton("Idle (standing)", "gPauseLiveLink", 1); + EnhancementRadioButton("Idle (look around)", "gPauseLiveLink", 2); + EnhancementRadioButton("Idle (belt)", "gPauseLiveLink", 3); + EnhancementRadioButton("Idle (shield)", "gPauseLiveLink", 4); + EnhancementRadioButton("Idle (test sword)", "gPauseLiveLink", 5); + EnhancementRadioButton("Idle (yawn)", "gPauseLiveLink", 6); + EnhancementRadioButton("Battle Stance", "gPauseLiveLink", 7); + EnhancementRadioButton("Walking (no shield)", "gPauseLiveLink", 8); + EnhancementRadioButton("Walking (holding shield)", "gPauseLiveLink", 9); + EnhancementRadioButton("Running (no shield)", "gPauseLiveLink", 10); + EnhancementRadioButton("Running (holding shield)", "gPauseLiveLink", 11); + EnhancementRadioButton("Hand on hip", "gPauseLiveLink", 12); + EnhancementRadioButton("Spin attack charge", "gPauseLiveLink", 13); + EnhancementRadioButton("Look at hand", "gPauseLiveLink", 14); + ImGui::Separator(); + ImGui::Text("Randomize"); + EnhancementRadioButton("Random", "gPauseLiveLink", 15); + Tooltip("Randomize the animation played each time you open the menu"); + EnhancementRadioButton("Random cycle", "gPauseLiveLink", 16); + Tooltip("andomize the animation played on hte menu after a certain time"); + if (CVar_GetS32("gPauseLiveLink", 0) >= 16) { + EnhancementSliderInt("Frame to wait: %d", "##MinFrameCount", "gMinFrameCount", 1, 1000, ""); + } + + ImGui::EndMenu(); + } EnhancementCheckbox("N64 Mode", "gN64Mode"); Tooltip("Sets aspect ratio to 4:3 and lowers resolution to 240p, the N64's native resolution"); - EnhancementCheckbox("Animated Link in Pause Menu", "gPauseLiveLink"); EnhancementCheckbox("Enable 3D Dropped items", "gNewDrops"); EnhancementCheckbox("Dynamic Wallet Icon", "gDynamicWalletIcon"); Tooltip("Changes the rupee in the wallet icon to match the wallet size you currently have"); diff --git a/soh/src/code/z_player_lib.c b/soh/src/code/z_player_lib.c index 83fae7ff1..cf7fbd51c 100644 --- a/soh/src/code/z_player_lib.c +++ b/soh/src/code/z_player_lib.c @@ -1661,26 +1661,118 @@ void func_80091A24(GlobalContext* globalCtx, void* seg04, void* seg06, SkelAnime CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_player_lib.c", 3288); } +uintptr_t SelectedAnim = 0; // Current Animaiton on the menu +s16 EquipedStance; // Link's current mode (Two handed, One handed...) +s16 FrameCountSinceLastAnim = 0; // Time since last animation +s16 MinFrameCount; // Frame to wait before checking if we need to change the animation + void func_8009214C(GlobalContext* globalCtx, u8* segment, SkelAnime* skelAnime, Vec3f* pos, Vec3s* rot, f32 scale, s32 sword, s32 tunic, s32 shield, s32 boots) { + Input* p1Input = &globalCtx->state.input[0]; Vec3f eye = { 0.0f, 0.0f, -400.0f }; Vec3f at = { 0.0f, 0.0f, 0.0f }; Vec3s* destTable; Vec3s* srcTable; s32 i; + bool canswitchrnd = false; + s16 SelectedMode = CVar_GetS32("gPauseLiveLink", 1); + MinFrameCount = CVar_GetS32("gMinFrameCount", 200); gSegments[4] = VIRTUAL_TO_PHYSICAL(segment + 0x3800); gSegments[6] = VIRTUAL_TO_PHYSICAL(segment + 0x8800); - if (CVar_GetS32("gPauseLiveLink", 0) || CVar_GetS32("gPauseTriforce", 0)) { - uintptr_t anim = gPlayerAnim_003238; // idle + uintptr_t* PauseMenuAnimSet[15][4] = { + { 0, 0, 0, 0 }, // 0 = none + // IDLE // Two Handed // No shield // Kid Hylian Shield + { gPlayerAnim_003238, gPlayerAnim_002BE0, gPlayerAnim_003240, gPlayerAnim_003240 }, // Idle + { gPlayerAnim_003200, gPlayerAnim_003200, gPlayerAnim_003200, gPlayerAnim_003200 }, // Idle look around + { gPlayerAnim_0033E0, gPlayerAnim_0033E0, gPlayerAnim_0033E0, gPlayerAnim_0033E0 }, // Idle Belt + { gPlayerAnim_003418, gPlayerAnim_003418, gPlayerAnim_003418, gPlayerAnim_003418 }, // Idle shield adjust + { gPlayerAnim_003420, gPlayerAnim_003428, gPlayerAnim_003420, gPlayerAnim_003420 }, // Idle test sword + { gPlayerAnim_0033F0, gPlayerAnim_0033F0, gPlayerAnim_0033F0, gPlayerAnim_0033F0 }, // Idle yawn + { gPlayerAnim_0025D0, gPlayerAnim_002BD0, gPlayerAnim_0025D0, gPlayerAnim_0025D0 }, // Battle Stance + { gPlayerAnim_003290, gPlayerAnim_002BF8, gPlayerAnim_003290, gPlayerAnim_003290 }, // Walking (No shield) + { gPlayerAnim_003268, gPlayerAnim_002BF8, gPlayerAnim_003268, gPlayerAnim_003268 }, // Walking (Holding shield) + { gPlayerAnim_003138, gPlayerAnim_002B40, gPlayerAnim_003138, gPlayerAnim_003138 }, // Running (No shield) + { gPlayerAnim_003140, gPlayerAnim_002B40, gPlayerAnim_003140, gPlayerAnim_003140 }, // Running (Holding shield) + { gPlayerAnim_0031A8, gPlayerAnim_0031A8, gPlayerAnim_0031A8, gPlayerAnim_0031A8 }, // Hand on hip + { gPlayerAnim_002AF0, gPlayerAnim_002928, gPlayerAnim_002AF0, gPlayerAnim_002AF0 }, // Spin Charge + { gPlayerAnim_002820, gPlayerAnim_002820, gPlayerAnim_002820, gPlayerAnim_002820 }, // Look at hand + }; + s16 AnimArraySize = ARRAY_COUNT(PauseMenuAnimSet); - if (CUR_EQUIP_VALUE(EQUIP_SWORD) >= 3) - anim = gPlayerAnim_002BE0; // Two Handed Anim - else if (CUR_EQUIP_VALUE(EQUIP_SHIELD) == 0) - anim = gPlayerAnim_003240; - else if (CUR_EQUIP_VALUE(EQUIP_SHIELD) == 2 && LINK_AGE_IN_YEARS == YEARS_CHILD) - anim = gPlayerAnim_003240; + if (CVar_GetS32("gPauseLiveLink", !0) || CVar_GetS32("gPauseTriforce", 0)) { + uintptr_t anim = 0; // Initialise anim + + if (CUR_EQUIP_VALUE(EQUIP_SWORD) >= 3) { + EquipedStance = 1; + } else if (CUR_EQUIP_VALUE(EQUIP_SHIELD) == 0) { + EquipedStance = 2; + } else if (CUR_EQUIP_VALUE(EQUIP_SHIELD) == 2 && LINK_AGE_IN_YEARS == YEARS_CHILD) { + EquipedStance = 3; + } else { + // Link is idle so revert to 0 + EquipedStance = 0; + } + + if (SelectedMode == 16) { + // Apply Random function + s16 SwitchAtFrame = 0; + s16 CurAnimDuration = 0; + if (FrameCountSinceLastAnim == 0) { + // When opening Kaleido this will be passed one time + SelectedAnim = rand() % (AnimArraySize - 0); + if (SelectedAnim == 0) { + // prevent loading 0 that would result to a crash. + SelectedAnim = 1; + } + } else if (FrameCountSinceLastAnim >= 1) { + SwitchAtFrame = Animation_GetLastFrame(PauseMenuAnimSet[SelectedAnim][EquipedStance]); + CurAnimDuration = Animation_GetLastFrame(PauseMenuAnimSet[SelectedAnim][EquipedStance]); + if (SwitchAtFrame < MinFrameCount) { + // Animation frame count is lower than minimal wait time then we wait for another round. + // This will be looped to always add current animation time if that still lower than minimum time + while (SwitchAtFrame < MinFrameCount) { + SwitchAtFrame = SwitchAtFrame + CurAnimDuration; + } + } else if (CurAnimDuration >= MinFrameCount) { + // Since we have more (or same) animation time than min duration we set the wait time to animation + // time. + SwitchAtFrame = CurAnimDuration; + } + if (FrameCountSinceLastAnim >= SwitchAtFrame) { + SelectedAnim = rand() % (AnimArraySize - 0); + if (SelectedAnim == 0) { + // prevent loading 0 that would result to a crash. + SelectedAnim = 1; + } + FrameCountSinceLastAnim = 1; + } + anim = PauseMenuAnimSet[SelectedAnim][EquipedStance]; + } + FrameCountSinceLastAnim++; + } else if (SelectedMode == 15) { + // When opening Kaleido this will be passed one time + if (FrameCountSinceLastAnim < 1) { + SelectedAnim = rand() % (AnimArraySize - 0); + FrameCountSinceLastAnim++; + if (SelectedAnim == 0) { + // prevent loading 0 that would result to a crash. + SelectedAnim = 1; + } + FrameCountSinceLastAnim = 1; + } + if (CHECK_BTN_ALL(p1Input->press.button, BTN_B) || CHECK_BTN_ALL(p1Input->press.button, BTN_START)) { + FrameCountSinceLastAnim = 0; + } + anim = PauseMenuAnimSet[SelectedAnim][EquipedStance]; + } else if (SelectedMode < 16) { + // Not random so we place our CVar as SelectedAnim + SelectedAnim = SelectedMode; + anim = PauseMenuAnimSet[SelectedAnim][EquipedStance]; + } + + anim = PauseMenuAnimSet[SelectedAnim][EquipedStance]; //anim = gPlayerAnim_003428; // Use for biggoron sword? diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c index 719eaa3f3..125981bff 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c @@ -89,11 +89,17 @@ void KaleidoScope_DrawEquipmentImage(GlobalContext* globalCtx, void* source, u32 CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_kaleido_equipment.c", 122); } +Vec3s link_kaleido_rot = { 0, 32300, 0 }; // Default rotation link face us. + void KaleidoScope_DrawPlayerWork(GlobalContext* globalCtx) { PauseContext* pauseCtx = &globalCtx->pauseCtx; Vec3f pos; - Vec3s rot; + //Vec3s rot; // Removed for not having it use din the function f32 scale; + Input* input = &globalCtx->state.input[0]; + s16 RotationSpeed = 150 * CVar_GetS32("gPauseLiveLinkRotationSpeed", 0); + bool AllowCRotation = (CVar_GetS32("gPauseLiveLinkRotation", 0) == 2) ? true : false; + bool AllowDPadRotation = (CVar_GetS32("gPauseLiveLinkRotation", 0) == 1) ? true : false; if (LINK_AGE_IN_YEARS == YEARS_CHILD) { pos.x = 2.0f; @@ -112,11 +118,29 @@ void KaleidoScope_DrawPlayerWork(GlobalContext* globalCtx) { scale = 0.047f; } - rot.y = 32300; - rot.x = rot.z = 0; + link_kaleido_rot.x = link_kaleido_rot.z = 0; + + if (AllowDPadRotation && CHECK_BTN_ALL(input->cur.button, BTN_DLEFT) || + AllowCRotation && CHECK_BTN_ALL(input->cur.button, BTN_CLEFT)) { + link_kaleido_rot.y = link_kaleido_rot.y - RotationSpeed; + } else if (AllowDPadRotation && CHECK_BTN_ALL(input->cur.button, BTN_DRIGHT) || + AllowCRotation && CHECK_BTN_ALL(input->cur.button, BTN_CRIGHT)) { + link_kaleido_rot.y = link_kaleido_rot.y + RotationSpeed; + } + + if (AllowDPadRotation && CHECK_BTN_ALL(input->press.button, BTN_DUP) || + AllowDPadRotation && CHECK_BTN_ALL(input->press.button, BTN_DDOWN)) { + link_kaleido_rot.y = 32300; + } else if (AllowCRotation && CHECK_BTN_ALL(input->press.button, BTN_CUP) || + AllowCRotation && CHECK_BTN_ALL(input->press.button, BTN_CDOWN)) { + link_kaleido_rot.y = 32300; + } + + link_kaleido_rot.x = 0; + extern int fbTest; gsSPSetFB(globalCtx->state.gfxCtx->polyOpa.p++, fbTest); - func_8009214C(globalCtx, pauseCtx->playerSegment, &pauseCtx->playerSkelAnime, &pos, &rot, scale, + func_8009214C(globalCtx, pauseCtx->playerSegment, &pauseCtx->playerSkelAnime, &pos, &link_kaleido_rot, scale, CUR_EQUIP_VALUE(EQUIP_SWORD), CUR_EQUIP_VALUE(EQUIP_TUNIC) - 1, CUR_EQUIP_VALUE(EQUIP_SHIELD), CUR_EQUIP_VALUE(EQUIP_BOOTS) - 1); gsSPResetFB(globalCtx->state.gfxCtx->polyOpa.p++); From daec428cb3844bdb5261f5ddf47b613cce514d05 Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Sun, 29 May 2022 16:45:27 -0400 Subject: [PATCH 30/30] call SDL_Quit() before exit(0) (linux window closing issue) (#408) * use _Exit(0) on linux * use SDL_Quit() instead of _Exit(0) * remove unnecessary call, add bandaid comment Co-authored-by: briaguya --- libultraship/libultraship/Lib/Fast3D/gfx_sdl2.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libultraship/libultraship/Lib/Fast3D/gfx_sdl2.cpp b/libultraship/libultraship/Lib/Fast3D/gfx_sdl2.cpp index 94c3ef5ca..061e3a8ee 100644 --- a/libultraship/libultraship/Lib/Fast3D/gfx_sdl2.cpp +++ b/libultraship/libultraship/Lib/Fast3D/gfx_sdl2.cpp @@ -249,6 +249,7 @@ static void gfx_sdl_handle_events(void) { } break; case SDL_QUIT: + SDL_Quit(); // bandaid fix for linux window closing issue exit(0); } }