Aller au contenu
Table des matières

nxsand : Une grille GPU pour le sable

nxsand est une simulation de sable sur Switch avec une cible de développement desktop. Les matériaux occupent une grille d’entiers. Des passes mettent cette grille à jour et un parcours de rendu transforme les identifiants en image.

Matériel et infographie
  • Mis à jour
  • C++ · 80.07%
Composants documentés
2Explorer les modules
Documents source
3Lire les instructions
Langages du dépôtC++ 80.07%7

Parts calculées à partir des octets GitHub Linguist.

C++80.07%
80.07%526 697 octets
GLSL10%
10%65 789 octets
Python4.44%
4.44%29 193 octets
PowerShell3.32%
3.32%21 830 octets
Langage%Octets
C++80.07%526 697
GLSL10%65 789
Python4.44%29 193
PowerShell3.32%21 830
Makefile1.63%10 750
Shell0.31%2 016
1 autres langages
Just0.23%1 491

1. Aperçu

1.1. Pourquoi il existe

Moteur de simulation de particules et physique cellulaire optimisé sous libnx.

1.2. Cas d’usage

Simulation physique interactive sur écran tactile de console.

2. Cas d’utilisation

Bac à sable de particules pour Nintendo Switch (homebrew), simulé sur GPU en OpenGL ES 3.0, avec versions bureau.

Diagramme de cas d’utilisation de nxsand : Peindre des matériaux; Voir réagir les matériaux; Sauver et charger un monde; Régler les performances; Importer un tampon Powder Toy; Compiler et tester le NROnxsandPeindre des matériauxVoir réagir les matériauxSauver et charger un mondeRégler les performancesImporter un tampon Powder ToyCompiler et tester le NROJoueurDéveloppeur homebrew«système»GPU (OpenGL ES 3.0)
Acteurs à gauche (personnes) et à droite (systèmes externes) ; chaque ovale est un cas d’utilisation appuyé par les fichiers cités ci-dessous.
Peindre des matériaux
JoueurGPU (OpenGL ES 3.0)

Le tactile, les Joy-Con ou la souris deviennent des traits de pinceau (source/sim/brush_stroke.cpp) écrits dans la grille par shaders/paint.frag ; le bouton X ouvre la roue des matériaux (source/ui/material_wheel.cpp).

Voir réagir les matériaux
JoueurGPU (OpenGL ES 3.0)

Un automate cellulaire de Margolus tourne sur des textures GL_R8UI en alternance dans shaders/sim.frag ou sim.comp ; les réactions, comme lave plus eau qui donne de la pierre, sont dans shaders/sim_common.glsl et le sim_rules_body.glsl qu’il inclut.

Sauver et charger un monde
Joueur

source/save/save.cpp garde jusqu’à trois emplacements en JSON avec grille en base64 dans sdmc:/switch/nxsand/ (./nxsand_save/ sur bureau) ; Y ou F5 fait une sauvegarde rapide.

Régler les performances
JoueurGPU (OpenGL ES 3.0)

settings.json et le menu Engine règlent la résolution, les sous-pas, les tuiles actives, le moteur fragment ou compute et les préréglages Battery Saver, Balanced ou Quality.

Importer un tampon Powder Toy
Développeur homebrew

nx::importTptStampJson (source/save/tpt_stamp_import.cpp) associe les éléments de The Powder Toy aux matériaux NXSand et met le tampon à l’échelle de la grille.

Compiler et tester le NRO
Développeur homebrew

make produit build/NXSand.nro avec devkitPro ; make desktop et make test compilent la version bureau SDL2 et les tests de référence CPU de tests/ ; la CI fait de même dans .github/workflows/native-nro.yml.

2.1. Scénario : Compiler NXSand et jouer un premier monde

  1. Installer devkitPro, puis lancer dkp-pacman -S switch-dev switch-sdl2 switch-mesa switch-glm switch-freetype switch-harfbuzz.
  2. Lancer make à la racine du dépôt pour obtenir build/NXSand.nro.
  3. Le copier dans sdmc:/switch/NXSand.nro et le lancer depuis le menu homebrew.
  4. Appuyer sur X pour choisir la lave, peindre avec A, puis passer à l’eau et la verser sur la lave pour voir apparaître pierre et fumée.
  5. Appuyer sur Y pour sauvegarder le monde dans sdmc:/switch/nxsand/.

Fichiers consultésREADME.mddocs/PHYSICS.mddocs/SETTINGS.mddocs/TPT_IMPORT.mdMakefileshaders/sim_common.glslshaders/paint.fragsource/save/save.cppsource/save/tpt_stamp_import.cppsource/sim/brush_stroke.cppsource/ui/material_wheel.cppsource/game/engine_settings.cpp.github/workflows/native-nro.yml

3. Démarrage

Ces commandes viennent de la documentation du dépôt. Elles n’ont pas été exécutées pendant cette revue.

README.md · Reference versions (June 2026)
dkp-pacman -Q libnx switch-sdl2
dkp-pacman -Syu    # pull newer libnx / switch-sdl2 when available
README.md · 2. Install Switch libraries
dkp-pacman -S switch-dev switch-sdl2 switch-mesa switch-glm switch-freetype switch-harfbuzz
README.md · 3. Build the NRO
make
README.md · Desktop (optional)
make desktop
./build/NXSand
make test         # CPU reference tests, no GPU
README.md · Desktop (optional)
pacman -S --needed mingw-w64-x86_64-gcc mingw-w64-x86_64-make mingw-w64-x86_64-SDL2 mingw-w64-x86_64-freetype mingw-w64-x86_64-angleproject

