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.
- Langages
- 7Répartition du code
- 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.
| Langage | % | Octets |
|---|---|---|
| C++ | 526 697 | |
| GLSL | 65 789 | |
| Python | 29 193 | |
| PowerShell | 21 830 | |
| Makefile | 10 750 | |
| Shell | 2 016 |
1 autres langages
| Just | 0.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.
- 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
- Installer devkitPro, puis lancer dkp-pacman -S switch-dev switch-sdl2 switch-mesa switch-glm switch-freetype switch-harfbuzz.
- Lancer make à la racine du dépôt pour obtenir build/NXSand.nro.
- Le copier dans sdmc:/switch/NXSand.nro et le lancer depuis le menu homebrew.
- 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.
- 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.
dkp-pacman -Q libnx switch-sdl2
dkp-pacman -Syu # pull newer libnx / switch-sdl2 when availabledkp-pacman -S switch-dev switch-sdl2 switch-mesa switch-glm switch-freetype switch-harfbuzzmakemake desktop
./build/NXSand
make test # CPU reference tests, no GPUpacman -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-angleproject4. 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).
- 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).
- Copy to the SD card: sdmc:/switch/NXSand.nro (unzip the artifact at the card root, or copy switch/NXSand.nro into switch/).
- 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.
4.2. 1. Install devkitPro
README.md
| OS | Install |
|---|---|
| Windows | Download 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 / macOS | Follow Getting Started on devkitpro.org. |
| Set DEVKITPRO if your environment does not (the installer usually does). |
4.3. 2. Install Switch libraries
README.md
4.4. Installing NXSand on Nintendo Switch
docs/INSTALL.md
4.5. Install on Switch
docs/INSTALL.md
- Copy NXSand.nro to sdmc:/switch/NXSand.nro (required).
- Install NXSand.nsp with your CFW tool (Tinfoil, DBI, Goldleaf, etc.).
- 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.
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.
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.
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.
Commandes de pinceau
Grille entière des matériaux
- Depuis Commandes de pinceau
- Vers Passe de simulation
- Depuis Texture de grille suivante
Passe de simulation
Texture de grille suivante
- Depuis Passe de simulation
- Vers Grille entière des matériaux
- Vers Pipeline de rendu
Pipeline de rendu
- Depuis Texture de grille suivante
Mermaid Diagramme interactif
Vue générale des composants et des échanges vérifiés dans le dépôt.

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
| Module | Couche | Fichiers | Types | Extensions |
|---|---|---|---|---|
ui | Présentation | 30 | 9 | .hpp .cpp |
gpu | Source principale | 19 | 17 | .hpp .cpp |
scripts | Services applicatifs | 18 | 0 | .ps1 .py .sh |
save | Source principale | 13 | 1 | .hpp .cpp |
sim | Source principale | 13 | 7 | .hpp .cpp |
platform/audio | Données et infrastructure | 10 | 3 | .cpp .hpp |
game | Domaine et règles métier | 8 | 10 | .cpp .hpp |
platform/input | Données et infrastructure | 7 | 4 | .hpp .cpp |
platform | Données et infrastructure | 4 | 0 | .cpp .hpp |
shaders | Source principale | 3 | 0 | .glsl |
third_party/glad | Source principale | 3 | 0 | .h .c |
third_party/nlohmann | Source principale | 1 | 0 | .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
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
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
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
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)
- Audio vers Game settings reads preferences
- Player vers Platform entry launches
- Platform entry vers App frame loop starts
- App frame loop vers GPU simulation ticks
- App frame loop vers World renderer renders
- App frame loop vers Input handling reads
- App frame loop vers Menus coordinates
- App frame loop vers World saves requests saves
- App frame loop vers Settings storage loads settings
- App frame loop vers Engine settings applies settings
- App frame loop vers Game settings uses settings
- App frame loop vers Simulation state holds state
- App frame loop vers Physics parameters holds parameters
- GPU simulation vers Simulation state updates grid
- GPU simulation vers Materials simulates materials
- GPU simulation vers Physics parameters uses parameters
- GPU simulation vers Simulation backend selects backend
- World renderer vers Shader programs uses shaders
- World renderer vers Simulation state draws grid
- World renderer vers Materials colors materials
- Input handling vers UI layout maps controls
- Menus vers Engine settings edits settings
- Menus vers Font atlas uses text
- 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
source/platform/main.cppfichier 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
_is_darkscripts/crop_icon.py:12_is_letterboxscripts/crop_icon.py:16_artwork_bboxscripts/crop_icon.py:21getenvEnabledsource/game/app.cpp:76bootLogStagesource/game/app.cpp:83simBackendNamesource/game/app.cpp:93namespace { }source/game/app.cpp:45namespace { }source/gpu/font_atlas.cpp:17namespace { }source/gpu/gl_loader.cpp:5
7.6. Services
Service 2
RenderPipelineshutdown, buildPaletteTexture, drawSimulation et 32 autresSimPipelineshutdown, 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é | Nature | Premiers champs |
|---|---|---|
MenuLayout | Structure de données | s, panelX, panelY, panelW, panelH, rowH, listY0, titleY |
PhysicsParamsGPU | Structure de données | fire_speed, fire_smokeRate, fire_ignitePlant, fire_igniteOil, fire_spreadRate, smoke_fadeRate, smoke_driftRate, water_flowRate |
ShaderCacheHeader | Structure de données | magic, version, keyHash, binaryFormat, payloadSize |
SimPassRect | Structure de données | simShader, computeShader, paintShader, activeTiles |
UiVertex | Structure de données | std, bloomBrightShader, bloomBlurShader, bloomCompositeShader |
BrushDab | Structure de données | x, y, std |
FtLibrary | Structure de données | std, true |
ParamSpec | Structure de données | id, label |
Afficher 6 entités de plus
PlayRegion | Structure de données | scaleX, scaleY |
|---|---|---|
DebugSettings | Structure de données | std |
DisplaySettings | Structure de données | std |
GameSettings | Structure de données | std |
ActiveTileRun | Structure de données | std |
BrushStrokePlan | Structure de données | std |
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.
AppDomaine et règles métier, 37 méthodesshutdown, frame, setSimGridSize, applyRuntimeSettings, applyRuntimeSettingsLight, applyRuntimeSettingsHeavyActiveTileMapSource principale, 23 méthodesreset, wakeAll, sleepAll, wakeFromGridTopDown, wakeBoundsPx, rememberBoundsPerfStatsSource principale, 12 méthodesbeginFrame, beginSim, endSim, beginPaint, endPaint, beginWorldRenderFontAtlasSource principale, 11 méthodesisReady, shutdown, invalidateGlTexture, resetGlResources, textWidth, drawTextShaderProgramSource principale, 8 méthodesloadFromFiles, loadComputeFromFile, use, uniformLocation, readFile, compileMenuRepeatStateDonnées et infrastructure, 3 méthodesreset, tick, tickAxisSwitchLinkHeartbeatSource principale, 2 méthodesstart, finish
7.9. Intégrations externes
Clients HTTP
Hôtes nommés dans le code
kroki.io1 fichiersscripts/regenerate-diagrams.py:26
7.10. Stack et dépendances
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
| Workflow | Déclencheurs | Tâches | Publie vers |
|---|---|---|---|
Documentation.github/workflows/docs.yml | push, lancement manuel |
| GitHub Pages |
Build NXSand.nro.github/workflows/native-nro.yml | push, demande de fusion, lancement manuel |
| — |
Release NXSand.github/workflows/release.yml | lancement manuel |
| 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
- antoinebou12. (2026, 5 novembre). nxsand. [Software repository] github.com.
- antoinebou12. (2026, 5 novembre). nxsand: README. [Repository documentation] github.com.
- antoinebou12. (2026, 5 novembre). source/gpu/sim_pipeline.hpp. [Source file] github.com.
- antoinebou12. (2026, 5 novembre). source/sim/sim_state.hpp. [Source file] github.com.
- antoinebou12. (2026, 5 novembre). Makefile. [Source file] github.com.
- 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.