Skip to content
myuu-151Public

About

Switch/Vita engine with desktop editor and one-click ROM packaging

Resources

Stars

10 stars

Watchers

0 watching

Forks

Repository files navigation

Affinity Logo

Affinity Engine

PS Vita & Nintendo Switch 3D engine with a Windows desktop editor.

This project is in active development. Features and APIs may change.


Features

  • Desktop editor (ImGui/OpenGL) — scene, meshes, skybox, elements/HUD, effects, and node tabs; hardware-rendered 3D viewport with console-parity shading (the per-rig Shadow Intensity slider drives the editor preview and bakes into the export, so what you see is what the console renders).
  • Visual scripting — 370 nodes (full reference) compiled to plain C at export; every gameplay system (movement, camera, combat, throws, lock-on, HUD, sound, effects) is node-driven with tunable pins.
  • Skeletal animation — glTF rigs with per-clip speed, bone-attached models/sprites, camera-light + smooth/flat shading, analog-scaled walk playback.
  • Navmesh AI — Recast/Detour baked at export; wander/follow NPC navigation with per-NPC tunables.
  • Two console targets from one editor: PS Vita (.vpk, vitaGL) and Nintendo Switch (.nro, libnx + GLES1.1) — pick in the menu bar, hit Export.

Getting Started

Prerequisites

  • Windows 10/11
  • Visual Studio 2022+ (MSVC C++17)
  • CMake 3.16+
  • Visual C++ Redistributable (required to run pre-built releases — download)

Building for PS Vita needs the VitaSDK toolchain — see Build for PS Vita. Building for Nintendo Switch needs devkitPro — see Build for Nintendo Switch.

Build the Editor

git clone https://github.com/myuu-151/Affinity.git
cd Affinity
cmake -S . -B build
cmake --build build --config Release

Run the editor:

build\Release\AffinityEditor.exe

Build for PS Vita

Click to expand — VitaSDK toolchain, export → build, and running in Vita3K.

PS Vita packaging uses VitaSDK, invoked through the devkitPro MSYS2 shell (CMake + make).

Toolchain — install VitaSDK to C:\vitasdk by following vitasdk.org (the vdpm bootstrap). The editor expects VITASDK=/c/vitasdk.

Build — in the editor, click Export. It exports the PSV data headers (psv_mapdata.h, psv_rig.h, psv_sprites.h, psv_hud.h, …) and runs cmake .. && make in psv_runtime/build. Output:

psv_runtime/build/affinity_psv.vpk

Install it on a real Vita with VitaShell, or run it in Vita3K.

Run in Vita3K