4. Références du dépôt

Extraits des guides du dépôt, dans leur langue d’origine. Les liens ouvrent la version du code consultée.

Prérequis et premier essai

4.1. Install on Switch (players)

README.md

You need a homebrew-ready Switch (setup guide).

  1. Get NXSand.nro — build it yourself (below), download the latest NXSand-switch zip from GitHub Actions (switch/NXSand.nro inside; optional NXSand.nsp forwarder when CI has SWITCH_PROD_KEYS), or use a release tag (Switch + Linux + Windows portable zips).
  2. Copy to the SD card: sdmc:/switch/NXSand.nro (unzip the artifact at the card root, or copy switch/NXSand.nro into switch/).
  3. Launch from the Homebrew Menu. Saves live in sdmc:/switch/nxsand/. Legacy sdmc:/switch/nxengine/ data is migrated on first launch when possible. Full install notes: docs/INSTALL.md.
Lire les instructions complètes ↗

4.2. 1. Install devkitPro

README.md

OSInstall
WindowsDownload and run the installer from devkitPro installer releases. Use the MSYS2 shortcut it adds (e.g. “devkitPro MSYS2”) so make and dkp-pacman are on your PATH.
Linux / macOSFollow Getting Started on devkitpro.org.
Set DEVKITPRO if your environment does not (the installer usually does).
Lire les instructions complètes ↗

4.3. 2. Install Switch libraries

README.md

In the devkitPro shell:
Lire les instructions complètes ↗

4.4. Installing NXSand on Nintendo Switch

docs/INSTALL.md

NXSand ships as a homebrew .nro. You need a Switch setup that can run homebrew. For controls, settings, and architecture, see the full documentation site.
Lire les instructions complètes ↗

4.5. Install on Switch

docs/INSTALL.md

  1. Copy NXSand.nro to sdmc:/switch/NXSand.nro (required).
  2. Install NXSand.nsp with your CFW tool (Tinfoil, DBI, Goldleaf, etc.).
  3. Launch NXSand from the Home menu. If the forwarder fails, launch the .nro from the homebrew menu instead. Forwarders need a CFW setup that allows unsigned NSP installs. Keep prod.keys private; never commit them.
Lire les instructions complètes ↗
Exploitation et dépannage

4.6. Troubleshooting

docs/INSTALL.md

  • The app file must be sdmc:/switch/NXSand.nro, not inside the save folder.
  • Build and deploy: powershell -File scripts\build-native.ps1 → copy dist/switch/NXSand.nro to sdmc:/switch/NXSand.nro. Run powershell -File scripts\verify-nro.ps1 before copying.
  • Confirm the deployed NRO: delete sdmc:/switch/nxsand/launch.log, launch once, and check the latest block includes build: switch-sim-log-v11, switch: sim shader=sim.frag, romfs: sim.frag=… sim_rules_body.glsl=…, sim shader path: shaders/sim.frag, switch: default sim backend=fragment, and no preferring compute sim. Recopy from a fresh build-native.ps1 build if you still see sim_switch paths.
  • If the app opens then exits, NXSand shows a fatal text screen and writes sdmc:/switch/nxsand/launch.log when possible.
Lire les instructions complètes ↗

4.7. When to update

docs/diagrams/README.md

  • sim-pipeline.mmd, sim-margolus-step.mmd: sim/render pass wiring, compute backend, active-tile scissor rules.
  • material-reactions.mmd, reaction-lava-water-quench.puml: shaders/sim.frag / sim_common.glsl reaction branches.
  • save-load-flow.puml: source/save/save.cpp JSON fields or paths.
  • game-scenes.mmd, brush-input-flow.mmd: menu flow, input mapping, PlayRegion.
  • core-runtime-classes.puml, source-modules.mmd: new top-level modules or ownership changes.
Lire les instructions complètes ↗
Documentation source

3 documents lus parmi 3 candidats.

5. Fonctions et composants 2

État de simulation
SimState contient les dimensions, le compteur et les paramètres du pinceau. SimPipeline possède deux textures et framebuffers avec des opérations de peinture, calcul, lecture et chargement. Le stockage alterné conserve la grille précédente pendant le calcul de la suivante.
Moteur et tests
Le parcours fragment utilise GL_R8UI; le parcours compute utilise GL_R32UI pour imageStore. Le pipeline expose les tuiles actives et les replis. Le Makefile sépare les tests CPU, les tests GPU et l’application Switch.

6. Architecture

Ouvrez un composant pour suivre ses connexions, ou explorez le diagramme complet.

Composants du système Contexte
Mermaid Diagramme interactif

Vue générale des composants et des échanges vérifiés dans le dépôt.

Vue statique de l’architecture de nxsand
Aperçu statique. Le diagramme interactif le remplace après le chargement de Mermaid.
flowchart LR
node_player(("Player"))

subgraph group_runtime["Runtime"]
  node_entry["Platform entry<br/>[main.cpp]"]
  node_app["App frame loop<br/>[app.cpp]"]
  node_game_settings["Game settings<br/>[game_settings.hpp]"]
  node_engine_settings["Engine settings"]
end

subgraph group_simulation["Simulation"]
  node_sim_state["Simulation state<br/>[sim_state.hpp]"]
  node_materials["Materials<br/>[materials.hpp]"]
  node_physics["Physics parameters<br/>[physics_params.hpp]"]
  node_sim_pipeline["GPU simulation<br/>[sim_pipeline.cpp]"]
  node_sim_backend["Simulation backend<br/>[sim_backend.hpp]"]
