From 5f718932e616fa2f0aacbc411e8a44afddd2ee9a Mon Sep 17 00:00:00 2001 From: KiritoDev <36680385+KiritoDv@users.noreply.github.com> Date: Mon, 25 Jul 2022 20:11:53 -0500 Subject: [PATCH 01/25] Nintendo switch support (#935) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Moved gfx effects to the gpu and removed loadtexbyname on some textures * Readded empty if * Added nintendo switch support * Fixed compilation errors and window closing issue on linux * Fixed kaleido on 64 bit * Fixed audio on nintendo switch * Implemented performance mode switcher * Added suggestions from pr review * Fixed ftruncate errors * Fixed compilation errors * Added missing include rule * Fixed libstorm path * Removed ftruncate extern to use a correct posix version * Merge branch 'develop' from HarbourMasters into znx (#3) * Add Support for macOS (#441) * Fixed soh filters * add more makefile changes * almost ready * more updates * update * update * Update Makefiles to handle both platforms * Allow for overriding the CXX and CC executables * Restore original structure while supporting custom CXX flags * Remove some platform specific libs * Dynamic target name * Make X11 paths package-agnostic * Remove changes to `gfx_opengl.cpp` * Use OpenGL2 on MacOS instead of OpenGL3 * make it actually render something * render at least the first texture, still need to figure out the second one * Let’s use OpenGL 3 again * maybe this works to get the right texture? link's eyes still look off a bit * did this work? * set the platform to macos * actual numbers are right, but logic is ugly XXX/TODO, i know * add zlib to ldflags for ZAPDUtils * A bit of cleanup * Revert unneeded changes * Remove GL_CHECK * Fix issues with z64 branch * use an std::map instead of a giant array * three point filter fix (#2) * Fix mac compilation * fix audio for 64 bit * revert audio heap size, keep bigger pools * Add more Apple specific checks to our modifications * Add building instructions for macOS * Remove unecessary step from building instructions * Add missing SDL2 & GLEW to Linux LDLIBS * Update BUILDING.md Co-authored-by: BountyChocolate123456 <101743444+BountyChocolate123456@users.noreply.github.com> * Update soh/.gitignore to include other arch binaries Co-authored-by: BountyChocolate123456 <101743444+BountyChocolate123456@users.noreply.github.com> * Use right platform name for debugging window Co-authored-by: BountyChocolate123456 <101743444+BountyChocolate123456@users.noreply.github.com> * Fix stormlib on macos (arm64) * Simplify some of the ifdef checks * Revert an older no longer necessary fix * Remove remaining unecessary deviations * Update building instructions after StormLib changes * Feature: Use OpenGL 4.1 (#1) * Further tweak the BUILDING * Tidy up * reword -j message * Add Jenkins CI Support (#2) * Fix type issues * add target and add makefile targets to create an .app `filledappbundle` creates the target with the .otr included this should perhaps be moved to Application Support though * pull gcc's rpath from otool output * move make target to the end so it's not default * Add Jenkins and make exe in par with other platforms * Actually save build artefacts * Fix artefact path * Remove x11 mentions and linking (not used) * Update building instructions for generating app * use appsupport directory * Add new app icon * Update target to match macOS types * Update more audio types * fix null deref in Audio_PlayFanfare * Remove old import from z64 * address final nit with apple ifdefs Co-authored-by: KiritoDev <36680385+KiritoDv@users.noreply.github.com> Co-authored-by: Jeffrey Crowell Co-authored-by: BountyChocolate123456 <101743444+BountyChocolate123456@users.noreply.github.com> * Move macOS to parallel stage * fix linux crash * Ignore all named saves Necessary after new save format * DPad items * Move UI location arrays from static to global to accomodate customizable UI * FIX: Increased the maximum actor limit for draw distance Fix issue #529 * FIX: Remove duplicates of gNewDrops from the enhancements menu * Get rid of erroneous int casts * casts jya_cobra's shadowTexture pointer to uintptr_t instead of s32. * Fix ability to assign equipment you don't own * Fix title cards for market potion shop and bombchu shop * Invalidate message item icon texture before drawing * Add margins for dpad * Fixed some instances where the original OOT save is erroneously preserved or recreated, leading to another conversion next time you launched the game * Headphones setting in game should now work. Resolves #13 * Map Select name fixes * Change Power to Upgrades * Rename Soh* files * Update names * Add more files * Add more files * Add toggles for disabling heart drops and random drops (#507) * Adds toggles for disabling random drops and fixed heart drops * Changed the "No Fixed Heart Drops" toggle to the more useful "No Random Heart Drops" toggle * Adds an explanation that the no heart drops option is similar to Hero Mode * Moved difficulty options into their own sub-menu Moved time saver options into their own sub-menu Moved clutter reducing options into their own sub-menu * fixed the tag name of mweep speed * Moved Skip Text to Experimental * Fix testing masks of DPad * Fix audio, boot commands, and save staes. * add menu from https://github.com/PurpleHato/Shipwright/tree/ResetMenu * implement reset * Update README.md * command on mac * special char doesn't work with default imgui font * change name based on PR comment * missed a couple spots * change sunset in save editor so dampe is out * Update to latest `docking` imgui (#582) * Update to latest `docking` imgui commit: 67410d53f739b6a0df138e2252f0e5136b42062f * Fix modified import for SDL * Update imgui_impl_sdl.cpp * Add Imgui include path for better imports * Controller Navigation Fix-Up (#544) * Controller Navigation Fix-Up * [MISC] Fix typo * Use Macro for __FILE__ & __LINE__ when possible (#559) * First batch some overlay * Almost all overlay * effect & gamestate * kaleido stuffs * more overlay * more left over from code folder * remaining hardcoded line and file * Open & Close _DISP __FILE__ & __LINE__ clean up * Some if (1) {} remove * LOG_xxxx __FILE__ , __LINE__ cleaned * ASSERT macro __FILE__ __LINE__ * mtx without line/file in functions * " if (1) {} " & "if (0) {}" and tab/white place * LogUtils as macro * GameState_, GameAlloc_, SystemArena_ & ZeldaArena_ * Revert "GameState_, GameAlloc_, SystemArena_ & ZeldaArena_" This reverts commit 0d85caaf7e342648c01a15fe21e93637352dc596. * Like last commit but as macro * Fix matrix not using macros * use function not macro * DebugArena_* functions GameAlloc_MallocDebug BgCheck_PosErrorCheck as macros removed issues with ; in macro file * MM Bunny Hood enhancements: no age restrictions & wear across entrances (#560) * Remove age restriction on MM Bunny Hood * Handle mask slot changing; init Link wearing mask * Reset mask state after selling * Use unordered maps in some hot paths (#566) * Use unordered maps in some hot paths * Address PR comments * Cheat: Infinite Epona Boost (#577) * Cheat: Infinite Epona Boost * Edit for readability * update pulseaudio for 44.1khz audio (#587) * use pulseaudio defaults * spaces/tabs * pulseaudio values tuned for n64 audio at 44.1khz * update tlength * remove one hardcoded samplerate Co-authored-by: briaguya * Restoration Item Sliders (#595) * Allows players to set custom restoration values for potions and milk * Fixed a dumb oversight * implemented fairy sliders * use ini window resolution (#410) * use ini window resolution * use arguments for directx window size * default 640x480 not 320x240 * kick off a build * and revert * default config 640x480 not 320x240 * add todo Co-authored-by: briaguya * 3D Drops & Projectiles update (#548) * Fix remaining rupee and keys * fix tabs -> spaces * more fix about tabs -> spaces * Better up <-> down mouvement for hearts * remove useless comment * Cosmetics menu rework (#589) * - * DPad/some margin fix(left side) * various ImGui stuff and fixes * disabled kaleido menu (non working) * fix win being dumb * same for C btn this time * Fix windows build * Beating hearts fix * Default win size and some placement fix * Fix Dpad Ammo & C notes, Kaleido, white dog * some texts fix and tab move * Add stone of agony, some fixes and build correctly * precise item place with Dpad * Gamecube -> GameCube Co-authored-by: Baoulettes * [CI] Create an Appimage for 64bit builds (#570) * [CI] Create AppImage file * [CI] Updated Jenkinsfile * [MISC] fix indentation * [MISC] Fix indentation * [MISC] Fix indentation * [CI] 7z appimage and readme * [CI] AppImage icon file (#597) * [CI] Add patchelf * [BUILD] Include Hi-Res icon * Fix portability use of std::clamp (#596) * Add N64 weird frames and OOB Bombchus cvars (#602) * Add gN64WeirdFrames and gBombchuOOB cvars * Rename gBombchuOOB to gBombchusOOB * Fix pipeline * [BUILD] Do not strip ZAPD (#598) * [BUILD] Do not strip ZAPD * [BUILD] Reuse Icon Asset * [APPIMAGE] Handle paths with spaces * [macos] Distribute optimized builds (#599) * Cosmetics texts fixes (#604) * branch init + few fixes * Reset button * Several texts fixes and default color to GameCube * space issues * some more extra space that was not needed. * space yes last time ... * Arrows being able to be rainbow some more texts fixes * more texts fixes * c-buttons some plurial fix * Fixes bug in demo effect due to removed display list set. * King dodongo room crash (#613) * first attempt * force camera setting to be at least 0 (dirty!) * - * reverted something to just include fix * Invalidate text box icon before drawing (#607) * [APPIMAGE] Set lib path for ZAPD (#611) * New drop runtime fix (#614) * inital rework * fixed default rotation for 2D sprites * fix tab/space issues * Fix Ganon's Castle title cards (#606) * Checkered room crash workaround (#615) * Increase poly and vertex count for dyna actors * Add TODO * Only apply fix in Forest Temple * Enable globally * Match case of 'Shipwright' in Linux build (#619) * Fix 0xabababab crash (#617) * Unconditionally setup the normal skybox * Only call Skybox_Setup once ever * Equipment upgrade text fix and any pause slot enhancement fix (#620) * Fix upgrade name text not rendering * Use cvar and don't render equip help for empty item slots * Fix rendering logic * Fix incorrect item name rendered for one frame * Reorder comparison * Remove extra indent * Remove accidental changes * ImGui grammer, consistency, and clarity fixes (#625) * ImGui grammer, consistency, and clarity fixes Co-Authored-By: Stormghetti <56653191+Stormghetti@users.noreply.github.com> * Adds more new lines for users on smaller displays Co-Authored-By: Stormghetti <56653191+Stormghetti@users.noreply.github.com> Co-authored-by: Stormghetti <56653191+Stormghetti@users.noreply.github.com> * New drops shadows & rotation fixes (#627) * fixes * forgot to add heart pieces in rotation logic * Dodongo's Cavern blue warp crash fix (#622) * Doodong's Cavern blue warp crash fix * >= not > * Don't waste a line of space * add support for clang compiler (#592) * hacks to align strings for clang... wow just wow * start work to getting built with clang * fix issues with struct constructors, all builds, doesn't link still * fix some narrowing issues that clang complains about * fix compliation of zapd * fix null deref in VersionInfo * builds with clang * make stringbuilding use StringHelper instead of addition * fix linking * add CLANG SHIP overlay on clang built versions * doesn't need to be volatile * mark unknown strings as extern * rename some stuff * can't align extern * hopefully fix compilation for everythign * expandtab * allow setting LD * Revert "allow setting LD" This reverts commit 711aba6db2c41bab476bd34e878af6a37a7f5559. maybe to use lld it should be a LDFLAG? * -Wno-deprecated-declarations is required for newer versions of clang on macOS 13 beta sdk, the version of apple clang requires this * Add jenkins support for clang * Forward CXX flags to stormlib compilation * Move GCC only flags to check * use exports to set multiarch setup * Fix Jenkins forever * use make instead of cmake --build add some flags to build with clang-11 as well * address review coments - rework extraction to allow multi thread - misc readability cleanup * update makefile to add WARN on linux+clang Co-authored-by: David Chavez * Fix develop * Fixes grey screen issue + tooltip for 2 handed shield * Don't close controller after SDL has quit (#642) * Don't close controller after SDL has quit * Don't check if controller can rumble if null * Fixes Barinade's set whenever boss fight is reloaded (#639) * Reimplements unused Barinade reset function. * Removes the Jellyfish from Barinade's body on reset. * add the ability to pull graves during the day (#637) * change max internal res multiplier to 3x, use float and % instead of int (#638) * change max internal res multiplier to 3x, use float and % instead of int * Update libultraship/libultraship/ImGuiImpl.cpp Co-authored-by: Kenix3 Co-authored-by: briaguya Co-authored-by: Kenix3 * Fixes crash on Biggoron trade failure screen wipe Resolves #621 * fixes center docking (#652) * testing out item replacement (#416) * skip learning song of storms * don't set flag when getting goron tunic as child * Initiates prelude check when master sword unloads. Not quite how N64 rando does it but so far it's the only way I've found to make it trigger without also triggering the time travel again. * Stops Shadow Temple lore prompts from appearing in rando. * Skips cutscene of royal tomb explosion in rando. Explosion sound doesn't play correctly and I think the debris appears in the wrong place, but the functionality is here. * Improves visual of exploding gravestone. * Adds some comments explaining the rando differences * Skip ruto text box in jabu blue warp For rando * skip intro cutscene in dodongo's cavern * load spoiler files on boot, fix spoilerfile existing check when making new saves * name entry dropped spoiler logic * make sure to actually init the cvar * no chime on load * uncomment * Skip ganondrof cutscene Skip to scream part of the death animation, skipping the text boxes etc. For rando * Update z_boss_ganondrof.c * skip owl flight cutscenes in rando * Fixes skipped text so it only applies to shadow temple. Earlier fix inadvertently applied to some other text as well, changed logic so that only specified sceneNums and textIds can have this enabled, and text skipped by sceneNum can have the skip overriden by textId if needed. Currently there are no overrides so the textId section of the logic is commented out to avoid compilation errors. * Adds a default to the switch case statements that leaves the randoSkipText variable unchanged, just in case. * TEST: Text for item * Adding ganon flavor text * ADD: AMMO Count * format ganon text/hint text * Autoskip the tower cutscene if settings call for tower collapse. * ganon hint text logic * Improved prelude after time travel fix * swapped the sizes between ganon hint text and ganon text, as they were set to the wrong things. * this is all i did * not the cleanest code ever but it's working * ADD: GS Count * ADD: Wallter (crash for now) * TWEAK: Wallet check * FIX: Use DrawItem instread of DrawUpgrade... b-baka! * Fixes some vanilla bugs introduced by rando code. * Added cutscene skip for zelda escaping Using the debug cutscene skipping function. Also added a conditional so the bridge doesn't spawn closed when cutscene is ready to trigger * ADD: X Spacing + Placeholders for song * ADD: default case for items * TWEAK: Spacing * FIX: Light Arrow * ADD: Ammo Option * use groups instead * ADD: More spacing logic * songs and names * TWEAK: Color on wallet * colors * Added flags cutscene before nabooru fight * ADD: ChromaKey text * First attempt skip cs after nabooru defeat * Better implementation for specific rando cutscene skips * use pulseaudio defaults * spaces/tabs * move color push/pop to stop crash * make the colors work again * the real bottle fix * pulseaudio values tuned for n64 audio at 44.1khz * update tlength * remove one hardcoded samplerate * Cleaned up and fixed zelda escape skip The if statement is a freaking monster, but unless we want to skip more cutscenes in the same way later, this is the most compact way of doing it that I know of. * Revert one line to match original nothing functional * another hint line that breaks autonewline logic * don't autospawn epona if we don't have the song/ocarina * Trying to use iron knuckle death effects not working yet * Streamlined OoT cutscene skip for future additions Also cleaned up if statement in general * Made if statement more readable Also added clarity for what cutscene was skipped * Fixed typo in comment * Janky nabooru defeat cs skip * altar text formatting (gonna need help shortening some of the french ones) * more altar text formatting * english altar text formatting complete * make gtg blocking guard check for card not bridge * FIX: Typo! * FIX: Uppercases * FIX: Typo * TWEAK: Alter + some names * TWEAK: More caps! * ADD: Missing string TWEAK more uppercases and namefixe s * Hide nabooru death by covering her in flames * bandaid fix for death crash issue * Twinrova defeat cs skip Skips the animation and manually calls the function to show the "beam" around the sisters * fix crash * fix caps to match * fix great fairy reward mashing/shielding issue * TWEAK : Typo clé to Clé * TWEAK: Some Altar hints TWEAK: Some capitals * TWEAK: Unmatching text + some cap again * TWEAK: More tweaks * fix build * remove extra json.hpp, add hint * Update randomizer_item_tracker.cpp * TWEAK: Double Defense with RedParticles instead of white * make sure we don't optimize out the check to ensure a spoilerfile exists * vanilla ganon boss key hint formatting * TWEAK: FR- better way of the hero text * fix * and again * Initializes dungeonsDone items in gSaveContext to 0. * Replaces sizeof calculation with a NUM_DUNGEONS constant. * Fixes Saria's Gift on the LW Bridge from getting killed when holding shield. * More airtight fix for Saria's Gift on the Bridge. * Lifts one of the conditions in the if statement a little higher to prevent unnecessary lookups of getItemId. * Invalidate text box icon before drawing * Fixes the case where Saria's gift is an Ice Trap. We still get the Ice Trap once, but never again. This does mean you can now hold R while walking in to avoid the ice trap, but everything else seems to work fine. * Initial commit Might need changing when we change the settings in the future * Fixes Door of Time opening cutscene after warping with prelude. * Initial waterfall skip Very rudimentary way of doing things but it seems to work so :shrug: * inital rework * fixed default rotation for 2D sprites * fix tab/space issues * 3d drops rando merge fix again * Allows Impa to appear in the Lullaby check post drawbridge escape. * Changes Ganon's Trials Count setting to a checkbox The checkbox is whether or not to skip all of them. Leaving the box unchecked will mean doing all of them. Eventually this will be switched back to a slider once we implement the logic for which trials start out completed. * Sets all Ganon's Trials to incomplete in new saves. Fixes https://github.com/briaguya-ai/rando-issue-tracker/issues/131 * fix castle guards when oot throw cutscene has already played in rando * Properly removes the beams when trials are cleared. * Removes Question Mark from Skip Ganon's Trials UI. * Adds a todo comment about when to change back to slider. * make deku seeds check for bullet bag * Various tweaks TWEAK: Altar Text TWEAK: Hint names TWEAK: Replace more problematic œ to oe * upgrade ocarina on both child and adult equips * FIX: Jabu Item * update equipped hookshot/longshot when obtained as other age * add hint * don't give the bgs check without the claim check * Skips Darunia Cutscene in Fire Temple * Added a TODO note about not skipping the cutscene. There is a setting we will want to have eventually that will require this cutscene to not be skipped since it is used during a glitch. * remove todo * restore fast ocarina option in imgui that was lost in merge * Fixes grey screen issue + tooltip for 2 handed shield * update to use dg instead of g for textures in item tracker * TWEAK: Default color for cosmetic RAND button was not the corect one * fix texture crash, remove unused item tracker code * don't open mask shop until we get zelda's letter * Update README.md * Prevents "correct" chime under incorrect conditions. * Fixes typo in conditional and adds "bonk" sound effect. "Bonk" sound is NA_SE_SY_OCARINA_ERROR and it plays when conditions for the Door of Time have not been met after playing Song of Time. This is only possible in rando's "Intended" Door of Time option, in which the Ocarina of Time and all 3 spritual stones are required to open the door, instead of the vanilla requirements of just having the song of time. * remove modify dpad equips toggle, replace with checks for dpad menu * remove extra check * add ability to hold c-up to assign to dpad when dpad menuing is enabled * disable d-pad navigation on item menu when holding c-up to equip * dpad+c-up stuff for equipment menu * ADD: Checbox for songs colors * TWEAK: RandoColors for normal songs * kind of quick and dirty but it works * TWEAK: Clarity of the tooltip Co-authored-by: briaguya Co-authored-by: Christopher Leggett Co-authored-by: aMannus Co-authored-by: PurpleHato Co-authored-by: Dog <5172592+Dog@users.noreply.github.com> Co-authored-by: Vague Rant Co-authored-by: Baoulettes Co-authored-by: Ada <60364512+GreatArgorath@users.noreply.github.com> * Cosmetics hotfixes (#640) * Initial branch creation * Revert Main Game so it do not conflict later * should fix window build, made namespace for Cosmetics * forgot to edit one title * Ability to add hidden window (usefull for Rainbow) Fix building issues * Line break, unused bool remove * add descriptive todo for death crash bandaid (#655) Co-authored-by: briaguya * Removed legacy audio mode and fixed ganon sound bug (#657) * Free Camera (#337) * wip free cam * Almost done, needs collision still * Added free cam behind cvar * added WIP collision * Fixed & implemented "Manual mode" from WW & TP * Fixed camera not rotating when Link is moving * fixed initialized camera rotation * Fixed camera getting stuck + made it smoother * reduced deadzone * fixed epona camera height + added WW z-target free camera * Adjusted player camera height & fixed fov * Fixed camera roll * fixed fov when moving the camera while in z-target * Camera resets to Auto when going through doors or changing maps * Fixed building * touch * more touch work * Added WIP mouse support to the free cam * gui stuff * fixed building * fixed building error * ok fixed building for real this time * oops * Fix compilation issues * removed mouse stuff that magically appeared in this branch * smoothed out stick values & removed remains of mouse support * re-added manual camera when pressing Z * reduced minimum Y position of camera * Addressed dcsv's nitpicks * part 2 * oops Co-authored-by: David Chavez * Rando: Allows Malon's Item Check to be obtained by pulling out the Ocarina. [FIXED PR] (#672) * Fixes using the Ocarina to get the check from Malon. Still some cleanup to do here. For some reason the player can shield before receiving the check. It doesn't set the flag if the player does that so they can still try again, but would prefer a different solution if possible. * Prevents Shielding from blocking the Item_Give from happening. * Code Cleanup and comments explaining the new rando flow. * Removes inventory check when pulling out Ocarina This allows OI to properly give the check, which is important for Glitched logic later down the line. Talking to Malon still requires the Ocarina in your inventory. * Prevents non-malon textboxes from triggering the check. Also adds a comment explaining the condtional for getting the check from talking to Malon since it got pretty long. * Actually fixes checking for text boxes. * Relocates a comment for improved clarity. * Fix Rando Water Temple Softlock (#665) We use 3DS logic to generate item placement, but didn't have this specific door in Water Temple unlocked from the beginning like 3DS does. This meant that if people took specific paths through the temple, they could softlock themselves by missing a key. * Rando: GtG and carpenter prompts skip (#663) * Skip gtg and carpenter prompt For rando. Tested and just works. * Fixed missing break * Hide debug overlay behind gDebugEnabled (#660) * Introduce App Directory Path (#572) * Introduce app directory path concept * macos: Remove hacky way of using applicaiton directory * Update the new SaveManager * Address stack user after return * Remove unecessary property * Use std::string for filepath * Improve clang specific detections * Use new path system for imgui files * Improve helper for getting relative paths * fix hidden wnd (#744) * Split damage multiplication into its own PR (#656) * Split damage multiplication into its own PR * Found a more elegant implementation of the powers char*[] * Fixes Maps, Compasses, and Boss Keys in Vanilla. (#751) * .xiF slebaL * Update Keese labels * Fixed soundfont issues * Skip warp song cutscenes in rando (#664) Does it by skipping to the last part of the cutscene data. Tested on all songs, both adult and child. * don't spawn blocking mido after we've already shown him the sword/shield (#675) Co-authored-by: briaguya * Controller Configuration UI and JSON Config (#760) * Initial controller hud ui * Reverted fbdemo changes * Moved config to json and implemented controller config * fix build on linux, gitignore new config file * fix build * Fix compilation and file directory paths * Call save on cvar save * Fixed cvar loading and added deck slots to the config * Changed control deck port 0 to use a physical device by default * Added gyro and rumble & fixed loading errors * Save config on toggle menubar * fix linux build * Fixed drift calculation * Controller config now saves when pressing F1 * Removed ExitGame hook from ImGuiImpl * Moved mappings to a map * Added GetKeyName * untranslate scancodes * Fixed hud layout on keyboard device * Fixed keyboard read on hud * Fixed crash when reloading controllers * Removed ConfigFile and changed file extension * Changed Dummy to Disconnected and fixed filters * Removed function leftover * Changed ControllerHud to InputEditor Co-authored-by: briaguya Co-authored-by: David Chavez * Enough! My ship sails in the morning. * Fixed menubar items position (#763) * Fixed menubar items position * Reverted tooltip tab position * Fixes macOS randomizer functionality with App Directory (#761) * Fixes macOS randomizer functionality with App Directory * Fix windows build * Update soh/soh/Enhancements/randomizer/3drando/rando_main.cpp * Update soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp * Revert band-aid fix Co-authored-by: Kenix3 * Fix migration cvar deletion path (#765) * Various controller fixes (#771) * Fix controller * Also fix rumble strength being a bool * Remove ControllerHud.cpp * Downgrade platform toolset back to previous version * Fix gyro * Fix bug that makes binding axes difficult and clear buttons before reading * Exaggerate gyro display and adjust stick binding threshold * Initialize drift thresholds * git subrepo push soh subrepo: subdir: "soh" merged: "75ccbade8" upstream: origin: "https://github.com/HarbourMasters/soh.git" branch: "master" commit: "75ccbade8" git-subrepo: version: "0.4.1" origin: "???" commit: "???" * One more change from PR review * Fix some paths * Fix merge conflict messup * More merge conflict fixes * And another conflict fix * And another fix * Remove reference to removed build files * Add full path to switch cmake Co-authored-by: David Chavez Co-authored-by: KiritoDev <36680385+KiritoDv@users.noreply.github.com> Co-authored-by: Jeffrey Crowell Co-authored-by: BountyChocolate123456 <101743444+BountyChocolate123456@users.noreply.github.com> Co-authored-by: sholdee <102821812+sholdee@users.noreply.github.com> Co-authored-by: briaguya Co-authored-by: rozlette Co-authored-by: PurpleHato Co-authored-by: Christopher Leggett Co-authored-by: Kenix3 Co-authored-by: vaguerant Co-authored-by: earthcrafterman Co-authored-by: louist103 <35883445+louist103@users.noreply.github.com> Co-authored-by: briaguya <70942617+briaguya-ai@users.noreply.github.com> Co-authored-by: qurious-pixel <62252937+qurious-pixel@users.noreply.github.com> Co-authored-by: Baoulettes Co-authored-by: Sirius902 <10891979+Sirius902@users.noreply.github.com> Co-authored-by: modestposer Co-authored-by: Ada <60364512+GreatArgorath@users.noreply.github.com> Co-authored-by: Stormghetti <56653191+Stormghetti@users.noreply.github.com> Co-authored-by: Sirius902 <3645979-Sirius902@users.noreply.gitlab.com> Co-authored-by: MelonSpeedruns Co-authored-by: aMannus Co-authored-by: Dog <5172592+Dog@users.noreply.github.com> Co-authored-by: Nicholas Estelami Co-authored-by: ChristopherJTrent Co-authored-by: agamache Co-authored-by: M4xw * Fixed switch compilation * Fixed responsive on switch imgui * Remove config save hook * Added physical slots into controller name * Add `ifdef` for switch specific code * Add `ifdef` for switch specific code * Added applet mode detection * Replaced homebrew icon * Fixed randomness on applet mode view * Fixed clkrst initialization * Switch profiles cleanup * Cleaned code based on dcvz comments * Remove unused hooks in Mercury * Fixed compilation * Use IMGUI_IMPL_OPENGL_LOADER_CUSTOM * Fix up StormLib modifications * Handle touch events at ImGui/SDL level * Enable opening menu with - * Load Nintendo Switch font * Updates to window initiation * Handle virtual keyboard via SDL * Print OTR missing message to screen * Rename makefile for Switch * Some more additional fixes * Branch creation plus edit Changed ItemWidth & made label invisible (else issues) Added a submit button next to the text field * Removed set_texture_filter on imgui draw * Readded nintendo switch font * Fixed randomizer crash * Fix issue with strdup windows * [SWITCH] Update Jenkins file (#9) * [SWITCH] Update Jenkins file * [SWITCH] Dockerfile.switch Can be combined with other Dockerfile * [SWITCH] Add entrypoint file * Update Jenkinsfile * [SWITCH] Dockerfile mtab link link `/proc/self/mounts /etc/mtab` Co-authored-by: David Chavez * Cleaned code based on PR comments * Fixed switch compilation * Cleaned full texture cache instead of doing it per char * Randomizer only saves when its not a vanilla save * Disabled input when menubar is opened * Removed return from SetupFont * Cleaned code based on comments * Cleaned up random texts on switch error screen * Killed * Removed debug and changed compilation flags Co-authored-by: KiritoDv Co-authored-by: Felipe Guaycuru Co-authored-by: David Chavez Co-authored-by: Jeffrey Crowell Co-authored-by: BountyChocolate123456 <101743444+BountyChocolate123456@users.noreply.github.com> Co-authored-by: sholdee <102821812+sholdee@users.noreply.github.com> Co-authored-by: briaguya Co-authored-by: rozlette Co-authored-by: PurpleHato Co-authored-by: Christopher Leggett Co-authored-by: Kenix3 Co-authored-by: vaguerant Co-authored-by: earthcrafterman Co-authored-by: louist103 <35883445+louist103@users.noreply.github.com> Co-authored-by: briaguya <70942617+briaguya-ai@users.noreply.github.com> Co-authored-by: qurious-pixel <62252937+qurious-pixel@users.noreply.github.com> Co-authored-by: Baoulettes Co-authored-by: Sirius902 <10891979+Sirius902@users.noreply.github.com> Co-authored-by: modestposer Co-authored-by: Ada <60364512+GreatArgorath@users.noreply.github.com> Co-authored-by: Stormghetti <56653191+Stormghetti@users.noreply.github.com> Co-authored-by: Sirius902 <3645979-Sirius902@users.noreply.gitlab.com> Co-authored-by: MelonSpeedruns Co-authored-by: aMannus Co-authored-by: Dog <5172592+Dog@users.noreply.github.com> Co-authored-by: Nicholas Estelami Co-authored-by: ChristopherJTrent Co-authored-by: agamache Co-authored-by: M4xw --- .ci/switch/buildswitch.bash | 11 + .gitignore | 7 + Dockerfile.switch | 58 ++++ Jenkinsfile | 44 ++- Makefile.switch | 36 +++ OTRExporter/OTRExporter/OTRExporter.vcxproj | 6 - StormLib/.gitignore | 1 + StormLib/CMakeLists.txt | 5 + StormLib/src/StormPort.h | 2 +- ZAPDTR/ZAPD/ZAPD.vcxproj | 6 - ZAPDTR/ZAPDUtils/Makefile.switch | 171 +++++++++++ ZAPDTR/ZAPDUtils/ZAPDUtils.vcxproj | 6 - libultraship/Makefile | 6 + libultraship/Makefile.switch | 192 ++++++++++++ libultraship/libultraship/Archive.cpp | 18 +- libultraship/libultraship/Console.cpp | 17 +- libultraship/libultraship/Cvar.cpp | 6 +- libultraship/libultraship/Cvar.h | 10 +- libultraship/libultraship/Environment.cpp | 1 + libultraship/libultraship/GameOverlay.h | 2 +- libultraship/libultraship/GlobalCtx2.cpp | 7 + libultraship/libultraship/ImGuiImpl.cpp | 72 ++++- libultraship/libultraship/InputEditor.cpp | 98 +++--- .../libultraship/Lib/Fast3D/gfx_glx.cpp | 7 +- .../libultraship/Lib/Fast3D/gfx_opengl.cpp | 13 +- .../libultraship/Lib/Fast3D/gfx_pc.cpp | 2 +- .../libultraship/Lib/Fast3D/gfx_sdl2.cpp | 49 ++- .../Lib/ImGui/backends/imgui_impl_opengl3.cpp | 4 + .../Lib/ImGui/backends/imgui_impl_sdl.cpp | 39 ++- libultraship/libultraship/SDLController.cpp | 15 +- libultraship/libultraship/SDLController.h | 1 + libultraship/libultraship/SwitchImpl.cpp | 286 ++++++++++++++++++ libultraship/libultraship/SwitchImpl.h | 36 +++ .../libultraship/SwitchPerformanceProfiles.h | 21 ++ libultraship/libultraship/Window.cpp | 9 +- libultraship/libultraship/WindowShim.cpp | 4 +- .../libultraship/libultraship.vcxproj | 6 - soh/Makefile | 2 +- soh/Makefile.switch | 280 +++++++++++++++++ soh/icon.jpg | Bin 0 -> 5859 bytes soh/include/functions.h | 4 +- soh/include/z64audio.h | 2 + soh/soh/Enhancements/bootcommands.c | 5 - .../cosmetics/CosmeticsEditor.cpp | 5 +- .../randomizer/3drando/rando_main.cpp | 1 + .../randomizer/3drando/spoiler_log.cpp | 6 +- soh/soh/OTRGlobals.cpp | 26 +- soh/soh/SaveManager.cpp | 9 +- soh/src/boot/assert.c | 2 + soh/src/code/fault_drawer.c | 5 +- soh/src/code/graph.c | 16 + soh/src/code/main.c | 2 - soh/src/code/z_message_PAL.c | 17 +- soh/switch/pathconf.c | 5 + 54 files changed, 1504 insertions(+), 157 deletions(-) create mode 100755 .ci/switch/buildswitch.bash create mode 100644 Dockerfile.switch create mode 100644 Makefile.switch create mode 100644 ZAPDTR/ZAPDUtils/Makefile.switch create mode 100644 libultraship/Makefile.switch create mode 100644 libultraship/libultraship/SwitchImpl.cpp create mode 100644 libultraship/libultraship/SwitchImpl.h create mode 100644 libultraship/libultraship/SwitchPerformanceProfiles.h create mode 100644 soh/Makefile.switch create mode 100644 soh/icon.jpg create mode 100644 soh/switch/pathconf.c diff --git a/.ci/switch/buildswitch.bash b/.ci/switch/buildswitch.bash new file mode 100755 index 000000000..032b19157 --- /dev/null +++ b/.ci/switch/buildswitch.bash @@ -0,0 +1,11 @@ +#!/bin/bash + +cp -av /usr/local/lib/libSDL2* /lib/x86_64-linux-gnu/ +git config --global --add safe.directory /soh +make setup -C soh -j$(nproc) OPTFLAGS=-O2 DEBUG=0 CC="gcc" CXX="g++" + +/opt/devkitpro/portlibs/switch/bin/aarch64-none-elf-cmake -B StormLib/build-switch -S StormLib -DCMAKE_INSTALL_PREFIX=/opt/devkitpro/portlibs/switch/ +make -C StormLib/build-switch -j$(nproc) +make install -C StormLib/build-switch + +make -f Makefile.switch -j$(nproc) OPTFLAGS=-O2 DEBUG=0 diff --git a/.gitignore b/.gitignore index 5f9933097..e4e07589b 100644 --- a/.gitignore +++ b/.gitignore @@ -407,6 +407,13 @@ oot.otr shipofharkinian.ini shipofharkinian.json +# Switch Stuff + +*.nro +*.nacp +ZAPDTR/ZAPDUtils/lib/* +!/soh/icon.jpg + # Xcode xcuserdata/ *.xcconfig diff --git a/Dockerfile.switch b/Dockerfile.switch new file mode 100644 index 000000000..7319f22a6 --- /dev/null +++ b/Dockerfile.switch @@ -0,0 +1,58 @@ +FROM ubuntu:20.04 as build + +ENV LANG C.UTF-8 +ARG DEBIAN_FRONTEND=noninteractive + +ENV GCCVER=10 +RUN \ + apt-get update && \ + apt-get upgrade -y && \ + apt-get install -y \ + binutils \ + gcc-10 \ + g++-10 \ + p7zip-full \ + python3 \ + make \ + cmake \ + curl \ + git \ + lld \ + wget \ + libsdl2-dev \ + zlib1g-dev \ + libbz2-dev \ + libpng-dev \ + libgles2-mesa-dev && \ + update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-${GCCVER} 10 && \ + update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-${GCCVER} 10 + +RUN git clone https://github.com/Perlmint/glew-cmake.git && \ + cmake glew-cmake && \ + make -j$(nproc) && \ + make install ARCH64=true + +ENV SDL2VER=2.0.22 +RUN curl -sLO https://libsdl.org/release/SDL2-${SDL2VER}.tar.gz && \ + tar -xzf SDL2-${SDL2VER}.tar.gz && \ + cd SDL2-${SDL2VER} && \ + ./configure --build=x86_64-linux-gnu && \ + make && make install && \ + rm ../SDL2-${SDL2VER}.tar.gz + +RUN \ + ln -sf /proc/self/mounts /etc/mtab && \ + mkdir -p /usr/local/share/keyring/ && \ + wget -O /usr/local/share/keyring/devkitpro-pub.gpg https://apt.devkitpro.org/devkitpro-pub.gpg && \ + echo "deb [signed-by=/usr/local/share/keyring/devkitpro-pub.gpg] https://apt.devkitpro.org stable main" > /etc/apt/sources.list.d/devkitpro.list && \ + apt-get update -y && \ + apt-get install -y devkitpro-pacman && \ + yes | dkp-pacman -Syu switch-dev switch-portlibs --noconfirm + +ENV DEVKITPRO=/opt/devkitpro +ENV DEVKITARM=/opt/devkitpro/devkitARM +ENV DEVKITPPC=/opt/devkitpro/devkitPPC +ENV PATH=$PATH:/opt/devkitpro/portlibs/switch/bin/ + +RUN mkdir /soh +WORKDIR /soh diff --git a/Jenkinsfile b/Jenkinsfile index f9ac7e7c8..033f1f758 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -106,9 +106,9 @@ pipeline { mv OTRGui/build/assets build/ mv ZAPDTR/ZAPD.out build/assets/extractor/ mv README.md readme.txt - + docker exec sohcont appimage/appimage.sh - + 7z a soh-linux.7z SOH-Linux.AppImage readme.txt ''' @@ -158,7 +158,47 @@ pipeline { } } } + stage ('Build Switch') { + options { + timeout(time: 20) + } + agent { + label "SoH-Linux-Builders" + } + steps { + checkout([ + $class: 'GitSCM', + branches: scm.branches, + doGenerateSubmoduleConfigurations: scm.doGenerateSubmoduleConfigurations, + extensions: scm.extensions, + userRemoteConfigs: scm.userRemoteConfigs + ]) + catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') { + sh ''' + + cp ../../ZELOOTD.z64 OTRExporter/baserom_non_mq.z64 + docker build . -t sohswitch -f Dockerfile.switch + docker run --name sohcont -dit --rm -v $(pwd):/soh sohswitch /bin/bash + docker exec sohcont .ci/switch/buildswitch.bash + + mv soh/soh.nro . + mv README.md readme.txt + + 7z a soh-switch.7z soh.nro readme.txt + + ''' + } + sh 'sudo docker container stop sohcont' + archiveArtifacts artifacts: 'soh-switch.7z', followSymlinks: false, onlyIfSuccessful: true + } + post { + always { + step([$class: 'WsCleanup']) // Clean workspace + } + } + } } } } } + diff --git a/Makefile.switch b/Makefile.switch new file mode 100644 index 000000000..2dd9f5ea2 --- /dev/null +++ b/Makefile.switch @@ -0,0 +1,36 @@ +#------------------------------------------------------------------------------- +.SUFFIXES: +#------------------------------------------------------------------------------- + +export SOH_TOP_DIR := $(CURDIR) + +.PHONY: all clean ZAPDUtils libultraship soh StormLib + +all: soh + @echo "Done!" + +ZAPDUtils: + @echo "Building $@..." + @$(MAKE) --no-print-directory -C $(CURDIR)/ZAPDTR/ZAPDUtils -f $(CURDIR)/ZAPDTR/ZAPDUtils/Makefile.switch + +StormLib: + @echo "Building $@..." + LDFLAGS="" ${DEVKITPRO}/portlibs/switch/bin/aarch64-none-elf-cmake -DCMAKE_TOOLCHAIN_FILE=${DEVKITPRO}/cmake/Switch.cmake -DCMAKE_BUILD_TYPE=Release -B $(CURDIR)/StormLib/nxbuild -S $(CURDIR)/StormLib + @$(MAKE) --no-print-directory -C $(CURDIR)/StormLib/nxbuild -f $(CURDIR)/StormLib/nxbuild/Makefile + +libultraship: StormLib ZAPDUtils + @echo "Building $@..." + @$(MAKE) --no-print-directory -C $(CURDIR)/libultraship -f $(CURDIR)/libultraship/Makefile.switch + +soh: libultraship + @echo "Building $@..." + @$(MAKE) --no-print-directory -C $(CURDIR)/soh -f $(CURDIR)/soh/Makefile.switch + +otr: + @echo "Building $@..." + @$(MAKE) --no-print-directory -C $(CURDIR)/soh -f $(CURDIR)/soh/Makefile setup + +clean: + @$(MAKE) --no-print-directory -C $(CURDIR)/ZAPDTR/ZAPDUtils -f $(CURDIR)/ZAPDTR/ZAPDUtils/Makefile.switch clean + @$(MAKE) --no-print-directory -C $(CURDIR)/libultraship -f $(CURDIR)/libultraship/Makefile.switch clean + @$(MAKE) --no-print-directory -C $(CURDIR)/soh -f $(CURDIR)/soh/Makefile.switch clean \ No newline at end of file diff --git a/OTRExporter/OTRExporter/OTRExporter.vcxproj b/OTRExporter/OTRExporter/OTRExporter.vcxproj index cecb9eaf3..c39da3df5 100644 --- a/OTRExporter/OTRExporter/OTRExporter.vcxproj +++ b/OTRExporter/OTRExporter/OTRExporter.vcxproj @@ -65,12 +65,6 @@ - - - {02d10590-9542-3f55-aaf8-6055677e2a2a} - false - - 16.0 Win32Proj diff --git a/StormLib/.gitignore b/StormLib/.gitignore index 3d764df91..660d12e05 100644 --- a/StormLib/.gitignore +++ b/StormLib/.gitignore @@ -140,6 +140,7 @@ Desktop.ini *.egg-info dist build +nxbuild eggs parts bin diff --git a/StormLib/CMakeLists.txt b/StormLib/CMakeLists.txt index bef21d8e9..243dea578 100644 --- a/StormLib/CMakeLists.txt +++ b/StormLib/CMakeLists.txt @@ -323,6 +323,11 @@ if(${CMAKE_SYSTEM_NAME} STREQUAL FreeBSD) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DO_LARGEFILE=0 -Dstat64=stat -Dlstat64=lstat -Dlseek64=lseek -Doff64_t=off_t -Dfstat64=fstat -Dftruncate64=ftruncate") endif() +if(NOT WIN32 AND NOT APPLE AND NOT ${CMAKE_SYSTEM_NAME} STREQUAL FreeBSD) + # Enable POSIX extensions such as `readlink` and `ftruncate`. + add_definitions(-D_POSIX_C_SOURCE=200809L) +endif() + add_library(${LIBRARY_NAME} ${LIB_TYPE} ${SRC_FILES} ${SRC_ADDITIONAL_FILES} ${STORM_DEF_FILES}) if(WIN32) set_target_properties(${LIBRARY_NAME} PROPERTIES OUTPUT_NAME "StormLib") diff --git a/StormLib/src/StormPort.h b/StormLib/src/StormPort.h index d38641422..77195f88d 100644 --- a/StormLib/src/StormPort.h +++ b/StormLib/src/StormPort.h @@ -95,7 +95,7 @@ #define PKEXPORT - #ifndef __SYS_ZLIB + #ifndef __SYS_ZLIB #define __SYS_ZLIB #endif diff --git a/ZAPDTR/ZAPD/ZAPD.vcxproj b/ZAPDTR/ZAPD/ZAPD.vcxproj index ad3c3e08c..9369e97da 100644 --- a/ZAPDTR/ZAPD/ZAPD.vcxproj +++ b/ZAPDTR/ZAPD/ZAPD.vcxproj @@ -359,12 +359,6 @@ - - - {02d10590-9542-3f55-aaf8-6055677e2a2a} - false - - diff --git a/ZAPDTR/ZAPDUtils/Makefile.switch b/ZAPDTR/ZAPDUtils/Makefile.switch new file mode 100644 index 000000000..ed173c44f --- /dev/null +++ b/ZAPDTR/ZAPDUtils/Makefile.switch @@ -0,0 +1,171 @@ +#--------------------------------------------------------------------------------- +.SUFFIXES: +#--------------------------------------------------------------------------------- + +ifeq ($(strip $(DEVKITPRO)),) +$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=/devkitpro") +endif + +TOPDIR ?= $(CURDIR) +include $(DEVKITPRO)/libnx/switch_rules + +#--------------------------------------------------------------------------------- +# TARGET is the name of the output +# BUILD is the directory where object files & intermediate files will be placed +# SOURCES is a list of directories containing source code +# DATA is a list of directories containing data files +# INCLUDES is a list of directories containing header files +# ROMFS is the directory containing data to be added to RomFS, relative to the Makefile (Optional) +# +# NO_ICON: if set to anything, do not use icon. +# NO_NACP: if set to anything, no .nacp file is generated. +# APP_TITLE is the name of the app stored in the .nacp file (Optional) +# APP_AUTHOR is the author of the app stored in the .nacp file (Optional) +# APP_VERSION is the version of the app stored in the .nacp file (Optional) +# APP_TITLEID is the titleID of the app stored in the .nacp file (Optional) +# ICON is the filename of the icon (.jpg), relative to the project folder. +# If not set, it attempts to use one of the following (in this order): +# - .jpg +# - icon.jpg +# - /default_icon.jpg +# +# CONFIG_JSON is the filename of the NPDM config file (.json), relative to the project folder. +# If not set, it attempts to use one of the following (in this order): +# - .json +# - config.json +# If a JSON file is provided or autodetected, an ExeFS PFS0 (.nsp) is built instead +# of a homebrew executable (.nro). This is intended to be used for sysmodules. +# NACP building is skipped as well. +#--------------------------------------------------------------------------------- +TARGET := ZAPDUtils +BUILD := build +SOURCES := Utils +DATA := +INCLUDES := + +#------------------------------------------------------------------------------- +# source files +#------------------------------------------------------------------------------- +SOURCEFILES_C := + +SOURCEFILES_CPP := + +#--------------------------------------------------------------------------------- +# options for code generation +#--------------------------------------------------------------------------------- +ARCH := -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE + +CFLAGS := -g -Wall -O2 -ffunction-sections \ + $(ARCH) $(DEFINES) + +CFLAGS += $(INCLUDE) -D__SWITCH__ + +CXXFLAGS := $(CFLAGS) -fno-rtti -fexceptions -std=gnu++20 +CFLAGS += -std=gnu11 + +ASFLAGS := -g $(ARCH) +LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) + +LIBS := -lnx + +#--------------------------------------------------------------------------------- +# list of directories containing libraries, this must be the top level containing +# include and lib +#--------------------------------------------------------------------------------- +LIBDIRS := $(PORTLIBS) $(LIBNX) + + +#--------------------------------------------------------------------------------- +# no real need to edit anything past this point unless you need to add additional +# rules for different file extensions +#--------------------------------------------------------------------------------- +ifneq ($(BUILD),$(notdir $(CURDIR))) +#--------------------------------------------------------------------------------- + +export OUTPUT := $(CURDIR)/lib/lib$(TARGET).a +export TOPDIR := $(CURDIR) + +export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ + $(foreach dir,$(DATA),$(CURDIR)/$(dir)) \ + $(foreach sf,$(SOURCEFILES_C),$(CURDIR)/$(dir $(sf))) \ + $(foreach sf,$(SOURCEFILES_CPP),$(CURDIR)/$(dir $(sf))) + +export DEPSDIR := $(CURDIR)/$(BUILD) + +CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) \ + $(foreach f,$(SOURCEFILES_C),$(notdir $(f))) +CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) \ + $(foreach f,$(SOURCEFILES_CPP),$(notdir $(f))) +SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) +BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) + +#--------------------------------------------------------------------------------- +# use CXX for linking C++ projects, CC for standard C +#--------------------------------------------------------------------------------- +ifeq ($(strip $(CPPFILES)),) +#--------------------------------------------------------------------------------- + export LD := $(CC) +#--------------------------------------------------------------------------------- +else +#--------------------------------------------------------------------------------- + export LD := $(CXX) +#--------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------- + +export OFILES_BIN := $(addsuffix .o,$(BINFILES)) +export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) +export OFILES := $(OFILES_BIN) $(OFILES_SRC) +export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES))) + +export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ + $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ + -I$(CURDIR)/$(BUILD) + +export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) + +.PHONY: $(BUILD) clean all + +#--------------------------------------------------------------------------------- +all: $(BUILD) + +lib: + @[ -d $@ ] || mkdir -p $@ + +$(BUILD) : lib + @[ -d $@ ] || mkdir -p $@ + @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile.switch + +#--------------------------------------------------------------------------------- +clean: + @echo clean ... + @rm -rf build lib + +#--------------------------------------------------------------------------------- +else +.PHONY: all + +DEPENDS := $(OFILES:.o=.d) + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- + +$(OUTPUT) : $(OFILES) + +$(OFILES_SRC) : $(HFILES) +$(OFILES_SRC) : $(HFILES_BIN) + +#--------------------------------------------------------------------------------- +# you need a rule like this for each extension you use as binary data +#--------------------------------------------------------------------------------- +%.bin.o %_bin.h : %.bin +#--------------------------------------------------------------------------------- + @echo $(notdir $<) + @$(bin2o) + +-include $(DEPENDS) + +#--------------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------------- \ No newline at end of file diff --git a/ZAPDTR/ZAPDUtils/ZAPDUtils.vcxproj b/ZAPDTR/ZAPDUtils/ZAPDUtils.vcxproj index 05b9e1908..164f4bb11 100644 --- a/ZAPDTR/ZAPDUtils/ZAPDUtils.vcxproj +++ b/ZAPDTR/ZAPDUtils/ZAPDUtils.vcxproj @@ -186,12 +186,6 @@ - - - {02d10590-9542-3f55-aaf8-6055677e2a2a} - false - - diff --git a/libultraship/Makefile b/libultraship/Makefile index 18dfca271..37640969d 100644 --- a/libultraship/Makefile +++ b/libultraship/Makefile @@ -9,6 +9,7 @@ UNAME := $(shell uname) ASAN ?= 0 DEBUG ?= 1 OPTFLAGS ?= -O0 +X11 ?= 0 LTO ?= 0 # flag to save whether the compiler being used is clang or gcc by checking CXX --version @@ -49,6 +50,11 @@ CPPFLAGS := -MMD MMFLAGS := -Wno-deprecated-declarations -ObjC++ -fobjc-weak -fobjc-arc +ifeq ($(X11), 1) +CXXFLAGS += -DX11_SUPPORTED +CFLAGS += -DX11_SUPPORTED +endif + # if not using clang, ask clang to use gcc standard library ifneq ($(CXX_IS_CLANG),1) STD_ISYSTEM=$(shell ${CXX} -xc++ -E -v - < /dev/null 2>&1 | grep "> search starts here" -A2 | tail -n 2 | head -n 1) diff --git a/libultraship/Makefile.switch b/libultraship/Makefile.switch new file mode 100644 index 000000000..72f0171aa --- /dev/null +++ b/libultraship/Makefile.switch @@ -0,0 +1,192 @@ +#--------------------------------------------------------------------------------- +.SUFFIXES: +#--------------------------------------------------------------------------------- + +ifeq ($(strip $(DEVKITPRO)),) +$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=/devkitpro") +endif + +TOPDIR ?= $(CURDIR) +include $(DEVKITPRO)/libnx/switch_rules + +#--------------------------------------------------------------------------------- +# TARGET is the name of the output +# BUILD is the directory where object files & intermediate files will be placed +# SOURCES is a list of directories containing source code +# DATA is a list of directories containing data files +# INCLUDES is a list of directories containing header files +# ROMFS is the directory containing data to be added to RomFS, relative to the Makefile (Optional) +# +# NO_ICON: if set to anything, do not use icon. +# NO_NACP: if set to anything, no .nacp file is generated. +# APP_TITLE is the name of the app stored in the .nacp file (Optional) +# APP_AUTHOR is the author of the app stored in the .nacp file (Optional) +# APP_VERSION is the version of the app stored in the .nacp file (Optional) +# APP_TITLEID is the titleID of the app stored in the .nacp file (Optional) +# ICON is the filename of the icon (.jpg), relative to the project folder. +# If not set, it attempts to use one of the following (in this order): +# - .jpg +# - icon.jpg +# - /default_icon.jpg +# +# CONFIG_JSON is the filename of the NPDM config file (.json), relative to the project folder. +# If not set, it attempts to use one of the following (in this order): +# - .json +# - config.json +# If a JSON file is provided or autodetected, an ExeFS PFS0 (.nsp) is built instead +# of a homebrew executable (.nro). This is intended to be used for sysmodules. +# NACP building is skipped as well. +#--------------------------------------------------------------------------------- +TARGET := ultraship +BUILD := build +SOURCES := \ + libultraship/Factories \ + libultraship/Lib/Fast3D \ + libultraship/Lib/ImGui \ + libultraship/Lib/Mercury \ + libultraship +DATA := +INCLUDES := \ + ../ZAPDTR/ZAPDUtils \ + ../StormLib/src \ + libultraship/Lib/Fast3D/U64 \ + libultraship/Lib/ImGui \ + libultraship/Lib/spdlog \ + libultraship/Lib/spdlog/include \ + libultraship + +#------------------------------------------------------------------------------- +# source files +#------------------------------------------------------------------------------- + +SOURCEFILES_C := \ + libultraship/mixer.c \ + libultraship/Lib/stb/stb_impl.c \ + +SOURCEFILES_CPP := \ + libultraship/Lib/ImGui/backends/imgui_impl_opengl3.cpp \ + libultraship/Lib/ImGui/backends/imgui_impl_sdl.cpp \ + libultraship/Lib/StrHash64.cpp \ + libultraship/Lib/tinyxml2/tinyxml2.cpp + +#--------------------------------------------------------------------------------- +# options for code generation +#--------------------------------------------------------------------------------- +ARCH := -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE -ffast-math -O3 + +CFLAGS := -Wall -ffunction-sections \ + $(ARCH) $(DEFINES) \ + -DSPDLOG_NO_THREAD_ID \ + -DSTBI_NO_THREAD_LOCALS + +CFLAGS += $(INCLUDE) -D__SWITCH__ -DENABLE_OPENGL + +CXXFLAGS := $(CFLAGS) -std=gnu++20 +CFLAGS += -std=gnu11 + +ASFLAGS := -g $(ARCH) +LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) + +LIBS := -lnx + +#--------------------------------------------------------------------------------- +# list of directories containing libraries, this must be the top level containing +# include and lib +#--------------------------------------------------------------------------------- +LIBDIRS := $(PORTLIBS) $(LIBNX) + + +#--------------------------------------------------------------------------------- +# no real need to edit anything past this point unless you need to add additional +# rules for different file extensions +#--------------------------------------------------------------------------------- +ifneq ($(BUILD),$(notdir $(CURDIR))) +#--------------------------------------------------------------------------------- + +export OUTPUT := $(CURDIR)/lib/lib$(TARGET).a +export TOPDIR := $(CURDIR) + +export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ + $(foreach dir,$(DATA),$(CURDIR)/$(dir)) \ + $(foreach sf,$(SOURCEFILES_C),$(CURDIR)/$(dir $(sf))) \ + $(foreach sf,$(SOURCEFILES_CPP),$(CURDIR)/$(dir $(sf))) + +export DEPSDIR := $(CURDIR)/$(BUILD) + +CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) \ + $(foreach f,$(SOURCEFILES_C),$(notdir $(f))) +CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) \ + $(foreach f,$(SOURCEFILES_CPP),$(notdir $(f))) +SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) +BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) + +#--------------------------------------------------------------------------------- +# use CXX for linking C++ projects, CC for standard C +#--------------------------------------------------------------------------------- +ifeq ($(strip $(CPPFILES)),) +#--------------------------------------------------------------------------------- + export LD := $(CC) +#--------------------------------------------------------------------------------- +else +#--------------------------------------------------------------------------------- + export LD := $(CXX) +#--------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------- + +export OFILES_BIN := $(addsuffix .o,$(BINFILES)) +export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) +export OFILES := $(OFILES_BIN) $(OFILES_SRC) +export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES))) + +export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ + $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ + -I$(CURDIR)/$(BUILD) + +export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) + +.PHONY: $(BUILD) clean all + +#--------------------------------------------------------------------------------- +all: $(BUILD) + +lib: + @[ -d $@ ] || mkdir -p $@ + +$(BUILD) : lib + @[ -d $@ ] || mkdir -p $@ + @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile.switch + +#--------------------------------------------------------------------------------- +clean: + @echo clean ... + @rm -rf build lib + +#--------------------------------------------------------------------------------- +else +.PHONY: all + +DEPENDS := $(OFILES:.o=.d) + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- + +$(OUTPUT) : $(OFILES) + +$(OFILES_SRC) : $(HFILES) +$(OFILES_SRC) : $(HFILES_BIN) + +#--------------------------------------------------------------------------------- +# you need a rule like this for each extension you use as binary data +#--------------------------------------------------------------------------------- +%.bin.o %_bin.h : %.bin +#--------------------------------------------------------------------------------- + @echo $(notdir $<) + @$(bin2o) + +-include $(DEPENDS) + +#--------------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------------- \ No newline at end of file diff --git a/libultraship/libultraship/Archive.cpp b/libultraship/libultraship/Archive.cpp index c57fb608c..81b0e180e 100644 --- a/libultraship/libultraship/Archive.cpp +++ b/libultraship/libultraship/Archive.cpp @@ -6,6 +6,10 @@ #include "Lib/StrHash64.h" #include +#ifdef __SWITCH__ +#include "SwitchImpl.h" +#endif + namespace Ship { Archive::Archive(const std::string& MainPath, bool enableWriting) : Archive(MainPath, "", enableWriting) { @@ -68,7 +72,7 @@ namespace Ship { //} if (!attempt) { - printf("({%i}) Failed to open file {%s} from mpq archive {%s}", GetLastError(), filePath.c_str(), MainPath.c_str()); + SPDLOG_ERROR("({}) Failed to open file {} from mpq archive {}.", GetLastError(), filePath.c_str(), MainPath.c_str()); std::unique_lock Lock(FileToLoad->FileLoadMutex); FileToLoad->bHasLoadError = true; return FileToLoad; @@ -327,13 +331,21 @@ namespace Ship { #ifdef _WIN32 std::wstring wfullPath = std::filesystem::absolute(MainPath).wstring(); #endif +#if defined(__SWITCH__) + std::string fullPath = MainPath; +#else std::string fullPath = std::filesystem::absolute(MainPath).string(); +#endif #ifdef _WIN32 if (!SFileOpenArchive(wfullPath.c_str(), 0, enableWriting ? 0 : MPQ_OPEN_READ_ONLY, &mpqHandle)) { #else if (!SFileOpenArchive(fullPath.c_str(), 0, enableWriting ? 0 : MPQ_OPEN_READ_ONLY, &mpqHandle)) { #endif + + #ifdef __SWITCH__ + Switch::ThrowMissingOTR(fullPath); + #endif SPDLOG_ERROR("({}) Failed to open main mpq file {}.", GetLastError(), fullPath.c_str()); return false; } @@ -362,7 +374,11 @@ namespace Ship { bool Archive::LoadPatchMPQ(const std::string& path) { HANDLE patchHandle = NULL; +#if defined(__SWITCH__) + std::string fullPath = path; +#else std::string fullPath = std::filesystem::absolute(path).string(); +#endif if (mpqHandles.contains(fullPath)) { return true; } diff --git a/libultraship/libultraship/Console.cpp b/libultraship/libultraship/Console.cpp index da61e4056..85ba1f78d 100644 --- a/libultraship/libultraship/Console.cpp +++ b/libultraship/libultraship/Console.cpp @@ -98,20 +98,14 @@ void Console::Update() { } } -extern "C" uint8_t __enableGameInput; - void Console::Draw() { bool input_focus = false; - __enableGameInput = true; if (!this->opened) return; ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver); ImGui::Begin("Console", nullptr, ImGuiWindowFlags_NoFocusOnAppearing); const ImVec2 pos = ImGui::GetWindowPos(); const ImVec2 size = ImGui::GetWindowSize(); - - __enableGameInput = !ImGui::IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows); - // SohImGui::ShowCursor(ImGui::IsWindowHovered(ImGuiHoveredFlags_RootAndChildWindows | ImGuiHoveredFlags_RectOnly), SohImGui::Dialogues::dConsole); // Renders autocomplete window @@ -230,8 +224,8 @@ void Console::Draw() { // Renders input textfield constexpr ImGuiInputTextFlags flags = ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_CallbackEdit | ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_CallbackHistory; - ImGui::PushItemWidth(-1); - if(ImGui::InputTextWithHint("CMDInput", ">", this->InputBuffer, MAX_BUFFER_SIZE, flags, &Console::CallbackStub, this)) { + ImGui::PushItemWidth(-53); + if(ImGui::InputTextWithHint("##CMDInput", ">", this->InputBuffer, MAX_BUFFER_SIZE, flags, &Console::CallbackStub, this)) { input_focus = true; if(this->InputBuffer[0] != '\0' && this->InputBuffer[0] != ' ') this->Dispatch(std::string(this->InputBuffer)); @@ -250,6 +244,13 @@ void Console::Draw() { } } + ImGui::SameLine(); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetContentRegionAvail().x - 50); + if(ImGui::Button("Submit") && !input_focus && this->InputBuffer[0] != '\0' && this->InputBuffer[0] != ' '){ + this->Dispatch(std::string(this->InputBuffer)); + memset(this->InputBuffer, 0, MAX_BUFFER_SIZE); + } + ImGui::SetItemDefaultFocus(); if (input_focus) ImGui::SetKeyboardFocusHere(-1); ImGui::PopItemWidth(); diff --git a/libultraship/libultraship/Cvar.cpp b/libultraship/libultraship/Cvar.cpp index 231308fe7..27d44df80 100644 --- a/libultraship/libultraship/Cvar.cpp +++ b/libultraship/libultraship/Cvar.cpp @@ -14,7 +14,7 @@ extern "C" CVar* CVar_Get(const char* name) { return (it != cvars.end()) ? it->second.get() : nullptr; } -extern "C" s32 CVar_GetS32(const char* name, s32 defaultValue) { +extern "C" int32_t CVar_GetS32(const char* name, int32_t defaultValue) { CVar* cvar = CVar_Get(name); if (cvar) { @@ -47,7 +47,7 @@ extern "C" const char* CVar_GetString(const char* name, const char* defaultValue return defaultValue; } -extern "C" void CVar_SetS32(const char* name, s32 value) { +extern "C" void CVar_SetS32(const char* name, int32_t value) { auto& cvar = cvars[name]; if (!cvar) { cvar = std::make_unique(); @@ -74,7 +74,7 @@ extern "C" void CVar_SetString(const char* name, const char* value) { cvar->value.valueStr = ImStrdup(value); } -extern "C" void CVar_RegisterS32(const char* name, s32 defaultValue) { +extern "C" void CVar_RegisterS32(const char* name, int32_t defaultValue) { if (!CVar_Get(name)) CVar_SetS32(name, defaultValue); } diff --git a/libultraship/libultraship/Cvar.h b/libultraship/libultraship/Cvar.h index f9583ef0c..1507b519d 100644 --- a/libultraship/libultraship/Cvar.h +++ b/libultraship/libultraship/Cvar.h @@ -1,7 +1,7 @@ #ifndef _CVAR_H #define _CVAR_H -#include +#include typedef enum CVarType { CVAR_TYPE_S32, CVAR_TYPE_FLOAT, CVAR_TYPE_STRING } CVarType; @@ -10,7 +10,7 @@ typedef struct CVar { CVarType type; union { - s32 valueS32; + int32_t valueS32; float valueFloat; const char* valueStr; } value; @@ -23,13 +23,13 @@ extern "C" //#include CVar* CVar_Get(const char* name); -s32 CVar_GetS32(const char* name, s32 defaultValue); +int32_t CVar_GetS32(const char* name, int32_t defaultValue); float CVar_GetFloat(const char* name, float defaultValue); const char* CVar_GetString(const char* name, const char* defaultValue); -void CVar_SetS32(const char* name, s32 value); +void CVar_SetS32(const char* name, int32_t value); void CVar_SetString(const char* name, const char* value); -void CVar_RegisterS32(const char* name, s32 defaultValue); +void CVar_RegisterS32(const char* name, int32_t defaultValue); void CVar_RegisterFloat(const char* name, float defaultValue); void CVar_RegisterString(const char* name, const char* defaultValue); diff --git a/libultraship/libultraship/Environment.cpp b/libultraship/libultraship/Environment.cpp index 7f10c8c44..53d0f330b 100644 --- a/libultraship/libultraship/Environment.cpp +++ b/libultraship/libultraship/Environment.cpp @@ -9,6 +9,7 @@ namespace SohUtils { void saveEnvironmentVar(const std::string& key, const std::string& value) { environmentVars[key] = value; } + std::string getEnvironmentVar(const std::string& key) { return environmentVars[key]; } diff --git a/libultraship/libultraship/GameOverlay.h b/libultraship/libultraship/GameOverlay.h index 605cd5898..c9290390e 100644 --- a/libultraship/libultraship/GameOverlay.h +++ b/libultraship/libultraship/GameOverlay.h @@ -38,5 +38,5 @@ namespace Ship { void LoadFont(const std::string& name, const std::string& path, float fontSize); }; - static bool OverlayCommand(const std::vector& args); + bool OverlayCommand(const std::vector& args); } diff --git a/libultraship/libultraship/GlobalCtx2.cpp b/libultraship/libultraship/GlobalCtx2.cpp index 329644192..5eb449ad3 100644 --- a/libultraship/libultraship/GlobalCtx2.cpp +++ b/libultraship/libultraship/GlobalCtx2.cpp @@ -10,6 +10,8 @@ #include "ModManager.h" #ifdef __APPLE__ #include "OSXFolderManager.h" +#elif defined(__SWITCH__) +#include "SwitchImpl.h" #endif namespace Ship { @@ -72,11 +74,16 @@ namespace Ship { { #ifdef _WIN32 MessageBox(nullptr, L"Main OTR file not found!", L"Uh oh", MB_OK); +#elif defined(__SWITCH__) + printf("Main OTR file not found!\n"); #else SPDLOG_ERROR("Main OTR file not found!"); #endif exit(1); } + #ifdef __SWITCH__ + Ship::Switch::Init(PostInitPhase); + #endif INSTANCE = new ModManager(ResMan); INSTANCE->Init(); } diff --git a/libultraship/libultraship/ImGuiImpl.cpp b/libultraship/libultraship/ImGuiImpl.cpp index f1f1fd12b..f7288ae3a 100644 --- a/libultraship/libultraship/ImGuiImpl.cpp +++ b/libultraship/libultraship/ImGuiImpl.cpp @@ -27,6 +27,16 @@ #include "Lib/spdlog/include/spdlog/common.h" #include "Utils/StringHelper.h" +#if __APPLE__ +#include +#else +#include +#endif + +#ifdef __SWITCH__ +#include "SwitchImpl.h" +#endif + #ifdef ENABLE_OPENGL #include "Lib/ImGui/backends/imgui_impl_opengl3.h" #include "Lib/ImGui/backends/imgui_impl_sdl.h" @@ -127,6 +137,7 @@ namespace SohImGui { void ImGuiWMInit() { switch (impl.backend) { case Backend::SDL: + SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "1"); ImGui_ImplSDL2_InitForOpenGL(static_cast(impl.sdl.window), impl.sdl.context); break; #if defined(ENABLE_DX11) || defined(ENABLE_DX12) @@ -339,10 +350,17 @@ namespace SohImGui { io = &ImGui::GetIO(); io->ConfigFlags |= ImGuiConfigFlags_DockingEnable; io->Fonts->AddFontDefault(); + #ifdef __SWITCH__ + Ship::Switch::SetupFont(io->Fonts); + #endif lastBackendID = GetBackendID(GlobalCtx2::GetInstance()->GetConfig()); if (CVar_GetS32("gOpenMenuBar", 0) != 1) { + #ifdef __SWITCH__ + SohImGui::overlay->TextDrawNotification(30.0f, true, "Press - to access enhancements menu"); + #else SohImGui::overlay->TextDrawNotification(30.0f, true, "Press F1 to access enhancements menu"); + #endif } auto imguiIniPath = Ship::GlobalCtx2::GetPathRelativeToAppDirectory("imgui.ini"); @@ -358,6 +376,9 @@ namespace SohImGui { controller->Init(); ImGuiWMInit(); ImGuiBackendInit(); + #ifdef __SWITCH__ + ImGui::GetStyle().ScaleAllSizes(2); + #endif ModInternal::RegisterHook([] { if (GlobalCtx2::GetInstance()->GetWindow()->IsFullscreen()) @@ -386,7 +407,10 @@ namespace SohImGui { CVar_SetS32("gNewSeedGenerated", 0); CVar_SetS32("gNewFileDropped", 0); CVar_SetString("gDroppedFile", "None"); - // Game::SaveSettings(); + + #ifdef __SWITCH__ + Switch::ApplyOverclock(); + #endif } void Update(EventImpl event) { @@ -734,7 +758,7 @@ namespace SohImGui { const ImGuiViewport* viewport = ImGui::GetMainViewport(); ImGui::SetNextWindowPos(viewport->WorkPos); - ImGui::SetNextWindowSize(ImVec2(wnd->GetCurrentWidth(), wnd->GetCurrentHeight())); + ImGui::SetNextWindowSize(ImVec2((int) wnd->GetCurrentWidth(), (int) wnd->GetCurrentHeight())); ImGui::SetNextWindowViewport(viewport->ID); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f)); ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f); @@ -757,7 +781,7 @@ namespace SohImGui { ImGui::DockSpace(dockId, ImVec2(0.0f, 0.0f), ImGuiDockNodeFlags_None | ImGuiDockNodeFlags_NoDockingInCentralNode); - if (ImGui::IsKeyPressed(TOGGLE_BTN)) { + if (ImGui::IsKeyPressed(TOGGLE_BTN) || ImGui::IsKeyPressed(TOGGLE_PAD_BTN)) { bool menu_bar = CVar_GetS32("gOpenMenuBar", 0); CVar_SetS32("gOpenMenuBar", !menu_bar); needs_save = true; @@ -791,8 +815,13 @@ namespace SohImGui { if (ImGui::BeginMenuBar()) { if (DefaultAssets.contains("Game_Icon")) { + #ifdef __SWITCH__ + ImVec2 iconSize = ImVec2(20.0f, 20.0f); + #else + ImVec2 iconSize = ImVec2(16.0f, 16.0f); + #endif ImGui::SetCursorPos(ImVec2(5, 2.5f)); - ImGui::Image(GetTextureByID(DefaultAssets["Game_Icon"]->textureId), ImVec2(16.0f, 16.0f)); + ImGui::Image(GetTextureByID(DefaultAssets["Game_Icon"]->textureId), iconSize); ImGui::SameLine(); ImGui::SetCursorPos(ImVec2(25, 0)); } @@ -931,8 +960,6 @@ namespace SohImGui { EXPERIMENTAL(); ImGui::Text("Texture Filter (Needs reload)"); EnhancementCombobox("gTextureFilter", filters, 3, 0); - GfxRenderingAPI* gapi = gfx_get_current_rendering_api(); - gapi->set_texture_filter((FilteringMode)CVar_GetS32("gTextureFilter", 0)); overlay->DrawSettings(); ImGui::EndMenu(); } @@ -1235,8 +1262,16 @@ namespace SohImGui { const char* fps_cvar = "gInterpolationFPS"; { - int val = CVar_GetS32(fps_cvar, 20); - val = MAX(MIN(val, 250), 20); + #ifdef __SWITCH__ + int minFps = 20; + int maxFps = 60; + #else + int minFps = 20; + int maxFps = 250; + #endif + + int val = CVar_GetS32(fps_cvar, minFps); + val = MAX(MIN(val, maxFps), 20); int fps = val; if (fps == 20) @@ -1258,7 +1293,7 @@ namespace SohImGui { ImGui::SameLine(); ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); - if (ImGui::SliderInt("##FPSInterpolation", &val, 20, 250, "", ImGuiSliderFlags_AlwaysClamp)) + if (ImGui::SliderInt("##FPSInterpolation", &val, minFps, maxFps, "", ImGuiSliderFlags_AlwaysClamp)) { if (val > 250) { @@ -1316,6 +1351,23 @@ namespace SohImGui { EnhancementCheckbox("Free Camera", "gFreeCamera"); Tooltip("Enables camera control\nNote: You must remap C buttons off of\nthe right stick in the controller\nconfig menu, and map the camera stick\nto the right stick."); + #ifdef __SWITCH__ + int slot = CVar_GetS32("gSwitchPerfMode", (int)SwitchProfiles::STOCK); + ImGui::Text("Switch performance mode"); + if (ImGui::BeginCombo("##perf", SWITCH_CPU_PROFILES[slot])) { + for (int sId = 0; sId <= SwitchProfiles::POWERSAVINGM3; sId++) { + if (ImGui::Selectable(SWITCH_CPU_PROFILES[sId], sId == slot)) { + INFO("Profile:: %s", SWITCH_CPU_PROFILES[sId]); + CVar_SetS32("gSwitchPerfMode", sId); + Switch::ApplyOverclock(); + needs_save = true; + } + + } + ImGui::EndCombo(); + } + #endif + ImGui::EndMenu(); } @@ -1430,6 +1482,8 @@ namespace SohImGui { ImGui::Text("Platform: Windows"); #elif __APPLE__ ImGui::Text("Platform: macOS"); +#elif defined(__SWITCH__) + ImGui::Text("Platform: Nintendo Switch"); #else ImGui::Text("Platform: Linux"); #endif diff --git a/libultraship/libultraship/InputEditor.cpp b/libultraship/libultraship/InputEditor.cpp index 25e641a06..eb191cc20 100644 --- a/libultraship/libultraship/InputEditor.cpp +++ b/libultraship/libultraship/InputEditor.cpp @@ -9,7 +9,6 @@ namespace Ship { - extern "C" uint8_t __enableGameInput; #define SEPARATION() ImGui::Dummy(ImVec2(0, 5)) void InputEditor::Init() { @@ -116,7 +115,11 @@ namespace Ship { DrawButton("Z", BTN_Z); DrawButton("START", BTN_START); SEPARATION(); + #ifdef __SWITCH__ + SohImGui::EndGroupPanel(IsKeyboard ? 7.0f : 56.0f); + #else SohImGui::EndGroupPanel(IsKeyboard ? 7.0f : 48.0f); + #endif ImGui::SameLine(); SohImGui::BeginGroupPanel("Digital Pad", ImVec2(150, 20)); DrawButton("Up", BTN_DUP); @@ -124,7 +127,11 @@ namespace Ship { DrawButton("Left", BTN_DLEFT); DrawButton("Right", BTN_DRIGHT); SEPARATION(); + #ifdef __SWITCH__ + SohImGui::EndGroupPanel(IsKeyboard ? 53.0f : 122.0f); + #else SohImGui::EndGroupPanel(IsKeyboard ? 53.0f : 94.0f); + #endif ImGui::SameLine(); SohImGui::BeginGroupPanel("Analog Stick", ImVec2(150, 20)); DrawButton("Up", BTN_STICKUP); @@ -148,7 +155,11 @@ namespace Ship { } else { ImGui::Dummy(ImVec2(0, 6)); } - SohImGui::EndGroupPanel(IsKeyboard ? 52.0f : 24.0f); + #ifdef __SWITCH__ + SohImGui::EndGroupPanel(IsKeyboard ? 52.0f : 52.0f); + #else + SohImGui::EndGroupPanel(IsKeyboard ? 52.0f : 24.0f); + #endif ImGui::SameLine(); if (!IsKeyboard) { @@ -174,44 +185,52 @@ namespace Ship { ImGui::InputFloat("##MSensitivity", &profile.Thresholds[SENSITIVITY], 1.0f, 0.0f, "%.0f"); ImGui::PopItemWidth(); ImGui::EndChild(); + #ifdef __SWITCH__ + SohImGui::EndGroupPanel(43.0f); + #else SohImGui::EndGroupPanel(14.0f); + #endif } if(Backend->CanGyro()) { ImGui::SameLine(); SohImGui::BeginGroupPanel("Gyro Options", ImVec2(175, 20)); - float cursorX = ImGui::GetCursorPosX() + 5; - ImGui::SetCursorPosX(cursorX); - ImGui::Checkbox("Enable Gyro", &profile.UseGyro); - ImGui::SetCursorPosX(cursorX); - ImGui::Text("Gyro Sensitivity: %d%%", static_cast(100.0f * profile.Thresholds[GYRO_SENSITIVITY])); - ImGui::PushItemWidth(135.0f); - ImGui::SetCursorPosX(cursorX); - ImGui::SliderFloat("##GSensitivity", &profile.Thresholds[GYRO_SENSITIVITY], 0.0f, 1.0f, ""); - ImGui::PopItemWidth(); - ImGui::Dummy(ImVec2(0, 1)); - ImGui::SetCursorPosX(cursorX); - if (ImGui::Button("Recalibrate Gyro##RGyro")) { - profile.Thresholds[DRIFT_X] = 0.0f; - profile.Thresholds[DRIFT_Y] = 0.0f; - } - ImGui::SetCursorPosX(cursorX); - DrawVirtualStick("##GyroPreview", ImVec2(-10.0f * Backend->wGyroY, 10.0f * Backend->wGyroX)); + float cursorX = ImGui::GetCursorPosX() + 5; + ImGui::SetCursorPosX(cursorX); + ImGui::Checkbox("Enable Gyro", &profile.UseGyro); + ImGui::SetCursorPosX(cursorX); + ImGui::Text("Gyro Sensitivity: %d%%", static_cast(100.0f * profile.Thresholds[GYRO_SENSITIVITY])); + ImGui::PushItemWidth(135.0f); + ImGui::SetCursorPosX(cursorX); + ImGui::SliderFloat("##GSensitivity", &profile.Thresholds[GYRO_SENSITIVITY], 0.0f, 1.0f, ""); + ImGui::PopItemWidth(); + ImGui::Dummy(ImVec2(0, 1)); + ImGui::SetCursorPosX(cursorX); + if (ImGui::Button("Recalibrate Gyro##RGyro")) { + profile.Thresholds[DRIFT_X] = 0.0f; + profile.Thresholds[DRIFT_Y] = 0.0f; + } + ImGui::SetCursorPosX(cursorX); + DrawVirtualStick("##GyroPreview", ImVec2(-10.0f * Backend->wGyroY, 10.0f * Backend->wGyroX)); - ImGui::SameLine(); - ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5); - ImGui::BeginChild("##GyInput", ImVec2(90, 85), false); - ImGui::Text("Drift X"); - ImGui::PushItemWidth(80); - ImGui::InputFloat("##GDriftX", &profile.Thresholds[DRIFT_X], 1.0f, 0.0f, "%.1f"); - ImGui::PopItemWidth(); - ImGui::Text("Drift Y"); - ImGui::PushItemWidth(80); - ImGui::InputFloat("##GDriftY", &profile.Thresholds[DRIFT_Y], 1.0f, 0.0f, "%.1f"); - ImGui::PopItemWidth(); - ImGui::EndChild(); + ImGui::SameLine(); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5); + ImGui::BeginChild("##GyInput", ImVec2(90, 85), false); + ImGui::Text("Drift X"); + ImGui::PushItemWidth(80); + ImGui::InputFloat("##GDriftX", &profile.Thresholds[DRIFT_X], 1.0f, 0.0f, "%.1f"); + ImGui::PopItemWidth(); + ImGui::Text("Drift Y"); + ImGui::PushItemWidth(80); + ImGui::InputFloat("##GDriftY", &profile.Thresholds[DRIFT_Y], 1.0f, 0.0f, "%.1f"); + ImGui::PopItemWidth(); + ImGui::EndChild(); + #ifdef __SWITCH__ + SohImGui::EndGroupPanel(46.0f); + #else SohImGui::EndGroupPanel(14.0f); + #endif } ImGui::SameLine(); @@ -227,7 +246,11 @@ namespace Ship { SohImGui::EndGroupPanel(); ImGui::SetCursorPosX(cursor.x); + #ifdef __SWITCH__ + ImGui::SetCursorPosY(cursor.y + 167); + #else ImGui::SetCursorPosY(cursor.y + 120); + #endif SohImGui::BeginGroupPanel("Options", ImVec2(158, 20)); float cursorX = ImGui::GetCursorPosX() + 5; ImGui::SetCursorPosX(cursorX); @@ -245,16 +268,21 @@ namespace Ship { } void InputEditor::DrawHud() { - - __enableGameInput = true; - if (!this->Opened) { BtnReading = -1; CVar_SetS32("gControllerConfigurationEnabled", 0); return; } - ImGui::SetNextWindowSizeConstraints(ImVec2(641, 250), ImVec2(1200, 290)); +#ifdef __SWITCH__ + ImVec2 minSize = ImVec2(641, 250); + ImVec2 maxSize = ImVec2(2200, 505); +#else + ImVec2 minSize = ImVec2(641, 250); + ImVec2 maxSize = ImVec2(1200, 290); +#endif + + ImGui::SetNextWindowSizeConstraints(minSize, maxSize); //OTRTODO: Disable this stupid workaround ( ReadRawPress() only works when the window is on the main viewport ) ImGui::SetNextWindowViewport(ImGui::GetMainViewport()->ID); ImGui::Begin("Controller Configuration", &this->Opened, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize); diff --git a/libultraship/libultraship/Lib/Fast3D/gfx_glx.cpp b/libultraship/libultraship/Lib/Fast3D/gfx_glx.cpp index 43dae33ff..0576583d8 100644 --- a/libultraship/libultraship/Lib/Fast3D/gfx_glx.cpp +++ b/libultraship/libultraship/Lib/Fast3D/gfx_glx.cpp @@ -1,4 +1,4 @@ -#ifdef __linux__ +#if defined(__linux__) && defined(X11_SUPPORTED) #include #include #include @@ -156,6 +156,7 @@ static struct { Atom atom_wm_delete_window; bool is_fullscreen; + bool is_running = true; void (*on_fullscreen_changed)(bool is_now_fullscreen); int keymap[256]; @@ -399,7 +400,7 @@ static void gfx_glx_set_keyboard_callbacks(bool (*on_key_down)(int scancode), bo } static void gfx_glx_main_loop(void (*run_one_game_iter)(void)) { - while (1) { + while (glx.is_running) { run_one_game_iter(); } } @@ -440,7 +441,7 @@ static void gfx_glx_handle_events(void) { } } if (xev.type == ClientMessage && (Atom)xev.xclient.data.l[0] == glx.atom_wm_delete_window) { - exit(0); + glx.is_running = false; } } } diff --git a/libultraship/libultraship/Lib/Fast3D/gfx_opengl.cpp b/libultraship/libultraship/Lib/Fast3D/gfx_opengl.cpp index d79c3aa8f..ad683e047 100644 --- a/libultraship/libultraship/Lib/Fast3D/gfx_opengl.cpp +++ b/libultraship/libultraship/Lib/Fast3D/gfx_opengl.cpp @@ -31,6 +31,9 @@ #elif __APPLE__ #include #include +#elif __SWITCH__ +#include +#include #else #include #include @@ -643,6 +646,10 @@ static void gfx_opengl_upload_texture(const uint8_t *rgba32_buf, uint32_t width, glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, rgba32_buf); } +#ifdef __SWITCH__ +#define GL_MIRROR_CLAMP_TO_EDGE 0x8743 +#endif + static uint32_t gfx_cm_to_opengl(uint32_t val) { switch (val) { case G_TX_NOMIRROR | G_TX_CLAMP: @@ -710,9 +717,9 @@ static void gfx_opengl_draw_triangles(float buf_vbo[], size_t buf_vbo_len, size_ } static void gfx_opengl_init(void) { -//#if FOR_WINDOWS +#ifndef __SWITCH__ glewInit(); -//#endif +#endif glGenBuffers(1, &opengl_vbo); glBindBuffer(GL_ARRAY_BUFFER, opengl_vbo); @@ -840,9 +847,7 @@ void gfx_opengl_start_draw_to_framebuffer(int fb_id, float noise_scale) { if (noise_scale != 0.0f) { current_noise_scale = 1.0f / noise_scale; } - glBindFramebuffer(GL_FRAMEBUFFER, fb.fbo); - current_framebuffer = fb_id; } diff --git a/libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp b/libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp index 0a04c9580..dd5f9bf95 100644 --- a/libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp +++ b/libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp @@ -1206,8 +1206,8 @@ static void gfx_sp_tri1(uint8_t vtx1_idx, uint8_t vtx2_idx, uint8_t vtx3_idx, bo rdp.viewport_or_scissor_changed = false; } - uint64_t cc_id = rdp.combine_mode; + uint64_t cc_id = rdp.combine_mode; bool use_alpha = (rdp.other_mode_l & (3 << 20)) == (G_BL_CLR_MEM << 20) && (rdp.other_mode_l & (3 << 16)) == (G_BL_1MA << 16); bool use_fog = (rdp.other_mode_l >> 30) == G_BL_CLR_FOG; bool texture_edge = (rdp.other_mode_l & CVG_X_ALPHA) == CVG_X_ALPHA; diff --git a/libultraship/libultraship/Lib/Fast3D/gfx_sdl2.cpp b/libultraship/libultraship/Lib/Fast3D/gfx_sdl2.cpp index cb0d7a7f0..2576bc17b 100644 --- a/libultraship/libultraship/Lib/Fast3D/gfx_sdl2.cpp +++ b/libultraship/libultraship/Lib/Fast3D/gfx_sdl2.cpp @@ -15,6 +15,11 @@ #include "SDL_opengl.h" #elif __APPLE__ #include +#elif __SWITCH__ +#include +#include +#include +#include "../../SwitchImpl.h" #else #include #define GL_GLEXT_PROTOTYPES 1 @@ -42,6 +47,7 @@ static int vsync_enabled = 0; static int window_width = DESIRED_SCREEN_WIDTH; static int window_height = DESIRED_SCREEN_HEIGHT; static bool fullscreen_state; +static bool is_running = true; static void (*on_fullscreen_changed_callback)(bool is_now_fullscreen); static bool (*on_key_down_callback)(int scancode); static bool (*on_key_up_callback)(int scancode); @@ -146,31 +152,43 @@ static void gfx_sdl_init(const char *game_name, bool start_in_fullscreen, uint32 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); +#elif defined(__SWITCH__) + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); #endif #ifdef _WIN32 timer = CreateWaitableTimer(nullptr, false, nullptr); #endif - //SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); - //SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4); - char title[512]; int len = sprintf(title, "%s (%s)", game_name, GFX_API_NAME); - window_width = width; - window_height = height; +#ifdef __SWITCH__ + // For Switch we need to set the window width before creating the window + Ship::Switch::GetDisplaySize(&window_width, &window_height); +#endif wnd = SDL_CreateWindow(title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, window_width, window_height, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI); + +#ifndef __SWITCH__ SDL_GL_GetDrawableSize(wnd, &window_width, &window_height); if (start_in_fullscreen) { set_fullscreen(true, false); } +#endif ctx = SDL_GL_CreateContext(wnd); +#ifdef __SWITCH__ + if(!gladLoadGLLoader(SDL_GL_GetProcAddress)){ + printf("Failed to initialize glad\n"); + } +#endif + SDL_GL_SetSwapInterval(1); SohImGui::WindowImpl window_impl; @@ -211,14 +229,21 @@ static void gfx_sdl_set_keyboard_callbacks(bool (*on_key_down)(int scancode), bo } static void gfx_sdl_main_loop(void (*run_one_game_iter)(void)) { - while (1) - { +#ifdef __SWITCH__ + while(Ship::Switch::IsRunning()) { +#else + while(is_running) { +#endif run_one_game_iter(); } +#ifdef __SWITCH__ + Ship::Switch::Exit(); +#endif + ModInternal::ExecuteHooks(); } static void gfx_sdl_get_dimensions(uint32_t *width, uint32_t *height) { - *width = window_width; + *width = window_width; *height = window_height; } @@ -271,7 +296,11 @@ static void gfx_sdl_handle_events(void) { #endif case SDL_WINDOWEVENT: if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) { - SDL_GL_GetDrawableSize(wnd, &window_width, &window_height); + #ifdef __SWITCH__ + Ship::Switch::GetDisplaySize(&window_width, &window_height); + #else + SDL_GL_GetDrawableSize(wnd, &window_width, &window_height); + #endif } break; case SDL_DROPFILE: @@ -303,7 +332,7 @@ static inline void sync_framerate_with_timer(void) { const int64_t next = previous_time + 10 * FRAME_INTERVAL_US_NUMERATOR / FRAME_INTERVAL_US_DENOMINATOR; const int64_t left = next - t; if (left > 0) { -#if defined __linux__ || defined __APPLE__ +#ifndef _WIN32 const timespec spec = { 0, left * 100 }; nanosleep(&spec, nullptr); #else diff --git a/libultraship/libultraship/Lib/ImGui/backends/imgui_impl_opengl3.cpp b/libultraship/libultraship/Lib/ImGui/backends/imgui_impl_opengl3.cpp index b7587d0e7..6d4483a91 100644 --- a/libultraship/libultraship/Lib/ImGui/backends/imgui_impl_opengl3.cpp +++ b/libultraship/libultraship/Lib/ImGui/backends/imgui_impl_opengl3.cpp @@ -132,6 +132,10 @@ #else #include // Use GL ES 3 #endif +#elif defined(__SWITCH__) +#define IMGUI_IMPL_OPENGL_LOADER_CUSTOM +#define GL_GLEXT_PROTOTYPES 1 +#include #elif !defined(IMGUI_IMPL_OPENGL_LOADER_CUSTOM) // Modern desktop OpenGL doesn't have a standard portable header file to load OpenGL function pointers. // Helper libraries are often used for this purpose! Here we are using our own minimal custom loader based on gl3w. diff --git a/libultraship/libultraship/Lib/ImGui/backends/imgui_impl_sdl.cpp b/libultraship/libultraship/Lib/ImGui/backends/imgui_impl_sdl.cpp index 931660a9d..8cbdceac5 100644 --- a/libultraship/libultraship/Lib/ImGui/backends/imgui_impl_sdl.cpp +++ b/libultraship/libultraship/Lib/ImGui/backends/imgui_impl_sdl.cpp @@ -65,6 +65,7 @@ #include "imgui.h" #include "imgui_impl_sdl.h" +#include "imgui_internal.h" // SDL // (the multi-viewports feature requires SDL features supported from SDL 2.0.4+. SDL 2.0.5+ is highly recommended) @@ -77,7 +78,7 @@ #include #endif -#if SDL_VERSION_ATLEAST(2,0,4) && !defined(__EMSCRIPTEN__) && !defined(__ANDROID__) && !(defined(__APPLE__) && TARGET_OS_IOS) && !defined(__amigaos4__) +#if SDL_VERSION_ATLEAST(2,0,4) && !defined(__EMSCRIPTEN__) && !defined(__ANDROID__) && !(defined(__APPLE__) && TARGET_OS_IOS) && !defined(__amigaos4__) && !defined(__SWITCH__) #define SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE 1 #else #define SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE 0 @@ -105,6 +106,7 @@ struct ImGui_ImplSDL2_Data char* ClipboardTextData; bool MouseCanUseGlobalState; bool UseVulkan; + bool ShowingVirtualKeyboard; ImGui_ImplSDL2_Data() { memset((void*)this, 0, sizeof(*this)); } }; @@ -269,6 +271,23 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event) { ImGuiIO& io = ImGui::GetIO(); ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData(); + ImGuiInputTextState* state = ImGui::GetInputTextState(ImGui::GetActiveID()); + + #ifdef __SWITCH__ + if (io.WantTextInput) { + if (!bd->ShowingVirtualKeyboard) { + state->ClearText(); + + bd->ShowingVirtualKeyboard = true; + SDL_StartTextInput(); + } + } else { + if (bd->ShowingVirtualKeyboard) { + bd->ShowingVirtualKeyboard = false; + SDL_StopTextInput(); + } + } + #endif switch (event->type) { @@ -411,6 +430,7 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window, SDL_Renderer* renderer, void // Our mouse update function expect PlatformHandle to be filled for the main viewport ImGuiViewport* main_viewport = ImGui::GetMainViewport(); main_viewport->PlatformHandle = (void*)window; +#if defined(_WIN32) || defined(__APPLE__) SDL_SysWMinfo info; SDL_VERSION(&info.version); if (SDL_GetWindowWMInfo(window, &info)) @@ -421,6 +441,7 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window, SDL_Renderer* renderer, void main_viewport->PlatformHandleRaw = (void*)info.info.cocoa.window; #endif } +#endif // Set SDL hint to receive mouse click events on window focus, otherwise SDL doesn't emit the event. // Without this, when clicking to gain focus, our widgets wouldn't activate even though they showed as hovered. @@ -583,8 +604,11 @@ static void ImGui_ImplSDL2_UpdateMouseCursor() static void ImGui_ImplSDL2_UpdateGamepads() { ImGuiIO& io = ImGui::GetIO(); - if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) - return; + + // Remove this check because we always want to be able to trigger the menu via controller + // The ImGuiConfigFlags_NavEnableGamepad is still separately used by ImGui for enabling imgui navigation + // if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) + // return; // Get gamepad io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad; @@ -600,10 +624,17 @@ static void ImGui_ImplSDL2_UpdateGamepads() const int thumb_dead_zone = 8000; // SDL_gamecontroller.h suggests using this value. MAP_BUTTON(ImGuiKey_GamepadStart, SDL_CONTROLLER_BUTTON_START); MAP_BUTTON(ImGuiKey_GamepadBack, SDL_CONTROLLER_BUTTON_BACK); +#ifdef __SWITCH__ + MAP_BUTTON(ImGuiKey_GamepadFaceDown, SDL_CONTROLLER_BUTTON_B); // Xbox A, PS Cross + MAP_BUTTON(ImGuiKey_GamepadFaceRight, SDL_CONTROLLER_BUTTON_A); // Xbox B, PS Circle + MAP_BUTTON(ImGuiKey_GamepadFaceLeft, SDL_CONTROLLER_BUTTON_Y); // Xbox X, PS Square + MAP_BUTTON(ImGuiKey_GamepadFaceUp, SDL_CONTROLLER_BUTTON_X); // Xbox Y, PS Triangle +#else MAP_BUTTON(ImGuiKey_GamepadFaceDown, SDL_CONTROLLER_BUTTON_A); // Xbox A, PS Cross MAP_BUTTON(ImGuiKey_GamepadFaceRight, SDL_CONTROLLER_BUTTON_B); // Xbox B, PS Circle MAP_BUTTON(ImGuiKey_GamepadFaceLeft, SDL_CONTROLLER_BUTTON_X); // Xbox X, PS Square MAP_BUTTON(ImGuiKey_GamepadFaceUp, SDL_CONTROLLER_BUTTON_Y); // Xbox Y, PS Triangle +#endif MAP_BUTTON(ImGuiKey_GamepadDpadLeft, SDL_CONTROLLER_BUTTON_DPAD_LEFT); MAP_BUTTON(ImGuiKey_GamepadDpadRight, SDL_CONTROLLER_BUTTON_DPAD_RIGHT); MAP_BUTTON(ImGuiKey_GamepadDpadUp, SDL_CONTROLLER_BUTTON_DPAD_UP); @@ -757,6 +788,7 @@ static void ImGui_ImplSDL2_CreateWindow(ImGuiViewport* viewport) SDL_GL_MakeCurrent(vd->Window, backup_context); viewport->PlatformHandle = (void*)vd->Window; +#if defined(_WIN32) || defined(__APPLE__) SDL_SysWMinfo info; SDL_VERSION(&info.version); if (SDL_GetWindowWMInfo(vd->Window, &info)) @@ -767,6 +799,7 @@ static void ImGui_ImplSDL2_CreateWindow(ImGuiViewport* viewport) viewport->PlatformHandleRaw = (void*)info.info.cocoa.window; #endif } +#endif } static void ImGui_ImplSDL2_DestroyWindow(ImGuiViewport* viewport) diff --git a/libultraship/libultraship/SDLController.cpp b/libultraship/libultraship/SDLController.cpp index 3d02a8614..398ce1944 100644 --- a/libultraship/libultraship/SDLController.cpp +++ b/libultraship/libultraship/SDLController.cpp @@ -4,6 +4,10 @@ #include "Window.h" #include +#ifdef _MSC_VER +#define strdup _strdup +#endif + extern "C" uint8_t __osMaxControllers; namespace Ship { @@ -25,11 +29,16 @@ namespace Ship { char GuidBuf[33]; SDL_JoystickGetGUIDString(SDL_JoystickGetDeviceGUID(physicalSlot), GuidBuf, sizeof(GuidBuf)); - GUID = std::string(GuidBuf); Cont = NewCont; wCamX = 0; wCamY = 0; - +#ifdef __SWITCH__ + GUID = StringHelper::Sprintf("%s:%d", GuidBuf, physicalSlot); + ControllerName = StringHelper::Sprintf("%s #%d", SDL_GameControllerNameForIndex(physicalSlot), physicalSlot + 1); +#else + GUID = std::string(GuidBuf); + ControllerName = std::string(SDL_GameControllerNameForIndex(physicalSlot)); +#endif return true; } @@ -441,7 +450,7 @@ namespace Ship { } const char* SDLController::GetControllerName() { - return SDL_GameControllerNameForIndex(physicalSlot); + return strdup(ControllerName.c_str()); } void SDLController::CreateDefaultBinding(int32_t slot) { diff --git a/libultraship/libultraship/SDLController.h b/libultraship/libultraship/SDLController.h index ae239a2f1..e5d24c946 100644 --- a/libultraship/libultraship/SDLController.h +++ b/libultraship/libultraship/SDLController.h @@ -31,6 +31,7 @@ namespace Ship { void CreateDefaultBinding(int32_t slot) override; private: + std::string ControllerName = "Unknown"; SDL_GameController* Cont; int physicalSlot; bool supportsGyro; diff --git a/libultraship/libultraship/SwitchImpl.cpp b/libultraship/libultraship/SwitchImpl.cpp new file mode 100644 index 000000000..321b40648 --- /dev/null +++ b/libultraship/libultraship/SwitchImpl.cpp @@ -0,0 +1,286 @@ +#ifdef __SWITCH__ +#include "SwitchImpl.h" +#include +#include +#include "SwitchPerformanceProfiles.h" +#include "Cvar.h" +#include "Hooks.h" + +extern "C" s32 CVar_GetS32(const char* name, s32 defaultValue); +extern "C" void CVar_SetS32(const char* name, s32 value); + +#define DOCKED_MODE 1 +#define HANDHELD_MODE 0 + +static AppletHookCookie applet_hook_cookie; +static bool isRunning = true; +static bool hasFocus = true; + +void DetectAppletMode(); + +static void on_applet_hook(AppletHookType hook, void *param); + +void Ship::Switch::Init(SwitchPhase phase){ + switch(phase){ + case PreInitPhase: + DetectAppletMode(); + break; + case PostInitPhase: + appletInitializeGamePlayRecording(); + #ifdef DEBUG + socketInitializeDefault(); + nxlinkStdio(); + #endif + appletSetGamePlayRecordingState(true); + appletHook(&applet_hook_cookie, on_applet_hook, NULL); + appletSetFocusHandlingMode(AppletFocusHandlingMode_NoSuspend); + if (!hosversionBefore(8, 0, 0)) { + clkrstInitialize(); + } + break; + } +} + +void Ship::Switch::Exit(){ +#ifdef DEBUG + socketExit(); +#endif + clkrstExit(); + appletSetGamePlayRecordingState(false); +} + +void Ship::Switch::SetupFont(ImFontAtlas* fonts) { + plInitialize(PlServiceType_System); + static PlFontData stdFontData, extFontData; + + PlFontData fonts_std; + PlFontData fonts_ext; + + plGetSharedFontByType(&fonts_std, PlSharedFontType_Standard); + plGetSharedFontByType(&fonts_ext, PlSharedFontType_NintendoExt); + + ImFontConfig config; + config.FontDataOwnedByAtlas = false; + + strcpy(config.Name, "Nintendo Standard"); + fonts->AddFontFromMemoryTTF (fonts_std.address, fonts_std.size, 24.0f, &config, fonts->GetGlyphRangesCyrillic()); + + strcpy(config.Name, "Nintendo Ext"); + static const ImWchar ranges[] = + { + 0xE000, 0xE06B, + 0xE070, 0xE07E, + 0xE080, 0xE099, + 0xE0A0, 0xE0BA, + 0xE0C0, 0xE0D6, + 0xE0E0, 0xE0F5, + 0xE100, 0xE105, + 0xE110, 0xE116, + 0xE121, 0xE12C, + 0xE130, 0xE13C, + 0xE140, 0xE14D, + 0xE150, 0xE153, + 0, + }; + + fonts->AddFontFromMemoryTTF (fonts_ext.address, fonts_ext.size, 24.0f, &config, ranges); + fonts->Build (); + + plExit(); +} + +bool Ship::Switch::IsRunning(){ + return isRunning; +} + +void Ship::Switch::GetDisplaySize(int *width, int *height) { + switch (appletGetOperationMode()) { + case DOCKED_MODE: + *width = 1920; + *height = 1080; + break; + case HANDHELD_MODE: + *width = 1280; + *height = 720; + break; + } +} + +void Ship::Switch::ApplyOverclock(void) { + SwitchProfiles perfMode = (SwitchProfiles) CVar_GetS32("gSwitchPerfMode", (int) Ship::MAXIMUM); + + if (perfMode >= 0 && perfMode <= Ship::POWERSAVINGM3) { + if (hosversionBefore(8, 0, 0)) { + pcvSetClockRate(PcvModule_CpuBus, SWITCH_CPU_SPEEDS_VALUES[ perfMode ]); + } else { + ClkrstSession session = {0}; + clkrstOpenSession(&session, PcvModuleId_CpuBus, 3); + clkrstSetClockRate(&session, SWITCH_CPU_SPEEDS_VALUES[ perfMode ]); + clkrstCloseSession(&session); + } + } +} + +struct Star { + SDL_Rect* rect; + float speed; + int layer; + int8_t color[3]; +}; + +std::vector stars; + +void Ship::Switch::PrintErrorMessageToScreen(const char *str, ...) { + + if (SDL_Init(SDL_INIT_VIDEO) < 0) + return; + + int width, height; + Uint64 now, last, deltaTime; + GetDisplaySize(&width, &height); + + SDL_Window* win = SDL_CreateWindow("Switch-Error", 0, 0, width, height, 0); + SDL_Renderer* renderer = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED); + + va_list args; + va_start(args, str); + vprintf(str, args); + va_end(args); + + int layers = 9; + + for(int layer = 0; layer < layers; layer++) { + for(int i = 0; i < 100; i++) { + srand(time(0)); + + int brightness = 50 - layer * (rand() * 5); + SDL_Rect rect; + rect.x = rand() % width; + rect.y = i*i; + rect.w = rand() % 20; + rect.h = rand() % 20; + + stars.push_back(new Star{ + &rect, + 0.03f, + layer, + { + 120 + brightness, + 120 + brightness, + 120 + brightness + } + }); + } + } + + while(appletMainLoop()){ + SDL_Event e; + if ( SDL_PollEvent(&e) ) { + if (e.type == SDL_QUIT) + break; + } + + last = now; + now = SDL_GetPerformanceCounter(); + + deltaTime = (double)((now - last) * 1000 / (double) SDL_GetPerformanceFrequency() ); + + SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); + SDL_RenderClear(renderer); + + for(int i = 0; i < stars.size(); i++){ + Star* star = stars[i]; + + if(star->rect->x >= width){ + star->rect->x = -star->rect->w; + } + + star->rect->x += 1; + // star->rect->y += (cos((star->rect->x / star->layer)) * .9f ) / 16; + SDL_SetRenderDrawColor(renderer, star->color[0], star->color[1], star->color[2], 255); + SDL_RenderFillRect( renderer, star->rect ); + } + + SDL_RenderPresent(renderer); + SDL_Delay(0); + } + +} + +static void on_applet_hook(AppletHookType hook, void *param) { + AppletFocusState focus_state; + + /* Exit request */ + switch (hook) { + case AppletHookType_OnExitRequest: + isRunning = false; + break; + + /* Focus state*/ + case AppletHookType_OnFocusState: + focus_state = appletGetFocusState(); + hasFocus = focus_state == AppletFocusState_InFocus; + + if (!hasFocus) { + if (hosversionBefore(8, 0, 0)) { + pcvSetClockRate(PcvModule_CpuBus, SWITCH_CPU_SPEEDS_VALUES[ Ship::STOCK ]); + } else { + ClkrstSession session = {0}; + clkrstOpenSession(&session, PcvModuleId_CpuBus, 3); + clkrstSetClockRate(&session, SWITCH_CPU_SPEEDS_VALUES[ Ship::STOCK ]); + clkrstCloseSession(&session); + } + } else + Ship::Switch::ApplyOverclock(); + break; + + /* Performance mode */ + case AppletHookType_OnPerformanceMode: + Ship::Switch::ApplyOverclock(); + break; + default: break; + } +} + +const char* RandomTexts[] = { + "Psst, don't forget to blame Melon", + "Potsanity when?", + "Why are you acting so random?", + "Enough! My ship sails in the morning", + "Do you want 2 or 7 of those?", + "Lamp oil, rope, bombs you want it, it's yours my friend as long as you have enough rupees", + "You can build it yourself", + "Descargar para android", + "Made with <3 by the Harbour Masters!", + "They say that Kenix is not a developer", + "Squadala we're off", + "They say one once saw an equals not get set equals", + "This is the port all true gamers dock at" + "Enhancements? Times Savers? Cheats? You want them? They're yours my friend!", + "They say you gotta have the BIIIIG salad", + "They say Louis stopped working on the imports so he can focus on the exports", + "They say ZAPD is good software", +}; + +void DetectAppletMode() { + AppletType at = appletGetAppletType(); + if (at == AppletType_Application || at == AppletType_SystemApplication) + return; + + srand(time(0)); + Ship::Switch::PrintErrorMessageToScreen( + "\x1b[2;2HYou've launched the Ship while in Applet mode." + "\x1b[4;2HPlease relaunch while in full-memory mode." + "\x1b[5;2HHold R when opening any game to enter HBMenu." + "\x1b[44;2H%s." + , RandomTexts[rand() % 25]); +} + +void Ship::Switch::ThrowMissingOTR(std::string OTRPath){ + Ship::Switch::PrintErrorMessageToScreen( + "\x1b[2;2HYou've launched the Ship without the OTR file." + "\x1b[4;2HPlease relaunch making sure %s exists." + "\x1b[44;2H%s." + , OTRPath.c_str(), RandomTexts[rand() % 25]); +} +#endif \ No newline at end of file diff --git a/libultraship/libultraship/SwitchImpl.h b/libultraship/libultraship/SwitchImpl.h new file mode 100644 index 000000000..af592413a --- /dev/null +++ b/libultraship/libultraship/SwitchImpl.h @@ -0,0 +1,36 @@ +#pragma once + +#include +#include + +#include "Lib/ImGui/imgui.h" +#include "SwitchPerformanceProfiles.h" + +namespace Ship { + enum SwitchProfiles { + MAXIMUM, + HIGH, + BOOST, + STOCK, + POWERSAVINGM1, + POWERSAVINGM2, + POWERSAVINGM3 + }; + + enum SwitchPhase { + PreInitPhase, + PostInitPhase + }; + + class Switch { + public: + static void Init(SwitchPhase phase); + static void Exit(); + static void SetupFont(ImFontAtlas* fonts); + static bool IsRunning(); + static void GetDisplaySize(int *width, int *height); + static void ApplyOverclock(); + static void ThrowMissingOTR(std::string OTRPath); + static void PrintErrorMessageToScreen(const char *str, ...); + }; +}; \ No newline at end of file diff --git a/libultraship/libultraship/SwitchPerformanceProfiles.h b/libultraship/libultraship/SwitchPerformanceProfiles.h new file mode 100644 index 000000000..1cb930c0a --- /dev/null +++ b/libultraship/libultraship/SwitchPerformanceProfiles.h @@ -0,0 +1,21 @@ +#pragma once + +static const char *SWITCH_CPU_PROFILES[] = { + "Maximum Performance", + "High Performance", + "Boost Performance", + "Stock Performance", + "Powersaving Mode 1", + "Powersaving Mode 2", + "Powersaving Mode 3", +}; + +static unsigned SWITCH_CPU_SPEEDS_VALUES[] = { + 1785000000, + 1581000000, + 1224000000, + 1020000000, + 918000000, + 816000000, + 714000000 +}; \ No newline at end of file diff --git a/libultraship/libultraship/Window.cpp b/libultraship/libultraship/Window.cpp index 9d28ecf5e..9957ebc48 100644 --- a/libultraship/libultraship/Window.cpp +++ b/libultraship/libultraship/Window.cpp @@ -28,6 +28,7 @@ #include #include "Hooks.h" #include "Console.h" +#include "Cvar.h" #include @@ -35,7 +36,6 @@ extern "C" { struct OSMesgQueue; uint8_t __osMaxControllers = MAXCONTROLLERS; - uint8_t __enableGameInput = 1; int32_t osContInit(OSMesgQueue* mq, uint8_t* controllerBits, OSContStatus* status) { *controllerBits = 0; @@ -45,6 +45,7 @@ extern "C" { exit(EXIT_FAILURE); } + #ifndef __SWITCH__ const char* controllerDb = "gamecontrollerdb.txt"; int mappingsAdded = SDL_GameControllerAddMappingsFromFile(controllerDb); if (mappingsAdded >= 0) { @@ -52,6 +53,7 @@ extern "C" { } else { SPDLOG_ERROR("Failed add SDL game controller mappings from \"{}\" ({})", controllerDb, SDL_GetError()); } + #endif Ship::Window::ControllerApi->Init(controllerBits); @@ -72,7 +74,7 @@ extern "C" { pad->gyro_x = 0; pad->gyro_y = 0; - if (__enableGameInput) { + if (!CVar_GetS32("gOpenMenuBar", 0)) { Ship::Window::ControllerApi->WriteToPad(pad); } @@ -302,7 +304,6 @@ namespace Ship { void Window::MainLoop(void (*MainFunction)(void)) { WmApi->main_loop(MainFunction); } - bool Window::KeyUp(int32_t dwScancode) { std::shared_ptr pConf = GlobalCtx2::GetInstance()->GetConfig(); @@ -314,7 +315,7 @@ namespace Ship { //if (dwScancode == Ship::stoi(Conf["KEYBOARD SHORTCUTS"]["KEY_CONSOLE"])) { // ToggleConsole(); //} - + lastScancode = -1; bool bIsProcessed = false; diff --git a/libultraship/libultraship/WindowShim.cpp b/libultraship/libultraship/WindowShim.cpp index 4469c5c29..ca9357575 100644 --- a/libultraship/libultraship/WindowShim.cpp +++ b/libultraship/libultraship/WindowShim.cpp @@ -22,7 +22,7 @@ void SetWindowManager(struct GfxWindowManagerAPI** WmApi, struct GfxRenderingAPI // First set default #ifdef ENABLE_OPENGL *RenderingApi = &gfx_opengl_api; - #if defined(__linux__) + #if defined(__linux__) && defined(X11_SUPPORTED) // LINUX_TODO: // *WmApi = &gfx_glx; *WmApi = &gfx_sdl; @@ -51,7 +51,7 @@ void SetWindowManager(struct GfxWindowManagerAPI** WmApi, struct GfxRenderingAPI *RenderingApi = &gfx_opengl_api; *WmApi = &gfx_sdl; } -#ifdef __linux__ +#if defined(__linux__) && defined(X11_SUPPORTED) if (gfx_backend == "glx") { *RenderingApi = &gfx_opengl_api; *WmApi = &gfx_glx; diff --git a/libultraship/libultraship/libultraship.vcxproj b/libultraship/libultraship/libultraship.vcxproj index 920f6442f..9c759f85a 100644 --- a/libultraship/libultraship/libultraship.vcxproj +++ b/libultraship/libultraship/libultraship.vcxproj @@ -450,12 +450,6 @@ - - - {02d10590-9542-3f55-aaf8-6055677e2a2a} - false - - diff --git a/soh/Makefile b/soh/Makefile index b05321a60..2c0f9ff31 100644 --- a/soh/Makefile +++ b/soh/Makefile @@ -179,7 +179,7 @@ all: $(MAKE) $(TARGET) setup: - cd ../OTRExporter && python3 extract_baserom.py + cd ../OTRExporter $(MAKE) mpq mpq: diff --git a/soh/Makefile.switch b/soh/Makefile.switch new file mode 100644 index 000000000..10eaaebab --- /dev/null +++ b/soh/Makefile.switch @@ -0,0 +1,280 @@ +#--------------------------------------------------------------------------------- +.SUFFIXES: +#--------------------------------------------------------------------------------- + +ifeq ($(strip $(DEVKITPRO)),) +$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=/devkitpro") +endif + +TOPDIR ?= $(CURDIR) +include $(DEVKITPRO)/libnx/switch_rules + +#--------------------------------------------------------------------------------- +# TARGET is the name of the output +# BUILD is the directory where object files & intermediate files will be placed +# SOURCES is a list of directories containing source code +# DATA is a list of directories containing data files +# INCLUDES is a list of directories containing header files +# ROMFS is the directory containing data to be added to RomFS, relative to the Makefile (Optional) +# +# NO_ICON: if set to anything, do not use icon. +# NO_NACP: if set to anything, no .nacp file is generated. +# APP_TITLE is the name of the app stored in the .nacp file (Optional) +# APP_AUTHOR is the author of the app stored in the .nacp file (Optional) +# APP_VERSION is the version of the app stored in the .nacp file (Optional) +# APP_TITLEID is the titleID of the app stored in the .nacp file (Optional) +# ICON is the filename of the icon (.jpg), relative to the project folder. +# If not set, it attempts to use one of the following (in this order): +# - .jpg +# - icon.jpg +# - /default_icon.jpg +# +# CONFIG_JSON is the filename of the NPDM config file (.json), relative to the project folder. +# If not set, it attempts to use one of the following (in this order): +# - .json +# - config.json +# If a JSON file is provided or autodetected, an ExeFS PFS0 (.nsp) is built instead +# of a homebrew executable (.nro). This is intended to be used for sysmodules. +# NACP building is skipped as well. +#--------------------------------------------------------------------------------- +TARGET := $(notdir $(CURDIR)) +BUILD := build +SOURCES := switch +DATA := +INCLUDES := \ + . \ + assets \ + build \ + include \ + src \ + ../ZAPDTR/ZAPDUtils \ + ../libultraship/libultraship \ + ../libultraship/libultraship/Lib/spdlog/include \ + ../libultraship/libultraship/Lib/Fast3D/U64 \ + ../libultraship/libultraship/Lib/Fast3D/U64/PR + +#------------------------------------------------------------------------------- +# source files +#------------------------------------------------------------------------------- +SOURCEFILES_C := \ + $(shell find soh -type f -name "*.c") \ + $(shell find src/boot -type f -name "*.c") \ + $(shell find src/buffers -type f -name "*.c") \ + $(shell find src/code -type f -name "*.c") \ + $(shell find src/overlays -type f -name "*.c") \ + src/libultra/gu/coss.c \ + src/libultra/gu/guLookAt.c \ + src/libultra/gu/guLookAtHilite.c \ + src/libultra/gu/guPerspectiveF.c \ + src/libultra/gu/guPosition.c \ + src/libultra/gu/guS2DInitBg.c \ + src/libultra/gu/ortho.c \ + src/libultra/gu/rotate.c \ + src/libultra/gu/sins.c \ + src/libultra/gu/sintable.c \ + src/libultra/libc/sprintf.c + +SOURCEFILES_CPP := \ + $(shell find soh -type f -name "*.cpp") +#--------------------------------------------------------------------------------- +# app info +#--------------------------------------------------------------------------------- + +APP_TITLE := Ship of Harkinian +APP_AUTHOR := Harbour Masters +APP_VERSION := Rachael-Alfa + +#--------------------------------------------------------------------------------- +# options for code generation +#--------------------------------------------------------------------------------- +ARCH := -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE -ffast-math -O3 + +CFLAGS := -ffunction-sections \ + $(ARCH) $(DEFINES) + +CFLAGS += $(INCLUDE) -D__SWITCH__ \ + -DSPDLOG_NO_THREAD_ID \ + -DSTBI_NO_THREAD_LOCALS \ + `sdl2-config --cflags` + +CXXFLAGS := $(CFLAGS) -std=gnu++20 -fpermissive +CFLAGS += -std=gnu11 + +# disable some warnings +CFLAGS += -Wno-incompatible-pointer-types -Wno-int-conversion \ + -Wno-builtin-declaration-mismatch -Wno-implicit-function-declaration \ + -Wno-stringop-overflow -Wno-discarded-qualifiers -Wno-switch-unreachable + +ASFLAGS := -g $(ARCH) +LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) + +STATIC_LIBS := $(SOH_TOP_DIR)/libultraship/lib/libultraship.a \ + $(SOH_TOP_DIR)/ZAPDTR/ZAPDUtils/lib/libZAPDUtils.a \ + $(SOH_TOP_DIR)/ZAPDTR/ZAPDUtils/lib/libZAPDUtils.a \ + $(SOH_TOP_DIR)/StormLib/nxbuild/libstorm.a \ + +LIBS := -L$(SOH_TOP_DIR)/StormLib/nxbuild/ -lultraship -lZAPDUtils -lstorm -lz -lbz2 -lnx -lglad -lglapi -ldrm_nouveau -lm `sdl2-config --libs` + +#--------------------------------------------------------------------------------- +# list of directories containing libraries, this must be the top level containing +# include and lib +#--------------------------------------------------------------------------------- +LIBDIRS := $(PORTLIBS) $(LIBNX) $(SOH_TOP_DIR)/StormLib/nxbuild $(SOH_TOP_DIR)/libultraship $(SOH_TOP_DIR)/ZAPDTR/ZAPDUtils + +#--------------------------------------------------------------------------------- +# no real need to edit anything past this point unless you need to add additional +# rules for different file extensions +#--------------------------------------------------------------------------------- +ifneq ($(BUILD),$(notdir $(CURDIR))) +#--------------------------------------------------------------------------------- + +export OUTPUT := $(CURDIR)/$(TARGET) +export TOPDIR := $(CURDIR) + +export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ + $(foreach dir,$(DATA),$(CURDIR)/$(dir)) \ + $(foreach sf,$(SOURCEFILES_C),$(CURDIR)/$(dir $(sf))) \ + $(foreach sf,$(SOURCEFILES_CPP),$(CURDIR)/$(dir $(sf))) + +export DEPSDIR := $(CURDIR)/$(BUILD) + +CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) \ + $(foreach f,$(SOURCEFILES_C),$(notdir $(f))) +CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) \ + $(foreach f,$(SOURCEFILES_CPP),$(notdir $(f))) +SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) +BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) + +#--------------------------------------------------------------------------------- +# use CXX for linking C++ projects, CC for standard C +#--------------------------------------------------------------------------------- +ifeq ($(strip $(CPPFILES)),) +#--------------------------------------------------------------------------------- + export LD := $(CC) +#--------------------------------------------------------------------------------- +else +#--------------------------------------------------------------------------------- + export LD := $(CXX) +#--------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------- + +export OFILES_BIN := $(addsuffix .o,$(BINFILES)) +export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) +export OFILES := $(OFILES_BIN) $(OFILES_SRC) +export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES))) + +export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ + $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ + -I$(CURDIR)/$(BUILD) + +export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) + +ifeq ($(strip $(CONFIG_JSON)),) + jsons := $(wildcard *.json) + ifneq (,$(findstring $(TARGET).json,$(jsons))) + export APP_JSON := $(TOPDIR)/$(TARGET).json + else + ifneq (,$(findstring config.json,$(jsons))) + export APP_JSON := $(TOPDIR)/config.json + endif + endif +else + export APP_JSON := $(TOPDIR)/$(CONFIG_JSON) +endif + +ifeq ($(strip $(ICON)),) + icons := $(wildcard *.jpg) + ifneq (,$(findstring $(TARGET).jpg,$(icons))) + export APP_ICON := $(TOPDIR)/$(TARGET).jpg + else + ifneq (,$(findstring icon.jpg,$(icons))) + export APP_ICON := $(TOPDIR)/icon.jpg + endif + endif +else + export APP_ICON := $(TOPDIR)/$(ICON) +endif + +ifeq ($(strip $(NO_ICON)),) + export NROFLAGS += --icon=$(APP_ICON) +endif + +ifeq ($(strip $(NO_NACP)),) + export NROFLAGS += --nacp=$(CURDIR)/$(TARGET).nacp +endif + +ifneq ($(APP_TITLEID),) + export NACPFLAGS += --titleid=$(APP_TITLEID) +endif + +ifneq ($(ROMFS),) + export NROFLAGS += --romfsdir=$(CURDIR)/$(ROMFS) +endif + +.PHONY: $(BUILD) clean all + +#--------------------------------------------------------------------------------- +all: $(BUILD) + +$(BUILD): + @[ -d $@ ] || mkdir -p $@ + @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile.switch + +#--------------------------------------------------------------------------------- +clean: + @echo clean ... +ifeq ($(strip $(APP_JSON)),) + @rm -fr $(BUILD) $(TARGET).nro $(TARGET).nacp $(TARGET).elf +else + @rm -fr $(BUILD) $(TARGET).nsp $(TARGET).nso $(TARGET).npdm $(TARGET).elf +endif + + +#--------------------------------------------------------------------------------- +else +.PHONY: all + +DEPENDS := $(OFILES:.o=.d) + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- +ifeq ($(strip $(APP_JSON)),) + +all : $(OUTPUT).nro + +ifeq ($(strip $(NO_NACP)),) +$(OUTPUT).nro : $(OUTPUT).elf $(OUTPUT).nacp +else +$(OUTPUT).nro : $(OUTPUT).elf +endif + +else + +all : $(OUTPUT).nsp + +$(OUTPUT).nsp : $(OUTPUT).nso $(OUTPUT).npdm + +$(OUTPUT).nso : $(OUTPUT).elf + +endif + +$(OUTPUT).elf : $(OFILES) \ + $(STATIC_LIBS) + +$(OFILES_SRC) : $(HFILES_BIN) + +#--------------------------------------------------------------------------------- +# you need a rule like this for each extension you use as binary data +#--------------------------------------------------------------------------------- +%.bin.o %_bin.h : %.bin +#--------------------------------------------------------------------------------- + @echo $(notdir $<) + @$(bin2o) + +-include $(DEPENDS) + +#--------------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------------- \ No newline at end of file diff --git a/soh/icon.jpg b/soh/icon.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3a855753b52ef27fa1e349f71433146233efe876 GIT binary patch literal 5859 zcmbVQ1zeO(w||yqX{1AhrIGF~SwfIlN>V})R!}JkB?LhcK^j+@r9mW>4ha#EPBG|o z6_$2k?}D$d@BQxgyEXeeXJ?+6GygNE=D|*3zXH^HP+ceh0)c>QxF3L>16;KH-CO{` zzyJ^g0DuG_0I>jsxE=^cDj?Rs`%n-+fPZ!!4|h`>z;S>YM^|uk+OFZ~^qsT++YWA? zJ|dpieJ)6eNQ%e-*pGlF0463TAtnNokdTmp!DN(7)RYtyl2z{ zSy5gADFIF{F?De%c|{c!6&{gGx|&KlvdSuor;~udWMq^Slx)=0Y>NC`{EGkQhHV3A zNIkgenSbPo%M5D5u-emX(x1^)j15z*pBNHdL7Mn*k)9G#Gu zl$?^9_8gI$hs-Z1EGjOks;;T6d;O-qq2q05S9j05-uEM;W8)K(Q`0kZ^9zeh%PXsE z>s#CCo!!0tgTtd!T&FmHw_m{i1s4qt7ajotJ^}G5E)d>b9O2Ut5ORtW(W)C0JKQ

**b-GhU|X_?7{yF+26qa;F0jM zf$7{9xeNPTbcSLCT!{+aks?~j5w8<)>nYNMiYf(#R=`j0-az-LVD?2EbG`$>#+ zyZ!0f(Q;sQ?yo?A^tR4V^PTgpTU(6BKK9E(_k1c|&V89P9Ot0#!~)%gs~yotu*Hu5 zc5jHPP&O<%A_(R_0m1v~WpLw%H?{|CS%=CMBw^vz8a)Mbe%0bOD+F7Y8g6O@g5Sr| zCNp`dUuBu>8n1w5<~2&75SN+1>G)9BtXDDOho$c-D^4sj?xjl9h}rZAm7q9Tl`Ldv z>2B}3l1$r{ipIByG~YCk(+ixwbrLf9+%bBWO6-pk{@HWT0_coDI2Q5Mh{$8F*29f2 zWyE1C{TgD)v(~y8wdfQeX0l1oppob4|24=WD$Vgb3YLrr%*;GTwO3Fh1md{P5hv|9 zg1Rh}l*#24l}yYU<$J_&((1ld+&hX$SPg{f-MQoHed`YU7^%`lW;SP*l$H?*6TQpD zXb-8)j%dgKVy^$N2!RAVqp*oYyr?Lx@s?uYhyAw);Qlssb7)rrbPt5>8WxDXE7By8 zXUkR_4gKgB&Hy`qz~;JPFKHDXQ}0^5(NVh__Qd-KYUwxacS#sKL*|l#Ugc3}x4ty1ytVHLBs-2261SeP(Kf<5*fvqJjK?79d0>|pc%TUo} zupF1w`gTmiWNSpXNfN}MQ7T~!EzT5BEME@Wv>l*dOIQD`&NH2!G9J3nKl+Zv>n*ja zxyJA%uI)#N{-jy-R^^vYZC|PgaoxH%2Hj1%ToMYA=1do29w-aRW90LtI((~R1+ODi+-QNn`|GJYVuSsgqFL?S7D$v*cuC{OOJf7kY&Z##}8}HG2Rzh zpO46k`E(RC2< z66UdhWr~#cGY!DZI5SUKF|#$bHXtA`xQk~z;|+In-mP4L0rI*jM(SQl)B{tYtOB<% zQ|k9JuNLX&Tf9vNuS*RF>5eUq?mh{6To6A;6-7DS24P+`WFDNedkPPM2a?t{L@v0s zZzCzf4=ijI5)k_t(>>;hCr#!NKiBR~6mWgd|Dwihm4|9HUdal>Ezy%uMGp|yG?vK*NU4-xBJG{_Qsia zghjrJC3I6;E>?+jt3GP4py^Wnu*=6Dvk^zMR#mt9*&ixKZx7jc$G2PdA`Z`n5JosF zQ5W#}q4=RorB6uGjC9rv^+*3!1GGMDRxfnLZ%a%SRqA|_%)gaV>ip4{U0C8Rzu3_0 zR-2XW`~f*n6-&c8sd9`5vM*jX>!#ZJ7K(W7HQ!G86OSwJ(OeVT%#T4Gia_*QdM8Sy7wjxP@1(o?_zwN;CZ817tDNg|Cyv zseQWI%U<*6h94s&?c)2H^Q2Cl8HA8jBf2pFoDP4xI>f6WRK(x;^>hChu|uX|DDSLA zp&{hbT8oPLoy>C*#sYg|`}Q5;2BfU8l=q!xZx zysQE*gZ>-ae+px~f5|!%tvNJAI7q?q<#R}z>Yn?T0e`uQ1<97wwub}EFTK@rL&=S! z0eu`9)Eb(G_g6VerhWLnbu4K$oGPr-D&bPW;NTK7Ih1+(UvS`tzrBf&I47ITj$JMj zeFDM))#j-6A9qx{UGIyAku{|HdLxL|ZN~u5d>sB$LS7KN5URdT0eEfmr3!UZYKYq$ zQ%JO=h^$Etxc{pS{z^5_)f>#NYUUK)d_OA9IE=Hl=xZCA$S*gW--R7ed**+#WH}WC zh^)&R;i2+BshtW0_0NX%jD6W1Zq1NriRAz*t$ETtFXguSyVRnMCi;~}dnu_$@U^v! z>OkGz5C-|9g(LGw_)1CRSZeXA=A1ghcKo>pD(`gqGZ>%L&V+eaqrGL1eQvGjSL8)? z#3@)mv(bZro2uDB<_nK*0^9H2cU?NsByqq1hfqOwxG$ z&yoov&Z8N9K}GmPu;)uEFGDiK(!ob^_xRD7iwy5wn?x}JxYZ7#%f*DynDvU9?#u7{ zc8?8_ZJH?$(2R5=LOqI+EKcB>%S`@Gqm$8k$D$yWd&2Sokfl2`OXWPvbQW%*NhZJQ z*+R?qy#YNrED)*sS#}N!OmFN6)$PL_Q%g7Dr^Xf{nGsTB2D`k~i(;s?r71ovt?0aO{ z>nS}m-V|{wsJs|6N@2wlFS@d*SvuDDs+C-tqP^Uxjab5shrO?s$qsotjk(`D%KtmSoLo~`}3*R?XOT76<)%-`}ie=a+W zv9*VrwS;K}^6~!_Ehw%rIp*phA3o1U=sfY|U-CXQ)dTDGBRBO^kIDpUMUjx>Ce?Ls zbH+}EG6zkbCZzAhh;xV3LJ9sl$~Dqv&QAp9bJ<9J_Q+4UTNB_+`TzR6c7wWANCq|Fvx&1QHny`+_J zs}qQjkhPGm9A$@60Hs-bYBzt7Jg?~R>$|dX(z9OM)-_6AX!&~;xzp-B-_qgSHrO!`V%{c6`{k?mu#%dA&%vsb$$|dqnwo%cB z4tbPj77g<349L1#=mZk-KzQN830{kf!b16SkQWy4X^pR`UKf}1|BeE&$3(=v`{C}t zTW-h8-JcMLYI5Qzpa}Br7){me#c7Y`AafUl-keVy%A-FCD5W_l!OLo?e$F~f;&3!y z?-~xDb18Z4<<_L>zL#Hq_j#Iw*(mG%LHCu#hDcidQHsT-Dlad%o=uvi{J0-oQmHN! zyd)s1HM;qf_1eN(<(7DMUoGP6tbW%1t}#845wfmLd5-ge5dZJ+dVG9DE5 zN^uiN>a#I9+$`LBbE4|-4YO8~10@W8m^`Oa9;J)gbsccr2(o&*!w|hoi3{ssex~24 zh7N%7{ESSTB4@rL@?y>02i<6qgat-PHkNZvumJj)$_)$DV_IQ0uZ*rf0(^N(dW&az zhMzpU^N{}A{GFuR?|08PH)LLCQ`Q^&q;+?KkhOk-UW^-K)~?<%*;w+KvVRA%wX zBfL?{n0qOvsHZRUe%B4_mQ~ZtH!B-9iL2JU10wJX^y+@#Jnk{CejIRl&HdRB##3|H zSYk4~^~fYh+kRWFvbH%xQFtmErwifxbLbo`F)%-fABn5ue?@mAkU=7f<$T*U{nj;Y zZvOVg6S_(pR<{|;78hqT#VCDO417`C>=QXG>8|}^(2hV!nlIyP3{91R^xNyx>3bZ< z?g@$lY|fb6CPZz%iKqA7o2Wtqs8Z!Hm)R@h{j@}r@-iWe{LzH$&52$rlG0(dE}{gG z0LYoUyGwVcV0V|C`cOaEI zW<%YSzpbL|U0LyaWkW`ByB*6Ki=p$DXS znvj-XtO?=yOij`bee27)bEButhVi4)|+B)Zb?Qz zUvle$BBs{^4?X1SmiM(h+@<35jq)-uS$5{Hy8I79LU&f`FB5VhG3nP}%B5+|-Ay)5LLut#ca_O*1f~LchBP zvRw1oMgY4Uy*n#3G3C&_zEI}V=jHgvfpQ6)51ESL=Zx}^V#sU)sZo6m6Bu<;vIfNc z=|d~d80nfQ#paBtMT4M2$nj=s>Uuyx^gd%zjm6mc-)RN+1*ES@vCwS4F#4c>-l7xJ z+J8jeY!%mEQB=eQK%xEUlPxR&u3!@tIMhC0yCmy;*J`toqDs5>5K(4+Jz7AE^NH34 zoWB)38z<4!Rii+bP2^09n9E!C8Q3!r~mmnQsOm6 zMt}hk-1(OWpi2Uhk~(?BKMufq^X0Y_ MZJmAoqry)A2b~mAJOBUy literal 0 HcmV?d00001 diff --git a/soh/include/functions.h b/soh/include/functions.h index 72fd6e98c..b185519f4 100644 --- a/soh/include/functions.h +++ b/soh/include/functions.h @@ -60,7 +60,7 @@ void Locale_ResetRegion(void); u32 func_80001F48(void); u32 func_80001F8C(void); u32 Locale_IsRegionNative(void); -#ifndef __APPLE__ +#if !defined(__APPLE__) && !defined(__SWITCH__) void __assert(const char* exp, const char* file, s32 line); #endif void isPrintfInit(void); @@ -1872,7 +1872,7 @@ void FaultDrawer_SetCharPad(s8, s8); void FaultDrawer_SetCursor(s32, s32); void FaultDrawer_FillScreen(); void* FaultDrawer_FormatStringFunc(void*, const char*, u32); -void FaultDrawer_VPrintf(const char*, char*); +void FaultDrawer_VPrintf(const char*, va_list); void FaultDrawer_Printf(const char*, ...); void FaultDrawer_DrawText(s32, s32, const char*, ...); void FaultDrawer_SetDrawerFB(void*, u16, u16); diff --git a/soh/include/z64audio.h b/soh/include/z64audio.h index 3911bb6c4..c765aa4ed 100644 --- a/soh/include/z64audio.h +++ b/soh/include/z64audio.h @@ -783,6 +783,8 @@ typedef struct { /* 0x0E */ u8 ttl; // duration after which the DMA can be discarded } SampleDma; // size = 0x10 +#include + typedef struct { /* 0x0000 */ char unk_0000; /* 0x0001 */ s8 numSynthesisReverbs; diff --git a/soh/soh/Enhancements/bootcommands.c b/soh/soh/Enhancements/bootcommands.c index 6dc6b18b4..c766049ae 100644 --- a/soh/soh/Enhancements/bootcommands.c +++ b/soh/soh/Enhancements/bootcommands.c @@ -44,11 +44,6 @@ void BootCommands_ParseBootArgs(s32 argc, char** argv) } } } - - for (i = 0; i < argc; i++) - DebugArena_Free(argv[i]); - - //DebugArena_Free(argv); } /* diff --git a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp index 64281ddd5..66b9b8939 100644 --- a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp +++ b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp @@ -8,6 +8,7 @@ #include #include #include +#include /** * Colors variables @@ -93,10 +94,10 @@ const char* RainbowColorCvarList[] = { "gCCRupeePrim", "gCCKeysPrim", "gDog1Col", "gDog2Col", "gCCVSOAPrim", "gKeese1_Ef_Prim","gKeese2_Ef_Prim","gKeese1_Ef_Env","gKeese2_Ef_Env", "gDF_Col", "gDF_Env", - "gNL_Diamond_Col", "gNL_Diamond_Env", "gNL_Orb_Col", "gNL_Orb_Env", + "gNL_Diamond_Col", "gNL_Diamond_Env", "gNL_Orb_Col", "gNL_Orb_Env", "gTrailCol", "gCharged1Col", "gCharged1ColEnv", "gCharged2Col", "gCharged2ColEnv", "gCCFileChoosePrim", "gCCFileChooseTextPrim", "gCCEquipmentsPrim", "gCCItemsPrim", - "gCCMapsPrim", "gCCQuestsPrim", "gCCSavePrim", "gCCGameoverPrim", + "gCCMapsPrim", "gCCQuestsPrim", "gCCSavePrim", "gCCGameoverPrim", }; const char* MarginCvarList[] { "gHearts", "gMagicBar", "gVSOA", "gBBtn", "gABtn", "gStartBtn", diff --git a/soh/soh/Enhancements/randomizer/3drando/rando_main.cpp b/soh/soh/Enhancements/randomizer/3drando/rando_main.cpp index e14cf502d..8f46310cf 100644 --- a/soh/soh/Enhancements/randomizer/3drando/rando_main.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/rando_main.cpp @@ -10,6 +10,7 @@ #define NOGDI #define WIN32_LEAN_AND_MEAN #include +#include #define TICKS_PER_SEC 268123480.0 diff --git a/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp b/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp index c64134fbc..142d2576f 100644 --- a/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp @@ -300,7 +300,7 @@ static void WriteLocation( // node->SetAttribute("price", price); // } // if (!location->IsAddedToPool()) { - // #ifdef ENABLE_DEBUG + // #ifdef ENABLE_DEBUG // node->SetAttribute("not-added", true); // #endif // } @@ -673,7 +673,7 @@ static void WriteHints(int language) { static void WriteAllLocations(int language) { for (const uint32_t key : allLocations) { ItemLocation* location = Location(key); - + switch (language) { case 0: default: @@ -725,7 +725,7 @@ const char* SpoilerLog_Write(int language) { WriteHints(language); //WriteShuffledEntrances(spoilerLog); WriteAllLocations(language); - + if (!std::filesystem::exists(Ship::GlobalCtx2::GetPathRelativeToAppDirectory("Randomizer"))) { std::filesystem::create_directory(Ship::GlobalCtx2::GetPathRelativeToAppDirectory("Randomizer")); } diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 6a1ecc198..393619cce 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -51,6 +51,10 @@ #include #endif +#ifdef __SWITCH__ +#include "SwitchImpl.h" +#endif + #include OTRGlobals* OTRGlobals::Instance; @@ -104,6 +108,9 @@ extern "C" void OTRExtScanner() { } extern "C" void InitOTR() { +#ifdef __SWITCH__ + Ship::Switch::Init(Ship::PreInitPhase); +#endif OTRGlobals::Instance = new OTRGlobals(); SaveManager::Instance = new SaveManager(); auto t = OTRGlobals::Instance->context->GetResourceManager()->LoadFile("version"); @@ -225,6 +232,7 @@ extern "C" void Graph_StartFrame() { // C->C++ Bridge extern "C" void Graph_ProcessGfxCommands(Gfx* commands) { +#ifndef __SWITCH__ if (!audio.initialized) { audio.initialized = true; std::thread([]() { @@ -251,19 +259,16 @@ extern "C" void Graph_ProcessGfxCommands(Gfx* commands) { #define AUDIO_FRAMES_PER_UPDATE (R_UPDATE_RATE > 0 ? R_UPDATE_RATE : 1 ) #define NUM_AUDIO_CHANNELS 2 + int samples_left = AudioPlayer_Buffered(); u32 num_audio_samples = samples_left < AudioPlayer_GetDesiredBuffered() ? SAMPLES_HIGH : SAMPLES_LOW; - // printf("Audio samples: %d %u\n", samples_left, num_audio_samples); // 3 is the maximum authentic frame divisor. s16 audio_buffer[SAMPLES_HIGH * NUM_AUDIO_CHANNELS * 3]; for (int i = 0; i < AUDIO_FRAMES_PER_UPDATE; i++) { AudioMgr_CreateNextAudioBuffer(audio_buffer + i * (num_audio_samples * NUM_AUDIO_CHANNELS), num_audio_samples); } - //for (uint32_t i = 0; i < 2 * num_audio_samples; i++) { - // audio_buffer[i] = Rand_Next() & 0xFF; - //} - // printf("Audio samples before submitting: %d\n", audio_api->buffered()); + AudioPlayer_Play((u8*)audio_buffer, num_audio_samples * (sizeof(int16_t) * NUM_AUDIO_CHANNELS * AUDIO_FRAMES_PER_UPDATE)); audio.processing = false; @@ -276,8 +281,9 @@ extern "C" void Graph_ProcessGfxCommands(Gfx* commands) { std::unique_lock Lock(audio.mutex); audio.processing = true; } - audio.cv_to_thread.notify_one(); +#endif + audio.cv_to_thread.notify_one(); std::vector> mtx_replacements; int target_fps = CVar_GetS32("gInterpolationFPS", 20); static int last_fps; @@ -318,12 +324,14 @@ extern "C" void Graph_ProcessGfxCommands(Gfx* commands) { last_fps = fps; last_update_rate = R_UPDATE_RATE; +#ifndef __SWITCH__ { std::unique_lock Lock(audio.mutex); while (audio.processing) { audio.cv_from_thread.wait(Lock); } } +#endif // OTRTODO: FIGURE OUT END FRAME POINT /* if (OTRGlobals::Instance->context->GetWindow()->lastScancode != -1) @@ -1412,7 +1420,7 @@ extern "C" int CopyScrubMessage(u16 scrubTextId, char* buffer, const int maxBuff price = 40; break; } - switch (language) { + switch (language) { case 0: default: scrubText += 0x12; // add the sound scrubText += 0x38; // sound id @@ -1467,7 +1475,7 @@ extern "C" int CopyScrubMessage(u16 scrubTextId, char* buffer, const int maxBuff scrubText += 0xA3; // message id break; } - + return CopyStringToCharBuffer(scrubText, buffer, maxBufferSize); } @@ -1488,7 +1496,7 @@ extern "C" int Randomizer_CopyGanonHintText(char* buffer, const int maxBufferSiz } extern "C" int Randomizer_CopyHintFromCheck(RandomizerCheck check, char* buffer, const int maxBufferSize) { - // we don't want to make a copy of the std::string returned from GetHintFromCheck + // we don't want to make a copy of the std::string returned from GetHintFromCheck // so we're just going to let RVO take care of it const std::string& hintText = OTRGlobals::Instance->gRandomizer->GetHintFromCheck(check); return CopyStringToCharBuffer(hintText, buffer, maxBufferSize); diff --git a/soh/soh/SaveManager.cpp b/soh/soh/SaveManager.cpp index f59cf0ecc..e0de89d09 100644 --- a/soh/soh/SaveManager.cpp +++ b/soh/soh/SaveManager.cpp @@ -49,6 +49,8 @@ SaveManager::SaveManager() { } void SaveManager::LoadRandomizerVersion1() { + if(!CVar_GetS32("gRandomizer", 0)) return; + for (int i = 0; i < ARRAY_COUNT(gSaveContext.itemLocations); i++) { SaveManager::Instance->LoadData("get" + std::to_string(i), gSaveContext.itemLocations[i].get); SaveManager::Instance->LoadData("check" + std::to_string(i), gSaveContext.itemLocations[i].check); @@ -88,6 +90,9 @@ void SaveManager::LoadRandomizerVersion1() { } void SaveManager::SaveRandomizer() { + + if(!gSaveContext.n64ddFlag) return; + for (int i = 0; i < ARRAY_COUNT(gSaveContext.itemLocations); i++) { SaveManager::Instance->SaveData("get" + std::to_string(i), gSaveContext.itemLocations[i].get); SaveManager::Instance->SaveData("check" + std::to_string(i), gSaveContext.itemLocations[i].check); @@ -170,7 +175,7 @@ void SaveManager::Init() { } else { CreateDefaultGlobal(); } - + // Load files to initialize metadata for (int fileNum = 0; fileNum < MaxFiles; fileNum++) { if (std::filesystem::exists(GetFileName(fileNum))) { @@ -906,7 +911,7 @@ void SaveManager::LoadArray(const std::string& name, const size_t size, LoadArra } currentJsonContext = saveJsonContext; } - + void SaveManager::LoadStruct(const std::string& name, LoadStructFunc func) { // Create an empty struct and set it as the current load context, then call the function that loads the struct. diff --git a/soh/src/boot/assert.c b/soh/src/boot/assert.c index b7895dddd..5a44a9308 100644 --- a/soh/src/boot/assert.c +++ b/soh/src/boot/assert.c @@ -1,5 +1,6 @@ #include "global.h" +#ifndef __SWITCH__ void __assert(const char* exp, const char* file, s32 line) { char msg[256]; @@ -7,3 +8,4 @@ void __assert(const char* exp, const char* file, s32 line) { sprintf(msg, "ASSERT: %s:%d(%d)", file, line, osGetThreadId(NULL)); Fault_AddHungupAndCrashImpl(msg, exp); } +#endif \ No newline at end of file diff --git a/soh/src/code/fault_drawer.c b/soh/src/code/fault_drawer.c index 9759bfe72..8cd08248f 100644 --- a/soh/src/code/fault_drawer.c +++ b/soh/src/code/fault_drawer.c @@ -265,16 +265,14 @@ void* FaultDrawer_FormatStringFunc(void* arg, const char* str, u32 count) { return arg; } -void FaultDrawer_VPrintf(const char* str, char* args) { // va_list +void FaultDrawer_VPrintf(const char* str, va_list args) { // va_list _Printf(FaultDrawer_FormatStringFunc, (char*)&sFaultDrawerStruct, str, args); } void FaultDrawer_Printf(const char* fmt, ...) { va_list args; va_start(args, fmt); - FaultDrawer_VPrintf(fmt, args); - va_end(args); } @@ -284,7 +282,6 @@ void FaultDrawer_DrawText(s32 x, s32 y, const char* fmt, ...) { FaultDrawer_SetCursor(x, y); FaultDrawer_VPrintf(fmt, args); - va_end(args); } diff --git a/soh/src/code/graph.c b/soh/src/code/graph.c index f4dcf56e8..cf0a53c76 100644 --- a/soh/src/code/graph.c +++ b/soh/src/code/graph.c @@ -481,6 +481,22 @@ static void RunFrame() uint64_t ticksA, ticksB; ticksA = GetPerfCounter(); +#ifdef __SWITCH__ + #define SAMPLES_HIGH 752 + #define SAMPLES_LOW 720 + + #define AUDIO_FRAMES_PER_UPDATE (R_UPDATE_RATE > 0 ? R_UPDATE_RATE : 1 ) + #define NUM_AUDIO_CHANNELS 2 + int samples_left = AudioPlayer_Buffered(); + u32 num_audio_samples = samples_left < AudioPlayer_GetDesiredBuffered() ? SAMPLES_HIGH : SAMPLES_LOW; + + s16 audio_buffer[SAMPLES_HIGH * NUM_AUDIO_CHANNELS * 3]; + for (int i = 0; i < AUDIO_FRAMES_PER_UPDATE; i++) { + AudioMgr_CreateNextAudioBuffer(audio_buffer + i * (num_audio_samples * NUM_AUDIO_CHANNELS), num_audio_samples); + } + + AudioPlayer_Play((u8*)audio_buffer, num_audio_samples * (sizeof(int16_t) * NUM_AUDIO_CHANNELS * AUDIO_FRAMES_PER_UPDATE)); +#endif Graph_StartFrame(); // TODO: Workaround for rumble being too long. Implement os thread functions. diff --git a/soh/src/code/main.c b/soh/src/code/main.c index 372e3947c..fd02b016a 100644 --- a/soh/src/code/main.c +++ b/soh/src/code/main.c @@ -41,8 +41,6 @@ void main(int argc, char** argv) GameConsole_Init(); InitOTR(); BootCommands_Init(); - - BootCommands_ParseBootArgs(argc - 1, (char**)&argv[1]); Main(0); } diff --git a/soh/src/code/z_message_PAL.c b/soh/src/code/z_message_PAL.c index e711e8abe..a91dd5e41 100644 --- a/soh/src/code/z_message_PAL.c +++ b/soh/src/code/z_message_PAL.c @@ -111,7 +111,7 @@ void Message_ResetOcarinaNoteState(void) { sOcarinaNoteCEnvR = 10; sOcarinaNoteCEnvG = 10; sOcarinaNoteCEnvB = 10; - if (CVar_GetS32("gHudColors", 1) == 0) { + if (CVar_GetS32("gHudColors", 1) == 0) { sOcarinaNoteAPrimR = 80; sOcarinaNoteAPrimG = 150; sOcarinaNoteAPrimB = 255; @@ -240,8 +240,6 @@ void Message_DrawTextChar(GlobalContext* globalCtx, void* textureImage, Gfx** p) s16 x = msgCtx->textPosX; s16 y = msgCtx->textPosY; - gSPInvalidateTexCache(gfx++, textureImage); - gDPPipeSync(gfx++); sCharTexSize = (R_TEXT_CHAR_SCALE / 100.0f) * 16.0f; @@ -1229,6 +1227,8 @@ void Message_Decode(GlobalContext* globalCtx) { MessageContext* msgCtx = &globalCtx->msgCtx; Font* font = &globalCtx->msgCtx.font; + gSPInvalidateTexCache(globalCtx->state.gfxCtx->polyOpa.p++, NULL); + globalCtx->msgCtx.textDelayTimer = 0; globalCtx->msgCtx.textUnskippable = globalCtx->msgCtx.textDelay = globalCtx->msgCtx.textDelayTimer = 0; sTextFade = false; @@ -1624,6 +1624,7 @@ void Message_OpenText(GlobalContext* globalCtx, u16 textId) { } sMessageHasSetSfx = D_8014B2F4 = sTextboxSkipped = sTextIsCredits = 0; + gSPInvalidateTexCache(globalCtx->state.gfxCtx->polyOpa.p++, NULL); if (textId >= 0x0500 && textId < 0x0600) { // text ids 0500 to 0600 are reserved for credits sTextIsCredits = true; @@ -1793,7 +1794,7 @@ void Message_StartTextbox(GlobalContext* globalCtx, u16 textId, Actor* actor) { // so we need to switch the order of these lines if (gSaveContext.n64ddFlag && textId == 0x2053) { msgCtx->talkActor = actor; - Message_OpenText(globalCtx, textId); + Message_OpenText(globalCtx, textId); } else { Message_OpenText(globalCtx, textId); msgCtx->talkActor = actor; @@ -2114,7 +2115,7 @@ void Message_DrawMain(GlobalContext* globalCtx, Gfx** p) { if(CBtnB_2 > 255){CBtnB_2=255;}; s16 sOcarinaNoteCPrimColors_CUSTOM[][3] = { { CBtnR, CBtnG, CBtnB }, //Unified - { CBtnR_2, CBtnG_2, CBtnB_2 }, + { CBtnR_2, CBtnG_2, CBtnB_2 }, { CBtnRL, CBtnGL, CBtnBL }, //Left { CBtnRD, CBtnGD, CBtnBD }, //Down { CBtnRR, CBtnGR, CBtnBR }, //Right @@ -2704,15 +2705,15 @@ void Message_DrawMain(GlobalContext* globalCtx, Gfx** p) { Message_ContinueTextbox(globalCtx, msgCtx->lastPlayedSong + 0x893); // You played [song name] Message_Decode(globalCtx); msgCtx->msgMode = MSGMODE_DISPLAY_SONG_PLAYED_TEXT; - - if (CVar_GetS32("gFastOcarinaPlayback", 0) == 0 || globalCtx->msgCtx.lastPlayedSong == OCARINA_SONG_TIME + + if (CVar_GetS32("gFastOcarinaPlayback", 0) == 0 || globalCtx->msgCtx.lastPlayedSong == OCARINA_SONG_TIME || globalCtx->msgCtx.lastPlayedSong == OCARINA_SONG_STORMS || globalCtx->msgCtx.lastPlayedSong == OCARINA_SONG_SUNS) { msgCtx->stateTimer = 20; } else { msgCtx->stateTimer = 1; } - + Message_DrawText(globalCtx, &gfx); break; case MSGMODE_DISPLAY_SONG_PLAYED_TEXT: diff --git a/soh/switch/pathconf.c b/soh/switch/pathconf.c new file mode 100644 index 000000000..9e4111db3 --- /dev/null +++ b/soh/switch/pathconf.c @@ -0,0 +1,5 @@ +#include + +long pathconf(const char *path, int name) { + return -1; +} \ No newline at end of file From 8bdc4458c73898e17c738c82eb83402b26968ef0 Mon Sep 17 00:00:00 2001 From: David Chavez Date: Tue, 26 Jul 2022 03:12:25 +0200 Subject: [PATCH 02/25] Improve string split performance (#933) --- ZAPDTR/ZAPDUtils/Utils/StringHelper.cpp | 26 +++++++++++-------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/ZAPDTR/ZAPDUtils/Utils/StringHelper.cpp b/ZAPDTR/ZAPDUtils/Utils/StringHelper.cpp index 070fffa63..051e9a87d 100644 --- a/ZAPDTR/ZAPDUtils/Utils/StringHelper.cpp +++ b/ZAPDTR/ZAPDUtils/Utils/StringHelper.cpp @@ -9,22 +9,18 @@ std::vector StringHelper::Split(std::string s, const std::string& delimiter) { - std::vector result; + size_t pos_start = 0, pos_end, delim_len = delimiter.length(); + std::string token; + std::vector res; - size_t pos = 0; - std::string token; + while ((pos_end = s.find(delimiter, pos_start)) != std::string::npos) { + token = s.substr(pos_start, pos_end - pos_start); + pos_start = pos_end + delim_len; + res.push_back(token); + } - while ((pos = s.find(delimiter)) != std::string::npos) - { - token = s.substr(0, pos); - result.push_back(token); - s.erase(0, pos + delimiter.length()); - } - - if (s.length() != 0) - result.push_back(s); - - return result; + res.push_back(s.substr(pos_start)); + return res; } std::string StringHelper::Strip(std::string s, const std::string& delimiter) @@ -127,4 +123,4 @@ bool StringHelper::IEquals(const std::string& a, const std::string& b) { return std::equal(a.begin(), a.end(), b.begin(), b.end(), [](char a, char b) { return tolower(a) == tolower(b); }); -} \ No newline at end of file +} From 477cf7f6ecac176982ac270e3bb987ddd5dcf2bf Mon Sep 17 00:00:00 2001 From: PurpleHato Date: Wed, 27 Jul 2022 00:46:02 +0200 Subject: [PATCH 03/25] ADD: Rando Spiritual Stones Power (#910) * ADD: Try to use Spiritual Stone alpha on altar Not super advanced but it kinda work, n eeds to figure out why the gSaveContext.inventory.questItems doesn't seems to care * TWEAK: Full working + added on child link side * TWEAK: added else with comment * frogot a } --- .../actors/ovl_Demo_Effect/z_demo_effect.c | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/soh/src/overlays/actors/ovl_Demo_Effect/z_demo_effect.c b/soh/src/overlays/actors/ovl_Demo_Effect/z_demo_effect.c index bbbcec63d..95bdf6e50 100644 --- a/soh/src/overlays/actors/ovl_Demo_Effect/z_demo_effect.c +++ b/soh/src/overlays/actors/ovl_Demo_Effect/z_demo_effect.c @@ -1540,7 +1540,34 @@ void DemoEffect_UpdateJewelAdult(DemoEffect* this, GlobalContext* globalCtx) { this->jewel.timer++; this->actor.shape.rot.y += 0x0400; DemoEffect_PlayJewelSfx(this, globalCtx); + + if (gSaveContext.n64ddFlag) { + switch (this->jewel.type) { + case DEMO_EFFECT_JEWEL_KOKIRI: + if (CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD)) { + DemoEffect_SetJewelColor(this, 1.0f); + } else { + DemoEffect_SetJewelColor(this, 0.0f); + } + break; + case DEMO_EFFECT_JEWEL_GORON: + if (CHECK_QUEST_ITEM(QUEST_GORON_RUBY)) { + DemoEffect_SetJewelColor(this, 1.0f); + } else { + DemoEffect_SetJewelColor(this, 0.0f); + } + break; + case DEMO_EFFECT_JEWEL_ZORA: + if (CHECK_QUEST_ITEM(QUEST_ZORA_SAPPHIRE)) { + DemoEffect_SetJewelColor(this, 1.0f); + } else { + DemoEffect_SetJewelColor(this, 0.0f); + } + break; + } + } else { DemoEffect_SetJewelColor(this, 1.0f); + } } /** @@ -1604,6 +1631,34 @@ void DemoEffect_UpdateJewelChild(DemoEffect* this, GlobalContext* globalCtx) { thisx->shape.rot.y += 0x0400; DemoEffect_PlayJewelSfx(this, globalCtx); this->effectFlags &= ~1; + + if (gSaveContext.n64ddFlag) { + switch (this->jewel.type) { + case DEMO_EFFECT_JEWEL_KOKIRI: + if (CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD)) { + DemoEffect_SetJewelColor(this, 1.0f); + } else { + DemoEffect_SetJewelColor(this, 0.0f); + } + break; + case DEMO_EFFECT_JEWEL_GORON: + if (CHECK_QUEST_ITEM(QUEST_GORON_RUBY)) { + DemoEffect_SetJewelColor(this, 1.0f); + } else { + DemoEffect_SetJewelColor(this, 0.0f); + } + break; + case DEMO_EFFECT_JEWEL_ZORA: + if (CHECK_QUEST_ITEM(QUEST_ZORA_SAPPHIRE)) { + DemoEffect_SetJewelColor(this, 1.0f); + } else { + DemoEffect_SetJewelColor(this, 0.0f); + } + break; + } + } else { + // Contrary to it's adult conterpart Authenthic doesn't use DemoEffect_SetJewelColor(this, 1.0f); here + } } /** From 68182473176510de5b2d28b6bc3a4a4fc9e0b022 Mon Sep 17 00:00:00 2001 From: GaryOderNichts <12049776+GaryOderNichts@users.noreply.github.com> Date: Wed, 27 Jul 2022 23:50:56 +0200 Subject: [PATCH 04/25] Big-endian support (#909) --- OTRExporter/OTRExporter/Exporter.cpp | 2 +- ZAPDTR/ZAPDUtils/Utils/BinaryReader.cpp | 44 +- ZAPDTR/ZAPDUtils/Utils/BinaryReader.h | 6 + ZAPDTR/ZAPDUtils/Utils/BinaryWriter.cpp | 31 +- ZAPDTR/ZAPDUtils/Utils/BinaryWriter.h | 4 + ZAPDTR/ZAPDUtils/Utils/BitConverter.h | 22 + ZAPDTR/ZAPDUtils/Utils/Stream.h | 7 - libultraship/libultraship/Cutscene.cpp | 512 +++++++++++++++++- libultraship/libultraship/DisplayList.cpp | 24 +- .../libultraship/Factories/ResourceLoader.cpp | 4 +- libultraship/libultraship/Resource.h | 8 +- libultraship/libultraship/SDLAudioPlayer.cpp | 2 +- libultraship/libultraship/endianness.h | 67 +++ soh/include/color.h | 6 + soh/include/command_macros_base.h | 10 + soh/include/macros.h | 9 +- soh/include/z64audio.h | 32 ++ soh/soh/OTRGlobals.cpp | 11 +- soh/src/code/audio_data.c | 8 +- soh/src/code/audio_effects.c | 6 +- soh/src/code/audio_seqplayer.c | 4 +- soh/src/code/z_room.c | 5 +- 22 files changed, 762 insertions(+), 62 deletions(-) create mode 100644 libultraship/libultraship/endianness.h diff --git a/OTRExporter/OTRExporter/Exporter.cpp b/OTRExporter/OTRExporter/Exporter.cpp index b8b0612f5..f2daa4279 100644 --- a/OTRExporter/OTRExporter/Exporter.cpp +++ b/OTRExporter/OTRExporter/Exporter.cpp @@ -3,7 +3,7 @@ void OTRExporter::WriteHeader(ZResource* res, const fs::path& outPath, BinaryWriter* writer, Ship::ResourceType resType, Ship::Version resVersion) { - writer->Write((uint8_t)Endianess::Little); // 0x00 + writer->Write((uint8_t)Endianness::Little); // 0x00 writer->Write((uint8_t)0); // 0x01 writer->Write((uint8_t)0); // 0x02 writer->Write((uint8_t)0); // 0x03 diff --git a/ZAPDTR/ZAPDUtils/Utils/BinaryReader.cpp b/ZAPDTR/ZAPDUtils/Utils/BinaryReader.cpp index 94ca98a01..5916ce982 100644 --- a/ZAPDTR/ZAPDUtils/Utils/BinaryReader.cpp +++ b/ZAPDTR/ZAPDUtils/Utils/BinaryReader.cpp @@ -18,6 +18,16 @@ void BinaryReader::Close() stream->Close(); } +void BinaryReader::SetEndianness(Endianness endianness) +{ + this->endianness = endianness; +} + +Endianness BinaryReader::GetEndianness() const +{ + return endianness; +} + void BinaryReader::Seek(uint32_t offset, SeekOffsetType seekType) { stream->Seek(offset, seekType); @@ -28,11 +38,16 @@ uint32_t BinaryReader::GetBaseAddress() return stream->GetBaseAddress(); } -void BinaryReader::Read([[maybe_unused]] char* buffer, int32_t length) +void BinaryReader::Read(int32_t length) { stream->Read(length); } +void BinaryReader::Read(char* buffer, int32_t length) +{ + stream->Read(buffer, length); +} + char BinaryReader::ReadChar() { return (char)stream->ReadByte(); @@ -53,6 +68,10 @@ int16_t BinaryReader::ReadInt16() int16_t result = 0; stream->Read((char*)&result, sizeof(int16_t)); + + if (endianness != Endianness::Native) + result = BSWAP16(result); + return result; } @@ -61,6 +80,10 @@ int32_t BinaryReader::ReadInt32() int32_t result = 0; stream->Read((char*)&result, sizeof(int32_t)); + + if (endianness != Endianness::Native) + result = BSWAP32(result); + return result; } @@ -69,6 +92,10 @@ uint16_t BinaryReader::ReadUInt16() uint16_t result = 0; stream->Read((char*)&result, sizeof(uint16_t)); + + if (endianness != Endianness::Native) + result = BSWAP16(result); + return result; } @@ -77,6 +104,10 @@ uint32_t BinaryReader::ReadUInt32() uint32_t result = 0; stream->Read((char*)&result, sizeof(uint32_t)); + + if (endianness != Endianness::Native) + result = BSWAP32(result); + return result; } @@ -85,6 +116,10 @@ uint64_t BinaryReader::ReadUInt64() uint64_t result = 0; stream->Read((char*)&result, sizeof(uint64_t)); + + if (endianness != Endianness::Native) + result = BSWAP64(result); + return result; } @@ -94,6 +129,9 @@ float BinaryReader::ReadSingle() stream->Read((char*)&result, sizeof(float)); + if (endianness != Endianness::Native) + result = BitConverter::ToFloatBE((uint8_t*)&result, 0); + if (std::isnan(result)) throw std::runtime_error("BinaryReader::ReadSingle(): Error reading stream"); @@ -105,6 +143,10 @@ double BinaryReader::ReadDouble() double result = NAN; stream->Read((char*)&result, sizeof(double)); + + if (endianness != Endianness::Native) + result = BitConverter::ToDoubleBE((uint8_t*)&result, 0); + if (std::isnan(result)) throw std::runtime_error("BinaryReader::ReadDouble(): Error reading stream"); diff --git a/ZAPDTR/ZAPDUtils/Utils/BinaryReader.h b/ZAPDTR/ZAPDUtils/Utils/BinaryReader.h index a1994aa4a..0b18351c8 100644 --- a/ZAPDTR/ZAPDUtils/Utils/BinaryReader.h +++ b/ZAPDTR/ZAPDUtils/Utils/BinaryReader.h @@ -8,6 +8,7 @@ #include "../Vec2f.h" #include "../Vec3f.h" #include "../Vec3s.h" +#include "BitConverter.h" #include "Stream.h" class BinaryReader @@ -18,9 +19,13 @@ public: void Close(); + void SetEndianness(Endianness endianness); + Endianness GetEndianness() const; + void Seek(uint32_t offset, SeekOffsetType seekType); uint32_t GetBaseAddress(); + void Read(int32_t length); void Read(char* buffer, int32_t length); char ReadChar(); int8_t ReadByte(); @@ -41,4 +46,5 @@ public: protected: std::shared_ptr stream; + Endianness endianness = Endianness::Native; }; \ No newline at end of file diff --git a/ZAPDTR/ZAPDUtils/Utils/BinaryWriter.cpp b/ZAPDTR/ZAPDUtils/Utils/BinaryWriter.cpp index c456bdeb3..aa7840f01 100644 --- a/ZAPDTR/ZAPDUtils/Utils/BinaryWriter.cpp +++ b/ZAPDTR/ZAPDUtils/Utils/BinaryWriter.cpp @@ -10,6 +10,11 @@ BinaryWriter::BinaryWriter(std::shared_ptr nStream) stream = nStream; } +void BinaryWriter::SetEndianness(Endianness endianness) +{ + this->endianness = endianness; +} + void BinaryWriter::Close() { stream->Close(); @@ -47,16 +52,25 @@ void BinaryWriter::Write(uint8_t value) void BinaryWriter::Write(int16_t value) { + if (endianness != Endianness::Native) + value = BSWAP16(value); + stream->Write((char*)&value, sizeof(int16_t)); } void BinaryWriter::Write(uint16_t value) { + if (endianness != Endianness::Native) + value = BSWAP16(value); + stream->Write((char*)&value, sizeof(uint16_t)); } void BinaryWriter::Write(int32_t value) { + if (endianness != Endianness::Native) + value = BSWAP32(value); + stream->Write((char*)&value, sizeof(int32_t)); } @@ -68,33 +82,48 @@ void BinaryWriter::Write(int32_t valueA, int32_t valueB) void BinaryWriter::Write(uint32_t value) { + if (endianness != Endianness::Native) + value = BSWAP32(value); + stream->Write((char*)&value, sizeof(uint32_t)); } void BinaryWriter::Write(int64_t value) { + if (endianness != Endianness::Native) + value = BSWAP64(value); + stream->Write((char*)&value, sizeof(int64_t)); } void BinaryWriter::Write(uint64_t value) { + if (endianness != Endianness::Native) + value = BSWAP64(value); + stream->Write((char*)&value, sizeof(uint64_t)); } void BinaryWriter::Write(float value) { + if (endianness != Endianness::Native) + value = BitConverter::ToFloatBE((uint8_t*)&value, 0); + stream->Write((char*)&value, sizeof(float)); } void BinaryWriter::Write(double value) { + if (endianness != Endianness::Native) + value = BitConverter::ToDoubleBE((uint8_t*)&value, 0); + stream->Write((char*)&value, sizeof(double)); } void BinaryWriter::Write(const std::string& str) { int strLen = str.size(); - stream->Write((char*)&strLen, sizeof(int)); + Write(strLen); for (char c : str) stream->WriteByte(c); diff --git a/ZAPDTR/ZAPDUtils/Utils/BinaryWriter.h b/ZAPDTR/ZAPDUtils/Utils/BinaryWriter.h index e6dd84105..67c8fcd1e 100644 --- a/ZAPDTR/ZAPDUtils/Utils/BinaryWriter.h +++ b/ZAPDTR/ZAPDUtils/Utils/BinaryWriter.h @@ -4,6 +4,7 @@ #include #include #include +#include "BitConverter.h" #include "Stream.h" class BinaryWriter @@ -12,6 +13,8 @@ public: BinaryWriter(Stream* nStream); BinaryWriter(std::shared_ptr nStream); + void SetEndianness(Endianness endianness); + std::shared_ptr GetStream(); uint64_t GetBaseAddress(); uint64_t GetLength(); @@ -34,4 +37,5 @@ public: protected: std::shared_ptr stream; + Endianness endianness = Endianness::Native; }; \ No newline at end of file diff --git a/ZAPDTR/ZAPDUtils/Utils/BitConverter.h b/ZAPDTR/ZAPDUtils/Utils/BitConverter.h index 708d4b537..b62891d3d 100644 --- a/ZAPDTR/ZAPDUtils/Utils/BitConverter.h +++ b/ZAPDTR/ZAPDUtils/Utils/BitConverter.h @@ -5,6 +5,28 @@ #include #include +#ifdef _MSC_VER +#define BSWAP16 _byteswap_ushort +#define BSWAP32 _byteswap_ulong +#define BSWAP64 _byteswap_uint64 +#else +#define BSWAP16 __builtin_bswap16 +#define BSWAP32 __builtin_bswap32 +#define BSWAP64 __builtin_bswap64 +#endif + +enum class Endianness +{ + Little = 0, + Big = 1, + +#if (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) || defined(__BIG_ENDIAN__) + Native = Big, +#else + Native = Little, +#endif +}; + class BitConverter { public: diff --git a/ZAPDTR/ZAPDUtils/Utils/Stream.h b/ZAPDTR/ZAPDUtils/Utils/Stream.h index e73a9a70d..e72d794b6 100644 --- a/ZAPDTR/ZAPDUtils/Utils/Stream.h +++ b/ZAPDTR/ZAPDUtils/Utils/Stream.h @@ -10,13 +10,6 @@ enum class SeekOffsetType End }; -// TODO: Eventually account for endianess in binaryreader and binarywriter -enum class Endianess -{ - Little = 0, - Big = 1, -}; - class Stream { public: diff --git a/libultraship/libultraship/Cutscene.cpp b/libultraship/libultraship/Cutscene.cpp index 420d491f1..a1e2421eb 100644 --- a/libultraship/libultraship/Cutscene.cpp +++ b/libultraship/libultraship/Cutscene.cpp @@ -1,5 +1,103 @@ #include "Cutscene.h" +enum class CutsceneCommands +{ + Cmd00 = 0x0000, + SetCameraPos = 0x0001, + SetCameraFocus = 0x0002, + SpecialAction = 0x0003, + SetLighting = 0x0004, + SetCameraPosLink = 0x0005, + SetCameraFocusLink = 0x0006, + Cmd07 = 0x0007, + Cmd08 = 0x0008, + Cmd09 = 0x0009, + Unknown = 0x001A, + Textbox = 0x0013, + SetActorAction0 = 0x000A, + SetActorAction1 = 0x000F, + SetActorAction2 = 0x000E, + SetActorAction3 = 0x0019, + SetActorAction4 = 0x001D, + SetActorAction5 = 0x001E, + SetActorAction6 = 0x002C, + SetActorAction7 = 0x001F, + SetActorAction8 = 0x0031, + SetActorAction9 = 0x003E, + SetActorAction10 = 0x008F, + SetSceneTransFX = 0x002D, + Nop = 0x000B, + PlayBGM = 0x0056, + StopBGM = 0x0057, + FadeBGM = 0x007C, + SetTime = 0x008C, + Terminator = 0x03E8, + End = 0xFFFF, + Error = 0xFEAF, +}; + +static inline uint32_t read_CMD_BBBB(BinaryReader* reader) +{ + uint32_t v; + reader->Read((char*)&v, sizeof(uint32_t)); + + return v; +} + +static inline uint32_t read_CMD_BBH(BinaryReader* reader) +{ + uint32_t v; + reader->Read((char*)&v, sizeof(uint32_t)); + + // swap the half word to match endianness + if (reader->GetEndianness() != Endianness::Native) + { + uint8_t* b = (uint8_t*)&v; + uint8_t tmp = b[2]; + b[2] = b[3]; + b[3] = tmp; + } + + return v; +} + +static inline uint32_t read_CMD_HBB(BinaryReader* reader) +{ + uint32_t v; + reader->Read((char*)&v, sizeof(uint32_t)); + + // swap the half word to match endianness + if (reader->GetEndianness() != Endianness::Native) + { + uint8_t* b = (uint8_t*)&v; + uint8_t tmp = b[0]; + b[0] = b[1]; + b[1] = tmp; + } + + return v; +} + +static inline uint32_t read_CMD_HH(BinaryReader* reader) +{ + uint32_t v; + reader->Read((char*)&v, sizeof(uint32_t)); + + // swap the half words to match endianness + if (reader->GetEndianness() != Endianness::Native) + { + uint8_t* b = (uint8_t*)&v; + uint8_t tmp = b[0]; + b[0] = b[1]; + b[1] = tmp; + tmp = b[2]; + b[2] = b[3]; + b[3] = tmp; + } + + return v; +} + void Ship::CutsceneV0::ParseFileBinary(BinaryReader* reader, Resource* res) { Cutscene* cs = (Cutscene*)res; @@ -9,11 +107,415 @@ void Ship::CutsceneV0::ParseFileBinary(BinaryReader* reader, Resource* res) uint32_t numEntries = reader->ReadUInt32(); cs->commands.reserve(numEntries); - for (uint32_t i = 0; i < numEntries; i++) - { - uint32_t data = reader->ReadUInt32(); - uint16_t opcode = data >> 16; + uint32_t numCommands = reader->ReadUInt32(); + cs->commands.push_back(numCommands); - cs->commands.push_back(data); + // endFrame + cs->commands.push_back(reader->ReadUInt32()); + + while (true) + { + uint32_t commandId = reader->ReadUInt32(); + cs->commands.push_back(commandId); + + switch (commandId) + { + case (uint32_t)CutsceneCommands::SetCameraPos: + { + cs->commands.push_back(read_CMD_HH(reader)); + cs->commands.push_back(read_CMD_HH(reader)); + + while (true) + { + uint32_t val = read_CMD_BBH(reader); + int8_t continueFlag = ((int8_t*)&val)[0]; + + cs->commands.push_back(val); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(read_CMD_HH(reader)); + cs->commands.push_back(read_CMD_HH(reader)); + + if (continueFlag == -1) + break; + } + } + break; + case (uint32_t)CutsceneCommands::SetCameraFocus: + { + cs->commands.push_back(read_CMD_HH(reader)); + cs->commands.push_back(read_CMD_HH(reader)); + + while (true) + { + uint32_t val = read_CMD_BBH(reader); + int8_t continueFlag = ((int8_t*)&val)[0]; + + cs->commands.push_back(val); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(read_CMD_HH(reader)); + cs->commands.push_back(read_CMD_HH(reader)); + + if (continueFlag == -1) + break; + } + break; + } + case (uint32_t)CutsceneCommands::SpecialAction: + { + uint32_t size = reader->ReadUInt32(); + cs->commands.push_back(size); + + for (uint32_t i = 0; i < size; i++) + { + cs->commands.push_back(read_CMD_HH(reader)); + cs->commands.push_back(read_CMD_HH(reader)); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + } + break; + } + case (uint32_t)CutsceneCommands::SetLighting: + { + uint32_t size = reader->ReadUInt32(); + cs->commands.push_back(size); + + for (uint32_t i = 0; i < size; i++) + { + cs->commands.push_back(read_CMD_HH(reader)); + cs->commands.push_back(read_CMD_HH(reader)); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + } + break; + } + case (uint32_t)CutsceneCommands::SetCameraPosLink: + { + cs->commands.push_back(read_CMD_HH(reader)); + cs->commands.push_back(read_CMD_HH(reader)); + + while (true) + { + uint32_t val = read_CMD_BBH(reader); + int8_t continueFlag = ((int8_t*)&val)[0]; + + cs->commands.push_back(val); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(read_CMD_HH(reader)); + cs->commands.push_back(read_CMD_HH(reader)); + + if (continueFlag == -1) + break; + } + break; + } + case (uint32_t)CutsceneCommands::SetCameraFocusLink: + { + cs->commands.push_back(read_CMD_HH(reader)); + cs->commands.push_back(read_CMD_HH(reader)); + + while (true) + { + uint32_t val = read_CMD_BBH(reader); + int8_t continueFlag = ((int8_t*)&val)[0]; + + cs->commands.push_back(val); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(read_CMD_HH(reader)); + cs->commands.push_back(read_CMD_HH(reader)); + + if (continueFlag == -1) + break; + } + break; + } + case (uint32_t)CutsceneCommands::Cmd09: + { + uint32_t size = reader->ReadUInt32(); + cs->commands.push_back(size); + + for (uint32_t i = 0; i < size; i++) + { + cs->commands.push_back(read_CMD_HH(reader)); + cs->commands.push_back(read_CMD_HBB(reader)); + cs->commands.push_back(read_CMD_BBH(reader)); + } + break; + } + case 0x15: + case (uint32_t)CutsceneCommands::Unknown: + { + uint32_t size = reader->ReadUInt32(); + cs->commands.push_back(size); + + for (uint32_t i = 0; i < size; i++) + { + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + } + } + break; + case (uint32_t)CutsceneCommands::Textbox: + { + uint32_t size = reader->ReadUInt32(); + cs->commands.push_back(size); + + for (uint32_t i = 0; i < size; i++) + { + cs->commands.push_back(read_CMD_HH(reader)); + cs->commands.push_back(read_CMD_HH(reader)); + cs->commands.push_back(read_CMD_HH(reader)); + } + break; + } + case (uint32_t)CutsceneCommands::SetActorAction0: + case (uint32_t)CutsceneCommands::SetActorAction1: + case 17: + case 18: + case 23: + case 34: + case 39: + case 46: + case 76: + case 85: + case 93: + case 105: + case 107: + case 110: + case 119: + case 123: + case 138: + case 139: + case 144: + case (uint32_t)CutsceneCommands::SetActorAction2: + case 16: + case 24: + case 35: + case 40: + case 48: + case 64: + case 68: + case 70: + case 78: + case 80: + case 94: + case 116: + case 118: + case 120: + case 125: + case 131: + case 141: + case (uint32_t)CutsceneCommands::SetActorAction3: + case 36: + case 41: + case 50: + case 67: + case 69: + case 72: + case 74: + case 81: + case 106: + case 117: + case 121: + case 126: + case 132: + case (uint32_t)CutsceneCommands::SetActorAction4: + case 37: + case 42: + case 51: + case 53: + case 63: + case 65: + case 66: + case 75: + case 82: + case 108: + case 127: + case 133: + case (uint32_t)CutsceneCommands::SetActorAction5: + case 38: + case 43: + case 47: + case 54: + case 79: + case 83: + case 128: + case 135: + case (uint32_t)CutsceneCommands::SetActorAction6: + case 55: + case 77: + case 84: + case 90: + case 129: + case 136: + case (uint32_t)CutsceneCommands::SetActorAction7: + case 52: + case 57: + case 58: + case 88: + case 115: + case 130: + case 137: + case (uint32_t)CutsceneCommands::SetActorAction8: + case 60: + case 89: + case 111: + case 114: + case 134: + case 142: + case (uint32_t)CutsceneCommands::SetActorAction9: + case (uint32_t)CutsceneCommands::SetActorAction10: + { + uint32_t size = reader->ReadUInt32(); + cs->commands.push_back(size); + + for (uint32_t i = 0; i < size; i++) + { + cs->commands.push_back(read_CMD_HH(reader)); + cs->commands.push_back(read_CMD_HH(reader)); + cs->commands.push_back(read_CMD_HH(reader)); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + } + + break; + } + case (uint32_t)CutsceneCommands::SetSceneTransFX: + { + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(read_CMD_HH(reader)); + cs->commands.push_back(read_CMD_HH(reader)); + break; + } + case (uint32_t)CutsceneCommands::PlayBGM: + { + uint32_t size = reader->ReadUInt32(); + cs->commands.push_back(size); + + for (uint32_t i = 0; i < size; i++) + { + cs->commands.push_back(read_CMD_HH(reader)); + cs->commands.push_back(read_CMD_HH(reader)); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + } + break; + } + case (uint32_t)CutsceneCommands::StopBGM: + { + uint32_t size = reader->ReadUInt32(); + cs->commands.push_back(size); + + for (uint32_t i = 0; i < size; i++) + { + cs->commands.push_back(read_CMD_HH(reader)); + cs->commands.push_back(read_CMD_HH(reader)); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + } + break; + } + case (uint32_t)CutsceneCommands::FadeBGM: + { + uint32_t size = reader->ReadUInt32(); + cs->commands.push_back(size); + + for (uint32_t i = 0; i < size; i++) + { + cs->commands.push_back(read_CMD_HH(reader)); + cs->commands.push_back(read_CMD_HH(reader)); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(reader->ReadUInt32()); + } + break; + } + case (uint32_t)CutsceneCommands::SetTime: + { + uint32_t size = reader->ReadUInt32(); + cs->commands.push_back(size); + + for (uint32_t i = 0; i < size; i++) + { + cs->commands.push_back(read_CMD_HH(reader)); + cs->commands.push_back(read_CMD_HBB(reader)); + cs->commands.push_back(reader->ReadUInt32()); + } + break; + } + case (uint32_t)CutsceneCommands::Terminator: + { + cs->commands.push_back(reader->ReadUInt32()); + cs->commands.push_back(read_CMD_HH(reader)); + cs->commands.push_back(read_CMD_HH(reader)); + break; + } + case 0xFFFFFFFF: // CS_END + { + cs->commands.push_back(reader->ReadUInt32()); + return; + } + default: +#ifdef _DEBUG + printf("CutsceneV0: Unknown command %x\n", commandId); +#endif + // error? + break; + } } } diff --git a/libultraship/libultraship/DisplayList.cpp b/libultraship/libultraship/DisplayList.cpp index 14f9f8410..b2934ee68 100644 --- a/libultraship/libultraship/DisplayList.cpp +++ b/libultraship/libultraship/DisplayList.cpp @@ -14,23 +14,25 @@ namespace Ship while (true) { - uint64_t data = reader->ReadUInt64(); + uint32_t w0 = reader->ReadUInt32(); + uint32_t w1 = reader->ReadUInt32(); if (sizeof(uintptr_t) < 8){ - dl->instructions.push_back(data); + dl->instructions.push_back(((uint64_t) w0 << 32) | w1); - uint8_t opcode = data >> 24; + uint8_t opcode = w0 >> 24; // These are 128-bit commands, so read an extra 64 bits... - if (opcode == G_SETTIMG_OTR || opcode == G_DL_OTR || opcode == G_VTX_OTR || opcode == G_BRANCH_Z_OTR || opcode == G_MARKER || opcode == G_MTX_OTR) - dl->instructions.push_back(reader->ReadUInt64()); + if (opcode == G_SETTIMG_OTR || opcode == G_DL_OTR || opcode == G_VTX_OTR || opcode == G_BRANCH_Z_OTR || opcode == G_MARKER || opcode == G_MTX_OTR) { + w0 = reader->ReadUInt32(); + w1 = reader->ReadUInt32(); + + dl->instructions.push_back(((uint64_t) w0 << 32) | w1); + } if (opcode == G_ENDDL) break; } else { - uint32_t w0 = (uint32_t)data; - uint32_t w1 = (uint32_t)(data >> 32); - dl->instructions.push_back(w0); dl->instructions.push_back(w1); @@ -38,10 +40,8 @@ namespace Ship if (opcode == G_SETTIMG_OTR || opcode == G_DL_OTR || opcode == G_VTX_OTR || opcode == G_BRANCH_Z_OTR || opcode == G_MARKER || opcode == G_MTX_OTR) { - data = reader->ReadUInt64(); - - w0 = (uint32_t)data; - w1 = (uint32_t)(data >> 32); + w0 = reader->ReadUInt32(); + w1 = reader->ReadUInt32(); dl->instructions.push_back(w0); dl->instructions.push_back(w1); diff --git a/libultraship/libultraship/Factories/ResourceLoader.cpp b/libultraship/libultraship/Factories/ResourceLoader.cpp index 28a651b83..194fc74e8 100644 --- a/libultraship/libultraship/Factories/ResourceLoader.cpp +++ b/libultraship/libultraship/Factories/ResourceLoader.cpp @@ -25,12 +25,12 @@ namespace Ship auto memStream = std::make_shared(FileToLoad->buffer.get(), FileToLoad->dwBufferSize); auto reader = std::make_shared(memStream); - Endianess endianess = (Endianess)reader->ReadByte(); + Endianness endianness = (Endianness)reader->ReadByte(); for (int i = 0; i < 3; i++) reader->ReadByte(); - // OTRTODO: Setup the binaryreader to use the resource's endianess + reader->SetEndianness(endianness); ResourceType resourceType = (ResourceType)reader->ReadUInt32(); Resource* result = nullptr; diff --git a/libultraship/libultraship/Resource.h b/libultraship/libultraship/Resource.h index 6bdae983e..f7ea98e93 100644 --- a/libultraship/libultraship/Resource.h +++ b/libultraship/libultraship/Resource.h @@ -51,12 +51,6 @@ namespace Ship F64 = 10 }; - enum class Endianess - { - Little = 0, - Big = 1, - }; - enum class Version { // BR @@ -90,7 +84,7 @@ namespace Ship class ResourceFile { public: - Endianess endianess; // 0x00 - Endianess of the file + Endianness endianness; // 0x00 - Endianness of the file uint32_t resourceType; // 0x01 - 4 byte MAGIC Version version; // 0x05 - Based on Ship release numbers uint64_t id; // 0x09 - Unique Resource ID diff --git a/libultraship/libultraship/SDLAudioPlayer.cpp b/libultraship/libultraship/SDLAudioPlayer.cpp index 3c15f720e..6e14c4be0 100644 --- a/libultraship/libultraship/SDLAudioPlayer.cpp +++ b/libultraship/libultraship/SDLAudioPlayer.cpp @@ -10,7 +10,7 @@ namespace Ship { SDL_AudioSpec want, have; SDL_zero(want); want.freq = this->GetSampleRate(); - want.format = AUDIO_S16; + want.format = AUDIO_S16SYS; want.channels = 2; want.samples = 1024; want.callback = NULL; diff --git a/libultraship/libultraship/endianness.h b/libultraship/libultraship/endianness.h new file mode 100644 index 000000000..87bec316b --- /dev/null +++ b/libultraship/libultraship/endianness.h @@ -0,0 +1,67 @@ +#ifndef ENDIANESS_H +#define ENDIANESS_H + +#ifdef _MSC_VER +#include + +#define BOMSWAP16 _byteswap_ushort +#define BOMSWAP32 _byteswap_ulong +#define BOMSWAP64 _byteswap_uint64 + +#define BOMSWAP16_CONST(x) \ + ((((x) >> 8) & 0x00FF) | (((x) << 8) & 0xFF00)) +#define BOMSWAP32_CONST(x) \ + ((((x) >> 24) & 0x000000FF) | (((x) >> 8) & 0x0000FF00) | \ + (((x) << 8) & 0x00FF0000) | (((x) << 24) & 0xFF000000)) +#define BOMSWAP64_CONST(x) \ + ((((x) >> 56) & 0x00000000000000FF) | (((x) >> 40) & 0x000000000000FF00) | \ + (((x) >> 24) & 0x0000000000FF0000) | (((x) >> 8) & 0x00000000FF000000) | \ + (((x) << 8) & 0x000000FF00000000) | (((x) << 24) & 0x0000FF0000000000) | \ + (((x) << 40) & 0x00FF000000000000) | (((x) << 56) & 0xFF00000000000000)) +#else +#define BOMSWAP16 __builtin_bswap16 +#define BOMSWAP32 __builtin_bswap32 +#define BOMSWAP64 __builtin_bswap64 + +#define BOMSWAP16_CONST __builtin_bswap16 +#define BOMSWAP32_CONST __builtin_bswap32 +#define BOMSWAP64_CONST __builtin_bswap64 +#endif + +#if (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) || defined(__BIG_ENDIAN__) +#ifndef IS_BIGENDIAN +#define IS_BIGENDIAN +#endif +#endif + +#ifdef IS_BIGENDIAN +#define BE16SWAP(x) (x) +#define BE32SWAP(x) (x) +#define BE64SWAP(x) (x) +#define LE16SWAP(x) BOMSWAP16(x) +#define LE32SWAP(x) BOMSWAP32(x) +#define LE64SWAP(x) BOMSWAP64(x) + +#define BE16SWAP_CONST(x) (x) +#define BE32SWAP_CONST(x) (x) +#define BE64SWAP_CONST(x) (x) +#define LE16SWAP_CONST(x) BOMSWAP16_CONST(x) +#define LE32SWAP_CONST(x) BOMSWAP32_CONST(x) +#define LE64SWAP_CONST(x) BOMSWAP64_CONST(x) +#else +#define BE16SWAP(x) BOMSWAP16(x) +#define BE32SWAP(x) BOMSWAP32(x) +#define BE64SWAP(x) BOMSWAP64(x) +#define LE16SWAP(x) (x) +#define LE32SWAP(x) (x) +#define LE64SWAP(x) (x) + +#define BE16SWAP_CONST(x) BOMSWAP16_CONST(x) +#define BE32SWAP_CONST(x) BOMSWAP32_CONST(x) +#define BE64SWAP_CONST(x) BOMSWAP64_CONST(x) +#define LE16SWAP_CONST(x) (x) +#define LE32SWAP_CONST(x) (x) +#define LE64SWAP_CONST(x) (x) +#endif + +#endif diff --git a/soh/include/color.h b/soh/include/color.h index 1a833b0d4..6c8e4c1ce 100644 --- a/soh/include/color.h +++ b/soh/include/color.h @@ -1,6 +1,8 @@ #ifndef COLOR_H #define COLOR_H +#include "endianness.h" + typedef struct { u8 r, g, b; } Color_RGB8; @@ -12,7 +14,11 @@ typedef struct { // only use when necessary for alignment purposes typedef union { struct { +#ifdef IS_BIGENDIAN + u8 r, g, b, a; +#else u8 a, b, g, r; +#endif }; u32 rgba; } Color_RGBA8_u32; diff --git a/soh/include/command_macros_base.h b/soh/include/command_macros_base.h index bae557909..a0b31bb7f 100644 --- a/soh/include/command_macros_base.h +++ b/soh/include/command_macros_base.h @@ -6,6 +6,15 @@ * Each macro packs bytes (B), halfwords (H) and words (W, for consistency) into a single word */ +#ifdef IS_BIGENDIAN +#define CMD_BBBB(a, b, c, d) (_SHIFTL(a, 24, 8) | _SHIFTL(b, 16, 8) | _SHIFTL(c, 8, 8) | _SHIFTL(d, 0, 8)) + +#define CMD_BBH(a, b, c) (_SHIFTL(a, 24, 8) | _SHIFTL(b, 16, 8) | _SHIFTL(c, 0, 16)) + +#define CMD_HBB(a, b, c) (_SHIFTL(a, 16, 16) | _SHIFTL(b, 8, 8) | _SHIFTL(c, 0, 8)) + +#define CMD_HH(a, b) (_SHIFTL(a, 16, 16) | _SHIFTL(b, 0, 16)) +#else #define CMD_BBBB(a, b, c, d) (_SHIFTL(a, 0, 8) | _SHIFTL(b, 8, 8) | _SHIFTL(c, 16, 8) | _SHIFTL(d, 24, 8)) #define CMD_BBH(a, b, c) (_SHIFTL(a, 0, 8) | _SHIFTL(b, 8, 8) | _SHIFTL(c, 16, 16)) @@ -13,6 +22,7 @@ #define CMD_HBB(a, b, c) (_SHIFTL(a, 0, 16) | _SHIFTL(b, 16, 8) | _SHIFTL(c, 24, 8)) #define CMD_HH(a, b) (_SHIFTL(a, 0, 16) | _SHIFTL(b, 16, 16)) +#endif #define CMD_W(a) (a) diff --git a/soh/include/macros.h b/soh/include/macros.h index 2c84434fe..f2e339e34 100644 --- a/soh/include/macros.h +++ b/soh/include/macros.h @@ -1,6 +1,8 @@ #ifndef MACROS_H #define MACROS_H +#include "endianness.h" + #define ARRAY_COUNT(arr) (s32)(sizeof(arr) / sizeof(arr[0])) #define ARRAY_COUNTU(arr) (u32)(sizeof(arr) / sizeof(arr[0])) @@ -254,12 +256,5 @@ extern GraphicsContext* __gfxCtx; #define SEG_ADDR(seg, addr) (addr | (seg << 24) | 1) -#ifdef _MSC_VER -#define BOMSWAP16 _byteswap_ushort -#define BOMSWAP32 _byteswap_ulong -#else -#define BOMSWAP16 __builtin_bswap16 -#define BOMSWAP32 __builtin_bswap32 -#endif #endif diff --git a/soh/include/z64audio.h b/soh/include/z64audio.h index c765aa4ed..47bd0b691 100644 --- a/soh/include/z64audio.h +++ b/soh/include/z64audio.h @@ -1,6 +1,8 @@ #ifndef Z64_AUDIO_H #define Z64_AUDIO_H +#include "endianness.h" + #define MK_CMD(b0,b1,b2,b3) ((((b0) & 0xFF) << 0x18) | (((b1) & 0xFF) << 0x10) | (((b2) & 0xFF) << 0x8) | (((b3) & 0xFF) << 0)) #define NO_LAYER ((SequenceLayer*)(-1)) @@ -685,6 +687,35 @@ typedef struct { } AudioPreloadReq; // size = 0x14 typedef struct { +#ifdef IS_BIGENDIAN + union{ + u32 opArgs; + struct { + u8 op; + u8 arg0; + u8 arg1; + u8 arg2; + }; + }; + union { + void* data; + f32 asFloat; + s32 asInt; + struct { + u16 asUShort; + u8 pad2[2]; + }; + struct { + s8 asSbyte; + u8 pad1[3]; + }; + struct { + u8 asUbyte; + u8 pad0[3]; + }; + u32 asUInt; + }; +#else union{ u32 opArgs; struct { @@ -712,6 +743,7 @@ typedef struct { }; u32 asUInt; }; +#endif } AudioCmd; typedef struct { diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 393619cce..053d2d801 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -117,8 +117,7 @@ extern "C" void InitOTR() { if (!t->bHasLoadError) { - //uint32_t gameVersion = BitConverter::ToUInt32BE((uint8_t*)t->buffer.get(), 0); - uint32_t gameVersion = *((uint32_t*)t->buffer.get()); + uint32_t gameVersion = LE32SWAP(*((uint32_t*)t->buffer.get())); OTRGlobals::Instance->context->GetResourceManager()->SetGameVersion(gameVersion); } @@ -795,8 +794,8 @@ extern "C" SoundFont* ResourceMgr_LoadAudioSoundFont(const char* path) { for (size_t k = 0; k < soundFont->drums[i].env.size(); k++) { - drum->envelope[k].delay = BOMSWAP16(soundFont->drums[i].env[k]->delay); - drum->envelope[k].arg = BOMSWAP16(soundFont->drums[i].env[k]->arg); + drum->envelope[k].delay = BE16SWAP(soundFont->drums[i].env[k]->delay); + drum->envelope[k].arg = BE16SWAP(soundFont->drums[i].env[k]->arg); } } @@ -827,8 +826,8 @@ extern "C" SoundFont* ResourceMgr_LoadAudioSoundFont(const char* path) { for (int k = 0; k < soundFont->instruments[i].env.size(); k++) { - inst->envelope[k].delay = BOMSWAP16(soundFont->instruments[i].env[k]->delay); - inst->envelope[k].arg = BOMSWAP16(soundFont->instruments[i].env[k]->arg); + inst->envelope[k].delay = BE16SWAP(soundFont->instruments[i].env[k]->delay); + inst->envelope[k].arg = BE16SWAP(soundFont->instruments[i].env[k]->arg); } } if (soundFont->instruments[i].lowNotesSound != nullptr) diff --git a/soh/src/code/audio_data.c b/soh/src/code/audio_data.c index 5fe49139b..37e817688 100644 --- a/soh/src/code/audio_data.c +++ b/soh/src/code/audio_data.c @@ -544,10 +544,10 @@ u8 gDefaultShortNoteGateTimeTable[] = { }; AdsrEnvelope gDefaultEnvelope[] = { - { 0x0100, 0x007D }, - { 0xE803, 0x007D }, - { 0xFFFF, 0x0000 }, - { 0x0000, 0x0000 }, + { BE16SWAP_CONST(1), BE16SWAP_CONST(32000) }, + { BE16SWAP_CONST(1000), BE16SWAP_CONST(32000) }, + { BE16SWAP_CONST(-1), BE16SWAP_CONST(0) }, + { BE16SWAP_CONST(0), BE16SWAP_CONST(0) }, }; NoteSubEu gZeroNoteSub = { 0 }; diff --git a/soh/src/code/audio_effects.c b/soh/src/code/audio_effects.c index d5aa3644f..f77462f98 100644 --- a/soh/src/code/audio_effects.c +++ b/soh/src/code/audio_effects.c @@ -246,7 +246,7 @@ f32 Audio_AdsrUpdate(AdsrState* adsr) { retry: case ADSR_STATE_LOOP: - adsr->delay = (s16)BOMSWAP16(adsr->envelope[adsr->envIndex].delay); + adsr->delay = (s16)BE16SWAP(adsr->envelope[adsr->envIndex].delay); switch (adsr->delay) { case ADSR_DISABLE: adsr->action.s.state = ADSR_STATE_DISABLED; @@ -255,7 +255,7 @@ f32 Audio_AdsrUpdate(AdsrState* adsr) { adsr->action.s.state = ADSR_STATE_HANG; break; case ADSR_GOTO: - adsr->envIndex = (s16)BOMSWAP16(adsr->envelope[adsr->envIndex].arg); + adsr->envIndex = (s16)BE16SWAP(adsr->envelope[adsr->envIndex].arg); goto retry; case ADSR_RESTART: adsr->action.s.state = ADSR_STATE_INITIAL; @@ -266,7 +266,7 @@ f32 Audio_AdsrUpdate(AdsrState* adsr) { if (adsr->delay == 0) { adsr->delay = 1; } - adsr->target = (s16)BOMSWAP16(adsr->envelope[adsr->envIndex].arg) / 32767.0f; + adsr->target = (s16)BE16SWAP(adsr->envelope[adsr->envIndex].arg) / 32767.0f; adsr->target = adsr->target * adsr->target; adsr->velocity = (adsr->target - adsr->current) / adsr->delay; adsr->action.s.state = ADSR_STATE_FADE; diff --git a/soh/src/code/audio_seqplayer.c b/soh/src/code/audio_seqplayer.c index b8fbd9e1f..dd9c6e1cc 100644 --- a/soh/src/code/audio_seqplayer.c +++ b/soh/src/code/audio_seqplayer.c @@ -1340,13 +1340,13 @@ void AudioSeq_SequenceChannelProcessScript(SequenceChannel* channel) { break; case 0xB2: offset = (u16)parameters[0]; - channel->unk_22 = BOMSWAP16(*(u16*)(seqPlayer->seqData + (uintptr_t)(offset + scriptState->value * 2))); + channel->unk_22 = BE16SWAP(*(u16*)(seqPlayer->seqData + (uintptr_t)(offset + scriptState->value * 2))); break; case 0xB4: channel->dynTable = (void*)&seqPlayer->seqData[channel->unk_22]; break; case 0xB5: - channel->unk_22 = BOMSWAP16(((u16*)(channel->dynTable))[scriptState->value]); + channel->unk_22 = BE16SWAP(((u16*)(channel->dynTable))[scriptState->value]); break; case 0xB6: scriptState->value = (*channel->dynTable)[0][scriptState->value]; diff --git a/soh/src/code/z_room.c b/soh/src/code/z_room.c index 04f2d421b..d73533ff8 100644 --- a/soh/src/code/z_room.c +++ b/soh/src/code/z_room.c @@ -217,13 +217,12 @@ void func_80095D04(GlobalContext* globalCtx, Room* room, u32 flags) { CLOSE_DISPS(globalCtx->state.gfxCtx); } -//#define JPEG_MARKER 0xFFD8FFE0 -#define JPEG_MARKER 0xE0FFD8FF +#define JPEG_MARKER 0xFFD8FFE0 s32 func_80096238(void* data) { OSTime time; - if (*(u32*)data == JPEG_MARKER) + if (BE32SWAP(*(u32*)data) == JPEG_MARKER) { char* decodedJpeg = ResourceMgr_LoadJPEG(data, 320 * 240 * 2); //char* decodedJpeg = ResourceMgr_LoadJPEG(data, 480 * 240 * 2); From fa0a66695c00aea3cf787a00d9876bd7672e827e Mon Sep 17 00:00:00 2001 From: aMannus Date: Thu, 28 Jul 2022 04:18:27 +0200 Subject: [PATCH 05/25] Skips time travel cutscene in rando (#956) --- soh/src/code/z_demo.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/soh/src/code/z_demo.c b/soh/src/code/z_demo.c index 46b5fd9cf..885446271 100644 --- a/soh/src/code/z_demo.c +++ b/soh/src/code/z_demo.c @@ -493,7 +493,8 @@ void Cutscene_Command_Terminator(GlobalContext* globalCtx, CutsceneContext* csCt // Automatically skip certain cutscenes when in rando // cmd->base == 33: Zelda escaping with impa cutscene - bool randoCsSkip = (gSaveContext.n64ddFlag && cmd->base == 33); + // cmd->base == 8: Traveling back/forward in time cutscene + bool randoCsSkip = (gSaveContext.n64ddFlag && (cmd->base == 33 || cmd->base == 8)); bool debugCsSkip = (CHECK_BTN_ALL(globalCtx->state.input[0].press.button, BTN_START) && (gSaveContext.fileNum != 0xFEDC) && CVar_GetS32("gDebugEnabled", 0)); From a6092c21d40d4506812dbef9c350e0ebada2c20e Mon Sep 17 00:00:00 2001 From: Nicholas Estelami Date: Sun, 29 May 2022 14:36:05 -0400 Subject: [PATCH 06/25] Merge with develop --- ZAPDTR/ZAPD/Globals.cpp | 1 + libultraship/libultraship/Cvar.cpp | 8 ++++---- libultraship/libultraship/Cvar.h | 12 +++++++++++- {soh/include => libultraship/libultraship}/color.h | 0 libultraship/libultraship/libultraship.vcxproj | 1 + .../libultraship/libultraship.vcxproj.filters | 3 +++ soh/soh.vcxproj | 1 - soh/soh.vcxproj.filters | 3 --- soh/soh/Enhancements/debugconsole.cpp | 6 +++--- 9 files changed, 23 insertions(+), 12 deletions(-) rename {soh/include => libultraship/libultraship}/color.h (100%) diff --git a/ZAPDTR/ZAPD/Globals.cpp b/ZAPDTR/ZAPD/Globals.cpp index 455205b2a..181e2dce8 100644 --- a/ZAPDTR/ZAPD/Globals.cpp +++ b/ZAPDTR/ZAPD/Globals.cpp @@ -23,6 +23,7 @@ Globals::Globals() singleThreaded = true; verbosity = VerbosityLevel::VERBOSITY_SILENT; outputPath = Directory::GetCurrentDirectory(); + singleThreaded = true; } Globals::~Globals() diff --git a/libultraship/libultraship/Cvar.cpp b/libultraship/libultraship/Cvar.cpp index 27d44df80..98d4ee9b0 100644 --- a/libultraship/libultraship/Cvar.cpp +++ b/libultraship/libultraship/Cvar.cpp @@ -52,7 +52,7 @@ extern "C" void CVar_SetS32(const char* name, int32_t value) { if (!cvar) { cvar = std::make_unique(); } - cvar->type = CVAR_TYPE_S32; + cvar->type = CVarType::S32; cvar->value.valueS32 = value; } @@ -61,7 +61,7 @@ void CVar_SetFloat(const char* name, float value) { if (!cvar) { cvar = std::make_unique(); } - cvar->type = CVAR_TYPE_FLOAT; + cvar->type = CVarType::Float; cvar->value.valueFloat = value; } @@ -70,8 +70,8 @@ extern "C" void CVar_SetString(const char* name, const char* value) { if (!cvar) { cvar = std::make_unique(); } - cvar->type = CVAR_TYPE_STRING; - cvar->value.valueStr = ImStrdup(value); + cvar->type = CVarType::String; + cvar->value.valueStr = value; } extern "C" void CVar_RegisterS32(const char* name, int32_t defaultValue) { diff --git a/libultraship/libultraship/Cvar.h b/libultraship/libultraship/Cvar.h index 1507b519d..c0568da41 100644 --- a/libultraship/libultraship/Cvar.h +++ b/libultraship/libultraship/Cvar.h @@ -3,7 +3,14 @@ #include -typedef enum CVarType { CVAR_TYPE_S32, CVAR_TYPE_FLOAT, CVAR_TYPE_STRING } CVarType; +#ifdef __cplusplus +typedef enum class CVarType +{ + S32, + Float, + String, + RGBA +} CVarType; typedef struct CVar { const char* name; @@ -16,6 +23,9 @@ typedef struct CVar { } value; } CVar; +CVar* CVar_Get(char* name); +#endif + #ifdef __cplusplus extern "C" { diff --git a/soh/include/color.h b/libultraship/libultraship/color.h similarity index 100% rename from soh/include/color.h rename to libultraship/libultraship/color.h diff --git a/libultraship/libultraship/libultraship.vcxproj b/libultraship/libultraship/libultraship.vcxproj index 9c759f85a..4d7eab9b4 100644 --- a/libultraship/libultraship/libultraship.vcxproj +++ b/libultraship/libultraship/libultraship.vcxproj @@ -351,6 +351,7 @@ + diff --git a/libultraship/libultraship/libultraship.vcxproj.filters b/libultraship/libultraship/libultraship.vcxproj.filters index abad0cb72..fa5c505aa 100644 --- a/libultraship/libultraship/libultraship.vcxproj.filters +++ b/libultraship/libultraship/libultraship.vcxproj.filters @@ -653,6 +653,9 @@ Source Files\Resources + + Header Files + Source Files\CustomImpl\Overlay diff --git a/soh/soh.vcxproj b/soh/soh.vcxproj index 6275e82fd..bc7c4d646 100644 --- a/soh/soh.vcxproj +++ b/soh/soh.vcxproj @@ -988,7 +988,6 @@ - diff --git a/soh/soh.vcxproj.filters b/soh/soh.vcxproj.filters index 5f48ff042..f0c05dee8 100644 --- a/soh/soh.vcxproj.filters +++ b/soh/soh.vcxproj.filters @@ -2384,9 +2384,6 @@ Header Files\include - - Header Files\include - Header Files\include diff --git a/soh/soh/Enhancements/debugconsole.cpp b/soh/soh/Enhancements/debugconsole.cpp index eb2b02b11..5ea885723 100644 --- a/soh/soh/Enhancements/debugconsole.cpp +++ b/soh/soh/Enhancements/debugconsole.cpp @@ -426,11 +426,11 @@ static bool GetCVarHandler(const std::vector& args) { if (cvar != nullptr) { - if (cvar->type == CVAR_TYPE_S32) + if (cvar->type == CVarType::S32) INFO("[SOH] Variable %s is %i", args[1].c_str(), cvar->value.valueS32); - else if (cvar->type == CVAR_TYPE_FLOAT) + else if (cvar->type == CVarType::Float) INFO("[SOH] Variable %s is %f", args[1].c_str(), cvar->value.valueFloat); - else if (cvar->type == CVAR_TYPE_STRING) + else if (cvar->type == CVarType::String) INFO("[SOH] Variable %s is %s", args[1].c_str(), cvar->value.valueStr); } else From 0193489b004f899fd7f17179b866a9d37f93042d Mon Sep 17 00:00:00 2001 From: Nicholas Estelami Date: Tue, 31 May 2022 00:59:35 -0400 Subject: [PATCH 07/25] RGBA8 CVar Support Added --- libultraship/libultraship/Cvar.cpp | 51 +++++++++++++++++++++-- libultraship/libultraship/Cvar.h | 8 ++++ libultraship/libultraship/GameOverlay.cpp | 6 +-- libultraship/libultraship/color.h | 4 ++ soh/soh/Enhancements/debugconsole.cpp | 48 +++++++++++++++++++-- soh/src/code/z_actor.c | 32 ++++---------- soh/src/code/z_player_lib.c | 14 ++----- 7 files changed, 119 insertions(+), 44 deletions(-) diff --git a/libultraship/libultraship/Cvar.cpp b/libultraship/libultraship/Cvar.cpp index 98d4ee9b0..eb6147baf 100644 --- a/libultraship/libultraship/Cvar.cpp +++ b/libultraship/libultraship/Cvar.cpp @@ -18,7 +18,7 @@ extern "C" int32_t CVar_GetS32(const char* name, int32_t defaultValue) { CVar* cvar = CVar_Get(name); if (cvar) { - if (cvar->type == CVAR_TYPE_S32) + if (cvar->type == CVarType::S32) return cvar->value.valueS32; } @@ -29,7 +29,7 @@ extern "C" float CVar_GetFloat(const char* name, float defaultValue) { CVar* cvar = CVar_Get(name); if (cvar) { - if (cvar->type == CVAR_TYPE_FLOAT) + if (cvar->type == CVarType::Float) return cvar->value.valueFloat; } @@ -40,13 +40,53 @@ extern "C" const char* CVar_GetString(const char* name, const char* defaultValue CVar* cvar = CVar_Get(name); if (cvar) { - if (cvar->type == CVAR_TYPE_STRING) + if (cvar->type == CVarType::String) return cvar->value.valueStr; } return defaultValue; } +extern "C" Color_RGB8 CVar_GetRGB(const char* name, Color_RGB8 defaultValue) +{ + Color_RGBA8 defaultValueRGBA; + defaultValueRGBA.r = defaultValue.r; + defaultValueRGBA.g = defaultValue.g; + defaultValueRGBA.b = defaultValue.b; + defaultValueRGBA.a = 255; + + Color_RGBA8 cvarGet = CVar_GetRGBA(name, defaultValueRGBA); + Color_RGB8 result; + + result.r = cvarGet.r; + result.g = cvarGet.g; + result.b = cvarGet.b; + + return result; +} + +extern "C" Color_RGBA8 CVar_GetRGBA(const char* name, Color_RGBA8 defaultValue) { + CVar* cvar = CVar_Get(name); + + if (cvar != nullptr) { + if (cvar->type == CVarType::RGBA) + return cvar->value.valueRGBA; + } + + return defaultValue; +} + +extern "C" void CVar_SetRGBA(const char* name, Color_RGBA8 value) +{ + auto& cvar = cvars[name]; + if (!cvar) { + cvar = std::make_unique(); + } + + cvar->type = CVarType::RGBA; + cvar->value.valueRGBA = value; +} + extern "C" void CVar_SetS32(const char* name, int32_t value) { auto& cvar = cvars[name]; if (!cvar) { @@ -74,6 +114,11 @@ extern "C" void CVar_SetString(const char* name, const char* value) { cvar->value.valueStr = value; } +extern "C" void CVar_RegisterRGBA(const char* name, Color_RGBA8 defaultValue) { + if (!CVar_Get(name)) + CVar_SetRGBA(name, defaultValue); +} + extern "C" void CVar_RegisterS32(const char* name, int32_t defaultValue) { if (!CVar_Get(name)) CVar_SetS32(name, defaultValue); diff --git a/libultraship/libultraship/Cvar.h b/libultraship/libultraship/Cvar.h index c0568da41..759d7f895 100644 --- a/libultraship/libultraship/Cvar.h +++ b/libultraship/libultraship/Cvar.h @@ -1,6 +1,7 @@ #ifndef _CVAR_H #define _CVAR_H +#include "color.h" #include #ifdef __cplusplus @@ -20,6 +21,7 @@ typedef struct CVar { int32_t valueS32; float valueFloat; const char* valueStr; + Color_RGBA8 valueRGBA; } value; } CVar; @@ -39,9 +41,14 @@ const char* CVar_GetString(const char* name, const char* defaultValue); void CVar_SetS32(const char* name, int32_t value); void CVar_SetString(const char* name, const char* value); +Color_RGB8 CVar_GetRGB(const char* name, Color_RGB8 defaultValue); +Color_RGBA8 CVar_GetRGBA(const char* name, Color_RGBA8 defaultValue); +void CVar_SetRGBA(const char* name, Color_RGBA8 value); + void CVar_RegisterS32(const char* name, int32_t defaultValue); void CVar_RegisterFloat(const char* name, float defaultValue); void CVar_RegisterString(const char* name, const char* defaultValue); +void CVar_RegisterRGBA(const char* name, Color_RGBA8 defaultValue); #ifdef __cplusplus }; @@ -53,6 +60,7 @@ void CVar_RegisterString(const char* name, const char* defaultValue); #include #include +extern "C" CVar * CVar_Get(const char* name); extern std::map, std::less<>> cvars; void CVar_SetFloat(const char* name, float value); #endif diff --git a/libultraship/libultraship/GameOverlay.cpp b/libultraship/libultraship/GameOverlay.cpp index 5f98a3104..ab6dfb33c 100644 --- a/libultraship/libultraship/GameOverlay.cpp +++ b/libultraship/libultraship/GameOverlay.cpp @@ -162,13 +162,13 @@ void Ship::GameOverlay::Draw() { ImVec4 color = ImVec4(1.0f, 1.0f, 1.0f, 1.0f); switch (var->type) { - case CVAR_TYPE_FLOAT: + case CVarType::Float: this->TextDraw(30, textY, true, color, "%s %.2f", text, var->value.valueFloat); break; - case CVAR_TYPE_S32: + case CVarType::S32: this->TextDraw(30, textY, true, color, "%s %d", text, var->value.valueS32); break; - case CVAR_TYPE_STRING: + case CVarType::String: this->TextDraw(30, textY, true, color, "%s %s", text, var->value.valueStr); break; } diff --git a/libultraship/libultraship/color.h b/libultraship/libultraship/color.h index 6c8e4c1ce..a260869a7 100644 --- a/libultraship/libultraship/color.h +++ b/libultraship/libultraship/color.h @@ -37,4 +37,8 @@ typedef union { u16 rgba; } Color_RGBA16; +#ifdef __cplusplus +}; +#endif + #endif diff --git a/soh/soh/Enhancements/debugconsole.cpp b/soh/soh/Enhancements/debugconsole.cpp index 5ea885723..bdae7754e 100644 --- a/soh/soh/Enhancements/debugconsole.cpp +++ b/soh/soh/Enhancements/debugconsole.cpp @@ -375,11 +375,16 @@ static bool StateSlotSelectHandler(const std::vector& args) { #define VARTYPE_INTEGER 0 #define VARTYPE_FLOAT 1 #define VARTYPE_STRING 2 +#define VARTYPE_RGBA 3 static int CheckVarType(const std::string& input) { int result = VARTYPE_STRING; + if (input[0] == '#') { + return VARTYPE_RGBA; + } + for (size_t i = 0; i < input.size(); i++) { if (!(std::isdigit(input[i]) || input[i] == '.')) @@ -407,7 +412,17 @@ static bool SetCVarHandler(const std::vector& args) { if (vType == VARTYPE_STRING) CVar_SetString(args[1].c_str(), args[2].c_str()); else if (vType == VARTYPE_FLOAT) - CVar_SetFloat(args[1].c_str(), std::stof(args[2])); + CVar_SetFloat((char*)args[1].c_str(), std::stof(args[2])); + else if (vType == VARTYPE_RGBA) + { + uint32_t val = std::stoul(&args[2].c_str()[1], nullptr, 16); + Color_RGBA8 clr; + clr.r = val >> 24; + clr.g = val >> 16; + clr.b = val >> 8; + clr.a = val & 0xFF; + CVar_SetRGBA((char*)args[1].c_str(), clr); + } else CVar_SetS32(args[1].c_str(), std::stoi(args[2])); @@ -432,6 +447,8 @@ static bool GetCVarHandler(const std::vector& args) { INFO("[SOH] Variable %s is %f", args[1].c_str(), cvar->value.valueFloat); else if (cvar->type == CVarType::String) INFO("[SOH] Variable %s is %s", args[1].c_str(), cvar->value.valueStr); + else if (cvar->type == CVarType::RGBA) + INFO("[SOH] Variable %s is %08X", args[1].c_str(), cvar->value.valueRGBA); } else { @@ -508,6 +525,22 @@ void DebugConsole_LoadLegacyCVars() { std::vector cfg = StringHelper::Split(line, " = "); if (line.empty()) continue; if (cfg.size() < 2) continue; + + if (cfg[1].find("\"") == std::string::npos && (cfg[1].find("#") != std::string::npos)) + { + std::string value(cfg[1]); + value.erase(std::ranges::remove(value, '#').begin(), value.end()); + auto splitTest = StringHelper::Split(value, "\r")[0]; + + uint32_t val = std::stoul(splitTest, nullptr, 16); + Color_RGBA8 clr; + clr.r = val >> 24; + clr.g = val >> 16; + clr.b = val >> 8; + clr.a = val & 0xFF; + CVar_SetRGBA(cfg[0].c_str(), clr); + } + if (cfg[1].find("\"") != std::string::npos) { std::string value(cfg[1]); value.erase(std::remove(value.begin(), value.end(), '\"'), value.end()); @@ -565,12 +598,19 @@ void DebugConsole_SaveCVars() for (const auto &cvar : cvars) { const std::string key = StringHelper::Sprintf("CVars.%s", cvar.first.c_str()); - if (cvar.second->type == CVAR_TYPE_STRING && cvar.second->value.valueStr != nullptr) + if (cvar.second->type == CVarType::String && cvar.second->value.valueStr != nullptr) pConf->setString(key, std::string(cvar.second->value.valueStr)); - else if (cvar.second->type == CVAR_TYPE_S32) + else if (cvar.second->type == CVarType::S32) pConf->setInt(key, cvar.second->value.valueS32); - else if (cvar.second->type == CVAR_TYPE_FLOAT) + else if (cvar.second->type == CVarType::Float) pConf->setFloat(key, cvar.second->value.valueFloat); + else if (cvar.second->type == CVarType::RGBA) + { + Color_RGBA8 clr = cvar.second->value.valueRGBA; + uint32_t val = (clr.r << 24) + (clr.g << 16) + (clr.b << 8) + clr.a; + Conf->setRGBA(clr); + //output += StringHelper::Sprintf("%s = #%08X\n", cvar.first.c_str(), val); + } } pConf->save(); diff --git a/soh/src/code/z_actor.c b/soh/src/code/z_actor.c index 70771880c..fff93a560 100644 --- a/soh/src/code/z_actor.c +++ b/soh/src/code/z_actor.c @@ -355,36 +355,20 @@ void func_8002BF60(TargetContext* targetCtx, Actor* actor, s32 actorCategory, Gl } } 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); + naviColor->inner = CVar_GetRGBA("gNavi_Idle_Inner", naviColor->inner); + naviColor->outer = CVar_GetRGBA("gNavi_Idle_Outer", naviColor->outer); } 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); + naviColor->inner = CVar_GetRGBA("gNavi_NPC_Inner", naviColor->inner); + naviColor->outer = CVar_GetRGBA("gNavi_NPC_Outer", naviColor->outer); } 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); + naviColor->inner = CVar_GetRGBA("gNavi_Enemy_Inner", naviColor->inner); + naviColor->outer = CVar_GetRGBA("gNavi_Enemy_Outer", naviColor->outer); } 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); + naviColor->inner = CVar_GetRGBA("gNavi_Prop_Inner", naviColor->inner); + naviColor->outer = CVar_GetRGBA("gNavi_Prop_Outer", naviColor->outer); } } diff --git a/soh/src/code/z_player_lib.c b/soh/src/code/z_player_lib.c index 470cec354..2db533821 100644 --- a/soh/src/code/z_player_lib.c +++ b/soh/src/code/z_player_lib.c @@ -752,18 +752,12 @@ void func_8008F470(GlobalContext* globalCtx, void** skeleton, Vec3s* jointTable, }; 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); + *color = CVar_GetRGB("gTunic_Kokiri", sTunicColors[PLAYER_TUNIC_KOKIRI]); } 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); + *color = CVar_GetRGB("gTunic_Goron", sTunicColors[PLAYER_TUNIC_GORON]); } 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)) { + *color = CVar_GetRGB("gTunic_Zora", sTunicColors[PLAYER_TUNIC_ZORA]); + } else if (!CVar_GetS32("gUseTunicsCol",0)){ if (tunic >= 3) { color->r = sOriginalTunicColors[0].r; color->g = sOriginalTunicColors[0].g; From 44bf5af33a4cbf4610eb121c7df558d733ae6cd1 Mon Sep 17 00:00:00 2001 From: Nicholas Estelami Date: Mon, 11 Jul 2022 18:52:48 -0400 Subject: [PATCH 08/25] Fixed up merge issues and crash --- ZAPDTR/ZAPD/Globals.cpp | 1 - libultraship/libultraship/ImGuiImpl.cpp | 149 +++++++++++------- .../cosmetics/CosmeticsEditor.cpp | 16 +- 3 files changed, 104 insertions(+), 62 deletions(-) diff --git a/ZAPDTR/ZAPD/Globals.cpp b/ZAPDTR/ZAPD/Globals.cpp index 181e2dce8..455205b2a 100644 --- a/ZAPDTR/ZAPD/Globals.cpp +++ b/ZAPDTR/ZAPD/Globals.cpp @@ -23,7 +23,6 @@ Globals::Globals() singleThreaded = true; verbosity = VerbosityLevel::VERBOSITY_SILENT; outputPath = Directory::GetCurrentDirectory(); - singleThreaded = true; } Globals::~Globals() diff --git a/libultraship/libultraship/ImGuiImpl.cpp b/libultraship/libultraship/ImGuiImpl.cpp index f7288ae3a..a15698db3 100644 --- a/libultraship/libultraship/ImGuiImpl.cpp +++ b/libultraship/libultraship/ImGuiImpl.cpp @@ -280,24 +280,66 @@ namespace SohImGui { stbi_image_free(img_data); } - 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"; + void LoadRainbowColor() { + u8 arrayLength = sizeof(RainbowColorCvarList) / sizeof(*RainbowColorCvarList); + for (u8 s = 0; s < arrayLength; 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; - 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; + 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) + { + Color_RGBA8 defaultColors; + defaultColors.r = default_colors.x; + defaultColors.g = default_colors.y; + defaultColors.b = default_colors.z; + defaultColors.a = default_colors.w; + + Color_RGBA8 cvarColor = CVar_GetRGBA(cvarname, defaultColors); + + ColorArray.x = cvarColor.r / 255.0; + ColorArray.y = cvarColor.g / 255.0; + ColorArray.z = cvarColor.b / 255.0; + ColorArray.w = cvarColor.a / 255.0; + } + 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()); @@ -661,14 +703,6 @@ namespace SohImGui { } 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"; @@ -680,10 +714,14 @@ namespace SohImGui { 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)); }; + + Color_RGBA8 colorsRGBA; + colorsRGBA.r = defaultcolors.x / 255; + colorsRGBA.g = defaultcolors.y / 255; + colorsRGBA.b = defaultcolors.z / 255; + if (has_alpha) { colorsRGBA.a = defaultcolors.w / 255; }; + + CVar_SetRGBA(cvarName, colorsRGBA); CVar_SetS32(Cvar_RBM.c_str(), 0); //On click disable rainbow mode. needs_save = true; } @@ -691,42 +729,47 @@ namespace SohImGui { } void EnhancementColor(const char* text, const char* cvarName, ImVec4 ColorRGBA, ImVec4 default_colors, bool allow_rainbow, bool has_alpha, bool TitleSameLine) { - //This will be moved to external cosmetics ed - 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) { ImGui::Text("%s", text); flags = ImGuiColorEditFlags_NoLabel; } - 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::PushID(cvarName); + + if (!has_alpha) { + if (ImGui::ColorEdit3(text, (float*)&ColorRGBA, flags)) + { + Color_RGBA8 colors; + colors.r = ColorRGBA.x * 255.0; + colors.g = ColorRGBA.y * 255.0; + colors.b = ColorRGBA.z * 255.0; + colors.a = ColorRGBA.w * 255.0; + + CVar_SetRGBA(cvarName, colors); + needs_save = true; + } } + else + { + if (ImGui::ColorEdit4(text, (float*)&ColorRGBA, flags)) + { + Color_RGBA8 colors; + colors.r = ColorRGBA.x / 255; + colors.g = ColorRGBA.y / 255; + colors.b = ColorRGBA.z / 255; + colors.a = ColorRGBA.w / 255; + + CVar_SetRGBA(cvarName, colors); + needs_save = true; + } + } + + ImGui::PopID(); + //ImGui::SameLine(); // Removing that one to gain some width spacing on the HUD editor ImGui::PushItemWidth(-FLT_MIN); ResetColor(cvarName, &ColorRGBA, default_colors, has_alpha); diff --git a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp index 66b9b8939..3b1ccb4c0 100644 --- a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp +++ b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp @@ -229,28 +229,28 @@ void Draw_Npcs(){ ImGui::TableSetupColumn("Outer colors##Navi", ImGuiTableColumnFlags_WidthStretch | ImGuiTableColumnFlags_IndentEnable | ImGuiTableColumnFlags_NoSort, TablesCellsWidth/2); Table_InitHeader(); Draw_HelpIcon("Inner color for Navi (idle flying around)"); - SohImGui::EnhancementColor("Navi Idle (Primary)", "gNavi_Idle_Inner_", navi_idle_i_col, ImVec4(255, 255, 255, 255), false); + SohImGui::EnhancementColor("Navi Idle (Primary)", "gNavi_Idle_Inner", navi_idle_i_col, ImVec4(255, 255, 255, 255), false); Table_NextCol(); Draw_HelpIcon("Outer color for Navi (idle flying around)"); - SohImGui::EnhancementColor("Navi Idle (Secondary)", "gNavi_Idle_Outer_", navi_idle_o_col, ImVec4(0, 0, 255, 255), false); + SohImGui::EnhancementColor("Navi Idle (Secondary)", "gNavi_Idle_Outer", navi_idle_o_col, ImVec4(0, 0, 255, 255), false); Table_NextLine(); Draw_HelpIcon("Inner color for Navi (when Navi fly around NPCs)"); - SohImGui::EnhancementColor("Navi NPC (Primary)", "gNavi_NPC_Inner_", navi_npc_i_col, ImVec4(150, 150, 255, 255), false); + SohImGui::EnhancementColor("Navi NPC (Primary)", "gNavi_NPC_Inner", navi_npc_i_col, ImVec4(150, 150, 255, 255), false); Table_NextCol(); Draw_HelpIcon("Outer color for Navi (when Navi fly around NPCs)"); - SohImGui::EnhancementColor("Navi NPC (Secondary)", "gNavi_NPC_Outer_", navi_npc_o_col, ImVec4(150, 150, 255, 255), false); + SohImGui::EnhancementColor("Navi NPC (Secondary)", "gNavi_NPC_Outer", navi_npc_o_col, ImVec4(150, 150, 255, 255), false); Table_NextLine(); Draw_HelpIcon("Inner color for Navi (when Navi fly around Enemies or Bosses)"); - SohImGui::EnhancementColor("Navi Enemy (Primary)", "gNavi_Enemy_Inner_", navi_enemy_i_col, ImVec4(255, 255, 0, 255), false); + SohImGui::EnhancementColor("Navi Enemy", "gNavi_Enemy_Inner", navi_enemy_i_col, ImVec4(255, 255, 0, 255), false); Table_NextCol(); Draw_HelpIcon("Outer color for Navi (when Navi fly around Enemies or Bosses)"); - SohImGui::EnhancementColor("Navi Enemy (Secondary)", "gNavi_Enemy_Outer_", navi_enemy_o_col, ImVec4(220, 155, 0, 255), false); + SohImGui::EnhancementColor("Navi Enemy (Secondary)", "gNavi_Enemy_Outer", navi_enemy_o_col, ImVec4(220, 155, 0, 255), false); Table_NextLine(); Draw_HelpIcon("Inner color for Navi (when Navi fly around props (signs etc))"); - SohImGui::EnhancementColor("Navi Prop (Primary)", "gNavi_Prop_Inner_", navi_prop_i_col, ImVec4(0, 255, 0, 255), false); + SohImGui::EnhancementColor("Navi Prop (Primary)", "gNavi_Prop_Inner", navi_prop_i_col, ImVec4(0, 255, 0, 255), false); Table_NextCol(); Draw_HelpIcon("Outer color for Navi (when Navi fly around props (signs etc))"); - SohImGui::EnhancementColor("Navi Prop (Secondary)", "gNavi_Prop_Outer_", navi_prop_o_col, ImVec4(0, 255, 0, 255), false); + SohImGui::EnhancementColor("Navi Prop (Secondary)", "gNavi_Prop_Outer", navi_prop_o_col, ImVec4(0, 255, 0, 255), false); ImGui::EndTable(); } SohImGui::EnhancementCheckbox("Custom colors for Keese", "gUseKeeseCol"); From 3bb234e6a66a368a2bfaeb2935993c29b553f98a Mon Sep 17 00:00:00 2001 From: Nicholas Estelami Date: Mon, 25 Jul 2022 23:11:45 -0400 Subject: [PATCH 09/25] Fixed merge issues. --- libultraship/libultraship/Cvar.cpp | 2 +- libultraship/libultraship/Cvar.h | 5 ++- libultraship/libultraship/ImGuiImpl.cpp | 44 ------------------------- libultraship/libultraship/color.h | 18 +++++----- soh/soh/Enhancements/debugconsole.cpp | 18 ++++++++-- 5 files changed, 27 insertions(+), 60 deletions(-) diff --git a/libultraship/libultraship/Cvar.cpp b/libultraship/libultraship/Cvar.cpp index eb6147baf..3a5ab6e04 100644 --- a/libultraship/libultraship/Cvar.cpp +++ b/libultraship/libultraship/Cvar.cpp @@ -9,7 +9,7 @@ std::map, std::less<>> cvars; -extern "C" CVar* CVar_Get(const char* name) { +CVar* CVar_Get(const char* name) { auto it = cvars.find(name); return (it != cvars.end()) ? it->second.get() : nullptr; } diff --git a/libultraship/libultraship/Cvar.h b/libultraship/libultraship/Cvar.h index 759d7f895..b8f294be6 100644 --- a/libultraship/libultraship/Cvar.h +++ b/libultraship/libultraship/Cvar.h @@ -25,7 +25,7 @@ typedef struct CVar { } value; } CVar; -CVar* CVar_Get(char* name); +extern "C" CVar * CVar_Get(const char* name); #endif #ifdef __cplusplus @@ -34,7 +34,6 @@ extern "C" #endif //#include -CVar* CVar_Get(const char* name); int32_t CVar_GetS32(const char* name, int32_t defaultValue); float CVar_GetFloat(const char* name, float defaultValue); const char* CVar_GetString(const char* name, const char* defaultValue); @@ -60,7 +59,7 @@ void CVar_RegisterRGBA(const char* name, Color_RGBA8 defaultValue); #include #include -extern "C" CVar * CVar_Get(const char* name); +//extern "C" CVar * CVar_Get(const char* name); extern std::map, std::less<>> cvars; void CVar_SetFloat(const char* name, float value); #endif diff --git a/libultraship/libultraship/ImGuiImpl.cpp b/libultraship/libultraship/ImGuiImpl.cpp index a15698db3..8997f6192 100644 --- a/libultraship/libultraship/ImGuiImpl.cpp +++ b/libultraship/libultraship/ImGuiImpl.cpp @@ -280,50 +280,6 @@ namespace SohImGui { stbi_image_free(img_data); } - void LoadRainbowColor() { - u8 arrayLength = sizeof(RainbowColorCvarList) / sizeof(*RainbowColorCvarList); - for (u8 s = 0; s < arrayLength; 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) { Color_RGBA8 defaultColors; diff --git a/libultraship/libultraship/color.h b/libultraship/libultraship/color.h index a260869a7..3e39389be 100644 --- a/libultraship/libultraship/color.h +++ b/libultraship/libultraship/color.h @@ -4,11 +4,11 @@ #include "endianness.h" typedef struct { - u8 r, g, b; + uint8_t r, g, b; } Color_RGB8; typedef struct { - u8 r, g, b, a; + uint8_t r, g, b, a; } Color_RGBA8; // only use when necessary for alignment purposes @@ -20,21 +20,21 @@ typedef union { u8 a, b, g, r; #endif }; - u32 rgba; + uint32_t rgba; } Color_RGBA8_u32; typedef struct { - f32 r, g, b, a; + float r, g, b, a; } Color_RGBAf; typedef union { struct { - u16 r : 5; - u16 g : 5; - u16 b : 5; - u16 a : 1; + uint16_t r : 5; + uint16_t g : 5; + uint16_t b : 5; + uint16_t a : 1; }; - u16 rgba; + uint16_t rgba; } Color_RGBA16; #ifdef __cplusplus diff --git a/soh/soh/Enhancements/debugconsole.cpp b/soh/soh/Enhancements/debugconsole.cpp index bdae7754e..85a8c3829 100644 --- a/soh/soh/Enhancements/debugconsole.cpp +++ b/soh/soh/Enhancements/debugconsole.cpp @@ -569,7 +569,19 @@ void DebugConsole_LoadCVars() { case nlohmann::detail::value_t::array: break; case nlohmann::detail::value_t::string: - CVar_SetString(item.key().c_str(), value.get().c_str()); + if (StringHelper::StartsWith(value.get(), "#")) + { + uint32_t val = std::stoul(&value.get().c_str()[1], nullptr, 16); + Color_RGBA8 clr; + clr.r = val >> 24; + clr.g = val >> 16; + clr.b = val >> 8; + clr.a = val & 0xFF; + + CVar_SetRGBA(item.key().c_str(), clr); + } + else + CVar_SetString(item.key().c_str(), value.get().c_str()); break; case nlohmann::detail::value_t::boolean: CVar_SetS32(item.key().c_str(), value.get()); @@ -608,8 +620,8 @@ void DebugConsole_SaveCVars() { Color_RGBA8 clr = cvar.second->value.valueRGBA; uint32_t val = (clr.r << 24) + (clr.g << 16) + (clr.b << 8) + clr.a; - Conf->setRGBA(clr); - //output += StringHelper::Sprintf("%s = #%08X\n", cvar.first.c_str(), val); + std::string str = StringHelper::Sprintf("#%08X", val); + pConf->setString(key, str); } } From 9d12813282328ad2b4bb6b6d5c40a89b69dc4ff6 Mon Sep 17 00:00:00 2001 From: Nicholas Estelami Date: Sun, 31 Jul 2022 14:50:28 -0400 Subject: [PATCH 10/25] Fixed merge/rebase issues --- libultraship/libultraship/color.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/libultraship/libultraship/color.h b/libultraship/libultraship/color.h index 3e39389be..44ba465c2 100644 --- a/libultraship/libultraship/color.h +++ b/libultraship/libultraship/color.h @@ -1,8 +1,14 @@ #ifndef COLOR_H #define COLOR_H +#include #include "endianness.h" +#ifdef __cplusplus +extern "C" +{ +#endif + typedef struct { uint8_t r, g, b; } Color_RGB8; @@ -15,9 +21,9 @@ typedef struct { typedef union { struct { #ifdef IS_BIGENDIAN - u8 r, g, b, a; + uint8_t r, g, b, a; #else - u8 a, b, g, r; + uint8_t a, b, g, r; #endif }; uint32_t rgba; From 47ad3bdc47d47052fe8358a67c769cce3f5935ac Mon Sep 17 00:00:00 2001 From: Nicholas Estelami Date: Sun, 31 Jul 2022 15:32:08 -0400 Subject: [PATCH 11/25] Fixed linux compile issue --- libultraship/libultraship/GameOverlay.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libultraship/libultraship/GameOverlay.cpp b/libultraship/libultraship/GameOverlay.cpp index ab6dfb33c..ccbdc142c 100644 --- a/libultraship/libultraship/GameOverlay.cpp +++ b/libultraship/libultraship/GameOverlay.cpp @@ -171,6 +171,9 @@ void Ship::GameOverlay::Draw() { case CVarType::String: this->TextDraw(30, textY, true, color, "%s %s", text, var->value.valueStr); break; + case CVarType::RGBA: + this->TextDraw(30, textY, true, color, "#%08X", text, var->value.valueRGBA); + break; } free((void*) text); From 582f084973b9c5cc4c5c49831fb44a957d5161d6 Mon Sep 17 00:00:00 2001 From: David Chavez Date: Mon, 1 Aug 2022 03:32:40 +0200 Subject: [PATCH 12/25] Use tex sizes from texture rather than hardcoded values (#610) * Use tex sizes from texture rather than hardcoded values * Dynamic do action tex sizes * Remove unused minimap texture keys * Restore MESSAGE_STATIC_TEX_SIZE * Use dynamic offsets * MACRO it up * Enable SPDLOG in Xcode * Handle non-existent texture --- libultraship/libultraship/Window.cpp | 36 ++++++++- soh/include/z64.h | 2 - soh/soh.xcodeproj/project.pbxproj | 6 +- .../xcshareddata/xcschemes/soh.xcscheme | 78 +++++++++++++++++++ soh/soh/GbiWrap.cpp | 3 + soh/soh/OTRGlobals.cpp | 6 ++ soh/soh/OTRGlobals.h | 3 + soh/src/code/z_construct.c | 28 +------ soh/src/code/z_map_data.c | 29 +++---- soh/src/code/z_map_exp.c | 9 ++- soh/src/code/z_message_PAL.c | 11 +-- soh/src/code/z_parameter.c | 62 ++++++++++----- .../ovl_kaleido_scope/z_kaleido_scope_PAL.c | 23 ++++-- 13 files changed, 209 insertions(+), 87 deletions(-) create mode 100644 soh/soh.xcodeproj/xcshareddata/xcschemes/soh.xcscheme diff --git a/libultraship/libultraship/Window.cpp b/libultraship/libultraship/Window.cpp index 9957ebc48..39d4aad06 100644 --- a/libultraship/libultraship/Window.cpp +++ b/libultraship/libultraship/Window.cpp @@ -32,6 +32,8 @@ #include +#define LOAD_TEX(texPath) static_cast(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(texPath).get()); + extern "C" { struct OSMesgQueue; @@ -123,8 +125,7 @@ extern "C" { const std::string* hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc); if (hashStr != nullptr) { - const auto res = static_cast(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr->c_str()).get()); - + const auto res = LOAD_TEX(hashStr->c_str()); ModInternal::ExecuteHooks(hashStr->c_str(), &res->imageData); return reinterpret_cast(res->imageData); @@ -151,13 +152,40 @@ extern "C" { } char* ResourceMgr_LoadTexByName(char* texPath) { - const auto res = static_cast(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(texPath).get()); + const auto res = LOAD_TEX(texPath); ModInternal::ExecuteHooks(texPath, &res->imageData); return (char*)res->imageData; } + uint16_t ResourceMgr_LoadTexWidthByName(char* texPath) { + const auto res = LOAD_TEX(texPath); + if (res != nullptr) + return res->width; + + SPDLOG_ERROR("Given texture path is a non-existent resource"); + return -1; + } + + uint16_t ResourceMgr_LoadTexHeightByName(char* texPath) { + const auto res = LOAD_TEX(texPath); + if (res != nullptr) + return res->height; + + SPDLOG_ERROR("Given texture path is a non-existent resource"); + return -1; + } + + uint32_t ResourceMgr_LoadTexSizeByName(char* texPath) { + const auto res = LOAD_TEX(texPath); + if (res != nullptr) + return res->imageDataSize; + + SPDLOG_ERROR("Given texture path is a non-existent resource"); + return -1; + } + void ResourceMgr_WriteTexS16ByName(char* texPath, size_t index, s16 value) { - const auto res = static_cast(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(texPath).get()); + const auto res = LOAD_TEX(texPath); if (res != nullptr) { diff --git a/soh/include/z64.h b/soh/include/z64.h index fdc634e58..94d8b280e 100644 --- a/soh/include/z64.h +++ b/soh/include/z64.h @@ -1458,8 +1458,6 @@ typedef struct { /* 0x18 */ s16 (*roomCompassOffsetY)[44]; // dungeon compass icon Y offset by room /* 0x1C */ u8* dgnMinimapCount; // number of room minimaps /* 0x20 */ u16* dgnMinimapTexIndexOffset; // dungeon minimap texture index offset - /* 0x24 */ u16* owMinimapTexSize; - /* 0x28 */ u16* owMinimapTexOffset; /* 0x2C */ s16* owMinimapPosX; /* 0x30 */ s16* owMinimapPosY; /* 0x34 */ s16 (*owCompassInfo)[4]; // [X scale, Y scale, X offset, Y offset] diff --git a/soh/soh.xcodeproj/project.pbxproj b/soh/soh.xcodeproj/project.pbxproj index e5b56cb72..a20ba8db4 100644 --- a/soh/soh.xcodeproj/project.pbxproj +++ b/soh/soh.xcodeproj/project.pbxproj @@ -6668,10 +6668,12 @@ "$(inherited)", "-DENABLE_OPENGL", "-DNDEBUG", + "-DSPDLOG_ACTIVE_LEVEL=0", ); OTHER_CPLUSPLUSFLAGS = ( "-DENABLE_OPENGL", "-DNDEBUG", + "-DSPDLOG_ACTIVE_LEVEL=0", ); OTHER_LIBTOOLFLAGS = ""; OTHER_REZFLAGS = ""; @@ -6728,10 +6730,12 @@ "$(inherited)", "-DENABLE_OPENGL", "-D_DEBUG", + "-DSPDLOG_ACTIVE_LEVEL=0", ); OTHER_CPLUSPLUSFLAGS = ( "-DENABLE_OPENGL", "-D_DEBUG", + "-DSPDLOG_ACTIVE_LEVEL=0", ); OTHER_LIBTOOLFLAGS = ""; OTHER_REZFLAGS = ""; @@ -6842,7 +6846,6 @@ "-DENABLE_OPENGL", "-D_CRT_SECURE_NO_WARNINGS", "-D_CONSOLE", - "-DSPDLOG_ACTIVE_LEVEL=0", "-DNDEBUG", ); OTHER_LDFLAGS = ( @@ -7031,7 +7034,6 @@ "-DENABLE_OPENGL", "-D_CRT_SECURE_NO_WARNINGS", "-D_CONSOLE", - "-DSPDLOG_ACTIVE_LEVEL=0", "-D_DEBUG", ); OTHER_LDFLAGS = ( diff --git a/soh/soh.xcodeproj/xcshareddata/xcschemes/soh.xcscheme b/soh/soh.xcodeproj/xcshareddata/xcschemes/soh.xcscheme new file mode 100644 index 000000000..86e5eaeeb --- /dev/null +++ b/soh/soh.xcodeproj/xcshareddata/xcschemes/soh.xcscheme @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/soh/GbiWrap.cpp b/soh/soh/GbiWrap.cpp index 9f71f1717..cf33ed547 100644 --- a/soh/soh/GbiWrap.cpp +++ b/soh/soh/GbiWrap.cpp @@ -17,6 +17,9 @@ void ResourceMgr_CacheDirectory(const char* resName); void ResourceMgr_LoadFile(const char* resName); char* ResourceMgr_LoadFileFromDisk(const char* filePath); char* ResourceMgr_LoadTexByName(char* texPath); +uint16_t ResourceMgr_LoadTexWidthByName(char* texPath); +uint16_t ResourceMgr_LoadTexHeightByName(char* texPath); +uint32_t ResourceMgr_LoadTexSizeByName(char* texPath); char* ResourceMgr_LoadTexOrDListByName(char* filePath); char* ResourceMgr_LoadPlayerAnimByName(char* animPath); char* ResourceMgr_GetNameByCRC(uint64_t crc, char* alloc); diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 053d2d801..f611909b1 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -452,6 +452,12 @@ extern "C" char* ResourceMgr_LoadJPEG(char* data, int dataSize) extern "C" char* ResourceMgr_LoadTexByName(const char* texPath); +extern "C" uint16_t ResourceMgr_LoadTexWidthByName(char* texPath); + +extern "C" uint16_t ResourceMgr_LoadTexHeightByName(char* texPath); + +extern "C" uint32_t ResourceMgr_LoadTexSizeByName(const char* texPath); + extern "C" char* ResourceMgr_LoadTexOrDListByName(const char* filePath) { auto res = OTRGlobals::Instance->context->GetResourceManager()->LoadResource(filePath); diff --git a/soh/soh/OTRGlobals.h b/soh/soh/OTRGlobals.h index 2bee6819d..d03c913e1 100644 --- a/soh/soh/OTRGlobals.h +++ b/soh/soh/OTRGlobals.h @@ -44,6 +44,9 @@ void ResourceMgr_LoadFile(const char* resName); char* ResourceMgr_LoadFileFromDisk(const char* filePath); char* ResourceMgr_LoadJPEG(char* data, int dataSize); char* ResourceMgr_LoadTexByName(const char* texPath); +uint16_t ResourceMgr_LoadTexWidthByName(char* texPath); +uint16_t ResourceMgr_LoadTexHeightByName(char* texPath); +uint32_t ResourceMgr_LoadTexSizeByName(char* texPath); char* ResourceMgr_LoadTexOrDListByName(const char* filePath); char* ResourceMgr_LoadPlayerAnimByName(const char* animPath); AnimationHeaderCommon* ResourceMgr_LoadAnimByName(const char* path); diff --git a/soh/src/code/z_construct.c b/soh/src/code/z_construct.c index 96915d919..08497fe1c 100644 --- a/soh/src/code/z_construct.c +++ b/soh/src/code/z_construct.c @@ -8,7 +8,6 @@ void func_80110990(GlobalContext* globalCtx) { void func_801109B0(GlobalContext* globalCtx) { InterfaceContext* interfaceCtx = &globalCtx->interfaceCtx; u32 parameterSize; - u16 doActionOffset; u8 temp; gSaveContext.sunsSongState = SUNSSONG_INACTIVE; @@ -49,30 +48,11 @@ void func_801109B0(GlobalContext* globalCtx) { ASSERT(interfaceCtx->doActionSegment != NULL); - if (gSaveContext.language == LANGUAGE_ENG) { - doActionOffset = 0; - } else if (gSaveContext.language == LANGUAGE_GER) { - doActionOffset = 0x2B80; - } else { - doActionOffset = 0x5700; - } + uint32_t attackDoActionTexSize = ResourceMgr_LoadTexSizeByName(gAttackDoActionENGTex); + memcpy(interfaceCtx->doActionSegment, ResourceMgr_LoadTexByName(gAttackDoActionENGTex), attackDoActionTexSize); + memcpy(interfaceCtx->doActionSegment + (attackDoActionTexSize / 2), ResourceMgr_LoadTexByName(gCheckDoActionENGTex), attackDoActionTexSize); - memcpy(interfaceCtx->doActionSegment, ResourceMgr_LoadTexByName(gAttackDoActionENGTex), 0x180); - memcpy(interfaceCtx->doActionSegment + 0x180, ResourceMgr_LoadTexByName(gCheckDoActionENGTex), 0x180); - //DmaMgr_SendRequest1(interfaceCtx->doActionSegment, (uintptr_t)_do_action_staticSegmentRomStart + doActionOffset, 0x300, - //__FILE__, __LINE__); - - if (gSaveContext.language == LANGUAGE_ENG) { - doActionOffset = 0x480; - } else if (gSaveContext.language == LANGUAGE_GER) { - doActionOffset = 0x3000; - } else { - doActionOffset = 0x5B80; - } - - memcpy(interfaceCtx->doActionSegment + 0x300, ResourceMgr_LoadTexByName(gReturnDoActionENGTex), 0x180); - //DmaMgr_SendRequest1(interfaceCtx->doActionSegment + 0x300, (uintptr_t)_do_action_staticSegmentRomStart + doActionOffset, - //0x180); + memcpy(interfaceCtx->doActionSegment + attackDoActionTexSize, ResourceMgr_LoadTexByName(gReturnDoActionENGTex), ResourceMgr_LoadTexSizeByName(gReturnDoActionENGTex)); interfaceCtx->iconItemSegment = GAMESTATE_ALLOC_MC( &globalCtx->state, 0x1000 * ARRAY_COUNT(gSaveContext.equips.buttonItems)); diff --git a/soh/src/code/z_map_data.c b/soh/src/code/z_map_data.c index f518a124c..f76a3b4ce 100644 --- a/soh/src/code/z_map_data.c +++ b/soh/src/code/z_map_data.c @@ -184,16 +184,6 @@ static u16 sDgnMinimapTexIndexOffset[10] = { 0, 13, 32, 49, 76, 114, 158, 190, 217, 227, }; -static u16 sOwMinimapTexSize[24] = { - 2920, 2560, 1560, 2784, 2976, 2040, 3240, 2336, 2080, 2600, 1792, 1888, - 3400, 1792, 1888, 2040, 3120, 2304, 2176, 1888, 1560, 3240, 2600, 3400, -}; - -static u16 sOwMinimapTexOffset[24] = { - 0x0000, 0x0B68, 0x1568, 0x1B80, 0x2660, 0x3200, 0x39F8, 0x46A0, 0x4FC0, 0x57E0, 0x6208, 0x6908, - 0x7068, 0x7DB0, 0x84B0, 0x8C10, 0x9408, 0xA038, 0xA938, 0xB1B8, 0xB918, 0xBF30, 0xCBD8, 0xD600, -}; - static s16 sOwMinimapPosX[24] = { 216, 216, 218, 202, 202, 250, 216, 234, 234, 216, 234, 234, 216, 234, 234, 250, 216, 234, 234, 234, 218, 80, 80, 216, @@ -319,14 +309,13 @@ static u8 sFloorID[10][8] = { static s16 sSkullFloorIconY[10] = { -47, -47, -33, -47, -47, -5, -19, -47, -99, -99 }; MapData gMapDataTable = { - sFloorTexIndexOffset, sBossFloor, sRoomPalette, - sMaxPaletteCount, sPaletteRoom, sRoomCompassOffsetX, - sRoomCompassOffsetY, sDgnMinimapCount, sDgnMinimapTexIndexOffset, - sOwMinimapTexSize, sOwMinimapTexOffset, sOwMinimapPosX, - sOwMinimapPosY, sOwCompassInfo, sDgnMinimapTexIndexBase, - sDgnCompassInfo, sOwMinimapWidth, sOwMinimapHeight, - sOwEntranceIconPosX, sOwEntranceIconPosY, sOwEntranceFlag, - sFloorCoordY, sSwitchEntryCount, sSwitchFromRoom, - sSwitchFromFloor, sSwitchToRoom, sFloorID, - sSkullFloorIconY, + sFloorTexIndexOffset, sBossFloor, sRoomPalette, + sMaxPaletteCount, sPaletteRoom, sRoomCompassOffsetX, + sRoomCompassOffsetY, sDgnMinimapCount, sDgnMinimapTexIndexOffset, + sOwMinimapPosX, sOwMinimapPosY, sOwCompassInfo, + sDgnMinimapTexIndexBase, sDgnCompassInfo, sOwMinimapWidth, + sOwMinimapHeight, sOwEntranceIconPosX, sOwEntranceIconPosY, + sOwEntranceFlag, sFloorCoordY, sSwitchEntryCount, + sSwitchFromRoom, sSwitchFromFloor, sSwitchToRoom, + sFloorID, sSkullFloorIconY, }; diff --git a/soh/src/code/z_map_exp.c b/soh/src/code/z_map_exp.c index 6572f6fc1..c9b927730 100644 --- a/soh/src/code/z_map_exp.c +++ b/soh/src/code/z_map_exp.c @@ -412,8 +412,10 @@ void Map_InitData(GlobalContext* globalCtx, s16 room) { //(uintptr_t)_map_grand_staticSegmentRomStart + gMapData->owMinimapTexOffset[extendedMapIndex], //gMapData->owMinimapTexSize[mapIndex], __FILE__, __LINE__); - if (sEntranceIconMapIndex < 24) - memcpy(globalCtx->interfaceCtx.mapSegment, ResourceMgr_LoadTexByName(minimapTableOW[sEntranceIconMapIndex]), gMapData->owMinimapTexSize[mapIndex]); + if (sEntranceIconMapIndex < 24) { + const char* textureName = minimapTableOW[sEntranceIconMapIndex]; + memcpy(globalCtx->interfaceCtx.mapSegment, ResourceMgr_LoadTexByName(textureName), ResourceMgr_LoadTexSizeByName(textureName)); + } interfaceCtx->unk_258 = mapIndex; break; @@ -445,7 +447,8 @@ void Map_InitData(GlobalContext* globalCtx, s16 room) { //((gMapData->dgnMinimapTexIndexOffset[mapIndex] + room) * 0xFF0), //0xFF0, __FILE__, __LINE__); - memcpy(globalCtx->interfaceCtx.mapSegment, ResourceMgr_LoadTexByName(minimapTableDangeon[gMapData->dgnMinimapTexIndexOffset[mapIndex] + room]), 0xFF0); + const char* textureName = minimapTableDangeon[gMapData->dgnMinimapTexIndexOffset[mapIndex] + room]; + memcpy(globalCtx->interfaceCtx.mapSegment, ResourceMgr_LoadTexByName(textureName), ResourceMgr_LoadTexSizeByName(textureName)); R_COMPASS_OFFSET_X = gMapData->roomCompassOffsetX[mapIndex][room]; R_COMPASS_OFFSET_Y = gMapData->roomCompassOffsetY[mapIndex][room]; diff --git a/soh/src/code/z_message_PAL.c b/soh/src/code/z_message_PAL.c index a91dd5e41..afc69e814 100644 --- a/soh/src/code/z_message_PAL.c +++ b/soh/src/code/z_message_PAL.c @@ -1196,7 +1196,7 @@ void Message_LoadItemIcon(GlobalContext* globalCtx, u16 itemId, s16 y) { R_TEXTBOX_ICON_YPOS = y + 6; R_TEXTBOX_ICON_SIZE = 32; memcpy((uintptr_t)msgCtx->textboxSegment + MESSAGE_STATIC_TEX_SIZE, - ResourceMgr_LoadTexByName(gItemIcons[itemId]), 0x1000); + ResourceMgr_LoadTexByName(gItemIcons[itemId]), ResourceMgr_LoadTexSizeByName(gItemIcons[itemId])); // "Item 32-0" osSyncPrintf("アイテム32-0\n"); } else { @@ -1204,7 +1204,7 @@ void Message_LoadItemIcon(GlobalContext* globalCtx, u16 itemId, s16 y) { R_TEXTBOX_ICON_YPOS = y + 10; R_TEXTBOX_ICON_SIZE = 24; memcpy((uintptr_t)msgCtx->textboxSegment + MESSAGE_STATIC_TEX_SIZE, - ResourceMgr_LoadTexByName(gItemIcons[itemId]), 0x900); + ResourceMgr_LoadTexByName(gItemIcons[itemId]), ResourceMgr_LoadTexSizeByName(gItemIcons[itemId])); // "Item 24" osSyncPrintf("アイテム24=%d (%d) {%d}\n", itemId, itemId - ITEM_KOKIRI_EMERALD, 84); } @@ -1565,9 +1565,9 @@ void Message_Decode(GlobalContext* globalCtx) { msgCtx->textboxBackgroundUnkArg = font->msgBuf[msgCtx->msgBufPos + 3] & 0xF; memcpy((uintptr_t)msgCtx->textboxSegment + MESSAGE_STATIC_TEX_SIZE, - ResourceMgr_LoadTexByName(gRedMessageXLeftTex), 0x900); + ResourceMgr_LoadTexByName(gRedMessageXLeftTex), ResourceMgr_LoadTexSizeByName(gRedMessageXLeftTex)); memcpy((uintptr_t)msgCtx->textboxSegment + MESSAGE_STATIC_TEX_SIZE + 0x900, - ResourceMgr_LoadTexByName(gRedMessageXRightTex), 0x900); + ResourceMgr_LoadTexByName(gRedMessageXRightTex), ResourceMgr_LoadTexSizeByName(gRedMessageXRightTex)); msgCtx->msgBufPos += 3; R_TEXTBOX_BG_YPOS = R_TEXTBOX_Y + 8; @@ -1750,7 +1750,8 @@ void Message_OpenText(GlobalContext* globalCtx, u16 textId) { // "Text Box Type" osSyncPrintf("吹き出し種類=%d\n", msgCtx->textBoxType); if (textBoxType < TEXTBOX_TYPE_NONE_BOTTOM) { - memcpy(msgCtx->textboxSegment, ResourceMgr_LoadTexByName(msgStaticTbl[messageStaticIndices[textBoxType]]), MESSAGE_STATIC_TEX_SIZE); + const char* textureName = msgStaticTbl[messageStaticIndices[textBoxType]]; + memcpy(msgCtx->textboxSegment, ResourceMgr_LoadTexByName(textureName), MESSAGE_STATIC_TEX_SIZE); if (textBoxType == TEXTBOX_TYPE_BLACK) { msgCtx->textboxColorRed = 0; msgCtx->textboxColorGreen = 0; diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index 2a4921d7f..40f2c2678 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -10,10 +10,31 @@ #include #endif -// TODO extract this information from the texture definitions themselves -#define DO_ACTION_TEX_WIDTH 48 -#define DO_ACTION_TEX_HEIGHT 16 -#define DO_ACTION_TEX_SIZE ((DO_ACTION_TEX_WIDTH * DO_ACTION_TEX_HEIGHT) / 2) // (sizeof(gCheckDoActionENGTex)) + +static uint16_t _doActionTexWidth, _doActionTexHeight = -1; +static uint16_t DO_ACTION_TEX_WIDTH() { + return 48; + + // TODO: Figure out why Ship::Texture is not returning a valid width + if (_doActionTexWidth == -1) + _doActionTexWidth = ResourceMgr_LoadTexWidthByName(gCheckDoActionENGTex); + return _doActionTexWidth; +} +static uint16_t DO_ACTION_TEX_HEIGHT() { + return 16; + + // TODO: Figure out why Ship::Texture is not returning a valid height + if (_doActionTexHeight == -1) + _doActionTexHeight = ResourceMgr_LoadTexHeightByName(gCheckDoActionENGTex); + return _doActionTexHeight; +} + +static uint32_t _doActionTexSize = -1; +static uint32_t DO_ACTION_TEX_SIZE() { + if (_doActionTexSize == -1) + _doActionTexSize = ResourceMgr_LoadTexSizeByName(gCheckDoActionENGTex); + return _doActionTexSize; +} // The button statuses include the A button when most things are only the equip item buttons // So, when indexing into it with a item button index, we need to adjust @@ -2457,8 +2478,8 @@ void Interface_LoadActionLabel(InterfaceContext* interfaceCtx, u16 action, s16 l if (action != DO_ACTION_NONE) { //osCreateMesgQueue(&interfaceCtx->loadQueue, &interfaceCtx->loadMsg, OS_MESG_BLOCK); - memcpy(interfaceCtx->doActionSegment + (loadOffset * DO_ACTION_TEX_SIZE), ResourceMgr_LoadTexByName(doAction), - DO_ACTION_TEX_SIZE); + memcpy(interfaceCtx->doActionSegment + (loadOffset * DO_ACTION_TEX_SIZE()), ResourceMgr_LoadTexByName(doAction), + DO_ACTION_TEX_SIZE()); //DmaMgr_SendRequest2(&interfaceCtx->dmaRequest_160, //interfaceCtx->doActionSegment + (loadOffset * DO_ACTION_TEX_SIZE), //(uintptr_t)_do_action_staticSegmentRomStart + (action * DO_ACTION_TEX_SIZE), DO_ACTION_TEX_SIZE, @@ -2467,7 +2488,7 @@ void Interface_LoadActionLabel(InterfaceContext* interfaceCtx, u16 action, s16 l } else { gSegments[7] = VIRTUAL_TO_PHYSICAL(interfaceCtx->doActionSegment); //func_80086D5C(SEGMENTED_TO_VIRTUAL(sDoActionTextures[loadOffset]), DO_ACTION_TEX_SIZE / 4); - func_80086D5C(interfaceCtx->doActionSegment + (loadOffset * DO_ACTION_TEX_SIZE), DO_ACTION_TEX_SIZE / 4); + func_80086D5C(interfaceCtx->doActionSegment + (loadOffset * DO_ACTION_TEX_SIZE()), DO_ACTION_TEX_SIZE() / 4); } } @@ -2545,7 +2566,7 @@ void Interface_LoadActionLabelB(GlobalContext* globalCtx, u16 action) { // OTRTODO osCreateMesgQueue(&interfaceCtx->loadQueue, &interfaceCtx->loadMsg, OS_MESG_BLOCK); - memcpy(interfaceCtx->doActionSegment + DO_ACTION_TEX_SIZE, ResourceMgr_LoadTexByName(doAction), DO_ACTION_TEX_SIZE); + memcpy(interfaceCtx->doActionSegment + DO_ACTION_TEX_SIZE(), ResourceMgr_LoadTexByName(doAction), DO_ACTION_TEX_SIZE()); //DmaMgr_SendRequest2(&interfaceCtx->dmaRequest_160, interfaceCtx->doActionSegment + DO_ACTION_TEX_SIZE, //(uintptr_t)_do_action_staticSegmentRomStart + (action * DO_ACTION_TEX_SIZE), DO_ACTION_TEX_SIZE, 0, //&interfaceCtx->loadQueue, NULL, __FILE__, __LINE__); @@ -3181,7 +3202,7 @@ void func_80088B34(s16 arg0) { void Interface_DrawActionLabel(GraphicsContext* gfxCtx, void* texture) { OPEN_DISPS(gfxCtx); - gDPLoadTextureBlock_4b(OVERLAY_DISP++, texture, G_IM_FMT_IA, DO_ACTION_TEX_WIDTH, DO_ACTION_TEX_HEIGHT, 0, + gDPLoadTextureBlock_4b(OVERLAY_DISP++, texture, 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); @@ -3254,8 +3275,8 @@ void Interface_DrawItemButtons(GlobalContext* globalCtx) { const s16 rStartLabelY_ori = R_START_LABEL_Y(gSaveContext.language)+Y_Margins_StartBtn; const s16 PosX_StartBtn_ori = OTRGetRectDimensionFromRightEdge(startButtonLeftPos[gSaveContext.language]+X_Margins_StartBtn); const s16 PosY_StartBtn_ori = 16+Y_Margins_StartBtn; - s16 StartBTN_Label_W = DO_ACTION_TEX_WIDTH; - s16 StartBTN_Label_H = DO_ACTION_TEX_HEIGHT; + s16 StartBTN_Label_W = DO_ACTION_TEX_WIDTH(); + s16 StartBTN_Label_H = DO_ACTION_TEX_HEIGHT(); int StartBTN_Label_H_Scaled = StartBTN_Label_H * 1.0f; int StartBTN_Label_W_Scaled = StartBTN_Label_W * 1.0f; int StartBTN_Label_W_factor = (1 << 10) * StartBTN_Label_W / StartBTN_Label_W_Scaled; @@ -3511,10 +3532,11 @@ void Interface_DrawItemButtons(GlobalContext* globalCtx) { } 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, + 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); //const s16 rStartLabelX = OTRGetRectDimensionFromRightEdge(R_START_LABEL_X(gSaveContext.language)+Right_HUD_Margin); @@ -4330,7 +4352,7 @@ void Interface_Draw(GlobalContext* globalCtx) { // Invalidate Do Action textures as they may have changed gSPInvalidateTexCache(OVERLAY_DISP++, interfaceCtx->doActionSegment); - gSPInvalidateTexCache(OVERLAY_DISP++, interfaceCtx->doActionSegment + DO_ACTION_TEX_SIZE); + gSPInvalidateTexCache(OVERLAY_DISP++, interfaceCtx->doActionSegment + DO_ACTION_TEX_SIZE()); gSPSegment(OVERLAY_DISP++, 0x02, interfaceCtx->parameterSegment); gSPSegment(OVERLAY_DISP++, 0x07, interfaceCtx->doActionSegment); @@ -4630,14 +4652,14 @@ void Interface_Draw(GlobalContext* globalCtx) { PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0); gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 255, 255, 255, interfaceCtx->bAlpha); - gDPLoadTextureBlock_4b(OVERLAY_DISP++, interfaceCtx->doActionSegment + DO_ACTION_TEX_SIZE, G_IM_FMT_IA, - DO_ACTION_TEX_WIDTH, DO_ACTION_TEX_HEIGHT, 0, G_TX_NOMIRROR | G_TX_WRAP, + gDPLoadTextureBlock_4b(OVERLAY_DISP++, interfaceCtx->doActionSegment + DO_ACTION_TEX_SIZE(), 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); R_B_LABEL_DD = (1 << 10) / (WREG(37 + gSaveContext.language) / 100.0f); gSPWideTextureRectangle(OVERLAY_DISP++, BbtnPosX << 2, BbtnPosY << 2, - (BbtnPosX + DO_ACTION_TEX_WIDTH) << 2, - (BbtnPosY + DO_ACTION_TEX_HEIGHT) << 2, G_TX_RENDERTILE, 0, 0, + (BbtnPosX + DO_ACTION_TEX_WIDTH()) << 2, + (BbtnPosY + DO_ACTION_TEX_HEIGHT()) << 2, G_TX_RENDERTILE, 0, 0, R_B_LABEL_DD, R_B_LABEL_DD); } @@ -4846,7 +4868,7 @@ void Interface_Draw(GlobalContext* globalCtx) { if ((interfaceCtx->unk_1EC < 2) || (interfaceCtx->unk_1EC == 3)) { Interface_DrawActionLabel(globalCtx->state.gfxCtx, interfaceCtx->doActionSegment); } else { - Interface_DrawActionLabel(globalCtx->state.gfxCtx, interfaceCtx->doActionSegment + DO_ACTION_TEX_SIZE); + Interface_DrawActionLabel(globalCtx->state.gfxCtx, interfaceCtx->doActionSegment + DO_ACTION_TEX_SIZE()); } gDPPipeSync(OVERLAY_DISP++); 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 9071e7a0f..2735ed9b4 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 @@ -2110,7 +2110,8 @@ void KaleidoScope_UpdateNamePanel(GlobalContext* globalCtx) { sp2A += 12; } - memcpy(pauseCtx->nameSegment, ResourceMgr_LoadTexByName(mapNameTextures[sp2A]), 0x400); + const char* textureName = mapNameTextures[sp2A]; + memcpy(pauseCtx->nameSegment, ResourceMgr_LoadTexByName(textureName), ResourceMgr_LoadTexSizeByName(textureName)); } else { osSyncPrintf("zoom_name=%d\n", pauseCtx->namedItem); @@ -2123,7 +2124,8 @@ void KaleidoScope_UpdateNamePanel(GlobalContext* globalCtx) { osSyncPrintf("J_N=%d point=%d\n", gSaveContext.language, sp2A); - memcpy(pauseCtx->nameSegment, ResourceMgr_LoadTexByName(iconNameTextures[sp2A]), 0x400); + const char* textureName = iconNameTextures[sp2A]; + memcpy(pauseCtx->nameSegment, ResourceMgr_LoadTexByName(textureName), ResourceMgr_LoadTexSizeByName(textureName)); } pauseCtx->nameDisplayTimer = 0; @@ -3224,8 +3226,12 @@ void KaleidoScope_UpdateCursorSize(PauseContext* pauseCtx) { void KaleidoScope_LoadDungeonMap(GlobalContext* globalCtx) { InterfaceContext* interfaceCtx = &globalCtx->interfaceCtx; - memcpy(interfaceCtx->mapSegment, ResourceMgr_LoadTexByName(sDungeonMapTexs[R_MAP_TEX_INDEX]), 0x800); - memcpy(interfaceCtx->mapSegment + 0x800, ResourceMgr_LoadTexByName(sDungeonMapTexs[R_MAP_TEX_INDEX + 1]), 0x800); + char* firstTextureName = sDungeonMapTexs[R_MAP_TEX_INDEX]; + char* secondTextureName = sDungeonMapTexs[R_MAP_TEX_INDEX + 1]; + uint32_t firstTextureSize = ResourceMgr_LoadTexSizeByName(firstTextureName); + + memcpy(interfaceCtx->mapSegment, ResourceMgr_LoadTexByName(firstTextureName), ResourceMgr_LoadTexSizeByName(firstTextureName)); + memcpy(interfaceCtx->mapSegment + (firstTextureSize / 2), ResourceMgr_LoadTexByName(secondTextureName), ResourceMgr_LoadTexSizeByName(secondTextureName)); } void KaleidoScope_UpdateDungeonMap(GlobalContext* globalCtx) { @@ -3403,11 +3409,14 @@ void KaleidoScope_Update(GlobalContext* globalCtx) if (((void)0, gSaveContext.worldMapArea) < 22) { if (gSaveContext.language == LANGUAGE_ENG) { - memcpy(pauseCtx->nameSegment + 0x400, ResourceMgr_LoadTexByName(mapNameTextures[36 + gSaveContext.worldMapArea]), 0xA00); + const char* textureName = mapNameTextures[36 + gSaveContext.worldMapArea]; + memcpy(pauseCtx->nameSegment + 0x400, ResourceMgr_LoadTexByName(textureName), ResourceMgr_LoadTexSizeByName(textureName)); } else if (gSaveContext.language == LANGUAGE_GER) { - memcpy(pauseCtx->nameSegment + 0x400, ResourceMgr_LoadTexByName(mapNameTextures[58 + gSaveContext.worldMapArea]), 0xA00); + const char* textureName = mapNameTextures[58 + gSaveContext.worldMapArea]; + memcpy(pauseCtx->nameSegment + 0x400, ResourceMgr_LoadTexByName(textureName), ResourceMgr_LoadTexSizeByName(textureName)); } else { - memcpy(pauseCtx->nameSegment + 0x400, ResourceMgr_LoadTexByName(mapNameTextures[80 + gSaveContext.worldMapArea]), 0xA00); + const char* textureName = mapNameTextures[80 + gSaveContext.worldMapArea]; + memcpy(pauseCtx->nameSegment + 0x400, ResourceMgr_LoadTexByName(textureName), ResourceMgr_LoadTexSizeByName(textureName)); } } // OTRTODO - player on pause From b98c8b4abb38aa26300f436827bfbf35e4a07904 Mon Sep 17 00:00:00 2001 From: Sarge-117 <108380086+Sarge-117@users.noreply.github.com> Date: Sun, 31 Jul 2022 18:35:05 -0700 Subject: [PATCH 13/25] Minor enhancement: Allow toggling on equipment screen (#813) * Allow Equipment Toggle Allow player to toggle equipment on/off on the equipment subscreen. For tunics and boots, this will revert them to Kokiri Tunic/Kokiri Boots. For shields, it will un-equip the shield entirely. For swords, only BGS/Giant's Knife is affected, and it will revert to Master Sword. * Set up Cvar and check for MS Set up the cvar/imgui and add a check that we own the Master Sword (in case we're in the Ganon fight) --- libultraship/libultraship/ImGuiImpl.cpp | 2 + .../ovl_kaleido_scope/z_kaleido_equipment.c | 39 ++++++++++++++++++- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/libultraship/libultraship/ImGuiImpl.cpp b/libultraship/libultraship/ImGuiImpl.cpp index 8997f6192..da3469301 100644 --- a/libultraship/libultraship/ImGuiImpl.cpp +++ b/libultraship/libultraship/ImGuiImpl.cpp @@ -1140,6 +1140,8 @@ namespace SohImGui { Tooltip("Displays an icon and plays a sound when Stone of Agony\nshould be activated, for those without rumble"); EnhancementCheckbox("Assignable Tunics and Boots", "gAssignableTunicsAndBoots"); Tooltip("Allows equipping the tunic and boots to c-buttons"); + EnhancementCheckbox("Equipment Toggle", "gEquipmentCanBeRemoved"); + Tooltip("Allows equipment to be removed by toggling it off on\nthe equipment subscreen."); EnhancementCheckbox("Link's Cow in Both Time Periods", "gCowOfTime"); Tooltip("Allows the Lon Lon Ranch obstacle course reward to be\nshared across time periods"); EnhancementCheckbox("Enable visible guard vision", "gGuardVision"); 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 edcc21c07..eaa2bb24a 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 @@ -515,12 +515,49 @@ void KaleidoScope_DrawEquipment(GlobalContext* globalCtx) { (gEquipAgeReqs[pauseCtx->cursorY[PAUSE_EQUIP]][pauseCtx->cursorX[PAUSE_EQUIP]] == ((void)0, gSaveContext.linkAge))) { if (CHECK_BTN_ALL(input->press.button, BTN_A)) { + + // Allow Link to remove his equipment from the equipment subscreen by toggling on/off + // Shields will be un-equipped entirely, and tunics/boots will revert to Kokiri Tunic/Kokiri Boots + // Only BGS/Giant's Knife is affected, and it will revert to Master Sword. + + // If we have the feature toggled on + if (CVar_GetS32("gEquipmentCanBeRemoved", 0)) { + + // If we're on the "swords" section of the equipment screen AND we're on a currently-equipped BGS/Giant's Knife + if (pauseCtx->cursorY[PAUSE_EQUIP] == 0 && pauseCtx->cursorX[PAUSE_EQUIP] == 3 + && CUR_EQUIP_VALUE(EQUIP_SWORD) == 3 && CHECK_OWNED_EQUIP(0,1)){ // And we have the Master Sword + Inventory_ChangeEquipment(EQUIP_SWORD, 2); // "Unequip" it by equipping Master Sword + gSaveContext.equips.buttonItems[0] = ITEM_SWORD_MASTER; + gSaveContext.infTable[29] = 0; + goto RESUME_EQUIPMENT_SWORD; // Skip to here so we don't re-equip it + } + + // If we're on the "shields" section of the equipment screen AND we're on a currently-equipped shield + if (pauseCtx->cursorY[PAUSE_EQUIP] == 1 && pauseCtx->cursorX[PAUSE_EQUIP] == CUR_EQUIP_VALUE(EQUIP_SHIELD)) { + Inventory_ChangeEquipment(EQUIP_SHIELD, 0); // Unequip it + goto RESUME_EQUIPMENT; // Skip to here so we don't re-equip it + } + + // If we're on the "tunics" section of the equipment screen AND we're on a currently-equipped tunic + if (pauseCtx->cursorY[PAUSE_EQUIP] == 2 && pauseCtx->cursorX[PAUSE_EQUIP] == CUR_EQUIP_VALUE(EQUIP_TUNIC)) { + Inventory_ChangeEquipment(EQUIP_TUNIC, 1); // "Unequip" it (by equipping Kokiri Tunic) + goto RESUME_EQUIPMENT; // Skip to here so we don't re-equip it + } + + // If we're on the "boots" section of the equipment screen AND we're on currently-equipped boots + if (pauseCtx->cursorY[PAUSE_EQUIP] == 3 && pauseCtx->cursorX[PAUSE_EQUIP] == CUR_EQUIP_VALUE(EQUIP_BOOTS)) { + Inventory_ChangeEquipment(EQUIP_BOOTS, 1); // "Unequip" it (by equipping Kokiri Boots) + goto RESUME_EQUIPMENT; // Skip to here so we don't re-equip it + } + } + if (CHECK_OWNED_EQUIP(pauseCtx->cursorY[PAUSE_EQUIP], pauseCtx->cursorX[PAUSE_EQUIP] - 1)) { Inventory_ChangeEquipment(pauseCtx->cursorY[PAUSE_EQUIP], pauseCtx->cursorX[PAUSE_EQUIP]); } else { goto EQUIP_FAIL; } + RESUME_EQUIPMENT: if (pauseCtx->cursorY[PAUSE_EQUIP] == 0) { gSaveContext.infTable[29] = 0; gSaveContext.equips.buttonItems[0] = cursorItem; @@ -537,7 +574,7 @@ void KaleidoScope_DrawEquipment(GlobalContext* globalCtx) { gSaveContext.equips.buttonItems[0] = ITEM_SWORD_KNIFE; } } - + RESUME_EQUIPMENT_SWORD: Interface_LoadItemIcon1(globalCtx, 0); } From 361a986b8e2ba7e03ac6fc995fed6b33033c87f1 Mon Sep 17 00:00:00 2001 From: vaguerant Date: Mon, 1 Aug 2022 11:37:47 +1000 Subject: [PATCH 14/25] Add bottle swipes to Fast Drops; rename to Skip Pickup Messages (#847) * Add bottle-swipes to Fast Drops; rename to Fast Pickups * More freecam friendly * Resolve freecam interaction * Rename to "Skip Pickup Messages" --- libultraship/libultraship/ImGuiImpl.cpp | 4 ++-- soh/src/overlays/actors/ovl_player_actor/z_player.c | 13 +++++++++---- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/libultraship/libultraship/ImGuiImpl.cpp b/libultraship/libultraship/ImGuiImpl.cpp index da3469301..9c7318b89 100644 --- a/libultraship/libultraship/ImGuiImpl.cpp +++ b/libultraship/libultraship/ImGuiImpl.cpp @@ -995,8 +995,8 @@ namespace SohImGui { Tooltip("Wearing the Bunny Hood grants a speed\nincrease like in Majora's Mask"); EnhancementCheckbox("Fast Chests", "gFastChests"); Tooltip("Kick open every chest"); - EnhancementCheckbox("Fast Drops", "gFastDrops"); - Tooltip("Skip first-time pickup messages for consumable items"); + EnhancementCheckbox("Skip Pickup Messages", "gFastDrops"); + Tooltip("Skip pickup messages for new consumable items and bottle swipes"); EnhancementCheckbox("Better Owl", "gBetterOwl"); Tooltip("The default response to Kaepora Gaebora is\nalways that you understood what he said"); EnhancementCheckbox("Fast Ocarina Playback", "gFastOcarinaPlayback"); 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 411647644..306a460d3 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -13129,7 +13129,10 @@ void func_8084ECA4(Player* this, GlobalContext* globalCtx) { if (LinkAnimation_Update(globalCtx, &this->skelAnime)) { if (this->unk_84F != 0) { if (this->unk_850 == 0) { - Message_StartTextbox(globalCtx, D_80854A04[this->unk_84F - 1].textId, &this->actor); + if (CVar_GetS32("gFastDrops", 0)) + { this->unk_84F = 0; } + else + { Message_StartTextbox(globalCtx, D_80854A04[this->unk_84F - 1].textId, &this->actor); } Audio_PlayFanfare(NA_BGM_ITEM_GET | 0x900); this->unk_850 = 1; } @@ -13165,11 +13168,13 @@ void func_8084ECA4(Player* this, GlobalContext* globalCtx) { if (i < 4) { this->unk_84F = i + 1; this->unk_850 = 0; - this->stateFlags1 |= PLAYER_STATE1_28 | PLAYER_STATE1_29; this->interactRangeActor->parent = &this->actor; Player_UpdateBottleHeld(globalCtx, this, catchInfo->itemId, ABS(catchInfo->actionParam)); - func_808322D0(globalCtx, this, sp24->unk_04); - func_80835EA4(globalCtx, 4); + if (!CVar_GetS32("gFastDrops", 0)) { + this->stateFlags1 |= PLAYER_STATE1_28 | PLAYER_STATE1_29; + func_808322D0(globalCtx, this, sp24->unk_04); + func_80835EA4(globalCtx, 4); + } } } } From 7dd6f59b8b3dd7c92cde95d1aa92f49c09664c6e Mon Sep 17 00:00:00 2001 From: PurpleHato Date: Mon, 1 Aug 2022 03:38:40 +0200 Subject: [PATCH 15/25] TWEAK: added 360hz support (#896) * FIX: Increased the maximum actor limit for draw distance Fix issue #529 * TWEAK: added 360hz support Has been asked by an user who have a fancy 360hz laptop refresh rate https://www.androidauthority.com/asus-rog-ces-2021-1191928/ * TWEAK: Forgot one value --- libultraship/libultraship/ImGuiImpl.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libultraship/libultraship/ImGuiImpl.cpp b/libultraship/libultraship/ImGuiImpl.cpp index 9c7318b89..c3b3f6432 100644 --- a/libultraship/libultraship/ImGuiImpl.cpp +++ b/libultraship/libultraship/ImGuiImpl.cpp @@ -900,7 +900,7 @@ namespace SohImGui { { const char* cvar = "gExtraLatencyThreshold"; int val = CVar_GetS32(cvar, 80); - val = MAX(MIN(val, 250), 0); + val = MAX(MIN(val, 360), 0); int fps = val; if (fps == 0) @@ -922,7 +922,7 @@ namespace SohImGui { ImGui::SameLine(); ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); - if (ImGui::SliderInt("##ExtraLatencyThreshold", &val, 0, 250, "", ImGuiSliderFlags_AlwaysClamp)) + if (ImGui::SliderInt("##ExtraLatencyThreshold", &val, 0, 360, "", ImGuiSliderFlags_AlwaysClamp)) { CVar_SetS32(cvar, val); needs_save = true; @@ -1268,7 +1268,7 @@ namespace SohImGui { int maxFps = 60; #else int minFps = 20; - int maxFps = 250; + int maxFps = 360; #endif int val = CVar_GetS32(fps_cvar, minFps); @@ -1296,9 +1296,9 @@ namespace SohImGui { if (ImGui::SliderInt("##FPSInterpolation", &val, minFps, maxFps, "", ImGuiSliderFlags_AlwaysClamp)) { - if (val > 250) + if (val > 360) { - val = 250; + val = 360; } else if (val < 20) { @@ -1329,7 +1329,7 @@ namespace SohImGui { if (ImGui::Button("Match Refresh Rate")) { int hz = roundf(gfx_get_detected_hz()); - if (hz >= 20 && hz <= 250) + if (hz >= 20 && hz <= 360) { CVar_SetS32(fps_cvar, hz); needs_save = true; From 99ecccfaab796c093bfd2778e01fc02d170ef23b Mon Sep 17 00:00:00 2001 From: GaryOderNichts <12049776+GaryOderNichts@users.noreply.github.com> Date: Mon, 1 Aug 2022 03:39:24 +0200 Subject: [PATCH 16/25] Save scarecrow songs as OcarinaNotes (#918) --- soh/include/z64save.h | 5 +- soh/soh/SaveManager.cpp | 211 +++++++++++++++++++++++++++++++++++++--- soh/soh/SaveManager.h | 1 + 3 files changed, 202 insertions(+), 15 deletions(-) diff --git a/soh/include/z64save.h b/soh/include/z64save.h index e58d7a925..114de9fd4 100644 --- a/soh/include/z64save.h +++ b/soh/include/z64save.h @@ -3,6 +3,7 @@ #include "ultra64.h" #include "z64math.h" +#include "z64audio.h" #include "soh/Enhancements/randomizer/randomizerTypes.h" typedef struct { @@ -114,9 +115,9 @@ typedef struct { /* 0x0EF8 */ u16 infTable[30]; // "inf_table" /* 0x0F38 */ u32 worldMapAreaData; // "area_arrival" /* 0x0F40 */ u8 scarecrowCustomSongSet; - /* 0x0F41 */ u8 scarecrowCustomSong[0x360]; + /* 0x0F41 */ OcarinaNote scarecrowCustomSong[108]; /* 0x12C5 */ u8 scarecrowSpawnSongSet; - /* 0x12C6 */ u8 scarecrowSpawnSong[0x80]; + /* 0x12C6 */ OcarinaNote scarecrowSpawnSong[16]; /* 0x1346 */ char unk_1346[0x02]; /* 0x1348 */ HorseData horseData; /* 0x1354 */ s32 fileNum; // "file_no" diff --git a/soh/soh/SaveManager.cpp b/soh/soh/SaveManager.cpp index e0de89d09..4fe0b1cfd 100644 --- a/soh/soh/SaveManager.cpp +++ b/soh/soh/SaveManager.cpp @@ -22,7 +22,8 @@ std::filesystem::path SaveManager::GetFileName(int fileNum) { SaveManager::SaveManager() { AddLoadFunction("base", 1, LoadBaseVersion1); - AddSaveFunction("base", 1, SaveBase); + AddLoadFunction("base", 2, LoadBaseVersion2); + AddSaveFunction("base", 2, SaveBase); AddLoadFunction("randomizer", 1, LoadRandomizerVersion1); AddSaveFunction("randomizer", 1, SaveRandomizer); @@ -319,11 +320,23 @@ void SaveManager::InitFileNormal() { gSaveContext.worldMapAreaData = 0; gSaveContext.scarecrowCustomSongSet = 0; for (int i = 0; i < ARRAY_COUNT(gSaveContext.scarecrowCustomSong); i++) { - gSaveContext.scarecrowCustomSong[i] = 0; + gSaveContext.scarecrowCustomSong[i].noteIdx = 0; + gSaveContext.scarecrowCustomSong[i].unk_01 = 0; + gSaveContext.scarecrowCustomSong[i].unk_02 = 0; + gSaveContext.scarecrowCustomSong[i].volume = 0; + gSaveContext.scarecrowCustomSong[i].vibrato = 0; + gSaveContext.scarecrowCustomSong[i].tone = 0; + gSaveContext.scarecrowCustomSong[i].semitone = 0; } gSaveContext.scarecrowSpawnSongSet = 0; for (int i = 0; i < ARRAY_COUNT(gSaveContext.scarecrowSpawnSong); i++) { - gSaveContext.scarecrowSpawnSong[i] = 0; + gSaveContext.scarecrowSpawnSong[i].noteIdx = 0; + gSaveContext.scarecrowSpawnSong[i].unk_01 = 0; + gSaveContext.scarecrowSpawnSong[i].unk_02 = 0; + gSaveContext.scarecrowSpawnSong[i].volume = 0; + gSaveContext.scarecrowSpawnSong[i].vibrato = 0; + gSaveContext.scarecrowSpawnSong[i].tone = 0; + gSaveContext.scarecrowSpawnSong[i].semitone = 0; } gSaveContext.horseData.scene = SCENE_SPOT00; @@ -700,12 +713,172 @@ void SaveManager::LoadBaseVersion1() { }); SaveManager::Instance->LoadData("worldMapAreaData", gSaveContext.worldMapAreaData); SaveManager::Instance->LoadData("scarecrowCustomSongSet", gSaveContext.scarecrowCustomSongSet); + SaveManager::Instance->LoadArray("scarecrowCustomSong", sizeof(gSaveContext.scarecrowCustomSong), [](size_t i) { + SaveManager::Instance->LoadData("", ((u8*)&gSaveContext.scarecrowCustomSong)[i]); + }); + SaveManager::Instance->LoadData("scarecrowSpawnSongSet", gSaveContext.scarecrowSpawnSongSet); + SaveManager::Instance->LoadArray("scarecrowSpawnSong", sizeof(gSaveContext.scarecrowSpawnSong), [](size_t i) { + SaveManager::Instance->LoadData("", ((u8*)&gSaveContext.scarecrowSpawnSong)[i]); + }); + SaveManager::Instance->LoadStruct("horseData", []() { + SaveManager::Instance->LoadData("scene", gSaveContext.horseData.scene); + SaveManager::Instance->LoadStruct("pos", []() { + SaveManager::Instance->LoadData("x", gSaveContext.horseData.pos.x); + SaveManager::Instance->LoadData("y", gSaveContext.horseData.pos.y); + SaveManager::Instance->LoadData("z", gSaveContext.horseData.pos.z); + }); + SaveManager::Instance->LoadData("angle", gSaveContext.horseData.angle); + }); + + SaveManager::Instance->LoadArray("dungeonsDone", ARRAY_COUNT(gSaveContext.dungeonsDone), [](size_t i) { + SaveManager::Instance->LoadData("", gSaveContext.dungeonsDone[i]); + }); + + SaveManager::Instance->LoadArray("trialsDone", ARRAY_COUNT(gSaveContext.trialsDone), + [](size_t i) { SaveManager::Instance->LoadData("", gSaveContext.trialsDone[i]); }); +} + +void SaveManager::LoadBaseVersion2() { + SaveManager::Instance->LoadData("entranceIndex", gSaveContext.entranceIndex); + SaveManager::Instance->LoadData("linkAge", gSaveContext.linkAge); + SaveManager::Instance->LoadData("cutsceneIndex", gSaveContext.cutsceneIndex); + SaveManager::Instance->LoadData("dayTime", gSaveContext.dayTime); + SaveManager::Instance->LoadData("nightFlag", gSaveContext.nightFlag); + SaveManager::Instance->LoadData("totalDays", gSaveContext.totalDays); + SaveManager::Instance->LoadData("bgsDayCount", gSaveContext.bgsDayCount); + SaveManager::Instance->LoadData("deaths", gSaveContext.deaths); + SaveManager::Instance->LoadArray("playerName", ARRAY_COUNT(gSaveContext.playerName), [](size_t i) { + SaveManager::Instance->LoadData("", gSaveContext.playerName[i]); + }); + SaveManager::Instance->LoadData("n64ddFlag", gSaveContext.n64ddFlag); + SaveManager::Instance->LoadData("healthCapacity", gSaveContext.healthCapacity); + SaveManager::Instance->LoadData("health", gSaveContext.health); + SaveManager::Instance->LoadData("magicLevel", gSaveContext.magicLevel); + SaveManager::Instance->LoadData("magic", gSaveContext.magic); + SaveManager::Instance->LoadData("rupees", gSaveContext.rupees); + SaveManager::Instance->LoadData("swordHealth", gSaveContext.swordHealth); + SaveManager::Instance->LoadData("naviTimer", gSaveContext.naviTimer); + SaveManager::Instance->LoadData("magicAcquired", gSaveContext.magicAcquired); + SaveManager::Instance->LoadData("doubleMagic", gSaveContext.doubleMagic); + SaveManager::Instance->LoadData("doubleDefense", gSaveContext.doubleDefense); + SaveManager::Instance->LoadData("bgsFlag", gSaveContext.bgsFlag); + SaveManager::Instance->LoadData("ocarinaGameRoundNum", gSaveContext.ocarinaGameRoundNum); + SaveManager::Instance->LoadStruct("childEquips", []() { + SaveManager::Instance->LoadArray("buttonItems", ARRAY_COUNT(gSaveContext.childEquips.buttonItems), [](size_t i) { + SaveManager::Instance->LoadData("", gSaveContext.childEquips.buttonItems[i], + static_cast(ITEM_NONE)); + }); + SaveManager::Instance->LoadArray("cButtonSlots", ARRAY_COUNT(gSaveContext.childEquips.cButtonSlots), [](size_t i) { + SaveManager::Instance->LoadData("", gSaveContext.childEquips.cButtonSlots[i], + static_cast(SLOT_NONE)); + }); + SaveManager::Instance->LoadData("equipment", gSaveContext.childEquips.equipment); + }); + SaveManager::Instance->LoadStruct("adultEquips", []() { + SaveManager::Instance->LoadArray("buttonItems", ARRAY_COUNT(gSaveContext.adultEquips.buttonItems), [](size_t i) { + SaveManager::Instance->LoadData("", gSaveContext.adultEquips.buttonItems[i], + static_cast(ITEM_NONE)); + }); + SaveManager::Instance->LoadArray("cButtonSlots", ARRAY_COUNT(gSaveContext.adultEquips.cButtonSlots), [](size_t i) { + SaveManager::Instance->LoadData("", gSaveContext.adultEquips.cButtonSlots[i], + static_cast(SLOT_NONE)); + }); + SaveManager::Instance->LoadData("equipment", gSaveContext.adultEquips.equipment); + }); + SaveManager::Instance->LoadData("unk_54", gSaveContext.unk_54); + SaveManager::Instance->LoadData("savedSceneNum", gSaveContext.savedSceneNum); + SaveManager::Instance->LoadStruct("equips", []() { + SaveManager::Instance->LoadArray("buttonItems", ARRAY_COUNT(gSaveContext.equips.buttonItems), [](size_t i) { + SaveManager::Instance->LoadData("", gSaveContext.equips.buttonItems[i], static_cast(ITEM_NONE)); + }); + SaveManager::Instance->LoadArray("cButtonSlots", ARRAY_COUNT(gSaveContext.equips.cButtonSlots), [](size_t i) { + SaveManager::Instance->LoadData("", gSaveContext.equips.cButtonSlots[i], static_cast(SLOT_NONE)); + }); + SaveManager::Instance->LoadData("equipment", gSaveContext.equips.equipment); + }); + SaveManager::Instance->LoadStruct("inventory", []() { + SaveManager::Instance->LoadArray("items", ARRAY_COUNT(gSaveContext.inventory.items), [](size_t i) { + SaveManager::Instance->LoadData("", gSaveContext.inventory.items[i]); + }); + SaveManager::Instance->LoadArray("ammo", ARRAY_COUNT(gSaveContext.inventory.ammo), [](size_t i) { + SaveManager::Instance->LoadData("", gSaveContext.inventory.ammo[i]); + }); + SaveManager::Instance->LoadData("equipment", gSaveContext.inventory.equipment); + SaveManager::Instance->LoadData("upgrades", gSaveContext.inventory.upgrades); + SaveManager::Instance->LoadData("questItems", gSaveContext.inventory.questItems); + SaveManager::Instance->LoadArray("dungeonItems", ARRAY_COUNT(gSaveContext.inventory.dungeonItems), [](size_t i) { + SaveManager::Instance->LoadData("", gSaveContext.inventory.dungeonItems[i]); + }); + SaveManager::Instance->LoadArray("dungeonKeys", ARRAY_COUNT(gSaveContext.inventory.dungeonKeys), [](size_t i) { + SaveManager::Instance->LoadData("", gSaveContext.inventory.dungeonKeys[i]); + }); + SaveManager::Instance->LoadData("defenseHearts", gSaveContext.inventory.defenseHearts); + SaveManager::Instance->LoadData("gsTokens", gSaveContext.inventory.gsTokens); + }); + SaveManager::Instance->LoadArray("sceneFlags", ARRAY_COUNT(gSaveContext.sceneFlags), [](size_t i) { + SaveManager::Instance->LoadStruct("", [&i]() { + SaveManager::Instance->LoadData("chest", gSaveContext.sceneFlags[i].chest); + SaveManager::Instance->LoadData("swch", gSaveContext.sceneFlags[i].swch); + SaveManager::Instance->LoadData("clear", gSaveContext.sceneFlags[i].clear); + SaveManager::Instance->LoadData("collect", gSaveContext.sceneFlags[i].collect); + SaveManager::Instance->LoadData("unk", gSaveContext.sceneFlags[i].unk); + SaveManager::Instance->LoadData("rooms", gSaveContext.sceneFlags[i].rooms); + SaveManager::Instance->LoadData("floors", gSaveContext.sceneFlags[i].floors); + }); + }); + SaveManager::Instance->LoadStruct("fw", []() { + SaveManager::Instance->LoadStruct("pos", []() { + SaveManager::Instance->LoadData("x", gSaveContext.fw.pos.x); + SaveManager::Instance->LoadData("y", gSaveContext.fw.pos.y); + SaveManager::Instance->LoadData("z", gSaveContext.fw.pos.z); + }); + SaveManager::Instance->LoadData("yaw", gSaveContext.fw.yaw); + SaveManager::Instance->LoadData("playerParams", gSaveContext.fw.playerParams); + SaveManager::Instance->LoadData("entranceIndex", gSaveContext.fw.entranceIndex); + SaveManager::Instance->LoadData("roomIndex", gSaveContext.fw.roomIndex); + SaveManager::Instance->LoadData("set", gSaveContext.fw.set); + SaveManager::Instance->LoadData("tempSwchFlags", gSaveContext.fw.tempSwchFlags); + SaveManager::Instance->LoadData("tempCollectFlags", gSaveContext.fw.tempCollectFlags); + }); + SaveManager::Instance->LoadArray("gsFlags", ARRAY_COUNT(gSaveContext.gsFlags), [](size_t i) { + SaveManager::Instance->LoadData("", gSaveContext.gsFlags[i]); + }); + SaveManager::Instance->LoadArray("highScores", ARRAY_COUNT(gSaveContext.highScores), [](size_t i) { + SaveManager::Instance->LoadData("", gSaveContext.highScores[i]); + }); + SaveManager::Instance->LoadArray("eventChkInf", ARRAY_COUNT(gSaveContext.eventChkInf), [](size_t i) { + SaveManager::Instance->LoadData("", gSaveContext.eventChkInf[i]); + }); + SaveManager::Instance->LoadArray("itemGetInf", ARRAY_COUNT(gSaveContext.itemGetInf), [](size_t i) { + SaveManager::Instance->LoadData("", gSaveContext.itemGetInf[i]); + }); + SaveManager::Instance->LoadArray("infTable", ARRAY_COUNT(gSaveContext.infTable), [](size_t i) { + SaveManager::Instance->LoadData("", gSaveContext.infTable[i]); + }); + SaveManager::Instance->LoadData("worldMapAreaData", gSaveContext.worldMapAreaData); + SaveManager::Instance->LoadData("scarecrowCustomSongSet", gSaveContext.scarecrowCustomSongSet); SaveManager::Instance->LoadArray("scarecrowCustomSong", ARRAY_COUNT(gSaveContext.scarecrowCustomSong), [](size_t i) { - SaveManager::Instance->LoadData("", gSaveContext.scarecrowCustomSong[i]); + SaveManager::Instance->LoadStruct("", [&i]() { + SaveManager::Instance->LoadData("noteIdx", gSaveContext.scarecrowCustomSong[i].noteIdx); + SaveManager::Instance->LoadData("unk_01", gSaveContext.scarecrowCustomSong[i].unk_01); + SaveManager::Instance->LoadData("unk_02", gSaveContext.scarecrowCustomSong[i].unk_02); + SaveManager::Instance->LoadData("volume", gSaveContext.scarecrowCustomSong[i].volume); + SaveManager::Instance->LoadData("vibrato", gSaveContext.scarecrowCustomSong[i].vibrato); + SaveManager::Instance->LoadData("tone", gSaveContext.scarecrowCustomSong[i].tone); + SaveManager::Instance->LoadData("semitone", gSaveContext.scarecrowCustomSong[i].semitone); + }); }); SaveManager::Instance->LoadData("scarecrowSpawnSongSet", gSaveContext.scarecrowSpawnSongSet); SaveManager::Instance->LoadArray("scarecrowSpawnSong", ARRAY_COUNT(gSaveContext.scarecrowSpawnSong), [](size_t i) { - SaveManager::Instance->LoadData("", gSaveContext.scarecrowSpawnSong[i]); + SaveManager::Instance->LoadStruct("", [&i]() { + SaveManager::Instance->LoadData("noteIdx", gSaveContext.scarecrowSpawnSong[i].noteIdx); + SaveManager::Instance->LoadData("unk_01", gSaveContext.scarecrowSpawnSong[i].unk_01); + SaveManager::Instance->LoadData("unk_02", gSaveContext.scarecrowSpawnSong[i].unk_02); + SaveManager::Instance->LoadData("volume", gSaveContext.scarecrowSpawnSong[i].volume); + SaveManager::Instance->LoadData("vibrato", gSaveContext.scarecrowSpawnSong[i].vibrato); + SaveManager::Instance->LoadData("tone", gSaveContext.scarecrowSpawnSong[i].tone); + SaveManager::Instance->LoadData("semitone", gSaveContext.scarecrowSpawnSong[i].semitone); + }); }); SaveManager::Instance->LoadStruct("horseData", []() { SaveManager::Instance->LoadData("scene", gSaveContext.horseData.scene); @@ -841,11 +1014,27 @@ void SaveManager::SaveBase() { SaveManager::Instance->SaveData("worldMapAreaData", gSaveContext.worldMapAreaData); SaveManager::Instance->SaveData("scarecrowCustomSongSet", gSaveContext.scarecrowCustomSongSet); SaveManager::Instance->SaveArray("scarecrowCustomSong", ARRAY_COUNT(gSaveContext.scarecrowCustomSong), [](size_t i) { - SaveManager::Instance->SaveData("", gSaveContext.scarecrowCustomSong[i]); + SaveManager::Instance->SaveStruct("", [&i]() { + SaveManager::Instance->SaveData("noteIdx", gSaveContext.scarecrowCustomSong[i].noteIdx); + SaveManager::Instance->SaveData("unk_01", gSaveContext.scarecrowCustomSong[i].unk_01); + SaveManager::Instance->SaveData("unk_02", gSaveContext.scarecrowCustomSong[i].unk_02); + SaveManager::Instance->SaveData("volume", gSaveContext.scarecrowCustomSong[i].volume); + SaveManager::Instance->SaveData("vibrato", gSaveContext.scarecrowCustomSong[i].vibrato); + SaveManager::Instance->SaveData("tone", gSaveContext.scarecrowCustomSong[i].tone); + SaveManager::Instance->SaveData("semitone", gSaveContext.scarecrowCustomSong[i].semitone); + }); }); SaveManager::Instance->SaveData("scarecrowSpawnSongSet", gSaveContext.scarecrowSpawnSongSet); SaveManager::Instance->SaveArray("scarecrowSpawnSong", ARRAY_COUNT(gSaveContext.scarecrowSpawnSong), [](size_t i) { - SaveManager::Instance->SaveData("", gSaveContext.scarecrowSpawnSong[i]); + SaveManager::Instance->SaveStruct("", [&i]() { + SaveManager::Instance->SaveData("noteIdx", gSaveContext.scarecrowSpawnSong[i].noteIdx); + SaveManager::Instance->SaveData("unk_01", gSaveContext.scarecrowSpawnSong[i].unk_01); + SaveManager::Instance->SaveData("unk_02", gSaveContext.scarecrowSpawnSong[i].unk_02); + SaveManager::Instance->SaveData("volume", gSaveContext.scarecrowSpawnSong[i].volume); + SaveManager::Instance->SaveData("vibrato", gSaveContext.scarecrowSpawnSong[i].vibrato); + SaveManager::Instance->SaveData("tone", gSaveContext.scarecrowSpawnSong[i].tone); + SaveManager::Instance->SaveData("semitone", gSaveContext.scarecrowSpawnSong[i].semitone); + }); }); SaveManager::Instance->SaveStruct("horseData", []() { SaveManager::Instance->SaveData("scene", gSaveContext.horseData.scene); @@ -1252,13 +1441,9 @@ void CopyV0Save(SaveContext_v0& src, SaveContext& dst) { } dst.worldMapAreaData = src.worldMapAreaData; dst.scarecrowCustomSongSet = src.scarecrowCustomSongSet; - for (size_t i = 0; i < ARRAY_COUNT(src.scarecrowCustomSong); i++) { - dst.scarecrowCustomSong[i] = src.scarecrowCustomSong[i]; - } + memcpy(&dst.scarecrowCustomSong[0], &src.scarecrowCustomSong[0], sizeof(src.scarecrowCustomSong)); dst.scarecrowSpawnSongSet = src.scarecrowSpawnSongSet; - for (size_t i = 0; i < ARRAY_COUNT(src.scarecrowSpawnSong); i++) { - dst.scarecrowSpawnSong[i] = src.scarecrowSpawnSong[i]; - } + memcpy(&dst.scarecrowSpawnSong[0], &src.scarecrowSpawnSong[0], sizeof(src.scarecrowSpawnSong)); dst.horseData.scene = src.horseData.scene; dst.horseData.pos.x = src.horseData.pos.x; dst.horseData.pos.y = src.horseData.pos.y; diff --git a/soh/soh/SaveManager.h b/soh/soh/SaveManager.h index ee13451fb..06a382baa 100644 --- a/soh/soh/SaveManager.h +++ b/soh/soh/SaveManager.h @@ -117,6 +117,7 @@ public: static void SaveRandomizer(); static void LoadBaseVersion1(); + static void LoadBaseVersion2(); static void SaveBase(); std::vector initFuncs; From 7a45380123a3328ea41140ec7459f03549f2058a Mon Sep 17 00:00:00 2001 From: Josh Bodner <30329717+jbodner09@users.noreply.github.com> Date: Sun, 31 Jul 2022 18:40:26 -0700 Subject: [PATCH 17/25] Automatically break long tooltip lines (#925) * Remove manual newlines from the middle of sentences in tooltips and automatically break long lines instead * Move split functionality into header so randomizer tooltips can use it * Rewrite logic to be O(n) * Found another typo * Move helper function to libultraship to (hopefully) get Jenkins happy * Fix typo I made when fixing the typo before * Remove unneeded header * Parameterize line length in case variable line length is desired in the future --- libultraship/libultraship/ImGuiImpl.cpp | 104 +++-- libultraship/libultraship/ImGuiImpl.h | 2 + .../Enhancements/debugger/ImGuiHelpers.cpp | 5 +- .../Enhancements/debugger/debugSaveEditor.cpp | 2 +- .../Enhancements/randomizer/randomizer.cpp | 413 +++++++++--------- .../randomizer/randomizer_item_tracker.cpp | 2 +- 6 files changed, 271 insertions(+), 257 deletions(-) diff --git a/libultraship/libultraship/ImGuiImpl.cpp b/libultraship/libultraship/ImGuiImpl.cpp index c3b3f6432..ea779b677 100644 --- a/libultraship/libultraship/ImGuiImpl.cpp +++ b/libultraship/libultraship/ImGuiImpl.cpp @@ -130,8 +130,9 @@ namespace SohImGui { } void Tooltip(const char* text) { - if (ImGui::IsItemHovered()) - ImGui::SetTooltip("%s", text); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("%s", BreakTooltip(text, 60).c_str()); + } } void ImGuiWMInit() { @@ -867,7 +868,7 @@ namespace SohImGui { // TODO mutual exclusions -- There should be some system to prevent conclifting enhancements from being selected EnhancementCheckbox("D-pad Support on Pause and File Select", "gDpadPauseName"); - Tooltip("Enables Pause and File Select screen navigation with the D-pad\nIf used with D-pad as Equip Items, you must hold C-Up\nto equip instead of navigate"); + Tooltip("Enables Pause and File Select screen navigation with the D-pad\nIf used with D-pad as Equip Items, you must hold C-Up to equip instead of navigate"); EnhancementCheckbox("D-pad Support in Ocarina and Text Choice", "gDpadOcarinaText"); EnhancementCheckbox("D-pad Support for Browsing Shop Items", "gDpadShop"); EnhancementCheckbox("D-pad as Equip Items", "gDpadEquips"); @@ -890,10 +891,10 @@ namespace SohImGui { if (ImGui::BeginMenu("Graphics")) { EnhancementSliderFloat("Internal Resolution: %d %%", "##IMul", "gInternalResolution", 0.5f, 2.0f, "", 1.0f, true); - Tooltip("Multiplies your output resolution by the value inputted,\nas a more intensive but effective form of anti-aliasing"); + Tooltip("Multiplies your output resolution by the value inputted, as a more intensive but effective form of anti-aliasing"); gfx_current_dimensions.internal_mul = CVar_GetFloat("gInternalResolution", 1); EnhancementSliderInt("MSAA: %d", "##IMSAA", "gMSAAValue", 1, 8, ""); - Tooltip("Activates multi-sample anti-aliasing when above 1x\nup to 8x for 8 samples for every pixel"); + Tooltip("Activates multi-sample anti-aliasing when above 1x up to 8x for 8 samples for every pixel"); gfx_msaa_level = CVar_GetS32("gMSAAValue", 1); if (impl.backend == Backend::DX11) @@ -928,12 +929,7 @@ namespace SohImGui { 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)\n" - "in order to avoid jitter.This setting allows the CPU\n" - "to work on one frame while GPU works on the previous frame.\n" - "This setting should be used when your computer is too slow\n" - "to do CPU + GPU work in time."); + Tooltip("When Interpolation FPS setting is at least this threshold, add one frame of input lag (e.g. 16.6 ms for 60 FPS) in order to avoid jitter. This setting allows the CPU to work on one frame while GPU works on the previous frame.\nThis setting should be used when your computer is too slow to do CPU + GPU work in time."); ImGui::SameLine(); ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); @@ -983,30 +979,30 @@ namespace SohImGui { EnhancementSliderInt("Text Speed: %dx", "##TEXTSPEED", "gTextSpeed", 1, 5, ""); EnhancementSliderInt("King Zora Speed: %dx", "##MWEEPSPEED", "gMweepSpeed", 1, 5, ""); EnhancementSliderInt("Biggoron Forge Time: %d days", "##FORGETIME", "gForgeTime", 0, 3, ""); - Tooltip("Allows you to change the number of days it takes for\nBiggoron to forge the Biggoron Sword"); + Tooltip("Allows you to change the number of days it takes for Biggoron to forge the Biggoron Sword"); EnhancementSliderInt("Vine/Ladder Climb speed +%d", "##CLIMBSPEED", "gClimbSpeed", 0, 12, ""); EnhancementCheckbox("Faster Block Push", "gFasterBlockPush"); EnhancementCheckbox("No Forced Navi", "gNoForcedNavi"); Tooltip("Prevent forced Navi conversations"); EnhancementCheckbox("No Skulltula Freeze", "gSkulltulaFreeze"); - Tooltip("Stops the game from freezing the player\nwhen picking up Gold Skulltulas"); + Tooltip("Stops the game from freezing the player when picking up Gold Skulltulas"); EnhancementCheckbox("MM Bunny Hood", "gMMBunnyHood"); - Tooltip("Wearing the Bunny Hood grants a speed\nincrease like in Majora's Mask"); + Tooltip("Wearing the Bunny Hood grants a speed increase like in Majora's Mask"); EnhancementCheckbox("Fast Chests", "gFastChests"); Tooltip("Kick open every chest"); EnhancementCheckbox("Skip Pickup Messages", "gFastDrops"); Tooltip("Skip pickup messages for new consumable items and bottle swipes"); EnhancementCheckbox("Better Owl", "gBetterOwl"); - Tooltip("The default response to Kaepora Gaebora is\nalways that you understood what he said"); + Tooltip("The default response to Kaepora Gaebora is always that you understood what he said"); EnhancementCheckbox("Fast Ocarina Playback", "gFastOcarinaPlayback"); - Tooltip("Skip the part where the Ocarina playback is called when you play\na song"); + Tooltip("Skip the part where the Ocarina playback is called when you play a song"); EnhancementCheckbox("Prevent Dropped Ocarina Inputs", "gDpadNoDropOcarinaInput"); Tooltip("Prevent dropping inputs when playing the ocarina quickly"); EnhancementCheckbox("Instant Putaway", "gInstantPutaway"); Tooltip("Allow Link to put items away without having to wait around"); EnhancementCheckbox("Mask Select in Inventory", "gMaskSelect"); - Tooltip("After completing the mask trading sub-quest,\npress A and any direction on the mask slot to change masks"); + Tooltip("After completing the mask trading sub-quest, press A and any direction on the mask slot to change masks"); ImGui::EndMenu(); } @@ -1137,13 +1133,13 @@ namespace SohImGui { } EnhancementCheckbox("Visual Stone of Agony", "gVisualAgony"); - Tooltip("Displays an icon and plays a sound when Stone of Agony\nshould be activated, for those without rumble"); + 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 equipping the tunic and boots to c-buttons"); EnhancementCheckbox("Equipment Toggle", "gEquipmentCanBeRemoved"); Tooltip("Allows equipment to be removed by toggling it off on\nthe equipment subscreen."); EnhancementCheckbox("Link's Cow in Both Time Periods", "gCowOfTime"); - Tooltip("Allows the Lon Lon Ranch obstacle course reward to be\nshared across time periods"); + Tooltip("Allows the Lon Lon Ranch obstacle course reward to be shared across time periods"); EnhancementCheckbox("Enable visible guard vision", "gGuardVision"); EnhancementCheckbox("Enable passage of time on file select", "gTimeFlowFileSelect"); EnhancementCheckbox("Allow the cursor to be on any slot", "gPauseAnyCursor"); @@ -1161,7 +1157,7 @@ namespace SohImGui { ImGui::Text("Rotation"); EnhancementRadioButton("Disabled", "gPauseLiveLinkRotation", 0); EnhancementRadioButton("Rotate Link with D-pad", "gPauseLiveLinkRotation", 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"); + Tooltip("Allow you to rotate Link on the Equipment menu with the D-pad\nUse D-pad Up or D-pad Down to reset Link's rotation"); EnhancementRadioButton("Rotate Link with C-buttons", "gPauseLiveLinkRotation", 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"); EnhancementRadioButton("Rotate Link with Right Stick", "gPauseLiveLinkRotation", 3); @@ -1206,7 +1202,7 @@ namespace SohImGui { EnhancementCheckbox("Enable 3D Dropped items/projectiles", "gNewDrops"); Tooltip("Change most 2D items and projectiles on the overworld to their 3D versions"); EnhancementCheckbox("Disable Black Bar Letterboxes", "gDisableBlackBars"); - Tooltip("Disables Black Bar Letterboxes during cutscenes and Z-targeting\nNote: there may be minor visual glitches that\nwere covered up by the black bars\nPlease disable this setting before reporting a bug"); + Tooltip("Disables Black Bar Letterboxes during cutscenes and Z-targeting\nNote: there may be minor visual glitches that were covered up by the black bars\nPlease disable this setting before reporting a bug"); 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"); @@ -1222,19 +1218,19 @@ namespace SohImGui { EnhancementCheckbox("Fix L&Z Page switch in Pause menu", "gNGCKaleidoSwitcher"); Tooltip("Makes L and R switch pages like on the GameCube\nZ opens the Debug Menu instead"); EnhancementCheckbox("Fix Dungeon entrances", "gFixDungeonMinimapIcon"); - Tooltip("Removes the dungeon entrance icon on the top-left corner\nof the screen when no dungeon is present on the current map"); + Tooltip("Removes the dungeon entrance icon on the top-left corner of the screen when no dungeon is present on the current map"); EnhancementCheckbox("Fix Two Handed idle animations", "gTwoHandedIdle"); - Tooltip("Re-enables the two-handed idle animation, a seemingly\nfinished animation that was disabled on accident in the original game"); + Tooltip("Re-enables the two-handed idle animation, a seemingly finished animation that was disabled on accident in the original game"); EnhancementCheckbox("Fix the Gravedigging Tour Glitch", "gGravediggingTourFix"); - Tooltip("Fixes a bug where the Gravedigging Tour Heart\nPiece disappears if the area reloads"); + Tooltip("Fixes a bug where the Gravedigging Tour Heart Piece disappears if the area reloads"); EnhancementCheckbox("Fix Deku Nut upgrade", "gDekuNutUpgradeFix"); - Tooltip("Prevents the Forest Stage Deku Nut upgrade from\nbecoming unobtainable after receiving the Poacher's Saw"); + Tooltip("Prevents the Forest Stage Deku Nut upgrade from becoming unobtainable after receiving the Poacher's Saw"); EnhancementCheckbox("Fix Navi text HUD position", "gNaviTextFix"); Tooltip("Correctly centers the Navi text prompt on the HUD's C-Up button"); EnhancementCheckbox("Fix Anubis fireballs", "gAnubisFix"); - Tooltip("Make Anubis fireballs do fire damage when reflected\nback at them with the Mirror Shield"); + Tooltip("Make Anubis fireballs do fire damage when reflected back at them with the Mirror Shield"); EnhancementCheckbox("Fix Megaton Hammer crouch stab", "gCrouchStabHammerFix"); - Tooltip("Make the Megaton Hammer's crouch stab able to destroy\nrocks without first swinging it normally"); + Tooltip("Make the Megaton Hammer's crouch stab able to destroy rocks without first swinging it normally"); if (CVar_GetS32("gCrouchStabHammerFix", 0) == 0) { CVar_SetS32("gCrouchStabFix", 0); } else { @@ -1250,7 +1246,7 @@ namespace SohImGui { EnhancementCheckbox("Red Ganon blood", "gRedGanonBlood"); Tooltip("Restore the original red blood from NTSC 1.0/1.1. Disable for green blood"); EnhancementCheckbox("Fish while hovering", "gHoverFishing"); - Tooltip("Restore a bug from NTSC 1.0 that allows casting\nthe Fishing Rod while using the Hover Boots"); + Tooltip("Restore a bug from NTSC 1.0 that allows casting the Fishing Rod while using the Hover Boots"); EnhancementCheckbox("N64 Weird Frames", "gN64WeirdFrames"); Tooltip("Restores N64 Weird Frames allowing weirdshots to behave the same as N64"); EnhancementCheckbox("Bombchus out of bounds", "gBombchusOOB"); @@ -1311,7 +1307,7 @@ namespace SohImGui { 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" + "A higher target FPS than your monitor's refresh rate will just waste resources, " "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"); @@ -1339,7 +1335,7 @@ namespace SohImGui { EnhancementCheckbox("Disable LOD", "gDisableLOD"); Tooltip("Turns off the Level of Detail setting, making models use their higher-poly variants at any distance"); EnhancementCheckbox("Disable Draw Distance", "gDisableDrawDistance"); - Tooltip("Turns off the objects draw distance,\nmaking objects being visible from a longer range"); + Tooltip("Turns off the objects draw distance, making objects being visible from a longer range"); if (CVar_GetS32("gDisableDrawDistance", 0) == 0) { CVar_SetS32("gDisableKokiriDrawDistance", 0); } else if (CVar_GetS32("gDisableDrawDistance", 0) == 1) { @@ -1350,7 +1346,7 @@ namespace SohImGui { Tooltip("Holding down B skips text\nKnown to cause a cutscene softlock in Water Temple\nSoftlock can be fixed by pressing D-Right in Debug mode"); EnhancementCheckbox("Free Camera", "gFreeCamera"); - Tooltip("Enables camera control\nNote: You must remap C buttons off of\nthe right stick in the controller\nconfig menu, and map the camera stick\nto the right stick."); + Tooltip("Enables camera control\nNote: You must remap C buttons off of the right stick in the controller config menu, and map the camera stick to the right stick."); #ifdef __SWITCH__ int slot = CVar_GetS32("gSwitchPerfMode", (int)SwitchProfiles::STOCK); @@ -1406,7 +1402,7 @@ namespace SohImGui { EnhancementCheckbox("Fireproof Deku Shield", "gFireproofDekuShield"); Tooltip("Prevents the Deku Shield from burning on contact with fire"); EnhancementCheckbox("Shield with Two-Handed Weapons", "gShieldTwoHanded"); - Tooltip("This allows you to put up your shield with any two-handed weapon in hand\nexcept for Deku Sticks"); + Tooltip("This allows you to put up your shield with any two-handed weapon in hand except for Deku Sticks"); ImGui::EndMenu(); } @@ -1416,11 +1412,11 @@ 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, and open the debug menu with L on the pause screen"); EnhancementCheckbox("OoT Skulltula Debug", "gSkulltulaDebugEnabled"); - Tooltip("Enables Skulltula Debug, when moving the cursor in the menu above various map\nicons (boss key, compass, map screen locations, etc) will set the GS bits in that\narea. USE WITH CAUTION AS IT DOES NOT UPDATE THE GS COUNT."); + Tooltip("Enables Skulltula Debug, when moving the cursor in the menu above various map icons (boss key, compass, map screen locations, etc) will set the GS bits in that area.\nUSE WITH CAUTION AS IT DOES NOT UPDATE THE GS COUNT."); EnhancementCheckbox("Fast File Select", "gSkipLogoTitle"); - Tooltip("Load the game to the selected menu or file\n\"Zelda Map Select\" require debug mode else you will fallback to File choose menu\nUsing a file number that don't have save will create a save file only\nif you toggle on \"Create a new save if none ?\" else it will bring you to the\nFile choose menu"); + Tooltip("Load the game to the selected menu or file\n\"Zelda Map Select\" require debug mode else you will fallback to File choose menu\nUsing a file number that don't have save will create a save file only if you toggle on \"Create a new save if none ?\" else it will bring you to the File choose menu"); if (CVar_GetS32("gSkipLogoTitle", 0)) { const char* FastFileSelect[5] = { "File N.1", @@ -1432,13 +1428,13 @@ namespace SohImGui { ImGui::Text("Loading :"); EnhancementCombobox("gSaveFileID", FastFileSelect, 5, 0); EnhancementCheckbox("Create a new save if none", "gCreateNewSave"); - Tooltip("Enable the creation of a new save file\nif none exist in the File number selected\nNo file name will be assigned please do in Save editor once you see the first text\nelse your save file name will be named \"00000000\"\nIf disabled you will fall back in File select menu"); + Tooltip("Enable the creation of a new save file if none exist in the File number selected\nNo file name will be assigned please do in Save editor once you see the first text else your save file name will be named \"00000000\"\nIf disabled you will fall back in File select menu"); }; ImGui::Separator(); EnhancementCheckbox("Stats", "gStatsEnabled"); - Tooltip("Shows the stats window, with your FPS and frametimes,\nand 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,\ntype 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(); @@ -1780,4 +1776,36 @@ namespace SohImGui { ImGui::EndGroup(); } + + // Automatically add newlines to break up tooltips longer than a specified number of characters + // Manually included newlines will still be respected and reset the line length + // Default line length is 60 characters + std::string BreakTooltip(const char* text, int lineLength) { + std::string newText(text); + const int tipLength = newText.length(); + int lastSpace = -1; + int currentLineLength = 0; + for (int currentCharacter = 0; currentCharacter < tipLength; currentCharacter++) { + if (newText[currentCharacter] == '\n') { + currentLineLength = 0; + lastSpace = -1; + continue; + } + else if (newText[currentCharacter] == ' ') { + lastSpace = currentCharacter; + } + + if ((currentLineLength >= lineLength) && (lastSpace >= 0)) { + newText[lastSpace] = '\n'; + currentLineLength = currentCharacter - lastSpace - 1; + lastSpace = -1; + } + currentLineLength++; + } + return newText; + } + + std::string BreakTooltip(const std::string& text, int lineLength) { + return BreakTooltip(text.c_str(), lineLength); + } } diff --git a/libultraship/libultraship/ImGuiImpl.h b/libultraship/libultraship/ImGuiImpl.h index 580d5cdb6..eb007efeb 100644 --- a/libultraship/libultraship/ImGuiImpl.h +++ b/libultraship/libultraship/ImGuiImpl.h @@ -94,4 +94,6 @@ namespace SohImGui { ImTextureID GetTextureByName(const std::string& name); void BeginGroupPanel(const char* name, const ImVec2 & size = ImVec2(0.0f, 0.0f)); void EndGroupPanel(float minHeight = 0.0f); + std::string BreakTooltip(const char* text, int lineLength = 60); + std::string BreakTooltip(const std::string& text, int lineLength = 60); } diff --git a/soh/soh/Enhancements/debugger/ImGuiHelpers.cpp b/soh/soh/Enhancements/debugger/ImGuiHelpers.cpp index 6f4f00637..7fec0de14 100644 --- a/soh/soh/Enhancements/debugger/ImGuiHelpers.cpp +++ b/soh/soh/Enhancements/debugger/ImGuiHelpers.cpp @@ -1,10 +1,11 @@ #include "ImGuiHelpers.h" +#include "../../../../libultraship/libultraship/ImGuiImpl.h" // Adds a text tooltip for the previous ImGui item void SetLastItemHoverText(const std::string& text) { if (ImGui::IsItemHovered()) { ImGui::BeginTooltip(); - ImGui::Text(text.c_str()); + ImGui::Text(SohImGui::BreakTooltip(text, 60).c_str()); ImGui::EndTooltip(); } } @@ -15,7 +16,7 @@ void InsertHelpHoverText(const std::string& text) { ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "?"); if (ImGui::IsItemHovered()) { ImGui::BeginTooltip(); - ImGui::Text(text.c_str()); + ImGui::Text(SohImGui::BreakTooltip(text, 60).c_str()); ImGui::EndTooltip(); } } diff --git a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp index f31a5e42a..513776b2a 100644 --- a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp +++ b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp @@ -1435,7 +1435,7 @@ void DrawPlayerTab() { InsertHelpHoverText("Link's speed along the Y plane. Caps at -20"); ImGui::InputScalar("Wall Height", ImGuiDataType_Float, &player->wallHeight); - InsertHelpHoverText("\"height used to determine whether link can climb or grab a ledge at the top\""); + InsertHelpHoverText("Height used to determine whether Link can climb or grab a ledge at the top"); ImGui::InputScalar("Invincibility Timer", ImGuiDataType_S8, &player->invincibilityTimer); InsertHelpHoverText("Can't take damage while this is nonzero"); diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 09704e867..59146ba10 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -3542,21 +3542,21 @@ void DrawRandoEditor(bool& open) { switch (CVar_GetS32("gRandomizeForest", 1)) { case 1: InsertHelpHoverText("Mido no longer blocks the path to the Deku Tree\n" - "The Kokiri boy no longer blocks the path\nout of the forest."); + "The Kokiri boy no longer blocks the path out of the forest."); break; case 2: InsertHelpHoverText( "The Kokiri boy no longer blocks the path out of the forest\nMido " - "still blocks the path to the Deku\nTree, requiring the Kokiri Sword " - "and a Deku Shield to\naccess the Deku Tree."); + "still blocks the path to the Deku Tree, requiring the Kokiri Sword " + "and a Deku Shield to access the Deku Tree."); break; case 0: InsertHelpHoverText( - "Beating Deku Tree is logically required to leave\nthe forest area " - "(Kokiri Forest / Loost Woods / Sacred\nForest Meadow / Deku Tree) " - "while the Kokiri Sword\nand a Deku Shield are required to access the " - "Deku\nTree Items needed for this will be guaranteed\ninside the " - "forest area.\nThis settins is incompatible with starting as adult."); + "Beating Deku Tree is logically required to leave the forest area " + "(Kokiri Forest / Lost Woods / Sacred Forest Meadow / Deku Tree) " + "while the Kokiri Sword and a Deku Shield are required to access the " + "Deku Tree\nItems needed for this will be guaranteed inside the " + "forest area.\nThis setting is incompatible with starting as adult."); break; } SohImGui::EnhancementCombobox("gRandomizeForest", randoForest, 3, 1); @@ -3566,13 +3566,13 @@ void DrawRandoEditor(bool& open) { switch (CVar_GetS32("gRandomizeKakarikoGate", 0)) { case 0: InsertHelpHoverText( - "The gate and the Happy Mask Shop both remain\nclosed until showing " - "Zelda's Letter to the guard\nin Kakariko."); + "The gate and the Happy Mask Shop both remain closed until showing " + "Zelda's Letter to the guard in Kakariko."); break; case 1: InsertHelpHoverText( - "The gate is always open instead of needing\nZelda's Letter.\nThe Happy Mask Shop " - "opens upon obtaining \n Zelda's Letter without needing to show\nit to the guard."); + "The gate is always open instead of needing Zelda's Letter.\nThe Happy Mask Shop " + "opens upon obtaining Zelda's Letter without needing to show it to the guard."); break; } SohImGui::EnhancementCombobox("gRandomizeKakarikoGate", randoKakarikoGate, 2, 1); @@ -3583,16 +3583,16 @@ void DrawRandoEditor(bool& open) { switch (CVar_GetS32("gRandomizeDoorOfTime", 0)) { case 0: InsertHelpHoverText( - "The Door of Time starts opened instead of needing\nto play the Song of Time."); + "The Door of Time starts opened instead of needing to play the Song of Time."); break; case 1: InsertHelpHoverText( - "Only an Ocarina and the Song of Time need to be\nfound to open the Door of Time."); + "Only an Ocarina and the Song of Time need to be found to open the Door of Time."); break; case 2: InsertHelpHoverText( - "The Ocarina of Time, the Song of Time and\nall Spiritual Stones need to " - "be found to\nopen the Door of Time."); + "The Ocarina of Time, the Song of Time and all Spiritual Stones need to " + "be found to open the Door of Time."); break; } SohImGui::EnhancementCombobox("gRandomizeDoorOfTime", randoDoorOfTime, 3, 0); @@ -3604,17 +3604,17 @@ void DrawRandoEditor(bool& open) { case 0: InsertHelpHoverText( "King Zora obstructs the way to Zora's Fountain.\nRuto's Letter must be " - "shown as child in order to\nmove him from both eras."); + "shown as child in order to move him from both eras."); break; case 1: InsertHelpHoverText( "King Zora is always moved in the adult era.\nThis means Ruto's Letter is " - "only required to\naccess Zora's fountain as child."); + "only required to access Zora's fountain as child."); break; case 2: InsertHelpHoverText( - "King Zora starts as moved in both the child and\nadult eras.\nThis also " - "removes Ruto's Letter from the\npool since it can't be used."); + "King Zora starts as moved in both the child and adult eras.\nThis also " + "removes Ruto's Letter from the pool since it can't be used."); break; } SohImGui::EnhancementCombobox("gRandomizeZorasFountain", randoZorasFountain, 3, 0); @@ -3631,9 +3631,9 @@ void DrawRandoEditor(bool& open) { break; case 2: InsertHelpHoverText( - "The carpenters are rescued from the start of the\ngame and if \"Shuffle " - "Gerudo Card\" is disabled,\nthe player starts with the Gerudo Card in " - "the\ninventory allowing access to Gerudo Training\nGrounds."); + "The carpenters are rescued from the start of the game and if \"Shuffle " + "Gerudo Card\" is disabled, the player starts with the Gerudo Card in " + "the inventory allowing access to Gerudo Training Grounds."); break; } SohImGui::EnhancementCombobox("gRandomizeGerudoFortress", randoGerudoFortress, 3, 1); @@ -3644,41 +3644,40 @@ void DrawRandoEditor(bool& open) { SohImGui::EnhancementCombobox("gRandomizeRainbowBridge", randoRainbowBridge, 7, 3); switch (CVar_GetS32("gRandomizeRainbowBridge", 3)) { case 1: - InsertHelpHoverText("The Rainbow Bridge requires Shadow and Spirit\nMedallions as well " + InsertHelpHoverText("The Rainbow Bridge requires Shadow and Spirit Medallions as well " "as Light Arrows."); break; case 2: - InsertHelpHoverText("The Rainbow Bridge requires collecting a\nconfigurable number of " + InsertHelpHoverText("The Rainbow Bridge requires collecting a configurable number of " "Spiritual Stones."); SohImGui::EnhancementSliderInt("Stone Count: %d", "##RandoStoneCount", "gRandomizeStoneCount", 0, 3, ""); SetLastItemHoverText( - "Sets the number of Spiritual Stones required to\nspawn the Rainbow Bridge."); + "Sets the number of Spiritual Stones required to spawn the Rainbow Bridge."); break; case 3: SohImGui::EnhancementSliderInt("Medallion Count: %d", "##RandoMedallionCount", "gRandomizeMedallionCount", 0, 6, "", 6); SetLastItemHoverText( - "The Rainbow Bridge requires collecting a\nconfigurable number of Medallions."); + "The Rainbow Bridge requires collecting a configurable number of Medallions."); break; case 4: SohImGui::EnhancementSliderInt("Reward Count: %d", "##RandoRewardCount", "gRandomizeRewardCount", 0, 9, ""); - SetLastItemHoverText("The Rainbow Bridge requires collecting a\nconfigurable number of " + SetLastItemHoverText("The Rainbow Bridge requires collecting a configurable number of " "Dungeon Rewards."); break; case 5: SohImGui::EnhancementSliderInt("Dungeon Count: %d", "##RandoDungeonCount", "gRandomizeDungeonCount", 0, 8, ""); SetLastItemHoverText( - "The Rainbow Bridge requires completing a\nconfigurable number of " - "Dungeons.\n\nDungeons " - "are considered complete when Link steps\ninto the blue warp at the end of them."); + "The Rainbow Bridge requires completing a configurable number of Dungeons.\nDungeons " + "are considered complete when Link steps into the blue warp at the end of them."); break; case 6: SohImGui::EnhancementSliderInt("Token Count: %d", "##RandoTokenCount", "gRandomizeTokenCount", 0, 100, ""); - SetLastItemHoverText("The Rainbow Bridge requires collecting a\nconfigurable number of " + SetLastItemHoverText("The Rainbow Bridge requires collecting a configurable number of " "Gold Skulltula Tokens."); break; } @@ -3687,17 +3686,17 @@ void DrawRandoEditor(bool& open) { // Random Ganon's Trials /* ImGui::Text("Random Ganon's Trials"); - InsertHelpHoverText("Sets a random number or required trials to enter\nGanon's Tower."); + InsertHelpHoverText("Sets a random number or required trials to enter Ganon's Tower."); SohImGui::EnhancementCombobox("gRandomizeGanonTrial", randoGanonsTrial, 2, 0); if (CVar_GetS32("gRandomizeGanonTrial", 0) == 0) { */ //SohImGui::EnhancementSliderInt("Ganon's Trial Count: %d", "##RandoTrialCount", // "gRandomizeGanonTrialCount", 0, 6, ""); - //InsertHelpHoverText("Set the number of trials required to enter\nGanon's Tower."); + //InsertHelpHoverText("Set the number of trials required to enter Ganon's Tower."); // RANDTODO: Switch back to slider when pre-completing some of Ganon's Trials is properly implemnted. SohImGui::EnhancementCheckbox("Skip Ganon's Trials", "gRandomizeGanonTrialCount"); InsertHelpHoverText( - "Sets whether or not Ganon's Castle Trials are required\nto enter Ganon's Tower."); + "Sets whether or not Ganon's Castle Trials are required to enter Ganon's Tower."); // } ImGui::Separator(); @@ -3716,9 +3715,9 @@ void DrawRandoEditor(bool& open) { // Starting Age // ImGui::Text("Starting Age"); // InsertHelpHoverText( - // "Choose which age Link will start as.\n\nStarting as adult means you start with the " - // "Master\nSword " - // "in your inventory.\n\nOnly the child option is compatible with Closed\nForest."); + // "Choose which age Link will start as.\nStarting as adult means you start with the " + // "Master Sword in your inventory.\nOnly the child option is compatible with " + // "Closed Forest."); // SohImGui::EnhancementCombobox("gRandomizeStartingAge", randoStartingAge, 3, 0); // ImGui::Separator(); @@ -3726,31 +3725,26 @@ void DrawRandoEditor(bool& open) { // Shuffle Entrances // ImGui::Text("Shuffle Entrances"); // InsertHelpHoverText("Shuffle where the entrances between areas lead to.\n" - // "If turned on, select which kinds of entrances you\n" - // "want shuffled in the options below. Note that some\n" - // "types of entrances can have widly varying\ngeneration times."); + // "If turned on, select which kinds of entrances you " + // "want shuffled in the options below.\n Note that some " + // "types of entrances can have widly varying generation times."); // SohImGui::EnhancementCombobox("gRandomizeShuffleEntrances", randoShuffleEntrances, 2, 0); // if (CVar_GetS32("gRandomizeShuffleEntrances", 0) == 1) { // ImGui::Indent(); // ImGui::Text("Shuffle Dungeons Entrances"); // InsertHelpHoverText( - // "Shuffle the pool of dungeon entrances, including\nBottom of the Well, Ice caven and " - // "Gerudo\n" - // "Training Grounds However, Ganon's Caslte is not\nshuffled.\n\nAdditionally, the " - // "entrance " - // "of " - // "Deku Tree, Fire\nTemple and Bottom of the Well are opened for both\nadult and child."); + // "Shuffle the pool of dungeon entrances, including Bottom of the Well, Ice Cavern and " + // "Gerudo Training Grounds\nGanon's Castle is not shuffled.\nAdditionally, the entrance " + // "of Deku Tree, Fire Temple and Bottom of the Well are open for both adult and child."); // SohImGui::EnhancementCombobox("gRandomizeShuffleDungeonsEntrances", // randoShuffleDungeonsEntrances, 2, 0); // ImGui::Text("Shuffle Overworld Entrances"); // InsertHelpHoverText( - // "Shuffle the pool of Overworld entrances, which\ncorresponds to almost all loading " - // "zones " - // "between\nOverworld areas.\n\nSome entrances are unshuffled to avoid issues:\n- Hyrule " - // "Castle " - // "Courtyard and Garden entrance\n- Both Market Back Alley entrances\n- Gerudo Valley to " - // "Lake " - // "Hylia (unless entrances\nare decoupled)."); + // "Shuffle the pool of Overworld entrances, which corresponds to almost all loading " + // "zones between Overworld areas.\nSome entrances are unshuffled to avoid issues:\n" + // "- Hyrule Castle Courtyard and Garden entrance\n" + // "- Both Market Back Alley entrances\n" + // "- Gerudo Valley to Lake Hylia (unless entrances are decoupled)"); // SohImGui::EnhancementCombobox("gRandomizeShuffleOverworldEntrances", // randoShuffleOverworldEntrances, 2, 0); // ImGui::Text("Shuffle Interiors Entrances"); @@ -3759,8 +3753,8 @@ void DrawRandoEditor(bool& open) { // randoShuffleInteriorsEntrances, 2, 0); // ImGui::Text("Shuffle Grottos Entrances"); // InsertHelpHoverText( - // "Shuffle the pool of grotto entrances, including\nall graves, small Fairy " - // "fountains and the Lost\nWoods Stage."); + // "Shuffle the pool of grotto entrances, including all graves, small Fairy " + // "fountains and the Lost Woods Stage."); // SohImGui::EnhancementCombobox("gRandomizeShuffleGrottosEntrances", // randoShuffleGrottosEntrances, 2, 0); // ImGui::Unindent(); @@ -3771,9 +3765,8 @@ void DrawRandoEditor(bool& open) { // Bombchus in Logic // ImGui::Text("Bombchus in Logic"); // InsertHelpHoverText( - // "Bombchus are properly considered in logic.\nThey can be replenished in shops " - // "or trough\nbombchu " - // "drops, if those are enabled.\nBombchu Bowling is opened by bombchus."); + // "Bombchus are properly considered in logic.\nThey can be replenished in shops or " + // "through bombchu drops, if those are enabled.\nBombchu Bowling is opened by bombchus."); // SohImGui::EnhancementCombobox("gRandomizeBombchusInLogic", randoBombchusInLogic, 3, 0); // ImGui::Separator(); @@ -3783,17 +3776,17 @@ void DrawRandoEditor(bool& open) { // switch (CVar_GetS32("gRandomizeAmmoDrops", 0)) { // case 0: // InsertHelpHoverText( - // "Bombs, arrows, seeds, nuts, sticks and\nmagic jars appear as normal.\n" + // "Bombs, arrows, seeds, nuts, sticks and magic jars appear as normal.\n" // "Bombchus can sometimes replace bomb drops."); // break; // case 1: // InsertHelpHoverText( - // "All ammo drops will be replaced by blue rupees,\nexcept for Deku Sticks.\n" + // "All ammo drops will be replaced by blue rupees, except for Deku Sticks.\n" // "Ammo upgrades will only refill ammo by 10 units."); // break; // case 2: // InsertHelpHoverText( - // "Bombs, arrow, seeds, nuts, sticks and\nmagic jars appear as normal."); + // "Bombs, arrow, seeds, nuts, sticks and magic jars appear as normal."); // break; // } // SohImGui::EnhancementCombobox("gRandomizeAmmoDrops", randoAmmoDrops, 3, 0); @@ -3843,20 +3836,19 @@ void DrawRandoEditor(bool& open) { switch (CVar_GetS32("gRandomizeShuffleDungeonReward", 0)) { case 0: InsertHelpHoverText( - "Medallions and Spiritual Stones will be given as\nrewards for beating " - "dungeons.\n\nThis " - "setting will force Link's Pocket to be a\nMedallion or a Spiritual Stone."); + "Medallions and Spiritual Stones will be given as rewards for beating dungeons.\n" + "This setting will force Link's Pocket to be a Medallion or a Spiritual Stone."); break; case 1: InsertHelpHoverText( - "Medallions and Spiritual Stones can only appear\ninside of dungeons."); + "Medallions and Spiritual Stones can only appear inside of dungeons."); break; case 2: InsertHelpHoverText( - "Medallions and Spiritual Stones can only appear\noutside dungeons."); + "Medallions and Spiritual Stones can only appear outside dungeons."); break; case 3: - InsertHelpHoverText("Medallions and Spiritual Stones can appear\nanywhere."); + InsertHelpHoverText("Medallions and Spiritual Stones can appear anywhere."); break; } SohImGui::EnhancementCombobox("gRandomizeShuffleDungeonReward", randoShuffleDungeonRewards, 4, @@ -3869,16 +3861,16 @@ void DrawRandoEditor(bool& open) { // ImGui::Text("Link's Pocket"); // switch (CVar_GetS32("gRandomizeLinksPocket", 0)) { // case 0: - // InsertHelpHoverText("Link will start with a Dungeon Reward in his\ninventory."); + // InsertHelpHoverText("Link will start with a Dungeon Reward in his inventory."); // break; // case 1: - // InsertHelpHoverText("Link will receive a random advancement item at the\nbeginning " + // InsertHelpHoverText("Link will receive a random advancement item at the beginning " // "of the playtrough."); // break; // case 2: // InsertHelpHoverText( - // "Link will recieve a random item from the item pool\nat the beginning " - // "of the playthrought."); + // "Link will recieve a random item from the item pool at the beginning " + // "of the playthrough."); // break; // case 3: // InsertHelpHoverText("Link will start with a very useful green rupee."); @@ -3893,16 +3885,15 @@ void DrawRandoEditor(bool& open) { ImGui::Text("Shuffle Songs"); switch (CVar_GetS32("gRandomizeShuffleSongs", 0)) { case 0: - InsertHelpHoverText("Songs will only appear at locations that normally\nteach songs."); + InsertHelpHoverText("Songs will only appear at locations that normally teach songs."); break; case 1: InsertHelpHoverText("Songs appear at the end of dungeons.\nFor major dungeons, they " - "will be at the boss " - "heart container location.\nThe remaining 4 songs are placed " - "at:\n- Zelda's Lullaby " - "location\n- Ice Cavern's Serenade of Water Location\n- Bottom of " - "the Well's Lens of " - "Truth Location\n- Gerudo Training Ground's Ice Arrow Location."); + "will be at the boss heart container location.\nThe remaining 4 " + "songs are placed at:\n- Zelda's Lullaby location\n" + "- Ice Cavern's Serenade of Water Location\n" + "- Bottom of the Well's Lens of Truth Location\n" + "- Gerudo Training Ground's Ice Arrow Location."); break; case 2: InsertHelpHoverText("Songs can appear in any location"); @@ -3919,32 +3910,32 @@ void DrawRandoEditor(bool& open) { // InsertHelpHoverText("All shop items will be the same as vanilla."); // break; // case 1: - // InsertHelpHoverText("Vanilla shop items will be shuffled among\ndifferent shops."); + // InsertHelpHoverText("Vanilla shop items will be shuffled among different shops."); // break; // case 2: // InsertHelpHoverText( // "Vanilla shop items will be shuffled among different shops, and each " - // "shop will contain\n1 non-vanilla shop item."); + // "shop will contain 1 non-vanilla shop item."); // break; // case 3: // InsertHelpHoverText( // "Vanilla shop items will be shuffled among different shops, and each " - // "shop will contain\n2 non-vanilla shop items."); + // "shop will contain 2 non-vanilla shop items."); // break; // case 4: // InsertHelpHoverText( // "Vanilla shop items will be shuffled among different shops, and each " - // "shop will contain\n3 non-vanilla shop items."); + // "shop will contain 3 non-vanilla shop items."); // break; // case 5: // InsertHelpHoverText( // "Vanilla shop items will be shuffled among different shops, and each " - // "shop will contain\n4 non-vanilla shop items."); + // "shop will contain 4 non-vanilla shop items."); // break; // case 6: // InsertHelpHoverText( // "Vanilla shop items will be shuffled among different shops, and each " - // "shop will contain\n1 to 4 non-vanilla shop items."); + // "shop will contain 1 to 4 non-vanilla shop items."); // break; // } // SohImGui::EnhancementCombobox("gRandomizeShopsanity", randoShopsanity, 7, 0); @@ -3959,16 +3950,15 @@ void DrawRandoEditor(bool& open) { // break; // case 1: // InsertHelpHoverText( - // "This only shuffles 65 location that are\nwithing dungeons, increasing the value " - // "of " - // "most\ndungeons and making internal dungeon exploration\nmore diverse."); + // "This only shuffles 65 location that are within dungeons, increasing the value " + // "of most dungeons and making internal dungeon exploration more diverse."); // break; // case 2: // InsertHelpHoverText( - // "This only shuffles the 65 locations that are\noutside of dungeons."); + // "This only shuffles the 65 locations that are outside of dungeons."); // break; // case 3: - // InsertHelpHoverText("Effectively adds 100 new locations for items to\nappear."); + // InsertHelpHoverText("Effectively adds 100 new locations for items to appear."); // break; // } // SohImGui::EnhancementCombobox("gRandomizeTokensanity", randoTokensanity, 4, 0); @@ -3980,15 +3970,15 @@ void DrawRandoEditor(bool& open) { // switch (CVar_GetS32("gRandomizeShuffleScrubs", 0)) { // case 0: // InsertHelpHoverText( - // "Only the 3 Scrubs that give one-time items in the\nvanilla game (PoH, " - // "Deku Nut capacity, and Deku\nStick capacity) will have random items."); + // "Only the 3 Scrubs that give one-time items in the vanilla game (PoH, " + // "Deku Nut capacity, and Deku Stick capacity) will have random items."); // break; // case 1: // InsertHelpHoverText("All Scrub prices will be reduced to 10 rupees each."); // break; // case 2: // InsertHelpHoverText("All Scrub prices will be their vanilla prices.\nThis will require " - // "spending over 1000 rupees on\nSrubs."); + // "spending over 1000 rupees on Scrubs."); // break; // case 3: // InsertHelpHoverText("All Scrub prices will be between 0 to 95 rupees.\nThis will on " @@ -4002,16 +3992,16 @@ void DrawRandoEditor(bool& open) { // // Shuffle Cows // ImGui::Text("Shuffle Cows"); // InsertHelpHoverText( - // "Enabling this will let cows give you items upon\nperforming Epona's Song in " - // "front of them. There\nare 9 cows."); + // "Enabling this will let cows give you items upon performing Epona's Song in " + // "front of them. There are 9 cows."); // SohImGui::EnhancementCombobox("gRandomizeShuffleCows", randoShuffleCows, 2, 0); // ImGui::Separator(); if(CVar_GetS32("gRandomizeStartingKokiriSword", 0) == 0) { // Shuffle Kokiri Sword ImGui::Text("Shuffle Kokiri Sword"); - InsertHelpHoverText("Enabling this shuffles the Kokiri Sword into the item pool.\n\nThis will " - "require extensive use of sticks until\nthe sword is found."); + InsertHelpHoverText("Enabling this shuffles the Kokiri Sword into the item pool.\nThis will " + "require extensive use of sticks until the sword is found."); SohImGui::EnhancementCombobox("gRandomizeShuffleKokiriSword", randoShuffleKokiriSword, 2, 0); ImGui::Separator(); } @@ -4019,9 +4009,9 @@ void DrawRandoEditor(bool& open) { if(CVar_GetS32("gRandomizeStartingOcarina", 0) == 0) { // Shuffle Ocarinas ImGui::Text("Shuffle Ocarinas"); - InsertHelpHoverText("Enabling this shuffles the Fairy Ocarina and the\nOcarina of time into " - "the item pool.\n\nThis " - "will require finding an Ocarina before being\nable to play songs."); + InsertHelpHoverText("Enabling this shuffles the Fairy Ocarina and the Ocarina of time into " + "the item pool.\n" + "This will require finding an Ocarina before being able to play songs."); SohImGui::EnhancementCombobox("gRandomizeShuffleOcarinas", randoShuffleOcarinas, 2, 0); ImGui::Separator(); } @@ -4031,11 +4021,11 @@ void DrawRandoEditor(bool& open) { // Shuffle Weird Egg ImGui::Text("Shuffle Weird Egg"); InsertHelpHoverText( - "Enabling this shuffles the Weird Egg from Malon\ninto the item pool.\nThis " - "will require finding the Weird Egg to talk to\nZelda in Hyrule Castle which " - "in turn locks\nrewards from Impa, Xaria, Malon and Talon as\nwell as the " - "Happy Mask Sidequest. The Weird egg\nis also required for Zelda's Letter to " - "unlock the\nKakariko Gate as child which can lock some\nprogression."); + "Enabling this shuffles the Weird Egg from Malon into the item pool.\nThis " + "will require finding the Weird Egg to talk to Zelda in Hyrule Castle which " + "in turn unlocks rewards from Impa, Saria, Malon and Talon as well as the " + "Happy Mask Sidequest.\nThe Weird egg is also required for Zelda's Letter to " + "unlock the Kakariko Gate as child which can lock some progression."); SohImGui::EnhancementCombobox("gRandomizeShuffleWeirdEgg", randoShuffleWeirdEgg, 2, 0); ImGui::Separator(); } @@ -4043,16 +4033,16 @@ void DrawRandoEditor(bool& open) { // Shuffle Gerudo Membership Card ImGui::Text("Shuffle Gerudo Membership Card"); InsertHelpHoverText( - "Enabling this shuffles the Gerudo Membership Card into the\nitem pool.\n\nThe Gerudo " - "Token is required to enter the Gerudo\nTraining Ground."); + "Enabling this shuffles the Gerudo Membership Card into the item pool.\nThe Gerudo " + "Token is required to enter the Gerudo Training Ground."); SohImGui::EnhancementCombobox("gRandomizeShuffleGerudoToken", randoShuffleGerudoToken, 2, 0); ImGui::Separator(); // todo implement magic bean 10 pack // // Shuffle Magic Beans // ImGui::Text("Shuffle Magic Beans"); - // InsertHelpHoverText("Enabling this adds a pack of 10 beans to the item\n" - // "pool and changes the Magic Bean Salesman to sell a\n" + // InsertHelpHoverText("Enabling this adds a pack of 10 beans to the item " + // "pool and changes the Magic Bean Salesman to sell a " // "random item at a price of 60 rupees."); // SohImGui::EnhancementCombobox("gRandomizeShuffleMagicBeans", randoShuffleMagicBeans, 2, 0); // ImGui::Separator(); @@ -4062,13 +4052,13 @@ void DrawRandoEditor(bool& open) { // ImGui::Text("Shuffle Merchants"); // if (CVar_GetS32("gRandomizeShuffleMerchants", 0) == 0) { // InsertHelpHoverText( - // "Enabling this adds a Giant's Knife and a pack\nof Bombchus to the item " - // "pool and changes both\nMediagoron and the Haunted Wasteland " - // "Carpet\nSalesman to sell a random item once at the price\nof 200 rupees."); + // "Enabling this adds a Giant's Knife and a pack of Bombchus to the item " + // "pool and changes both Mediagoron and the Haunted Wasteland " + // "Carpet Salesman to sell a random item once at the price of 200 rupees."); // } else if (CVar_GetS32("gRandomizeShuffleMerchants", 0) <= 2) { // InsertHelpHoverText( - // "These hints will make Medigoron and the Carpet\nsalesman tell you which item they\'re " - // "selling.\n\nThe Clearer Hints setting will affect how they\nrefer to the item."); + // "These hints will make Medigoron and the Carpet salesman tell you which item they're " + // "selling.\nThe Clearer Hints setting will affect how they refer to the item."); // } // SohImGui::EnhancementCombobox("gRandomizeShuffleMerchants", randoShuffleMerchants, 3, 0); // ImGui::Separator(); @@ -4077,13 +4067,10 @@ void DrawRandoEditor(bool& open) { // Shuffle Adult Trade // ImGui::Text("Shuffle Adult Trade"); // InsertHelpHoverText( - // "Enabling this adds all of the adult trade quest\nitems to the pool, each of which can be " - // "traded\nfor a unique reward You will be able to choose\nwhich of your owner adult trade " - // "items " - // " " - // "is visible\nin the inventory by selecting the item and using\nthe L and R buttons If " - // "disabled " - // "only the Claim\nCheck will be found in the pool."); + // "Enabling this adds all of the adult trade quest items to the pool, each of which can be " + // "traded for a unique reward.\nYou will be able to choose which of your adult trade items " + // "are visible in the inventory by selecting the item and using the L and R buttons.\n" + // "If disabled only the Claim Check will be found in the pool."); // SohImGui::EnhancementCombobox("gRandomizeShuffleAdultTrade", randoShuffleAdultTrade, 2, 0); } ImGui::PopItemWidth(); @@ -4114,26 +4101,26 @@ void DrawRandoEditor(bool& open) { // ImGui::Text("Maps / Compasses"); // switch (CVar_GetS32("gRandomizeShuffleMapsAndCompasses", 0)) { // case 0: - // InsertHelpHoverText("Maps and Compasses can only appear in their repsective dungeon."); + // InsertHelpHoverText("Maps and Compasses can only appear in their respective dungeon."); // break; // case 1: // InsertHelpHoverText( - // "Maps and Compasses can only appear in a dungeon\nbut not necessarily the " + // "Maps and Compasses can only appear in a dungeon but not necessarily the " // "dungeon they are for."); // break; // case 2: - // InsertHelpHoverText("Maps and Compasses can only appear outside of\ndungeons."); + // InsertHelpHoverText("Maps and Compasses can only appear outside of dungeons."); // break; // case 3: - // InsertHelpHoverText("Maps and Compasses can appear anywhere in the\nworld."); + // InsertHelpHoverText("Maps and Compasses can appear anywhere in the world."); // break; // case 4: // InsertHelpHoverText( // "Maps and Compasses are given to you from the start.\nThis will add a " - // "small amount of money and\nrefill items to the pool."); + // "small amount of money and refill items to the pool."); // break; // case 5: - // InsertHelpHoverText("Maps and Compasses will appear in their vanilla\nlocations."); + // InsertHelpHoverText("Maps and Compasses will appear in their vanilla locations."); // break; // } // SohImGui::EnhancementCombobox("gRandomizeShuffleMapsAndCompasses", randoShuffleMapsAndCompasses, @@ -4145,28 +4132,28 @@ void DrawRandoEditor(bool& open) { // ImGui::Text("Small Keys"); // switch (CVar_GetS32("gRandomizeShuffleSmallKeys", 0)) { // case 0: - // InsertHelpHoverText("Small Keys can only appear in their respective\ndungeon."); + // InsertHelpHoverText("Small Keys can only appear in their respective dungeon."); // break; // case 1: // InsertHelpHoverText( - // "Small Keys can only appear inside of any dungon,\nbut won't necessarily " - // "be in the dungeon that the\nkey is for.\nA difficult mode since it is " - // "more likely\nto need to enter a dungeon multiple times."); + // "Small Keys can only appear inside of any dungon, but won't necessarily " + // "be in the dungeon that the key is for.\nA difficult mode since it is " + // "more likely to need to enter a dungeon multiple times."); // break; // case 2: // InsertHelpHoverText( // "Small Keys can only appear outside of dungeons.\nYou may need to enter a " - // "dungeon multiple times to\ngain items to access the overworld locations " - // "with\nthe keys required to finish a dungeon."); + // "dungeon multiple times to gain items to access the overworld locations " + // "with the keys required to finish a dungeon."); // break; // case 3: // InsertHelpHoverText( // "Small Keys can appear anywhere in the world.\nA difficult mode since it " - // "is more likely to need to\nenter a dungeon multiple times."); + // "is more likely to need to enter a dungeon multiple times."); // break; // case 4: // InsertHelpHoverText( - // "Small Keys are given to you from the start so you\nwon't have to worry " + // "Small Keys are given to you from the start so you won't have to worry " // "about locked doors.\nAn easier mode."); // break; // case 5: @@ -4182,18 +4169,17 @@ void DrawRandoEditor(bool& open) { // switch (CVar_GetS32("gRandomizeShuffleGerudoFortressKeys", 0)) { // case 0: // InsertHelpHoverText( - // "Gerudo Fortress Keys will appear in their vanilla\nlocation dropping " - // "from fighting Gerudo " - // "guard\nthat attack when trying to free the jailed\ncarpenters."); + // "Gerudo Fortress Keys will appear in their vanilla location dropping from " + // "fighting Gerudo guards that attack when trying to free the jailed carpenters."); // break; // case 1: - // InsertHelpHoverText("Gerudo Fortress Keys can only appear inside of\ndungeons."); + // InsertHelpHoverText("Gerudo Fortress Keys can only appear inside of dungeons."); // break; // case 2: - // InsertHelpHoverText("Gerudo Fortress Keys can only appear outside of\ndungeons."); + // InsertHelpHoverText("Gerudo Fortress Keys can only appear outside of dungeons."); // break; // case 3: - // InsertHelpHoverText("Gerudo Fortress Keys can appear anywhere in the\nworld."); + // InsertHelpHoverText("Gerudo Fortress Keys can appear anywhere in the world."); // break; // } // SohImGui::EnhancementCombobox("gRandomizeShuffleGerudoFortressKeys", @@ -4205,28 +4191,27 @@ void DrawRandoEditor(bool& open) { // ImGui::Text("Boss Keys"); // switch (CVar_GetS32("gRandomizeShuffleBossKeys", 0)) { // case 0: - // InsertHelpHoverText("Boss Keys can only appear in their respective\ndungeons."); + // InsertHelpHoverText("Boss Keys can only appear in their respective dungeons."); // break; // case 1: // InsertHelpHoverText( - // "Boss Keys can only appear inside of any dungeon,\nbut won't necessarily " - // "be in the dungon that the\nkey is for.\nA difficult mode since it is " - // "more\nlikely to need to enter a dungeon multiple times."); + // "Boss Keys can only appear inside of any dungeon, but won't necessarily " + // "be in the dungon that the key is for.\nA difficult mode since it is " + // "more likely to need to enter a dungeon multiple times."); // break; // case 2: // InsertHelpHoverText( - // "Boss keys can only appear outside of dungeons.\nYou may need to enter a dungeon " - // "without " - // "the boss\nkey to get items required to find the key in the\noverworld."); + // "Boss Keys can only appear outside of dungeons.\nYou may need to enter a dungeon " + // "without the boss key to get items required to find the key in the overworld."); // break; // case 3: // InsertHelpHoverText( - // "Boss key can appear anywhere in the overworld.\nA difficult mode since it " - // "is more likely to need to\nenter a dungeon multiple times."); + // "Boss Keys can appear anywhere in the overworld.\nA difficult mode since it " + // "is more likely to need to enter a dungeon multiple times."); // break; // case 4: // InsertHelpHoverText( - // "Boss Keys are given to you from the start so you\nwon't have to worry " + // "Boss Keys are given to you from the start so you won't have to worry " // "about boss doors.\nAn easier mode."); // break; // case 5: @@ -4245,80 +4230,80 @@ void DrawRandoEditor(bool& open) { switch (CVar_GetS32("gRandomizeShuffleGanonBossKey", 0)) { case 0: SetLastItemHoverText( - "Ganon's Boss Key is given to you from the\nstart and you don't " + "Ganon's Boss Key is given to you from the start and you don't " "have to worry about finding it."); break; case 1: - SetLastItemHoverText("Ganon's Boss Key will appear in the vanilla\nlocation."); + SetLastItemHoverText("Ganon's Boss Key will appear in the vanilla location."); break; case 2: - SetLastItemHoverText("Ganon's Boss Key will appear somewhere inside\nGanon's Castle."); + SetLastItemHoverText("Ganon's Boss Key will appear somewhere inside Ganon's Castle."); break; // case 0: // SetLastItemHoverText( - // "Ganon's Castle Boss Key can only appear inside of\na dungeon, but not " + // "Ganon's Castle Boss Key can only appear inside of a dungeon, but not " // "necessarily Ganon's Castle."); // break; // case 1: - // SetLastItemHoverText("Ganon's Castle Boss Key can only appear outside of\ndungeons."); + // SetLastItemHoverText("Ganon's Castle Boss Key can only appear outside of dungeons."); // break; // case 2: - // SetLastItemHoverText("Ganon's Castle Boss Key can appear anywhere in the\nworld."); + // SetLastItemHoverText("Ganon's Castle Boss Key can appear anywhere in the world."); // break; // case 3: // SetLastItemHoverText( - // "These settings put the boss key on the Light Arrow\nCutscene location, " - // "from Zelda in Temple of Time as\nadult, with differing requirements."); + // "These settings put the boss key on the Light Arrow Cutscene location, " + // "from Zelda in Temple of Time as adult, with differing requirements."); // break; // case 4: - // SetLastItemHoverText("Ganon's Caslte Boss Key can appear anywhere in the\nworld."); + // SetLastItemHoverText("Ganon's Castle Boss Key can appear anywhere in the world."); // break; // case 5: // SetLastItemHoverText( - // "These settings put the boss key on the Light Arrow\nCutscene location, " - // "from Zelda in Temple of Time as\nadult, with differing requirements."); + // "These settings put the boss key on the Light Arrow Cutscene location, " + // "from Zelda in Temple of Time as adult, with differing requirements."); // SohImGui::EnhancementSliderInt("Medallion Count: %d", "##RandoGanonMedallionCount", // "gRandomizeGanonMedallionCount", 0, 6, ""); // InsertHelpHoverText( - // "Set the number of Medallions required to trigger\nthe Light Arrow Cutscene."); + // "Set the number of Medallions required to trigger the Light Arrow Cutscene."); // break; // case 6: // SetLastItemHoverText( - // "These settings put the boss key on the Light Arrow\nCutscene location, " - // "from Zelda in Temple of Time as\nadult, with differing requirements."); + // "These settings put the boss key on the Light Arrow Cutscene location, " + // "from Zelda in Temple of Time as adult, with differing requirements."); // SohImGui::EnhancementSliderInt("Stone Count: %d", "##RandoGanonStoneCount", // "gRandomizeGanonStoneCount", 0, 3, ""); - // InsertHelpHoverText("Set the number of Spiritual Stones required to trigger\nthe Light " + // InsertHelpHoverText("Set the number of Spiritual Stones required to trigger the Light " // "Arrow Cutscene."); // break; // case 7: // SetLastItemHoverText( - // "These settings put the boss key on the Light Arrow\nCutscene location, " - // "from Zelda in Temple of Time as\nadult, with differing requirements."); + // "These settings put the boss key on the Light Arrow Cutscene location, " + // "from Zelda in Temple of Time as adult, with differing requirements."); // SohImGui::EnhancementSliderInt("Reward Count: %d", "##RandoGanonRewardCount", // "gRandomizeGanonRewardCount", 0, 9, ""); // InsertHelpHoverText( - // "Set the number of Dungeon Rewards (Spiritual\nStones and Medallions) " - // "required to trigger the\nLight Arrow Cutscene."); + // "Set the number of Dungeon Rewards (Spiritual Stones and Medallions) " + // "required to trigger the Light Arrow Cutscene."); // break; // case 8: // SetLastItemHoverText( - // "These settings put the boss key on the Light Arrow\nCutscene location, " - // "from Zelda in Temple of Time as\nadult, with differing requirements."); + // "These settings put the boss key on the Light Arrow Cutscene location, " + // "from Zelda in Temple of Time as adult, with differing requirements."); // SohImGui::EnhancementSliderInt("MDungeon Count: %d", "##RandoGanonDungeonCount", // "gRandomizeGanonDungeonCount", 0, 8, ""); // InsertHelpHoverText( - // "Set the number of completed dungeons required to\ntrigger the Light Arrow " - // "Cutscene.\n\nDungeons are considered complete when Link steps\ninto the " + // "Set the number of completed dungeons required to trigger the Light Arrow " + // "Cutscene.\nDungeons are considered complete when Link steps into the " // "blue warp at the end of them."); // break; // case 9: // SetLastItemHoverText( - // "These settings put the boss key on the Light Arrow\nCutscene location, " - // "from Zelda in Temple of Time as\nadult, with differing requirements."); + // "These settings put the boss key on the Light Arrow Cutscene location, " + // "from Zelda in Temple of Time as adult, with differing requirements."); // SohImGui::EnhancementSliderInt("Token Count: %d", "##RandoGanonTokenCount", // "gRandomizeGanonTokenCount", 0, 100, ""); - // InsertHelpHoverText("Set the number of Gold Skulltula Tokens required\nto trigger the " + // InsertHelpHoverText("Set the number of Gold Skulltula Tokens required to trigger the " // "Light Arrow Cutscene."); // break; } @@ -4342,82 +4327,82 @@ void DrawRandoEditor(bool& open) { // todo implement minigame repeat skip // // Skip Minigame repetition // SohImGui::EnhancementCheckbox("Skip Minigame Repetition", "gRandomizeSkipMinigameRepetition"); - // InsertHelpHoverText("Completing the second objective in the Dampe Race\nand Gerudo Archery on the " - // "first attempt will give\nboth rewards at once for that minigame."); + // InsertHelpHoverText("Completing the second objective in the Dampe Race and Gerudo Archery on the " + // "first attempt will give both rewards at once for that minigame."); // ImGui::Separator(); // todo implement free scarecrow (is this already in?) // // Free scarecrow // SohImGui::EnhancementCheckbox("Free Scarecrow", "gRandomizeFreeScarecrow"); // InsertHelpHoverText( - // "Pulling the Ocarina near a spot at which\nPierre can spawn will do so, without " - // "needing\nthe song."); + // "Pulling the Ocarina near a spot at which Pierre can spawn will do so, without " + // "needing the song."); // ImGui::Separator(); // todo implement skip poes (did we already?) // // Skip Four Poes cutscene // SohImGui::EnhancementCheckbox("Skip Four Poes Cutscene", "gRandomizeSkipFourPoesCutscene"); // InsertHelpHoverText( - // "The cutscene with the 4 poes in Forest Temple will\nbe skipped. If the cutscene " - // "is not skipped, it can\nbe exploited to reach the basement early."); + // "The cutscene with the 4 poes in Forest Temple will be skipped. If the cutscene " + // "is not skipped, it can be exploited to reach the basement early."); // ImGui::Separator(); // todo implement skip lake hylia owl // // Skip Lake Hylia owl // SohImGui::EnhancementCheckbox("Skip Lake Hylia Owl Cutscene", "gRandomizeSkipLakeHyliaOwl"); // InsertHelpHoverText( - // "The owl flight cutscene in Lake Hylia will be\nskipped. This cutscene lets you " - // "see what item\nis on top of the laboratory roof."); + // "The owl flight cutscene in Lake Hylia will be skipped. This cutscene lets you " + // "see what item is on top of the laboratory roof."); // ImGui::Separator(); // Cuccos to return SohImGui::EnhancementSliderInt("Cuccos to return: %d", "##RandoCuccosToReturn", "gRandomizeCuccosToReturn", 0, 7, "", 7); - InsertHelpHoverText("The cucco Lady will give a reward for returning\nthis many of her cuccos to the pen."); + InsertHelpHoverText("The cucco Lady will give a reward for returning this many of her cuccos to the pen."); ImGui::Separator(); // // Big Poe Target Count SohImGui::EnhancementSliderInt("Big Poe Target Count: %d", "##RandoBigPoeTargetCount", "gRandomizeBigPoeTargetCount", 1, 10, "", 10); - InsertHelpHoverText("The Poe buyer will give a reward for turning in\nthe chosen number of Big Poes."); + InsertHelpHoverText("The Poe buyer will give a reward for turning in the chosen number of Big Poes."); ImGui::Separator(); // // Skip child stealth SohImGui::EnhancementCheckbox("Skip Child Stealth", "gRandomizeSkipChildStealth"); - InsertHelpHoverText("The crawlspace into Hyrule Castle goes straight to\nZelda, skipping the guards."); + InsertHelpHoverText("The crawlspace into Hyrule Castle goes straight to Zelda, skipping the guards."); ImGui::Separator(); // Skip Epona race SohImGui::EnhancementCheckbox("Skip Epona Race", "gRandomizeSkipEponaRace"); - InsertHelpHoverText("Epona can be summoned with Epona's Song without\nneeding to race Ingo."); + InsertHelpHoverText("Epona can be summoned with Epona's Song without needing to race Ingo."); ImGui::Separator(); // Skip tower escape SohImGui::EnhancementCheckbox("Skip Tower Escape", "gRandomizeSkipTowerEscape"); - InsertHelpHoverText("The tower escape sequence between Ganondorf and\nGanon will be skipped."); + InsertHelpHoverText("The tower escape sequence between Ganondorf and Ganon will be skipped."); ImGui::Separator(); // todo implement complete mask quest // // Complete Mask Quest // SohImGui::EnhancementCheckbox("Complete Mask Quest", "gRandomizeCompleteMaskQuest"); // InsertHelpHoverText( - // "Once the Happy Mask Shop is opened, all masks\nwill be available to be borrowed."); + // "Once the Happy Mask Shop is opened, all masks will be available to be borrowed."); // ImGui::Separator(); // todo implement keep farores (in soh) // // Keep Farore's Wind Warp Point // SohImGui::EnhancementCheckbox("Keep Farore's Wind Warp Point", "gRandomizeKeepFaroresWindWarp"); // InsertHelpHoverText( - // "The Farore's Wind warp point will stay active\nafter having been warped to. The " - // "old point will\nneed to be dispelled before setting a new one."); + // "The Farore's Wind warp point will stay active after having been warped to.\nThe " + // "old point will need to be dispelled before setting a new one."); // ImGui::Separator(); // todo implement skip song replays (in soh) // // Skip Song Replays // ImGui::Text("Skip Song Replays"); // InsertHelpHoverText( - // "The automatic replay after you play a song will\nbe skipped.\nYou can choose to " - // "keep the SFX anyway, but you\nwill have control of Link during it."); + // "The automatic replay after you play a song will be skipped.\nYou can choose to " + // "keep the SFX anyway, but you will have control of Link during it."); // SohImGui::EnhancementCombobox("gRandomizeSkipSongReplays", randoSkipSongReplays, 3, 0); // ImGui::Separator(); @@ -4428,12 +4413,10 @@ void DrawRandoEditor(bool& open) { // Gossip Stone Hints ImGui::Text("Gossip Stone Hints"); InsertHelpHoverText( - "Gossip Stones can be made to give hints about\nwhere items can be found.\nDifferent settings " - "can " - "be chosen to decide which\nitem is needed to speak to Gossip Stones. Choosing\nto sticl with " - "the " - "Mask of Trutj will make the\nhints very difficult to obtain.\nHints for \"on the way of the " - "hero\" are locations\ntaht contain items that are required to beat the\ngame."); + "Gossip Stones can be made to give hints about where items can be found.\nDifferent settings can " + "be chosen to decide which item is needed to speak to Gossip Stones. \nChoosing to stick with the " + "Mask of Truth will make the hints very difficult to obtain.\nHints for \"on the way of the " + "hero\" are locations that contain items that are required to beat the game."); SohImGui::EnhancementCombobox("gRandomizeGossipStoneHints", randoGossipStoneHints, 4, 1); if (CVar_GetS32("gRandomizeGossipStoneHints", 1) != 0) { @@ -4443,18 +4426,18 @@ void DrawRandoEditor(bool& open) { switch (CVar_GetS32("gRandomizeHintClarity", 2)) { case 0: InsertHelpHoverText( - "Sets the difficulty of hints.\nObscure: Hints are unique for each thing, but\nthe " + "Sets the difficulty of hints.\nObscure: Hints are unique for each thing, but the " "writing may be confusing.\nEx: Kokiri Sword > a butter knife"); break; case 1: InsertHelpHoverText( "Sets the difficulty of hints.\nAmbiguous: Hints are clearly written, " - "but may\nrefer to more than one thing.\nEx: Kokiri Sword > a sword"); + "but may refer to more than one thing.\nEx: Kokiri Sword > a sword"); break; case 2: InsertHelpHoverText( "Sets the difficulty of hints.\nClear: Hints are clearly written and " - "are unique\nfor each thing.\nEx: Kokiri Sword > the Kokiri Sword"); + "are unique for each thing.\nEx: Kokiri Sword > the Kokiri Sword"); break; } SohImGui::EnhancementCombobox("gRandomizeHintClarity", randoHintClarity, 3, 2); @@ -4490,7 +4473,7 @@ void DrawRandoEditor(bool& open) { // todo implement starting time // // Starting Time // ImGui::Text("Starting Time"); - // InsertHelpHoverText("Change up Link's sleep routine."); + // InsertHelpHoverText("Change up Link's sleep routine."); // SohImGui::EnhancementCombobox("gRandomizeStartingTime", randoStartingTime, 2, 0); // ImGui::Separator(); @@ -4498,7 +4481,7 @@ void DrawRandoEditor(bool& open) { // // Chest Size and Color // ImGui::Text("Chest Size and Color"); // InsertHelpHoverText( - // "This option will change the appearance of all\nregular chests depending on their " + // "This option will change the appearance of all regular chests depending on their " // "contents:\nMajor Items = Big Wooden Chests\nLesser Items = Small Wooden " // "Chests\nBoss Keys = Big Fancy Chests\nSmall Keys = Small Fancy Chests"); // SohImGui::EnhancementCombobox("gRandomizeChestSizeAndColor", randoChestSizeAndColor, 2, 0); @@ -4509,11 +4492,11 @@ void DrawRandoEditor(bool& open) { // switch (CVar_GetS32("gRandomize", 0)) { // case 0: // InsertHelpHoverText( - // "All alternative traps will cause a small damage\nand no other negative effets."); + // "All alternative traps will cause small damage and no other negative effects."); // break; // case 1: - // InsertHelpHoverText("Some chest traps will burn your Deku Shield or\ncause a lot of damage " - // "(with one-hit protection)."); + // InsertHelpHoverText("Some chest traps will burn your Deku Shield or cause a lot of damage " + // "(with one-hit KO protection)."); // break; // case 2: // InsertHelpHoverText("All traps will be the base game ice trap."); @@ -4535,7 +4518,7 @@ void DrawRandoEditor(bool& open) { InsertHelpHoverText("Original item pool."); break; case 2: - InsertHelpHoverText("Some excess items are removed, including health\nupgrades."); + InsertHelpHoverText("Some excess items are removed, including health upgrades."); break; case 3: InsertHelpHoverText("Most excess items are removed."); @@ -4555,14 +4538,14 @@ void DrawRandoEditor(bool& open) { break; case 2: InsertHelpHoverText( - "Chance to add extra Ice Traps when junk items are\nadded to the item pool."); + "Chance to add extra Ice Traps when junk items are added to the item pool."); break; case 3: InsertHelpHoverText("All added junk items will be Ice Traps."); break; case 4: InsertHelpHoverText( - "All junk items will be replaced by Ice Traps, even\nthose in the base pool."); + "All junk items will be replaced by Ice Traps, even those in the base pool."); break; } SohImGui::EnhancementCombobox("gRandomizeIceTraps", randoIceTraps, 5, 1); @@ -4571,7 +4554,7 @@ void DrawRandoEditor(bool& open) { // todo implement double defense getitem // // Remove Double Defense // SohImGui::EnhancementCheckbox("Remove Double Defense", "gRandomizeRemoveDoubleDefense"); - // InsertHelpHoverText("If set the double defense item will be removed\nfrom the item pool for " + // InsertHelpHoverText("If set the double defense item will be removed from the item pool for " // "balanced and plentiful."); // ImGui::Separator(); @@ -4579,8 +4562,8 @@ void DrawRandoEditor(bool& open) { // // Prog Goron Sword // SohImGui::EnhancementCheckbox("Prog Goron Sword", "gRandomizeProgGoronSword"); // InsertHelpHoverText( - // "Giant's Knife will walays be found before Biggoron's\nSword. Medigoron only " - // "starts selling new knives\nonce the Giant's Knife has been found\nand broken."); + // "Giant's Knife will always be found before Biggoron's Sword.\nMedigoron only " + // "starts selling new knives once the Giant's Knife has been found and broken."); // ImGui::Separator(); ImGui::PopItemWidth(); ImGui::EndTable(); diff --git a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp index 3e7756e34..2dcef684c 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp @@ -985,7 +985,7 @@ void DrawItemTracker(bool& open) { } SohImGui::EnhancementCheckbox("Display \"Ammo/MaxAmo\"", "gItemTrackerAmmoDisplay"); SohImGui::EnhancementCheckbox("Randomizer colors for Songs", "gItemTrackeSongColor"); - SohImGui::Tooltip("Will dispaly non-warp songs with randomizer\ncolors instead of pure white"); + SohImGui::Tooltip("Will display non-warp songs with randomizer colors instead of pure white"); SohImGui::EnhancementSliderInt("Icon size : %dpx", "##ITEMTRACKERICONSIZE", "gRandoTrackIconSize", 32, 128, ""); SohImGui::EnhancementSliderInt("X spacing : %dpx", "##ITEMTRACKERSPACINGX", "gRandoTrackIconSpacingX", minimalSpacingX, 256, From 206f63f9e6ac7f6aabf78789e3b9f48bc5761fad Mon Sep 17 00:00:00 2001 From: InfoManiac742 <26778801+InfoManiac742@users.noreply.github.com> Date: Sun, 31 Jul 2022 18:48:43 -0700 Subject: [PATCH 18/25] Fix build link in README (#944) Currently leads to a 404 page since there's no longer a branch called "develop", I've just sent it to the main page for the builds site --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index baae758c9..48faf9d07 100644 --- a/README.md +++ b/README.md @@ -83,7 +83,7 @@ Refer to the [building instructions](BUILDING.md) to compile SoH. - Confirm that `zapd.exe` exists in the `/assets/extractor` folder ## Nightly Builds -Nightly builds of Ship of Harkinian are available [here](https://builds.shipofharkinian.com/job/SoH_Multibranch/job/develop) +Nightly builds of Ship of Harkinian are available [here](https://builds.shipofharkinian.com/) ## The Harbour Masters Are... From a1ed35e5bde7392ab94f113c60864960251d9e72 Mon Sep 17 00:00:00 2001 From: KiritoDev <36680385+KiritoDv@users.noreply.github.com> Date: Sun, 31 Jul 2022 20:49:54 -0500 Subject: [PATCH 19/25] Fixed slowdown on dodongo (#945) * Fixed slowdown on dodongo * Invalidate only works on pc * Added todo comment --- soh/src/overlays/actors/ovl_Boss_Dodongo/z_boss_dodongo.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/soh/src/overlays/actors/ovl_Boss_Dodongo/z_boss_dodongo.c b/soh/src/overlays/actors/ovl_Boss_Dodongo/z_boss_dodongo.c index 37105d040..721fcf51c 100644 --- a/soh/src/overlays/actors/ovl_Boss_Dodongo/z_boss_dodongo.c +++ b/soh/src/overlays/actors/ovl_Boss_Dodongo/z_boss_dodongo.c @@ -1697,7 +1697,10 @@ void BossDodongo_DrawEffects(GlobalContext* globalCtx) { func_80093D84(globalCtx->state.gfxCtx); unkMtx = &globalCtx->billboardMtxF; + // OTRTODO: This call causes the whole texture cache to be cleaned up, which causes an important slowdown on switch so we need to find a way to avoid it. +#ifndef __SWITCH__ gSPInvalidateTexCache(POLY_XLU_DISP++, 0); +#endif for (i = 0; i < 80; i++, eff++) { if (eff->unk_24 == 1) { From d648c7275c1a63d0fd15eb8229231c5ad5cc96f9 Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Sun, 31 Jul 2022 20:51:36 -0500 Subject: [PATCH 20/25] Hide Dpad in minimal UI (#955) --- soh/src/code/z_parameter.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index 40f2c2678..44d529587 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -4745,12 +4745,14 @@ void Interface_Draw(GlobalContext* globalCtx) { } else { gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 255, 255, 255, dpadAlpha); } - gDPLoadTextureBlock(OVERLAY_DISP++, ResourceMgr_LoadFileRaw("assets/ship_of_harkinian/buttons/dpad.bin"), - G_IM_FMT_IA, G_IM_SIZ_16b, 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++, DpadPosX << 2, DpadPosY << 2, - (DpadPosX + 32) << 2, (DpadPosY + 32) << 2, - G_TX_RENDERTILE, 0, 0, (1 << 10), (1 << 10)); + if (fullUi) { + gDPLoadTextureBlock(OVERLAY_DISP++, ResourceMgr_LoadFileRaw("assets/ship_of_harkinian/buttons/dpad.bin"), + G_IM_FMT_IA, G_IM_SIZ_16b, 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++, DpadPosX << 2, DpadPosY << 2, + (DpadPosX + 32) << 2, (DpadPosY + 32) << 2, + G_TX_RENDERTILE, 0, 0, (1 << 10), (1 << 10)); + } // DPad-Up Button Icon & Ammo Count if (gSaveContext.equips.buttonItems[4] < 0xF0) { From 4f29833476817a91b40da1177d2815e775f91537 Mon Sep 17 00:00:00 2001 From: Kenix3 Date: Sun, 31 Jul 2022 21:52:10 -0400 Subject: [PATCH 21/25] Adds beta quest Gameshark cheat. (#975) * Adds beta quest Gameshark cheat. * Fixes issue where lus was including a function from soh. * Limits beta quest to 0-8 --- libultraship/libultraship/ImGuiImpl.cpp | 79 +++++++++++++++++++++++++ libultraship/libultraship/ImGuiImpl.h | 12 ++++ soh/src/code/z_common_data.c | 2 +- soh/src/code/z_play.c | 4 +- 4 files changed, 95 insertions(+), 2 deletions(-) diff --git a/libultraship/libultraship/ImGuiImpl.cpp b/libultraship/libultraship/ImGuiImpl.cpp index ea779b677..e01026b10 100644 --- a/libultraship/libultraship/ImGuiImpl.cpp +++ b/libultraship/libultraship/ImGuiImpl.cpp @@ -68,6 +68,13 @@ OSContPad* pads; std::map DefaultAssets; std::vector emptyArgs; +bool isBetaQuestEnabled = false; + +extern "C" { + void enableBetaQuest() { isBetaQuestEnabled = true; } + void disableBetaQuest() { isBetaQuestEnabled = false; } +} + namespace SohImGui { WindowImpl impl; @@ -1404,6 +1411,78 @@ namespace SohImGui { EnhancementCheckbox("Shield with Two-Handed Weapons", "gShieldTwoHanded"); Tooltip("This allows you to put up your shield with any two-handed weapon in hand except for Deku Sticks"); + { + static int32_t betaQuestEnabled = CVar_GetS32("gEnableBetaQuest", 0); + static int32_t lastBetaQuestEnabled = betaQuestEnabled; + static int32_t betaQuestWorld = CVar_GetS32("gBetaQuestWorld", 0xFFEF); + static int32_t lastBetaQuestWorld = betaQuestWorld; + + if (!isBetaQuestEnabled) { + ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true); + ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f); + } + + EnhancementCheckbox("Enable Beta Quest", "gEnableBetaQuest"); + Tooltip("Turns on OoT Beta Quest. *WARNING* This will reset your game."); + betaQuestEnabled = CVar_GetS32("gEnableBetaQuest", 0); + if (betaQuestEnabled) { + if (betaQuestEnabled != lastBetaQuestEnabled) { + betaQuestWorld = 0; + } + + ImGui::Text("Beta Quest World: %d", betaQuestWorld); + + if (ImGui::Button(" - ##BetaQuest")) { + betaQuestWorld--; + } + ImGui::SameLine(); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); + + ImGui::SliderInt("##BetaQuest", &betaQuestWorld, 0, 8, "", ImGuiSliderFlags_AlwaysClamp); + Tooltip("Set the Beta Quest world to explore. *WARNING* Changing this will reset your game.\nCtrl+Click to type in a value."); + + ImGui::Text("After Slider Beta Quest World: %d", betaQuestWorld); + + + ImGui::SameLine(); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); + if (ImGui::Button(" + ##BetaQuest")) { + betaQuestWorld++; + } + + if (betaQuestWorld > 8) { + betaQuestWorld = 8; + } + else if (betaQuestWorld < 0) { + betaQuestWorld = 0; + } + + ImGui::Text("After Clamp Beta Quest World: %d", betaQuestWorld); + } + else { + lastBetaQuestWorld = betaQuestWorld = 0xFFEF; + CVar_SetS32("gBetaQuestWorld", betaQuestWorld); + needs_save = true; + } + if (betaQuestEnabled != lastBetaQuestEnabled || betaQuestWorld != lastBetaQuestWorld) + { + // Reset the game if the beta quest state or world changed because beta quest happens on redirecting the title screen cutscene. + lastBetaQuestEnabled = betaQuestEnabled; + lastBetaQuestWorld = betaQuestWorld; + CVar_SetS32("gEnableBetaQuest", betaQuestEnabled); + CVar_SetS32("gBetaQuestWorld", betaQuestWorld); + + console->Commands["reset"].handler(emptyArgs); + + needs_save = true; + } + + if (!isBetaQuestEnabled) { + ImGui::PopItemFlag(); + ImGui::PopStyleVar(); + } + } + ImGui::EndMenu(); } diff --git a/libultraship/libultraship/ImGuiImpl.h b/libultraship/libultraship/ImGuiImpl.h index eb007efeb..01235d411 100644 --- a/libultraship/libultraship/ImGuiImpl.h +++ b/libultraship/libultraship/ImGuiImpl.h @@ -1,5 +1,15 @@ #pragma once +#ifdef __cplusplus +extern "C" { +#endif + void enableBetaQuest(); + void disableBetaQuest(); +#ifdef __cplusplus +} +#endif + +#ifdef __cplusplus #include "GameOverlay.h" #include "Lib/ImGui/imgui.h" #include "Console.h" @@ -97,3 +107,5 @@ namespace SohImGui { std::string BreakTooltip(const char* text, int lineLength = 60); std::string BreakTooltip(const std::string& text, int lineLength = 60); } + +#endif \ No newline at end of file diff --git a/soh/src/code/z_common_data.c b/soh/src/code/z_common_data.c index c92a36b71..53334fb84 100644 --- a/soh/src/code/z_common_data.c +++ b/soh/src/code/z_common_data.c @@ -8,7 +8,7 @@ void SaveContext_Init(void) { gSaveContext.seqId = (u8)NA_BGM_DISABLED; gSaveContext.natureAmbienceId = NATURE_ID_DISABLED; gSaveContext.forcedSeqId = NA_BGM_GENERAL_SFX; - gSaveContext.nextCutsceneIndex = 0xFFEF; + gSaveContext.nextCutsceneIndex = CVar_GetS32("gBetaQuestWorld", 0xFFEF); gSaveContext.cutsceneTrigger = 0; gSaveContext.chamberCutsceneNum = 0; gSaveContext.nextDayTime = 0xFFFF; diff --git a/soh/src/code/z_play.c b/soh/src/code/z_play.c index 5656f4c07..763ed1ee8 100644 --- a/soh/src/code/z_play.c +++ b/soh/src/code/z_play.c @@ -4,7 +4,7 @@ #include #include "soh/Enhancements/gameconsole.h" - +#include "../libultraship/ImGuiImpl.h" #include "soh/frame_interpolation.h" void* D_8012D1F0 = NULL; @@ -190,6 +190,7 @@ void Gameplay_Destroy(GameState* thisx) { KaleidoManager_Destroy(); ZeldaArena_Cleanup(); Fault_RemoveClient(&D_801614B8); + disableBetaQuest(); gGlobalCtx = NULL; } @@ -260,6 +261,7 @@ void GivePlayerRandoRewardSariaGift(GlobalContext* globalCtx, RandomizerCheck ch void Gameplay_Init(GameState* thisx) { GlobalContext* globalCtx = (GlobalContext*)thisx; GraphicsContext* gfxCtx = globalCtx->state.gfxCtx; + enableBetaQuest(); gGlobalCtx = globalCtx; //globalCtx->state.gfxCtx = NULL; uintptr_t zAlloc; From 9389ceb8c12c3e9d29b3e6428eb2ff07791d59ed Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Sun, 31 Jul 2022 21:09:30 -0500 Subject: [PATCH 22/25] Speed up lifting silver rocks and obelisks by 5x (#953) * Speed up lifting silver rocks and obelisks by 3x * Increase rock lifting speed to 5x * Fix bug that sped up picking up small rocks, grass, bombflowers * Add enhancement checkbox for faster block lifting and reduced speed to 3x --- libultraship/libultraship/ImGuiImpl.cpp | 2 ++ soh/src/code/z_onepointdemo.c | 19 +++++++++++++++++++ soh/src/code/z_onepointdemo_data.inc | 6 +++--- .../actors/ovl_player_actor/z_player.c | 6 +++++- 4 files changed, 29 insertions(+), 4 deletions(-) diff --git a/libultraship/libultraship/ImGuiImpl.cpp b/libultraship/libultraship/ImGuiImpl.cpp index e01026b10..c3dc8e23f 100644 --- a/libultraship/libultraship/ImGuiImpl.cpp +++ b/libultraship/libultraship/ImGuiImpl.cpp @@ -990,6 +990,8 @@ namespace SohImGui { EnhancementSliderInt("Vine/Ladder Climb speed +%d", "##CLIMBSPEED", "gClimbSpeed", 0, 12, ""); EnhancementCheckbox("Faster Block Push", "gFasterBlockPush"); + EnhancementCheckbox("Faster Heavy Block Lift", "gFasterHeavyBlockLift"); + Tooltip("Speeds up lifting silver rocks and obelisks"); EnhancementCheckbox("No Forced Navi", "gNoForcedNavi"); Tooltip("Prevent forced Navi conversations"); EnhancementCheckbox("No Skulltula Freeze", "gSkulltulaFreeze"); diff --git a/soh/src/code/z_onepointdemo.c b/soh/src/code/z_onepointdemo.c index 5dcdeb2e4..2fd692da8 100644 --- a/soh/src/code/z_onepointdemo.c +++ b/soh/src/code/z_onepointdemo.c @@ -1041,18 +1041,37 @@ s32 OnePointCutscene_SetInfo(GlobalContext* globalCtx, s16 camIdx, s16 csId, Act func_800C0808(globalCtx, camIdx, player, CAM_SET_CS_C); break; case 4020: + if (CVar_GetS32("gFasterHeavyBlockLift", 0)) { + D_8012368C[0].timerInit *= (1.0f / 3.0f); + D_8012368C[1].timerInit *= (1.0f / 3.0f); + D_8012368C[2].timerInit *= (1.0f / 3.0f); + D_8012368C[3].timerInit *= (1.0f / 3.0f); + } csInfo->keyFrames = D_8012368C; csInfo->keyFrameCnt = 4; func_800C0808(globalCtx, camIdx, player, CAM_SET_CS_C); break; case 4021: + if (CVar_GetS32("gFasterHeavyBlockLift", 0)) { + D_8012372C[0].timerInit *= (1.0f / 3.0f); + D_8012372C[1].timerInit *= (1.0f / 3.0f); + D_8012372C[2].timerInit *= (1.0f / 3.0f); + D_8012372C[3].timerInit *= (1.0f / 3.0f); + } csInfo->keyFrames = D_8012372C; csInfo->keyFrameCnt = 4; func_800C0808(globalCtx, camIdx, player, CAM_SET_CS_C); break; case 4022: + if (CVar_GetS32("gFasterHeavyBlockLift", 0)) { + D_801237CC[0].timerInit *= (1.0f / 3.0f); + D_801237CC[1].timerInit *= (1.0f / 3.0f); + D_801237CC[2].timerInit *= (1.0f / 3.0f); + D_801237CC[3].timerInit *= (1.0f / 3.0f); + D_801237CC[4].timerInit *= (1.0f / 3.0f); + } csCam->timer = D_801237CC[0].timerInit + D_801237CC[3].timerInit + D_801237CC[1].timerInit + D_801237CC[2].timerInit + D_801237CC[4].timerInit; diff --git a/soh/src/code/z_onepointdemo_data.inc b/soh/src/code/z_onepointdemo_data.inc index 2488be71b..216340f40 100644 --- a/soh/src/code/z_onepointdemo_data.inc +++ b/soh/src/code/z_onepointdemo_data.inc @@ -624,21 +624,21 @@ static OnePointCsFull D_801235C4[5] = { { 0x12, 0xFF, 0x0000, 1, 0, 60.0f, 1.0f, { -1.0f, -1.0f, -1.0f }, { -1.0f, -1.0f, -1.0f } }, }; -static OnePointCsFull D_8012368C[4] = { +OnePointCsFull D_8012368C[4] = { { 0x0F, 0xFF, 0x0101, 10, 0, 60.0f, 1.0f, { -1110.0f, -180.0f, -840.0f }, { -985.0f, -220.0f, -840.0f } }, { 0x02, 0xFF, 0x0101, 70, -45, 75.0f, 1.0f, { -1060.0f, -160.0f, -840.0f }, { -1005.0f, -230.0f, -840.0f } }, { 0x0F, 0xFF, 0x0000, 10, -45, 75.0f, 1.0f, { -1.0f, -1.0f, -1.0f }, { -1.0f, -1.0f, -1.0f } }, { 0x0F, 0xFF, 0x0101, 180, 9, 80.0f, 1.0f, { -1205.0f, -175.0f, -840.0f }, { -1305.0f, -230.0f, -828.0f } }, }; -static OnePointCsFull D_8012372C[4] = { +OnePointCsFull D_8012372C[4] = { { 0x0F, 0xFF, 0x0142, 10, 0, 70.0f, 1.0f, { 0.0f, 80.0f, 0.0f }, { -1650.0f, 200.0f, -2920.0f } }, { 0x02, 0xFF, 0x0142, 110, -2, 50.0f, 0.5f, { 0.0f, 150.0f, 0.0f }, { -1320.0f, 170.0f, -2900.0f } }, { 0x0B, 0xFF, 0x4242, 100, 2, 70.0f, 0.1f, { 0.0f, 150.0f, 50.0f }, { -1.0f, -1.0f, -1.0f } }, { 0x03, 0xFF, 0x4242, 60, 2, 45.0f, 0.01f, { 0.0f, 150.0f, 50.0f }, { 0.0f, 200.0f, -80.0f } }, }; -static OnePointCsFull D_801237CC[5] = { +OnePointCsFull D_801237CC[5] = { { 0x8F, 0xFF, 0x4242, 20, 0, 50.0f, 1.0f, { 0.0f, 50.0f, -10.0f }, { 0.0f, 0.0f, 100.0f } }, { 0x0A, 0xFF, 0x0101, 80, 0, 75.0f, 1.0f, { 2900.0f, 1300.0f, 530.0f }, { 2800.0f, 1190.0f, 540.0f } }, { 0x0F, 0xFF, 0x0000, 10, 0, 75.0f, 1.0f, { -1.0f, -1.0f, -1.0f }, { -1.0f, -1.0f, -1.0f } }, 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 306a460d3..844e301a9 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -4648,7 +4648,11 @@ void func_8083A0F4(GlobalContext* globalCtx, Player* this) { anim = D_80853914[PLAYER_ANIMGROUP_13][this->modelAnimType]; } - func_80832264(globalCtx, this, anim); + if (CVar_GetS32("gFasterHeavyBlockLift", 0) && interactActorId == ACTOR_BG_HEAVY_BLOCK) { + LinkAnimation_PlayOnceSetSpeed(globalCtx, &this->skelAnime, anim, 3.0f); + } else { + LinkAnimation_PlayOnce(globalCtx, &this->skelAnime, anim); + } } } else { From 4ed82c71dc9e24748cb06a6c70f4d52e87372ecc Mon Sep 17 00:00:00 2001 From: David Chavez Date: Mon, 1 Aug 2022 09:18:48 +0200 Subject: [PATCH 23/25] Fix c++20 clang issue --- soh/soh/Enhancements/debugconsole.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soh/soh/Enhancements/debugconsole.cpp b/soh/soh/Enhancements/debugconsole.cpp index 85a8c3829..ba866b062 100644 --- a/soh/soh/Enhancements/debugconsole.cpp +++ b/soh/soh/Enhancements/debugconsole.cpp @@ -529,7 +529,7 @@ void DebugConsole_LoadLegacyCVars() { if (cfg[1].find("\"") == std::string::npos && (cfg[1].find("#") != std::string::npos)) { std::string value(cfg[1]); - value.erase(std::ranges::remove(value, '#').begin(), value.end()); + value.erase(std::remove_if(value.begin(), value.end(), [](char c) { return c == '#'; }), value.end()); auto splitTest = StringHelper::Split(value, "\r")[0]; uint32_t val = std::stoul(splitTest, nullptr, 16); From 61c68666d622bddf1c8964cb3160ce5d0198af74 Mon Sep 17 00:00:00 2001 From: David Chavez Date: Tue, 2 Aug 2022 16:22:20 +0200 Subject: [PATCH 24/25] Closer align Makefiles & Dockerfiles (#748) --- .ci/switch/buildswitch.bash | 11 --- BUILDING.md | 7 -- Dockerfile | 81 +++++++++++-------- Dockerfile.switch | 58 ------------- Jenkinsfile | 19 +++-- ZAPDTR/Makefile | 18 +++-- libultraship/Makefile | 7 +- .../linux/build-appimage.sh | 2 +- scripts/linux/build.sh | 11 +++ {appimage => scripts/linux}/soh.desktop | 0 {appimage => scripts/linux}/soh.sh | 0 scripts/switch/build.sh | 4 + soh/Makefile | 69 +++++++--------- soh/include/z64.h | 2 +- .../Enhancements/debugger/debugSaveEditor.cpp | 2 +- 15 files changed, 116 insertions(+), 175 deletions(-) delete mode 100755 .ci/switch/buildswitch.bash delete mode 100644 Dockerfile.switch rename appimage/appimage.sh => scripts/linux/build-appimage.sh (96%) create mode 100755 scripts/linux/build.sh rename {appimage => scripts/linux}/soh.desktop (100%) rename {appimage => scripts/linux}/soh.sh (100%) create mode 100755 scripts/switch/build.sh diff --git a/.ci/switch/buildswitch.bash b/.ci/switch/buildswitch.bash deleted file mode 100755 index 032b19157..000000000 --- a/.ci/switch/buildswitch.bash +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash - -cp -av /usr/local/lib/libSDL2* /lib/x86_64-linux-gnu/ -git config --global --add safe.directory /soh -make setup -C soh -j$(nproc) OPTFLAGS=-O2 DEBUG=0 CC="gcc" CXX="g++" - -/opt/devkitpro/portlibs/switch/bin/aarch64-none-elf-cmake -B StormLib/build-switch -S StormLib -DCMAKE_INSTALL_PREFIX=/opt/devkitpro/portlibs/switch/ -make -C StormLib/build-switch -j$(nproc) -make install -C StormLib/build-switch - -make -f Makefile.switch -j$(nproc) OPTFLAGS=-O2 DEBUG=0 diff --git a/BUILDING.md b/BUILDING.md index 70ddd16b4..2a52e3f58 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -32,13 +32,6 @@ sudo docker run --rm -it -v $(pwd):/soh soh /bin/bash ``` Inside the Docker container: ```bash -# Clone and build StormLib -git clone https://github.com/ladislav-zezula/StormLib external/StormLib -cmake -B external/StormLib/build -S external/StormLib -cmake --build external/StormLib/build -cp external/StormLib/build/libstorm.a external -cp /usr/local/lib/libGLEW.a external - cd soh # Extract the assets/Compile the exporter/Run the exporter make setup -j$(nproc) OPTFLAGS=-O2 DEBUG=0 diff --git a/Dockerfile b/Dockerfile index 279674229..bf7d49ad5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,45 +3,56 @@ FROM ubuntu:20.04 as build ENV LANG C.UTF-8 ARG DEBIAN_FRONTEND=noninteractive +ENV GCCVER=10 RUN apt-get update && \ - apt-get upgrade -y && \ - apt-get install -y \ - binutils \ - gcc-10 \ - g++-10 \ - patchelf \ - p7zip-full \ - python3.9 \ - make \ - cmake \ - curl \ - git \ - lld \ - libsdl2-dev \ - zlib1g-dev \ - libbz2-dev \ - libpng-dev \ - libgles2-mesa-dev && \ - ln -s /usr/bin/g++-10 /usr/bin/g++ && \ - update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 10 && \ - gcc --version && \ - g++ --version - -RUN apt-get clean autoclean && apt-get autoremove --yes && rm -rf /var/lib/apt /var/lib/cache /var/lib/log - + apt-get upgrade -y && \ + apt-get install -y \ + binutils \ + gcc-${GCCVER} \ + g++-${GCCVER} \ + p7zip-full \ + python3 \ + make \ + cmake \ + curl \ + git \ + lld \ + wget \ + libglew-dev \ + libsdl2-dev \ + zlib1g-dev \ + libbz2-dev \ + libpng-dev \ + libgles2-mesa-dev && \ + update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-${GCCVER} 10 && \ + update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-${GCCVER} 10 + RUN git clone https://github.com/Perlmint/glew-cmake.git && \ - cmake glew-cmake && \ - make -j$(nproc) && \ - make install - + cmake glew-cmake && \ + make -j$(nproc) && \ + make install + ENV SDL2VER=2.0.22 RUN curl -sLO https://libsdl.org/release/SDL2-${SDL2VER}.tar.gz && \ - tar -xzf SDL2-${SDL2VER}.tar.gz && \ - cd SDL2-${SDL2VER} && \ - ./configure --prefix=/usr && \ - make && make install && \ - rm ../SDL2-${SDL2VER}.tar.gz && \ - cp -av /lib/libSDL* /lib/x86_64-linux-gnu/ + tar -xzf SDL2-${SDL2VER}.tar.gz && \ + cd SDL2-${SDL2VER} && \ + ./configure --build=x86_64-linux-gnu && \ + make -j$(nproc) && make install && \ + rm ../SDL2-${SDL2VER}.tar.gz + +RUN \ + ln -sf /proc/self/mounts /etc/mtab && \ + mkdir -p /usr/local/share/keyring/ && \ + wget -O /usr/local/share/keyring/devkitpro-pub.gpg https://apt.devkitpro.org/devkitpro-pub.gpg && \ + echo "deb [signed-by=/usr/local/share/keyring/devkitpro-pub.gpg] https://apt.devkitpro.org stable main" > /etc/apt/sources.list.d/devkitpro.list && \ + apt-get update -y && \ + apt-get install -y devkitpro-pacman && \ + yes | dkp-pacman -Syu switch-dev switch-portlibs --noconfirm + +ENV DEVKITPRO=/opt/devkitpro +ENV DEVKITARM=/opt/devkitpro/devkitARM +ENV DEVKITPPC=/opt/devkitpro/devkitPPC +ENV PATH=$PATH:/opt/devkitpro/portlibs/switch/bin/ RUN mkdir /soh WORKDIR /soh diff --git a/Dockerfile.switch b/Dockerfile.switch deleted file mode 100644 index 7319f22a6..000000000 --- a/Dockerfile.switch +++ /dev/null @@ -1,58 +0,0 @@ -FROM ubuntu:20.04 as build - -ENV LANG C.UTF-8 -ARG DEBIAN_FRONTEND=noninteractive - -ENV GCCVER=10 -RUN \ - apt-get update && \ - apt-get upgrade -y && \ - apt-get install -y \ - binutils \ - gcc-10 \ - g++-10 \ - p7zip-full \ - python3 \ - make \ - cmake \ - curl \ - git \ - lld \ - wget \ - libsdl2-dev \ - zlib1g-dev \ - libbz2-dev \ - libpng-dev \ - libgles2-mesa-dev && \ - update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-${GCCVER} 10 && \ - update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-${GCCVER} 10 - -RUN git clone https://github.com/Perlmint/glew-cmake.git && \ - cmake glew-cmake && \ - make -j$(nproc) && \ - make install ARCH64=true - -ENV SDL2VER=2.0.22 -RUN curl -sLO https://libsdl.org/release/SDL2-${SDL2VER}.tar.gz && \ - tar -xzf SDL2-${SDL2VER}.tar.gz && \ - cd SDL2-${SDL2VER} && \ - ./configure --build=x86_64-linux-gnu && \ - make && make install && \ - rm ../SDL2-${SDL2VER}.tar.gz - -RUN \ - ln -sf /proc/self/mounts /etc/mtab && \ - mkdir -p /usr/local/share/keyring/ && \ - wget -O /usr/local/share/keyring/devkitpro-pub.gpg https://apt.devkitpro.org/devkitpro-pub.gpg && \ - echo "deb [signed-by=/usr/local/share/keyring/devkitpro-pub.gpg] https://apt.devkitpro.org stable main" > /etc/apt/sources.list.d/devkitpro.list && \ - apt-get update -y && \ - apt-get install -y devkitpro-pacman && \ - yes | dkp-pacman -Syu switch-dev switch-portlibs --noconfirm - -ENV DEVKITPRO=/opt/devkitpro -ENV DEVKITARM=/opt/devkitpro/devkitARM -ENV DEVKITPPC=/opt/devkitpro/devkitPPC -ENV PATH=$PATH:/opt/devkitpro/portlibs/switch/bin/ - -RUN mkdir /soh -WORKDIR /soh diff --git a/Jenkinsfile b/Jenkinsfile index 033f1f758..60f022253 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -97,8 +97,7 @@ pipeline { cp ../../ZELOOTD.z64 OTRExporter/baserom_non_mq.z64 docker build . -t soh docker run --name sohcont -dit --rm -v $(pwd):/soh soh /bin/bash - cp ../../buildsoh.bash soh - docker exec sohcont soh/buildsoh.bash + docker exec sohcont scripts/linux/build.sh mkdir build mv soh/soh.elf build/ @@ -106,9 +105,9 @@ pipeline { mv OTRGui/build/assets build/ mv ZAPDTR/ZAPD.out build/assets/extractor/ mv README.md readme.txt - - docker exec sohcont appimage/appimage.sh - + + docker exec sohcont scripts/linux/build-appimage.sh + 7z a soh-linux.7z SOH-Linux.AppImage readme.txt ''' @@ -143,9 +142,9 @@ pipeline { sh ''' cp ../../ZELOOTD.z64 OTRExporter/baserom_non_mq.z64 cd soh - make setup -j4 OPTFLAGS=-O2 DEBUG=0 LD="ld" - make -j4 DEBUG=0 OPTFLAGS=-O2 LD="ld" - make -j4 appbundle + make setup -j$(sysctl -n hw.physicalcpu) OPTFLAGS=-O2 DEBUG=0 LD="ld" + make -j$(sysctl -n hw.physicalcpu) DEBUG=0 OPTFLAGS=-O2 LD="ld" + make appbundle mv ../README.md readme.txt 7z a soh-mac.7z soh.app readme.txt ''' @@ -177,9 +176,9 @@ pipeline { sh ''' cp ../../ZELOOTD.z64 OTRExporter/baserom_non_mq.z64 - docker build . -t sohswitch -f Dockerfile.switch + docker build . -t sohswitch docker run --name sohcont -dit --rm -v $(pwd):/soh sohswitch /bin/bash - docker exec sohcont .ci/switch/buildswitch.bash + docker exec sohcont scripts/switch/build.sh mv soh/soh.nro . mv README.md readme.txt diff --git a/ZAPDTR/Makefile b/ZAPDTR/Makefile index 6d8ba354d..660e0469c 100644 --- a/ZAPDTR/Makefile +++ b/ZAPDTR/Makefile @@ -48,11 +48,15 @@ endif LDFLAGS := -Llib/libgfxd -L../libultraship -L../StormLib/build \ -pthread -lgfxd -lultraship ZAPDUtils/ZAPDUtils.a -lstorm -lbz2 -lm -ldl +LDFLAGS += $(shell pkg-config --libs glew libpng zlib) $(shell sdl2-config --libs) +INC += $(shell pkg-config --cflags libpng) + ifeq ($(UNAME), Darwin) - LDFLAGS += $(shell pkg-config --libs glew libpng zlib) $(shell sdl2-config --libs) -framework OpenGL -framework Foundation - INC += $(shell pkg-config --cflags libpng) -else - LDFLAGS += -lpng -lGL -lGLEW -lX11 -lz -lSDL2 -lpulse + LDFLAGS += -framework OpenGL -framework Foundation +endif + +ifeq ($(UNAME), Linux) + LDFLAGS += $(shell pkg-config --libs x11 libpulse) endif # Use LLD if available. Set LLD=0 to not use it @@ -65,10 +69,12 @@ ifneq ($(LLD),0) endif UNAMEM := $(shell uname -m) -ifneq ($(UNAME), Darwin) +ifeq ($(UNAME), Linux) LDFLAGS += -Wl,-export-dynamic -lstdc++fs EXPORTERS := -Wl,--whole-archive ../OTRExporter/OTRExporter/OTRExporter.a -Wl,--no-whole-archive -else +endif + +ifeq ($(UNAME), Darwin) EXPORTERS := -Wl,-force_load ../OTRExporter/OTRExporter/OTRExporter.a endif diff --git a/libultraship/Makefile b/libultraship/Makefile index 37640969d..8369126f4 100644 --- a/libultraship/Makefile +++ b/libultraship/Makefile @@ -29,7 +29,6 @@ WARN := -Wall -Wextra -Werror \ -Wno-narrowing \ -Wno-missing-field-initializers \ -Wno-error=multichar \ - -Wno-unused-command-line-argument \ -Wno-delete-non-abstract-non-virtual-dtor \ -Wno-unused-private-field \ -Wno-deprecated-copy-with-user-provided-copy \ @@ -46,7 +45,7 @@ endif CXXFLAGS := $(WARN) $(CXXWARN) -std=c++20 -D_GNU_SOURCE -DENABLE_OPENGL -DSPDLOG_ACTIVE_LEVEL=0 CFLAGS := $(WARN) $(CWARN) -std=c99 -D_GNU_SOURCE -DENABLE_OPENGL -DSPDLOG_ACTIVE_LEVEL=0 -CPPFLAGS := -MMD +CPPFLAGS := -MMD $(shell pkg-config --cflags sdl2 glew) MMFLAGS := -Wno-deprecated-declarations -ObjC++ -fobjc-weak -fobjc-arc @@ -62,10 +61,6 @@ ifneq ($(CXX_IS_CLANG),1) MMFLAGS += -stdlib++-isystem ${STD_ISYSTEM} -cxx-isystem ${CXX_ISYSTEM} endif -ifeq ($(UNAME), Darwin) #APPLE - CPPFLAGS += $(shell pkg-config --cflags sdl2 glew) -framework OpenGL -framework Foundation -endif - ifneq ($(DEBUG),0) CXXFLAGS += -g -D_DEBUG CFLAGS += -g -D_DEBUG diff --git a/appimage/appimage.sh b/scripts/linux/build-appimage.sh similarity index 96% rename from appimage/appimage.sh rename to scripts/linux/build-appimage.sh index 7ac03934e..053ce580a 100755 --- a/appimage/appimage.sh +++ b/scripts/linux/build-appimage.sh @@ -6,7 +6,7 @@ curl -sSfL https://github.com$(curl https://github.com/probonopd/go-appimage/rel chmod a+x mkappimage.AppImage mkdir -p AppDir/usr/bin -cp appimage/{soh.desktop,soh.sh} AppDir/ +cp scripts/linux/{soh.desktop,soh.sh} AppDir/ cp soh/macosx/sohIcon.png AppDir/soh.png curl -sSfL https://raw.githubusercontent.com/gabomdq/SDL_GameControllerDB/master/gamecontrollerdb.txt -o AppDir/usr/bin/gamecontrollerdb.txt diff --git a/scripts/linux/build.sh b/scripts/linux/build.sh new file mode 100755 index 000000000..f9d1f9e2c --- /dev/null +++ b/scripts/linux/build.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +cd soh +make setup -j$(nproc) OPTFLAGS=-O2 DEBUG=0 +make -j$(nproc) OPTFLAGS=-O2 DEBUG=0 + +cd ../OTRGui +mkdir build +cd build +cmake .. +cmake --build . --config Release diff --git a/appimage/soh.desktop b/scripts/linux/soh.desktop similarity index 100% rename from appimage/soh.desktop rename to scripts/linux/soh.desktop diff --git a/appimage/soh.sh b/scripts/linux/soh.sh similarity index 100% rename from appimage/soh.sh rename to scripts/linux/soh.sh diff --git a/scripts/switch/build.sh b/scripts/switch/build.sh new file mode 100755 index 000000000..e5d65d99d --- /dev/null +++ b/scripts/switch/build.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +make setup -C soh -j$(nproc) OPTFLAGS=-O2 DEBUG=0 +make -f Makefile.switch -j$(nproc) diff --git a/soh/Makefile b/soh/Makefile index 2c0f9ff31..24b3c9e8b 100644 --- a/soh/Makefile +++ b/soh/Makefile @@ -16,26 +16,35 @@ DEBUG ?= 1 OPTFLAGS ?= -O0 LTO ?= 0 +# flag to save whether the compiler being used is clang or gcc by checking CXX --version +CXX_IS_CLANG ?= $(shell $(CXX) --version | grep -c clang) + WARN := \ -Wno-return-type \ - -Wno-unused-command-line-argument \ - -Wno-implicit-function-declaration \ - -Wno-c++11-narrowing \ -funsigned-char \ -fno-stack-protector -fno-common -fno-zero-initialized-in-bss -fno-strict-aliasing -fno-inline-functions -fno-inline-small-functions -ffreestanding -fwrapv \ -CXXFLAGS := $(WARN) -std=c++20 -D_GNU_SOURCE -fpermissive -no-pie -nostdlib -CFLAGS := $(WARN) -std=c99 -D_GNU_SOURCE -no-pie -nostdlib -LDFLAGS := - -ifeq ($(UNAME), Linux) #LINUX - CXXFLAGS += -mhard-float -msse2 -mfpmath=sse - CFLAGS += -mhard-float -msse2 -mfpmath=sse +ifeq ($(CXX_IS_CLANG),1) + WARN += -Wno-c++11-narrowing endif -ifeq ($(UNAME), Darwin) #APPLE - CXXFLAGS += $(shell pkg-config --cflags sdl2) $(shell sdl2-config --cflags) $(shell pkg-config --cflags glew) -framework OpenGL - CFLAGS += $(shell pkg-config --cflags sdl2) $(shell sdl2-config --cflags) $(shell pkg-config --cflags glew) -framework OpenGL +CXXFLAGS := $(WARN) -std=c++20 -D_GNU_SOURCE -fpermissive -nostdlib $(shell pkg-config --cflags glew) $(shell sdl2-config --cflags) +CFLAGS := $(WARN) -std=c99 -Wno-implicit-function-declaration -D_GNU_SOURCE -nostdlib $(shell pkg-config --cflags glew) $(shell sdl2-config --cflags) +LDFLAGS := + +ifneq ($(CXX_IS_CLANG),1) + CXXFLAGS += -no-pie + CFLAGS += -no-pie +endif + +ifeq ($(UNAME), Linux) + ifeq ($(UNAMEM), x86_64) + CXXFLAGS += -msse2 -mfpmath=sse -mhard-float + CFLAGS += -msse2 -mfpmath=sse -mhard-float + endif + + CXXFLAGS += $(shell pkg-config --cflags libpulse) + CFLAGS += $(shell pkg-config --cflags libpulse) endif CPPFLAGS := -MMD @@ -57,11 +66,11 @@ ifneq ($(LTO),0) LDFLAGS += -flto endif -ifeq ($(UNAME), Linux) #LINUX +ifeq ($(UNAME), Linux) TARGET := soh.elf endif -ifeq ($(UNAME), Darwin) #APPLE +ifeq ($(UNAME), Darwin) TARGET := soh-$(UNAMEM) endif @@ -78,25 +87,15 @@ INC_DIRS := $(addprefix -I, \ ../libultraship/libultraship/Lib/Fast3D/U64/PR \ ) -ifeq ($(UNAME), Linux) #LINUX - INC_DIRS += $(addprefix -I, \ - /opt/X11/include \ -) -endif - LDDIRS := $(addprefix -L, \ ../libultraship/ \ ) -ifeq ($(UNAME), Linux) #LINUX - LDDIRS += $(addprefix -L, \ - /opt/X11/lib \ -) -endif - LDLIBS := \ $(ZAPDUTILS) \ $(LIBSTORM) \ + $(shell sdl2-config --libs) \ + $(shell pkg-config --libs glew) \ $(addprefix -l, \ dl \ bz2 \ @@ -105,24 +104,16 @@ LDLIBS := \ ultraship \ ) -ifeq ($(UNAME), Linux) #LINUX -LDLIBS += \ - $(addprefix -l, \ - X11 \ - SDL2 \ - GL \ - GLEW \ - pulse \ -) +ifeq ($(UNAME), Linux) +LDLIBS += $(shell pkg-config --libs x11 libpulse) endif -ifeq ($(UNAME), Darwin) #APPLE +ifeq ($(UNAME), Darwin) LDLIBS += \ $(addprefix -framework , \ OpenGL \ Foundation \ -) \ - $(shell sdl2-config --libs) $(shell pkg-config --libs glew) +) endif ASSET_BIN_DIRS := $(shell find assets/* -type d -not -path "assets/xml*") diff --git a/soh/include/z64.h b/soh/include/z64.h index 94d8b280e..d9570ae5e 100644 --- a/soh/include/z64.h +++ b/soh/include/z64.h @@ -30,7 +30,7 @@ #include "ichain.h" #include "regs.h" -#if defined(_WIN64) || defined(__x86_64__) || defined(__arm64__) +#if defined(__LP64__) #define _SOH64 #endif diff --git a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp index 513776b2a..48c9c4695 100644 --- a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp +++ b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp @@ -1001,7 +1001,7 @@ void DrawFlagsTab() { // Draws a combo that lets you choose and upgrade value from a drop-down of text values void DrawUpgrade(const std::string& categoryName, int32_t categoryId, const std::vector& names) { - ImGui::Text(categoryName.c_str()); + ImGui::Text("%s", categoryName.c_str()); ImGui::SameLine(); ImGui::PushID(categoryName.c_str()); if (ImGui::BeginCombo("##upgrade", names[CUR_UPG_VALUE(categoryId)].c_str())) { From f7abf79bf33ef98746e9396859410635414b2c32 Mon Sep 17 00:00:00 2001 From: briaguya Date: Tue, 2 Aug 2022 13:26:26 -0400 Subject: [PATCH 25/25] update rando tooltips to utilize auto newlines --- .../Enhancements/randomizer/randomizer.cpp | 70 +++++++++---------- 1 file changed, 32 insertions(+), 38 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 3697ec379..f7c3deb0f 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -3767,25 +3767,25 @@ void DrawRandoEditor(bool& open) { // Forest ImGui::Text(Settings::OpenForest.GetName().c_str()); InsertHelpHoverText( - "Closed - Kokiri sword & shield are required to access\n" - "the Deku Tree, and completing the Deku Tree is required to\n" + "Closed - Kokiri sword & shield are required to access " + "the Deku Tree, and completing the Deku Tree is required to " "access the Hyrule Field exit.\n" "\n" - "Closed Deku - Kokiri boy no longer blocks the path to Hyrule\n" - "Field but Mido still requires the Kokiri sword and Deku shield\n" + "Closed Deku - Kokiri boy no longer blocks the path to Hyrule " + "Field but Mido still requires the Kokiri sword and Deku shield " "to access the tree.\n" "\n" - "Open - Mido no longer blocks the path to the Deku Tree. Kokiri\n" + "Open - Mido no longer blocks the path to the Deku Tree. Kokiri " "boy no longer blocks the path out of the forest."); SohImGui::EnhancementCombobox("gRandomizeForest", randoForest, 3, 0); PaddedSeparator(); // Kakariko Gate ImGui::Text(Settings::OpenKakariko.GetName().c_str()); InsertHelpHoverText( - "Closed - The gate will remain closed until Zelda's letter\n" + "Closed - The gate will remain closed until Zelda's letter " "is shown to the guard.\n" "\n" - "Open - The gate is always open. The happy mask shop\n" + "Open - The gate is always open. The happy mask shop " "will open immediately after obtaining Zelda's letter." ); SohImGui::EnhancementCombobox("gRandomizeKakarikoGate", randoKakarikoGate, 2, 0); @@ -3794,14 +3794,13 @@ void DrawRandoEditor(bool& open) { // Door of Time ImGui::Text(Settings::OpenDoorOfTime.GetName().c_str()); InsertHelpHoverText( - "Closed - The Ocarina of Time, the Song of Time and all\n" + "Closed - The Ocarina of Time, the Song of Time and all " "three spiritual stones are required to open the Door of Time.\n" "\n" - "Song only - Play the Song of Time in front of the Door of\n" + "Song only - Play the Song of Time in front of the Door of " "Time to open it.\n" "\n" - "Open - The Door of Time is permanently open with no\n" - "requirements." + "Open - The Door of Time is permanently open with no requirements." ); SohImGui::EnhancementCombobox("gRandomizeDoorOfTime", randoDoorOfTime, 3, 0); PaddedSeparator(); @@ -3809,14 +3808,14 @@ void DrawRandoEditor(bool& open) { // Zora's Fountain ImGui::Text(Settings::ZorasFountain.GetName().c_str()); InsertHelpHoverText( - "Closed - King Zora obstructs the way to Zora's Fountain.\n" - "Ruto's letter must be shown as child Link in order to move\n" + "Closed - King Zora obstructs the way to Zora's Fountain. " + "Ruto's letter must be shown as child Link in order to move " "him in both time periods.\n" "\n" - "Closed as child - Ruto's Letter is only required to move King Zora\n" + "Closed as child - Ruto's Letter is only required to move King Zora " "as child Link. Zora's Fountain starts open as adult.\n" "\n" - "Open - King Zora has already mweeped out of the way in both\n" + "Open - King Zora has already mweeped out of the way in both " "time periods. Ruto's Letter is removed from the item pool." ); SohImGui::EnhancementCombobox("gRandomizeZorasFountain", randoZorasFountain, 3, 0); @@ -3825,7 +3824,7 @@ void DrawRandoEditor(bool& open) { // Gerudo Fortress ImGui::Text(Settings::GerudoFortress.GetName().c_str()); InsertHelpHoverText( - "Sets the amount of carpenters required to repair the bridge\n" + "Sets the amount of carpenters required to repair the bridge " "in Gerudo Valley.\n" "\n" "Normal - All 4 carpenters are required to be saved.\n" @@ -3842,8 +3841,7 @@ void DrawRandoEditor(bool& open) { InsertHelpHoverText( "Alters the requirements to open the bridge to Ganon's Castle.\n" "\n" - "Vanilla - Obtain the Shadow Medallion, Spirit Medallion and Light\n" - "Arrows.\n" + "Vanilla - Obtain the Shadow Medallion, Spirit Medallion and Light Arrows.\n" "\n" "Always open - No requirements.\n" "\n" @@ -3851,11 +3849,11 @@ void DrawRandoEditor(bool& open) { "\n" "Medallions - Obtain the specified amount of medallions.\n" "\n" - "Dungeon rewards - Obtain the specified total sum of spiritual\n" + "Dungeon rewards - Obtain the specified total sum of spiritual " "stones or medallions.\n" "\n" - "Dungeons - Complete the specified amount of dungeons. Dungeons\n" - "are considered complete after stepping in to the blue warp after\n" + "Dungeons - Complete the specified amount of dungeons. Dungeons " + "are considered complete after stepping in to the blue warp after " "the boss.\n" "\n" "Tokens - Obtain the specified amount of Skulltula tokens." @@ -3922,8 +3920,7 @@ void DrawRandoEditor(bool& open) { // Shuffle Songs ImGui::Text(Settings::ShuffleSongs.GetName().c_str()); InsertHelpHoverText( - "Song locations - Songs will only appear at locations that normally\n" - "teach songs.\n" + "Song locations - Songs will only appear at locations that normally teach songs.\n" "\n" "Dungeon rewards - Songs appear after beating a major dungeon boss.\n" "The 4 remaining songs are located at:\n" @@ -3941,7 +3938,7 @@ void DrawRandoEditor(bool& open) { // Shuffle Tokens ImGui::Text(Settings::Tokensanity.GetName().c_str()); InsertHelpHoverText( - "Shuffles Golden Skulltula Tokens into the item pool. This means\n" + "Shuffles Golden Skulltula Tokens into the item pool. This means " "Golden Skulltulas can contain other items as well.\n" "\n" "Off - GS tokens will not be shuffled.\n" @@ -3956,7 +3953,7 @@ void DrawRandoEditor(bool& open) { PaddedSeparator(); SohImGui::EnhancementCheckbox("Nighttime GS expect Sun's Song", "gRandomizeGsExpectSunsSong"); - InsertHelpHoverText("All Golden Skulltulas that require nighttime to appear will only be\n" + InsertHelpHoverText("All Golden Skulltulas that require nighttime to appear will only be " "expected to be collected after getting Sun's Song."); PaddedSeparator(); @@ -3966,8 +3963,7 @@ void DrawRandoEditor(bool& open) { InsertHelpHoverText( "Shuffles the Kokiri Sword into the item pool.\n" "\n" - "This will require the use of sticks until the Kokiri\n" - "Sword is found." + "This will require the use of sticks until the Kokiri Sword is found." ); PaddedSeparator(); } @@ -3976,8 +3972,7 @@ void DrawRandoEditor(bool& open) { // Shuffle Ocarinas SohImGui::EnhancementCheckbox(Settings::ShuffleOcarinas.GetName().c_str(), "gRandomizeShuffleOcarinas"); InsertHelpHoverText( - "Enabling this shuffles the Fairy Ocarina and the Ocarina of Time\n" - "into the item pool.\n" + "Enabling this shuffles the Fairy Ocarina and the Ocarina of Time into the item pool.\n" "\n" "This will require finding an Ocarina before being able to play songs." ); @@ -4003,7 +3998,7 @@ void DrawRandoEditor(bool& open) { ImGui::PopItemFlag(); } InsertHelpHoverText( - "Shuffles the Weird Egg from Malon in to the item pool. Enabling\n" + "Shuffles the Weird Egg from Malon in to the item pool. Enabling " "\"Skip Child Zelda\" disables this feature.\n" "\n" "The Weird Egg is required to unlock several events:\n" @@ -4020,7 +4015,7 @@ void DrawRandoEditor(bool& open) { InsertHelpHoverText( "Shuffles the Gerudo Membership Card into the item pool.\n" "\n" - "The Gerudo Card is required to enter the Gerudo Training Grounds, opening\n" + "The Gerudo Card is required to enter the Gerudo Training Grounds, opening " "the gate to Haunted Wasteland and the Horseback Archery minigame." ); } @@ -4036,7 +4031,7 @@ void DrawRandoEditor(bool& open) { InsertHelpHoverText( "Shuffles the location of spiritual stones and medallions.\n" "\n" - "End of dungeons - Spiritual stones and medallions will be given as rewards\n" + "End of dungeons - Spiritual stones and medallions will be given as rewards " "for beating major dungeons. Link will always start with one stone or medallion.\n" "\n" "Any dungeon - Spiritual stones and medallions can be found inside any dungeon.\n" @@ -4121,14 +4116,13 @@ void DrawRandoEditor(bool& open) { } ImGui::PopItemFlag(); } - InsertHelpHoverText("The crawlspace into Hyrule Castle goes straight to Zelda, skipping\n" - "the guards."); + InsertHelpHoverText("The crawlspace into Hyrule Castle goes straight to Zelda, skipping the guards."); PaddedSeparator(); // Skip child zelda SohImGui::EnhancementCheckbox("Skip Child Zelda", "gRandomizeSkipChildZelda"); InsertHelpHoverText( - "Start with Zelda's Letter in your inventory and skip the sequence up\n" + "Start with Zelda's Letter in your inventory and skip the sequence up " "until after meeting Zelda. Disables the ability to shuffle Weird Egg." ); PaddedSeparator(); @@ -4154,8 +4148,8 @@ void DrawRandoEditor(bool& open) { // Gossip Stone Hints ImGui::Text(Settings::GossipStoneHints.GetName().c_str()); InsertHelpHoverText( - "Allows Gossip Stones to provide hints on item locations. Hints mentioning\n" - "\"Way of the Hero\" indicate a location that holds an item required to beat\n" + "Allows Gossip Stones to provide hints on item locations. Hints mentioning " + "\"Way of the Hero\" indicate a location that holds an item required to beat " "the seed.\n" "\n" "No hints - No hints will be given at all.\n" @@ -4238,7 +4232,7 @@ void DrawRandoEditor(bool& open) { "\n" "Mayhem - All added junk items will be Ice Traps.\n" "\n" - "Onslaught - All junk items will be replaced by Ice Traps, even those\n" + "Onslaught - All junk items will be replaced by Ice Traps, even those " "in the base pool." ); SohImGui::EnhancementCombobox("gRandomizeIceTraps", randoIceTraps, 5, 1);