The Legend of Zelda: Ocarina of Time (Nintendo Switch 2) running natively on Windows & Linux, with no emulator.
Status | Install and play | In-game menu | Problems | Build from source | How it works | Want to help? | Credits | License
Hookshot is a static recompilation. The game's code is translated to C and compiled into a Windows or Linux program,
the console's system software is reimplemented, and the Switch 2 graphics are rebuilt on Vulkan. All of this happens
on your PC, from your own copy of the game.
Warning
Some users report the file in releases to be a Trojan - it is not. Feel free to run it through any antivirus software
Discord: https://discord.gg/DVQQJphbBf
Important
This repository does not contain the game, keys or an executable, and it does not explain how to get them. You
need your own copy. Everything the build creates (hookshot.exe, the generated code, the shader caches and your
saves) comes from your game and stays on your PC. Never share those files.
Experimental. Most testing so far has been around the start of the game. Players have reported on many PCs since: the table says what works and what does not yet.
| What | Status |
|---|---|
| Kokiri Forest: reaching gameplay and walking around | ✅ Works |
| Sound, controller, keyboard and saves | ✅ Works |
| In-game menu, frame generation and upscaling | ✅ Works |
| Flicker (the picture flashing too bright while moving) | ✅ Fixed in v2.0.2 (#645) |
| Ground fog vanishing when looking down | ✅ Fixed in v2.0.2 (#638) |
| Models with missing pieces (doors, fences, parts of trees) | ✅ Fixed where tested, more play needed |
| Stutter when entering new areas | |
| Performance | |
| Hyrule Field, Castle Town, Kakariko and the dungeons | |
| Ultrawide | |
| NVIDIA cards | ✅ Works. The most tested |
| AMD cards | |
| Intel cards | ❓ Few reports, many of them black screens or crashes (#17) |
| Cards without mesh shaders (such as AMD RX 5000 and older) | ❌ Not supported: parts of the picture are missing. A fallback was tried and taken out again for now (#640) |
| Linux | ✅ Works with the AppImage. Tested on several distributions (CachyOS, Fedora, Bazzite, SteamOS) and cards, with open problems on some AMD cards (#604, #528) |
The game does not come ready-made: Hookshot Builder builds it on your PC from your copy. You do this once. After that you start the game from its launcher, which also updates it.
- Your copy of the game at the supported version: program
0400486024DEC000, update v131072, builde0f3ccfa. Other versions do not work. A.nupfile, or theromfsandexefsfolders. - 64-bit Windows 10 or 11, or 64-bit Linux with glibc 2.35 or newer (Ubuntu 22.04, Debian 12, Fedora, Arch, SteamOS ...) and a CPU with AVX2.
- A graphics card with Vulkan 1.3 and mesh shaders, with an up-to-date driver: NVIDIA GeForce RTX 20 series or newer, AMD Radeon RX 6000 series or newer, or Intel Arc. On Linux, Mesa or NVIDIA's driver. Cards without mesh shaders are not supported.
- 8 GB of video memory (VRAM) or more is recommended. Cards with less can use the in-game menu's lower Quality presets.
- 16 GB of RAM or more. A run uses about 10 GB.
- About 60 GB free while building.
- An internet connection for the download. Nothing else to install: the builder brings its own compiler and tools.
- Open the latest release and download
HookshotBuilder.exe. - Run it. It downloads the rest of Hookshot Builder (about 500 MB), checks it, and opens it.
- Pick your game. The builder looks for
.nupfiles in your Downloads, Desktop and Documents folders and lists them under Found on this PC. Not listed? Press Browse…, drop the file on the window, or choose romfs and exefs folders. The builder checks that it is the right version. - Under Install the game to, keep the folder (
Games\Hookshotin your user folder) or press Change. Choose the Game language. - Press Build the game. It takes about 10 to 45 minutes, depending on your CPU and memory. You can use your PC in the meantime.
- When it says Your game is ready, press Play. The Desktop shortcut and Start menu entry boxes are ticked: untick them if you don't want them.
Next time, start the game from the Hookshot shortcut, or hookshot.exe in the game folder. That is the launcher: it
has Play, and Update when a newer release is out.
The first start prepares the game's shaders, which takes a while. Later starts are faster.
- Open the latest release and download
Hookshot-<version>-x86_64.AppImage. It is Hookshot Builder with everything it needs inside. - Allow it to run as a program. In most file managers: right-click it, open Properties, and turn on
"Allow executing file as program" (the words differ between desktops). Or in a terminal:
chmod +x Hookshot-*-x86_64.AppImage. - Double-click it. The Hookshot Builder window opens.
- Under Game files, choose .nup file or romfs and exefs, then press Browse to pick them. The builder checks the version.
- Under Save the game to, keep
~/Games/Hookshotor choose another folder. Choose a Language. - Press Build. It takes about 10 to 45 minutes, depending on your CPU and memory.
- When it says "Your game is ready", press Play.
The game is also added to your applications menu as "Hookshot". That entry, and hookshot in the game folder, open the
launcher: Play, and Update when a newer release is out. Keep the AppImage where it is: the launcher uses it to
update.
When a new release is out, the launcher says "Update available". Press Update: in hookshot.exe on Windows, or in
hookshot (or the AppImage) on Linux. It downloads only the parts that changed and builds the game again in the same
folder, compiling only what changed. Your saves and settings are kept. What changed is on the
Releases page.
What an update keeps and replaces, and updating from the command line
To be safe, copy your saves somewhere first: the user folder in the game folder on Windows, or
~/.local/share/hookshot on Linux.
| Kept | Replaced |
|---|---|
Your saves (user, or ~/.local/share/hookshot on Linux) |
The game in bin and its files |
hookshot_options.ini, the in-game menu's choices and your controls |
image.bin and the shader list |
hookshot_env.txt |
language.txt, written again with the game's language |
mods |
The game files the first build read are kept in the game folder, so an update does not need your .nup again.
From a clone: git pull, then python -I nx2/make_game.py --update <game folder>. The Linux AppImage does the same
with --update <game folder>.
- The build reads your game and never changes it. It writes to the folder you choose and to the builder's own folder:
%LOCALAPPDATA%\HookshotBuilderon Windows,~/.cache/hookshot-builderon Linux. - The romfs is hard-linked instead of copied where the disk allows it.
- The builder keeps its build files (about 4 GB) so that updates are quick. None of them are needed to play: on Windows, Free up space on the "Your game is ready" page deletes them, and the build files folder can be moved before a build (Change, Default).
- Saves: the
userfolder in the game folder on Windows,~/.local/share/hookshoton Linux (auserfolder from an earlier Linux build is moved there once).--user <folder>puts them somewhere else (command line arguments). To carry on with a save from an emulator (Lichii, Eglantine, Orchid, ...) or NX2navi, or to take yours there, see using a save from an emulator. - To uninstall, delete the game folder, the builder's folder and the shortcuts.
| Problem | What to do |
|---|---|
| Where is the log? | hookshot_log.txt in the game folder holds the last run. The four runs before are hookshot_log.1.txt (the last) to .4.txt. Started from a terminal, the game prints there instead. Every 600 frames it has a vk: status: line: the video memory in use of what the driver allows, and DLSS's details while it draws; vk: over the driver's video-memory allowance says when the game passed it |
| "Hookshot supports build e0f3ccfa" or "This version isn't supported" | Check that you chose the right game with its update installed |
| The game opens and closes, or the log says "device lost" | Update your graphics driver. On AMD cards there are known crashes (#708, #614) |
| Parts of the picture are missing, or a message says your card has no mesh shader support | The card or its driver has no mesh shaders. Update the driver; older cards are not supported (#640) |
| AMD: blocky textures, solid rectangles in the sky or unusually dark courtyard surfaces | Try the RGBA8 texture workaround. It uses more graphics memory |
| Linux: the game does not start or the picture is broken | The game needs a Vulkan 1.3 driver with mesh shaders. Check with vulkaninfo | grep mesh: it should list VK_EXT_mesh_shader. Update Mesa or the NVIDIA driver |
Steam Deck: the game freezes and closes in Kokiri Forest or the Great Deku Tree (gfx_0.0.0 timeout in journalctl -k) |
RX_VK_SKIP_CODE=2c56dc1006942f74 in hookshot_env.txt gets past it, but the models those draws make go missing (see Switches for testing below, #817) |
| "Your antivirus removed part of the build tools" | A false alarm on unsigned programs. Restore the files from Windows Security's Protection history, or add %LOCALAPPDATA%\HookshotBuilder to its exclusions, then press Repair |
| Stutter the first time you see something | Normal for now: shaders are being prepared. It gets better when you pass through the same place again |
| The game is in the wrong language | Change the code in language.txt in the game folder. The file lists them all |
If the problem continues, report it with the version, where
you were in the game, your graphics card, hookshot_log.txt and a screenshot or video. Never send game files.
For these AMD texture artifacts, try keeping decoded ASTC textures as RGBA8 instead of re-encoding them to BC3
(#57, #1006).
Close the game, then create or edit hookshot_env.txt in the built game folder, beside image.bin, and add:
RX_VK_ASTC_RGBA8=1Restart the game. The same setting applies when Steam or RecompLauncher starts that game folder.
This is a workaround for some artifacts, not a general lighting fix. It can substantially increase graphics-memory use and cause stalls when the card runs out of headroom. To undo it, remove that line and restart the game.
Press Insert (or F1) in game, or on a controller the Home button (or Select and Start together).
The same keys close it, and so does Esc. The menu has three tabs, Graphics, Gameplay and Controls:
Q and E (or Tab and Shift+Tab) switch between them, LB and RB on
a controller. Up and Down choose a row, Left and Right change it
(Enter changes it too); under the rows, the help says what the row is and, on a line of its own, what the
value chosen does. On a controller the D-pad chooses and changes, the bottom face button changes too, and the right
one closes the menu. Your choices are saved in hookshot_options.ini in the game folder.
The rows marked "after a restart" below are read when the game starts. While one is changed, its value says "(after restart)" and the foot of the Graphics tab lists it; closing the menu then asks whether to restart now. Later keeps the change for the next start (and is not asked again until you change one of those rows); Restart now saves your choices and starts the game again, so progress since your last save is lost.
| Tab | Option | Choices | Default |
|---|---|---|---|
| Graphics | Quality preset | Custom, Minimum (4GB), Low (6GB), Balanced (8GB), High (12GB), Ultra (16GB+) | Custom |
| Fullscreen | Off, On (the same as F11) | Off | |
| GPU device | Auto, or each graphics card by name (after a restart) | Auto | |
| Frame generation | Off, 2x to 8x | Off | |
| Frame pacing | Off, On | Off | |
| NVIDIA Reflex | Off, On, On + Boost (NVIDIA GPUs with VK_NV_low_latency2) |
Off | |
| Output resolution | 1920x1080, 2048x1152, 2560x1440, 3840x2160 (after a restart) | 2048x1152 | |
| Upscaler | Game's own, NVIDIA DLSS, NVIDIA DLAA (only in builds with NVIDIA's DLSS SDK, below; DLSS and DLAA on RTX GPUs) | Game's own | |
| DLSS model | Transformer (K), Transformer 2 (M), Transformer 2 (L), NVIDIA default (builds with DLSS; used by DLSS and DLAA) | Transformer (K) | |
| Render resolution | Auto (the game's own dynamic resolution), 100%, 75%, 67%, 50% (each with its size). With DLSS: Auto, Quality (67%), Balanced (58%), Performance (50%), Ultra Performance (33%). With DLAA: Native | Auto | |
| Window scaling filter | Off, Catmull-Rom, Lanczos | Off | |
| Sharpness | 0 to 100%, in steps of 10 | 0% | |
| Handheld profile | Off, On (after a restart) | Off | |
| Ultrawide | 16:9, Monitor's shape (after a restart) | 16:9 | |
| Robust buffers | Auto, Off, On (after a restart) | Auto | |
| Gameplay | FPS counter | Off, On | Off |
| Game speed | Per frame, Real time | Real time | |
| Text speed | Normal, 2x, 4x, Instant | Normal | |
| Microphone | Off, Default, or each microphone by name | Default | |
| Controls | Controller in background | Off, On | Off |
| Mouse camera | As the stick, Native | As the stick | |
| Mouse sensitivity | 0.10 to 5.00 | 1.00 | |
| Invert mouse vertical | Off, On | Off | |
| Invert camera X | Off, On | Off | |
| Invert camera Y | Off, On | Off | |
| Rumble strength | Off, 25% to 150%, in steps of 25 | 100% | |
| Motion controls | Off, On | On | |
| Motion sensitivity X | 10% to 300% | 100% | |
| Motion sensitivity Y | 10% to 300% | 100% | |
| Invert motion X | Off, On | Off | |
| Invert motion Y | Off, On | Off | |
| Layout preset | Nintendo (Def), Xbox / PC, Swap Face, Custom | Nintendo (Def) | |
| Controls | Opens the Controls page |
- Quality preset sets Render resolution, Window scaling filter, Sharpness, Frame generation, Frame pacing, Game speed, Handheld profile and the video memory limits for a card with that much memory. It leaves the Upscaler as you chose it: with DLSS, the preset's resolution becomes DLSS's nearest mode. Changing most other rows yourself sets it back to Custom.
- GPU device matters on a PC with more than one graphics card (a laptop's integrated and dedicated GPUs, or a
second card for Lossless Scaling). Auto prefers a dedicated one, and only cards with Vulkan 1.3 are listed.
hookshot_log.txtlists every card asvk: device <n>;RX_VK_DEVICE=<n>chooses one for a single run and wins over the menu. - Frame generation makes extra frames between the game's own. It adds a little input delay, and fast motion can show artifacts. Frame pacing shows frames at an even interval: less stutter, up to one frame of delay.
- The scaling rows, in the picture's order: Output resolution is the size of the game's whole frame, HUD included. The Upscaler fills it from the 3D: the game's own network, or NVIDIA DLSS or DLAA (the 3D at full size, edges smoothed). Both look softer than the game's own: set Sharpness to around 80% with them. DLSS model chooses their network (below). Render resolution is the 3D's share of the output. The Window scaling filter then scales the frame to your window, and Sharpness sharpens it.
- Output resolution: its rows below show the sizes for the output you chose. Docked only. On a 1920x1080 display,
the 1920x1080 option keeps HUD and text sharp when the game fills the screen by mapping them pixel for pixel. At
3840x2160 the game's render targets get a bigger GPU pool, so a full-size 3D fits. For one run, set
HOS_OUTPUT_RESto3for 1920x1080,0for 2048x1152,1for 2560x1440, or2for 3840x2160. - Window scaling filter matters only when your window's size differs from the Output resolution: for the sharpest picture, set the Output resolution to your screen's, and the row shows "Not needed (window = output)". It and Sharpness also work when Frame generation is Off.
- NVIDIA Reflex Off is the game as without it.
RX_VK_REFLEX_LOG=1logs the driver's latency timings every 300 frames while it is on. - Handheld profile runs the game as if the console were undocked: lower resolution, lighter on the GPU.
- Robust buffers: a read past a buffer's end is dropped instead of stopping the GPU. Auto is on, on every card; Off can be faster on some NVIDIA cards.
- Game speed: with Per frame, the game runs slower whenever it is below 60 fps. Real time keeps it at normal speed down to 15 fps.
- FPS counter shows in the top right corner. With frame generation on, it also shows the game's own rate.
- Microphone is what the ocarina hears when the game's own microphone option is on (an instrument, or humming).
Default follows Windows' default recording device; the list shows each microphone by name, and a change applies at
once. A chosen microphone that is unplugged stays chosen (shown as not connected): Default stands in until it is
back. On Linux (SDL2) two microphones with the same name cannot be told apart: the first is used. Windows must allow desktop apps to use the microphone
(Settings, Privacy & security, Microphone).
HOS_MIC_LOG=1logs what the game reads, a line a second. - Controller in background: On keeps the controller working while another window has the focus. The keyboard and mouse still need the game's window.
- Mouse camera: Native turns the camera with the mouse one to one, as in a PC game. As the stick uses the mouse in place of the right stick. The - and = keys change the sensitivity in game too.
- Rumble strength scales the controller's rumble: 100% is the game's own, Off turns it off. The game's HD rumble goes to a controller's heavy and light motors by its frequency.
- Motion controls: the controller's gyroscope aims where the game uses motion, as on the Switch. It works with
Switch Pro controllers and pads in Switch mode, DualSense and DualShock 4 (through SDL), held flat or upright. Its row
says whether the connected pad has a gyroscope; Off leaves the game seeing a pad lying still. Motion sensitivity X/Y
scale the left-right and up-down aim (100% is the console's), Invert motion X/Y turn either direction around. Motion follows the pad used
last. The gyroscope's drift is learned while the pad rests on a table, so set it down for a second if the aim
creeps.
HOS_MOTION_DEBUG=1(inhookshot_env.txt) logs what the game gets twice a second. - Layout preset: Nintendo has A on the right face button, Xbox / PC and Swap Face put A on the bottom one. Changing a button yourself sets it to Custom.
Use a controller, or the keyboard and mouse. On the keyboard, W A S D move and the arrow keys (or I J K L) turn the camera. With the default keyboard bindings, press E to select New Game on the title screen.
To change which gamepad button or key presses a Switch button, or which keys move and turn the camera, open the
Controls tab's Controls page. Choose a row and a column (Gamepad or Keyboard), press Enter (or the bottom
face button), then the new button or key. Esc cancels, Delete clears it, and Reset to defaults
puts them all back. A gamepad button taken from another Switch button swaps with it. The page saves them in
hookshot_options.ini.
Writing the controls in hookshot_options.ini yourself
pad_a=0
key_a=69,13pad_<button> is a gamepad input by position: 0 bottom face button, 1 right, 2 left, 3 top, 4 Select or Back, 5 Home,
6 Start, 7 and 8 the stick presses, 9 and 10 the shoulder buttons, 11 to 14 the D-pad (up, down, left, right), 15 and
16 the triggers, -1 none. key_<button> is one or two
Windows key codes in decimal (69 is
E, 13 Enter), 0 none; the mouse's buttons are 1 (left), 2 (right), 4 (middle), 5 and 6 (side
buttons), and count while the mouse is captured. The buttons are a b x y l r zl zr plus minus ls
rs left up right down, and for keys only the left stick's and the camera's directions: move_up
move_down move_left move_right cam_up cam_down cam_left cam_right. A button the file leaves out keeps
its default.
Put mods in a mods folder in the game folder, beside hookshot.exe (or point HOS_MODS at another folder), in the
layout emulators use: mods/<name>/romfs/... holds files that replace or add to the game's own. Deeper layouts such as
mods/contents/<title id>/<name>/romfs work too. A folder whose name starts with - or _ is off. When two mods
have the same file, the one whose folder name sorts last wins, so name them 01-..., 02-... to set the order.
Only RomFS mods are loaded. exefs patches (.pchtxt, .ips) are left out: Hookshot compiles the game's code ahead
of time, so patching its instructions would need a rebuild. The log (hookshot_log.txt) names each mod and the files
read from it.
For developers, and for players who prefer the command line. The builder windows run the same script,
nx2/make_game.py. CONTRIBUTING.md has more.
Windows, from the command line
python -I nx2/make_game.py --nup "C:\path\your-game.nup" --out "C:\Games\Hookshot" --language en-US
python -I nx2/make_game.py --romfs "C:\path\romfs" --exefs "C:\path\exefs" --out "C:\Games\Hookshot" --language en-USAdd --check with your .nup or --exefs to only check the game's version. It builds nothing.
Add --log "C:\path\build.log" to also save the build's output to a file (UTF-8, replaced if it exists); it works
with --check and --update too, and on Linux.
HOOKSHOT_JOBS=<n> (or --jobs <n>) limits how many files compile at once.
You need:
- Python 3 from python.org (the Microsoft Store's Python installs packages where
python -Idoes not look), withpip install lz4 numpy capstone "unicorn>=2.1,<2.2" zstandard. - llvm-mingw (the
ucrt-x86_64build), unpacked asllvm-mingwin the clone or withHOOKSHOT_MINGWset to its folder. Without it the build uses the clang from emsdk atC:\emsdkwith Visual Studio's C++ tools and the Windows SDK (HOOKSHOT_MSVC=1forces that route). - What the builder's
toolsfolder carries and a clone does not. RunHookshotBuilder.exeonce: the folder is%LOCALAPPDATA%\HookshotBuilder\versions\<version>\HookshotBuilder\tools. The builder sets the variables itself; from the command line, set them before you runmake_game.py:tools\cpm: the Vulkan headers and FFmpeg. SetRX_CPMto this folder. Without it the build leaves outhookshot_vk.dll, the Vulkan renderer, and says nothing.tools\wgpu-native: setWGPU_NATIVEto this folder.tools\third_party: the prebuilt files a clone lacks (a64emit,lld-link,zbicand SDL2). Copy its.dll,.exe,.liband.sha1files to the same places underthird_party\.tools\work: copy it towork\. It holds the hot-function list, the link order, the profile and the icon; without them the game builds but runs slower.
- Visual Studio 2022 with .NET 8, only if you want to change the builder itself.
Linux, the AppImage from the command line
./Hookshot-<version>-x86_64.AppImage --cli --nup ~/your-game.nup --out ~/Games/Hookshot # make_game.py's options
./Hookshot-<version>-x86_64.AppImage --play # the game the builder built last, without the window
./Hookshot-<version>-x86_64.AppImage --play ~/Games/Hookshot # the game in that folder
./Hookshot-<version>-x86_64.AppImage --update ~/Games/Hookshot # the new release, and that folder built againHOOKSHOT_JOBS=<n> (or --jobs <n> with --cli) limits how many files compile at once.
In a game folder, hookshot is the launcher and the game itself is bin/hookshot. The builder's settings are in
~/.config/hookshot/builder.ini.
Linux, without the AppImage
You need clang and lld (LLVM 23 or newer reads the play profile; an older one builds without it), Python 3 with
lz4, numpy, capstone, unicorn and zstandard, FFmpeg's development files (with dav1d, for the movies) and
SDL3 (SDL2 works too). Then run python -I nx2/make_game.py ... as on Windows, with RX_CPM pointing at a folder with Vulkan-Headers,
SPIRV-Headers and VulkanMemoryAllocator in CPM's layout.
scripts/linux/deps.sh fetches and builds all of these into build-linux/deps, and scripts/linux/appimage.sh makes
the AppImage from them. A folder built from a source checkout has no launcher: hookshot there is the game.
The Windows game, built on Linux
Unpack llvm-mingw's Linux build (ucrt-ubuntu-22.04-x86_64), then run make_game.py with RX_TARGET=windows and
HOOKSHOT_MINGW set to its folder. The objects go to ~/.cache/hookshot-builder-windows, apart from the Linux game's.
The game folder runs under Proton or on Windows.
The built game is bin\hookshot.exe on Windows and bin/hookshot in a packaged Linux game folder. A build from a
source checkout has hookshot.exe or hookshot in its build folder, with no launcher beside it. The hookshot.exe
or hookshot launcher in the game folder does not pass these arguments to the game, so start the game directly to
use them.
| Argument | What it does |
|---|---|
image.bin |
The game image to run. Without it the game uses the image.bin, romfs and user in its folder |
--romfs <folder> |
The extracted RomFS folder |
--user <folder> |
Where the game keeps per-user data: saves, caches, temp files and mouse_sens.txt. Default: user in the game folder on Windows, ~/.local/share/hookshot on Linux; with an explicit image path, user in the current folder |
--trace |
Log every Horizon OS call (the same as HOS_TRACE=1) |
--prepare-shaders |
Prepare the shaders and exit without starting the game (the build's last step) |
For example, keep saves somewhere else:
cd "C:\Games\Hookshot"
.\bin\hookshot.exe --user "D:\Hookshot data"cd ~/Games/Hookshot
./bin/hookshot --user "$HOME/hookshot-data"hookshot_env.txt and the other test switches are documented below.
NVIDIA DLSS (optional, NVIDIA's SDK under NVIDIA's license)
A game built with NVIDIA's DLSS SDK offers NVIDIA DLSS and NVIDIA DLAA in the Graphics tab's Upscaler row on
NVIDIA RTX cards (dlss= in hookshot_options.ini, RX_VK_DLSS=0/1/2 for one run): DLSS Super Resolution in place of
the game's own upscaler, with camera jitter (NVIDIA Reflex needs no SDK and is in
every build). NVIDIA's files are NVIDIA's, under its own license, the
NVIDIA RTX SDKs license.
Hookshot never includes or redistributes them: each build downloads them for itself, and only after you accept that
license. Never share a game folder built with them, and do not post builds made with them.
- Windows, the Hookshot Builder: tick NVIDIA DLSS (downloads NVIDIA's SDK under NVIDIA's license) before you
build. It is off by default and shows NVIDIA's license when you tick it. The build downloads the SDK into
%LOCALAPPDATA%\HookshotBuilder\ngx-sdkand puts DLSS's runtime,nvngx_dlss.dll, in the game folder'sngxfolder. - Windows, the command line:
python -I scripts/ngx_sdk.py --platform windows <sdk folder>asks you to accept NVIDIA's license (or pass--accept-nvidia-license) and fetches the headers,nvsdk_ngx_s.libandnvngx_dlss.dll, each checked against its SHA-256. Then build withHOOKSHOT_NGX_SDK=<sdk folder>:make_game.pycopiesnvngx_dlss.dllinto<game folder>\ngx. NGX is also pointed at%LOCALAPPDATA%\Hookshot\ngx, and atRX_VK_DLSS_DIRwhen it is set, and uses the newestnvngx_dlss.dllit finds across them (to try a given one, make sure no other folder has a newer one). Never copy NGX's core,_nvngx.dll, beside the game: it comes with NVIDIA's driver. - Linux: the same with
--platform linux(orscripts/linux/ngx-sdk.sh):libnvsdk_ngx.afor the build andlibnvidia-ngx-dlss.sofor the game folder'sngxfolder (also looked for in$XDG_DATA_HOME/hookshot/ngx). NGX's core comes with NVIDIA's Linux driver.
The DLSS model row chooses DLSS's network, by NVIDIA's preset letter, for every mode: Transformer (K), the
transformer model and the one tested most here (the default); Transformer 2 (M), NVIDIA's second-generation
transformer as it picks it for Performance; Transformer 2 (L), the same generation as tuned for Ultra Performance;
NVIDIA default, which lets DLSS's runtime pick for each mode, so it can change with a runtime update. The runtime
the SDK comes with (310.9.16) has all of them. A change applies at once, without a restart (dlss_model= in
hookshot_options.ini, 0 to 3 in that order). RX_VK_DLSS_PRESET=<letter> (or 0 for NVIDIA's default) chooses
the preset for one run and wins over the row; the log's vk: NVIDIA DLSS: ... preset <letter> line says which one was
asked for, and with RX_VK_DLSS_LOG=1 NGX's own Using App hint Preset <letter> lines say which it took.
8 GB cards: DLAA draws the 3D at full size, and DLSS and DLAA add images of their own beside the game's. In busy
areas that can pass what the driver allows the game, and the game then stutters: Quality or Balanced is safer there.
The log's vk: status: line every 600 frames shows the video memory in use of the allowance, with DLSS's details
(its images' size, the jitter and the actor motion) appended while it draws, and a vk: over the driver's video-memory allowance line says when the game passed it.
The game's log says whether DLSS started, and why not when it did not (vk: NVIDIA DLSS: lines in hookshot_log.txt).
NGX starts on demand: when the Insert menu first opens (to know whether the Upscaler can offer DLSS) or at the first
gameplay upscale with DLSS chosen, so on the title screen the log has no NGX lines yet.
With RX_VK_DLSS_LOG=1 NGX's own lines go there too (ngx:). Some of them look like errors but are not:
failed to load NGXCore: 126 (twice) is NVIDIA's library looking for _nvngx.dll and nvngx.dll beside the game, which
are not there on purpose, before it loads the driver's; Feature ... failed to load from cache is NGX finding no model
of its own downloads (C:\ProgramData\NVIDIA\NGX\models) before it uses the game folder's nvngx_dlss.dll.
Switches for testing (hookshot_env.txt)
Switches to test (RX_VK_NOOPT=1 and the others) go in hookshot_env.txt in the game folder, one NAME=VALUE a
line, on Windows and Linux. The running game reads it, not the builder. A test run can name another file with
HOS_ENV_FILE=<path>; the game then reads that one instead and leaves hookshot_env.txt alone.
To enable the debug menu, add HOS_OOT_CHEATS=1 to hookshot_env.txt in the game folder. Restart the game,
press Insert, then open Gameplay → Cheats.
For a first run on a 4 GB card such as a GTX 1650, RX_VK_LOW_SPEC=1 starts with the Minimum (4GB) preset, with
frame generation and upscaling off. It applies only when there is no hookshot_options.ini yet; after that, change
the settings in the in-game menu.
RX_VK_MOVIE_UPSCALE=linear replaces the movies' neural upscale with the plain linear one. The default, auto, keeps
the networks and falls back only when a movie frame takes the GPU more than 40 ms. It does not change the gameplay
upscaler, and movies can look softer. RX_VK_NETWORK_KEEP=all takes precedence and keeps the movie networks.
RX_VK_SKIP_CODE=<prefix,...> leaves out the draws of every program with a stage whose native code key starts with one
of the prefixes (the keys the log prints after "its code:"). On a Steam Deck, RX_VK_SKIP_CODE=2c56dc1006942f74
avoids a GPU hang in Kokiri Forest and the Great Deku Tree: the GPU runs for seconds in the programs that share that
task shader (a culling pass) until the kernel resets it (#817).
It is a workaround, not a fix: those are task + mesh programs, so the geometry they draw goes with them, and key models
are missing while it is set. Off unless set.
nx2/lift.pytranslates the game's ARM64 code to C.nx2/build.pycompiles that C together withhost/, which plays the part of the console's system.host/nvn_native.crecords the game's NVN2 graphics calls, andgpu/vk/replays them on Vulkan.- Switch 2 Ampere shaders are lowered to Maxwell (
lower_to_maxwell.h) and translated to SPIR-V by Eden's shader recompiler.
More detail is in the development guide and the design notes.
Testing on other graphics cards and reporting the result already helps a lot, and so does playing further into the game than anyone has yet.
Bigger ways to help:
- Linux testing. The Linux build (
host/posix) has been tested on several distributions and cards: reports from others still help. - Fixes in your own fork. Fork the project, fix what you find and send the change back. Keep game files, keys and anything generated from your game out of it.
CONTRIBUTING.md has the setup, the test commands, the code conventions and what a good pull request looks like.
Hookshot exists thanks to the work of many people:
- NotRexed: Hookshot, BlueShell (Mario Kart World), Skybound (Tears of the Kingdom) and the a64-kit tools.
- Eden and Eglantine: the shader recompiler and Switch 2 shader work.
- suyu: the graphics decoders and the AArch64 translator.
- seedds/nxnative: reference for how task and mesh shaders work.
- EvilBoyce / evilmfkr (EvilOOT): the GPU culling that brings back Kokiri's foliage (trees, ferns, grass, falling leaves, fireflies), the ambient light probes, the pond's water, the game's own fog, the freeze after Load (Horizon's mutex handoff) and the exposure flicker fix.
- zortos293/Lichii: reference for Ampere shader lowering, and its compare-exchange retry fix.
- mstorsjo/llvm-mingw: the bundled Windows compiler (no Visual Studio needed).
- NVIDIA DLSS: builds made with NVIDIA's DLSS SDK (optional, downloaded by each build, never bundled) use NVIDIA DLSS Super Resolution, NVIDIA's technology. NVIDIA and DLSS are trademarks of NVIDIA Corporation.
- kinnay/zbic, Opus and SDL: decompression, audio and controllers.
- sostenesfreitas/ocarina-recomp: this README's layout, and its notes confirmed the mesh stage's control section.
- MythosOfs/Orchid: the fog and exposure workaround for Ocarina of Time.
- Mesa (NAK): the reference for Ampere's instruction encoding.
- Everyone who sent fixes: SkippySteve (Linux and the AppImage, and many more), monsterlag, klimovich008, hckrman101 (the exposure flicker and fog fixes, build speed, CI), shayderrr, gab9281, Wpaif, nicholasgower, ZurielAtr, Joey-Magnus, Zorkats, d3zessete, chrispository, vzeol, leonidasmark, Segmentree, ShyVortex, hiKareeem and i900gaming, among others.
Hookshot is free software under the GNU General Public License, version 3 or later (GPL-3.0-or-later). It includes code from Eden, suyu and Orchid, which are under the GPL too. Third-party parts under other licenses that work with the GPL (Sirit, the Vulkan Memory Allocator, SDL, Opus, stb, zbic and the a64-kit tools) keep their own notices in their folders.
Hookshot is an unofficial fan project, not affiliated with or endorsed by Nintendo. The Legend of Zelda and Ocarina of Time are trademarks of Nintendo.