end

subgraph group_presentation["Presentation"]
  node_render["World renderer"]
  node_shader_program["Shader programs<br/>[shader_program.cpp]"]
  node_font["Font atlas<br/>[font_atlas.cpp]"]
  node_audio["Audio<br/>[tone_audio.cpp]"]
end

subgraph group_interaction["Interaction"]
  node_input["Input handling<br/>[input.cpp]"]
  node_menu["Menus<br/>[menu.cpp]"]
  node_layout["UI layout<br/>[layout.hpp]"]
  node_theme["UI theme<br/>[theme.hpp]"]
end

subgraph group_persistence["Persistence"]
  node_save["World saves<br/>[save.cpp]"]
  node_save_paths["Save storage<br/>[save_paths.cpp]"]
  node_settings_io["Settings storage<br/>[settings_io.cpp]"]
end

node_player -->|"launches"| node_entry
node_entry -->|"starts"| node_app
node_app -->|"renders"| node_render
node_app -->|"reads"| node_input
node_app -->|"coordinates"| node_menu
node_app -->|"applies settings"| node_engine_settings
node_app -->|"uses settings"| node_game_settings
node_sim_pipeline -->|"updates grid"| node_sim_state
node_sim_pipeline -->|"simulates materials"| node_materials
node_sim_pipeline -->|"uses parameters"| node_physics
node_sim_pipeline -->|"selects backend"| node_sim_backend
node_render -->|"uses shaders"| node_shader_program
node_render -->|"draws grid"| node_sim_state
node_render -->|"colors materials"| node_materials
node_menu -->|"edits settings"| node_engine_settings
node_menu -->|"uses text"| node_font
node_menu -->|"draws interface"| node_render
node_layout -->|"uses styles"| node_theme
node_input -->|"maps controls"| node_layout
node_audio -->|"reads preferences"| node_game_settings
node_save -.->|"uses storage"| node_save_paths
node_settings_io -->|"uses storage"| node_save_paths
group_runtime --> group_simulation
group_runtime --> group_persistence
class node_entry,node_app,node_game_settings,node_engine_settings toneBlue
class node_sim_state,node_materials,node_physics,node_sim_pipeline,node_sim_backend toneAmber
class node_render,node_shader_program,node_font,node_audio toneMint
class node_input,node_menu,node_layout,node_theme toneRose
class node_save,node_save_paths,node_settings_io,node_player toneIndigo

Un bac à sable de particules pour Nintendo Switch, avec des versions bureau pour itérer rapidement. La boucle d’images coordonne la simulation GPU, le rendu, les entrées, les menus, la persistance et les réglages autour d’une grille de matériaux.

Composants
21
Connexions
28
Liens appuyés par le code
15/28
Version texte du diagramme

Le diagramme regroupe les liens parallèles entre groupes : il en montre 24 sur 28. Liste complète :

  • Player → Platform entry (launches)
  • Platform entry → App frame loop (starts)
  • App frame loop → GPU simulation (ticks)
  • App frame loop → World renderer (renders)
  • App frame loop → Input handling (reads)
  • App frame loop → Menus (coordinates)
  • App frame loop → World saves (requests saves)
  • App frame loop → Settings storage (loads settings)
  • App frame loop → Engine settings (applies settings)
  • App frame loop → Game settings (uses settings)
  • App frame loop → Simulation state (holds state)
  • App frame loop → Physics parameters (holds parameters)
  • GPU simulation → Simulation state (updates grid)
  • GPU simulation → Materials (simulates materials)
  • GPU simulation → Physics parameters (uses parameters)
  • GPU simulation → Simulation backend (selects backend)
  • World renderer → Shader programs (uses shaders)
  • World renderer → Simulation state (draws grid)
  • World renderer → Materials (colors materials)
  • Menus → Engine settings (edits settings)
  • Menus → Font atlas (uses text)
  • Menus → World renderer (draws interface)
  • UI layout → UI theme (uses styles)
  • Input handling → UI layout (maps controls)
  • Audio → Game settings (reads preferences)
  • World saves → Save storage (uses storage)
  • Settings storage → Save storage (uses storage)
  • Engine settings → Settings storage (persists preferences)
Suivre un parcours dans le code

Suivez paintDisk vers la modification de grille, puis step vers le moteur choisi. readTexture désigne la grille courante pour le rendu. La sauvegarde doit aussi tenir compte de l’orientation des lignes OpenGL, plutôt que copier une capture.

7. Dossier technique

Établi à partir du code au commit af70da3 (138 fichiers). Chaque élément vient d’une correspondance de motif dans le code: ouvrez le fichier lié avant de vous y fier.

7.1. Couches et modules

Les dossiers sont classés par couche selon leur nom, de l’interface utilisateur jusqu’à l’accès aux données. Comme le classement repose sur les noms seulement, le diagramme ne dit rien des appels entre couches.

Mermaid Vue en couches
flowchart TB
  subgraph L_presentation["Présentation"]
    direction TB
    presentation_0["ui<br/>30 fichiers"]
  end
  subgraph L_application["Services applicatifs"]
    direction TB
    application_0["scripts<br/>18 fichiers"]
    application_1["gpu<br/>4 fichiers"]
  end
  subgraph L_domain["Domaine et règles métier"]
    direction TB
    domain_0["game<br/>8 fichiers"]
  end
  subgraph L_infrastructure["Données et infrastructure"]
    direction TB
    infrastructure_0["platform/audio<br/>10 fichiers"]
    infrastructure_1["platform/input<br/>7 fichiers"]
    infrastructure_2["platform<br/>4 fichiers"]
    infrastructure_3["gpu<br/>2 fichiers"]
  end
  subgraph L_core["Source principale"]
    direction TB
    core_0["gpu<br/>13 fichiers"]
    core_1["save<br/>13 fichiers"]
    core_2["sim<br/>13 fichiers"]
    core_3["shaders<br/>3 fichiers"]
    core_more["+2"]
  end
  subgraph L_tests["Tests"]
    direction TB
    tests_0["tests<br/>21 fichiers"]
  end
  subgraph L_hosting["Build, CI et hébergement"]
    direction TB
    hosting_0[".github<br/>4 fichiers"]
    hosting_1["(root)<br/>2 fichiers"]
  end
  L_presentation ~~~ L_application
  L_application ~~~ L_domain
  L_domain ~~~ L_infrastructure
  L_infrastructure ~~~ L_core
  L_core ~~~ L_tests
  L_core ~~~ L_hosting
Modules et couche principale
ModuleCoucheFichiersTypesExtensions
uiPrésentation309.hpp .cpp
gpuSource principale1917.hpp .cpp
scriptsServices applicatifs180.ps1 .py .sh
saveSource principale131.hpp .cpp
simSource principale137.hpp .cpp
platform/audioDonnées et infrastructure103.cpp .hpp
gameDomaine et règles métier810.cpp .hpp
platform/inputDonnées et infrastructure74.hpp .cpp
platformDonnées et infrastructure40.cpp .hpp
shadersSource principale30.glsl
third_party/gladSource principale30.h .c
third_party/nlohmannSource principale10.hpp

7.2. Modèle C4

Du contexte du système aux déclarations du code. Chaque niveau conserve les limites des sources disponibles.

UML 1 · Contexte du système
1 · Contexte du système

La vue C4 la plus large : qui utilise le projet et sur quels systèmes et stockages externes il s’appuie. Rendu avec uml-mcp.

Source PlantUML
@startuml
!include <C4/C4_Context>
LAYOUT_LEFT_RIGHT()
Person(P_cli, "Utilisateur CLI")
System(SYS, "nxsand", "nxsand est une simulation de sable sur Switch avec une cible de dével…")
System_Ext(E0, "Kroki")
Rel(P_cli, SYS, "Utilise")
Rel(SYS, E0, "Appelle")
@enduml
UML 2 · Conteneurs
2 · Conteneurs

Un niveau plus près : les parties qui s’exécutent séparément dans le projet, leur langage principal et le chemin des appels entre elles. Rendu avec uml-mcp.

Source PlantUML
@startuml
!include <C4/C4_Container>
LAYOUT_LEFT_RIGHT()
Person(P_cli, "Utilisateur CLI")
System_Boundary(SYS, "nxsand") {
  Container(APP, "nxsand", "C++")
}
System_Ext(E0, "Kroki")
Rel(P_cli, APP, "Utilise")
Rel(APP, E0, "Appelle")
@enduml
UML 3 · Composants et couches
3 · Composants et couches

Modules regroupés par couche du code. Les limites indiquent l’organisation, sans affirmer une isolation à l’exécution ni des appels. Rendu avec uml-mcp.

Source PlantUML
@startuml
!include <C4/C4_Component>
LAYOUT_TOP_DOWN()
System_Boundary(SYS, "nxsand") {
Boundary(L0, "Présentation", "layer") {
Component(M0_0, "ui", "C++", "30 fichiers")
}
Boundary(L1, "Services applicatifs", "layer") {
Component(M1_0, "scripts", ".ps1, Python, .sh", "18 fichiers")
Component(M1_1, "gpu", "C++", "4 fichiers")
}
Boundary(L2, "Domaine et règles métier", "layer") {
Component(M2_0, "game", "C++", "8 fichiers")
}
Boundary(L3, "Données et infrastructure", "layer") {
Component(M3_0, "platform/audio", "C++", "10 fichiers")
Component(M3_1, "platform/input", "C++", "7 fichiers")
Component(M3_2, "platform", "C++", "4 fichiers")
Component(M3_3, "gpu", "C++", "2 fichiers")
}
Boundary(L4, "Source principale", "layer") {
Component(M4_0, "gpu", "C++", "13 fichiers")
Component(M4_1, "save", "C++", "13 fichiers")
Component(M4_2, "sim", "C++", "13 fichiers")
Component(M4_3, "shaders", ".glsl", "3 fichiers")
Component(M4_4, "third_party/glad", "C/C++, C", "3 fichiers")
Component(M4_5, "third_party/nlohmann", "C++", "1 fichiers")
}
Boundary(L5, "Tests", "layer") {
Component(M5_0, "tests", "C++", "21 fichiers")
}
Boundary(L6, "Build, CI et hébergement", "layer") {
Component(M6_0, ".github", ".yml, .json", "4 fichiers")
Component(M6_1, "(root)", "Makefile, justfile", "2 fichiers")
}
}
@enduml
UML 4 · Code
4 · Code

Déclarations, champs et méthodes sélectionnés, regroupés par fichier source. Aucun héritage ni appel n’est déduit. Rendu avec uml-mcp.

Source PlantUML
@startuml
skinparam backgroundColor transparent
skinparam shadowing false
skinparam roundCorner 10
skinparam defaultFontName Arial
skinparam defaultFontSize 13
skinparam ArrowColor #4e6070
skinparam ArrowFontColor #3d4f5f
skinparam titleFontSize 14
skinparam actorBorderColor #006a62
skinparam actorBackgroundColor #e9f3f4
skinparam usecaseBorderColor #006a62
skinparam usecaseBackgroundColor #e9f3f4
skinparam componentBorderColor #006a62
skinparam componentBackgroundColor #e9f3f4
skinparam interfaceBorderColor #006a62
skinparam interfaceBackgroundColor #ffffff
skinparam nodeBorderColor #4e6070
skinparam nodeBackgroundColor #f4f8fb
skinparam databaseBorderColor #006a62
skinparam databaseBackgroundColor #ffffff
skinparam cloudBorderColor #4e6070
skinparam cloudBackgroundColor #f0f5fa
skinparam artifactBorderColor #006a62
skinparam artifactBackgroundColor #ffffff
skinparam rectangleBorderColor #b0c2d3
skinparam activityBorderColor #006a62
skinparam activityBackgroundColor #e9f3f4
skinparam partitionBorderColor #b0c2d3
skinparam stereotypeCBackgroundColor #ffffff
top to bottom direction
hide empty members
package "nxsand" {
package "source/game/app.hpp" as F0 {
class "App" as T0_0 {
  shutdown()
  frame()
  setSimGridSize()
  applyRuntimeSettings()
  applyRuntimeSettingsLight()
  applyRuntimeSettingsHeavy()
}
}
package "source/gpu/active_tiles.hpp" as F1 {
class "ActiveTileMap" as T1_0 {
  reset()
  wakeAll()
  sleepAll()
  wakeFromGridTopDown()
  wakeBoundsPx()
  rememberBounds()
}
class "ActiveTileRun" as T1_1 {
  std
}
}
package "source/gpu/perf_stats.hpp" as F2 {
class "PerfStats" as T2_0 {
  beginFrame()
  beginSim()
  endSim()
  beginPaint()
  endPaint()
  beginWorldRender()
}
}
package "source/gpu/font_atlas.hpp" as F3 {
class "FontAtlas" as T3_0 {
  isReady()
  shutdown()
  invalidateGlTexture()
  resetGlResources()
  textWidth()
  drawText()
}
}
package "source/gpu/shader_program.hpp" as F4 {
class "ShaderProgram" as T4_0 {
  loadFromFiles()
  loadComputeFromFile()
  use()
  uniformLocation()
  readFile()
  compile()
}
}
package "source/platform/input/menu_repeat.hpp" as F5 {
class "MenuRepeatState" as T5_0 {
  reset()
  tick()
  tickAxis()
}
}
package "source/gpu/shader_program.cpp" as F6 {
class "SwitchLinkHeartbeat" as T6_0 {
  start()
  finish()
}
}
package "source/ui/menu.hpp" as F7 {
class "MenuLayout" as T7_0 {
  s
  panelX
  panelY
  panelW
  panelH
  rowH
  listY0
  titleY
}
}
package "source/sim/physics_gpu.hpp" as F8 {
class "PhysicsParamsGPU" as T8_0 {
  fire_speed
  fire_smokeRate
  fire_ignitePlant
  fire_igniteOil
  fire_spreadRate
  smoke_fadeRate
  smoke_driftRate
  water_flowRate
}
}
package "source/gpu/shader_cache.cpp" as F9 {
class "ShaderCacheHeader" as T9_0 {
  magic
  version
  keyHash
  binaryFormat
  payloadSize
}
}
package "source/gpu/sim_pipeline.hpp" as F10 {
class "SimPassRect" as T10_0 {
  simShader
  computeShader
  paintShader
  activeTiles
}
}
package "source/gpu/render_pipeline.hpp" as F11 {
class "UiVertex" as T11_0 {
  std
  bloomBrightShader
  bloomBlurShader
  bloomCompositeShader
}
}
package "source/sim/brush_stroke.hpp" as F12 {
class "BrushDab" as T12_0 {
  x
  y
  std
}
class "BrushStrokePlan" as T12_1 {
  std
}
}
package "source/gpu/font_atlas.cpp" as F13 {
class "FtLibrary" as T13_0 {
  std
  true
}
}
package "source/sim/physics_settings.hpp" as F14 {
class "ParamSpec" as T14_0 {
  id
  label
}
}
package "source/ui/layout.hpp" as F15 {
class "PlayRegion" as T15_0 {
  scaleX
  scaleY
}
}
package "source/game/game_settings.hpp" as F16 {
class "DebugSettings" as T16_0 {
  std
}
class "DisplaySettings" as T16_1 {
  std
}
class "GameSettings" as T16_2 {
  std
}
}
}
@enduml

7.3. Flux de données

Les appels du diagramme GitDiagram, dans l’ordre où on les rencontre depuis les points d’entrée. GitDiagram produit ce graphe par IA; les chemins de fichiers cités ont été comparés à l’arbre du dépôt.

Mermaid Diagramme de séquence
sequenceDiagram
  autonumber
  participant P0 as Audio
  participant P1 as Game settings
  participant P2 as Player
  participant P3 as Platform entry
  participant P4 as App frame loop
  participant P5 as GPU simulation
  participant P6 as World renderer
  participant P7 as Input handling
  participant P8 as Menus
  participant P9 as World saves
  participant P10 as Settings storage
  participant P11 as Engine settings
  participant P12 as Simulation state
  participant P13 as Physics parameters
  participant P14 as Materials
  P0->>P1: reads preferences
  P2->>P3: launches
  P3->>P4: starts
  P4->>P5: ticks
  P4->>P6: renders
  P4->>P7: reads
  P4->>P8: coordinates
  P4->>P9: requests saves
  P4->>P10: loads settings
  P4->>P11: applies settings
  P4->>P1: uses settings
  P4->>P12: holds state
  P4->>P13: holds parameters
  P5->>P12: updates grid
  P5->>P14: simulates materials
  P5->>P13: uses parameters
Étapes en texte (+4)
  1. Audio vers Game settings reads preferences
  2. Player vers Platform entry launches
  3. Platform entry vers App frame loop starts
  4. App frame loop vers GPU simulation ticks
  5. App frame loop vers World renderer renders
  6. App frame loop vers Input handling reads
  7. App frame loop vers Menus coordinates
  8. App frame loop vers World saves requests saves
  9. App frame loop vers Settings storage loads settings
  10. App frame loop vers Engine settings applies settings
  11. App frame loop vers Game settings uses settings
  12. App frame loop vers Simulation state holds state
  13. App frame loop vers Physics parameters holds parameters
  14. GPU simulation vers Simulation state updates grid
  15. GPU simulation vers Materials simulates materials
  16. GPU simulation vers Physics parameters uses parameters
  17. GPU simulation vers Simulation backend selects backend
  18. World renderer vers Shader programs uses shaders
  19. World renderer vers Simulation state draws grid
  20. World renderer vers Materials colors materials
  21. Input handling vers UI layout maps controls
  22. Menus vers Engine settings edits settings
  23. Menus vers Font atlas uses text
  24. Menus vers World renderer draws interface

7.4. Interface publique

Du code extérieur peut utiliser tout ce qui est listé ici. Le projet déclare aussi 51 types publics.

Ligne de commande 9

Points d’entrée

7.5. Interface privée

Ces noms sont internes selon les conventions du langage: tiret bas initial, private, static ou pub(crate).

Fonction static (locale au fichier)
74
Espace de noms anonyme
19
Assistant préfixé _
9

7.6. Services

Service 2

  • RenderPipelineshutdown, buildPaletteTexture, drawSimulation et 32 autres
  • SimPipelineshutdown, clearAll, paintDisk et 24 autres

7.7. Entités et modèle de données 36

Mermaid Diagramme de classes des entités
classDiagram
  direction LR
  class E0["MenuLayout"] {
    +float s
    +float panelX
    +float panelY
    +float panelW
    +float panelH
    +float rowH
  }
  class E1["PhysicsParamsGPU"] {
    +float fire_speed
    +float fire_smokeRate
    +float fire_ignitePlant
    +float fire_igniteOil
    +float fire_spreadRate
    +float smoke_fadeRate
  }
  class E2["ShaderCacheHeader"] {
    +char magic
    +uint32_t version
    +uint64_t keyHash
    +uint32_t binaryFormat
    +uint32_t payloadSize
  }
  class E3["SimPassRect"] {
    +ShaderProgram simShader
    +ShaderProgram computeShader
    +ShaderProgram paintShader
    +ActiveTileMap activeTiles
  }
  class E4["UiVertex"] {
    +:vector std
    +ShaderProgram bloomBrightShader
    +ShaderProgram bloomBlurShader
    +ShaderProgram bloomCompositeShader
  }
  class E5["BrushDab"] {
    +int x
    +int y
    +:vector std
  }
  class E6["FtLibrary"] {
    +:ifstream std
    +return true
  }
  class E7["ParamSpec"] {
    +char id
    +char label
  }
  class E8["PlayRegion"] {
    +int scaleX
    +int scaleY
  }
  class E9["DebugSettings"] {
    +:pair std
  }

Une flèche relie un champ à l’entité que son type nomme.

EntitéNaturePremiers champs
MenuLayoutStructure de donnéess, panelX, panelY, panelW, panelH, rowH, listY0, titleY
PhysicsParamsGPUStructure de donnéesfire_speed, fire_smokeRate, fire_ignitePlant, fire_igniteOil, fire_spreadRate, smoke_fadeRate, smoke_driftRate, water_flowRate
ShaderCacheHeaderStructure de donnéesmagic, version, keyHash, binaryFormat, payloadSize
SimPassRectStructure de donnéessimShader, computeShader, paintShader, activeTiles
UiVertexStructure de donnéesstd, bloomBrightShader, bloomBlurShader, bloomCompositeShader
BrushDabStructure de donnéesx, y, std
FtLibraryStructure de donnéesstd, true
ParamSpecStructure de donnéesid, label
Afficher 6 entités de plus
PlayRegionStructure de donnéesscaleX, scaleY
DebugSettingsStructure de donnéesstd
DisplaySettingsStructure de donnéesstd
GameSettingsStructure de donnéesstd
ActiveTileRunStructure de donnéesstd
BrushStrokePlanStructure de donnéesstd

7.8. Logique métier

Une fois écartés le code d’interface et les services et entités ci-dessus, ces classes ont le plus de méthodes.

