├── .github
├── ISSUE_TEMPLATE
│ └── bug_report.md
├── linux
│ ├── Zelda64Recompiled.desktop
│ └── appimage.sh
└── workflows
│ ├── update-pr-artifacts.yml
│ ├── validate-external.yml
│ ├── validate-internal.yml
│ └── validate.yml
├── .gitignore
├── .gitmodules
├── BUILDING.md
├── CMakeLists.txt
├── CMakeSettings.json
├── COPYING
├── N64ModernRuntime.patch
├── README.md
├── assets
├── ChiaroBold.otf
├── ChiaroNormal.otf
├── LatoLatin-Bold.ttf
├── LatoLatin-BoldItalic.ttf
├── LatoLatin-Italic.ttf
├── LatoLatin-Regular.ttf
├── NotoEmoji-Regular.ttf
├── components
│ └── prompt.rml
├── config_menu.rml
├── config_menu
│ ├── controls.rml
│ ├── debug.rml
│ ├── general.rml
│ ├── graphics.rml
│ └── sound.rml
├── icons
│ ├── Arrow.svg
│ ├── Plus.svg
│ ├── Quit.svg
│ ├── RecordBorder.svg
│ ├── Reset.svg
│ ├── Trash.svg
│ ├── VizMap
│ │ ├── ButtonLarge.svg
│ │ ├── ButtonMedium.svg
│ │ ├── ButtonSmall.svg
│ │ ├── DPad.svg
│ │ ├── DPadArrow.svg
│ │ ├── Map.svg
│ │ ├── Shield.svg
│ │ └── Target.svg
│ └── X.svg
├── launcher.rml
├── mm-clipped.svg
├── promptfont
│ ├── LICENSE.txt
│ ├── README.md
│ ├── promptfont.css
│ └── promptfont.ttf
├── recomp.rcss
├── rml.rcss
└── scss
│ ├── .nvmrc
│ ├── .stylelintrc
│ ├── main.scss
│ ├── package-lock.json
│ ├── package.json
│ └── styles
│ ├── base.scss
│ ├── components
│ ├── BottomLeft.scss
│ ├── Button.scss
│ ├── CenteredPage.scss
│ ├── Config.scss
│ ├── ControlOption.scss
│ ├── IconButton.scss
│ ├── InputConfig.scss
│ ├── Launcher.scss
│ ├── MenuListItem.scss
│ ├── Prompt.scss
│ ├── SubtitleTitle.scss
│ ├── Tabs.scss
│ ├── Toggle.scss
│ └── _components.scss
│ ├── functions
│ └── _spacing.scss
│ ├── global.scss
│ ├── globals
│ ├── _old.scss
│ └── _scrollbars.scss
│ ├── mixins
│ ├── _helpers.scss
│ ├── _transitions.scss
│ └── _typography.scss
│ ├── pages
│ ├── _pages.scss
│ └── config
│ │ ├── _config.scss
│ │ └── debug.scss
│ └── vars
│ ├── _animations.scss
│ ├── _borders.scss
│ ├── _colors.scss
│ ├── _gradients.scss
│ ├── _spacing.scss
│ └── _transitions.scss
├── docs
└── deck_gyro_1.jpg
├── icons
├── 128.ico
├── 16.ico
├── 256.ico
├── 32.ico
├── 512.ico
├── 512.png
├── 64.ico
└── app.rc
├── include
├── ovl_patches.hpp
├── promptfont.h
├── recomp_files.h
├── recomp_input.h
├── recomp_ui.h
├── zelda_config.h
├── zelda_debug.h
├── zelda_game.h
├── zelda_render.h
└── zelda_sound.h
├── launch.vs.json
├── lib
├── FindFreetype.cmake
├── GamepadMotionHelpers
│ ├── .gitignore
│ ├── CMakeLists.txt
│ ├── GamepadMotion.hpp
│ ├── LICENSE
│ └── README.md
└── concurrentqueue
│ ├── blockingconcurrentqueue.h
│ ├── concurrentqueue.h
│ └── lightweightsemaphore.h
├── n_aspMain.toml
├── patches.toml
├── patches
├── .gitignore
├── Makefile
├── dummy_headers
│ ├── assets
│ │ └── objects
│ │ │ └── object_fall2
│ │ │ └── object_fall2.h
│ ├── code
│ │ └── sub_s
│ │ │ └── sub_s.h
│ └── objects
│ │ ├── gameplay_keep
│ │ └── gameplay_keep.h
│ │ ├── object_boss03
│ │ └── object_boss03.h
│ │ ├── object_boss04
│ │ └── object_boss04.h
│ │ └── object_ha
│ │ └── object_ha.h
├── graphics.h
├── misc_funcs.h
├── patch_helpers.h
├── patches.h
├── patches.ld
├── print.c
├── sounds.h
├── syms.ld
├── temp.c
├── xldtob.c
├── xlitob.c
├── xprintf.c
└── xstdio.h
├── rsp
└── .gitignore
├── shadercache
└── .gitkeep
├── shaders
├── InterfacePS.hlsl
└── InterfaceVS.hlsl
├── src
├── game
│ ├── config.cpp
│ ├── controls.cpp
│ ├── debug.cpp
│ ├── input.cpp
│ ├── quicksaving.cpp
│ ├── recomp_api.cpp
│ └── scene_table.cpp
├── main
│ ├── main.cpp
│ ├── register_overlays.cpp
│ ├── register_patches.cpp
│ └── rt64_render_context.cpp
└── ui
│ ├── ui_color_hack.cpp
│ ├── ui_config.cpp
│ ├── ui_launcher.cpp
│ ├── ui_renderer.cpp
│ ├── ui_rml_hacks.cpp
│ └── ui_rml_hacks.hpp
└── us.toml
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Report a bug in the project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | ## If you have a crash on startup, please make sure your graphics drivers are up to date before submitting a bug report.
11 |
12 | **What is your GPU driver version? Old drivers, particularly on Nvidia, are known to cause crashes on boot on 1.1.0. If you are on Nvidia and the game is crashing on boot, please update to driver version 555.85 or newer before opening an issue.**
13 |
14 | **Have you checked whether this issue is vanilla behavior? In other words, does it occur on original hardware?**
15 |
16 | **Were you playing with intended mechanics, or using glitches? If it's the latter, which glitches?**
17 |
18 | **Describe the bug**
19 | A clear and concise description of what the bug is.
20 |
21 | **To Reproduce**
22 | Steps to reproduce the behavior:
23 | 1. Go to '...'
24 | 2. etc.
25 |
26 | **Expected behavior**
27 | A clear and concise description of what you expected to happen.
28 |
29 | **Screenshots**
30 | Please attach a screenshot of the bug.
31 |
32 | **Desktop (please complete the following information):**
33 | - OS: [Windows 10, Windows 11, Linux distro]
34 | - Version: [e.g. 1.0.0]
35 | - CPU: [e.g. Intel Core ..., AMD Ryzen ..., etc.]
36 | - GPU: [e.g. NVIDIA GeForce .../Radeon RX .../Intel UHD .../etc.]
37 | - GPU driver: [e.g Nvidia driver 545.XX, AMD driver 24.X.X, etc]
38 |
39 | **Additional context**
40 | Add any other context about the problem here.
41 |
--------------------------------------------------------------------------------
/.github/linux/Zelda64Recompiled.desktop:
--------------------------------------------------------------------------------
1 | [Desktop Entry]
2 | Name=Zelda64Recompiled
3 | Type=Application
4 | Terminal=false
5 | Icon=Zelda64Recompiled
6 | Exec=Zelda64Recompiled
7 | GenericName=Zelda64Recompiled
8 | Categories=Game;
9 |
10 |
--------------------------------------------------------------------------------
/.github/linux/appimage.sh:
--------------------------------------------------------------------------------
1 | ARCH=$(uname -m)
2 | LINUX_DEPLOY_ARCH=$(uname -m)
3 |
4 | if [ "$ARCH" = "x86_64" ]; then
5 | ARCH="x86_64"
6 | LINUX_DEPLOY_ARCH="x86_64"
7 | elif [ "$ARCH" = "aarch64" ]; then
8 | ARCH="arm_aarch64"
9 | LINUX_DEPLOY_ARCH="aarch64"
10 | else
11 | echo "Unsupported architecture: $ARCH"
12 | exit 1
13 | fi
14 |
15 | curl -sSfLO "https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-$LINUX_DEPLOY_ARCH.AppImage"
16 | curl -sSfLO "https://github.com/linuxdeploy/linuxdeploy-plugin-gtk/raw/master/linuxdeploy-plugin-gtk.sh"
17 |
18 | chmod a+x linuxdeploy*
19 |
20 | mkdir -p AppDir/usr/bin
21 | cp Zelda64Recompiled AppDir/usr/bin/
22 | cp -r assets/ AppDir/usr/bin/
23 | cp gamecontrollerdb.txt AppDir/usr/bin/
24 | cp icons/512.png AppDir/Zelda64Recompiled.png
25 | cp .github/linux/Zelda64Recompiled.desktop AppDir/
26 |
27 | "./linuxdeploy-$LINUX_DEPLOY_ARCH.AppImage" --appimage-extract
28 | mv squashfs-root/ deploy
29 | ./deploy/AppRun --appdir=AppDir/ -d AppDir/Zelda64Recompiled.desktop -i AppDir/Zelda64Recompiled.png -e AppDir/usr/bin/Zelda64Recompiled --plugin gtk
30 | sed -i 's/exec/#exec/g' AppDir/AppRun
31 | echo 'if [ -f "portable.txt" ]; then' >> AppDir/AppRun
32 | echo ' APP_FOLDER_PATH=$PWD' >> AppDir/AppRun
33 | echo ' cd "$this_dir"/usr/bin/' >> AppDir/AppRun
34 | echo ' APP_FOLDER_PATH=$APP_FOLDER_PATH ./Zelda64Recompiled' >> AppDir/AppRun
35 | echo 'else' >> AppDir/AppRun
36 | echo ' cd "$this_dir"/usr/bin/' >> AppDir/AppRun
37 | echo ' ./Zelda64Recompiled' >> AppDir/AppRun
38 | echo 'fi' >> AppDir/AppRun
39 |
40 | # Remove conflicting libraries
41 | rm -rf AppDir/usr/lib/libgmodule*
42 | rm -rf AppDir/usr/lib/gio/modules/*.so
43 | rm -rf AppDir/usr/lib/libwayland*
44 |
45 | ./deploy/usr/bin/linuxdeploy-plugin-appimage --appdir=AppDir
46 |
--------------------------------------------------------------------------------
/.github/workflows/update-pr-artifacts.yml:
--------------------------------------------------------------------------------
1 | name: update-pr-artifacts
2 | on:
3 | workflow_run:
4 | workflows: [validate-external, validate-internal]
5 | types:
6 | - completed
7 | jobs:
8 | update-pr-artifacts:
9 | runs-on: ubuntu-latest
10 | if: (github.event.workflow_run.event == 'pull_request' || github.event.workflow_run.event == 'pull_request_target') && github.event.workflow_run.conclusion == 'success'
11 | name: Update PR Artifacts
12 | steps:
13 | - name: Get PR Number
14 | id: pr-number
15 | uses: actions/github-script@v6
16 | with:
17 | result-encoding: string
18 | script: |
19 | const { owner, repo } = context.repo;
20 |
21 | const findPRNumber = async () => {
22 | const pulls = await github.rest.pulls.list({ owner, repo });
23 | for await (const { data } of github.paginate.iterator(pulls)) {
24 | for (const pull of data) {
25 | if (pull.head.sha === '${{ github.event.workflow_run.head_sha }}' && pull.user.id === ${{ github.event.sender.id }}) {
26 | return pull.number;
27 | }
28 | }
29 | }
30 |
31 | return null;
32 | };
33 |
34 | const prNumber = await findPRNumber();
35 | if (!prNumber) {
36 | core.error(`No matching pull request found`);
37 | } else {
38 | return prNumber;
39 | }
40 | - name: Create Artifacts Content
41 | id: artifacts-content
42 | uses: actions/github-script@v6
43 | with:
44 | result-encoding: string
45 | script: |
46 | const artifacts = await github.rest.actions.listWorkflowRunArtifacts({
47 | owner: context.repo.owner,
48 | repo: context.repo.repo,
49 | run_id: context.payload.workflow_run.id,
50 | });
51 |
52 | const nightlyLinks = artifacts.data.artifacts.reduce((acc, item) => {
53 | acc += `- [${item.name}.zip](https://nightly.link/${context.repo.owner}/${context.repo.repo}/actions/artifacts/${item.id}.zip)\n`;
54 | return acc;
55 | }, '### Build Artifacts\n');
56 |
57 | return nightlyLinks;
58 | - name: Update PR Description
59 | uses: garrettjoecox/pr-section@3.1.0
60 | with:
61 | section-name: 'artifacts'
62 | repo-token: '${{ secrets.GITHUB_TOKEN }}'
63 | pr-number: ${{ steps.pr-number.outputs.result }}
64 | section-value: '${{ steps.artifacts-content.outputs.result }}'
65 |
--------------------------------------------------------------------------------
/.github/workflows/validate-external.yml:
--------------------------------------------------------------------------------
1 | name: validate-external
2 | on:
3 | pull_request_target:
4 | types: [opened, synchronize]
5 | jobs:
6 | authorize:
7 | if: github.repository != github.event.pull_request.head.repo.full_name
8 | environment:
9 | ${{ github.event_name == 'pull_request_target' &&
10 | github.event.pull_request.head.repo.full_name != github.repository &&
11 | 'external' || 'internal' }}
12 | runs-on: ubuntu-latest
13 | steps:
14 | - run: echo ✓
15 | build:
16 | needs: authorize
17 | uses: ./.github/workflows/validate.yml
18 | secrets:
19 | ZRE_REPO_WITH_PAT: ${{ secrets.ZRE_REPO_WITH_PAT }}
20 |
--------------------------------------------------------------------------------
/.github/workflows/validate-internal.yml:
--------------------------------------------------------------------------------
1 | name: validate-internal
2 | on:
3 | push:
4 | branches:
5 | - dev
6 | pull_request:
7 | types: [opened, synchronize]
8 | jobs:
9 | build:
10 | if: github.event_name == 'push' || github.repository == github.event.pull_request.head.repo.full_name
11 | uses: ./.github/workflows/validate.yml
12 | secrets: inherit
13 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # VSCode file settings
2 | .vscode/settings.json
3 | .vscode/c_cpp_properties.json
4 | .vscode/launch.json
5 |
6 | # Input elf and rom files
7 | *.elf
8 | *.z64
9 |
10 | # Output C files
11 | RecompiledFuncs/
12 | RecompiledPatches/
13 |
14 | # Linux build output
15 | build/
16 | *.o
17 |
18 | # Windows build output
19 | *.exe
20 | *.dll
21 | *.lib
22 | *.pdb
23 |
24 | # User-specific files
25 | *.rsuser
26 | *.suo
27 | *.user
28 | *.userosscache
29 | *.sln.docstates
30 |
31 | # Build results
32 | [Dd]ebug/
33 | [Dd]ebugPublic/
34 | [Rr]elease/
35 | [Rr]eleases/
36 | x64/
37 | x86/
38 | [Ww][Ii][Nn]32/
39 | [Aa][Rr][Mm]/
40 | [Aa][Rr][Mm]64/
41 | bld/
42 | [Bb]in/
43 | [Oo]bj/
44 | [Ll]og/
45 | [Ll]ogs/
46 | out/
47 |
48 | # Visual Studio 2015/2017 cache/options directory
49 | .vs/
50 | vcpkg_installed/
51 |
52 | # Runtime files
53 | imgui.ini
54 | rt64.log
55 |
56 | node_modules/
57 |
58 | # Recompiler Linux binary
59 | N64Recomp
60 | RSPRecomp
61 | .DS_Store
62 |
63 | # Controller mappings file
64 | gamecontrollerdb.txt
65 |
66 | # Temp files
67 | src/main/*TMP
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "lib/RmlUi"]
2 | path = lib/RmlUi
3 | url = https://github.com/mikke89/RmlUi/
4 | [submodule "lib/rt64"]
5 | path = lib/rt64
6 | url = https://github.com/rt64/rt64
7 | [submodule "lib/freetype-windows-binaries"]
8 | path = lib/freetype-windows-binaries
9 | url = https://github.com/ubawurinna/freetype-windows-binaries
10 | [submodule "lib/lunasvg"]
11 | path = lib/lunasvg
12 | url = https://github.com/sammycage/lunasvg
13 | [submodule "lib/sse2neon"]
14 | path = lib/sse2neon
15 | url = https://github.com/DLTcollab/sse2neon.git
16 | [submodule "lib/N64ModernRuntime"]
17 | path = lib/N64ModernRuntime
18 | url = https://github.com/N64Recomp/N64ModernRuntime.git
19 | [submodule "Dk64Syms"]
20 | path = Dk64Syms
21 | url = https://github.com/Rainchus/Dk64Syms.git
22 | [submodule "lib/dk64_decomp"]
23 | path = lib/dk64_decomp
24 | url = https://gitlab.com/Rainchus/dk64
25 | branch = recomp
26 |
--------------------------------------------------------------------------------
/BUILDING.md:
--------------------------------------------------------------------------------
1 | # Building Guide
2 |
3 | This guide will help you build the project on your local machine. The process will require you to provide a ROM of the JP version of the game.
4 |
5 | These steps cover: running the recompiler and building the project.
6 |
7 | ## 1. Clone the ChameleonTwist1-JP-Recomp Repository
8 | This project makes use of submodules so you will need to clone the repository with the `--recurse-submodules` flag.
9 |
10 | ```bash
11 | git clone --recurse-submodules
12 | # if you forgot to clone with --recurse-submodules
13 | # cd /path/to/cloned/repo && git submodule update --init --recursive
14 | ```
15 |
16 | ## 2. Install Dependencies
17 |
18 | ### Linux
19 | For Linux the instructions for Ubuntu are provided, but you can find the equivalent packages for your preferred distro.
20 |
21 | ```bash
22 | # For Ubuntu, simply run:
23 | sudo apt-get install cmake ninja-build libsdl2-dev libgtk-3-dev lld llvm clang
24 | ```
25 |
26 | ### Windows
27 | You will need to install [Visual Studio 2022](https://visualstudio.microsoft.com/downloads/).
28 | In the setup process you'll need to select the following options and tools for installation:
29 | - Desktop development with C++
30 | - C++ Clang Compiler for Windows
31 | - C++ CMake tools for Windows
32 |
33 | The other tool necessary will be `make` which can be installe via [Chocolatey](https://chocolatey.org/):
34 | ```bash
35 | choco install make
36 | ```
37 |
38 | ## 3. Generating the C code
39 |
40 | You will need to place a Japanese ROM with the name `chameleontwist.jp.z64` in the root of the project
41 | Now that you have the required files, you must build the live-recomp branch of [N64Recomp](https://github.com/N64Recomp/N64Recomp/tree/live-recomp) and run it to generate the C code to be compiled. The building instructions can be found [here](https://github.com/Mr-Wiseguy/N64Recomp?tab=readme-ov-file#building). That will build the executables: `N64Recomp` and `RSPRecomp` which you should copy to the root of the Zelda64Recomp repository.
42 |
43 | After that, go back to the repository root, and run the following commands:
44 | ```bash
45 | ./N64Recomp jp.rev0.toml
46 | ./RSPRecomp aspMain.us.rev1.toml
47 | ```
48 |
49 | ## 4. Temporary Step
50 | Copy [this version](https://github.com/N64Recomp/N64Recomp/blob/live-recomp/include/recomp.h) of `recomp.h` to `lib/N64ModernRuntime/librecomp/include/librecomp/recomp.h`
51 | Soon this will not be required
52 |
53 |
54 | ## 5. Building the Project
55 |
56 | Finally, you can build the project! :rocket:
57 |
58 | On Windows, you can open the repository folder with Visual Studio, and you'll be able to `[build / run / debug]` the project from there.
59 |
60 | If you prefer the command line or you're on a Unix platform you can build the project using CMake:
61 |
62 | ```bash
63 | cmake -S . -B build-cmake -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang -G Ninja -DCMAKE_BUILD_TYPE=Release # or Debug if you want to debug
64 | cmake --build build-cmake --target Zelda64Recompiled -j$(nproc) --config Release # or Debug
65 | ```
66 |
67 | ## 6. Success
68 |
69 | Voilà! You should now have a `ChameleonTwistJPRecompiled` executable in the build directory! If you used Visual Studio this will be `out/build/x64-[Configuration]` and if you used the provided CMake commands then this will be `build-cmake`. You will need to run the executable out of the root folder of this project or copy the assets folder to the build folder to run it.
70 |
--------------------------------------------------------------------------------
/CMakeSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "configurations": [
3 | {
4 | "name": "x64-Debug",
5 | "generator": "Ninja",
6 | "configurationType": "Debug",
7 | "inheritEnvironments": [ "clang_cl_x64" ],
8 | "buildRoot": "${projectDir}\\out\\build\\${name}",
9 | "installRoot": "${projectDir}\\out\\install\\${name}",
10 | "cmakeCommandArgs": "",
11 | "buildCommandArgs": "",
12 | "ctestCommandArgs": ""
13 | },
14 | {
15 | "name": "x64-Release",
16 | "generator": "Ninja",
17 | "configurationType": "Release",
18 | "buildRoot": "${projectDir}\\out\\build\\${name}",
19 | "installRoot": "${projectDir}\\out\\install\\${name}",
20 | "cmakeCommandArgs": "",
21 | "buildCommandArgs": "",
22 | "ctestCommandArgs": "",
23 | "inheritEnvironments": [ "clang_cl_x64" ]
24 | },
25 | {
26 | "name": "x64-ReleaseWithDebInfo",
27 | "generator": "Ninja",
28 | "configurationType": "RelWithDebInfo",
29 | "buildRoot": "${projectDir}\\out\\build\\${name}",
30 | "installRoot": "${projectDir}\\out\\install\\${name}",
31 | "cmakeCommandArgs": "",
32 | "buildCommandArgs": "",
33 | "ctestCommandArgs": "",
34 | "inheritEnvironments": [ "clang_cl_x64" ],
35 | "variables": []
36 | }
37 | ]
38 | }
--------------------------------------------------------------------------------
/N64ModernRuntime.patch:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rainchus/Dk64-Recompiled/7d24f9bbd7f8b0931695f04a1ebb0309fd0eec75/N64ModernRuntime.patch
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Chameleon Twist: Recompiled
2 | Chameleon Twist: Recompiled is a project that uses [N64: Recompiled](https://github.com/Mr-Wiseguy/N64Recomp) to **statically recompile** Chameleon Twist into a native port with many new features and enhancements. This project uses [RT64](https://github.com/rt64/rt64) as the rendering engine to provide some of these enhancements.
3 |
4 | ### [Check out the latest release here](https://github.com/Rainchus/ChameleonTwist1-JP-Recomp/releases).
5 |
6 | ### **This repository and its releases do not contain game assets. The original game is required to build or run this project.**
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | _Thank you [Blaze](https://runblaze.dev) for supporting this project by providing Linux ARM64 and Apple Silicon macOS Github Action Runners!_
19 |
20 |
21 |
22 | ## Table of Contents
23 | * [System Requirements](#system-requirements)
24 | * [Features](#features)
25 | * [Plug and Play](#plug-and-play)
26 | * [Fully Intact N64 Effects](#fully-intact-n64-effects)
27 | * [Easy-to-Use Menus](#easy-to-use-menus)
28 | * [High Framerate Support](#high-framerate-support)
29 | * [Low Input Lag](#low-input-lag)
30 | * [Instant Load Times](#instant-load-times)
31 | * [Linux and Steam Deck Support](#linux-and-steam-deck-support)
32 | * [Planned Features](#planned-features)
33 | * [FAQ](#faq)
34 | * [Known Issues](#known-issues)
35 | * [Building](#building)
36 | * [Libraries Used and Projects Referenced](#libraries-used-and-projects-referenced)
37 |
38 | ## System Requirements
39 | A GPU supporting Direct3D 12.0 (Shader Model 6) or Vulkan 1.2 is required to run this project. The oldest GPUs that should be supported for each vendor are:
40 | * GeForce GT 630
41 | * Radeon HD 7750 (the one from 2012, not to be confused with the RX 7000 series) and newer
42 | * Intel HD 510 (Skylake)
43 |
44 | A CPU supporting the AVX instruction set is also required (Intel Core 2000 series or AMD Bulldozer and newer).
45 |
46 | If you have issues with crashes on startup, make sure your graphics drivers are fully up to date.
47 |
48 | ## Features
49 |
50 | #### Fully Intact N64 Effects
51 | A lot of care was put into RT64 to make sure all graphical effects were rendered exactly as they did originally on the N64. No workarounds or "hacks" were made to replicate these effects, with the only modifications to them being made for enhancement purposes such as widescreen support.
52 |
53 | #### Easy-to-Use Menus
54 | Gameplay settings, graphics settings, input mappings, and audio settings can all be configured with the in-game config menu. The menus can all be used with mouse, controller, or keyboard for maximum convenience.
55 |
56 | #### High Framerate Support
57 | Play at any framerate you want thanks to functionality provided by RT64! Game objects and terrain, texture scrolling, screen effects, and most HUD elements are all rendered at high framerates. By default, this project is configured to run at your monitor's refresh rate. You can also play at the original framerate of the game if you prefer. **Changing framerate has no effect on gameplay.**
58 |
59 | **Note**: External framerate limiters (such as the NVIDIA Control Panel) are known to potentially cause problems, so if you notice any stuttering then turn them off and use the manual framerate slider in the in-game graphics menu instead.
60 |
61 | #### Widescreen and Ultrawide Support
62 | Any aspect ratio is supported, with most effects modded to work correctly in widescreen. The HUD can also be positioned at 16:9 when using ultrawide aspect ratios if preferred.
63 |
64 | **Note**: Some animation quirks can be seen at the edges of the screen in certain cutscenes when using very wide aspect ratios.
65 |
66 | #### Additional Control Options
67 | Customize your experience by setting your stick deadzone to your liking, as well as adjusting the X and Y axis inversion for both aiming and the optional dual analog camera.
68 |
69 | #### Low Input Lag
70 | This project has been optimized to have as little input lag as possible, making the game feel more responsive than ever!
71 |
72 | #### Instant Load Times
73 | Saving and loading files, going from place to place, and pausing all happen in the blink of an eye thanks to the game running natively on modern hardware.
74 |
75 | #### Linux and Steam Deck Support
76 | A Linux binary is available for playing on most up-to-date distros, including on the Steam Deck.
77 |
78 | To play on Steam Deck, extract the Linux build onto your deck. Then, in desktop mode, right click the Zelda64Recompiled executable file and select "Add to Steam". From there, you can return to Gaming mode and configure the controls as needed. See the [Steam Deck gyro aim FAQ section](#how-do-i-set-up-gyro-aiming-on-steam-deck) for more detailed instructions.
79 |
80 | ## FAQ
81 |
82 | #### What is static recompilation?
83 | Static recompilation is the process of automatically translating an application from one platform to another. For more details, check out the full description of how this project's recompilation works here: [N64: Recompiled](https://github.com/Mr-Wiseguy/N64Recomp).
84 |
85 | #### How is this related to the decompilation project?
86 | Unlike N64 ports in the past, this project is not based on the source code provided by a decompilation of the game. This is because static recompilation bypasses the need for decompiled source code when making a port, allowing ports to be made **without source code**. However, the reverse engineering work done by the decompilation team was invaluable for providing some of the enhancements featured in this project. For this reason, the project uses headers and some functions from the decompilation project in order to make modifications to the game. Many thanks to the decompilation team for all of the hard work they've done.
87 |
88 | #### Where is the savefile stored?
89 | - Windows: `%LOCALAPPDATA%\ChameleonTwistRecompiled\saves`
90 | - Linux: `~/.config/ChameleonTwistRecompiled/saves`
91 |
92 | #### How do I choose a different ROM?
93 | **You don't.** This project is **only** a port of Chameleon Twist and it will only accept one specific ROM: the JP version of the N64 release of Chameleon Twist. ROMs in formats other than .z64 will be automatically converted, as long as it is the correct ROM. **It is not an emulator and it cannot run any arbitrary ROM.**
94 |
95 | If you want to play a modded ROM or in another language, note that support for modding and other languages will be added to the project itself in the future and will not rely on you supplying a different ROM.
96 |
97 | ## Known Issues
98 | * Intel GPUs on Linux may not currently work. If you have experience with Vulkan development on Linux, help here would be greatly appreciated!
99 | * The prebuilt Linux binary may not work correctly on some distributions of Linux. If you encounter such an issue, building the project locally yourself is recommended. A Flatpak or AppImage may be provided in the future to solve this issue. Adding the Linux version to Steam and setting "Steam Linux Runtime" as the compatibility tool or launching it via Gamescope may work around the issue. Alternatively, running the Windows version with Proton is known to work well and may also work around this issue.
100 | * Overlays such as MSI Afterburner and other software such as Wallpaper Engine can cause performance issues with this project that prevent the game from rendering correctly. Disabling such software is recommended.
101 |
102 | ## Building
103 | Building is not required to play this project, as prebuilt binaries (which do not contain game assets) can be found in the [Releases](https://github.com/Rainchus/ChameleonTwist1-JP-Recomp/releases) section. Instructions on how to build this project can be found in the [BUILDING.md](BUILDING.md) file.
104 |
105 | ## Libraries Used and Projects Referenced
106 | * [RT64](https://github.com/rt64/rt64) for the project's rendering engine
107 | * [RmlUi](https://github.com/mikke89/RmlUi) for building the menus and launcher
108 | * [lunasvg](https://github.com/sammycage/lunasvg) for SVG rendering, used by RmlUi
109 | * [FreeType](https://freetype.org/) for font rendering, used by RmlUi
110 | * [moodycamel::ConcurrentQueue](https://github.com/cameron314/concurrentqueue) for semaphores and fast, lock-free MPMC queues
111 | * [Gamepad Motion Helpers](https://github.com/JibbSmart/GamepadMotionHelpers) for sensor fusion and calibration algorithms to implement gyro aiming
112 | * [Chameleon Twist Decompilation](https://github.com/chameleonTwistRet/chameleonTwistv1.0-JP) for headers and some function definitions, used for making patches or some enhancements
113 | * [Ares emulator](https://github.com/ares-emulator/ares) for RSP vector instruction reference implementations, used in RSP recompilation
114 |
115 | Special thanks to [thecozies](https://github.com/thecozies) for designing and helping implement the launcher and config menus!
116 |
--------------------------------------------------------------------------------
/assets/ChiaroBold.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rainchus/Dk64-Recompiled/7d24f9bbd7f8b0931695f04a1ebb0309fd0eec75/assets/ChiaroBold.otf
--------------------------------------------------------------------------------
/assets/ChiaroNormal.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rainchus/Dk64-Recompiled/7d24f9bbd7f8b0931695f04a1ebb0309fd0eec75/assets/ChiaroNormal.otf
--------------------------------------------------------------------------------
/assets/LatoLatin-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rainchus/Dk64-Recompiled/7d24f9bbd7f8b0931695f04a1ebb0309fd0eec75/assets/LatoLatin-Bold.ttf
--------------------------------------------------------------------------------
/assets/LatoLatin-BoldItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rainchus/Dk64-Recompiled/7d24f9bbd7f8b0931695f04a1ebb0309fd0eec75/assets/LatoLatin-BoldItalic.ttf
--------------------------------------------------------------------------------
/assets/LatoLatin-Italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rainchus/Dk64-Recompiled/7d24f9bbd7f8b0931695f04a1ebb0309fd0eec75/assets/LatoLatin-Italic.ttf
--------------------------------------------------------------------------------
/assets/LatoLatin-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rainchus/Dk64-Recompiled/7d24f9bbd7f8b0931695f04a1ebb0309fd0eec75/assets/LatoLatin-Regular.ttf
--------------------------------------------------------------------------------
/assets/NotoEmoji-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rainchus/Dk64-Recompiled/7d24f9bbd7f8b0931695f04a1ebb0309fd0eec75/assets/NotoEmoji-Regular.ttf
--------------------------------------------------------------------------------
/assets/components/prompt.rml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
{{ promptHeader }}
9 |
{{ promptContent }}
10 |
11 |
17 | {{ promptConfirmLabel }}
18 |
19 |
24 | {{ promptCancelLabel }}
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/assets/config_menu.rml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Inventory
6 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 | General
41 |
42 |
43 |
44 |
45 |
46 |
47 | Controls
48 |
49 |
50 |
51 |
52 |
53 |
54 | Graphics
55 |
56 |
57 |
58 |
59 |
60 |
61 | Sound
62 |
63 |
64 |
65 |
66 |
67 |
68 | Debug
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
81 |
82 |
83 |
90 |
91 |
92 |
96 |
97 | Navigate
98 | {{nav_help__navigate}}
99 |
100 |
101 | Accept
102 | {{nav_help__accept}}
103 |
104 |
105 | Exit
106 | {{nav_help__exit}}
107 |
108 |
110 |
111 |
112 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
--------------------------------------------------------------------------------
/assets/config_menu/debug.rml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
106 |
107 |
108 |
--------------------------------------------------------------------------------
/assets/config_menu/sound.rml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/assets/icons/Arrow.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/assets/icons/Plus.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/assets/icons/Quit.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/assets/icons/RecordBorder.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/assets/icons/Reset.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/assets/icons/Trash.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/assets/icons/VizMap/ButtonLarge.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/assets/icons/VizMap/ButtonMedium.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/assets/icons/VizMap/ButtonSmall.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/assets/icons/VizMap/DPad.svg:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/assets/icons/VizMap/DPadArrow.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/assets/icons/VizMap/Map.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/assets/icons/VizMap/Shield.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
10 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/assets/icons/VizMap/Target.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
13 |
15 |
17 |
19 |
20 |
21 |
22 |
23 |
25 |
26 |
28 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
39 |
40 |
41 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/assets/icons/X.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/assets/launcher.rml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Launcher
4 |
5 |
6 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
Zelda 64: Recompiled
21 |
Ocarina of Time
22 | Coming Soon™
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
Zelda 64: Recompiled
34 |
Majora's Mask
35 |
36 |
37 |
38 |
42 |
46 |
50 |
54 |
58 |
59 |
60 |
61 | {{version_number}}
62 |
63 |
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/assets/promptfont/LICENSE.txt:
--------------------------------------------------------------------------------
1 | This Font Software is licensed under the SIL Open Font License,
2 | Version 1.1. This license is copied below, and is also available
3 | with a FAQ at
4 |
5 |
6 | -----------------------------------------------------------
7 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
8 | -----------------------------------------------------------
9 |
10 | PREAMBLE
11 | The goals of the Open Font License (OFL) are to stimulate worldwide
12 | development of collaborative font projects, to support the font creation
13 | efforts of academic and linguistic communities, and to provide a free and
14 | open framework in which fonts may be shared and improved in partnership
15 | with others.
16 |
17 | The OFL allows the licensed fonts to be used, studied, modified and
18 | redistributed freely as long as they are not sold by themselves. The
19 | fonts, including any derivative works, can be bundled, embedded,
20 | redistributed and/or sold with any software provided that any reserved
21 | names are not used by derivative works. The fonts and derivatives,
22 | however, cannot be released under any other type of license. The
23 | requirement for fonts to remain under this license does not apply
24 | to any document created using the fonts or their derivatives.
25 |
26 | DEFINITIONS
27 | "Font Software" refers to the set of files released by the Copyright
28 | Holder(s) under this license and clearly marked as such. This may
29 | include source files, build scripts and documentation.
30 |
31 | "Reserved Font Name" refers to any names specified as such after the
32 | copyright statement(s).
33 |
34 | "Original Version" refers to the collection of Font Software components as
35 | distributed by the Copyright Holder(s).
36 |
37 | "Modified Version" refers to any derivative made by adding to, deleting,
38 | or substituting -- in part or in whole -- any of the components of the
39 | Original Version, by changing formats or by porting the Font Software to a
40 | new environment.
41 |
42 | "Author" refers to any designer, engineer, programmer, technical
43 | writer or other person who contributed to the Font Software.
44 |
45 | PERMISSION & CONDITIONS
46 | Permission is hereby granted, free of charge, to any person obtaining
47 | a copy of the Font Software, to use, study, copy, merge, embed, modify,
48 | redistribute, and sell modified and unmodified copies of the Font
49 | Software, subject to the following conditions:
50 |
51 | 1) Neither the Font Software nor any of its individual components,
52 | in Original or Modified Versions, may be sold by itself.
53 |
54 | 2) Original or Modified Versions of the Font Software may be bundled,
55 | redistributed and/or sold with any software, provided that each copy
56 | contains the above copyright notice and this license. These can be
57 | included either as stand-alone text files, human-readable headers or
58 | in the appropriate machine-readable metadata fields within text or
59 | binary files as long as those fields can be easily viewed by the user.
60 |
61 | 3) No Modified Version of the Font Software may use the Reserved Font
62 | Name(s) unless explicit written permission is granted by the corresponding
63 | Copyright Holder. This restriction only applies to the primary font name as
64 | presented to the users.
65 |
66 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
67 | Software shall not be used to promote, endorse or advertise any
68 | Modified Version, except to acknowledge the contribution(s) of the
69 | Copyright Holder(s) and the Author(s) or with their explicit written
70 | permission.
71 |
72 | 5) The Font Software, modified or unmodified, in part or in whole,
73 | must be distributed entirely under this license, and must not be
74 | distributed under any other license. The requirement for fonts to
75 | remain under this license does not apply to any document created
76 | using the Font Software.
77 |
78 | TERMINATION
79 | This license becomes null and void if any of the above conditions are
80 | not met.
81 |
82 | DISCLAIMER
83 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
84 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
85 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
86 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
87 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
88 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
89 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
90 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
91 | OTHER DEALINGS IN THE FONT SOFTWARE.
92 |
--------------------------------------------------------------------------------
/assets/promptfont/README.md:
--------------------------------------------------------------------------------
1 | ## About PromptFont
2 | This is a font designed for button prompts in games. It includes the base alphabet, as well as icons for modifier and control keys, and gamepad buttons. All the icons included in the font are custom made and available under the same [SIL Open Font Licence](LICENSE.txt). Included trademarks however of course still belong to their respective owners.
3 |
4 | PromptFont is based on the Xolonium font by Severin Meyer.
5 |
6 | ## Attribution
7 | If you use this font in your project please leave an attribution notice in your credits like this:
8 |
9 | > PromptFont by Yukari "Shinmera" Hafner, available at https://shinmera.com/promptfont
10 |
11 | ## Special Glyphs
12 | Please see the included ``glyphs.json`` file for all the relevant glyphs in the font. It includes the code point of every glyph along with a unique name to address it with and a general category. You should be able to use it to create an equivalent mapping of glyphs in your engine of choice.
13 |
14 | ## Engine Specifics
15 | Since there's far too many engines out there and their methods vary a lot, we can't include guides in this repository. For specifics on how to use this font in your engine of choice, please consult their documentation on importing custom fonts and custom glyph ranges, and how to write text with specific unicode codepoints. Since this is literally just a font, it should not prove too difficult.
16 |
17 | ## Contributing Glyphs
18 | For a brief guide on what to watch out for if you'd like to contribute to this font, please see the [CONTRIBUTING.md](CONTRIBUTING.md) file. If you'd like to request new glyphs to be added, please comment on the [issue ticket]().
19 |
20 | ## Support
21 | If you'd like to support the continued development of PromptFont, please consider becoming a backer on Patreon:
22 |
23 | [](https://patreon.com/shinmera)
24 |
--------------------------------------------------------------------------------
/assets/promptfont/promptfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rainchus/Dk64-Recompiled/7d24f9bbd7f8b0931695f04a1ebb0309fd0eec75/assets/promptfont/promptfont.ttf
--------------------------------------------------------------------------------
/assets/rml.rcss:
--------------------------------------------------------------------------------
1 | /*
2 | * Default styles for all the basic elements.
3 | */
4 |
5 | div
6 | {
7 | display: block;
8 | }
9 |
10 | p
11 | {
12 | display: block;
13 | }
14 |
15 | h1
16 | {
17 | display: block;
18 | }
19 |
20 | em
21 | {
22 | font-style: italic;
23 | }
24 |
25 | strong
26 | {
27 | font-weight: bold;
28 | }
29 |
30 | select
31 | {
32 | text-align: left;
33 | }
34 |
35 | tabset tabs
36 | {
37 | display: block;
38 | }
39 |
40 | table {
41 | box-sizing: border-box;
42 | display: table;
43 | }
44 | tr {
45 | box-sizing: border-box;
46 | display: table-row;
47 | }
48 | td {
49 | box-sizing: border-box;
50 | display: table-cell;
51 | }
52 | col {
53 | box-sizing: border-box;
54 | display: table-column;
55 | }
56 | colgroup {
57 | display: table-column-group;
58 | }
59 | thead, tbody, tfoot {
60 | display: table-row-group;
61 | }
62 |
--------------------------------------------------------------------------------
/assets/scss/.nvmrc:
--------------------------------------------------------------------------------
1 | iron
2 |
--------------------------------------------------------------------------------
/assets/scss/.stylelintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "stylelint-config-recommended",
4 | "stylelint-config-standard",
5 | "stylelint-config-sass-guidelines",
6 | "stylelint-config-property-sort-order-smacss",
7 | "stylelint-config-standard-scss"
8 | ],
9 | "plugins": ["stylelint-scss"],
10 | "overrides": [{
11 | "files": ["**/*.scss"],
12 | "customSyntax": "postcss-scss"
13 | }],
14 | "rules": {
15 | "no-descending-specificity": null,
16 | "declaration-empty-line-before": null,
17 | "declaration-colon-newline-after": null,
18 | "declaration-block-no-duplicate-properties": true,
19 | "declaration-block-trailing-semicolon": null,
20 | "declaration-no-important": true,
21 | "declaration-property-value-disallowed-list": {
22 | "/^transition/": ["/all/"]
23 | },
24 | "block-closing-brace-newline-after": null,
25 | "max-empty-lines": null,
26 | "selector-list-comma-newline-after": null,
27 | "at-rule-empty-line-before": null,
28 | "at-rule-semicolon-newline-after": null,
29 | "selector-pseudo-element-colon-notation": "single",
30 | "color-no-hex": true,
31 | "function-url-quotes": "always",
32 | "max-nesting-depth": [
33 | 4,
34 | {
35 | "ignoreAtRules": ["each", "media", "supports", "include"],
36 | "severity": "warning"
37 | }
38 | ],
39 | "number-leading-zero": null,
40 | "order/order": [
41 | [
42 | "custom-properties",
43 | "dollar-variables",
44 | {
45 | "type": "at-rule",
46 | "name": "extend"
47 | },
48 | {
49 | "type": "at-rule",
50 | "name": "include"
51 | },
52 | "declarations",
53 | "rules"
54 | ]
55 | ],
56 | "order/properties-alphabetical-order": null,
57 | "property-no-vendor-prefix": [
58 | true,
59 | {
60 | "severity": "warning"
61 | }
62 | ],
63 | "value-no-vendor-prefix": [
64 | true,
65 | {
66 | "severity": "warning"
67 | }
68 | ],
69 | "scss/selector-no-redundant-nesting-selector": null,
70 | "selector-class-pattern": null,
71 | "selector-max-compound-selectors": [
72 | 4,
73 | {
74 | "severity": "warning"
75 | }
76 | ],
77 | "selector-no-qualifying-type": null,
78 | "string-quotes": null,
79 | "max-line-length": null,
80 | "keyframes-name-pattern": null,
81 | "scss/double-slash-comment-empty-line-before": null,
82 | "scss/double-slash-comment-whitespace-inside": null,
83 | "scss/dollar-variable-empty-line-before": null,
84 | "scss/dollar-variable-pattern": "[a-z-]",
85 | "scss/at-import-partial-extension": null,
86 | "declaration-block-no-redundant-longhand-properties": null,
87 | "color-function-notation": null,
88 | "alpha-value-notation": null,
89 | "at-rule-no-unknown": null,
90 | "property-no-unknown": null,
91 | "scss/at-rule-no-unknown": true,
92 | "selector-pseudo-class-no-unknown": [true, { "ignorePseudoClasses": ["selected"] }],
93 | "font-family-no-missing-generic-family-keyword": null,
94 | "scss/no-global-function-names": null,
95 | "unit-no-unknown": [true, { "ignoreUnits": ["dp"] }],
96 | "selector-type-no-unknown": [true, { "ignore": ["custom-elements", "default-namespace"] }],
97 | "value-keyword-case": null
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/assets/scss/main.scss:
--------------------------------------------------------------------------------
1 | @import "styles/base";
2 | @import "styles/global";
3 |
--------------------------------------------------------------------------------
/assets/scss/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mmrecomp-ui-scss",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "start": "npm run watch",
8 | "watch": "sass --no-source-map --no-charset --style=compressed main.scss ..\\recomp.rcss --watch",
9 | "watch:debug": "sass --no-source-map --no-charset main.scss ..\\recomp.rcss --watch",
10 | "build": "sass --no-source-map --no-charset --style=compressed main.scss ..\\recomp.rcss",
11 | "build:debug": "sass --no-source-map --no-charset main.scss ..\\recomp.rcss",
12 | "lint": "stylelint '.\\**\\*.scss'"
13 | },
14 | "author": "",
15 | "license": "ISC",
16 | "devDependencies": {
17 | "postcss-scss": "^4.0.9",
18 | "stylelint": "^15.11.0",
19 | "stylelint-config-property-sort-order-smacss": "^9.1.0",
20 | "stylelint-config-sass-guidelines": "^10.0.0",
21 | "stylelint-config-scss": "^1.0.0-security",
22 | "stylelint-config-standard": "^34.0.0",
23 | "stylelint-config-standard-scss": "^11.1.0",
24 | "stylelint-scss": "^5.3.1"
25 | },
26 | "dependencies": {
27 | "sass": "^1.75.0"
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/assets/scss/styles/base.scss:
--------------------------------------------------------------------------------
1 | @use 'sass:math';
2 | @import "./functions/spacing";
3 | @import "./vars/spacing";
4 | @import "./vars/colors";
5 | @import "./vars/borders";
6 | @import "./vars/gradients";
7 | @import "./vars/transitions";
8 | @import "./vars/animations";
9 | @import "./mixins/typography";
10 | @import "./mixins/transitions";
11 | @import "./mixins/helpers";
12 |
--------------------------------------------------------------------------------
/assets/scss/styles/components/BottomLeft.scss:
--------------------------------------------------------------------------------
1 | @use 'sass:math';
2 |
3 | .bottom-left {
4 | display: flex;
5 | position: absolute;
6 | bottom: space(4);
7 | flex-direction: row;
8 | align-items: flex-start;
9 | justify-content: flex-start;
10 | width: 100%;
11 | max-width: space($base-modal-max-width);
12 | height: auto;
13 | margin: 0 space(4);
14 | }
15 |
--------------------------------------------------------------------------------
/assets/scss/styles/components/Button.scss:
--------------------------------------------------------------------------------
1 | @use 'sass:color';
2 |
3 | @mixin create-button-variation($base-col) {
4 | border-color: rgba($base-col, 0.8);
5 | background-color: rgba($base-col, 0.05);
6 | color: $color-text-dim;
7 |
8 | &:focus, &:hover {
9 | border-color: $base-col;
10 | background-color: rgba($base-col, 0.3);
11 | color: $color-text;
12 | }
13 |
14 | &:disabled,&[disabled] {
15 | color: $color-text-inactive;
16 | }
17 |
18 | &:active {
19 | background-color: rgba($base-col, 0.2);
20 | color: color.scale($color-text, $lightness: 20%);
21 | }
22 | }
23 |
24 | .button {
25 | @extend %label-md;
26 | @extend %nav-all;
27 | @include create-button-variation($color-primary);
28 | @include trans-colors;
29 |
30 | display: block;
31 | width: auto;
32 | height: auto;
33 | // leave 1dp room for border expansion
34 | padding: space(24 - 1);
35 | border-width: $border-width-thickness;
36 |
37 | border-radius: $border-radius-md;
38 |
39 | // Setting it by default for convenience
40 | &--primary {
41 | @include create-button-variation($color-primary);
42 | }
43 |
44 | &--large {
45 | @extend %label-lg;
46 | }
47 |
48 | &--secondary {
49 | @include create-button-variation($color-secondary);
50 | }
51 |
52 | &--tertiary {
53 | @include create-button-variation($color-text);
54 | }
55 |
56 | &--success {
57 | @include create-button-variation($color-success);
58 | }
59 |
60 | &--error {
61 | @include create-button-variation($color-error);
62 | }
63 |
64 | &--warning {
65 | @include create-button-variation($color-warning);
66 | }
67 |
68 | &:not([disabled]) {
69 | @extend %nav-all;
70 | cursor: pointer;
71 | }
72 |
73 | &:disabled,&[disabled] {
74 | opacity: 0.5;
75 | }
76 |
77 | &__label {
78 | width: auto;
79 | height: auto;
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/assets/scss/styles/components/CenteredPage.scss:
--------------------------------------------------------------------------------
1 | @use 'sass:math';
2 |
3 | .centered-page {
4 | display: flex;
5 | // visibility: hidden;
6 | position: absolute;
7 | top: 0;
8 | right: 0;
9 | bottom: 0;
10 | left: 0;
11 | padding: space($page-margin);
12 | background-color: $color-border-soft;
13 | }
14 |
15 | .centered-page__modal {
16 | display: flex;
17 | position: relative;
18 | flex: 1 1 100%;
19 | flex-direction: column;
20 | width: 100%;
21 | max-width: space($base-modal-max-width);
22 | height: 100%;
23 | margin: auto;
24 | border-width: $border-width-thickness;
25 | border-radius: $border-radius-modal;
26 | border-color: $color-border;
27 | background: $color-modal-overlay;
28 |
29 | > .tabs {
30 | display: flex;
31 | position: relative;
32 | flex: 1 1 100%;
33 | flex-direction: column;
34 | width: 100%;
35 | max-width: space($base-modal-max-width);
36 | height: 100%;
37 | margin: auto;
38 | }
39 |
40 | panels {
41 | flex: 1 1 100%;
42 | }
43 | }
44 |
45 | .centered-page__controls {
46 | display: flex;
47 | position: absolute;
48 | bottom: space(24);
49 | flex-direction: row;
50 | align-items: center;
51 | justify-content: center;
52 | width: 100%;
53 | max-width: space($base-modal-max-width);
54 | height: auto;
55 | margin: 0 auto;
56 |
57 | > label {
58 | @extend %label-sm;
59 | display: inline-block;
60 | align-items: center;
61 | justify-content: space-between;
62 | width: auto;
63 | height: space(24);
64 |
65 | &:not(:last-child) {
66 | margin-right: space(40);
67 | }
68 |
69 | > span:first-child {
70 | margin-right: space(4);
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/assets/scss/styles/components/Config.scss:
--------------------------------------------------------------------------------
1 |
2 | .config__icon-buttons {
3 | display: flex;
4 | position: absolute;
5 | top: space(8);
6 | right: space(0);
7 | flex-direction: row;
8 | align-items: center;
9 | justify-content: flex-end;
10 | width: auto;
11 |
12 | .icon-button {
13 | margin: 0 space(8);
14 | }
15 | }
16 |
17 | .config__form {
18 | @include border-top($color-border-soft);
19 | display: flex;
20 | flex: 1 1 100%;
21 | flex-direction: column;
22 | justify-content: space-between;
23 | width: 100%;
24 | height: 100%;
25 | border-bottom-right-radius: $border-radius-modal;
26 | border-bottom-left-radius: $border-radius-modal;
27 | }
28 |
29 | .config__wrapper {
30 | flex: 1 1 100%;
31 | width: auto;
32 | height: auto;
33 | padding: space(16);
34 | border-radius: 0dp;
35 | border-bottom-right-radius: $border-radius-modal;
36 | border-bottom-left-radius: $border-radius-modal;
37 | background-color: $color-bg-shadow;
38 | text-align: left;
39 |
40 | p {
41 | @extend %body;
42 | padding: space(16);
43 | line-height: space(28);
44 | white-space: pre-line;
45 |
46 | b {
47 | color: $color-primary;
48 | }
49 |
50 | i {
51 | color: $color-warning;
52 | font-style: normal;
53 | }
54 | }
55 | }
56 |
57 | .config__hz-wrapper {
58 | display: flex;
59 | flex: 1 1 100%;
60 | flex-direction: row;
61 | width: 100%;
62 | height: 100%;
63 | border-radius: 0dp;
64 | text-align: left;
65 | }
66 |
67 | .config__header, .config__footer {
68 | display: flex;
69 | align-items: center;
70 | justify-content: space-between;
71 | width: 100%;
72 | background-color: $color-bg-shadow;
73 | }
74 |
75 | .config__header {
76 | @include border-bottom($color-border-soft);
77 | padding: space(12) space(20);
78 | }
79 |
80 | .config__footer {
81 | @include border-top($color-border-soft);
82 | padding: space(20) space(20);
83 | border-bottom-right-radius: $border-radius-modal;
84 | border-bottom-left-radius: $border-radius-modal;
85 | }
86 |
87 | .config__header-left {
88 | display: flex;
89 | flex: 1 1 auto;
90 | flex-direction: row;
91 |
92 | > :not(:first-child) {
93 | margin-left: space(8);
94 | }
95 | }
96 |
97 | .config__row {
98 | display: flex;
99 | flex-direction: row;
100 | }
101 |
102 | .config-option {
103 | display: flex;
104 | flex: 1;
105 | flex-direction: column;
106 | align-items: flex-start;
107 | justify-content: flex-start;
108 | margin: space(16) space(0) space(24);
109 |
110 | &:last-child {
111 | margin-top: space(16);
112 | }
113 | }
114 |
115 | .config-option__title {
116 | @extend %label-md;
117 | padding: 0 space(12);
118 | }
119 |
120 | .config-option__list {
121 | display: flex;
122 | flex-direction: row;
123 | align-items: flex-start;
124 | justify-content: flex-start;
125 | width: 100%;
126 | height: auto;
127 | padding: 0;
128 |
129 | input:first-of-type {
130 | nav-left: none;
131 | }
132 |
133 | input:last-of-type {
134 | nav-right: none;
135 | }
136 |
137 | .config-option__tab-label {
138 | @extend %label-sm;
139 | @include trans-colors-opa;
140 | display: block;
141 | position: relative;
142 | height: auto;
143 | margin: space(4) space(12) 0;
144 | padding: space(8) 0;
145 | color: $color-text-inactive;
146 | tab-index: none;
147 |
148 | &:hover {
149 | color: $color-text;
150 | cursor: pointer;
151 | }
152 | }
153 |
154 | input.radio {
155 | @extend %nav-all;
156 | @include trans-colors-opa;
157 | visibility: visible;
158 | width: 0;
159 | height: 0;
160 |
161 | &:not(:disabled) {
162 | &:checked + .config-option__tab-label {
163 | border-bottom: 1dp;
164 | border-color: $color-text;
165 | color: $color-text;
166 |
167 | &:hover {
168 | cursor: default;
169 | }
170 | }
171 |
172 | .rmlui-window:not([mouse-active]) &:focus + .config-option__tab-label {
173 | transition: none;
174 | animation: $focus-anim-border;
175 | border-color: $color-secondary;
176 | color: $color-secondary;
177 | }
178 |
179 | &:focus + .config-option__tab-label,
180 | &:hover + .config-option__tab-label {
181 | color: $color-text;
182 | }
183 | }
184 |
185 | &:disabled + .config-option__tab-label {
186 | opacity: 0.5;
187 |
188 | &:hover {
189 | cursor: default;
190 | }
191 | }
192 | }
193 |
194 | input.range slidertrack {
195 | @include trans-colors;
196 | height: 2dp;
197 | margin-top: space(8);
198 | background-color: $color-border;
199 | }
200 |
201 | input.range sliderbar {
202 | @include trans-colors;
203 | width: space(16);
204 | height: space(16);
205 | margin-top: space(1);
206 | margin-right: space(-8);
207 | margin-left: space(-8);
208 | transition: background-color $transition-quick;
209 | border-radius: 8dp;
210 | background-color: $color-text-dim;
211 |
212 | .rmlui-window:not([mouse-active]) &:focus {
213 | @include border($color-a);
214 | animation: $focus-anim-bg;
215 | }
216 |
217 | &:hover {
218 | background-color: $color-text;
219 | cursor: pointer;
220 | }
221 | }
222 |
223 | input.range sliderbar:active,
224 | input.range slidertrack:active + sliderbar {
225 | background-color: $color-secondary;
226 | }
227 |
228 | input.range sliderarrowdec,
229 | input.range sliderarrowinc {
230 | display: none;
231 | }
232 | }
233 |
234 | .config-option__details {
235 | @extend %label-xs;
236 | height: space(18);
237 | margin: space(14) space(12) 0;
238 | color: $color-primary;
239 | }
240 |
241 | .config-option__range-wrapper {
242 | max-width: space(360);
243 | margin-top: space(4);
244 | }
245 |
246 | .config-option__range-label {
247 | @extend %label-sm;
248 |
249 | display: block;
250 | // flex: 0 0 space(32);
251 | width: space(56);
252 | margin: 0 12dp;
253 | margin-right: space(16);
254 | padding: 0;
255 | color: $color-text;
256 | tab-index: none;
257 | }
258 |
--------------------------------------------------------------------------------
/assets/scss/styles/components/ControlOption.scss:
--------------------------------------------------------------------------------
1 | @use 'sass:color';
2 | @use 'sass:math';
3 |
4 | .control-option {
5 | @include set-color($color-text-dim);
6 | @include trans-colors-svg;
7 | display: flex;
8 | position: relative;
9 | flex-direction: row;
10 | align-items: center;
11 | justify-content: space-between;
12 | width: 100%;
13 | height: auto;
14 | padding: space(4) space(16) space(4) space(20);
15 | border-radius: $border-radius-sm;
16 | background-color: rgba(0, 0, 0, 0);
17 |
18 | &:focus-visible:not(:disabled, [disabled]),
19 | &:hover:not(:disabled, [disabled]) {
20 | @include set-color($color-text);
21 | background-color: $color-bg-overlay;
22 | }
23 |
24 | &:disabled, &[disabled] {
25 | opacity: 0.5;
26 | }
27 |
28 | &--active {
29 | // while actively looking for inputs, set styles to the correct slots
30 | $valid-binding-slots: 0, 1;
31 | @each $slot in $valid-binding-slots {
32 | // global attr -> this active row -> binding slot
33 | [cur-binding-slot="#{$slot}"] & .control-option__binding[bind-slot="#{$slot}"] {
34 | border-color: $color-error;
35 |
36 | .control-option__binding-icon {
37 | opacity: 0;
38 | }
39 |
40 | .control-option__binding-recording {
41 | opacity: 1;
42 | }
43 | }
44 | }
45 | }
46 |
47 | .icon-button {
48 | flex: 1 1 auto;
49 | }
50 | }
51 |
52 | .control-option__label {
53 | @extend %label-md;
54 | flex: 2 1 space(300);
55 | height: auto;
56 | white-space: nowrap;
57 | }
58 |
59 | .control-option__bindings {
60 | display: flex;
61 | position: relative;
62 | flex: 2 1 space(400);
63 | flex-direction: row;
64 | align-items: center;
65 | justify-content: space-between;
66 | width: 100%;
67 | height: space(56);
68 | padding: 0 space(12) 0 space(4);
69 | }
70 |
71 | .control-option__binding {
72 | @include set-color($color-text-dim);
73 | @include trans-colors-border;
74 | display: flex;
75 | position: relative;
76 |
77 | flex: 1 1 100%;
78 | align-items: center;
79 | justify-content: center;
80 | width: 100%;
81 | height: space(56);
82 | margin: 0 space(4);
83 | padding: space(8);
84 | border-width: $border-width-thickness;
85 | border-radius: $border-radius-sm;
86 | border-color: $color-bg-overlay;
87 | background-color: $color-bg-overlay;
88 |
89 | &:focus, &:hover {
90 | @include set-color($color-text);
91 | border-color: $color-text;
92 | background-color: $color-border-soft;
93 | }
94 |
95 | &:active {
96 | @include set-color(color.scale($color-text, $lightness: 20%));
97 | }
98 |
99 | &:disabled, &[disabled] {
100 | @include set-color($color-text-dim);
101 | opacity: 0.5;
102 | }
103 |
104 | &:not([disabled]) {
105 | @extend %nav-all;
106 | cursor: pointer;
107 | }
108 | }
109 |
110 | .control-option__binding-icon {
111 | @include trans-colors-opa;
112 | opacity: 1;
113 | }
114 |
115 | @keyframes control-option__binding-recording-scale {
116 | 0% {
117 | transform: scale(1);
118 | }
119 |
120 | 50% {
121 | transform: scale(0.85);
122 | }
123 |
124 | 100% {
125 | transform: scale(1);
126 | }
127 | }
128 |
129 | .control-option__binding-recording {
130 | @include trans-colors-opa;
131 | display: flex;
132 | position: absolute;
133 | top: 0;
134 | right: 0;
135 | bottom: 0;
136 | left: 0;
137 | align-items: center;
138 | justify-content: center;
139 | opacity: 0;
140 |
141 | .control-option__binding-circle {
142 | $rec-size: 24;
143 |
144 | width: space($rec-size);
145 | height: space($rec-size);
146 | animation: 1.5s sine-in-out infinite control-option__binding-recording-scale;
147 | border-radius: space($rec-size);
148 | background-color: $color-error;
149 | }
150 |
151 | .control-option__binding-edge {
152 | $edge-size: 36;
153 | $h-edge-size: math.div($edge-size, 2);
154 |
155 | position: absolute;
156 |
157 | top: 50%;
158 | left: 50%;
159 | width: space($edge-size);
160 | height: space($edge-size);
161 |
162 | transform: translate(-50%, -50%);
163 |
164 | > svg.control-option__binding-edge-svg {
165 | width: space($edge-size);
166 | height: space($edge-size);
167 | image-color: $color-error;
168 | }
169 | }
170 | }
171 |
--------------------------------------------------------------------------------
/assets/scss/styles/components/IconButton.scss:
--------------------------------------------------------------------------------
1 | @use 'sass:color';
2 |
3 | /*
4 |
7 |
8 |
9 | */
10 | @mixin create-icon-button-variation($base-col) {
11 | border-color: rgba($base-col, 0.8);
12 | background-color: rgba($base-col, 0.05);
13 |
14 | &:focus, &:hover {
15 | border-color: $base-col;
16 | background-color: rgba($base-col, 0.3);
17 | }
18 |
19 | &:active {
20 | background-color: rgba($base-col, 0.2);
21 | }
22 | }
23 |
24 | $icon-button-size: 56 - ($border-width-thickness-num * 2);
25 |
26 | .icon-button {
27 | @include set-color($color-text-dim);
28 | @include trans-colors-border;
29 |
30 | display: flex;
31 | align-items: center;
32 | justify-content: center;
33 | width: space($icon-button-size);
34 | min-width: space($icon-button-size);
35 | max-width: space($icon-button-size);
36 | height: space($icon-button-size);
37 | min-height: space($icon-button-size);
38 | max-height: space($icon-button-size);
39 | border-width: $border-width-thickness;
40 | border-radius: space($icon-button-size * 0.5);
41 | border-color: $color-transparent;
42 | background-color: $color-transparent;
43 |
44 | &:focus, &:hover {
45 | @include set-color($color-text);
46 | background-color: $color-border;
47 | }
48 |
49 | &:active {
50 | @include set-color(color.scale($color-text, $lightness: 20%));
51 | background-color: $color-border-soft;
52 | }
53 |
54 | &:disabled,&[disabled] {
55 | @include set-color($color-text-dim);
56 | opacity: 0.5;
57 | }
58 |
59 | &:not([disabled]) {
60 | @extend %nav-all;
61 | cursor: pointer;
62 | }
63 |
64 | svg {
65 | width: space(32);
66 | height: space(32);
67 | }
68 |
69 | &--primary {
70 | @include create-icon-button-variation($color-primary);
71 | }
72 |
73 | &--secondary {
74 | @include create-icon-button-variation($color-secondary);
75 | }
76 |
77 | &--tertiary {
78 | @include create-icon-button-variation($color-text);
79 | }
80 |
81 | &--success {
82 | @include create-icon-button-variation($color-success);
83 | }
84 |
85 | &--danger {
86 | @include create-icon-button-variation($color-error);
87 | }
88 |
89 | &--warning {
90 | @include create-icon-button-variation($color-warning);
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/assets/scss/styles/components/InputConfig.scss:
--------------------------------------------------------------------------------
1 | @use 'sass:math';
2 |
3 | // Probably will need to adjust for other langs...
4 | $mapping-min-width: 80 * 8;
5 | $visual-max-width: $base-modal-max-width - $mapping-min-width - $scrollbar-width;
6 |
7 | .input-config {
8 | padding: 0;
9 | }
10 |
11 | .input-config__horizontal-split {
12 | display: flex;
13 | position: relative;
14 | flex-direction: row;
15 | height: 100%;
16 | }
17 |
18 | .input-config__mappings {
19 | display: block;
20 | flex: 1 1 auto;
21 | min-width: space($mapping-min-width);
22 | height: 100%;
23 | }
24 |
25 | .input-config__mappings-scroll {
26 | display: block;
27 | width: 100%;
28 | max-height: 100%;
29 | overflow-y: auto;
30 | }
31 |
32 | .input-config__mappings-wrapper {
33 | padding: space(8);
34 | }
35 |
36 | .input-config__visual-wrapper {
37 | display: block;
38 | flex: 1 1 100%;
39 | width: auto;
40 | max-width: space($visual-max-width);
41 | height: auto;
42 | max-height: space(math.div($visual-max-width, 4) * 3);
43 | margin: auto 0;
44 | }
45 |
46 | .input-config__visual-aspect {
47 | position: relative;
48 | width: 100%;
49 | margin: auto 0;
50 | padding-bottom: 75%;
51 | background-color: $color-bg-shadow;
52 | }
53 |
54 | .input-config__visual {
55 | display: flex;
56 | position: absolute;
57 | top: space(16);
58 | right: space(16);
59 | bottom: space(16);
60 | left: space(16);
61 | flex-direction: column;
62 | border-radius: space(108);
63 | background-color: $color-white-a5;
64 | }
65 |
66 | .input-config__visual-half {
67 | display: flex;
68 | position: relative;
69 | flex: 1 1 100%;
70 | flex-direction: row;
71 | padding: 6%;
72 |
73 | &--bottom {
74 | align-items: flex-end;
75 | justify-content: space-between;
76 | }
77 | }
78 |
79 | .input-config__visual-quarter-left {
80 | display: flex;
81 | flex: 1 1 50%;
82 | align-items: flex-start;
83 | justify-content: flex-start;
84 | width: auto;
85 | }
86 |
87 | .input-config__visual-quarter-right {
88 | display: flex;
89 | flex: 1 1 100%;
90 | align-items: flex-start;
91 | justify-content: flex-end;
92 | }
93 |
94 | .input-config__visual-stick-wrapper {
95 | display: flex;
96 | position: absolute;
97 | top: 0;
98 | right: 0;
99 | bottom: 0;
100 | left: 0;
101 | align-items: center;
102 | justify-content: center;
103 | }
104 |
105 | .input-viz {
106 | @include trans-colors-opa;
107 | display: flex;
108 | position: relative;
109 | align-items: center;
110 | justify-content: center;
111 |
112 | > svg:not(.input-viz__dpad-arrow) {
113 | position: absolute;
114 | top: 0;
115 | right: 0;
116 | bottom: 0;
117 | left: 0;
118 | }
119 |
120 | &__mappings div {
121 | @extend %prompt-font-sm;
122 | }
123 | }
124 |
125 | $all-inputs: A,
126 | B,
127 | Z,
128 | START,
129 | DPAD_UP,
130 | DPAD_DOWN,
131 | DPAD_LEFT,
132 | DPAD_RIGHT,
133 | L,
134 | R,
135 | C_UP,
136 | C_DOWN,
137 | C_LEFT,
138 | C_RIGHT,
139 | X_AXIS_NEG,
140 | X_AXIS_POS,
141 | Y_AXIS_NEG,
142 | Y_AXIS_POS;
143 |
144 | // Show default state while no inputs are active
145 | [cur-input="NONE"] .input-viz[visual-input] {
146 | opacity: 1;
147 | }
148 |
149 | @each $inp in $all-inputs {
150 | .input-viz[visual-input~="#{$inp}"] {
151 | opacity: 0.25;
152 |
153 | [cur-input="#{$inp}"] & {
154 | opacity: 1.0;
155 | }
156 | }
157 | }
158 |
159 | @mixin set-sizes($sz) {
160 | width: space($sz);
161 | height: space($sz);
162 |
163 | > svg {
164 | width: space($sz);
165 | height: space($sz);
166 | }
167 | }
168 |
169 | .input-viz__button {
170 | @include set-color($color-text);
171 |
172 | &--sm {
173 | @include set-sizes(64);
174 | }
175 |
176 | &--md {
177 | @include set-sizes(76);
178 | }
179 |
180 | &--lg {
181 | @include set-sizes(84);
182 | }
183 |
184 | &--C {
185 | @include set-svgs-color($color-warning);
186 | }
187 |
188 | &--A {
189 | @include set-svgs-color($color-a);
190 | margin-top: auto;
191 | }
192 |
193 | &--B {
194 | @include set-svgs-color($color-success);
195 | }
196 |
197 | &--Start {
198 | @include set-svgs-color($color-error);
199 | }
200 | }
201 |
202 | .input-viz__Z {
203 | @include set-svgs-color($color-warning);
204 | @include set-sizes(136);
205 | }
206 |
207 | $dpad-size: 192;
208 |
209 | .input-viz.input-viz__dpad {
210 | @include set-svgs-color($color-text);
211 | @include set-sizes($dpad-size);
212 | position: relative;
213 | }
214 |
215 | $stick-size: 200;
216 |
217 | .input-config__visual-stick {
218 | display: flex;
219 | position: relative;
220 | align-items: center;
221 | justify-content: center;
222 | width: space($stick-size);
223 | height: space($stick-size);
224 | border-radius: space(math.div($stick-size, 2));
225 | background-color: $color-white-a5;
226 | }
227 |
228 | .input-viz__dpad-split,
229 | .input-viz__stick-split {
230 | @include inset-block(0);
231 | display: flex;
232 | width: 100%;
233 | height: 100%;
234 |
235 | &--vertical {
236 | flex-direction: column;
237 | align-items: center;
238 | justify-content: space-between;
239 | }
240 |
241 | &--horizontal {
242 | flex-direction: row;
243 | align-items: center;
244 | justify-content: space-between;
245 | }
246 |
247 | > div {
248 | display: flex;
249 | flex: 1 1 100%;
250 | flex-direction: row;
251 | align-items: center;
252 | justify-content: center;
253 | }
254 | }
255 |
256 | .input-viz__dpad-split > div {
257 | width: space(math.div($dpad-size, 3));
258 | height: space(math.div($dpad-size, 3));
259 | }
260 |
261 | .input-viz__stick-split > div {
262 | width: space(math.div($stick-size, 3));
263 | height: space(math.div($stick-size, 3));
264 | }
265 |
266 | .input-viz__dpad-arrow {
267 | $edge-dist: space(4);
268 | position: absolute;
269 | width: space(60);
270 | height: space(60);
271 |
272 | &--up {
273 | top: $edge-dist;
274 | margin: 0 auto;
275 | }
276 |
277 | &--down {
278 | bottom: $edge-dist;
279 | margin: 0 auto;
280 | transform: rotate(180deg);
281 | }
282 |
283 | &--left {
284 | left: $edge-dist;
285 | margin: auto 0;
286 | transform: rotate(-90deg);
287 | }
288 |
289 | &--right {
290 | right: $edge-dist;
291 | margin: auto 0;
292 | transform: rotate(90deg);
293 | }
294 | }
295 |
296 | .input-viz__R {
297 | @include set-svgs-color($color-white);
298 | @include set-sizes(96);
299 | }
300 |
301 | .input-viz__L {
302 | @include set-svgs-color($color-secondary);
303 | @include set-sizes(136);
304 | }
305 |
306 | .input-config__c-buttons {
307 | position: relative;
308 | width: space(76 + 76 + 56);
309 | height: space(76 + 56);
310 |
311 | &-lr, &-du {
312 | display: flex;
313 | position: absolute;
314 | top: 0;
315 | right: 0;
316 | bottom: 0;
317 | left: 0;
318 | }
319 |
320 | &-lr {
321 | flex-direction: row;
322 | align-items: flex-start;
323 | justify-content: space-between;
324 | }
325 |
326 | &-du {
327 | flex-direction: column-reverse;
328 | align-items: center;
329 | justify-content: space-between;
330 | }
331 |
332 | .input-viz {
333 | &[visual-input="C_UP"] {
334 | margin-top: space(-32);
335 | }
336 | }
337 | }
338 |
339 | .input-config__main-buttons {
340 | display: flex;
341 | position: relative;
342 | flex-direction: row;
343 | justify-content: space-between;
344 | width: space(268);
345 | height: space(128);
346 | margin-right: space(10);
347 | }
348 |
--------------------------------------------------------------------------------
/assets/scss/styles/components/Launcher.scss:
--------------------------------------------------------------------------------
1 |
2 | // TODO: Affect all elements with launcher fade-in
3 | // @keyframes fade-launcher-in {
4 | // 0% {
5 | // opacity: 0;
6 | // }
7 | // to {
8 | // opacity: 1;
9 | // }
10 | // }
11 |
12 | .launcher {
13 | display: block;
14 | position: relative;
15 | flex-direction: row;
16 | justify-content: space-between;
17 | width: 100%;
18 | height: 100%;
19 | background-color: $color-background-1;
20 | }
21 |
22 | .launcher__vertical-split {
23 | display: flex;
24 | position: absolute;
25 | top: 0;
26 | right: 50%;
27 | bottom: 0;
28 | left: 0;
29 | flex-direction: column;
30 | align-items: flex-start;
31 | justify-content: space-between;
32 |
33 | &--right {
34 | right: 0;
35 | left: 50%;
36 | align-items: flex-end;
37 | }
38 | }
39 |
40 |
41 | @keyframes slide-mm-bg-over {
42 | 0% {
43 | transform: translateX(space(100));
44 | }
45 |
46 | 100% {
47 | transform: translateX(space(0));
48 | }
49 | }
50 |
51 | .launcher__background-wrapper {
52 | display: flex;
53 | position: absolute;
54 | top: -55vw;
55 | right: -100%;
56 | bottom: -50vw;
57 | left: -70vw;
58 | align-items: center;
59 | justify-content: flex-start;
60 | transform: translateX(space(0));
61 | animation: 25s cubic-out 1 slide-mm-bg-over;
62 | }
63 |
64 | @keyframes fade-mm-in {
65 | 0% {
66 | opacity: 0;
67 | }
68 |
69 | 100% {
70 | opacity: 0.1;
71 | }
72 | }
73 |
74 | .launcher__background-mm {
75 | position: absolute;
76 | top: 0;
77 | bottom: 0;
78 | left: 0;
79 | width: auto;
80 | height: 100%;
81 | animation: 2.5s cubic-in-out 1 fade-mm-in;
82 | opacity: 0.1;
83 | }
84 |
85 | .launcher__title-quadrant {
86 | flex: 1 1 auto;
87 | width: auto;
88 | height: auto;
89 | padding-top: space(96);
90 | padding-left: space(96);
91 |
92 | &--right {
93 | padding-right: space(96);
94 | padding-left: 0;
95 | }
96 | }
97 |
98 | .launcher__content-quadrant {
99 | display: flex;
100 | position: relative;
101 | flex: 1 1 100%;
102 | flex-direction: column;
103 | align-items: flex-start;
104 | justify-content: flex-end;
105 | width: 100%;
106 | height: auto;
107 | padding: space(32);
108 | }
109 |
--------------------------------------------------------------------------------
/assets/scss/styles/components/MenuListItem.scss:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | Example layout:
4 |
8 | - Variants:
9 | .menu-list-item--right (align to right side)
10 | - Optional:
11 | - Coming Soon™
12 |
13 | */
14 |
15 | .menu-list-item {
16 | @include set-color($color-text-dim);
17 | display: flex;
18 | flex-direction: row;
19 | align-items: center;
20 | width: 100%;
21 | height: auto;
22 | padding: space(16);
23 | border-radius: $border-radius-sm;
24 | background-color: rgba(0, 0, 0, 0);
25 | cursor: pointer;
26 |
27 | &--right {
28 | flex-direction: row-reverse;
29 | align-content: flex-end;
30 |
31 | .menu-list-item__bullet {
32 | margin-left: space(12);
33 | opacity: 1;
34 | }
35 |
36 | &.menu-list-item:focus:not(:disabled, [disabled]),
37 | &.menu-list-item:hover:not(:disabled, [disabled]) {
38 | decorator: $primary-rl-fade;
39 | }
40 | }
41 |
42 | &:focus:not(:disabled, [disabled]),
43 | &:hover:not(:disabled, [disabled]) {
44 | @include set-color($color-primary);
45 | decorator: $primary-lr-fade;
46 |
47 | .menu-list-item__bullet {
48 | opacity: 1;
49 | }
50 | }
51 |
52 | &:not(:disabled, [disabled]) {
53 | @extend %nav-all;
54 | }
55 |
56 | &:disabled, &[disabled] {
57 | opacity: 0.5;
58 | tab-index: none;
59 | cursor: default;
60 | }
61 |
62 | }
63 |
64 | .menu-list-item__label {
65 | @extend %label-lg;
66 | }
67 |
68 | .menu-list-item__bullet {
69 | margin-right: space(12);
70 | opacity: 0;
71 | }
72 |
--------------------------------------------------------------------------------
/assets/scss/styles/components/Prompt.scss:
--------------------------------------------------------------------------------
1 | @use 'sass:math';
2 |
3 | $prompt-space: 24;
4 |
5 | .prompt {
6 | &__overlay {
7 | background-color: $color-bg-overlay;
8 | pointer-events: auto;
9 | }
10 |
11 | &__overlay,
12 | &__content-wrapper {
13 | position: absolute;
14 | top: 0;
15 | right: 0;
16 | bottom: 0;
17 | left: 0;
18 | }
19 |
20 | &__content-wrapper {
21 | display: flex;
22 | position: absolute;
23 | top: 0;
24 | right: 0;
25 | bottom: 0;
26 | left: 0;
27 | align-items: center;
28 | justify-content: center;
29 | }
30 |
31 | &__content {
32 | display: flex;
33 | position: relative;
34 | flex: 1 1 100%;
35 | flex-direction: column;
36 | width: 100%;
37 | max-width: space(700);
38 | height: auto;
39 | margin: auto;
40 | border-width: $border-width-thickness;
41 | border-radius: $border-radius-modal;
42 | border-color: $color-border;
43 | background: $color-modal-overlay;
44 |
45 | h3, p {
46 | margin: space($prompt-space);
47 | }
48 |
49 | p {
50 | margin-top: 0;
51 | }
52 | }
53 |
54 | &__controls {
55 | display: flex;
56 | flex-direction: row;
57 | justify-content: center;
58 | padding: space($prompt-space) space(math.div($prompt-space, 2));
59 | border-top-width: $border-width-thickness;
60 | border-top-color: $color-border-soft;
61 |
62 | .button {
63 | min-width: space(math.div(700, 3));
64 | margin: 0 space(math.div($prompt-space, 2));
65 | text-align: center;
66 | nav-up: none;
67 | nav-down: none;
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/assets/scss/styles/components/SubtitleTitle.scss:
--------------------------------------------------------------------------------
1 | /*
2 | Example layout:
3 |
4 |
5 | Zelda 64: Recompiled
6 | Ocarina of Time
7 | Coming Soon™
8 |
9 | - Variants:
10 | .subtitle-title--right (align to right side)
11 | - Optional:
12 | - Coming Soon™
13 |
14 | */
15 |
16 | .subtitle-title {
17 | display: block;
18 | position: relative;
19 | flex-direction: column;
20 | align-content: flex-start;
21 | align-items: flex-start;
22 | width: auto;
23 | height: auto;
24 | padding: 0;
25 | background-color: rgba(0, 0, 0, 0);
26 | color: $color-text-dim;
27 | text-align: left;
28 | cursor: pointer;
29 |
30 | &--right {
31 | align-content: flex-end;
32 | }
33 |
34 | &--right, &--right > * {
35 | text-align: right;
36 | }
37 |
38 | &[selected] {
39 | color: $color-text;
40 | cursor: default;
41 | }
42 |
43 | &:focus:not(:disabled, [disabled]),
44 | &:hover:not(:disabled, [disabled], [selected]) {
45 | color: $color-primary;
46 | }
47 |
48 | &:not(:disabled, [disabled]) {
49 | @extend %nav-all;
50 | }
51 |
52 | &:disabled, &[disabled] {
53 | opacity: 0.5;
54 | cursor: default;
55 | tab-index: none;
56 | }
57 |
58 | h3 {
59 | margin-bottom: space(6);
60 | }
61 |
62 | h1 {
63 | margin-top: space(6);
64 | }
65 |
66 | &__disclaimer {
67 | @extend %label-sm;
68 |
69 | margin-top: space(16);
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/assets/scss/styles/components/Tabs.scss:
--------------------------------------------------------------------------------
1 | /*
2 | Example:
3 |
4 | Graphics
5 |
6 |
7 | */
8 |
9 | .tabs tabs {
10 | display: flex;
11 | flex-direction: row;
12 | align-items: center;
13 | justify-content: flex-start;
14 | }
15 |
16 | .tab {
17 | @extend %nav-all;
18 | @extend %header-3;
19 | display: block;
20 | position: relative;
21 | margin: 0;
22 | padding: space(20) space(24);
23 | transition: color $transition-quick;
24 | opacity: 0.9;
25 | background-color: rgba(0,0,0,0);
26 | color: $color-text-inactive;
27 |
28 | &:selected {
29 | color: $color-text;
30 |
31 | .tab__indicator {
32 | background-color: $color-border-solid;
33 | }
34 |
35 | &:hover {
36 | cursor: default;
37 | }
38 | }
39 |
40 | .rmlui-window:not([mouse-active]) &:focus {
41 | transition: none;
42 | animation: $focus-anim-border;
43 |
44 | &:selected .tab__indicator {
45 | animation: $focus-anim-bg;
46 | }
47 | }
48 |
49 | &:focus, &:hover {
50 | opacity: 1;
51 | color: $color-text;
52 | cursor: pointer;
53 | }
54 | }
55 |
56 | .tab__indicator {
57 | position: absolute;
58 | right: 0;
59 | bottom: 2dp;
60 | left: 0;
61 | height: 2dp;
62 | background-color: rgba(0, 0, 0, 0);
63 | }
64 |
--------------------------------------------------------------------------------
/assets/scss/styles/components/Toggle.scss:
--------------------------------------------------------------------------------
1 | @use "sass:math";
2 |
3 | $toggle-width: 162;
4 | $toggle-height: 72;
5 |
6 | $toggle-floater-width: 80;
7 | $toggle-floater-height: 64;
8 | $toggle-floater-margin: 4;
9 | $toggle-checked-left-offset: $toggle-width - $toggle-floater-margin - $toggle-floater-width;
10 |
11 | .toggle {
12 | @extend %nav-all;
13 | @include trans-colors-opa;
14 | display: flex;
15 | position: relative;
16 | flex-direction: row;
17 | align-items: center;
18 | justify-content: space-between;
19 | width: space($toggle-width);
20 | height: space($toggle-height);
21 | border-radius: space(math.div($toggle-height, 2));
22 | opacity: 0.9;
23 | background: $color-transparent;
24 | cursor: pointer;
25 |
26 | &:hover, &:focus-visible, &:focus {
27 | opacity: 1;
28 | background-color: $color-secondary-a30;
29 | }
30 |
31 | &:active {
32 | opacity: 1;
33 | background-color: $color-secondary-a5;
34 | }
35 |
36 | .toggle__border {
37 | @include inner-border-block($color-secondary-l);
38 | border-radius: space(math.div($toggle-height, 2));
39 | }
40 |
41 | .toggle__floater {
42 | position: absolute;
43 | top: 50%;
44 | left: space($toggle-floater-margin);
45 | width: space($toggle-floater-width);
46 | height: space($toggle-floater-height);
47 | transform: translateY(-50%);
48 | border-radius: space(math.div($toggle-floater-height, 2));
49 | background: $color-secondary-d;
50 | }
51 |
52 | &--checked {
53 | .toggle__floater {
54 | left: space($toggle-checked-left-offset);
55 | }
56 |
57 | .toggle__icon {
58 | &.toggle__icon--left {
59 | opacity: 0.9;
60 | color: $color-secondary-l;
61 | }
62 |
63 | &.toggle__icon--right {
64 | opacity: 1.0;
65 | color: $color-text;
66 | }
67 | }
68 | }
69 | }
70 |
71 | .toggle__icons {
72 | display: flex;
73 | position: absolute;
74 | top: 50%;
75 | right: space(16);
76 | left: space(16);
77 | align-items: center;
78 | justify-content: space-between;
79 | height: space(56);
80 | transform: translateY(-50%);
81 | }
82 |
83 | .toggle__icon {
84 | @extend %prompt-font-lg;
85 | @include trans-colors;
86 | display: flex;
87 | align-items: center;
88 | justify-content: center;
89 | width: space(56);
90 | height: space(56);
91 | color: $color-text;
92 |
93 | &--right {
94 | opacity: 1;
95 | color: $color-secondary-l;
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/assets/scss/styles/components/_components.scss:
--------------------------------------------------------------------------------
1 | @import "./CenteredPage";
2 | @import "./ControlOption";
3 | @import "./Tabs";
4 | @import "./Config";
5 | @import "./InputConfig";
6 | @import "./Button";
7 | @import "./IconButton";
8 | @import "./Launcher";
9 | @import "./MenuListItem";
10 | @import "./SubtitleTitle";
11 | @import "./Toggle";
12 | @import "./BottomLeft";
13 | @import "./Prompt";
14 |
--------------------------------------------------------------------------------
/assets/scss/styles/functions/_spacing.scss:
--------------------------------------------------------------------------------
1 |
2 | @function space($amt) {
3 | @return #{$amt}dp;
4 | }
5 |
--------------------------------------------------------------------------------
/assets/scss/styles/global.scss:
--------------------------------------------------------------------------------
1 | @import "./base";
2 | @import "./globals/old";
3 | @import "./globals/scrollbars";
4 | @import "./components/components";
5 | @import "./pages/pages";
6 |
7 | $font-size: 20dp;
8 |
9 | body
10 | {
11 | @extend %body;
12 | box-sizing: border-box;
13 | color: $color-text;
14 | font-family: $font-stack;
15 | }
16 |
17 | .rmlui-window {
18 | opacity: 1;
19 |
20 | &--hidden {
21 | opacity: 0;
22 | }
23 |
24 | &:not([mouse-active]) {
25 | pointer-events: none;
26 | }
27 | }
28 |
29 | .nav-vert {
30 | @extend %nav-vert;
31 | }
32 |
33 | .nav-horiz {
34 | @extend %nav-horiz;
35 | }
36 |
37 | .nav-dir {
38 | @extend %nav-dir;
39 | }
40 |
41 | .nav-foc {
42 | @extend %nav-foc;
43 | }
44 |
45 | .nav-all {
46 | @extend %nav-all;
47 | }
48 |
49 | *, *:before, *:after {
50 | box-sizing: border-box;
51 | }
52 |
53 | h1 {
54 | @extend %header-1;
55 | }
56 |
57 | h2 {
58 | @extend %header-2;
59 | }
60 |
61 | h3 {
62 | @extend %header-3;
63 | }
64 |
65 | .label-lg {
66 | @extend %label-lg;
67 | }
68 |
69 | .label-md {
70 | @extend %label-md;
71 | }
72 |
73 | .label-sm {
74 | @extend %label-sm;
75 | }
76 |
77 | .prompt-font {
78 | @extend %prompt-font;
79 | }
80 |
81 | .prompt-font-sm {
82 | @extend %prompt-font-sm;
83 | }
84 |
85 | button {
86 | background-color: $color-primary-d;
87 | }
88 |
89 | @keyframes blue-pulse {
90 | 0% {
91 | color: $color-secondary;
92 | }
93 |
94 | 50% {
95 | color: $color-secondary-l;
96 | }
97 |
98 | 100% {
99 | color: $color-secondary;
100 | }
101 | }
102 |
103 | @keyframes blue-pulse-with-border {
104 | 0% {
105 | border-color: $color-secondary;
106 | color: $color-secondary;
107 | }
108 |
109 | 50% {
110 | border-color: $color-secondary-l;
111 | color: $color-secondary-l;
112 | }
113 |
114 | 100% {
115 | border-color: $color-secondary;
116 | color: $color-secondary;
117 | }
118 | }
119 |
120 | @keyframes blue-pulse-background {
121 | 0% {
122 | background-color: $color-secondary;
123 | }
124 |
125 | 50% {
126 | background-color: $color-secondary-l;
127 | }
128 |
129 | 100% {
130 | background-color: $color-secondary;
131 | }
132 | }
133 |
--------------------------------------------------------------------------------
/assets/scss/styles/globals/_old.scss:
--------------------------------------------------------------------------------
1 | /* stylelint-disable color-no-hex */
2 | /* stylelint-disable selector-max-id */
3 |
4 | * {
5 | box-sizing:border-box;
6 | }
7 |
8 | hr {
9 | display:block;
10 | padding:1.5dp;
11 | background: $color-background-1;
12 | }
13 |
14 | body {
15 | color: #fff;
16 | font-family: chiaro;
17 | font-size: 20dp;
18 | font-style: normal;
19 | font-weight: normal
20 | }
21 |
22 | /* div {
23 | focus:none;
24 | tab-index:none;
25 | } */
26 |
27 | div#window {
28 | position: relative;
29 | box-sizing: border-box;
30 | width: 100%;
31 | height: 100%;
32 | border-color: $color-border;
33 | background-color: $color-background-2;
34 | }
35 |
36 | div#content {
37 | z-index: 2;
38 | width: auto;
39 | height: 100%;
40 | overflow: hidden auto;
41 | text-align: center
42 | }
43 |
44 | p {
45 | text-align: left;
46 | }
47 |
48 | input.submit {
49 | margin-left: 0
50 | }
51 |
52 |
53 | input.text,
54 | input.password {
55 | box-sizing: border-box;
56 | height: 31dp;
57 | padding: 11dp 10dp 0;
58 | text-align: left;
59 | cursor: text
60 | }
61 |
62 | textarea {
63 | padding: 14dp 12dp 10dp;
64 | text-align: left;
65 | cursor: text
66 | }
67 |
68 | input.text,
69 | input.password,
70 | select,
71 | textarea {
72 | /* color: #333; */
73 |
74 | /* font-size: 13dp */
75 | height: auto;
76 | }
77 |
78 | table input.text {
79 | box-sizing: border-box;
80 | width: 100%;
81 | height: auto;
82 |
83 | /* height: 18dp; */
84 | margin: 0;
85 | border-width: $border-width-thickness;
86 | border-color: #000;
87 | background-color: #fff;
88 | font-size: 15dp;
89 |
90 | /* padding: 0 5dp; */
91 | line-height: 1;
92 | decorator: none;
93 |
94 | /* vertical-align: center; */
95 | }
96 |
97 | select {
98 | // display: inline-block;
99 | // /* width: 175dp; */
100 | // /* height: 37dp; */
101 | // /* height: auto; */
102 | // text-align: left;
103 | // box-sizing:border-box;
104 | // /* padding: 4dp; */
105 | // vertical-align: center;
106 | // padding: 4dp;
107 | // border-radius: 5dp;
108 | // background-color: rgb(120, 120, 120);
109 | // width: 100%;
110 | }
111 | // select {
112 | // @extend %body;
113 | // display: flex;
114 | // align-items: center;
115 | // justify-content: flex-start;
116 | // box-sizing: border-box;
117 | // padding: space(16);
118 | // flex: 1 1 100%;
119 | // // width: auto;
120 | // height: space(1000);
121 | // border-radius: $border-radius-lg;
122 | // background-color: $color-white-a20;
123 | // }
124 |
125 | // select selectvalue {
126 | // height: auto;
127 | // /* padding: 4dp; */
128 | // /* margin-right: 30dp; */
129 | // /* height: 25dp; */
130 | // /* padding: 4dp; */
131 | // /* decorator: image(selectvalue) */
132 | // }
133 |
134 | // select:hover selectvalue {
135 | // /* margin-right: 30dp; */
136 | // /* height: 25dp; */
137 | // /* padding: 4dp; */
138 | // background-color: rgb(150, 150, 150);
139 | // /* decorator: image(selectvalue) */
140 | // }
141 |
142 | // select selectarrow {
143 | // /* width: 30dp; */
144 | // /* height: 37dp; */
145 | // /* decorator: image(selectarrow) */
146 | // /* background-color: black; */
147 | // /* appearance: none; */
148 | // }
149 |
150 | // select:hover selectarrow {
151 | // /* decorator: image(selectarrow-hover) */
152 | // }
153 |
154 | // select:active selectarrow,
155 | // select selectarrow:checked {
156 | // /* decorator: image(selectarrow-active) */
157 | // }
158 |
159 | // select selectbox {
160 | // /* margin-left: 1dp; */
161 | // /* margin-top: -7dp; */
162 | // /* margin-bottom: -10dp; */
163 | // /* width: 162dp; */
164 | // /* padding: 1dp 4dp 4dp 4dp */
165 | // }
166 |
167 | // select selectbox,
168 | // tbody {
169 | // background-color: rgb(120,120,120);
170 | // /* decorator: tiled-box(selectbox-tl, selectbox-t, selectbox-tr, selectbox-l, selectbox-c, auto, selectbox-bl, selectbox-b, selectbox-br) */
171 | // }
172 |
173 | // select selectbox option {
174 | // width: auto;
175 | // background-color: rgb(120, 120, 120)
176 | // }
177 |
178 | // select selectbox option:nth-child(even),
179 | // tr:nth-child(even) {
180 | // background-color: rgb(100, 100, 100)
181 | // }
182 |
183 | // select selectbox option:checked {
184 | // font-weight:bold;
185 | // color:rgb(255,255,255);
186 | // }
187 |
188 | // select selectbox option:hover {
189 | // background: rgb(150,150,150)
190 | // }
191 |
192 | input.radio,
193 | input.checkbox {
194 | flex: 0;
195 | width:0dp;
196 | nav-up:auto;
197 | nav-right:auto;
198 | nav-down:auto;
199 | nav-left:auto;
200 | tab-index:auto;
201 | focus:auto;
202 | }
203 |
--------------------------------------------------------------------------------
/assets/scss/styles/globals/_scrollbars.scss:
--------------------------------------------------------------------------------
1 | @use 'sass:math';
2 |
3 | $scrollbar-width: 12;
4 |
5 | @mixin _set-scroll-size($size-key) {
6 | #{$size-key}: space($scrollbar-width);
7 |
8 | slidertrack {
9 | #{$size-key}: space($scrollbar-width);
10 | }
11 |
12 | sliderbar {
13 | #{$size-key}: space($scrollbar-width);
14 | }
15 | }
16 |
17 | scrollbarvertical,scrollbarhorizontal {
18 | margin: 0;
19 | border: 0;
20 |
21 | slidertrack {
22 | background: $color-primary-l;
23 | opacity: 0.05;
24 | }
25 |
26 | sliderbar {
27 | border-radius: space(math.div($scrollbar-width, 2) - 1);
28 | background: $color-primary-l;
29 | opacity: 0.1;
30 |
31 | &:hover:not(:active) {
32 | opacity: 0.2;
33 | }
34 |
35 | &:active {
36 | opacity: 0.3;
37 | }
38 | }
39 |
40 | sliderarrowdec, sliderarrowinc {
41 | width: 0;
42 | height: 0;
43 | }
44 | }
45 |
46 | scrollbarvertical {
47 | @include _set-scroll-size(width);
48 | }
49 |
50 | scrollbarhorizontal {
51 | @include _set-scroll-size(height);
52 | }
53 |
--------------------------------------------------------------------------------
/assets/scss/styles/mixins/_helpers.scss:
--------------------------------------------------------------------------------
1 |
2 | %nav-vert {
3 | nav-up: auto;
4 | nav-down: auto;
5 | }
6 |
7 | %nav-horiz {
8 | nav-right: auto;
9 | nav-left: auto;
10 | }
11 |
12 | %nav-dir {
13 | @extend %nav-vert;
14 | @extend %nav-horiz;
15 | }
16 |
17 | %nav-foc {
18 | focus: auto;
19 | tab-index: auto;
20 | }
21 |
22 | %nav-all {
23 | @extend %nav-dir;
24 | @extend %nav-foc;
25 | }
26 |
27 | @mixin set-svgs-color($col) {
28 | svg {
29 | image-color: $col;
30 | }
31 | }
32 |
33 | /*
34 | @include set-color(COLOR);
35 | */
36 | @mixin set-color($col) {
37 | @include set-svgs-color($col);
38 | color: $col;
39 | }
40 |
--------------------------------------------------------------------------------
/assets/scss/styles/mixins/_transitions.scss:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | @include trans-colors;
4 | */
5 | @mixin trans-colors {
6 | transition: color $transition-quick, background-color $transition-quick;
7 | }
8 |
9 | /*
10 | @include trans-colors-opa;
11 | */
12 | @mixin trans-colors-opa {
13 | transition: color $transition-quick, background-color $transition-quick, opacity $transition-quick;
14 | }
15 |
16 | /*
17 | @include trans-colors-svg;
18 | */
19 | @mixin trans-colors-svg {
20 | transition: color $transition-quick, background-color $transition-quick, opacity $transition-quick;
21 |
22 | svg {
23 | transition: image-color $transition-quick, background-color $transition-quick;
24 | }
25 | }
26 |
27 | /*
28 | @include trans-colors-border;
29 | */
30 | @mixin trans-colors-border {
31 | transition: color $transition-quick, background-color $transition-quick, opacity $transition-quick, border-color $transition-quick;
32 |
33 | svg {
34 | transition: image-color $transition-quick, background-color $transition-quick;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/assets/scss/styles/mixins/_typography.scss:
--------------------------------------------------------------------------------
1 |
2 | $font-stack: chiaro;
3 |
4 | @mixin set-font-sizing($sz, $spacing) {
5 | // font-family: $font-stack;
6 | $sz-add: $sz + 4;
7 | font-size: space($sz-add);
8 | letter-spacing: space($sz-add * $spacing);
9 | line-height: space($sz-add);
10 | }
11 |
12 | %header-1 {
13 | @include set-font-sizing(64, 0.07);
14 | font-style: normal;
15 | font-weight: 700;
16 | }
17 |
18 | %header-2 {
19 | @include set-font-sizing(48, 0.07);
20 | font-style: normal;
21 | font-weight: 700;
22 | }
23 |
24 | %header-3 {
25 | @include set-font-sizing(32, 0.07);
26 | font-style: normal;
27 | font-weight: 700;
28 | }
29 |
30 | %label-lg {
31 | @include set-font-sizing(32, 0.11);
32 | font-style: normal;
33 | font-weight: 700;
34 | }
35 |
36 | %label-md {
37 | @include set-font-sizing(24, 0.11);
38 | font-style: normal;
39 | font-weight: 700;
40 | }
41 |
42 | %label-sm {
43 | @include set-font-sizing(16, 0.14);
44 | font-style: normal;
45 | font-weight: 700;
46 | text-transform: uppercase;
47 | }
48 |
49 | %label-xs {
50 | @include set-font-sizing(14, 0.14);
51 | font-style: normal;
52 | font-weight: 400;
53 | }
54 |
55 | %body {
56 | @include set-font-sizing(16, 0.0);
57 | font-style: normal;
58 | font-weight: 400;
59 | }
60 |
61 | %prompt-font-lg {
62 | font-family: promptfont;
63 | font-size: space(56);
64 | font-style: normal;
65 | font-weight: 400;
66 | line-height: space(56);
67 | }
68 |
69 | %prompt-font {
70 | font-family: promptfont;
71 | font-size: space(40);
72 | font-style: normal;
73 | font-weight: 400;
74 | line-height: space(40);
75 | }
76 |
77 | %prompt-font-sm {
78 | font-family: promptfont;
79 | font-size: space(32);
80 | font-style: normal;
81 | font-weight: 400;
82 | line-height: space(32);
83 | }
84 |
--------------------------------------------------------------------------------
/assets/scss/styles/pages/_pages.scss:
--------------------------------------------------------------------------------
1 | @import "./config/config";
2 |
--------------------------------------------------------------------------------
/assets/scss/styles/pages/config/_config.scss:
--------------------------------------------------------------------------------
1 | @import "./debug";
2 |
--------------------------------------------------------------------------------
/assets/scss/styles/pages/config/debug.scss:
--------------------------------------------------------------------------------
1 |
2 | .config-debug {
3 | display: block;
4 | position: relative;
5 | width: 100%;
6 | max-height: 100%;
7 | padding: space(8);
8 | }
9 |
10 | .config-debug__scroll {
11 | display: block;
12 | position: relative;
13 | width: 100%;
14 | max-height: 100%;
15 | overflow-y: auto;
16 | }
17 |
18 | .config-debug-option {
19 | @include set-color($color-text-dim);
20 | @include trans-colors-svg;
21 | @include border-bottom($color-border-soft);
22 | display: block;
23 | position: relative;
24 | flex-direction: column;
25 | width: 100%;
26 | height: auto;
27 | padding: space(12) space(4);
28 | background-color: rgba(0, 0, 0, 0);
29 |
30 | &:focus:not(:disabled, [disabled]),
31 | &:focus-visible:not(:disabled, [disabled]),
32 | &:hover:not(:disabled, [disabled]) {
33 | @include set-color($color-text);
34 | background-color: $color-bg-overlay;
35 | }
36 |
37 | &:disabled, &[disabled] {
38 | opacity: 0.5;
39 | }
40 |
41 | .icon-button {
42 | margin-left: space(8);
43 | }
44 | }
45 |
46 | .config-debug__option-split {
47 | display: flex;
48 | flex-direction: row;
49 | align-items: center;
50 | justify-content: space-between;
51 | }
52 |
53 | .config-debug-option__label {
54 | @extend %label-md;
55 | display: flex;
56 | flex-direction: row;
57 | align-items: center;
58 | justify-content: flex-start;
59 | padding: space(4) space(16) space(12);
60 | width: auto;
61 | height: auto;
62 | white-space: nowrap;
63 | }
64 |
65 | .config-debug__option-controls {
66 | display: block;
67 | position: relative;
68 | flex: 1 1 auto;
69 | height: auto;
70 | width: auto;
71 | max-width: space(800);
72 | padding: 0 space(12);
73 | }
74 |
75 | .config-debug__option-trigger {
76 | flex: 1 1 auto;
77 | }
78 |
79 | .config-debug__select-wrapper {
80 | display: flex;
81 | position: relative;
82 | flex-direction: row;
83 | align-items: center;
84 | justify-content: flex-start;
85 | flex: 1 1 100%;
86 | width: auto;
87 | max-width: space(800);
88 | height: auto;
89 | padding: space(4);
90 |
91 | .config-debug__select-label {
92 | @extend %label-sm;
93 | padding-right: space(16);
94 | flex: auto;
95 | width: space(196);
96 |
97 | > div {
98 | display: inline;
99 | width: auto;
100 | height: auto;
101 | }
102 | }
103 |
104 | input {
105 | @extend %body;
106 | @extend %nav-all;
107 | display: block;
108 | position: relative;
109 | box-sizing: border-box;
110 | padding: 0;
111 | flex: 1 1 100%;
112 | width: auto;
113 | height: space(20);
114 | margin: auto 0;
115 | }
116 |
117 | select {
118 | @extend %body;
119 | @extend %nav-all;
120 | @include trans-colors-border;
121 | @include border($color-white-a50);
122 | display: block;
123 | position: relative;
124 | box-sizing: border-box;
125 | padding: 0;
126 | flex: 1 1 100%;
127 | width: auto;
128 | height: space(48);
129 | border-radius: $border-radius-md;
130 | background-color: $color-white-a5;
131 | cursor: pointer;
132 |
133 | align-items: center;
134 | justify-content: flex-start;
135 | padding: space(14);
136 |
137 | &:hover, &:focus {
138 | @include border($color-white-a80);
139 | background-color: $color-white-a20;
140 | }
141 |
142 | selectvalue {
143 | display: inline;
144 | margin: auto 0;
145 | height: auto;
146 | }
147 |
148 | selectbox {
149 | @include border($color-white-a80);
150 | background-color: $color-background-3;
151 | padding: space(4) 0;
152 | margin-top: space(2);
153 | border-radius: $border-radius-md;
154 |
155 | option {
156 | @extend %nav-all;
157 | @include trans-colors;
158 | padding: space(8) space(12);
159 | background-color: $color-transparent;
160 | color: $color-text-dim;
161 | font-weight: 400;
162 |
163 | &:hover, &:focus {
164 | background-color: $color-white-a20;
165 | }
166 |
167 | &:hover:not(:checked) {
168 | cursor: pointer;
169 | }
170 |
171 | &:checked {
172 | color: $color-white;
173 | background-color: $color-white-a5;
174 | }
175 | }
176 | }
177 | }
178 | }
179 |
--------------------------------------------------------------------------------
/assets/scss/styles/vars/_animations.scss:
--------------------------------------------------------------------------------
1 |
2 | $focus-anim: blue-pulse-with-border 0.75s infinite;
3 | $focus-anim-border: blue-pulse 0.75s infinite;
4 | $focus-anim-bg: blue-pulse-background 0.75s infinite;
5 |
--------------------------------------------------------------------------------
/assets/scss/styles/vars/_borders.scss:
--------------------------------------------------------------------------------
1 |
2 | $border-radius-sm: 8dp;
3 | $border-radius-md: 12dp;
4 | // modals/pages
5 | $border-radius-lg: 16dp;
6 |
7 | $border-radius-modal: $border-radius-lg;
8 |
9 | $border-width-thickness-num: 1.1;
10 | // $border-width-thickness-num: 1.5;
11 | $border-width-thickness: space($border-width-thickness-num);
12 |
13 | @mixin border($col: $color-border) {
14 | border-width: $border-width-thickness;
15 | border-color: $col;
16 | }
17 |
18 | @mixin border-top($col: $color-border) {
19 | border-top-width: $border-width-thickness;
20 | border-top-color: $col;
21 | }
22 |
23 | @mixin border-bottom($col: $color-border) {
24 | border-bottom-width: $border-width-thickness;
25 | border-bottom-color: $col;
26 | }
27 |
28 | @mixin inset-block($inset-amt) {
29 | position: absolute;
30 | top: $inset-amt;
31 | right: $inset-amt;
32 | bottom: $inset-amt;
33 | left: $inset-amt;
34 | }
35 |
36 | // add this to a child of the container that needs a border.
37 | // parent must have `position: relative`
38 | @mixin inner-border-block($col: $color-border) {
39 | @include inset-block($border-width-thickness);
40 | @include border($col);
41 | display: block;
42 | }
43 |
--------------------------------------------------------------------------------
/assets/scss/styles/vars/_colors.scss:
--------------------------------------------------------------------------------
1 | /* stylelint-disable color-no-hex, color-hex-length */
2 |
3 | $color-background-1: #08070D;
4 | $color-background-2: #121018;
5 | $color-background-3: #191622;
6 | $color-bg-overlay: rgba(190, 184, 219, 0.1000);
7 | $color-modal-overlay: rgba(8, 7, 13, 0.9000);
8 | $color-bg-shadow: rgba(0, 0, 0, 0.3500);
9 | $color-bg-shadow-2: rgba(8, 7, 13, 0.7200);
10 | $color-text: #F2F2F2;
11 | $color-text-dim: #CCCCCC;
12 | $color-text-inactive: rgba(255, 255, 255, 0.6000);
13 | $color-primary: #B97DF2;
14 | $color-primary-l: #DABAF7;
15 | $color-primary-d: #7A2AC6;
16 | $color-primary-a5: rgba(185, 125, 242, 0.0500);
17 | $color-primary-a20: rgba(185, 125, 242, 0.2000);
18 | $color-primary-a30: rgba(185, 125, 242, 0.3000);
19 | $color-primary-a50: rgba(185, 125, 242, 0.5000);
20 | $color-primary-a80: rgba(185, 125, 242, 0.8000);
21 | $color-secondary: #17D6E8;
22 | $color-secondary-l: #A2EFF6;
23 | $color-secondary-d: #25A1AD;
24 | $color-secondary-a5: rgba(23, 214, 232, 0.0500);
25 | $color-secondary-a20: rgba(23, 214, 232, 0.2000);
26 | $color-secondary-a30: rgba(23, 214, 232, 0.3000);
27 | $color-secondary-a50: rgba(23, 214, 232, 0.5000);
28 | $color-secondary-a80: rgba(23, 214, 232, 0.8000);
29 | $color-warning: #E9CD35;
30 | $color-warning-l: #F9E57C;
31 | $color-warning-d: #C5AA16;
32 | $color-warning-a5: rgba(233, 205, 53, 0.0500);
33 | $color-warning-a20: rgba(233, 205, 53, 0.2000);
34 | $color-warning-a30: rgba(233, 205, 53, 0.3000);
35 | $color-warning-a50: rgba(233, 205, 53, 0.5000);
36 | $color-warning-a80: rgba(233, 205, 53, 0.8000);
37 | $color-error: #F86039;
38 | $color-error-l: #FE8667;
39 | $color-error-d: #B23919;
40 | $color-error-a5: rgba(248, 96, 57, 0.0500);
41 | $color-error-a20: rgba(248, 96, 57, 0.2000);
42 | $color-error-a30: rgba(248, 96, 57, 0.3000);
43 | $color-error-a50: rgba(248, 96, 57, 0.5000);
44 | $color-error-a80: rgba(248, 96, 57, 0.8000);
45 | $color-success: #45D043;
46 | $color-success-l: #AAEAA9;
47 | $color-success-d: #2CA72A;
48 | $color-success-a5: rgba(69, 208, 67, 0.0500);
49 | $color-success-a20: rgba(69, 208, 67, 0.2000);
50 | $color-success-a30: rgba(69, 208, 67, 0.3000);
51 | $color-success-a50: rgba(69, 208, 67, 0.5000);
52 | $color-success-a80: rgba(69, 208, 67, 0.8000);
53 | $color-border: rgba(255, 255, 255, 0.2000);
54 | $color-border-soft: rgba(255, 255, 255, 0.1000);
55 | $color-border-hard: rgba(255, 255, 255, 0.3000);
56 | $color-border-solid: rgba(255, 255, 255, 0.6000);
57 | $color-transparent: rgba(0, 0, 0, 0.0000);
58 | $color-a: #3333FF;
59 | $color-a-l: #B2B2FF;
60 | $color-a-d: #2020AC;
61 | $color-a-a5: rgba(51, 51, 255, 0.0500);
62 | $color-a-a20: rgba(51, 51, 255, 0.2000);
63 | $color-a-a30: rgba(51, 51, 255, 0.3000);
64 | $color-a-a50: rgba(51, 51, 255, 0.5000);
65 | $color-a-a80: rgba(51, 51, 255, 0.8000);
66 | $color-white: #FFFFFF;
67 | $color-white-a5: rgba(255, 255, 255, 0.0500);
68 | $color-white-a20: rgba(255, 255, 255, 0.2000);
69 | $color-white-a30: rgba(255, 255, 255, 0.3000);
70 | $color-white-a50: rgba(255, 255, 255, 0.5000);
71 | $color-white-a80: rgba(255, 255, 255, 0.8000);
72 |
--------------------------------------------------------------------------------
/assets/scss/styles/vars/_gradients.scss:
--------------------------------------------------------------------------------
1 |
2 | // Not supported yet, need to use decorator: gradient atm
3 | // $primary-lr-fade: linear-gradient(90deg, rgba($color-primary-l, 0.08) 0%, rgba($color-primary-l, 0.00) 100%);
4 | // $primary-rl-fade: linear-gradient(90deg, rgba($color-primary-l, 0.00) 0%, rgba($color-primary-l, 0.08) 100%);
5 |
6 | $primary-lr-fade: horizontal-gradient(#{$color-primary-d}14 #{$color-primary-l}00);
7 | $primary-rl-fade: horizontal-gradient(#{$color-primary-d}00 #{$color-primary-l}14);
8 |
--------------------------------------------------------------------------------
/assets/scss/styles/vars/_spacing.scss:
--------------------------------------------------------------------------------
1 | @use 'sass:math';
2 |
3 | // $page-margin: 32;
4 | $page-margin: 64;
5 | $base-height: 1080;
6 | $base-modal-height: $base-height - ($page-margin * 2);
7 | $base-modal-max-width: math.div($base-modal-height * 16, 9);
8 |
--------------------------------------------------------------------------------
/assets/scss/styles/vars/_transitions.scss:
--------------------------------------------------------------------------------
1 | // see: lib/RmlUi/Source/Core/PropertyParserAnimation.cpp
2 | $transition-quick: 0.05s linear-in-out;
3 | // $transition-quick: 0.033s linear-in-out;
4 |
--------------------------------------------------------------------------------
/docs/deck_gyro_1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rainchus/Dk64-Recompiled/7d24f9bbd7f8b0931695f04a1ebb0309fd0eec75/docs/deck_gyro_1.jpg
--------------------------------------------------------------------------------
/icons/128.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rainchus/Dk64-Recompiled/7d24f9bbd7f8b0931695f04a1ebb0309fd0eec75/icons/128.ico
--------------------------------------------------------------------------------
/icons/16.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rainchus/Dk64-Recompiled/7d24f9bbd7f8b0931695f04a1ebb0309fd0eec75/icons/16.ico
--------------------------------------------------------------------------------
/icons/256.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rainchus/Dk64-Recompiled/7d24f9bbd7f8b0931695f04a1ebb0309fd0eec75/icons/256.ico
--------------------------------------------------------------------------------
/icons/32.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rainchus/Dk64-Recompiled/7d24f9bbd7f8b0931695f04a1ebb0309fd0eec75/icons/32.ico
--------------------------------------------------------------------------------
/icons/512.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rainchus/Dk64-Recompiled/7d24f9bbd7f8b0931695f04a1ebb0309fd0eec75/icons/512.ico
--------------------------------------------------------------------------------
/icons/512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rainchus/Dk64-Recompiled/7d24f9bbd7f8b0931695f04a1ebb0309fd0eec75/icons/512.png
--------------------------------------------------------------------------------
/icons/64.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rainchus/Dk64-Recompiled/7d24f9bbd7f8b0931695f04a1ebb0309fd0eec75/icons/64.ico
--------------------------------------------------------------------------------
/icons/app.rc:
--------------------------------------------------------------------------------
1 | 1 ICON DISCARDABLE "512.ico"
2 | 2 ICON DISCARDABLE "256.ico"
3 | 3 ICON DISCARDABLE "128.ico"
4 | 4 ICON DISCARDABLE "64.ico"
5 | 5 ICON DISCARDABLE "32.ico"
6 | 6 ICON DISCARDABLE "16.ico"
--------------------------------------------------------------------------------
/include/ovl_patches.hpp:
--------------------------------------------------------------------------------
1 | #ifndef __OVL_PATCHES_HPP__
2 | #define __OVL_PATCHES_HPP__
3 |
4 | namespace zelda64 {
5 | void register_overlays();
6 | void register_patches();
7 | }
8 |
9 | #endif
10 |
--------------------------------------------------------------------------------
/include/recomp_files.h:
--------------------------------------------------------------------------------
1 | #ifndef __RECOMP_FILES_H__
2 | #define __RECOMP_FILES_H__
3 |
4 | #include
5 | #include
6 |
7 | namespace recomp {
8 | std::ifstream open_input_file_with_backup(const std::filesystem::path& filepath, std::ios_base::openmode mode = std::ios_base::in);
9 | std::ifstream open_input_backup_file(const std::filesystem::path& filepath, std::ios_base::openmode mode = std::ios_base::in);
10 | std::ofstream open_output_file_with_backup(const std::filesystem::path& filepath, std::ios_base::openmode mode = std::ios_base::out);
11 | bool finalize_output_file_with_backup(const std::filesystem::path& filepath);
12 | };
13 |
14 | #endif
15 |
--------------------------------------------------------------------------------
/include/recomp_input.h:
--------------------------------------------------------------------------------
1 | #ifndef __RECOMP_INPUT_H__
2 | #define __RECOMP_INPUT_H__
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 |
12 | #include "ultramodern/input.hpp"
13 |
14 | #include "json/json.hpp"
15 |
16 | namespace recomp {
17 | // x-macros to build input enums and arrays.
18 | // First parameter is the enum name, second parameter is the bit field for the input (or 0 if there is no associated one), third is the readable name.
19 | // TODO refactor this to allow projects to rename these, or get rid of the readable name and leave that up to individual projects to map.
20 | #define DEFINE_N64_BUTTON_INPUTS() \
21 | DEFINE_INPUT(A, 0x8000, "Action") \
22 | DEFINE_INPUT(B, 0x4000, "Attack/Cancel") \
23 | DEFINE_INPUT(Z, 0x2000, "Target") \
24 | DEFINE_INPUT(START, 0x1000, "Start") \
25 | DEFINE_INPUT(L, 0x0020, "Toggle map") \
26 | DEFINE_INPUT(R, 0x0010, "Shield") \
27 | DEFINE_INPUT(C_UP, 0x0008, "Look/Fairy") \
28 | DEFINE_INPUT(C_LEFT, 0x0002, "Item 1") \
29 | DEFINE_INPUT(C_DOWN, 0x0004, "Item 2") \
30 | DEFINE_INPUT(C_RIGHT, 0x0001, "Item 3") \
31 | DEFINE_INPUT(DPAD_UP, 0x0800, "Special Item 1") \
32 | DEFINE_INPUT(DPAD_RIGHT, 0x0100, "Special Item 2") \
33 | DEFINE_INPUT(DPAD_DOWN, 0x0400, "Special Item 3") \
34 | DEFINE_INPUT(DPAD_LEFT, 0x0200, "Special Item 4")
35 |
36 | #define DEFINE_N64_AXIS_INPUTS() \
37 | DEFINE_INPUT(Y_AXIS_POS, 0, "Up") \
38 | DEFINE_INPUT(Y_AXIS_NEG, 0, "Down") \
39 | DEFINE_INPUT(X_AXIS_NEG, 0, "Left") \
40 | DEFINE_INPUT(X_AXIS_POS, 0, "Right") \
41 |
42 | #define DEFINE_RECOMP_UI_INPUTS() \
43 | DEFINE_INPUT(TOGGLE_MENU, 0, "Toggle Menu") \
44 | DEFINE_INPUT(ACCEPT_MENU, 0, "Accept (Menu)") \
45 | DEFINE_INPUT(APPLY_MENU, 0, "Apply (Menu)")
46 |
47 | #define DEFINE_ALL_INPUTS() \
48 | DEFINE_N64_BUTTON_INPUTS() \
49 | DEFINE_N64_AXIS_INPUTS() \
50 | DEFINE_RECOMP_UI_INPUTS()
51 |
52 | // Enum containing every recomp input.
53 | #define DEFINE_INPUT(name, value, readable) name,
54 | enum class GameInput {
55 | DEFINE_ALL_INPUTS()
56 |
57 | COUNT,
58 | N64_BUTTON_START = A,
59 | N64_BUTTON_COUNT = C_RIGHT - N64_BUTTON_START + 1,
60 | N64_AXIS_START = X_AXIS_NEG,
61 | N64_AXIS_COUNT = Y_AXIS_POS - N64_AXIS_START + 1,
62 | };
63 | #undef DEFINE_INPUT
64 |
65 | struct InputField {
66 | uint32_t input_type;
67 | int32_t input_id;
68 | std::string to_string() const;
69 | auto operator<=>(const InputField& rhs) const = default;
70 | };
71 |
72 | void poll_inputs();
73 | float get_input_analog(const InputField& field);
74 | float get_input_analog(const std::span fields);
75 | bool get_input_digital(const InputField& field);
76 | bool get_input_digital(const std::span fields);
77 | void get_gyro_deltas(float* x, float* y);
78 | void get_mouse_deltas(float* x, float* y);
79 | void get_right_analog(float* x, float* y);
80 |
81 | enum class InputDevice {
82 | Controller,
83 | Keyboard,
84 | COUNT
85 | };
86 |
87 | void start_scanning_input(InputDevice device);
88 | void stop_scanning_input();
89 | void finish_scanning_input(InputField scanned_field);
90 | void cancel_scanning_input();
91 | void config_menu_set_cont_or_kb(bool cont_interacted);
92 | InputField get_scanned_input();
93 | int get_scanned_input_index();
94 |
95 | struct DefaultN64Mappings {
96 | std::vector a;
97 | std::vector b;
98 | std::vector l;
99 | std::vector r;
100 | std::vector z;
101 | std::vector start;
102 |
103 | std::vector c_left;
104 | std::vector c_right;
105 | std::vector c_up;
106 | std::vector c_down;
107 |
108 | std::vector dpad_left;
109 | std::vector dpad_right;
110 | std::vector dpad_up;
111 | std::vector dpad_down;
112 |
113 | std::vector analog_left;
114 | std::vector analog_right;
115 | std::vector analog_up;
116 | std::vector analog_down;
117 |
118 | std::vector toggle_menu;
119 | std::vector accept_menu;
120 | std::vector apply_menu;
121 | };
122 |
123 | inline const std::vector& get_default_mapping_for_input(const DefaultN64Mappings& defaults, const GameInput input) {
124 | static const std::vector empty_input_field{};
125 | switch (input) {
126 | case GameInput::A: return defaults.a;
127 | case GameInput::B: return defaults.b;
128 | case GameInput::L: return defaults.l;
129 | case GameInput::R: return defaults.r;
130 | case GameInput::Z: return defaults.z;
131 | case GameInput::START: return defaults.start;
132 | case GameInput::C_LEFT: return defaults.c_left;
133 | case GameInput::C_RIGHT: return defaults.c_right;
134 | case GameInput::C_UP: return defaults.c_up;
135 | case GameInput::C_DOWN: return defaults.c_down;
136 | case GameInput::DPAD_LEFT: return defaults.dpad_left;
137 | case GameInput::DPAD_RIGHT: return defaults.dpad_right;
138 | case GameInput::DPAD_UP: return defaults.dpad_up;
139 | case GameInput::DPAD_DOWN: return defaults.dpad_down;
140 | case GameInput::X_AXIS_NEG: return defaults.analog_left;
141 | case GameInput::X_AXIS_POS: return defaults.analog_right;
142 | case GameInput::Y_AXIS_POS: return defaults.analog_up;
143 | case GameInput::Y_AXIS_NEG: return defaults.analog_down;
144 | case GameInput::TOGGLE_MENU: return defaults.toggle_menu;
145 | case GameInput::ACCEPT_MENU: return defaults.accept_menu;
146 | case GameInput::APPLY_MENU: return defaults.apply_menu;
147 | default: return empty_input_field;
148 | }
149 | }
150 |
151 | extern const DefaultN64Mappings default_n64_keyboard_mappings;
152 | extern const DefaultN64Mappings default_n64_controller_mappings;
153 |
154 | constexpr size_t bindings_per_input = 2;
155 |
156 | size_t get_num_inputs();
157 | const std::string& get_input_name(GameInput input);
158 | const std::string& get_input_enum_name(GameInput input);
159 | GameInput get_input_from_enum_name(const std::string_view name);
160 | InputField& get_input_binding(GameInput input, size_t binding_index, InputDevice device);
161 | void set_input_binding(GameInput input, size_t binding_index, InputDevice device, InputField value);
162 |
163 | bool get_n64_input(int controller_num, uint16_t* buttons_out, float* x_out, float* y_out);
164 | void set_rumble(int controller_num, bool);
165 | void update_rumble();
166 | void handle_events();
167 |
168 | ultramodern::input::connected_device_info_t get_connected_device_info(int controller_num);
169 |
170 | // Rumble strength ranges from 0 to 100.
171 | int get_rumble_strength();
172 | void set_rumble_strength(int strength);
173 |
174 | // Gyro and mouse sensitivities range from 0 to 100.
175 | int get_gyro_sensitivity();
176 | int get_mouse_sensitivity();
177 | int get_joystick_deadzone();
178 | void set_gyro_sensitivity(int strength);
179 | void set_mouse_sensitivity(int strength);
180 | void set_joystick_deadzone(int strength);
181 | void apply_joystick_deadzone(float x_in, float y_in, float* x_out, float* y_out);
182 | void set_right_analog_suppressed(bool suppressed);
183 |
184 | enum class BackgroundInputMode {
185 | On,
186 | Off,
187 | OptionCount
188 | };
189 |
190 | NLOHMANN_JSON_SERIALIZE_ENUM(recomp::BackgroundInputMode, {
191 | {recomp::BackgroundInputMode::On, "On"},
192 | {recomp::BackgroundInputMode::Off, "Off"}
193 | });
194 |
195 | BackgroundInputMode get_background_input_mode();
196 | void set_background_input_mode(BackgroundInputMode mode);
197 |
198 | bool game_input_disabled();
199 | bool all_input_disabled();
200 | }
201 |
202 | #endif
203 |
--------------------------------------------------------------------------------
/include/recomp_ui.h:
--------------------------------------------------------------------------------
1 | #ifndef __RECOMP_UI__
2 | #define __RECOMP_UI__
3 |
4 | #include
5 | #include
6 |
7 | #include "SDL.h"
8 | #include "RmlUi/Core.h"
9 |
10 | namespace Rml {
11 | class ElementDocument;
12 | class EventListenerInstancer;
13 | class Context;
14 | class Event;
15 | }
16 |
17 | namespace recompui {
18 | class UiEventListenerInstancer;
19 |
20 | class MenuController {
21 | public:
22 | virtual ~MenuController() {}
23 | virtual Rml::ElementDocument* load_document(Rml::Context* context) = 0;
24 | virtual void register_events(UiEventListenerInstancer& listener) = 0;
25 | virtual void make_bindings(Rml::Context* context) = 0;
26 | };
27 |
28 | std::unique_ptr create_launcher_menu();
29 | std::unique_ptr create_config_menu();
30 |
31 | using event_handler_t = void(const std::string& param, Rml::Event&);
32 |
33 | void queue_event(const SDL_Event& event);
34 | bool try_deque_event(SDL_Event& out);
35 |
36 | std::unique_ptr make_event_listener_instancer();
37 | void register_event(UiEventListenerInstancer& listener, const std::string& name, event_handler_t* handler);
38 |
39 | enum class Menu {
40 | Launcher,
41 | Config,
42 | None
43 | };
44 |
45 | void set_current_menu(Menu menu);
46 | Menu get_current_menu();
47 |
48 | enum class ConfigSubmenu {
49 | General,
50 | Controls,
51 | Graphics,
52 | Audio,
53 | Debug,
54 | Count
55 | };
56 |
57 | enum class ButtonVariant {
58 | Primary,
59 | Secondary,
60 | Tertiary,
61 | Success,
62 | Error,
63 | Warning,
64 | NumVariants,
65 | };
66 |
67 | void set_config_submenu(ConfigSubmenu submenu);
68 |
69 | void destroy_ui();
70 | void apply_color_hack();
71 | void get_window_size(int& width, int& height);
72 | void set_cursor_visible(bool visible);
73 | void update_supported_options();
74 | void toggle_fullscreen();
75 | void update_rml_display_refresh_rate();
76 |
77 | extern const std::unordered_map button_variants;
78 |
79 | struct PromptContext {
80 | Rml::DataModelHandle model_handle;
81 | std::string header = "";
82 | std::string content = "";
83 | std::string confirmLabel = "Confirm";
84 | std::string cancelLabel = "Cancel";
85 | ButtonVariant confirmVariant = ButtonVariant::Success;
86 | ButtonVariant cancelVariant = ButtonVariant::Error;
87 | std::function onConfirm;
88 | std::function onCancel;
89 |
90 | std::string returnElementId = "";
91 |
92 | bool open = false;
93 | bool shouldFocus = false;
94 | bool focusOnCancel = true;
95 |
96 | PromptContext() = default;
97 |
98 | void close_prompt();
99 | void open_prompt(
100 | const std::string& headerText,
101 | const std::string& contentText,
102 | const std::string& confirmLabelText,
103 | const std::string& cancelLabelText,
104 | std::function confirmCb,
105 | std::function cancelCb,
106 | ButtonVariant _confirmVariant = ButtonVariant::Success,
107 | ButtonVariant _cancelVariant = ButtonVariant::Error,
108 | bool _focusOnCancel = true,
109 | const std::string& _returnElementId = ""
110 | );
111 | void on_confirm(void);
112 | void on_cancel(void);
113 | void on_click(Rml::DataModelHandle model_handle, Rml::Event& event, const Rml::VariantList& inputs);
114 | };
115 |
116 | PromptContext *get_prompt_context(void);
117 |
118 | bool get_cont_active(void);
119 | void set_cont_active(bool active);
120 | void activate_mouse();
121 |
122 | void message_box(const char* msg);
123 |
124 | void set_render_hooks();
125 | }
126 |
127 | #endif
128 |
--------------------------------------------------------------------------------
/include/zelda_config.h:
--------------------------------------------------------------------------------
1 | #ifndef __ZELDA_CONFIG_H__
2 | #define __ZELDA_CONFIG_H__
3 |
4 | #include
5 | #include
6 | #include "ultramodern/config.hpp"
7 | #include "recomp_input.h"
8 |
9 | namespace zelda64 {
10 | constexpr std::u8string_view program_id = u8"ChameleonTwistRecompiled";
11 | constexpr std::string_view program_name = "Chameleon Twist: Recompiled";
12 |
13 | // TODO: Move loading configs to the runtime once we have a way to allow per-project customization.
14 | void load_config();
15 | void save_config();
16 |
17 | void reset_input_bindings();
18 | void reset_cont_input_bindings();
19 | void reset_kb_input_bindings();
20 | void reset_single_input_binding(recomp::InputDevice device, recomp::GameInput input);
21 |
22 | std::filesystem::path get_app_folder_path();
23 |
24 | bool get_debug_mode_enabled();
25 | void set_debug_mode_enabled(bool enabled);
26 |
27 | enum class AutosaveMode {
28 | On,
29 | Off,
30 | OptionCount
31 | };
32 |
33 | NLOHMANN_JSON_SERIALIZE_ENUM(zelda64::AutosaveMode, {
34 | {zelda64::AutosaveMode::On, "On"},
35 | {zelda64::AutosaveMode::Off, "Off"}
36 | });
37 |
38 | enum class TargetingMode {
39 | Switch,
40 | Hold,
41 | OptionCount
42 | };
43 |
44 | NLOHMANN_JSON_SERIALIZE_ENUM(zelda64::TargetingMode, {
45 | {zelda64::TargetingMode::Switch, "Switch"},
46 | {zelda64::TargetingMode::Hold, "Hold"}
47 | });
48 |
49 | TargetingMode get_targeting_mode();
50 | void set_targeting_mode(TargetingMode mode);
51 |
52 | enum class CameraInvertMode {
53 | InvertNone,
54 | InvertX,
55 | InvertY,
56 | InvertBoth,
57 | OptionCount
58 | };
59 |
60 | NLOHMANN_JSON_SERIALIZE_ENUM(zelda64::CameraInvertMode, {
61 | {zelda64::CameraInvertMode::InvertNone, "InvertNone"},
62 | {zelda64::CameraInvertMode::InvertX, "InvertX"},
63 | {zelda64::CameraInvertMode::InvertY, "InvertY"},
64 | {zelda64::CameraInvertMode::InvertBoth, "InvertBoth"}
65 | });
66 |
67 | CameraInvertMode get_camera_invert_mode();
68 | void set_camera_invert_mode(CameraInvertMode mode);
69 |
70 | CameraInvertMode get_analog_camera_invert_mode();
71 | void set_analog_camera_invert_mode(CameraInvertMode mode);
72 |
73 | enum class AnalogCamMode {
74 | On,
75 | Off,
76 | OptionCount
77 | };
78 |
79 | NLOHMANN_JSON_SERIALIZE_ENUM(zelda64::AnalogCamMode, {
80 | {zelda64::AnalogCamMode::On, "On"},
81 | {zelda64::AnalogCamMode::Off, "Off"}
82 | });
83 |
84 | AutosaveMode get_autosave_mode();
85 | void set_autosave_mode(AutosaveMode mode);
86 |
87 | AnalogCamMode get_analog_cam_mode();
88 | void set_analog_cam_mode(AnalogCamMode mode);
89 |
90 | void open_quit_game_prompt();
91 | };
92 |
93 | #endif
94 |
--------------------------------------------------------------------------------
/include/zelda_debug.h:
--------------------------------------------------------------------------------
1 | #ifndef __ZELDA_DEBUG_H__
2 | #define __ZELDA_DEBUG_H__
3 |
4 | #include
5 | #include
6 |
7 | namespace zelda64 {
8 | struct SceneWarps {
9 | int index;
10 | std::string name;
11 | std::vector entrances;
12 | };
13 |
14 | struct AreaWarps {
15 | std::string name;
16 | std::vector scenes;
17 | };
18 |
19 | extern std::vector game_warps;
20 |
21 | void do_warp(int area, int scene, int entrance);
22 | void set_time(uint8_t day, uint8_t hour, uint8_t minute);
23 | }
24 |
25 | #endif
26 |
--------------------------------------------------------------------------------
/include/zelda_game.h:
--------------------------------------------------------------------------------
1 | #ifndef __ZELDA_GAME_H__
2 | #define __ZELDA_GAME_H__
3 |
4 | namespace zelda64 {
5 | void quicksave_save();
6 | void quicksave_load();
7 | };
8 |
9 | #endif
10 |
--------------------------------------------------------------------------------
/include/zelda_render.h:
--------------------------------------------------------------------------------
1 | #ifndef __ZELDA_RENDER_H__
2 | #define __ZELDA_RENDER_H__
3 |
4 | #include
5 | #include
6 |
7 | #include "common/rt64_user_configuration.h"
8 | #include "ultramodern/renderer_context.hpp"
9 | #include "librecomp/mods.hpp"
10 |
11 | namespace RT64 {
12 | struct Application;
13 | }
14 |
15 | namespace zelda64 {
16 | namespace renderer {
17 | class RT64Context final : public ultramodern::renderer::RendererContext {
18 | public:
19 | ~RT64Context() override;
20 | RT64Context(uint8_t* rdram, ultramodern::renderer::WindowHandle window_handle, bool developer_mode);
21 |
22 | bool valid() override { return static_cast(app); }
23 |
24 | bool update_config(const ultramodern::renderer::GraphicsConfig& old_config, const ultramodern::renderer::GraphicsConfig& new_config) override;
25 |
26 | void enable_instant_present() override;
27 | void send_dl(const OSTask* task) override;
28 | void update_screen(uint32_t vi_origin) override;
29 | void shutdown() override;
30 | uint32_t get_display_framerate() const override;
31 | float get_resolution_scale() const override;
32 |
33 | protected:
34 | std::unique_ptr app;
35 | std::unordered_set enabled_texture_packs;
36 | };
37 |
38 | std::unique_ptr create_render_context(uint8_t* rdram, ultramodern::renderer::WindowHandle window_handle, bool developer_mode);
39 |
40 | RT64::UserConfiguration::Antialiasing RT64MaxMSAA();
41 | bool RT64SamplePositionsSupported();
42 | bool RT64HighPrecisionFBEnabled();
43 |
44 | void enable_texture_pack(const recomp::mods::ModHandle& mod);
45 | void disable_texture_pack(const recomp::mods::ModHandle& mod);
46 | }
47 | }
48 |
49 | #endif
--------------------------------------------------------------------------------
/include/zelda_sound.h:
--------------------------------------------------------------------------------
1 | #ifndef __ZELDA_SOUND_H__
2 | #define __ZELDA_SOUND_H__
3 |
4 | namespace zelda64 {
5 | void reset_sound_settings();
6 | void set_main_volume(int volume);
7 | int get_main_volume();
8 | void set_bgm_volume(int volume);
9 | int get_bgm_volume();
10 | void set_low_health_beeps_enabled(bool enabled);
11 | bool get_low_health_beeps_enabled();
12 | }
13 |
14 | #endif
15 |
--------------------------------------------------------------------------------
/launch.vs.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "0.2.1",
3 | "defaults": {},
4 | "configurations": [
5 | {
6 | "type": "default",
7 | "project": "CMakeLists.txt",
8 | "projectTarget": "DK64Recompiled.exe",
9 | "name": "DK64Recompiled.exe",
10 | "currentDir": "${workspaceRoot}"
11 | }
12 | ]
13 | }
--------------------------------------------------------------------------------
/lib/FindFreetype.cmake:
--------------------------------------------------------------------------------
1 | set(FREETYPE_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/lib/freetype-windows-binaries/include)
2 | set(FREETYPE_LIBRARIES "${CMAKE_SOURCE_DIR}/lib/freetype-windows-binaries/release static/vs2015-2022/win64/freetype.lib")
3 |
--------------------------------------------------------------------------------
/lib/GamepadMotionHelpers/.gitignore:
--------------------------------------------------------------------------------
1 | # Prerequisites
2 | *.d
3 |
4 | # Compiled Object files
5 | *.slo
6 | *.lo
7 | *.o
8 | *.obj
9 |
10 | # Precompiled Headers
11 | *.gch
12 | *.pch
13 |
14 | # Compiled Dynamic libraries
15 | *.so
16 | *.dylib
17 | *.dll
18 |
19 | # Fortran module files
20 | *.mod
21 | *.smod
22 |
23 | # Compiled Static libraries
24 | *.lai
25 | *.la
26 | *.a
27 | *.lib
28 |
29 | # Executables
30 | *.exe
31 | *.out
32 | *.app
33 |
--------------------------------------------------------------------------------
/lib/GamepadMotionHelpers/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.8)
2 |
3 | project(GamepadMotionHelpers LANGUAGES CXX)
4 |
5 | add_library(${PROJECT_NAME} INTERFACE)
6 | add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME})
7 | target_include_directories(${PROJECT_NAME}
8 | INTERFACE
9 | $
10 | $)
11 |
--------------------------------------------------------------------------------
/lib/GamepadMotionHelpers/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020-2023 Julian "Jibb" Smart
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/n_aspMain.toml:
--------------------------------------------------------------------------------
1 | text_offset = 0x2146010
2 | text_size = 0xC30
3 | text_address = 0x04001080
4 | rom_file_path = "donkeykong64.decompressed.us.z64"
5 | output_file_path = "rsp/n_aspMain.cpp"
6 | output_function_name = "n_aspMain"
7 |
8 | extra_indirect_branch_targets = [
9 | 0x10E8, 0x138C, 0x1190, 0x1A28, 0x11BC, 0x17C0, 0x11FC, 0x1C58,
10 | 0x1C58, 0x126C, 0x1338, 0x123C, 0x1C58, 0x12C4, 0x12B0, 0x1374
11 | ]
--------------------------------------------------------------------------------
/patches.toml:
--------------------------------------------------------------------------------
1 | # Config file for recompiling patches for the Majora's Mask NTSC 1.0 Recompilation.
2 |
3 | [input]
4 | # Paths are relative to the location of this config file.
5 | elf_path = "patches/patches.elf"
6 | output_func_path = "RecompiledPatches"
7 | single_file_output = true
8 |
9 | # Allow absolute symbols to be used as jump targets.
10 | use_absolute_symbols = true
11 |
12 | # Point the recompiler at the symbol files so that it can resolve relocations during recompilation.
13 | func_reference_syms_file = "Dk64Syms/dump.toml"
14 | data_reference_syms_files = [ "Dk64Syms/data_dump.toml" ]
15 | # data_reference_syms_files = [ "Dk64Syms/sf64.us.rev1.datasyms.toml", "Dk64Syms/sf64.us.rev1.datasyms_static.toml" ]
16 |
17 | # Tell the recompiler to write the output binary. Doing this instead of using objcopy allows the recompiler to patch MIPS32 relocs.
18 | output_binary_path = "patches/patches.bin"
19 |
20 | # Do not emit warnings for unpaired LO16 values, as clang produces many of them.
21 | unpaired_lo16_warnings = false
22 |
23 | strict_patch_mode = true
--------------------------------------------------------------------------------
/patches/.gitignore:
--------------------------------------------------------------------------------
1 | *.d
2 | *.o
3 | *.elf
4 | *.bin
5 | ./funcs.h
6 | patches.map
7 |
--------------------------------------------------------------------------------
/patches/Makefile:
--------------------------------------------------------------------------------
1 | TARGET = patches.elf
2 |
3 | CC ?= clang
4 | LD ?= ld.lld
5 |
6 | CFLAGS := -target mips -mips2 -mabi=32 -O2 -G0 -mno-abicalls -mno-odd-spreg -mno-check-zero-division \
7 | -fomit-frame-pointer -ffast-math -fno-unsafe-math-optimizations -fno-builtin-memset \
8 | -Wall -Wextra -Wno-incompatible-library-redeclaration -Wno-unused-parameter -Wno-unknown-pragmas -Wno-unused-variable -Wno-missing-braces -Wno-unsupported-floating-point-opt
9 | CPPFLAGS := -nostdinc -D_LANGUAGE_C -DMIPS -I dummy_headers -I ../lib/dk64_decomp/include -I ../lib/dk64_decomp/include/2.0L/PR -I ../lib/dk64_decomp/include/2.0L -I ../lib/dk64_decomp/include/libc -I ../lib/dk64_decomp/src -I../lib/rt64/include
10 | LDFLAGS := -nostdlib -T patches.ld -T syms.ld -Map patches.map --unresolved-symbols=ignore-all --emit-relocs
11 |
12 | C_SRCS := $(wildcard *.c)
13 | C_OBJS := $(C_SRCS:.c=.o)
14 | C_DEPS := $(C_SRCS:.c=.d)
15 |
16 | $(TARGET): $(C_OBJS) patches.ld syms.ld
17 | $(LD) $(C_OBJS) $(LDFLAGS) -o $@
18 |
19 | $(C_OBJS): %.o : %.c
20 | $(CC) $(CFLAGS) $(CPPFLAGS) $< -MMD -MF $(@:.o=.d) -c -o $@
21 |
22 | clean:
23 | rm -rf $(C_OBJS) $(TARGET) $(C_DEPS)
24 |
25 | -include $(C_DEPS)
26 |
27 | .PHONY: clean
28 |
--------------------------------------------------------------------------------
/patches/dummy_headers/assets/objects/object_fall2/object_fall2.h:
--------------------------------------------------------------------------------
1 | // Required to include MM decomp headers without having built the repo
2 |
3 | #ifndef OBJECT_FALL2_H
4 | #define OBJECT_FALL2_H 1
5 |
6 | extern Vtx object_fall2Vtx_000000[];
7 | extern Gfx gOpenMouthMoonDL[];
8 | extern u64 gOpenMouthMoonFarSideTLUT[];
9 | extern u64 gOpenMouthMoonFaceTLUT[];
10 | extern u64 gOpenMouthMoonEyesTex[];
11 | extern u64 gOpenMouthMoonFarSideTex[];
12 | extern u64 gOpenMouthMoonFaceTex[];
13 | extern u64 gOpenMouthMoonTeethTex[];
14 | extern u8 object_fall2_Blob_005EF4[];
15 | extern Vtx object_fall2_Vtx_005F10[];
16 | extern Gfx object_fall2_DL_006E00[];
17 | extern Gfx object_fall2_DL_006EF0[];
18 | extern Gfx object_fall2_DL_006FF8[];
19 | extern Gfx object_fall2_DL_007100[];
20 | extern Gfx object_fall2_DL_007208[];
21 | extern Gfx object_fall2_DL_007310[];
22 | extern Gfx object_fall2_DL_007418[];
23 | extern Gfx object_fall2_DL_007520[];
24 | extern Gfx object_fall2_DL_007628[];
25 | extern Gfx object_fall2_DL_007730[];
26 | extern u64 object_fall2_Tex_007838[];
27 | extern u64 object_fall2_Tex_008038[];
28 | extern AnimatedMatTexScrollParams object_fall2_Matanimheader_008840TexScrollParams_008838[];
29 | extern AnimatedMaterial object_fall2_Matanimheader_008840[];
30 | extern u8 object_fall2_Blob_008898[];
31 | #endif
32 |
--------------------------------------------------------------------------------
/patches/dummy_headers/code/sub_s/sub_s.h:
--------------------------------------------------------------------------------
1 | // Required to include MM decomp headers without having built the repo
2 |
3 | #ifndef SUB_S_H
4 | #define SUB_S_H 1
5 |
6 | extern Vtx codeVtx_120260[];
7 | extern Gfx gShadowMaterialDL[];
8 | extern Gfx gShadowModelDL[];
9 |
10 | #endif
11 |
--------------------------------------------------------------------------------
/patches/dummy_headers/objects/gameplay_keep/gameplay_keep.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rainchus/Dk64-Recompiled/7d24f9bbd7f8b0931695f04a1ebb0309fd0eec75/patches/dummy_headers/objects/gameplay_keep/gameplay_keep.h
--------------------------------------------------------------------------------
/patches/dummy_headers/objects/object_boss03/object_boss03.h:
--------------------------------------------------------------------------------
1 | // Required to include MM decomp headers without having built the repo
2 |
3 | #ifndef OBJECT_BOSS03_H
4 | #define OBJECT_BOSS03_H 1
5 |
6 | typedef enum GyorgLimb {
7 | /* 0x00 */ GYORG_LIMB_NONE,
8 | /* 0x01 */ GYORG_LIMB_ROOT,
9 | /* 0x02 */ GYORG_LIMB_HEAD,
10 | /* 0x03 */ GYORG_LIMB_BODY_ROOT,
11 | /* 0x04 */ GYORG_LIMB_UPPER_TRUNK,
12 | /* 0x05 */ GYORG_LIMB_LOWER_TRUNK,
13 | /* 0x06 */ GYORG_LIMB_TAIL,
14 | /* 0x07 */ GYORG_LIMB_RIGHT_FIN_ROOT,
15 | /* 0x08 */ GYORG_LIMB_UPPER_RIGHT_FIN,
16 | /* 0x09 */ GYORG_LIMB_LOWER_RIGHT_FIN,
17 | /* 0x0A */ GYORG_LIMB_LEFT_FIN_ROOT,
18 | /* 0x0B */ GYORG_LIMB_UPPER_LEFT_FIN,
19 | /* 0x0C */ GYORG_LIMB_LOWER_LEFT_FIN,
20 | /* 0x0D */ GYORG_LIMB_JAW_ROOT,
21 | /* 0x0E */ GYORG_LIMB_JAW,
22 | /* 0x0F */ GYORG_LIMB_MAX
23 | } GyorgLimb;
24 |
25 | typedef enum GyorgSmallFishLimb {
26 | /* 0x00 */ GYORG_SMALL_FISH_LIMB_NONE,
27 | /* 0x01 */ GYORG_SMALL_FISH_LIMB_ROOT,
28 | /* 0x02 */ GYORG_SMALL_FISH_LIMB_BODY_ROOT,
29 | /* 0x03 */ GYORG_SMALL_FISH_LIMB_TRUNK_ROOT,
30 | /* 0x04 */ GYORG_SMALL_FISH_LIMB_TAIL_FIN,
31 | /* 0x05 */ GYORG_SMALL_FISH_LIMB_TRUNK,
32 | /* 0x06 */ GYORG_SMALL_FISH_LIMB_LEFT_FIN,
33 | /* 0x07 */ GYORG_SMALL_FISH_LIMB_DORSAL_FIN,
34 | /* 0x08 */ GYORG_SMALL_FISH_LIMB_RIGHT_FIN,
35 | /* 0x09 */ GYORG_SMALL_FISH_LIMB_HEAD,
36 | /* 0x0A */ GYORG_SMALL_FISH_LIMB_MAX
37 | } GyorgSmallFishLimb;
38 |
39 | extern s16 sGyorgIdleAnimFrameData[];
40 | extern JointIndex sGyorgIdleAnimJointIndices[];
41 | extern AnimationHeader gGyorgIdleAnim;
42 | extern u64 gGyorgUnusedMajorasWrathWhipTex[];
43 | extern Vtx object_boss03Vtx_0001A0[];
44 | extern Gfx gGyorgUnusedMajorasWrathWhipDL1[];
45 | extern Gfx gGyorgUnusedMajorasWrathWhipDL2[];
46 | extern Gfx gGyorgUnusedMajorasWrathWhipDL3[];
47 | extern Vtx object_boss03Vtx_0002D8[];
48 | extern Gfx gGyorgHeadDL[];
49 | extern Gfx gGyorgJawDL[];
50 | extern Gfx gGyorgUpperLeftFinDL[];
51 | extern Gfx gGyorgLowerLeftFinDL[];
52 | extern Gfx gGyorgUpperRightFinDL[];
53 | extern Gfx gGyorgLowerRightFinDL[];
54 | extern Gfx gGyorgUpperTrunkDL[];
55 | extern Gfx gGyorgLowerTrunkDL[];
56 | extern Gfx gGyorgTailDL[];
57 | extern AnimatedMaterial gGyorgUnused5388TexAnim[];
58 | extern u64 gGyorgFinsSpikesAndJawTLUT[];
59 | extern u64 gGyorgSidesTLUT[];
60 | extern u64 gGyorgMouthAndSpikeBacksideTLUT[];
61 | extern u64 gGyorgBellyAndFinFleshTLUT[];
62 | extern u64 gGyorgEyeTex[];
63 | extern u64 gGyorgFinsSpikesAndJawTex[];
64 | extern u64 gGyorgSidesTex[];
65 | extern u64 gGyorgMouthAndSpikeBacksideTex[];
66 | extern u64 gGyorgBellyAndFinFleshTex[];
67 | extern u64 gGyorgHornsTeethAndClawsTex[];
68 | extern Vtx object_boss03Vtx_007E10[];
69 | extern Gfx gGyorgBubbleMaterialDL[];
70 | extern Gfx gGyorgBubbleModelDL[];
71 | extern u64 gGyorgTitleCardTex[];
72 | extern StandardLimb gGyorgRootLimb;
73 | extern StandardLimb gGyorgHeadLimb;
74 | extern StandardLimb gGyorgBodyRootLimb;
75 | extern StandardLimb gGyorgUpperTrunkLimb;
76 | extern StandardLimb gGyorgLowerTrunkLimb;
77 | extern StandardLimb gGyorgTailLimb;
78 | extern StandardLimb gGyorgRightFinRootLimb;
79 | extern StandardLimb gGyorgUpperRightFinLimb;
80 | extern StandardLimb gGyorgLowerRightFinLimb;
81 | extern StandardLimb gGyorgLeftFinRootLimb;
82 | extern StandardLimb gGyorgUpperLeftFinLimb;
83 | extern StandardLimb gGyorgLowerLeftFinLimb;
84 | extern StandardLimb gGyorgJawRootLimb;
85 | extern StandardLimb gGyorgJawLimb;
86 | extern void* gGyorgSkelLimbs[];
87 | extern FlexSkeletonHeader gGyorgSkel;
88 | extern s16 sGyorgFloppingAnimFrameData[];
89 | extern JointIndex sGyorgFloppingAnimJointIndices[];
90 | extern AnimationHeader gGyorgFloppingAnim;
91 | extern s16 sGyorgJumpingAnimFrameData[];
92 | extern JointIndex sGyorgJumpingAnimJointIndices[];
93 | extern AnimationHeader gGyorgJumpingAnim;
94 | extern s16 sGyorgStunnedAnimFrameData[];
95 | extern JointIndex sGyorgStunnedAnimJointIndices[];
96 | extern AnimationHeader gGyorgStunnedAnim;
97 | extern s16 sGyorgBackingUpAnimFrameData[];
98 | extern JointIndex sGyorgBackingUpAnimJointIndices[];
99 | extern AnimationHeader gGyorgBackingUpAnim;
100 | extern s16 sGyorgFastSwimmingAnimFrameData[];
101 | extern JointIndex sGyorgFastSwimmingAnimJointIndices[];
102 | extern AnimationHeader gGyorgFastSwimmingAnim;
103 | extern s16 sGyorgGentleSwimmingAnimFrameData[];
104 | extern JointIndex sGyorgGentleSwimmingAnimJointIndices[];
105 | extern AnimationHeader gGyorgGentleSwimmingAnim;
106 | extern s16 sGyorgTailSweepAnimFrameData[];
107 | extern JointIndex sGyorgTailSweepAnimJointIndices[];
108 | extern AnimationHeader gGyorgTailSweepAnim;
109 | extern s16 sGyorgCrawlingAnimFrameData[];
110 | extern JointIndex sGyorgCrawlingAnimJointIndices[];
111 | extern AnimationHeader gGyorgCrawlingAnim;
112 | extern Vtx object_boss03Vtx_00A6E0[];
113 | extern Gfx gGyorgSeaweedPiece1DL[];
114 | extern Gfx gGyorgSeaweedPiece2DL[];
115 | extern Gfx gGyorgSeaweedPiece3DL[];
116 | extern Gfx gGyorgSeaweedPiece4DL[];
117 | extern Gfx gGyorgSeaweedPiece5DL[];
118 | extern Gfx gGyorgSeaweedTopDL[];
119 | extern u64 gGyorgSeaweedTopTLUT[];
120 | extern u64 gGyorgSeaweedTLUT[];
121 | extern u64 gGyorgSeaweedTopTex[];
122 | extern u64 gGyorgSeaweedTex[];
123 | extern AnimatedMaterial gGyorgUnusedBB00TexAnim[];
124 | extern Vtx object_boss03Vtx_00BB10[];
125 | extern Gfx gUnusedGyorgSmallFishHeadDL[];
126 | extern Gfx gUnusedGyorgSmallFishTrunkDL[];
127 | extern Gfx gUnusedGyorgSmallFishRightFinDL[];
128 | extern Gfx gUnusedGyorgSmallFishDorsalFinDL[];
129 | extern Gfx gUnusedGyorgSmallFishLeftFinDL[];
130 | extern Gfx gUnusedGyorgSmallFishTailFinDL[];
131 | extern u64 gUnusedGyorgSmallFishTLUT[];
132 | extern u64 gUnusedGyorgSmallFishTex[];
133 | extern Vtx object_boss03Vtx_00CA50[];
134 | extern Gfx gGyorgSmallFishHeadDL[];
135 | extern Gfx gGyorgSmallFishTrunkDL[];
136 | extern Gfx gGyorgSmallFishRightFinDL[];
137 | extern Gfx gGyorgSmallFishDorsalFinDL[];
138 | extern Gfx gGyorgSmallFishLeftFinDL[];
139 | extern Gfx gGyorgSmallFishTailFinDL[];
140 | extern u64 gGyorgSmallFishTLUT[];
141 | extern u64 gGyorgSmallFishTex[];
142 | extern StandardLimb gGyorgSmallFishRootLimb;
143 | extern StandardLimb gGyorgSmallFishBodyRootLimb;
144 | extern StandardLimb gGyorgSmallFishTrunkRootLimb;
145 | extern StandardLimb gGyorgSmallFishTailFinLimb;
146 | extern StandardLimb gGyorgSmallFishTrunkLimb;
147 | extern StandardLimb gGyorgSmallFishLeftFinLimb;
148 | extern StandardLimb gGyorgSmallFishDorsalFinLimb;
149 | extern StandardLimb gGyorgSmallFishRightFinLimb;
150 | extern StandardLimb gGyorgSmallFishHeadLimb;
151 | extern void* gGyorgSmallFishSkelLimbs[];
152 | extern FlexSkeletonHeader gGyorgSmallFishSkel;
153 | extern s16 sGyorgSmallFishSwimAnimFrameData[];
154 | extern JointIndex sGyorgSmallFishSwimAnimJointIndices[];
155 | extern AnimationHeader gGyorgSmallFishSwimAnim;
156 | #endif
157 |
--------------------------------------------------------------------------------
/patches/dummy_headers/objects/object_boss04/object_boss04.h:
--------------------------------------------------------------------------------
1 | // Required to include MM decomp headers without having built the repo
2 |
3 | #ifndef OBJECT_BOSS04_H
4 | #define OBJECT_BOSS04_H 1
5 |
6 | typedef enum WartLimb {
7 | /* 0x00 */ WART_LIMB_NONE,
8 | /* 0x01 */ WART_LIMB_ROOT,
9 | /* 0x02 */ WART_LIMB_BODY,
10 | /* 0x03 */ WART_LIMB_EYE_ROOT,
11 | /* 0x04 */ WART_LIMB_EYE,
12 | /* 0x05 */ WART_LIMB_TOP_EYELID_ROOT,
13 | /* 0x06 */ WART_LIMB_TOP_EYELID,
14 | /* 0x07 */ WART_LIMB_BOTTOM_EYELID_ROOT,
15 | /* 0x08 */ WART_LIMB_BOTTOM_EYELID,
16 | /* 0x09 */ WART_LIMB_MAX
17 | } WartLimb;
18 |
19 | extern s16 sWartIdleAnimFrameData[];
20 | extern JointIndex sWartIdleAnimJointIndices[];
21 | extern AnimationHeader gWartIdleAnim;
22 | extern Vtx object_boss04Vtx_000060[];
23 | extern Gfx gWartShellDL[];
24 | extern Gfx gWartBottomEyelidDL[];
25 | extern Gfx gWartTopEyelidDL[];
26 | extern Gfx gWartEyeDL[];
27 | extern u64 gWartShellTLUT[];
28 | extern u64 gWartRidgesTLUT[];
29 | extern u64 gWartShellTex[];
30 | extern u64 gWartRidgesTex[];
31 | extern u64 gWartEyeTex[];
32 | extern Vtx object_boss04Vtx_0033A8[];
33 | extern Gfx gWartBubbleOpaqueMaterialDL[];
34 | extern Gfx gWartBubbleMaterialDL[];
35 | extern Gfx gWartBubbleModelDL[];
36 | extern u64 gWartBubbleTex[];
37 | extern Vtx object_boss04Vtx_003CE0[];
38 | extern u64 gWartShadowTex[];
39 | extern Gfx gWartShadowMaterialDL[];
40 | extern Gfx gWartShadowModelDL[];
41 | extern StandardLimb gWartRootLimb;
42 | extern StandardLimb gWartBodyLimb;
43 | extern StandardLimb gWartEyeRootLimb;
44 | extern StandardLimb gWartEyeLimb;
45 | extern StandardLimb gWartTopEyelidRootLimb;
46 | extern StandardLimb gWartTopEyelidLimb;
47 | extern StandardLimb gWartBottomEyelidRootLimb;
48 | extern StandardLimb gWartBottomEyelidLimb;
49 | extern void* gWartSkelLimbs[];
50 | extern FlexSkeletonHeader gWartSkel;
51 | #endif
52 |
--------------------------------------------------------------------------------
/patches/graphics.h:
--------------------------------------------------------------------------------
1 | #ifndef __PATCH_GRAPHICS_H__
2 | #define __PATCH_GRAPHICS_H__
3 |
4 | #include "patch_helpers.h"
5 |
6 | DECLARE_FUNC(float, recomp_get_aspect_ratio, float);
7 | DECLARE_FUNC(s32, recomp_get_target_framerate, s32);
8 | DECLARE_FUNC(s32, recomp_high_precision_fb_enabled);
9 | DECLARE_FUNC(float, recomp_get_resolution_scale);
10 |
11 | #endif
12 |
--------------------------------------------------------------------------------
/patches/misc_funcs.h:
--------------------------------------------------------------------------------
1 | #ifndef __RECOMP_FUNCS_H__
2 | #define __RECOMP_FUNCS_H__
3 |
4 | #include "patch_helpers.h"
5 |
6 | DECLARE_FUNC(void, recomp_load_overlays, u32 rom, void* ram, u32 size);
7 | DECLARE_FUNC(void, recomp_puts, const char* data, u32 size);
8 | DECLARE_FUNC(void, recomp_exit);
9 |
10 | #endif
11 |
--------------------------------------------------------------------------------
/patches/patch_helpers.h:
--------------------------------------------------------------------------------
1 | #ifndef __PATCH_HELPERS_H__
2 | #define __PATCH_HELPERS_H__
3 |
4 | #ifdef MIPS
5 | #include "ultra64.h"
6 | #else
7 | #include "recomp.h"
8 | #endif
9 |
10 | #ifdef __cplusplus
11 | # define EXTERNC extern "C"
12 | #else
13 | # define EXTERNC
14 | #endif
15 |
16 | #ifdef MIPS
17 | # define DECLARE_FUNC(type, name, ...) \
18 | EXTERNC type name(__VA_ARGS__)
19 | #else // MIPS
20 | # define DECLARE_FUNC(type, name, ...) \
21 | EXTERNC void name(uint8_t* rdram, recomp_context* ctx)
22 | #endif
23 |
24 | #endif
25 |
--------------------------------------------------------------------------------
/patches/patches.h:
--------------------------------------------------------------------------------
1 | #ifndef __PATCHES_H__
2 | #define __PATCHES_H__
3 |
4 | #define RECOMP_EXPORT __attribute__((section(".recomp_export")))
5 | #define RECOMP_PATCH __attribute__((section(".recomp_patch")))
6 | #define RECOMP_FORCE_PATCH __attribute__((section(".recomp_force_patch")))
7 |
8 | // TODO fix renaming symbols in patch recompilation
9 | #define osCreateMesgQueue osCreateMesgQueue_recomp
10 | #define osRecvMesg osRecvMesg_recomp
11 | #define osSendMesg osSendMesg_recomp
12 | #define osViGetCurrentFramebuffer osViGetCurrentFramebuffer_recomp
13 | #define osFlashWriteArray osFlashWriteArray_recomp
14 | #define osFlashWriteBuffer osFlashWriteBuffer_recomp
15 | #define osWritebackDCache osWritebackDCache_recomp
16 | #define osInvalICache osInvalICache_recomp
17 | #define osGetTime osGetTime_recomp
18 |
19 | #define osContStartReadData osContStartReadData_recomp
20 | #define osContGetReadData osContGetReadData_recomp
21 | #define osContStartQuery osContStartQuery_recomp
22 | #define osContGetQuery osContGetQuery_recomp
23 |
24 | #define sinf __sinf_recomp
25 | #define cosf __cosf_recomp
26 | #define bzero bzero_recomp
27 | #define gRandFloat sRandFloat
28 | // #include "global.h"
29 | #include "PR/ultratypes.h"
30 | #include "rt64_extended_gbi.h"
31 |
32 | #ifndef gEXFillRectangle
33 | #define gEXFillRectangle(cmd, lorigin, rorigin, ulx, uly, lrx, lry) \
34 | G_EX_COMMAND2(cmd, \
35 | PARAM(RT64_EXTENDED_OPCODE, 8, 24) | PARAM(G_EX_FILLRECT_V1, 24, 0), \
36 | PARAM(lorigin, 12, 0) | PARAM(rorigin, 12, 12), \
37 | \
38 | PARAM((ulx) * 4, 16, 16) | PARAM((uly) * 4, 16, 0), \
39 | PARAM((lrx) * 4, 16, 16) | PARAM((lry) * 4, 16, 0) \
40 | )
41 | #endif
42 |
43 | #define gEXMatrixGroupNoInterpolation(cmd, push, proj, edit) \
44 | gEXMatrixGroup(cmd, G_EX_ID_IGNORE, G_EX_INTERPOLATE_SIMPLE, push, proj, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_ORDER_LINEAR, edit)
45 |
46 | #define gEXMatrixGroupInterpolateOnlyTiles(cmd, push, proj, edit) \
47 | gEXMatrixGroup(cmd, G_EX_ID_IGNORE, G_EX_INTERPOLATE_SIMPLE, push, proj, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_LINEAR, edit)
48 |
49 | #define gEXMatrixGroupDecomposedNormal(cmd, id, push, proj, edit) \
50 | gEXMatrixGroupDecomposed(cmd, id, push, proj, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_LINEAR, edit)
51 |
52 | #define gEXMatrixGroupDecomposedSkipRot(cmd, id, push, proj, edit) \
53 | gEXMatrixGroupDecomposed(cmd, id, push, proj, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_LINEAR, edit)
54 |
55 | #define gEXMatrixGroupDecomposedSkipPosRot(cmd, id, push, proj, edit) \
56 | gEXMatrixGroupDecomposed(cmd, id, push, proj, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_LINEAR, edit)
57 |
58 | #define gEXMatrixGroupDecomposedSkipAll(cmd, id, push, proj, edit) \
59 | gEXMatrixGroupDecomposed(cmd, id, push, proj, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_LINEAR, edit)
60 |
61 | #define gEXMatrixGroupDecomposedVerts(cmd, id, push, proj, edit) \
62 | gEXMatrixGroupDecomposed(cmd, id, push, proj, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_LINEAR, edit)
63 |
64 | #define gEXMatrixGroupDecomposedVertsOrderAuto(cmd, id, push, proj, edit) \
65 | gEXMatrixGroupDecomposed(cmd, id, push, proj, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_AUTO, edit)
66 |
67 |
68 | int recomp_printf(const char* fmt, ...);
69 |
70 | #define INCBIN(identifier, filename) \
71 | asm(".pushsection .rodata\n" \
72 | "\t.local " #identifier "\n" \
73 | "\t.type " #identifier ", @object\n" \
74 | "\t.balign 8\n" \
75 | #identifier ":\n" \
76 | "\t.incbin \"" filename "\"\n\n" \
77 | \
78 | "\t.balign 8\n" \
79 | "\t.popsection\n"); \
80 | extern u8 identifier[]
81 |
82 | void recomp_crash(const char* err);
83 |
84 | #endif
85 |
--------------------------------------------------------------------------------
/patches/patches.ld:
--------------------------------------------------------------------------------
1 | RAMBASE = 0x80801000; /* Used to hold any new symbols */
2 | EXTRA_RAM_SIZE = 0x01000000; /* Amount of extra ram allocated by recomp */
3 |
4 | MEMORY {
5 | extram : ORIGIN = RAMBASE, LENGTH = 64M
6 | rom : ORIGIN = 0, LENGTH = 64M
7 | }
8 |
9 | SECTIONS {
10 | .ctors : { *(.ctors*) *(.init_array*) } >extram AT >rom
11 | .dtors : { *(.dtors*) } >extram AT >rom
12 | .text : { *(.text*) } >extram AT >rom
13 | .recomp_patch : { *(.recomp_patch*) *(.recomp_force_patch*) } >extram AT >rom
14 | .recomp_export : { *(.recomp_export*) } >extram AT >rom
15 | .rodata : { *(.rodata*) } >extram AT >rom
16 | .data : { *(.data*) } >extram AT >rom
17 | .bss (NOLOAD) : { *(.bss*) *(COMMON) } >extram
18 | ASSERT(. < RAMBASE + EXTRA_RAM_SIZE, "Maxed out recomp extra ram")
19 |
20 | .reloc 0 : { *(.reloc*) }
21 | .symtab 0 : { *(.symtab) }
22 | .strtab 0 : { *(.strtab) }
23 | .shstrtab 0 : { *(.shstrtab) }
24 |
25 | /DISCARD/ : { *(*); }
26 | }
27 |
--------------------------------------------------------------------------------
/patches/print.c:
--------------------------------------------------------------------------------
1 | #include "patches.h"
2 | #include "misc_funcs.h"
3 |
4 | #define va_list __builtin_va_list
5 | #define va_start __builtin_va_start
6 | #define va_arg __builtin_va_arg
7 | #define va_end __builtin_va_end
8 |
9 | int dummyData = 1;
10 | int dummyBss;
11 |
12 | void dummyFunc(void)
13 | {
14 | return;
15 | }
16 |
17 | typedef unsigned int size_t;
18 | typedef char *outfun(char*,const char*,size_t);
19 |
20 | int _Printf(outfun prout, char *arg, const char *fmt, va_list args);
21 |
22 | char* proutPrintf(char* dst, const char* fmt, size_t size) {
23 | recomp_puts(fmt, size);
24 | return (void*)1;
25 | }
26 |
27 | int recomp_printf(const char* fmt, ...) {
28 | va_list args;
29 | va_start(args, fmt);
30 |
31 | int ret = _Printf(&proutPrintf, NULL, fmt, args);
32 |
33 | va_end(args);
34 |
35 | return ret;
36 | }
37 |
--------------------------------------------------------------------------------
/patches/sounds.h:
--------------------------------------------------------------------------------
1 | #ifndef __PATCH_AUDIO_H__
2 | #define __PATCH_AUDIO_H__
3 |
4 | #include "patch_helpers.h"
5 |
6 | DECLARE_FUNC(float, recomp_get_bgm_volume);
7 | DECLARE_FUNC(u32, recomp_get_low_health_beeps_enabled);
8 |
9 | #endif
10 |
--------------------------------------------------------------------------------
/patches/syms.ld:
--------------------------------------------------------------------------------
1 | __start = 0x80000000;
2 |
3 | /* Dummy addresses that get recompiled into function calls */
4 | recomp_puts = 0x8F000000;
5 | recomp_exit = 0x8F000004;
6 | recomp_handle_quicksave_actions = 0x8F000008;
7 | recomp_handle_quicksave_actions_main = 0x8F00000C;
8 | osRecvMesg_recomp = 0x8F000010;
9 | osSendMesg_recomp = 0x8F000014;
10 | recomp_get_gyro_deltas = 0x8F000018;
11 | recomp_get_aspect_ratio = 0x8F00001C;
12 | recomp_get_pending_warp = 0x8F000020;
13 | recomp_powf = 0x8F000024;
14 | recomp_get_target_framerate = 0x8F000028;
15 | recomp_get_targeting_mode = 0x8F00002C;
16 | recomp_get_bgm_volume = 0x8F000030;
17 | recomp_get_low_health_beeps_enabled = 0x8F000034;
18 | __sinf_recomp = 0x8F000038;
19 | __cosf_recomp = 0x8F00003C;
20 | osCreateMesgQueue_recomp = 0x8F000048;
21 | recomp_set_current_frame_poll_id = 0x8F00004C;
22 | recomp_time_us = 0x8F000050;
23 | recomp_measure_latency = 0x8F000054;
24 | osViGetCurrentFramebuffer_recomp = 0x8F000058;
25 | bzero_recomp = 0x8F00005C;
26 | osFlashWriteArray_recomp = 0x8F000060;
27 | osFlashWriteBuffer_recomp = 0x8F000064;
28 | osWritebackDCache_recomp = 0x8F000068;
29 | recomp_get_pending_set_time = 0x8F00006C;
30 | osContStartReadData_recomp = 0x8F000070;
31 | osContGetReadData_recomp = 0x8F000074;
32 | osContStartQuery_recomp = 0x8F000078;
33 | osContGetQuery_recomp = 0x8F00007C;
34 | recomp_get_mouse_deltas = 0x8F000080;
35 | bcmp_recomp = 0x8F000084;
36 | osGetTime_recomp = 0x8F000088;
37 | recomp_autosave_enabled = 0x8F00008C;
38 | recomp_load_overlays = 0x8F000090;
39 | osInvalICache_recomp = 0x8F000094;
40 | recomp_analog_cam_enabled = 0x8F000098;
41 | recomp_get_camera_inputs = 0x8F00009C;
42 | recomp_set_right_analog_suppressed = 0x8F0000A0;
43 | recomp_get_inverted_axes = 0x8F0000A4;
44 | recomp_high_precision_fb_enabled = 0x8F0000A8;
45 | recomp_get_resolution_scale = 0x8F0000AC;
46 | recomp_get_analog_inverted_axes = 0x8F0000B0;
47 | __divdi3_recomp = 0x8F0000B4;
48 | __umoddi3_recomp = 0x8F0000B8;
49 | __udivdi3_recomp = 0x8F0000BC;
--------------------------------------------------------------------------------
/patches/temp.c:
--------------------------------------------------------------------------------
1 | #include "patches.h"
2 | #include "PR/os_message.h"
3 |
4 | typedef enum pointertable_e {
5 | TABLE_00_MIDI,
6 | TABLE_01_MAP_GEOMETRY,
7 | TABLE_02_MAP_WALLS,
8 | TABLE_03_MAP_FLOORS,
9 | TABLE_04_PROP_GEOMETRY,
10 | TABLE_05_ACTOR_GEOMETRY,
11 | TABLE_06_UNUSED,
12 | TABLE_07_TEXTURES_UNCOMPRESSED,
13 | TABLE_08_CUTSCENES,
14 | TABLE_09_SETUP,
15 | TABLE_10_SCRIPTS,
16 | TABLE_11_ANIMATIONS,
17 | TABLE_12_TEXT,
18 | TABLE_13_ANIM_CODE,
19 | TABLE_14_TEXTURES_HUD,
20 | TABLE_15_PATHS,
21 | TABLE_16_SPAWNERS,
22 | TABLE_17_DKTV,
23 | TABLE_18_TRIGGERS,
24 | TABLE_19_UNKNOWN,
25 | TABLE_20_UNKNOWN,
26 | TABLE_21_AUTOWALKS,
27 | TABLE_22_CRITTERS,
28 | TABLE_23_EXITS,
29 | TABLE_24_CHECKPOINTS,
30 | TABLE_25_TEXTURES_GEOMETRY,
31 | TABLE_26_UNCOMPRESSED_SIZES,
32 | TABLE_27_UNUSED,
33 | TABLE_28_UNUSED,
34 | TABLE_29_UNUSED,
35 | TABLE_30_UNUSED,
36 | TABLE_31_UNUSED
37 | } pointertable_e;
38 |
39 | typedef struct AutowalkFile {
40 | s16 count;
41 | s16 data[];
42 | } AutowalkFile;
43 |
44 | void *getPointerTableFile(enum pointertable_e pointerTableIndex, s32 fileIndex, u8 arg2, u8 arg3);
45 | void func_global_asm_806F4528(AutowalkFile *);
46 | void func_global_asm_8066B434(void *arg0, s32 arg1, s32 arg2);
47 |
48 | RECOMP_PATCH void func_global_asm_806F3760(s16 map) {
49 | AutowalkFile *autowalkFile;
50 |
51 | autowalkFile = getPointerTableFile(TABLE_21_AUTOWALKS, map, 1, 0);
52 |
53 | recomp_printf("Autowalk File Loaded\n");
54 | recomp_printf("test count: %08X\n", autowalkFile->count);
55 |
56 | func_global_asm_806F4528(autowalkFile);
57 | if (autowalkFile) {
58 | func_global_asm_8066B434(autowalkFile, 0x4C, 0x56);
59 | }
60 | }
--------------------------------------------------------------------------------
/patches/xlitob.c:
--------------------------------------------------------------------------------
1 | #include "patches.h"
2 | #include "string.h"
3 | #include "xstdio.h"
4 |
5 | typedef struct lldiv_t
6 | {
7 | long long quot;
8 | long long rem;
9 | } lldiv_t;
10 |
11 | extern long long __divdi3_recomp(long long num, long long denom);
12 | extern unsigned long long __udivdi3_recomp(unsigned long long num, unsigned long long denom);
13 | extern unsigned long long __umoddi3_recomp(unsigned long long num, unsigned long long denom);
14 |
15 | __attribute__((noinline))
16 | lldiv_t lldiv(long long num, long long denom) {
17 | lldiv_t ret;
18 |
19 | ret.quot = __divdi3_recomp(num, denom);
20 | ret.rem = num - denom * ret.quot;
21 |
22 | if (ret.quot < 0 && ret.rem > 0) {
23 | ret.quot += 1;
24 | ret.rem -= denom;
25 | }
26 |
27 | return ret;
28 | }
29 |
30 | #define BUFF_LEN 0x18
31 |
32 | static char ldigs[] = "0123456789abcdef";
33 | static char udigs[] = "0123456789ABCDEF";
34 |
35 | inline void *my_memcpy(void *dest, const void *src, size_t n) {
36 | // Cast the void pointers to char pointers for byte-wise copying
37 | char *d = (char *)dest;
38 | const char *s = (const char *)src;
39 |
40 | // Copy n bytes from src to dest
41 | for (size_t i = 0; i < n; i++) {
42 | d[i] = s[i];
43 | }
44 |
45 | return dest; // Return the destination pointer
46 | }
47 |
48 | void _Litob(_Pft *px, char code) {
49 | char buff[BUFF_LEN];
50 | const char *digs;
51 | int base;
52 | int i;
53 | unsigned long long ullval;
54 |
55 | digs = (code == 'X') ? udigs : ldigs;
56 |
57 | base = (code == 'o') ? 8 : ((code != 'x' && code != 'X') ? 10 : 16);
58 | i = BUFF_LEN;
59 | ullval = px->v.ll;
60 |
61 | if ((code == 'd' || code == 'i') && px->v.ll < 0) {
62 | ullval = -ullval;
63 | }
64 |
65 | if (ullval != 0 || px->prec != 0) {
66 | buff[--i] = digs[__umoddi3_recomp(ullval, base)];
67 | }
68 |
69 | px->v.ll = (long long)__udivdi3_recomp(ullval, base);
70 |
71 | while (px->v.ll > 0 && i > 0) {
72 | lldiv_t qr = lldiv(px->v.ll, base);
73 | px->v.ll = qr.quot;
74 | buff[--i] = digs[qr.rem];
75 | }
76 |
77 | px->n1 = BUFF_LEN - i;
78 |
79 | // Manually copy px->n1 bytes from buff + i to px->s (mimicking memcpy)
80 | for (int j = 0; j < px->n1; j++) {
81 | px->s[j] = buff[i + j];
82 | }
83 |
84 | if (px->n1 < px->prec) {
85 | px->nz0 = px->prec - px->n1;
86 | }
87 |
88 | if (px->prec < 0 && (px->flags & (FLAGS_ZERO | FLAGS_MINUS)) == FLAGS_ZERO) {
89 | if ((i = px->width - px->n0 - px->nz0 - px->n1) > 0) {
90 | px->nz0 += i;
91 | }
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/patches/xstdio.h:
--------------------------------------------------------------------------------
1 | #ifndef _XSTDIO_H
2 | #define _XSTDIO_H
3 |
4 | #include "stdarg.h"
5 |
6 | #ifdef __sgi
7 | typedef double ldouble; // IDO does not support long doubles
8 | #else
9 | typedef long double ldouble;
10 | #endif
11 |
12 | typedef struct {
13 | /* 0x0 */ union {
14 | /* 0x0 */ long long ll;
15 | /* 0x0 */ ldouble ld;
16 | } v;
17 | /* 0x8 */ unsigned char* s;
18 | /* 0xC */ int n0;
19 | /* 0x10 */ int nz0;
20 | /* 0x14 */ int n1;
21 | /* 0x18 */ int nz1;
22 | /* 0x1C */ int n2;
23 | /* 0x20 */ int nz2;
24 | /* 0x24 */ int prec;
25 | /* 0x28 */ int width;
26 | /* 0x2C */ size_t nchar;
27 | /* 0x30 */ unsigned int flags;
28 | /* 0x34 */ char qual;
29 | } _Pft;
30 |
31 | #define FLAGS_SPACE 1
32 | #define FLAGS_PLUS 2
33 | #define FLAGS_MINUS 4
34 | #define FLAGS_HASH 8
35 | #define FLAGS_ZERO 16
36 |
37 | int _Printf(void* pfn(void*,const char*,size_t), void *arg, const char *fmt, va_list ap);
38 | void _Litob(_Pft *px, char code);
39 | void _Ldtob(_Pft* px, char code);
40 |
41 | #endif
42 |
--------------------------------------------------------------------------------
/rsp/.gitignore:
--------------------------------------------------------------------------------
1 | aspMain.cpp
2 | njpgdspMain.cpp
3 | n_aspMain.cpp
4 |
--------------------------------------------------------------------------------
/shadercache/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rainchus/Dk64-Recompiled/7d24f9bbd7f8b0931695f04a1ebb0309fd0eec75/shadercache/.gitkeep
--------------------------------------------------------------------------------
/shaders/InterfacePS.hlsl:
--------------------------------------------------------------------------------
1 | SamplerState gSampler : register(s1, space0);
2 | Texture2D gTexture : register(t2, space1);
3 |
4 | void PSMain(
5 | in float4 iColor : COLOR,
6 | in float2 iUV : TEXCOORD,
7 | out float4 oColor : SV_TARGET
8 | )
9 | {
10 | oColor = gTexture.SampleLevel(gSampler, iUV, 0) * iColor;
11 | }
12 |
--------------------------------------------------------------------------------
/shaders/InterfaceVS.hlsl:
--------------------------------------------------------------------------------
1 | struct Input {
2 | float4x4 transform;
3 | float2 translation;
4 | };
5 |
6 | [[vk::push_constant]]
7 | ConstantBuffer gInput : register(b0, space0);
8 |
9 | void VSMain(
10 | in float2 iPosition : POSITION,
11 | in float4 iColor : COLOR,
12 | in float2 iUV : TEXCOORD,
13 | out float4 oColor : COLOR,
14 | out float2 oUV : TEXCOORD,
15 | out float4 oPosition : SV_Position
16 | )
17 | {
18 | float2 translatedPos = iPosition + gInput.translation;
19 | oPosition = mul(gInput.transform, float4(translatedPos, 0, 1));
20 |
21 | oColor = iColor;
22 | oUV = iUV;
23 | }
24 |
--------------------------------------------------------------------------------
/src/game/controls.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #include "librecomp/helpers.hpp"
4 | #include "recomp_input.h"
5 | #include "ultramodern/ultramodern.hpp"
6 |
7 | // Arrays that hold the mappings for every input for keyboard and controller respectively.
8 | using input_mapping = std::array;
9 | using input_mapping_array = std::array(recomp::GameInput::COUNT)>;
10 | static input_mapping_array keyboard_input_mappings{};
11 | static input_mapping_array controller_input_mappings{};
12 |
13 | // Make the button value array, which maps a button index to its bit field.
14 | #define DEFINE_INPUT(name, value, readable) uint16_t(value##u),
15 | static const std::array n64_button_values = {
16 | DEFINE_N64_BUTTON_INPUTS()
17 | };
18 | #undef DEFINE_INPUT
19 |
20 | // Make the input name array.
21 | #define DEFINE_INPUT(name, value, readable) readable,
22 | static const std::vector input_names = {
23 | DEFINE_ALL_INPUTS()
24 | };
25 | #undef DEFINE_INPUT
26 |
27 | // Make the input enum name array.
28 | #define DEFINE_INPUT(name, value, readable) #name,
29 | static const std::vector input_enum_names = {
30 | DEFINE_ALL_INPUTS()
31 | };
32 | #undef DEFINE_INPUT
33 |
34 | size_t recomp::get_num_inputs() {
35 | return (size_t)GameInput::COUNT;
36 | }
37 |
38 | const std::string& recomp::get_input_name(GameInput input) {
39 | return input_names.at(static_cast(input));
40 | }
41 |
42 | const std::string& recomp::get_input_enum_name(GameInput input) {
43 | return input_enum_names.at(static_cast(input));
44 | }
45 |
46 | recomp::GameInput recomp::get_input_from_enum_name(const std::string_view enum_name) {
47 | auto find_it = std::find(input_enum_names.begin(), input_enum_names.end(), enum_name);
48 | if (find_it == input_enum_names.end()) {
49 | return recomp::GameInput::COUNT;
50 | }
51 |
52 | return static_cast(find_it - input_enum_names.begin());
53 | }
54 |
55 | // Due to an RmlUi limitation this can't be const. Ideally it would return a const reference or even just a straight up copy.
56 | recomp::InputField& recomp::get_input_binding(GameInput input, size_t binding_index, recomp::InputDevice device) {
57 | input_mapping_array& device_mappings = (device == recomp::InputDevice::Controller) ? controller_input_mappings : keyboard_input_mappings;
58 | input_mapping& cur_input_mapping = device_mappings.at(static_cast(input));
59 |
60 | if (binding_index < cur_input_mapping.size()) {
61 | return cur_input_mapping[binding_index];
62 | }
63 | else {
64 | static recomp::InputField dummy_field = {};
65 | return dummy_field;
66 | }
67 | }
68 |
69 | void recomp::set_input_binding(recomp::GameInput input, size_t binding_index, recomp::InputDevice device, recomp::InputField value) {
70 | input_mapping_array& device_mappings = (device == recomp::InputDevice::Controller) ? controller_input_mappings : keyboard_input_mappings;
71 | input_mapping& cur_input_mapping = device_mappings.at(static_cast(input));
72 |
73 | if (binding_index < cur_input_mapping.size()) {
74 | cur_input_mapping[binding_index] = value;
75 | }
76 | }
77 |
78 | bool recomp::get_n64_input(int controller_num, uint16_t* buttons_out, float* x_out, float* y_out) {
79 | uint16_t cur_buttons = 0;
80 | float cur_x = 0.0f;
81 | float cur_y = 0.0f;
82 |
83 | if (controller_num != 0) {
84 | return false;
85 | }
86 |
87 | if (!recomp::game_input_disabled()) {
88 | for (size_t i = 0; i < n64_button_values.size(); i++) {
89 | size_t input_index = (size_t)GameInput::N64_BUTTON_START + i;
90 | cur_buttons |= recomp::get_input_digital(keyboard_input_mappings[input_index]) ? n64_button_values[i] : 0;
91 | cur_buttons |= recomp::get_input_digital(controller_input_mappings[input_index]) ? n64_button_values[i] : 0;
92 | }
93 |
94 | float joystick_deadzone = recomp::get_joystick_deadzone() / 100.0f;
95 |
96 | float joystick_x = recomp::get_input_analog(controller_input_mappings[(size_t)GameInput::X_AXIS_POS])
97 | - recomp::get_input_analog(controller_input_mappings[(size_t)GameInput::X_AXIS_NEG]);
98 |
99 | float joystick_y = recomp::get_input_analog(controller_input_mappings[(size_t)GameInput::Y_AXIS_POS])
100 | - recomp::get_input_analog(controller_input_mappings[(size_t)GameInput::Y_AXIS_NEG]);
101 |
102 | recomp::apply_joystick_deadzone(joystick_x, joystick_y, &joystick_x, &joystick_y);
103 |
104 | cur_x = recomp::get_input_analog(keyboard_input_mappings[(size_t)GameInput::X_AXIS_POS])
105 | - recomp::get_input_analog(keyboard_input_mappings[(size_t)GameInput::X_AXIS_NEG]) + joystick_x;
106 |
107 | cur_y = recomp::get_input_analog(keyboard_input_mappings[(size_t)GameInput::Y_AXIS_POS])
108 | - recomp::get_input_analog(keyboard_input_mappings[(size_t)GameInput::Y_AXIS_NEG]) + joystick_y;
109 | }
110 |
111 | *buttons_out = cur_buttons;
112 | *x_out = std::clamp(cur_x, -1.0f, 1.0f);
113 | *y_out = std::clamp(cur_y, -1.0f, 1.0f);
114 |
115 | return true;
116 | }
117 |
--------------------------------------------------------------------------------
/src/game/debug.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include "zelda_debug.h"
3 | #include "librecomp/helpers.hpp"
4 | // #include "../patches/input.h"
5 |
6 | std::atomic pending_warp = 0xFFFF;
7 | std::atomic pending_set_time = 0xFFFF;
8 |
9 | void zelda64::do_warp(int area, int scene, int entrance) {
10 | const zelda64::SceneWarps game_scene = zelda64::game_warps[area].scenes[scene];
11 | int game_scene_index = game_scene.index;
12 | pending_warp.store(((game_scene_index & 0xFF) << 8) | ((entrance & 0x0F) << 4));
13 | }
14 |
15 | extern "C" void recomp_get_pending_warp(uint8_t* rdram, recomp_context* ctx) {
16 | // Return the current warp value and reset it.
17 | _return(ctx, pending_warp.exchange(0xFFFF));
18 | }
19 |
20 | void zelda64::set_time(uint8_t day, uint8_t hour, uint8_t minute) {
21 | pending_set_time.store((day << 16) | (uint16_t(hour) << 8) | minute);
22 | }
23 |
24 | extern "C" void recomp_get_pending_set_time(uint8_t* rdram, recomp_context* ctx) {
25 | // Return the current set time value and reset it.
26 | _return(ctx, pending_set_time.exchange(0xFFFF));
27 | }
28 |
--------------------------------------------------------------------------------
/src/game/quicksaving.cpp:
--------------------------------------------------------------------------------
1 | // Quicksaving is disabled for now
2 |
3 | #if 0
4 |
5 | #include "librecomp/helpers.hpp"
6 | #include "librecomp/input.hpp"
7 | #include "ultramodern/ultramodern.hpp"
8 |
9 | enum class QuicksaveAction {
10 | None,
11 | Save,
12 | Load
13 | };
14 |
15 | std::atomic cur_quicksave_action = QuicksaveAction::None;
16 |
17 | void zelda64::quicksave_save() {
18 | cur_quicksave_action.store(QuicksaveAction::Save);
19 | }
20 |
21 | void zelda64::quicksave_load() {
22 | cur_quicksave_action.store(QuicksaveAction::Load);
23 | }
24 |
25 | uint8_t saved_rdram[ultramodern::rdram_size];
26 |
27 | thread_local recomp_context saved_context;
28 |
29 | void save_context(recomp_context* ctx) {
30 | saved_context = *ctx;
31 | }
32 |
33 | void load_context(recomp_context* ctx) {
34 | *ctx = saved_context;
35 |
36 | // Restore the pointer to the odd floats for correctly handling mips3 float mode.
37 | if (ctx->mips3_float_mode) {
38 | // FR = 1, odd single floats point to their own registers
39 | ctx->f_odd = &ctx->f1.u32l;
40 | }
41 | else {
42 | // FR = 0, odd single floats point to the upper half of the previous register
43 | ctx->f_odd = &ctx->f0.u32h;
44 | }
45 | }
46 |
47 | extern "C" void recomp_handle_quicksave_actions(uint8_t* rdram, recomp_context* ctx) {
48 | QuicksaveAction action = cur_quicksave_action.load();
49 |
50 | if (action != QuicksaveAction::None) {
51 | PTR(OSMesgQueue) quicksave_enter_mq = _arg<0, PTR(OSMesgQueue)>(rdram, ctx);
52 | PTR(OSMesgQueue) quicksave_exit_mq = _arg<1, PTR(OSMesgQueue)>(rdram, ctx);
53 |
54 | printf("saving context for thread %d\n", TO_PTR(OSThread, ultramodern::this_thread())->id);
55 |
56 | // Save or load the thread's context as needed based on the action.
57 | if (action == QuicksaveAction::Save) {
58 | save_context(ctx);
59 | }
60 | else if (action == QuicksaveAction::Load) {
61 | load_context(ctx);
62 | }
63 | else {
64 | assert(false);
65 | }
66 |
67 | // Tell the main thread that one of the other permanent threads is ready for performing a quicksave action.
68 | osSendMesg(rdram, quicksave_enter_mq, NULLPTR, OS_MESG_NOBLOCK);
69 | // Wait for the main thread to signal that other permanent threads are safe to continue.
70 | osRecvMesg(rdram, quicksave_exit_mq, NULLPTR, OS_MESG_BLOCK);
71 | }
72 | }
73 |
74 | extern "C" void wake_threads_for_quicksave_action(uint8_t* rdram, recomp_context* ctx);
75 |
76 | extern "C" void recomp_handle_quicksave_actions_main(uint8_t* rdram, recomp_context* ctx) {
77 | QuicksaveAction action = cur_quicksave_action.load();
78 |
79 | if (action != QuicksaveAction::None) {
80 | PTR(OSMesgQueue) quicksave_enter_mq = _arg<0, PTR(OSMesgQueue)>(rdram, ctx);
81 | PTR(OSMesgQueue) quicksave_exit_mq = _arg<1, PTR(OSMesgQueue)>(rdram, ctx);
82 |
83 | wake_threads_for_quicksave_action(rdram, ctx);
84 |
85 | // Wait for all other permanent threads (hence the minus 1) to signal that they're ready for a quicksave action.
86 | for (uint32_t i = 0; i < ultramodern::permanent_thread_count() - 1; i++) {
87 | osRecvMesg(rdram, quicksave_enter_mq, NULLPTR, OS_MESG_BLOCK);
88 | }
89 |
90 | // Allow any temporary threads to complete by lowering this thread's priority to 0.
91 | // TODO this won't cause all temporary threads to complete if any are blocked by permanent threads
92 | // or events like timers. Situations like that will need to be handed on a case-by-case basis for a given game.
93 | if (ultramodern::temporary_thread_count() != 0) {
94 | OSPri old_pri = osGetThreadPri(rdram, NULLPTR);
95 | osSetThreadPri(rdram, NULLPTR, 0);
96 |
97 | osSetThreadPri(rdram, NULLPTR, old_pri);
98 | }
99 |
100 | if (action == QuicksaveAction::Save) {
101 | std::copy(rdram, rdram + ultramodern::rdram_size, saved_rdram);
102 | }
103 | else if (action == QuicksaveAction::Load) {
104 | std::copy(saved_rdram, saved_rdram + ultramodern::rdram_size, rdram);
105 | }
106 | else {
107 | assert(false);
108 | }
109 |
110 | printf("Quicksave action complete\n");
111 |
112 | cur_quicksave_action.store(QuicksaveAction::None);
113 |
114 | // Tell all other permanent threads that they're good to continue.
115 | for (uint32_t i = 0; i < ultramodern::permanent_thread_count() - 1; i++) {
116 | osSendMesg(rdram, quicksave_exit_mq, NULLPTR, OS_MESG_BLOCK);
117 | }
118 | }
119 | }
120 |
121 | #endif
122 |
--------------------------------------------------------------------------------
/src/main/register_overlays.cpp:
--------------------------------------------------------------------------------
1 | #include "ovl_patches.hpp"
2 | #include "../../RecompiledFuncs/recomp_overlays.inl"
3 |
4 | #include "librecomp/overlays.hpp"
5 |
6 | void zelda64::register_overlays() {
7 | recomp::overlays::overlay_section_table_data_t sections {
8 | .code_sections = section_table,
9 | .num_code_sections = ARRLEN(section_table),
10 | .total_num_sections = num_sections,
11 | };
12 |
13 | recomp::overlays::overlays_by_index_t overlays {
14 | .table = overlay_sections_by_index,
15 | .len = ARRLEN(overlay_sections_by_index),
16 | };
17 |
18 | recomp::overlays::register_overlays(sections, overlays);
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/register_patches.cpp:
--------------------------------------------------------------------------------
1 | #include "ovl_patches.hpp"
2 | #include "../../RecompiledPatches/patches_bin.h"
3 | #include "../../RecompiledPatches/recomp_overlays.inl"
4 |
5 | #include "librecomp/overlays.hpp"
6 | #include "librecomp/game.hpp"
7 |
8 | void zelda64::register_patches() {
9 | recomp::overlays::register_patches(mm_patches_bin, sizeof(mm_patches_bin), section_table, ARRLEN(section_table));
10 | }
11 |
--------------------------------------------------------------------------------
/src/ui/ui_color_hack.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include "RmlUi/Core.h"
3 | #include "RmlUi/../../Source/Core/PropertyParserColour.h"
4 | #include "recomp_ui.h"
5 | #include
6 |
7 | using ColourMap = Rml::UnorderedMap;
8 |
9 | namespace recompui {
10 | class PropertyParserColorHack : public Rml::PropertyParser {
11 | public:
12 | PropertyParserColorHack();
13 | virtual ~PropertyParserColorHack();
14 | bool ParseValue(Rml::Property& property, const Rml::String& value, const Rml::ParameterMap& /*parameters*/) const override;
15 | private:
16 | static ColourMap html_colours;
17 | };
18 | static_assert(sizeof(PropertyParserColorHack) == sizeof(Rml::PropertyParserColour));
19 | PropertyParserColorHack::PropertyParserColorHack() {
20 | html_colours["black"] = Rml::Colourb(0, 0, 0);
21 | html_colours["silver"] = Rml::Colourb(192, 192, 192);
22 | html_colours["gray"] = Rml::Colourb(128, 128, 128);
23 | html_colours["grey"] = Rml::Colourb(128, 128, 128);
24 | html_colours["white"] = Rml::Colourb(255, 255, 255);
25 | html_colours["maroon"] = Rml::Colourb(128, 0, 0);
26 | html_colours["red"] = Rml::Colourb(255, 0, 0);
27 | html_colours["orange"] = Rml::Colourb(255, 165, 0);
28 | html_colours["purple"] = Rml::Colourb(128, 0, 128);
29 | html_colours["fuchsia"] = Rml::Colourb(255, 0, 255);
30 | html_colours["green"] = Rml::Colourb(0, 128, 0);
31 | html_colours["lime"] = Rml::Colourb(0, 255, 0);
32 | html_colours["olive"] = Rml::Colourb(128, 128, 0);
33 | html_colours["yellow"] = Rml::Colourb(255, 255, 0);
34 | html_colours["navy"] = Rml::Colourb(0, 0, 128);
35 | html_colours["blue"] = Rml::Colourb(0, 0, 255);
36 | html_colours["teal"] = Rml::Colourb(0, 128, 128);
37 | html_colours["aqua"] = Rml::Colourb(0, 255, 255);
38 | html_colours["transparent"] = Rml::Colourb(0, 0, 0, 0);
39 | html_colours["whitesmoke"] = Rml::Colourb(245, 245, 245);
40 | }
41 |
42 | PropertyParserColorHack::~PropertyParserColorHack() {}
43 |
44 | bool PropertyParserColorHack::ParseValue(Rml::Property& property, const Rml::String& value, const Rml::ParameterMap& /*parameters*/) const {
45 | if (value.empty())
46 | return false;
47 |
48 | Rml::Colourb colour;
49 |
50 | // Check for a hex colour.
51 | if (value[0] == '#')
52 | {
53 | char hex_values[4][2] = { {'f', 'f'}, {'f', 'f'}, {'f', 'f'}, {'f', 'f'} };
54 |
55 | switch (value.size())
56 | {
57 | // Single hex digit per channel, RGB and alpha.
58 | case 5:
59 | hex_values[3][0] = hex_values[3][1] = value[4];
60 | //-fallthrough
61 | // Single hex digit per channel, RGB only.
62 | case 4:
63 | hex_values[0][0] = hex_values[0][1] = value[1];
64 | hex_values[1][0] = hex_values[1][1] = value[2];
65 | hex_values[2][0] = hex_values[2][1] = value[3];
66 | break;
67 |
68 | // Two hex digits per channel, RGB and alpha.
69 | case 9:
70 | hex_values[3][0] = value[7];
71 | hex_values[3][1] = value[8];
72 | //-fallthrough
73 | // Two hex digits per channel, RGB only.
74 | case 7: memcpy(hex_values, &value.c_str()[1], sizeof(char) * 6); break;
75 |
76 | default: return false;
77 | }
78 |
79 | // Parse each of the colour elements.
80 | for (int i = 0; i < 4; i++)
81 | {
82 | int tens = Rml::Math::HexToDecimal(hex_values[i][0]);
83 | int ones = Rml::Math::HexToDecimal(hex_values[i][1]);
84 | if (tens == -1 || ones == -1)
85 | return false;
86 |
87 | colour[i] = (Rml::byte)(tens * 16 + ones);
88 | }
89 | }
90 | else if (value.substr(0, 3) == "rgb")
91 | {
92 | Rml::StringList values;
93 | values.reserve(4);
94 |
95 | size_t find = value.find('(');
96 | if (find == Rml::String::npos)
97 | return false;
98 |
99 | size_t begin_values = find + 1;
100 |
101 | Rml::StringUtilities::ExpandString(values, value.substr(begin_values, value.rfind(')') - begin_values), ',');
102 |
103 | // Check if we're parsing an 'rgba' or 'rgb' colour declaration.
104 | if (value.size() > 3 && value[3] == 'a')
105 | {
106 | if (values.size() != 4)
107 | return false;
108 | }
109 | else
110 | {
111 | if (values.size() != 3)
112 | return false;
113 |
114 | values.push_back("255");
115 | }
116 |
117 | // Parse the three RGB values.
118 | for (int i = 0; i < 3; ++i)
119 | {
120 | int component;
121 |
122 | // We're parsing a percentage value.
123 | if (values[i].size() > 0 && values[i][values[i].size() - 1] == '%')
124 | component = int((float)atof(values[i].substr(0, values[i].size() - 1).c_str()) * (255.0f / 100.0f));
125 | // We're parsing a 0 -> 255 integer value.
126 | else
127 | component = atoi(values[i].c_str());
128 |
129 | colour[i] = (Rml::byte)(Rml::Math::Clamp(component, 0, 255));
130 | }
131 | // Parse the alpha value. Modified from the original RmlUi implementation to use 0-1 instead of 0-255.
132 | {
133 | int component;
134 |
135 | // We're parsing a percentage value.
136 | if (values[3].size() > 0 && values[3][values[3].size() - 1] == '%')
137 | component = ((float)atof(values[3].substr(0, values[3].size() - 1).c_str()) * (255.0f / 100.0f));
138 | // We're parsing a 0 -> 1 float value.
139 | else
140 | component = atof(values[3].c_str()) * 255.0f;
141 |
142 | colour[3] = (Rml::byte)(Rml::Math::Clamp(component, 0, 255));
143 | }
144 | }
145 | else
146 | {
147 | // Check for the specification of an HTML colour.
148 | ColourMap::const_iterator iterator = html_colours.find(Rml::StringUtilities::ToLower(value));
149 | if (iterator == html_colours.end())
150 | return false;
151 | else
152 | colour = (*iterator).second;
153 | }
154 |
155 | property.value = Rml::Variant(colour);
156 | property.unit = Rml::Unit::COLOUR;
157 |
158 | return true;
159 | }
160 |
161 | // This hack overwrites the contents of a property parser pointer for "color" (which is known to point to a valid Rml::PropertyParserColour) with the contents of a PropertyParserColorHack.
162 | // This overwrites the object's vtable, allowing us to override color parsing behavior to use 0-1 alpha instead of 0-255.
163 | // Ideally we'd just replace the pointer itself, but RmlUi doesn't provide a way to do that currently.
164 | void apply_color_hack() {
165 | // Allocate and leak a parser to act as a vtable source.
166 | PropertyParserColorHack* new_parser = new PropertyParserColorHack();
167 | // Copy the allocated object into the color parser pointer to overwrite its vtable.
168 | memcpy((void*)Rml::StyleSheetSpecification::GetParser("color"), (void*)new_parser, sizeof(*new_parser));
169 | }
170 |
171 | ColourMap PropertyParserColorHack::html_colours{};
172 | }
173 |
--------------------------------------------------------------------------------
/src/ui/ui_launcher.cpp:
--------------------------------------------------------------------------------
1 | #include "recomp_ui.h"
2 | #include "zelda_config.h"
3 | #include "librecomp/game.hpp"
4 | #include "ultramodern/ultramodern.hpp"
5 | #include "RmlUi/Core.h"
6 | #include "nfd.h"
7 | #include
8 |
9 | std::string version_number = "v1.1.1";
10 |
11 | Rml::DataModelHandle model_handle;
12 | bool mm_rom_valid = false;
13 |
14 | extern std::vector supported_games;
15 |
16 | void select_rom() {
17 | nfdnchar_t* native_path = nullptr;
18 | nfdresult_t result = NFD_OpenDialogN(&native_path, nullptr, 0, nullptr);
19 |
20 | if (result == NFD_OKAY) {
21 | std::filesystem::path path{native_path};
22 |
23 | NFD_FreePathN(native_path);
24 | native_path = nullptr;
25 |
26 | recomp::RomValidationError rom_error = recomp::select_rom(path, supported_games[0].game_id);
27 | switch (rom_error) {
28 | case recomp::RomValidationError::Good:
29 | mm_rom_valid = true;
30 | model_handle.DirtyVariable("mm_rom_valid");
31 | break;
32 | case recomp::RomValidationError::FailedToOpen:
33 | recompui::message_box("Failed to open ROM file.");
34 | break;
35 | case recomp::RomValidationError::NotARom:
36 | recompui::message_box("This is not a valid ROM file.");
37 | break;
38 | case recomp::RomValidationError::IncorrectRom:
39 | recompui::message_box("This ROM is not the correct game.");
40 | break;
41 | case recomp::RomValidationError::NotYet:
42 | recompui::message_box("This game isn't supported yet.");
43 | break;
44 | case recomp::RomValidationError::IncorrectVersion:
45 | recompui::message_box(
46 | "This ROM is the correct game, but the wrong version.\nThis project requires the NTSC-U N64 version of the game.");
47 | break;
48 | case recomp::RomValidationError::OtherError:
49 | recompui::message_box("An unknown error has occurred.");
50 | break;
51 | }
52 | }
53 | }
54 |
55 | class LauncherMenu : public recompui::MenuController {
56 | public:
57 | LauncherMenu() {
58 | mm_rom_valid = recomp::is_rom_valid(supported_games[0].game_id);
59 | }
60 | ~LauncherMenu() override {
61 |
62 | }
63 | Rml::ElementDocument* load_document(Rml::Context* context) override {
64 | return context->LoadDocument("assets/launcher.rml");
65 | }
66 | void register_events(recompui::UiEventListenerInstancer& listener) override {
67 | recompui::register_event(listener, "select_rom",
68 | [](const std::string& param, Rml::Event& event) {
69 | select_rom();
70 | }
71 | );
72 | recompui::register_event(listener, "rom_selected",
73 | [](const std::string& param, Rml::Event& event) {
74 | mm_rom_valid = true;
75 | model_handle.DirtyVariable("mm_rom_valid");
76 | }
77 | );
78 | recompui::register_event(listener, "start_game",
79 | [](const std::string& param, Rml::Event& event) {
80 | recomp::start_game(supported_games[0].game_id);
81 | recompui::set_current_menu(recompui::Menu::None);
82 | }
83 | );
84 | recompui::register_event(listener, "open_controls",
85 | [](const std::string& param, Rml::Event& event) {
86 | recompui::set_current_menu(recompui::Menu::Config);
87 | recompui::set_config_submenu(recompui::ConfigSubmenu::Controls);
88 | }
89 | );
90 | recompui::register_event(listener, "open_settings",
91 | [](const std::string& param, Rml::Event& event) {
92 | recompui::set_current_menu(recompui::Menu::Config);
93 | recompui::set_config_submenu(recompui::ConfigSubmenu::General);
94 | }
95 | );
96 | recompui::register_event(listener, "exit_game",
97 | [](const std::string& param, Rml::Event& event) {
98 | ultramodern::quit();
99 | }
100 | );
101 | }
102 | void make_bindings(Rml::Context* context) override {
103 | Rml::DataModelConstructor constructor = context->CreateDataModel("launcher_model");
104 |
105 | constructor.Bind("mm_rom_valid", &mm_rom_valid);
106 | constructor.Bind("version_number", &version_number);
107 |
108 | model_handle = constructor.GetModelHandle();
109 | }
110 | };
111 |
112 | std::unique_ptr recompui::create_launcher_menu() {
113 | return std::make_unique();
114 | }
115 |
--------------------------------------------------------------------------------
/src/ui/ui_rml_hacks.cpp:
--------------------------------------------------------------------------------
1 | #include "recomp_ui.h"
2 | #include "RmlUi/Core.h"
3 | #include "ui_rml_hacks.hpp"
4 |
5 | //! these are hidden methods not exposed by RmlUi
6 | //! they may need to be updated eventually with RmlUi
7 |
8 | RecompRml::CanFocus RecompRml::CanFocusElement(Rml::Element* element)
9 | {
10 | if (!element->IsVisible())
11 | return RecompRml::CanFocus::NoAndNoChildren;
12 |
13 | const Rml::ComputedValues& computed = element->GetComputedValues();
14 |
15 | if (computed.focus() == Rml::Style::Focus::None)
16 | return RecompRml::CanFocus::NoAndNoChildren;
17 |
18 | if (computed.tab_index() == Rml::Style::TabIndex::Auto)
19 | return RecompRml::CanFocus::Yes;
20 |
21 | return RecompRml::CanFocus::No;
22 | }
23 |
24 | Rml::Element* SearchFocusSubtree(Rml::Element* element, bool forward)
25 | {
26 | auto can_focus = RecompRml::CanFocusElement(element);
27 | if (can_focus == RecompRml::CanFocus::Yes)
28 | return element;
29 | else if (can_focus == RecompRml::CanFocus::NoAndNoChildren)
30 | return nullptr;
31 |
32 | for (int i = 0; i < element->GetNumChildren(); i++)
33 | {
34 | int child_index = i;
35 | if (!forward)
36 | child_index = element->GetNumChildren() - i - 1;
37 | if (Rml::Element* result = SearchFocusSubtree(element->GetChild(child_index), forward))
38 | return result;
39 | }
40 |
41 | return nullptr;
42 | }
43 |
44 | Rml::Element* RecompRml::FindNextTabElement(Rml::Element* current_element, bool forward)
45 | {
46 | // This algorithm is quite sneaky, I originally thought a depth first search would work, but it appears not. What is
47 | // required is to cut the tree in half along the nodes from current_element up the root and then either traverse the
48 | // tree in a clockwise or anticlock wise direction depending if you're searching forward or backward respectively.
49 |
50 | // If we're searching forward, check the immediate children of this node first off.
51 | if (forward)
52 | {
53 | for (int i = 0; i < current_element->GetNumChildren(); i++)
54 | if (Rml::Element* result = SearchFocusSubtree(current_element->GetChild(i), forward))
55 | return result;
56 | }
57 |
58 | // Now walk up the tree, testing either the bottom or top
59 | // of the tree, depending on whether we're going forward
60 | // or backward respectively.
61 | bool search_enabled = false;
62 | Rml::Element* document = current_element->GetOwnerDocument();
63 | Rml::Element* child = current_element;
64 | Rml::Element* parent = current_element->GetParentNode();
65 | while (child != document)
66 | {
67 | const int num_children = parent->GetNumChildren();
68 | for (int i = 0; i < num_children; i++)
69 | {
70 | // Calculate index into children
71 | const int child_index = forward ? i : (num_children - i - 1);
72 | Rml::Element* search_child = parent->GetChild(child_index);
73 |
74 | // Do a search if its enabled
75 | if (search_enabled)
76 | if (Rml::Element* result = SearchFocusSubtree(search_child, forward))
77 | return result;
78 |
79 | // Enable searching when we reach the child.
80 | if (search_child == child)
81 | search_enabled = true;
82 | }
83 |
84 | // Advance up the tree
85 | child = parent;
86 | parent = parent->GetParentNode();
87 | search_enabled = false;
88 | }
89 |
90 | // We could not find anything to focus along this direction.
91 |
92 | // If we can focus the document, then focus that now.
93 | if (current_element != document && RecompRml::CanFocusElement(document) == RecompRml::CanFocus::Yes)
94 | return document;
95 |
96 | // Otherwise, search the entire document tree. This way we will wrap around.
97 | const int num_children = document->GetNumChildren();
98 | for (int i = 0; i < num_children; i++)
99 | {
100 | const int child_index = forward ? i : (num_children - i - 1);
101 | if (Rml::Element* result = SearchFocusSubtree(document->GetChild(child_index), forward))
102 | return result;
103 | }
104 |
105 | return nullptr;
106 | }
107 |
--------------------------------------------------------------------------------
/src/ui/ui_rml_hacks.hpp:
--------------------------------------------------------------------------------
1 | #ifndef UI_RML_HACKS_H
2 | #define UI_RML_HACKS_H
3 |
4 | #include "RmlUi/Core.h"
5 | namespace RecompRml {
6 | Rml::Element* FindNextTabElement(Rml::Element* current_element, bool forward);
7 |
8 | enum class CanFocus { Yes, No, NoAndNoChildren };
9 |
10 | CanFocus CanFocusElement(Rml::Element* element);
11 | }
12 |
13 | #endif
14 |
--------------------------------------------------------------------------------