diff --git a/.github/workflows/apt-deps.txt b/.github/workflows/apt-deps.txt index 4d5fe5521..26e920d17 100644 --- a/.github/workflows/apt-deps.txt +++ b/.github/workflows/apt-deps.txt @@ -1 +1 @@ -libusb-dev libusb-1.0-0-dev libsdl2-dev libsdl2-net-dev libpng-dev libglew-dev libzip-dev zipcmp zipmerge ziptool nlohmann-json3-dev libtinyxml2-dev libspdlog-dev ninja-build +libusb-dev libusb-1.0-0-dev libsdl2-dev libsdl2-net-dev libpng-dev libglew-dev nlohmann-json3-dev libtinyxml2-dev libspdlog-dev ninja-build diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index f1d042351..b31a5bf66 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -114,7 +114,7 @@ jobs: - name: Install dependencies run: | sudo apt-get update - sudo apt-get install -y $(cat .github/workflows/apt-deps.txt) + sudo apt-get install -y $(cat .github/workflows/apt-deps.txt) libzip-dev zipcmp zipmerge ziptool - name: Cache build folders uses: actions/cache@v4 with: @@ -254,17 +254,17 @@ jobs: linux-build-${{ github.ref }} linux-build- path: | - SDL2-2.28.5 - SDL2_net-2.2.0 + SDL2-2.30.3 tinyxml2-10.0.0 + libzip-1.10.1 - name: Install latest SDL run: | export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" - if [ ! -d "SDL2-2.28.5" ]; then - wget https://www.libsdl.org/release/SDL2-2.28.5.tar.gz - tar -xzf SDL2-2.28.5.tar.gz + if [ ! -d "SDL2-2.30.3" ]; then + wget https://www.libsdl.org/release/SDL2-2.30.3.tar.gz + tar -xzf SDL2-2.30.3.tar.gz fi - cd SDL2-2.28.5 + cd SDL2-2.30.3 ./configure --enable-hidapi-libusb make -j 10 sudo make install @@ -283,18 +283,20 @@ jobs: cmake .. make sudo make install - - name: Install latest SDL_net + - name: Install libzip without crypto run: | export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" - if [ ! -d "SDL2_net-2.2.0" ]; then - wget https://www.libsdl.org/projects/SDL_net/release/SDL2_net-2.2.0.tar.gz - tar -xzf SDL2_net-2.2.0.tar.gz + if [ ! -d "libzip-1.10.1" ]; then + wget https://github.com/nih-at/libzip/releases/download/v1.10.1/libzip-1.10.1.tar.gz + tar -xzf libzip-1.10.1.tar.gz fi - cd SDL2_net-2.2.0 - ./configure - make -j 10 + cd libzip-1.10.1 + mkdir -p build + cd build + cmake .. -DENABLE_COMMONCRYPTO=OFF -DENABLE_GNUTLS=OFF -DENABLE_MBEDTLS=OFF -DENABLE_OPENSSL=OFF + make sudo make install - sudo cp -av /usr/local/lib/libSDL* /lib/x86_64-linux-gnu/ + sudo cp -av /usr/local/lib/libzip* /lib/x86_64-linux-gnu/ - name: Download 2ship.o2r uses: actions/download-artifact@v4 with: diff --git a/CMake/Packaging.cmake b/CMake/Packaging.cmake index 5c8ba3b5e..7a748f839 100644 --- a/CMake/Packaging.cmake +++ b/CMake/Packaging.cmake @@ -79,7 +79,6 @@ execute_process( --executable=$ $<$>:--desktop-file=$> $<$>:--icon-file=$> - --exclude-library "*libcrypto*" --output=appimage # --verbosity=2 ) diff --git a/copy-existing-otrs.cmake b/CMake/copy-existing-otrs.cmake similarity index 96% rename from copy-existing-otrs.cmake rename to CMake/copy-existing-otrs.cmake index efda3f7a5..882788c3a 100644 --- a/copy-existing-otrs.cmake +++ b/CMake/copy-existing-otrs.cmake @@ -17,7 +17,7 @@ if(SYSTEM_NAME MATCHES "Windows") if(NOT ONLY2SHIPOTR AND EXISTS ${SOURCE_DIR}/OTRExporter/mm.zip) execute_process(COMMAND ${CMAKE_COMMAND} -E copy mm.zip ${TARGET_DIR}/mm.o2r) endif() - if(EXISTS ${SOURCE_DIR}/OTRExporter/o2r) + if(EXISTS ${SOURCE_DIR}/OTRExporter/2ship.o2r) execute_process(COMMAND ${CMAKE_COMMAND} -E copy 2ship.o2r ${TARGET_DIR}) endif() endif() diff --git a/CMake/lus-cvars.cmake b/CMake/lus-cvars.cmake index ac4a6adea..0859f98ff 100644 --- a/CMake/lus-cvars.cmake +++ b/CMake/lus-cvars.cmake @@ -1,6 +1,5 @@ set(CVAR_VSYNC_ENABLED "${CVAR_PREFIX_SETTING}.VsyncEnabled" CACHE STRING "") set(CVAR_Z_FIGHTING_MODE "${CVAR_PREFIX_SETTING}.ZFightingMode" CACHE STRING "") -set(CVAR_DISABLE_CLOSE_COLOR_WRAP "${CVAR_PREFIX_SETTING}.DisableCloseColorWrap" CACHE STRING "") set(CVAR_NEW_FILE_DROPPED "${CVAR_PREFIX_GENERAL}.NewFileDropped" CACHE STRING "") set(CVAR_DROPPED_FILE "${CVAR_PREFIX_GENERAL}.DroppedFile" CACHE STRING "") set(CVAR_INTERNAL_RESOLUTION "${CVAR_PREFIX_SETTING}.InternalResolution" CACHE STRING "") @@ -17,7 +16,6 @@ set(CVAR_STATS_WINDOW_OPEN "${CVAR_PREFIX_WINDOW}.Stats" CACHE STRING "") set(CVAR_ENABLE_MULTI_VIEWPORTS "${CVAR_PREFIX_SETTING}.EnableMultiViewports" CACHE STRING "") set(CVAR_LOW_RES_MODE "${CVAR_PREFIX_SETTING}.LowResMode" CACHE STRING "") set(CVAR_SIMULATED_INPUT_LAG "${CVAR_PREFIX_SETTING}.SimulatedInputLag" CACHE STRING "") -set(CVAR_ALT_ASSETS "${CVAR_PREFIX_ENHANCEMENT}.AltAssets" CACHE STRING "") set(CVAR_GAME_OVERLAY_FONT "${CVAR_PREFIX_SETTING}.OverlayFont" CACHE STRING "") set(CVAR_MENU_BAR_OPEN "${CVAR_PREFIX_SETTING}.OpenMenuBar" CACHE STRING "") set(CVAR_PREFIX_CONTROLLERS "${CVAR_PREFIX_SETTING}.Controllers" CACHE STRING "") diff --git a/CMakeLists.txt b/CMakeLists.txt index eb7915f96..fcdb1001f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,10 +5,10 @@ set(CMAKE_CXX_STANDARD 20 CACHE STRING "The C++ standard to use") set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum OS X deployment version") -project(2s2h VERSION 1.0.0 LANGUAGES C CXX) +project(2s2h VERSION 1.0.1 LANGUAGES C CXX) include(CMake/2ship-cvars.cmake) include(CMake/lus-cvars.cmake) -set(PROJECT_BUILD_NAME "Rika Alfa" CACHE STRING "") +set(PROJECT_BUILD_NAME "Rika Bravo" CACHE STRING "") set(PROJECT_TEAM "github.com/harbourmasters" CACHE STRING "") set_property(DIRECTORY ${CMAKE_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT 2ship) @@ -31,6 +31,9 @@ endif() # Enable the Gfx debugger in LUS to use libgfxd from ZAPDTR set(GFX_DEBUG_DISASSEMBLER ON) +# Tell LUS we're using F3DEX_GBI_2 (in a way that doesn't break libgfxd) +set(USE_F3DEX2 ON) + ################################################################################ # Set target arch type if empty. Visual studio solution generator provides it. ################################################################################ @@ -146,7 +149,7 @@ add_custom_target( # CMake versions prior to 3.17 do not have the rm command, use remove instead for older versions COMMAND ${CMAKE_COMMAND} -E $,remove,rm> -f mm.zip 2ship.o2r COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/OTRExporter/extract_assets.py -z "$" --non-interactive --xml-root ../mm/assets/xml --custom-otr-file 2ship.o2r "--custom-assets-path" ${CMAKE_CURRENT_SOURCE_DIR}/mm/assets/custom --port-ver "${CMAKE_PROJECT_VERSION}" - COMMAND ${CMAKE_COMMAND} -DSYSTEM_NAME=${CMAKE_SYSTEM_NAME} -DTARGET_DIR="$" -DSOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR} -DBINARY_DIR=${CMAKE_BINARY_DIR} -P ${CMAKE_CURRENT_SOURCE_DIR}/copy-existing-otrs.cmake + COMMAND ${CMAKE_COMMAND} -DSYSTEM_NAME=${CMAKE_SYSTEM_NAME} -DTARGET_DIR="$" -DSOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR} -DBINARY_DIR=${CMAKE_BINARY_DIR} -P ${CMAKE_CURRENT_SOURCE_DIR}/CMake/copy-existing-otrs.cmake WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/OTRExporter COMMENT "Running asset extraction..." DEPENDS ZAPD @@ -168,7 +171,7 @@ add_custom_target( # CMake versions prior to 3.17 do not have the rm command, use remove instead for older versions COMMAND ${CMAKE_COMMAND} -E $,remove,rm> -f 2ship.o2r COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/OTRExporter/extract_assets.py -z "$" --norom --custom-otr-file 2ship.o2r "--custom-assets-path" ${CMAKE_CURRENT_SOURCE_DIR}/mm/assets/custom --port-ver "${CMAKE_PROJECT_VERSION}" - COMMAND ${CMAKE_COMMAND} -DSYSTEM_NAME=${CMAKE_SYSTEM_NAME} -DTARGET_DIR="$" -DSOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR} -DBINARY_DIR=${CMAKE_BINARY_DIR} -DONLY2SHIPOTR=On -P ${CMAKE_CURRENT_SOURCE_DIR}/copy-existing-otrs.cmake + COMMAND ${CMAKE_COMMAND} -DSYSTEM_NAME=${CMAKE_SYSTEM_NAME} -DTARGET_DIR="$" -DSOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR} -DBINARY_DIR=${CMAKE_BINARY_DIR} -DONLY2SHIPOTR=On -P ${CMAKE_CURRENT_SOURCE_DIR}/CMake/copy-existing-otrs.cmake WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/OTRExporter COMMENT "Generating 2ship.o2r..." DEPENDS ZAPD diff --git a/OTRExporter b/OTRExporter index c2a891be8..287c79891 160000 --- a/OTRExporter +++ b/OTRExporter @@ -1 +1 @@ -Subproject commit c2a891be8ba1d33e09ee39eb4bf1c95e3b753e0e +Subproject commit 287c79891882df5a0797cd9d39c0dcb97af9f007 diff --git a/ZAPDTR b/ZAPDTR index ce2d63d8d..b002f2875 160000 --- a/ZAPDTR +++ b/ZAPDTR @@ -1 +1 @@ -Subproject commit ce2d63d8dd594a8ebc35073868d071aa36258317 +Subproject commit b002f28757a7ff9f928a4d9dd1834137edb144bb diff --git a/libultraship b/libultraship index 0c4b49112..070eb35dd 160000 --- a/libultraship +++ b/libultraship @@ -1 +1 @@ -Subproject commit 0c4b491125e86709400d7bae866159eecd079d38 +Subproject commit 070eb35dde54f8dcbffad8fb3d97367bb792b6b1 diff --git a/mm/2s2h/BenGui/BenGui.cpp b/mm/2s2h/BenGui/BenGui.cpp index 1b605880a..b41e537e0 100644 --- a/mm/2s2h/BenGui/BenGui.cpp +++ b/mm/2s2h/BenGui/BenGui.cpp @@ -20,8 +20,6 @@ #include "include/global.h" #include "include/z64audio.h" -bool ShouldClearTextureCacheAtEndOfFrame = false; - namespace BenGui { // MARK: - Delegates diff --git a/mm/2s2h/BenGui/BenMenuBar.cpp b/mm/2s2h/BenGui/BenMenuBar.cpp index 1807a9a56..ae63ead7b 100644 --- a/mm/2s2h/BenGui/BenMenuBar.cpp +++ b/mm/2s2h/BenGui/BenMenuBar.cpp @@ -14,8 +14,6 @@ #include "2s2h/DeveloperTools/WarpPoint.h" #include "HudEditor.h" -extern bool ShouldClearTextureCacheAtEndOfFrame; - extern "C" { #include "z64.h" #include "functions.h" @@ -181,11 +179,15 @@ void DrawSettingsMenu() { "form of anti-aliasing"); #endif #ifndef __WIIU__ - if (UIWidgets::CVarSliderInt("MSAA: %d", CVAR_MSAA_VALUE, 1, 8, 1)) { + if (UIWidgets::CVarSliderInt((CVarGetInteger(CVAR_MSAA_VALUE, 1) == 1) ? "Anti-aliasing (MSAA): Off" + : "Anti-aliasing (MSAA): %d", + CVAR_MSAA_VALUE, 1, 8, 1)) { Ship::Context::GetInstance()->GetWindow()->SetMsaaLevel(CVarGetInteger(CVAR_MSAA_VALUE, 1)); }; UIWidgets::Tooltip( - "Activates multi-sample anti-aliasing when above 1x up to 8x for 8 samples for every pixel"); + "Activates MSAA (multi-sample anti-aliasing) from 2x up to 8x, to smooth the edges of rendered " + "geometry.\n" + "Higher sample count will result in smoother edges on models, but may reduce performance."); #endif { // FPS Slider @@ -437,14 +439,14 @@ void DrawEnhancementsMenu() { UIWidgets::CVarCheckbox( "Pause Menu Save", "gEnhancements.Saving.PauseSave", { .tooltip = "Re-introduce the pause menu save system. Pressing B in the pause menu will give you the " - "option to create an Owl Save from your current location.\n\nWhen loading back into the " - "game, you will be placed either at the entrance of the dungeon you saved in, or in South " - "Clock Town." }); + "option to create a persistent Owl Save from your current location.\n\nWhen loading back " + "into the game, you will be placed either at the entrance of the dungeon you saved in, or " + "in South Clock Town." }); if (UIWidgets::CVarCheckbox( "Autosave", "gEnhancements.Saving.Autosave", - { .tooltip = "Automatically create owl saves on the chosen interval.\n\nWhen loading back into the " - "game, you will be placed either at the entrance of the dungeon you saved in, or in " - "South Clock Town." })) { + { .tooltip = "Automatically create a persistent Owl Save on the chosen interval.\n\nWhen loading " + "back into the game, you will be placed either at the entrance of the dungeon you " + "saved in, or in South Clock Town." })) { RegisterAutosave(); } UIWidgets::CVarSliderInt("Autosave Interval (minutes): %d", "gEnhancements.Saving.AutosaveInterval", 1, 60, @@ -535,10 +537,8 @@ void DrawEnhancementsMenu() { } if (UIWidgets::BeginMenu("Modes")) { - if (UIWidgets::CVarCheckbox("Play As Kafei", "gModes.PlayAsKafei", - { .tooltip = "Requires scene reload to take effect." })) { - UpdatePlayAsKafeiSkeletons(); - } + UIWidgets::CVarCheckbox("Play As Kafei", "gModes.PlayAsKafei", + { .tooltip = "Requires scene reload to take effect." }); ImGui::EndMenu(); } if (UIWidgets::BeginMenu("Player Movement")) { diff --git a/mm/2s2h/BenGui/HudEditor.cpp b/mm/2s2h/BenGui/HudEditor.cpp index 150c1c692..75b5ad58a 100644 --- a/mm/2s2h/BenGui/HudEditor.cpp +++ b/mm/2s2h/BenGui/HudEditor.cpp @@ -59,9 +59,9 @@ extern "C" void HudEditor_ModifyRectPosValuesFromBase(s16 baseX, s16 baseY, s16* *rectTop = baseY + (offsetFromBaseY * CVarGetFloat(hudEditorElements[hudEditorActiveElement].scaleCvar, 1.0f)); } -extern "C" void HudEditor_ModifyRectPosValues(s16* rectLeft, s16* rectTop) { - s16 offsetFromBaseX = *rectLeft - hudEditorElements[hudEditorActiveElement].defaultX; - s16 offsetFromBaseY = *rectTop - hudEditorElements[hudEditorActiveElement].defaultY; +void HudEditor_ModifyRectPosValuesFloat(f32* rectLeft, f32* rectTop) { + f32 offsetFromBaseX = *rectLeft - hudEditorElements[hudEditorActiveElement].defaultX; + f32 offsetFromBaseY = *rectTop - hudEditorElements[hudEditorActiveElement].defaultY; *rectLeft = CVarGetInteger(hudEditorElements[hudEditorActiveElement].xCvar, hudEditorElements[hudEditorActiveElement].defaultX) + (offsetFromBaseX * CVarGetFloat(hudEditorElements[hudEditorActiveElement].scaleCvar, 1.0f)); @@ -78,6 +78,16 @@ extern "C" void HudEditor_ModifyRectPosValues(s16* rectLeft, s16* rectTop) { } } +extern "C" void HudEditor_ModifyRectPosValues(s16* rectLeft, s16* rectTop) { + f32 newLeft = *rectLeft; + f32 newTop = *rectTop; + + HudEditor_ModifyRectPosValuesFloat(&newLeft, &newTop); + + *rectLeft = (s16)newLeft; + *rectTop = (s16)newTop; +} + extern "C" void HudEditor_ModifyRectSizeValues(s16* rectWidth, s16* rectHeight) { *rectWidth *= CVarGetFloat(hudEditorElements[hudEditorActiveElement].scaleCvar, 1.0f); *rectHeight *= CVarGetFloat(hudEditorElements[hudEditorActiveElement].scaleCvar, 1.0f); @@ -90,16 +100,13 @@ extern "C" void HudEditor_ModifyTextureStepValues(s16* dsdx, s16* dtdy) { // Modify matrix values based on the identity matrix (0,0) centered on the screen extern "C" void HudEditor_ModifyMatrixValues(f32* transX, f32* transY) { - *transX = (f32)(SCREEN_WIDTH / 2) + *transX; - *transY = (f32)(SCREEN_HEIGHT / 2) - *transY; + *transX = ((f32)SCREEN_WIDTH / 2) + *transX; + *transY = ((f32)SCREEN_HEIGHT / 2) - *transY; - s16 newX = *transX; - s16 newY = *transY; + HudEditor_ModifyRectPosValuesFloat(transX, transY); - HudEditor_ModifyRectPosValues(&newX, &newY); - - *transX = (f32)newX - (SCREEN_WIDTH / 2); - *transY = (f32)(SCREEN_HEIGHT / 2) - newY; + *transX = *transX - ((f32)SCREEN_WIDTH / 2); + *transY = ((f32)SCREEN_HEIGHT / 2) - *transY; } extern "C" void HudEditor_ModifyKaleidoEquipAnimValues(s16* ulx, s16* uly, s16* shrinkRate) { diff --git a/mm/2s2h/BenGui/UIWidgets.cpp b/mm/2s2h/BenGui/UIWidgets.cpp index 8b6ef9225..c50aceae7 100644 --- a/mm/2s2h/BenGui/UIWidgets.cpp +++ b/mm/2s2h/BenGui/UIWidgets.cpp @@ -180,6 +180,8 @@ bool Checkbox(const char* _label, bool* value, const CheckboxOptions& options) { if (window->SkipItems) return false; + ImGui::BeginDisabled(options.disabled); + bool above = options.labelPosition == LabelPosition::Above; bool lpFar = options.labelPosition == LabelPosition::Far; bool right = options.alignment == ComponentAlignment::Right; @@ -210,19 +212,15 @@ bool Checkbox(const char* _label, bool* value, const CheckboxOptions& options) { ImGui::ItemSize(total_bb, style.FramePadding.y); if (!ImGui::ItemAdd(total_bb, id)) { - IMGUI_TEST_ENGINE_ITEM_INFO(id, label, - g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Checkable | - (*value ? ImGuiItemStatusFlags_Checked : 0)); + ImGui::EndDisabled(); return false; } - - bool hovered, held; - bool pressed = ImGui::ButtonBehavior(total_bb, id, &hovered, &held); + bool hovered, held, pressed; + pressed = ImGui::ButtonBehavior(total_bb, id, &hovered, &held); if (pressed) { *value = !(*value); ImGui::MarkItemEdited(id); } - ImGui::BeginDisabled(options.disabled); PushStyleCheckbox(options.color); ImVec2 checkPos = pos; ImVec2 labelPos = pos; diff --git a/mm/2s2h/BenPort.cpp b/mm/2s2h/BenPort.cpp index 10572be77..15dc9ef65 100644 --- a/mm/2s2h/BenPort.cpp +++ b/mm/2s2h/BenPort.cpp @@ -101,6 +101,7 @@ OTRGlobals* OTRGlobals::Instance; GameInteractor* GameInteractor::Instance; extern "C" char** cameraStrings; +bool prevAltAssets = false; std::vector> cameraStdStrings; Color_RGB8 kokiriColor = { 0x1E, 0x69, 0x1B }; @@ -148,6 +149,8 @@ OTRGlobals::OTRGlobals() { // tell LUS to reserve 3 SoH specific threads (Game, Audio, Save) context = Ship::Context::CreateInstance("2 Ship 2 Harkinian", appShortName, "2ship2harkinian.json", archiveFiles, {}, 3); + prevAltAssets = CVarGetInteger("gAltAssets", 0); + context->GetResourceManager()->SetAltAssetsEnabled(prevAltAssets); // Override LUS defaults Ship::Context::GetInstance()->GetLogger()->set_level( @@ -408,25 +411,6 @@ extern "C" void OTRExtScanner() { } } -std::string SanitizePath(std::string stringValue) { - // Add backslashes. - for (auto i = stringValue.begin();;) { - auto const pos = - std::find_if(i, stringValue.end(), [](char const c) { return '\\' == c || '\'' == c || '"' == c; }); - if (pos == stringValue.end()) { - break; - } - i = std::next(stringValue.insert(pos, '\\'), 2); - } - - // Removes others. - stringValue.erase(std::remove_if(stringValue.begin(), stringValue.end(), - [](char const c) { return '\n' == c || '\r' == c || '\0' == c || '\x1A' == c; }), - stringValue.end()); - - return stringValue; -} - void Ben_ProcessDroppedFiles(std::string filePath) { SPDLOG_INFO("Processing dropped file: {}", filePath); @@ -509,9 +493,6 @@ extern "C" void InitOTR() { CVarClear("gLetItSnow"); } - // BENTODO Once we have a proper fix for the color cominber, remove this - CVarRegisterInteger(CVAR_DISABLE_CLOSE_COLOR_WRAP, 1); - srand(now); #ifdef ENABLE_CROWD_CONTROL CrowdControl::Instance = new CrowdControl(); @@ -584,8 +565,6 @@ extern "C" uint64_t GetUnixTimestamp() { return now; } -extern bool ShouldClearTextureCacheAtEndOfFrame; - extern "C" void Graph_StartFrame() { #ifndef __WIIU__ using Ship::KbScancode; @@ -668,7 +647,7 @@ extern "C" void Graph_StartFrame() { #endif case KbScancode::LUS_KB_TAB: { // Toggle HD Assets - CVarSetInteger(CVAR_ALT_ASSETS, !CVarGetInteger(CVAR_ALT_ASSETS, 0)); + CVarSetInteger("gAltAssets", !CVarGetInteger("gAltAssets", 0)); // ShouldClearTextureCacheAtEndOfFrame = true; break; } @@ -676,7 +655,7 @@ extern "C" void Graph_StartFrame() { #endif if (CVarGetInteger(CVAR_NEW_FILE_DROPPED, 0)) { - std::string filePath = SanitizePath(CVarGetString(CVAR_DROPPED_FILE, "")); + std::string filePath = CVarGetString(CVAR_DROPPED_FILE, ""); if (!filePath.empty()) { GameInteractor::Instance->ExecuteHooks(filePath); } @@ -757,12 +736,16 @@ extern "C" void Graph_ProcessGfxCommands(Gfx* commands) { audio.cv_from_thread.wait(Lock); } } - // - // if (ShouldClearTextureCacheAtEndOfFrame) { - // gfx_texture_cache_clear(); - // Ship::SkeletonPatcher::UpdateSkeletons(); - // ShouldClearTextureCacheAtEndOfFrame = false; - //} + + bool curAltAssets = CVarGetInteger("gAltAssets", 0); + if (prevAltAssets != curAltAssets) { + prevAltAssets = curAltAssets; + Ship::Context::GetInstance()->GetResourceManager()->SetAltAssetsEnabled(curAltAssets); + gfx_texture_cache_clear(); + // TODO: skeleton patch, hooks + // SOH::SkeletonPatcher::UpdateSkeletons(); + // GameInteractor::Instance->ExecuteHooks(); + } // OTRTODO: FIGURE OUT END FRAME POINT /* if (OTRGlobals::Instance->context->GetWindow()->lastScancode != -1) @@ -796,6 +779,10 @@ extern "C" uint16_t OTRGetPixelDepth(float x, float y) { return wnd->GetPixelDepth(x, adjustedY); } +extern "C" bool ResourceMgr_IsAltAssetsEnabled() { + return Ship::Context::GetInstance()->GetResourceManager()->IsAltAssetsEnabled(); +} + extern "C" uint32_t ResourceMgr_GetNumGameVersions() { return Ship::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->GetGameVersions().size(); } @@ -1237,7 +1224,7 @@ extern "C" SkeletonHeader* ResourceMgr_LoadSkeletonByName(const char* path, Skel pathStr = pathStr.substr(sOtr.length()); } - bool isAlt = CVarGetInteger(CVAR_ALT_ASSETS, 0); + bool isAlt = ResourceMgr_IsAltAssetsEnabled(); if (isAlt) { pathStr = Ship::IResource::gAltAssetPrefix + pathStr; diff --git a/mm/2s2h/Enhancements/Camera/FreeLook.cpp b/mm/2s2h/Enhancements/Camera/FreeLook.cpp index b7e26e51c..2e68ed20d 100644 --- a/mm/2s2h/Enhancements/Camera/FreeLook.cpp +++ b/mm/2s2h/Enhancements/Camera/FreeLook.cpp @@ -172,6 +172,7 @@ void RegisterCameraFreeLook() { case CAM_FUNC_JUMP3: case CAM_FUNC_BATTLE1: case CAM_FUNC_UNIQUE2: + case CAM_FUNC_UNIQUE3: if (Camera_CanFreeLook(camera)) { Camera_FreeLook(camera); *should = false; diff --git a/mm/2s2h/Enhancements/Cheats/Infinite.cpp b/mm/2s2h/Enhancements/Cheats/Infinite.cpp index 182bd8338..ff542feab 100644 --- a/mm/2s2h/Enhancements/Cheats/Infinite.cpp +++ b/mm/2s2h/Enhancements/Cheats/Infinite.cpp @@ -26,13 +26,33 @@ void RegisterInfiniteCheats() { } if (CVarGetInteger("gCheats.InfiniteConsumables", 0)) { - AMMO(ITEM_BOW) = CUR_CAPACITY(UPG_QUIVER); - AMMO(ITEM_BOMB) = CUR_CAPACITY(UPG_BOMB_BAG); - AMMO(ITEM_BOMBCHU) = CUR_CAPACITY(UPG_BOMB_BAG); - AMMO(ITEM_DEKU_STICK) = CUR_CAPACITY(UPG_DEKU_STICKS); - AMMO(ITEM_DEKU_NUT) = CUR_CAPACITY(UPG_DEKU_NUTS); - AMMO(ITEM_MAGIC_BEANS) = 20; - AMMO(ITEM_POWDER_KEG) = 1; + if (INV_CONTENT(ITEM_BOW) == ITEM_BOW) { + AMMO(ITEM_BOW) = CUR_CAPACITY(UPG_QUIVER); + } + + if (INV_CONTENT(ITEM_BOMB) == ITEM_BOMB) { + AMMO(ITEM_BOMB) = CUR_CAPACITY(UPG_BOMB_BAG); + } + + if (INV_CONTENT(ITEM_BOMBCHU) == ITEM_BOMBCHU) { + AMMO(ITEM_BOMBCHU) = CUR_CAPACITY(UPG_BOMB_BAG); + } + + if (INV_CONTENT(ITEM_DEKU_STICK) == ITEM_DEKU_STICK) { + AMMO(ITEM_DEKU_STICK) = CUR_CAPACITY(UPG_DEKU_STICKS); + } + + if (INV_CONTENT(ITEM_DEKU_NUT) == ITEM_DEKU_NUT) { + AMMO(ITEM_DEKU_NUT) = CUR_CAPACITY(UPG_DEKU_NUTS); + } + + if (INV_CONTENT(ITEM_MAGIC_BEANS) == ITEM_MAGIC_BEANS) { + AMMO(ITEM_MAGIC_BEANS) = 20; + } + + if (INV_CONTENT(ITEM_POWDER_KEG) == ITEM_POWDER_KEG) { + AMMO(ITEM_POWDER_KEG) = 1; + } } }); } diff --git a/mm/2s2h/Enhancements/Cutscenes/StoryCutscenes/SkipClockTowerOpen.cpp b/mm/2s2h/Enhancements/Cutscenes/StoryCutscenes/SkipClockTowerOpen.cpp index ca31cef09..37876cb4d 100644 --- a/mm/2s2h/Enhancements/Cutscenes/StoryCutscenes/SkipClockTowerOpen.cpp +++ b/mm/2s2h/Enhancements/Cutscenes/StoryCutscenes/SkipClockTowerOpen.cpp @@ -5,18 +5,34 @@ extern "C" { #include "z64.h" void Flags_SetWeekEventReg(s32 flag); extern SaveContext gSaveContext; +extern PlayState* gPlayState; } void RegisterSkipClockTowerOpen() { + // This will handle skipping if you are around the Clock Town area, but not directly in south clock town + REGISTER_VB_SHOULD(GI_VB_CLOCK_TOWER_OPENING_CONSIDER_THIS_FIRST_CYCLE, { + if (CVarGetInteger("gEnhancements.Cutscenes.SkipStoryCutscenes", 0)) { + *should = false; + } + }); + + // This will handle skipping if you are directly in South Clock Town REGISTER_VB_SHOULD(GI_VB_PLAY_TRANSITION_CS, { - // Cutscene where clock tower opens. Will only show if the player is in Clock Town - if (gSaveContext.save.entrance == ENTRANCE(SOUTH_CLOCK_TOWN, 0) && gSaveContext.save.cutsceneIndex == 0xFFF1 && + if ((gSaveContext.save.entrance == ENTRANCE(SOUTH_CLOCK_TOWN, 0) || + gSaveContext.save.entrance == ENTRANCE(TERMINA_FIELD, 0)) && + gSaveContext.save.cutsceneIndex == 0xFFF1 && CVarGetInteger("gEnhancements.Cutscenes.SkipStoryCutscenes", 0)) { - // Setting the respawn flag to 2 will respawn the player where they were before the cutscene, consistent - // with the normal behavior - gSaveContext.respawnFlag = 2; - gSaveContext.save.cutsceneIndex = 0; + // Copied from ObjTokeidai_TowerOpening_EndCutscene SET_WEEKEVENTREG(WEEKEVENTREG_CLOCK_TOWER_OPENED); + gSaveContext.save.cutsceneIndex = 0; + gSaveContext.respawnFlag = 2; + gSaveContext.save.entrance = gSaveContext.respawn[RESPAWN_MODE_RETURN].entrance; + if (gSaveContext.respawn[RESPAWN_MODE_RETURN].playerParams == + PLAYER_PARAMS(0xFF, PLAYER_INITMODE_TELESCOPE)) { + gSaveContext.nextTransitionType = TRANS_TYPE_CIRCLE; + } else { + gSaveContext.nextTransitionType = TRANS_TYPE_FADE_BLACK; + } } }); } diff --git a/mm/2s2h/Enhancements/GameInteractor/GameInteractor.cpp b/mm/2s2h/Enhancements/GameInteractor/GameInteractor.cpp index 0eafed218..20ddcf6ba 100644 --- a/mm/2s2h/Enhancements/GameInteractor/GameInteractor.cpp +++ b/mm/2s2h/Enhancements/GameInteractor/GameInteractor.cpp @@ -49,6 +49,10 @@ void GameInteractor_ExecuteOnRoomInit(s16 sceneId, s8 roomNum) { GameInteractor::Instance->ExecuteHooksForFilter(sceneId, roomNum); } +void GameInteractor_ExecuteOnPlayDestroy() { + GameInteractor::Instance->ExecuteHooks(); +} + bool GameInteractor_ShouldActorInit(Actor* actor) { bool result = true; GameInteractor::Instance->ExecuteHooks(actor, &result); @@ -230,3 +234,22 @@ int GameInteractor_InvertControl(GIInvertType type) { return result; } + +uint32_t GameInteractor_Dpad(GIDpadType type, uint32_t buttonCombo) { + uint32_t result = 0; + + switch (type) { + case GI_DPAD_OCARINA: + if (CVarGetInteger("gEnhancements.Playback.DpadOcarina", 0)) { + result = buttonCombo; + } + break; + case GI_DPAD_EQUIP: + if (CVarGetInteger("gEnhancements.Dpad.DpadEquips", 0)) { + result = buttonCombo; + } + break; + } + + return result; +} diff --git a/mm/2s2h/Enhancements/GameInteractor/GameInteractor.h b/mm/2s2h/Enhancements/GameInteractor/GameInteractor.h index 8359f3003..c6a44249d 100644 --- a/mm/2s2h/Enhancements/GameInteractor/GameInteractor.h +++ b/mm/2s2h/Enhancements/GameInteractor/GameInteractor.h @@ -51,6 +51,7 @@ typedef enum { GI_VB_TATL_INTERUPT_MSG6, GI_VB_ITEM_BE_RESTRICTED, GI_VB_FLIP_HOP_VARIABLE, + GI_VB_CLOCK_TOWER_OPENING_CONSIDER_THIS_FIRST_CYCLE, } GIVanillaBehavior; typedef enum { @@ -58,6 +59,11 @@ typedef enum { GI_INVERT_CAMERA_RIGHT_STICK_Y, } GIInvertType; +typedef enum { + GI_DPAD_OCARINA, + GI_DPAD_EQUIP, +} GIDpadType; + #ifdef __cplusplus #include @@ -255,6 +261,7 @@ class GameInteractor { DEFINE_HOOK(OnSceneInit, (s8 sceneId, s8 spawnNum)); DEFINE_HOOK(OnRoomInit, (s8 sceneId, s8 roomNum)); + DEFINE_HOOK(OnPlayDestroy, ()); DEFINE_HOOK(ShouldActorInit, (Actor * actor, bool* should)); DEFINE_HOOK(OnActorInit, (Actor * actor)); @@ -296,6 +303,7 @@ void GameInteractor_ExecuteBeforeMoonCrashSaveReset(); void GameInteractor_ExecuteOnSceneInit(s16 sceneId, s8 spawnNum); void GameInteractor_ExecuteOnRoomInit(s16 sceneId, s8 roomNum); +void GameInteractor_ExecuteOnPlayDestroy(); bool GameInteractor_ShouldActorInit(Actor* actor); void GameInteractor_ExecuteOnActorInit(Actor* actor); @@ -327,6 +335,7 @@ bool GameInteractor_Should(GIVanillaBehavior flag, bool result, void* optionalAr flag, [](GIVanillaBehavior _, bool* should, void* opt) body) int GameInteractor_InvertControl(GIInvertType type); +uint32_t GameInteractor_Dpad(GIDpadType type, uint32_t buttonCombo); #ifdef __cplusplus } diff --git a/mm/2s2h/Enhancements/Graphics/PlayAsKafei.cpp b/mm/2s2h/Enhancements/Graphics/PlayAsKafei.cpp index 9b3e6b45e..9c69d6704 100644 --- a/mm/2s2h/Enhancements/Graphics/PlayAsKafei.cpp +++ b/mm/2s2h/Enhancements/Graphics/PlayAsKafei.cpp @@ -17,20 +17,12 @@ extern TexturePtr sPlayerMouthTextures[PLAYER_FORM_MAX][PLAYER_MOUTH_MAX]; static SkeletonHeader gLinkHumanSkelBackup; static SkeletonHeader gKafeiSkelBackup; -void UpdatePlayAsKafeiSkeletons() { +void UpdatePlayAsKafei() { if (CVarGetInteger("gModes.PlayAsKafei", 0)) { auto gLinkHumanSkelResource = Ship::Context::GetInstance()->GetResourceManager()->LoadResource(gLinkHumanSkel); SkeletonHeader* gLinkHumanSkelPtr = (SkeletonHeader*)gLinkHumanSkelResource->GetRawPointer(); memcpy(gLinkHumanSkelPtr, &gKafeiSkelBackup, sizeof(SkeletonHeader)); - } else { - auto gLinkHumanSkelResource = Ship::Context::GetInstance()->GetResourceManager()->LoadResource(gLinkHumanSkel); - SkeletonHeader* gLinkHumanSkelPtr = (SkeletonHeader*)gLinkHumanSkelResource->GetRawPointer(); - memcpy(gLinkHumanSkelPtr, &gLinkHumanSkelBackup, sizeof(SkeletonHeader)); - } -} -void UpdatePlayAsKafeiOther() { - if (CVarGetInteger("gModes.PlayAsKafei", 0)) { ResourceMgr_PatchGfxByName(gLinkHumanWaistDL, "gLinkHumanWaistDL0", 0, gsSPDisplayListOTRFilePath(gKafeiWaistDL)); ResourceMgr_PatchGfxByName(gLinkHumanWaistDL, "gLinkHumanWaistDL1", 1, gsSPEndDisplayList()); @@ -49,6 +41,10 @@ void UpdatePlayAsKafeiOther() { sPlayerMouthTextures[PLAYER_FORM_HUMAN][2] = (TexturePtr)gKafeiMouthAngryTex; sPlayerMouthTextures[PLAYER_FORM_HUMAN][3] = (TexturePtr)gKafeiMouthHappyTex; } else { + auto gLinkHumanSkelResource = Ship::Context::GetInstance()->GetResourceManager()->LoadResource(gLinkHumanSkel); + SkeletonHeader* gLinkHumanSkelPtr = (SkeletonHeader*)gLinkHumanSkelResource->GetRawPointer(); + memcpy(gLinkHumanSkelPtr, &gLinkHumanSkelBackup, sizeof(SkeletonHeader)); + ResourceMgr_UnpatchGfxByName(gLinkHumanWaistDL, "gLinkHumanWaistDL0"); ResourceMgr_UnpatchGfxByName(gLinkHumanWaistDL, "gLinkHumanWaistDL1"); @@ -78,9 +74,7 @@ void RegisterPlayAsKafei() { memcpy(&gLinkHumanSkelBackup, gLinkHumanSkelPtr, sizeof(SkeletonHeader)); memcpy(&gKafeiSkelBackup, gKafeiSkelPtr, sizeof(SkeletonHeader)); - UpdatePlayAsKafeiSkeletons(); - UpdatePlayAsKafeiOther(); + UpdatePlayAsKafei(); - GameInteractor::Instance->RegisterGameHook( - [](s8 sceneId, s8 spawnNum) { UpdatePlayAsKafeiOther(); }); + GameInteractor::Instance->RegisterGameHook([]() { UpdatePlayAsKafei(); }); } diff --git a/mm/2s2h/Enhancements/Saving/SavingEnhancements.cpp b/mm/2s2h/Enhancements/Saving/SavingEnhancements.cpp index 860ee49c3..ff626a1ba 100644 --- a/mm/2s2h/Enhancements/Saving/SavingEnhancements.cpp +++ b/mm/2s2h/Enhancements/Saving/SavingEnhancements.cpp @@ -16,8 +16,8 @@ static HOOK_ID autosaveGameStateUpdateHookId = 0; static HOOK_ID autosaveGameStateDrawFinishHookId = 0; // Used for saving through Autosaves and Pause Menu saves. -extern "C" int32_t GetSaveEntrance(PlayState* play) { - switch (play->sceneId) { +extern "C" int SavingEnhancements_GetSaveEntrance() { + switch (gPlayState->sceneId) { // Woodfall Temple + Odolwa case SCENE_MITURIN: case SCENE_MITURIN_BS: @@ -40,6 +40,43 @@ extern "C" int32_t GetSaveEntrance(PlayState* play) { } } +extern "C" bool SavingEnhancements_CanSave() { + // Game State + if (gPlayState == NULL || GET_PLAYER(gPlayState) == NULL) { + return false; + } + + // Owl saving available + if (!gSaveContext.flashSaveAvailable || gSaveContext.fileNum == 255) { + return false; + } + + // Not in a blocking cutscene + if (Player_InBlockingCsMode(gPlayState, GET_PLAYER(gPlayState))) { + return false; + } + + // Not in the middle of dialog + if (gPlayState->msgCtx.msgMode != 0) { + return false; + } + + // Hasn't gotten to clock town yet + if (gPlayState->sceneId == SCENE_SPOT00 || gPlayState->sceneId == SCENE_LOST_WOODS || + gPlayState->sceneId == SCENE_OPENINGDAN) { + return false; + } + + // Can't save once you've gone to the moon + if (gPlayState->sceneId == SCENE_SOUGEN || gPlayState->sceneId == SCENE_LAST_LINK || + gPlayState->sceneId == SCENE_LAST_DEKU || gPlayState->sceneId == SCENE_LAST_GORON || + gPlayState->sceneId == SCENE_LAST_ZORA || gPlayState->sceneId == SCENE_LAST_BS) { + return false; + } + + return true; +} + void DeleteOwlSave() { // Remove Owl Save on time cycle reset, needed when persisting owl saves and/or when // creating owl saves without the player being send back to the file select screen. @@ -82,9 +119,7 @@ void HandleAutoSave() { } // If owl save available to create, do it and reset the interval. - if (gSaveContext.flashSaveAvailable && gSaveContext.fileNum != 255 && - !Player_InBlockingCsMode(gPlayState, player) && gPlayState->pauseCtx.state == 0 && - gPlayState->msgCtx.msgMode == 0) { + if (SavingEnhancements_CanSave() && gPlayState->pauseCtx.state == 0) { // Reset timestamp, set icon timer to show autosave icon for 5 seconds (100 frames) lastSaveTimestamp = GetUnixTimestamp(); @@ -92,7 +127,7 @@ void HandleAutoSave() { // Create owl save gSaveContext.save.isOwlSave = true; - gSaveContext.save.shipSaveInfo.pauseSaveEntrance = GetSaveEntrance(gPlayState); + gSaveContext.save.shipSaveInfo.pauseSaveEntrance = SavingEnhancements_GetSaveEntrance(); Play_SaveCycleSceneFlags(&gPlayState->state); gSaveContext.save.saveInfo.playerData.savedSceneId = gPlayState->sceneId; func_8014546C(&gPlayState->sramCtx); @@ -106,7 +141,8 @@ void HandleAutoSave() { void RegisterSavingEnhancements() { REGISTER_VB_SHOULD(GI_VB_DELETE_OWL_SAVE, { - if (CVarGetInteger("gEnhancements.Saving.PersistentOwlSaves", 0)) { + if (CVarGetInteger("gEnhancements.Saving.PersistentOwlSaves", 0) || + gSaveContext.save.shipSaveInfo.pauseSaveEntrance != -1) { *should = false; } }); diff --git a/mm/2s2h/Enhancements/Saving/SavingEnhancements.h b/mm/2s2h/Enhancements/Saving/SavingEnhancements.h index 327817c1d..71018fe64 100644 --- a/mm/2s2h/Enhancements/Saving/SavingEnhancements.h +++ b/mm/2s2h/Enhancements/Saving/SavingEnhancements.h @@ -4,4 +4,15 @@ void RegisterSavingEnhancements(); void RegisterAutosave(); +#ifdef __cplusplus +extern "C" { +#endif + +int SavingEnhancements_GetSaveEntrance(); +bool SavingEnhancements_CanSave(); + +#ifdef __cplusplus +} +#endif + #endif // SAVING_ENHANCEMENTS_H diff --git a/mm/2s2h/SaveManager/SaveManager.cpp b/mm/2s2h/SaveManager/SaveManager.cpp index 691d740b2..d816972f6 100644 --- a/mm/2s2h/SaveManager/SaveManager.cpp +++ b/mm/2s2h/SaveManager/SaveManager.cpp @@ -7,6 +7,7 @@ #include "macros.h" #include "BenJsonConversions.hpp" +#include "BenPort.h" extern "C" { #include "src/overlays/gamestates/ovl_file_choose/z_file_select.h" @@ -34,7 +35,7 @@ typedef enum FlashSlotFile { ((GET_NEWF(save, 0) == 'Z') && (GET_NEWF(save, 1) == 'E') && (GET_NEWF(save, 2) == 'L') && \ (GET_NEWF(save, 3) == 'D') && (GET_NEWF(save, 4) == 'A') && (GET_NEWF(save, 5) == '3')) -const std::filesystem::path savesFolderPath(Ship::Context::GetPathRelativeToAppDirectory("saves")); +const std::filesystem::path savesFolderPath(Ship::Context::GetPathRelativeToAppDirectory("saves", appShortName)); // Migrations // The idea here is that we can read in any version of the save as generic JSON, then apply migrations diff --git a/mm/2s2h/resource/type/Skeleton.cpp b/mm/2s2h/resource/type/Skeleton.cpp index f4a65a3e3..643713afd 100644 --- a/mm/2s2h/resource/type/Skeleton.cpp +++ b/mm/2s2h/resource/type/Skeleton.cpp @@ -62,11 +62,11 @@ void SkeletonPatcher::ClearSkeletons() { } void SkeletonPatcher::UpdateSkeletons() { - bool isHD = CVarGetInteger(CVAR_ALT_ASSETS, 0); + auto resourceMgr = Ship::Context::GetInstance()->GetResourceManager(); + bool isHD = resourceMgr->IsAltAssetsEnabled(); for (auto skel : skeletons) { Skeleton* newSkel = - (Skeleton*)Ship::Context::GetInstance() - ->GetResourceManager() + (Skeleton*)resourceMgr ->LoadResource((isHD ? Ship::IResource::gAltAssetPrefix : "") + skel.vanillaSkeletonPath, true) .get(); diff --git a/mm/CMakeLists.txt b/mm/CMakeLists.txt index 86e067161..b03c9ff59 100644 --- a/mm/CMakeLists.txt +++ b/mm/CMakeLists.txt @@ -423,6 +423,7 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Windows") #"$<$:ENABLE_CROWD_CONTROL>" "INCLUDE_GAME_PRINTF;" #"ENABLE_CROWD_CONTROL;" + "F3DEX_GBI_2" "UNICODE;" "_UNICODE" STORMLIB_NO_AUTO_LINK @@ -437,6 +438,7 @@ elseif (CMAKE_SYSTEM_NAME STREQUAL "CafeOS") "$<$:" "NDEBUG" ">" + "F3DEX_GBI_2" "SPDLOG_ACTIVE_LEVEL=3;" "SPDLOG_NO_THREAD_ID;" "SPDLOG_NO_TLS;" @@ -450,6 +452,7 @@ elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU|Clang|AppleClang") "$<$:" "NDEBUG" ">" + "F3DEX_GBI_2" # "$<$:ENABLE_CROWD_CONTROL>" "SPDLOG_ACTIVE_LEVEL=0;" "_CONSOLE;" diff --git a/mm/include/functions.h b/mm/include/functions.h index ea5806f21..62ac3cb60 100644 --- a/mm/include/functions.h +++ b/mm/include/functions.h @@ -1365,10 +1365,6 @@ void osSpTaskYield(void); void osViSetXScale(f32 value); void osViSetYScale(f32 value); // #endregion -// #region 2S2H [Enhancements] -// [Autosaves & Pause Menu Saves] -int32_t GetSaveEntrance(PlayState* play); -// #endregion void Regs_InitData(PlayState* play); diff --git a/mm/include/gfx.h b/mm/include/gfx.h index 85705ba2f..ab031b075 100644 --- a/mm/include/gfx.h +++ b/mm/include/gfx.h @@ -244,8 +244,8 @@ void func_8012D374(GraphicsContext* gfxCtx, u8 r, u8 g, u8 b); void func_8012D40C(f32* param_1, f32* param_2, s16* param_3); void gSPSegment(void* value, int segNum, uintptr_t target); void gSPSegmentLoadRes(void* value, int segNum, uintptr_t target); -void gDPSetTextureImage(Gfx* pkt, u32 format, u32 size, u32 width, uintptr_t i); -void gDPSetTextureImageFB(Gfx* pkt, u32 format, u32 size, u32 width, int fb); +// void gDPSetTextureImage(Gfx* pkt, u32 format, u32 size, u32 width, uintptr_t i); +// void gDPSetTextureImageFB(Gfx* pkt, u32 format, u32 size, u32 width, int fb); void gSPDisplayList(Gfx* pkt, Gfx* dl); void gSPDisplayListOffset(Gfx* pkt, Gfx* dl, int offset); void gSPVertex(Gfx* pkt, uintptr_t v, int n, int v0); diff --git a/mm/include/z64save.h b/mm/include/z64save.h index ea7e1128d..5dc8c5f8f 100644 --- a/mm/include/z64save.h +++ b/mm/include/z64save.h @@ -559,11 +559,12 @@ typedef enum { (void)0 // #region 2S2H [DPad] +#define BTN_DPAD (BTN_DRIGHT | BTN_DLEFT | BTN_DDOWN | BTN_DUP) #define DPAD_TO_HELD_ITEM(btn) (btn + EQUIP_SLOT_MAX) #define HELD_ITEM_TO_DPAD(heldBtn) (heldBtn - EQUIP_SLOT_MAX) #define IS_HELD_DPAD(heldBtn) ((heldBtn >= DPAD_TO_HELD_ITEM(EQUIP_SLOT_D_RIGHT)) && (heldBtn <= DPAD_TO_HELD_ITEM(EQUIP_SLOT_D_UP))) -#define BTN_DPAD_EQUIP (CVarGetInteger("gEnhancements.Dpad.DpadEquips", 0) ? (BTN_DRIGHT | BTN_DLEFT | BTN_DDOWN | BTN_DUP) : 0) +#define BTN_DPAD_EQUIP (GameInteractor_Dpad(GI_DPAD_EQUIP, BTN_DPAD)) #define CHECK_BTN_DPAD(input) (CVarGetInteger("gEnhancements.Dpad.DpadEquips", 0) && \ (CHECK_BTN_ALL(input, BTN_DRIGHT) || \ CHECK_BTN_ALL(input, BTN_DLEFT) || \ diff --git a/mm/src/audio/code_8019AF00.c b/mm/src/audio/code_8019AF00.c index 4ad272c41..7f9e75cde 100644 --- a/mm/src/audio/code_8019AF00.c +++ b/mm/src/audio/code_8019AF00.c @@ -2521,7 +2521,8 @@ void AudioOcarina_CheckSongsWithoutMusicStaff(void) { u8 k; if (CHECK_BTN_ANY(sOcarinaInputButtonCur, BTN_L) && - CHECK_BTN_ANY(sOcarinaInputButtonCur, BTN_A | BTN_CRIGHT | BTN_CLEFT | BTN_CDOWN | BTN_CUP)) { + CHECK_BTN_ANY(sOcarinaInputButtonCur, BTN_A | BTN_CRIGHT | BTN_CLEFT | BTN_CDOWN | BTN_CUP | + GameInteractor_Dpad(GI_DPAD_OCARINA, BTN_DPAD))) { AudioOcarina_StartDefault(sOcarinaFlags); return; } @@ -2596,17 +2597,17 @@ void AudioOcarina_PlayControllerInput(u8 isOcarinaSfxSuppressedWhenCancelled) { // Ensures the button pressed to start the ocarina does not also play an ocarina note if ((sOcarinaInputButtonStart == 0) || ((sOcarinaInputButtonStart & - (BTN_A | BTN_CRIGHT | BTN_CLEFT | BTN_CDOWN | BTN_CUP | BTN_DRIGHT | BTN_DLEFT | BTN_DDOWN | BTN_DUP)) != + (BTN_A | BTN_CRIGHT | BTN_CLEFT | BTN_CDOWN | BTN_CUP | GameInteractor_Dpad(GI_DPAD_OCARINA, BTN_DPAD))) != (sOcarinaInputButtonCur & - (BTN_A | BTN_CRIGHT | BTN_CLEFT | BTN_CDOWN | BTN_CUP | BTN_DRIGHT | BTN_DLEFT | BTN_DDOWN | BTN_DUP)))) { + (BTN_A | BTN_CRIGHT | BTN_CLEFT | BTN_CDOWN | BTN_CUP | GameInteractor_Dpad(GI_DPAD_OCARINA, BTN_DPAD))))) { sOcarinaInputButtonStart = 0; if (1) {} sCurOcarinaPitch = OCARINA_PITCH_NONE; sCurOcarinaButtonIndex = OCARINA_BTN_INVALID; - ocarinaBtnsHeld = (sOcarinaInputButtonCur & (BTN_A | BTN_CRIGHT | BTN_CLEFT | BTN_CDOWN | BTN_CUP | BTN_DRIGHT | - BTN_DLEFT | BTN_DDOWN | BTN_DUP)) & + ocarinaBtnsHeld = (sOcarinaInputButtonCur & (BTN_A | BTN_CRIGHT | BTN_CLEFT | BTN_CDOWN | BTN_CUP | + GameInteractor_Dpad(GI_DPAD_OCARINA, BTN_DPAD))) & (sOcarinaInputButtonPrev & (BTN_A | BTN_CRIGHT | BTN_CLEFT | BTN_CDOWN | BTN_CUP | - BTN_DRIGHT | BTN_DLEFT | BTN_DDOWN | BTN_DUP)); + GameInteractor_Dpad(GI_DPAD_OCARINA, BTN_DPAD))); if (!(sOcarinaInputButtonPress & ocarinaBtnsHeld) && (sOcarinaInputButtonCur != 0)) { sOcarinaInputButtonPress = sOcarinaInputButtonCur; @@ -2621,19 +2622,22 @@ void AudioOcarina_PlayControllerInput(u8 isOcarinaSfxSuppressedWhenCancelled) { sCurOcarinaPitch = OCARINA_PITCH_D4; sCurOcarinaButtonIndex = OCARINA_BTN_A; - } else if (CHECK_BTN_ANY(sOcarinaInputButtonPress, BTN_CDOWN | (dpadCvarActive ? BTN_DDOWN : 0))) { + } else if (CHECK_BTN_ANY(sOcarinaInputButtonPress, + BTN_CDOWN | GameInteractor_Dpad(GI_DPAD_OCARINA, BTN_DDOWN))) { sCurOcarinaPitch = OCARINA_PITCH_F4; sCurOcarinaButtonIndex = OCARINA_BTN_C_DOWN; - } else if (CHECK_BTN_ANY(sOcarinaInputButtonPress, BTN_CRIGHT | (dpadCvarActive ? BTN_DRIGHT : 0))) { + } else if (CHECK_BTN_ANY(sOcarinaInputButtonPress, + BTN_CRIGHT | GameInteractor_Dpad(GI_DPAD_OCARINA, BTN_DRIGHT))) { sCurOcarinaPitch = OCARINA_PITCH_A4; sCurOcarinaButtonIndex = OCARINA_BTN_C_RIGHT; - } else if (CHECK_BTN_ANY(sOcarinaInputButtonPress, BTN_CLEFT | (dpadCvarActive ? BTN_DLEFT : 0))) { + } else if (CHECK_BTN_ANY(sOcarinaInputButtonPress, + BTN_CLEFT | GameInteractor_Dpad(GI_DPAD_OCARINA, BTN_DLEFT))) { sCurOcarinaPitch = OCARINA_PITCH_B4; sCurOcarinaButtonIndex = OCARINA_BTN_C_LEFT; - } else if (CHECK_BTN_ANY(sOcarinaInputButtonPress, BTN_CUP | (dpadCvarActive ? BTN_DUP : 0))) { + } else if (CHECK_BTN_ANY(sOcarinaInputButtonPress, BTN_CUP | GameInteractor_Dpad(GI_DPAD_OCARINA, BTN_DUP))) { sCurOcarinaPitch = OCARINA_PITCH_D5; sCurOcarinaButtonIndex = OCARINA_BTN_C_UP; } diff --git a/mm/src/code/stubs.c b/mm/src/code/stubs.c index a40bb8e83..35de8a506 100644 --- a/mm/src/code/stubs.c +++ b/mm/src/code/stubs.c @@ -184,13 +184,13 @@ void gSPSegmentLoadRes(void* value, int segNum, uintptr_t target) { __gSPSegment(value, segNum, target); } -void gDPSetTextureImage(Gfx* pkt, u32 format, u32 size, u32 width, uintptr_t i) { - __gDPSetTextureImage(pkt, format, size, width, i); -} +// void gDPSetTextureImage(Gfx* pkt, u32 format, u32 size, u32 width, uintptr_t i) { +// __gDPSetTextureImage(pkt, format, size, width, i); +// } -void gDPSetTextureImageFB(Gfx* pkt, u32 format, u32 size, u32 width, int fb) { - __gDPSetTextureImageFB(pkt, format, size, width, fb); -} +// void gDPSetTextureImageFB(Gfx* pkt, u32 format, u32 size, u32 width, int fb) { +// __gDPSetTextureImageFB(pkt, format, size, width, fb); +// } void gSPDisplayList(Gfx* pkt, Gfx* dl) { char* imgData = (char*)dl; diff --git a/mm/src/code/z_kankyo.c b/mm/src/code/z_kankyo.c index f391ff095..ec169e4d3 100644 --- a/mm/src/code/z_kankyo.c +++ b/mm/src/code/z_kankyo.c @@ -3161,13 +3161,14 @@ void Environment_DrawSkyboxStarsImpl(PlayState* play, Gfx** gfxP) { { 0xD058, 0x4C2C, 0x3A98 }, { 0xD8F0, 0x36B0, 0x47E0 }, { 0xD954, 0x3264, 0x3E1C }, { 0xD8F0, 0x3070, 0x37DC }, { 0xD8F0, 0x1F40, 0x5208 }, { 0xD760, 0x1838, 0x27D8 }, { 0x0000, 0x4E20, 0x4A38 }, { 0x076C, 0x2328, 0xDCD8 }, }; - static const Color_RGBA8_u32 D_801DD8E0[] = { + // 2S2H [Port] Switched from Color_RGBA8_u32 to Color_RGBA8 to avoid endianenes struct union ordering issues + static const Color_RGBA8 D_801DD8E0[] = { { 65, 164, 255, 255 }, { 131, 164, 230, 255 }, { 98, 205, 255, 255 }, { 82, 82, 255, 255 }, { 123, 164, 164, 255 }, { 98, 205, 255, 255 }, { 98, 164, 230, 255 }, { 255, 90, 0, 255 }, }; // 2S2H [Port] This originally had `UNALIGNED` however we don't need that for PC and it was causing warnings in the // header file - static const Color_RGBA8_u32 D_801DD900[] = { + static const Color_RGBA8 D_801DD900[] = { { 64, 80, 112, 255 }, { 96, 96, 128, 255 }, { 128, 112, 144, 255 }, { 160, 128, 160, 255 }, { 192, 144, 168, 255 }, { 224, 160, 176, 255 }, { 224, 160, 176, 255 }, { 104, 104, 136, 255 }, { 136, 120, 152, 255 }, { 168, 136, 168, 255 }, { 200, 152, 184, 255 }, { 232, 168, 184, 255 }, @@ -3268,9 +3269,12 @@ void Environment_DrawSkyboxStarsImpl(PlayState* play, Gfx** gfxP) { } if ((i < 15) || ((i == 15) && ((((void)0, gSaveContext.save.day) % 7) == 0))) { - gDPSetColor(gfx++, G_SETPRIMCOLOR, D_801DD8E0[i % ARRAY_COUNTU(D_801DD8E0)].rgba); + // 2S2H [Port] Switched from gDPSetColor to gDPSetPrimColor for Color_RGBA8 individual fields + Color_RGBA8 color = D_801DD8E0[i % ARRAY_COUNTU(D_801DD8E0)]; + gDPSetPrimColor(gfx++, 0, 0, color.r, color.g, color.b, color.a); } else if (((i & 0x3F) == 0) || (i == 16)) { - gDPSetColor(gfx++, G_SETPRIMCOLOR, D_801DD900[phi_v1 % ARRAY_COUNTU(D_801DD900)].rgba); + Color_RGBA8 color = D_801DD900[phi_v1 % ARRAY_COUNTU(D_801DD900)]; + gDPSetPrimColor(gfx++, 0, 0, color.r, color.g, color.b, color.a); phi_v1++; } diff --git a/mm/src/code/z_parameter.c b/mm/src/code/z_parameter.c index 45525c678..42487add4 100644 --- a/mm/src/code/z_parameter.c +++ b/mm/src/code/z_parameter.c @@ -7391,10 +7391,10 @@ void Interface_DrawTimers(PlayState* play) { s16 j; s16 i; // 2S2H [Cosmetic] Hud editor values for timers - s16 newTimerX; - s16 newTimerY; - u8 modifiedTimerHudValues; - s16 hudTimerElement; + s16 newTimerX = 0; + s16 newTimerY = 0; + u8 modifiedTimerHudValues = false; + s16 hudTimerElement = HUD_EDITOR_ELEMENT_NONE; OPEN_DISPS(play->state.gfxCtx); diff --git a/mm/src/code/z_play.c b/mm/src/code/z_play.c index 0d7dab16d..a939ed217 100644 --- a/mm/src/code/z_play.c +++ b/mm/src/code/z_play.c @@ -467,6 +467,9 @@ void Play_Destroy(GameState* thisx) { KaleidoScopeCall_Destroy(this); KaleidoManager_Destroy(); ZeldaArena_Cleanup(); + + GameInteractor_ExecuteOnPlayDestroy(); + // #region 2S2H [General] Making gPlayState available gPlayState = NULL; // #endregion diff --git a/mm/src/overlays/actors/ovl_Arms_Hook/z_arms_hook.c b/mm/src/overlays/actors/ovl_Arms_Hook/z_arms_hook.c index bceca1c3d..686e9572b 100644 --- a/mm/src/overlays/actors/ovl_Arms_Hook/z_arms_hook.c +++ b/mm/src/overlays/actors/ovl_Arms_Hook/z_arms_hook.c @@ -7,6 +7,7 @@ #include "z_arms_hook.h" #include "objects/gameplay_keep/gameplay_keep.h" #include "objects/object_link_child/object_link_child.h" +#include "2s2h/Enhancements/GameInteractor/GameInteractor.h" #define FLAGS (ACTOR_FLAG_10 | ACTOR_FLAG_20) diff --git a/mm/src/overlays/actors/ovl_Boss_02/z_boss_02.c b/mm/src/overlays/actors/ovl_Boss_02/z_boss_02.c index 00e04e370..2fe43d749 100644 --- a/mm/src/overlays/actors/ovl_Boss_02/z_boss_02.c +++ b/mm/src/overlays/actors/ovl_Boss_02/z_boss_02.c @@ -12,6 +12,7 @@ #include "overlays/actors/ovl_Item_B_Heart/z_item_b_heart.h" #include "objects/gameplay_keep/gameplay_keep.h" #include "2s2h/Enhancements/FrameInterpolation/FrameInterpolation.h" +#include "2s2h/Enhancements/GameInteractor/GameInteractor.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_UNFRIENDLY | ACTOR_FLAG_10 | ACTOR_FLAG_20) diff --git a/mm/src/overlays/actors/ovl_En_Dnq/z_en_dnq.c b/mm/src/overlays/actors/ovl_En_Dnq/z_en_dnq.c index eb5b47181..fc24454ec 100644 --- a/mm/src/overlays/actors/ovl_En_Dnq/z_en_dnq.c +++ b/mm/src/overlays/actors/ovl_En_Dnq/z_en_dnq.c @@ -457,10 +457,12 @@ void func_80A52FB8(EnDnq* this, PlayState* play) { } void EnDnq_HandleCutscene(EnDnq* this, PlayState* play) { + //! @bug The credits cutscene accesses this array OOB with a cueId of 6, which ends up giving 0 static s32 sCsAnimIndex[] = { DEKU_KING_ANIM_IDLE, DEKU_KING_ANIM_IDLE_MORPH, DEKU_KING_ANIM_SURPRISE, DEKU_KING_ANIM_JUMPED_ON_START, DEKU_KING_ANIM_JUMPED_ON_END, DEKU_KING_ANIM_JUMPED_ON_END_MORPH, + DEKU_KING_ANIM_IDLE, // 2S2H [Port] Added to prevent a crash with garbage data for cueId 6 }; s32 cueChannel; u32 cueId; diff --git a/mm/src/overlays/actors/ovl_En_Test4/z_en_test4.c b/mm/src/overlays/actors/ovl_En_Test4/z_en_test4.c index 5900c4a9c..fb9a88f3b 100644 --- a/mm/src/overlays/actors/ovl_En_Test4/z_en_test4.c +++ b/mm/src/overlays/actors/ovl_En_Test4/z_en_test4.c @@ -8,6 +8,7 @@ #include "z64horse.h" #include "overlays/gamestates/ovl_daytelop/z_daytelop.h" #include "overlays/actors/ovl_En_Horse/z_en_horse.h" +#include "2s2h/Enhancements/GameInteractor/GameInteractor.h" #define FLAGS (ACTOR_FLAG_10 | ACTOR_FLAG_20 | ACTOR_FLAG_100000) @@ -443,7 +444,9 @@ void func_80A42AB8(EnTest4* this, PlayState* play) { if (CURRENT_DAY == 3) { if ((this->nextBellTime == CLOCK_TIME(0, 0)) && - ((gSaveContext.save.saveInfo.inventory.items[SLOT_OCARINA] == ITEM_NONE) || + (GameInteractor_Should(GI_VB_CLOCK_TOWER_OPENING_CONSIDER_THIS_FIRST_CYCLE, + gSaveContext.save.saveInfo.inventory.items[SLOT_OCARINA] == ITEM_NONE, + this) || (play->sceneId == SCENE_CLOCKTOWER))) { s32 playerParams; u32 entrance = gSaveContext.save.entrance; diff --git a/mm/src/overlays/actors/ovl_player_actor/z_player.c b/mm/src/overlays/actors/ovl_player_actor/z_player.c index 84e74fd50..7dfdc0419 100644 --- a/mm/src/overlays/actors/ovl_player_actor/z_player.c +++ b/mm/src/overlays/actors/ovl_player_actor/z_player.c @@ -18258,10 +18258,11 @@ void func_80855218(PlayState* play, Player* this, struct_8085D910** arg2) { } u16 D_8085D908[] = { - WEEKEVENTREG_30_80, // PLAYER_FORM_FIERCE_DEITY - WEEKEVENTREG_30_20, // PLAYER_FORM_GORON - WEEKEVENTREG_30_40, // PLAYER_FORM_ZORA - WEEKEVENTREG_30_10, // PLAYER_FORM_DEKU + WEEKEVENTREG_30_80, // PLAYER_FORM_FIERCE_DEITY + WEEKEVENTREG_30_20, // PLAYER_FORM_GORON + WEEKEVENTREG_30_40, // PLAYER_FORM_ZORA + WEEKEVENTREG_30_10, // PLAYER_FORM_DEKU + PACK_WEEKEVENTREG_FLAG(16, 0x0A), // 2S2H [Port] Added to match OOB value read on console for human form }; struct_8085D910 D_8085D910[] = { { 0x10, 0xA, 0x3B, 0x3F }, @@ -18297,6 +18298,11 @@ void Player_Action_86(Player* this, PlayState* play) { this->actor.draw = NULL; this->av1.actionVar1 = 0; Play_DisableMotionBlurPriority(); + //! @bug When taking off a transformation mask, PLAYER_FORM_HUMAN will index OOB leading + // to the next value causing WEEKEVENT_REG 16 being set with 0x0A which sets two flags at once + // WEEKEVENTREG_16_02 and WEEKEVENTREG_16_08 + // WEEKEVENTREG_16_02 corresponds to showing a text ID from the Gorman Brothers on the 3rd day + // if the player has saved the farm, so this bug would prevent that text from displaying SET_WEEKEVENTREG(D_8085D908[GET_PLAYER_FORM]); } } else if ((this->av1.actionVar1++ > ((this->transformation == PLAYER_FORM_HUMAN) ? 0x53 : 0x37)) || diff --git a/mm/src/overlays/gamestates/ovl_file_choose/z_file_choose_NES.c b/mm/src/overlays/gamestates/ovl_file_choose/z_file_choose_NES.c index 80a0c29f5..6befa3948 100644 --- a/mm/src/overlays/gamestates/ovl_file_choose/z_file_choose_NES.c +++ b/mm/src/overlays/gamestates/ovl_file_choose/z_file_choose_NES.c @@ -15,6 +15,7 @@ #include "2s2h/Enhancements/FrameInterpolation/FrameInterpolation.h" #include "2s2h_assets.h" #include +#include "BenPort.h" s32 D_808144F10 = 100; f32 D_808144F14 = 8.0f; @@ -1832,9 +1833,15 @@ void FileSelect_DrawWindowContents(GameState* thisx) { PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0); gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, this->emptyFileTextAlpha); gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 0); - gDPLoadTextureBlock(POLY_OPA_DISP++, sWarningLabels[this->warningLabel], G_IM_FMT_IA, G_IM_SIZ_8b, 128, 16, 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); + if (ResourceMgr_GetGameVersion(0) == MM_NTSC_US_GC) { + gDPLoadTextureBlock_4b(POLY_OPA_DISP++, sWarningLabels[this->warningLabel], G_IM_FMT_IA, 128, 16, 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); + } else { // MM_NTSC_US_10 + gDPLoadTextureBlock(POLY_OPA_DISP++, sWarningLabels[this->warningLabel], G_IM_FMT_IA, G_IM_SIZ_8b, 128, 16, + 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, + G_TX_NOLOD, G_TX_NOLOD); + } gSP1Quadrangle(POLY_OPA_DISP++, 16, 18, 19, 17, 0); } diff --git a/mm/src/overlays/gamestates/ovl_title/z_title.c b/mm/src/overlays/gamestates/ovl_title/z_title.c index 6cf5bdf59..d94842021 100644 --- a/mm/src/overlays/gamestates/ovl_title/z_title.c +++ b/mm/src/overlays/gamestates/ovl_title/z_title.c @@ -25,10 +25,10 @@ static const ALIGN_ASSET(2) char gLUSLogoTextTex[] = dgLUSLogoTextTex; const char* GetGameVersionString() { uint32_t gameVersion = ResourceMgr_GetGameVersion(0); switch (gameVersion) { - // BENTODO: Use enums from LUS once added and add rest of version names - case 0x5354631C: - case 0xDA6983E7: + case MM_NTSC_US_10: return "MM-US 1.0"; + case MM_NTSC_US_GC: + return "MM-US GC"; default: return "UNKNOWN"; } diff --git a/mm/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_mask.c b/mm/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_mask.c index 5b85511cc..13583678c 100644 --- a/mm/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_mask.c +++ b/mm/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_mask.c @@ -8,6 +8,7 @@ #include "interface/parameter_static/parameter_static.h" #include "BenGui/HudEditor.h" +#include "2s2h/Enhancements/GameInteractor/GameInteractor.h" s16 sMaskEquipState = EQUIP_STATE_MAGIC_ARROW_GROW_ORB; diff --git a/mm/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope_NES.c b/mm/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope_NES.c index 172e06919..071f4d208 100644 --- a/mm/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope_NES.c +++ b/mm/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope_NES.c @@ -18,6 +18,7 @@ #include "archives/item_name_static/item_name_static.h" #include "archives/map_name_static/map_name_static.h" #include "2s2h/Enhancements/FrameInterpolation/FrameInterpolation.h" +#include "2s2h/Enhancements/Saving/SavingEnhancements.h" #include "2s2h_assets.h" @@ -3377,7 +3378,7 @@ void KaleidoScope_Update(PlayState* play) { if (!pauseCtx->itemDescriptionOn && (CHECK_BTN_ALL(input->press.button, BTN_START) || CHECK_BTN_ALL(input->press.button, BTN_B))) { Interface_SetAButtonDoAction(play, DO_ACTION_NONE); - if (CVarGetInteger("gEnhancements.Saving.PauseSave", 0)) { + if (CVarGetInteger("gEnhancements.Saving.PauseSave", 0) && SavingEnhancements_CanSave()) { if (CHECK_BTN_ALL(input->press.button, BTN_B)) { pauseCtx->state = PAUSE_STATE_SAVEPROMPT; Audio_PlaySfx_MessageDecide(); @@ -3418,7 +3419,7 @@ void KaleidoScope_Update(PlayState* play) { // Abort having the player play the song and close the pause menu AudioOcarina_SetInstrument(OCARINA_INSTRUMENT_OFF); Interface_SetAButtonDoAction(play, DO_ACTION_NONE); - if (CVarGetInteger("gEnhancements.Saving.PauseSave", 0)) { + if (CVarGetInteger("gEnhancements.Saving.PauseSave", 0) && SavingEnhancements_CanSave()) { if (CHECK_BTN_ALL(input->press.button, BTN_B)) { pauseCtx->state = PAUSE_STATE_SAVEPROMPT; Audio_PlaySfx_MessageDecide(); @@ -3461,7 +3462,7 @@ void KaleidoScope_Update(PlayState* play) { if (CHECK_BTN_ALL(input->press.button, BTN_START) || CHECK_BTN_ALL(input->press.button, BTN_B)) { AudioOcarina_SetInstrument(OCARINA_INSTRUMENT_OFF); Interface_SetAButtonDoAction(play, DO_ACTION_NONE); - if (CVarGetInteger("gEnhancements.Saving.PauseSave", 0)) { + if (CVarGetInteger("gEnhancements.Saving.PauseSave", 0) && SavingEnhancements_CanSave()) { if (CHECK_BTN_ALL(input->press.button, BTN_B)) { pauseCtx->state = PAUSE_STATE_SAVEPROMPT; Audio_PlaySfx_MessageDecide(); @@ -3518,7 +3519,7 @@ void KaleidoScope_Update(PlayState* play) { // 2S2H [Enhancement] Eventually we might allow them to load from their last entrance, // but we need to first identify and fix edge cases where that doesn't work properly // like grottos and cutscenes - gSaveContext.save.shipSaveInfo.pauseSaveEntrance = GetSaveEntrance(play); + gSaveContext.save.shipSaveInfo.pauseSaveEntrance = SavingEnhancements_GetSaveEntrance(); } Play_SaveCycleSceneFlags(&play->state); gSaveContext.save.saveInfo.playerData.savedSceneId = play->sceneId;