App Domaine et règles métier, 37 méthodes
shutdown, frame, setSimGridSize, applyRuntimeSettings, applyRuntimeSettingsLight, applyRuntimeSettingsHeavy
ActiveTileMap Source principale, 23 méthodes
reset, wakeAll, sleepAll, wakeFromGridTopDown, wakeBoundsPx, rememberBounds
PerfStats Source principale, 12 méthodes
beginFrame, beginSim, endSim, beginPaint, endPaint, beginWorldRender
FontAtlas Source principale, 11 méthodes
isReady, shutdown, invalidateGlTexture, resetGlResources, textWidth, drawText
ShaderProgram Source principale, 8 méthodes
loadFromFiles, loadComputeFromFile, use, uniformLocation, readFile, compile
MenuRepeatState Données et infrastructure, 3 méthodes
reset, tick, tickAxis
SwitchLinkHeartbeat Source principale, 2 méthodes
start, finish

7.9. Intégrations externes

Clients HTTP

urllib

Hôtes nommés dans le code

7.10. Stack et dépendances

Native (Make) Makefile 12 à l’exécution

DEVKITPRO

Ouvrir le manifeste

Dépendances externes

7.11. Pipeline CI/CD

3 workflows GitHub Actions, 11 tâches. Chaque boîte est une tâche ; les boîtes à double bord publient ou déploient, et les flèches suivent les dépendances needs.

Mermaid Déroulement du pipeline
flowchart LR
  subgraph wf0["Documentation"]
    direction LR
    wf0_build[["build<br/>ubuntu-latest"]]
    wf0_deploy[["deploy<br/>ubuntu-latest"]]
  end
  subgraph wf1["Build NXSand.nro"]
    direction LR
    wf1_unit_tests["CPU unit tests<br/>ubuntu-latest"]
    wf1_switch[["Switch NRO<br/>ubuntu-latest"]]
    wf1_desktop["Desktop sanity build (Linux)<br/>ubuntu-latest"]
    wf1_desktop_windows["Desktop sanity build (Windows)<br/>windows-latest"]
  end
  subgraph wf2["Release NXSand"]
    direction LR
    wf2_unit_tests["CPU unit tests<br/>ubuntu-latest"]
    wf2_build_switch[["Package Switch NRO<br/>ubuntu-latest"]]
    wf2_build_linux[["Package Linux portable<br/>ubuntu-latest"]]
    wf2_build_windows[["Package Windows portable<br/>windows-latest"]]
    wf2_publish[["Publish GitHub release<br/>ubuntu-latest"]]
  end
  t0(["push · lancement manuel"])
  t1(["push · demande de fusion · lancement manuel"])
  t2(["lancement manuel"])
  d0[("GitHub Pages")]
  d1[("Versions GitHub")]
  t0 --> wf0_build
  wf0_build --> wf0_deploy
  wf0_deploy -.-> d0
  t1 --> wf1_unit_tests
  wf1_unit_tests --> wf1_switch
  wf1_unit_tests --> wf1_desktop
  wf1_unit_tests --> wf1_desktop_windows
  t2 --> wf2_unit_tests
  wf2_unit_tests --> wf2_build_switch
  wf2_unit_tests --> wf2_build_linux
  wf2_unit_tests --> wf2_build_windows
  wf2_build_switch --> wf2_publish
  wf2_build_linux --> wf2_publish
  wf2_build_windows --> wf2_publish
  wf2_publish -.-> d1
Workflows, déclencheurs, tâches et cibles
WorkflowDéclencheursTâchesPublie vers
Documentation
.github/workflows/docs.yml
push, lancement manuel
  • build ubuntu-latest
    actions/checkout · actions/setup-python · Install MkDocs · Build site · Upload Pages artifact
  • deploy ← build ubuntu-latest
    Deploy to GitHub Pages
GitHub Pages
Build NXSand.nro
.github/workflows/native-nro.yml
push, demande de fusion, lancement manuel
  • CPU unit tests ubuntu-latest
    actions/checkout · Install build tools · Build and run unit tests · Build and run GPU unit tests
  • Switch NRO ← unit-tests ubuntu-latest
    actions/checkout · Verify required portlibs · Build NRO and stage dist · Export NSP forwarder · Package switch zip · actions/upload-artifact
  • Desktop sanity build (Linux) ← unit-tests ubuntu-latest
    actions/checkout · Install SDL2 + GLESv2 + FreeType (Mesa) · Fetch UI font · Build desktop · GPU unit tests · Verify binary
  • Desktop sanity build (Windows) ← unit-tests windows-latest
    actions/checkout · msys2/setup-msys2 · Fetch UI font · Build desktop · Verify binary
—
Release NXSand
.github/workflows/release.yml
lancement manuel
  • CPU unit tests ubuntu-latest
    actions/checkout · Install build tools · Build and run unit tests
  • Package Switch NRO ← unit-tests ubuntu-latest
    actions/checkout · Verify required portlibs · Build NRO · Export NSP forwarder · Package Switch zip · actions/upload-artifact
  • Package Linux portable ← unit-tests ubuntu-latest
    actions/checkout · Install SDL2 + GLESv2 + FreeType (Mesa) · Fetch UI font · Build desktop · Package Linux zip · actions/upload-artifact
  • Package Windows portable ← unit-tests windows-latest
    actions/checkout · msys2/setup-msys2 · Fetch UI font · Build desktop · Package Windows zip · actions/upload-artifact
  • Publish GitHub release ← build-switch, build-linux, build-windows ubuntu-latest
    actions/checkout · actions/download-artifact · List release artifacts · Skip publish under act · Publish GitHub release
Versions GitHub

7.12. Déploiement

Mermaid Schéma de déploiement
flowchart LR
  repo[("Dépôt GitHub")]
  ci[["GitHub Actions<br/>3 workflows"]]
  pub_GitHub_Pages[("GitHub Pages")]
  pub_GitHub_Releases[("Versions GitHub")]
  host_MkDocs_site("Site de documentation (MkDocs)<br/>mkdocs.yml")
  repo -->|"push ou demande de fusion"| ci
  ci -->|"publie"| pub_GitHub_Pages
  ci -->|"publie"| pub_GitHub_Releases
  ci -.->|"configuré"| host_MkDocs_site

Où il s’exécute

Publié vers

7.13. Sécurité

Contrôles

Variables d’environnement 20

La page reprend les noms sans leurs valeurs et souligne ceux qui ressemblent à des secrets.

NXENGINE_BOOT_LOG NXENGINE_SIM_H NXENGINE_SIM_W NXSAND_BOOT_LOG NXSAND_SIM_H NXSAND_SIM_W MINGW_PREFIX NXENGINE_DEBUG_GRID NXENGINE_DISABLE_AUDIO NXENGINE_LAUNCH_LOG NXENGINE_PALETTE_MODE NXENGINE_SWITCH_SWAP_FACE_XY NXENGINE_VERBOSE_LAUNCH_LOG NXSAND_DEBUG_GRID NXSAND_DISABLE_AUDIO NXSAND_FONT_PATH

7.14. Tests automatisés

Fichiers de test
21
Fichiers source
129
Tests unitaires
21

Aucun rapport chiffré de couverture dans les sources analysées.

Où sont les tests

tests 21

Rien trouvé pour: Base de données, Supervision.

8. Types et structure des fichiers

53 types déclarés, dont 12 dans l’aperçu des relations de base.

Diagramme des types
classDiagram
direction TB
class t7ba1fb6b5b9e["SimPassRect"] {
  <<struct>>
}
class t658fbe1e623e["SimPipeline"] {
  SimPipeline()
  init()
  shutdown()
  clearAll()
}
class tb8626ee066b2["SimState"] {
  <<struct>>
}
class tfdb610a7db47["SimCompileAudioGuard"] {
  <<struct>>
  SimCompileAudioGuard()
}
class ta050db13a10c["App"] {
  init()
  shutdown()
  frame()
  setSimGridSize()
}
class tf962c5d4ce57["PerformanceSettings"] {
  <<struct>>
}
class tbdcb989e9dca["VisualSettings"] {
  <<struct>>
}
class tbb5d68fb65da["ControlSettings"] {
  <<struct>>
}
class t480673c07c2c["AudioSettings"] {
  <<struct>>
}
class t28451b24c3ad["AccessibilitySettings"] {
  <<struct>>
}
class t45aedf66edc0["DebugSettings"] {
  <<struct>>
}
class t4b3cad79f762["DisplaySettings"] {
  <<struct>>
}

Les bases non résolues restent identifiées; les signatures complètes ne sont pas reconstruites.

9. Référence

135 / 135 fichiers admissibles lus (240 dans l’arbre); 0 trop volumineux, 0 échec de lecture et 5 diagnostic de syntaxe.

Ce que couvre l’analyse

Les dossiers connus de dépendances et de compilation, les fichiers d’identifiants et les binaires sont exclus. La collecte couvre les README, les manifestes reconnus et les fichiers source pris en charge.

Les statistiques Linguist couvrent l’ensemble du dépôt et peuvent inclure d’autres langages.

11. Fichiers à lire 3

12. Glossaire

Dépôt

Les fichiers source, la configuration et l’historique versionné d’un projet.

README

Le document d’entrée du dépôt, qui présente généralement son rôle et son installation.

Dépendance

Une bibliothèque, un outil ou un service nécessaire à la compilation ou à l’exécution d’un composant.

Volume et montage de dossier

Un volume est un stockage géré par la plateforme de conteneurs ; un montage de dossier expose un chemin de l’hôte dans un conteneur.

Interface en ligne de commande

Une interface textuelle où les commandes et arguments choisissent les opérations. Les codes de retour permettent aux scripts de détecter un succès ou un échec.

Compilation

Les étapes qui transforment les sources et dépendances en programme exécutable ou en livrable distribuable.

Intégration continue

Des vérifications automatiques lors des changements de source, comme la compilation, les tests et l’analyse statique. Elles ne couvrent que ce qu’elles vérifient.

GPU

Un processeur conçu pour les calculs parallèles, dont le rendu graphique et de nombreuses opérations numériques.

Shader

Un programme exécuté à une étape d’un pipeline graphique ou de calcul, par exemple pour transformer des sommets ou calculer la couleur des pixels.

Backend

Une implémentation derrière une interface commune. Selon le contexte, il peut s’agir d’un service côté serveur ou d’une implémentation graphique, d’entrée ou de stockage.

13. Références

  1. antoinebou12. (2026, 5 novembre). nxsand. [Software repository] github.com.
  2. antoinebou12. (2026, 5 novembre). nxsand: README. [Repository documentation] github.com.
  3. antoinebou12. (2026, 5 novembre). source/gpu/sim_pipeline.hpp. [Source file] github.com.
  4. antoinebou12. (2026, 5 novembre). source/sim/sim_state.hpp. [Source file] github.com.
  5. antoinebou12. (2026, 5 novembre). Makefile. [Source file] github.com.
  6. Boucher, A. (2026, 23 octobre). nxsand : Une grille GPU pour le sable. [Project article] antoineboucher.info.

Les sources sans date de publication indiquent la date de leur dernière vérification, le 5 novembre 2026. Les liens des fichiers conservent la révision inspectée lorsqu’elle est disponible.