The runtime is already built with the Vita3K-support flags enabled, so the .vpk runs in the emulator — but Vita3K needs the PS Vita shader compiler library libshacccg.suprx first, or every game (including this one) fails to render with a shader/gxm error.

  1. Get libshacccg.suprx. It's a Sony firmware module, so it isn't redistributable — dump it from your own PS Vita. The easiest way is the FAGDec tool (or Vita3K's own Shader compiler guide), which extracts libshacccg.suprx from your console's firmware.

  2. Drop it here (create the data folder if it doesn't exist):

    C:\Users\<you>\AppData\Roaming\Vita3K\Vita3K\ur0\data\libshacccg.suprx
    

    On Vita3K this ur0:/data/ lives under %APPDATA%\Vita3K\Vita3K\ur0\data\. The file is ~1.7 MB. Restart Vita3K after adding it.

  3. Install the game — in Vita3K, drag affinity_psv.vpk onto the window (or File ▸ Install .vpk), then launch it from the app list.

Manual build
# devkitPro MSYS2 shell, after exporting the PSV headers from the editor
export VITASDK=/c/vitasdk
export PATH="$VITASDK/bin:$PATH"
cd psv_runtime && mkdir -p build && cd build
cmake .. && make

Build for Nintendo Switch

Click to expand — devkitPro toolchain, export → build, and running on a modded Switch.

The Switch runtime (switch_runtime/) is a fork of the PS Vita runtime on libnx + EGL + OpenGL ES 1.1 (fixed-function, via mesa/nouveau). It consumes the same exported data headers as the Vita build — one export feeds both consoles.

Toolchain — install devkitPro with the Switch packages, then add the GL stack:

# devkitPro MSYS2 shell
dkp-pacman -S switch-dev switch-mesa switch-glad

Build — in the editor's Build menu, set Target: Switch (nro) and click Build. It exports the data headers into switch_runtime/include/ and runs make through devkitPro, with the live compile terminal. Output:

switch_runtime/affinity_switch.nro

Success dialog ▸ Open Folder reveals the nro.

Run on hardware (modded Switch)

  1. Copy affinity_switch.nro to the SD card at sdmc:/switch/ (any subfolder works; FTP via ftpd or a card reader).
  2. Boot CFW and open the Homebrew Menu in application mode — hold R while launching any installed game. (The Album icon opens hbmenu in applet mode with limited memory; GL homebrew can fail there.)
  3. Launch Affinity (Switch).

It also runs in Ryujinx (drag the .nro onto the window) — on Intel iGPUs prefer the OpenGL backend.

Controls map positionally from the Vita layout: B/A/Y/X = Cross/Circle/Square/Triangle, L/R = L1/R1, ZL/ZR = L2/R2, Plus = Start, Minus = Select.

Manual build
# devkitPro MSYS2 shell, after exporting the data headers from the editor
export DEVKITPRO=/opt/devkitpro
cd switch_runtime && make -j$(nproc)

Local AI Assistant

Click to expand — offline LLM assistant: setup, models, instruction vs. reasoning, and GPU acceleration.

A built-in chat assistant (View ▸ Assistant) powered by a local LLM via embedded llama.cpp — it runs entirely on your machine, no internet, no API keys, nothing leaves your PC.

It's grounded in the editor's actual node catalog (every node, its type, and its pins), so it can:

  • Answer how to set things up — "which nodes make the player jump?", "how do I do a lock-on camera?"
  • Generate node graphs — "build a graph: on Circle held, freeze the player and play a skel anim" — then one-click insert the result straight into the open blueprint (placed and pre-selected so you can drag it into place).

Setup

The model isn't bundled (it's large and separately licensed) — download any GGUF chat model and drop it in a models/ folder at the repo root. A small coder model works best for node generation:

  1. Get a GGUF from bartowski on Hugging Face — e.g. Qwen2.5-Coder-3B-Instruct-GGUF (grab a *Q4_K_M.gguf; the 3B is light on CPU, the 7B is sharper if you have the RAM/GPU).
  2. Put it in models/ (e.g. models/Qwen2.5-Coder-3B-Instruct-Q4_K_M.gguf). The editor auto-detects the first .gguf there.
  3. Open View ▸ Assistant, click Load (first load digests the node catalog once — give it a moment on CPU), then chat once it says Loaded … (ready).

CPU-only by default. It caches the node catalog after the first load so replies stay fast. The panel's Settings button picks compute: CPU 50% / 75% (share of cores) or GPU 50% / 75% / 100% (share of layers offloaded).

Instruction vs. reasoning models

Two kinds of GGUF work here, and they suit different jobs — you load one at a time, and switching is just a Load of the other file:

  • Instruction models (e.g. Qwen2.5-Coder-Instruct, 3B / 7B / 14B) answer directly. Fast, and the right default for everyday building and edits — bigger = sharper on complex graphs.
  • Reasoning models (e.g. DeepSeek-R1-Distill-Qwen-14B) think through the problem first — a long internal chain-of-thought — before answering. Slower, but they hold large, interdependent graphs together much better. Reach for one when an instruction model keeps fumbling a big (100+ node) graph.

The Constrain output (grammar) toggle works with both: it's lazy, so a reasoning model can do its full thinking pass and only the final graph is locked to valid syntax (real node types, params, clip names) — plain Q&A and prose stay free, so you can leave it on. Auto-repair (also in Settings) then lints the result and re-prompts the model to fix any broken links / pins.

Reasoning models generate a lot of think-tokens, so give them room: bump Settings ▸ Context to 32K if your VRAM allows. (A 14B at 32K won't fully fit a 16 GB GPU — keep 16K, or use a smaller quant, if it spills to CPU and slows down.)

GPU acceleration (optional)

GPU offload only does something if llama.cpp is built with a GPU backend (the default build is CPU-only). On a machine with the toolkit installed, enable one at configure time — then the Settings ▸ GPU options run on the GPU (a full 7B fits in ~5 GB VRAM, a 14B in ~11 GB, running ~20–50× faster than CPU):

cmake -B build -S . -DAFFINITY_LLM_CUDA=ON      # NVIDIA — needs the CUDA Toolkit
# or
cmake -B build -S . -DAFFINITY_LLM_VULKAN=ON    # any GPU — needs the Vulkan SDK
cmake --build build --config Release

Once built, open View ▸ Assistant ▸ Settings, choose GPU 100% (full offload), and pick your card in the GPU device dropdown. The choice is saved to assistant_prefs.ini and restored on the next launch.

Vulkan build, step by step (Windows)

Vulkan works on any modern GPU (NVIDIA/AMD/Intel) and needs no CUDA Toolkit — it's the quickest path on an NVIDIA card if you don't already have CUDA installed.

  1. Install the Vulkan SDK (LunarG). Your GPU driver already ships the runtime; the SDK provides the build-time headers + glslc.
  2. Configure with the Visual Studio generator and the Vulkan flag:
    cmake -B build -S . -G "Visual Studio 17 2022" -A x64 -DAFFINITY_LLM_VULKAN=ON
  3. If configure fails with Could not find ... SPIRV-Headers (older SDKs, e.g. 1.3.275, don't ship its CMake package), install the header-only package and point CMake at it — no SDK re-download needed:
    git clone --depth 1 https://github.com/KhronosGroup/SPIRV-Headers.git
    cmake -S SPIRV-Headers -B SPIRV-Headers/build -DCMAKE_INSTALL_PREFIX=SPIRV-Headers/out
    cmake --build SPIRV-Headers/build --target install
    # then re-run configure, adding:
    #   -DSPIRV-Headers_DIR=<abs path>/SPIRV-Headers/out/share/cmake/SPIRV-Headers
    (Or just update to a newer Vulkan SDK, which bundles the SPIRV-Headers CMake package.)
  4. Build:
    cmake --build build --config Release --target AffinityEditor

To confirm offload is working, load a model with GPU 100% set and watch dedicated VRAM rise in Task Manager (or nvidia-smi) — a 14B should put ~10–11 GB on the card.


Controls

Editor

Key Action
W / S Move forward / back
A / D Rotate left / right
Q / E Camera height down / up
I / K Pitch up / down
G Grab (translate) selected object
S Scale selected object
X / Y / Z Constrain to axis (during grab)
R + drag Resize selected object
Delete Delete selected object
Right-click Place new object in viewport
Ctrl+A Select all nodes
Ctrl+C / V Copy / paste nodes (works across projects)
Ctrl+Z Undo delete

Nodes

Key Action
Space Add node at cursor
Right-click Add node / node properties
Delete Delete selected nodes
Ctrl+A Select all nodes
Ctrl+C / V Copy / paste nodes (works across projects)
Ctrl+Z Undo delete
Ctrl+G Group selected nodes
Ctrl+Shift+G Ungroup selected group
Alt + click Create annotation
Double-click Enter group node
Escape Exit group
Scroll wheel Zoom canvas
Middle mouse + drag Pan canvas

Project Structure

src/
  editor/          — ImGui editor (main loop, frame tick, GL scene viewport)
  viewport/        — Software rasterizer (authentic Mode 7 floor preview)
  map/             — Mesh, sprite, and tilemap data types
  math/            — Fixed-point types, camera struct
  platform/psv/    — PS Vita VPK packaging (invokes VitaSDK)
  platform/common/ — Shared node-graph -> C codegen (PSV)
psv_runtime/
  main.c, audio.c  — PS Vita runtime (Mode 4 / 3D, vitaGL)
  include/         — Generated PSV data headers
switch_runtime/
  source/          — Nintendo Switch runtime (libnx + GLES1.1 fork of psv_runtime)
  include/         — switch_port.h platform shim + the same generated data headers
thirdparty/
  glfw/            — Windowing
  imgui/           — UI framework

License

MIT

About

Switch/Vita engine with desktop editor and one-click ROM packaging

Resources

Stars

10 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages