Contribute to CNA
CNA is an open-source C++23 reimplementation of the XNA 4.0 API built on SDL3. Contributions of any kind are welcome — new implementations, tests, platform fixes, and documentation improvements all help.
Getting started
Step 1 — Clone CNA and initialise submodules
git clone https://github.com/openeggbert/cna.git
cd cna
git submodule update --init --recursive
This populates third_party/SDL, third_party/SDL_image, and third_party/SDL_mixer. SDL3 is built from source by CMake — no system SDL packages are required.
Step 2 — Clone sibling repositories
CNA requires sharp-runtime and, for the EasyGL backend, easy-gl, to be present as sibling directories next to cna/:
parent/
├── cna/
├── sharp-runtime/
└── easy-gl/
Clone them at the same level:
git clone https://github.com/openeggbert/sharp-runtime.git
git clone https://github.com/openeggbert/easy-gl.git
Step 3 — Build with EasyGL
cmake -S . -B build -DCNA_GRAPHICS_BACKEND=EASYGL
cmake --build build --target CNA CnaTests
The CNA target builds the framework library. The CnaTests target builds the GoogleTest unit-test binary. For other backends (SDL_RENDERER, BGFX, VULKAN) and cross-compilation instructions, see the Building documentation.
Step 4 — Run the tests
ctest --test-dir build --output-on-failure
All 4,373 unit tests should pass on a clean Linux build with the EasyGL backend. If any fail, please open an issue with the full CTest output.
Repository structure
| Path | Contents |
|---|---|
include/Microsoft/Xna/Framework/ |
Public C++ headers — the XNA 4.0 API surface. Any type or method added here must match the XNA 4.0 public API (or be marked NOXNA). |
src/ |
Implementation files corresponding to the public headers. |
tests/ |
GoogleTest unit tests (CnaTests target, 4,373 tests). Covers math types, geometry, curves, game loop semantics, PackedVector precision, and more. |
third_party/ |
Vendored submodules: SDL3, SDL3_image, SDL3_mixer. Do not modify these directly. |
docs/ |
CNA-internal documentation: xna-4-api-coverage.md, coverage.md, and related notes on implementation status. |
CHECKLIST.md |
Per-file porting checklist tracking which XNA types have been ported. Also explains the NOXNA marker convention. |
GRAPHICS_TASKS.md |
Graphics-specific implementation task plan listing remaining work per backend. |
The NOXNA marker
Rule: When porting XNA APIs, stay faithful to the public XNA 4.0 surface. Use the NOXNA marker only for C++ glue code that has no counterpart in the managed XNA/FNA API.
Methods and types annotated with a // NOXNA comment in the source are not part of the XNA 4.0 public API. They exist purely to support C++ idioms and integration patterns. Examples:
- Iterator support —
begin()/end()on collections to enable range-for loops GetTypeName()— runtime type name helper for debugging- RAII helpers and move constructors that have no equivalent in managed C#
The authoritative reference for the XNA 4.0 public API surface is FNA (C#). When in doubt whether a method belongs to the XNA API, check the corresponding FNA class. If it is present there without modification, it belongs in CNA without the NOXNA marker. If it is a C++-only addition, mark it NOXNA.
What needs work
Below are the most impactful contribution opportunities, grouped by area. Any of these would be a meaningful addition to the project.
Compiled .fx shader bytecode
The highest-leverage gap in the whole project. Effect's bytecode constructor throws, so any XNA game with custom HLSL shaders cannot be ported without rewriting them by hand — it is what blocks 23 of the 86 official XNA samples. Wants someone comfortable with DXBC/HLSL bytecode and a translation path to GLSL/SPIR-V.
bgfx RenderTargetCube depth attachment
A cube-map face with a Depth24Stencil8 attachment renders nothing at all on bgfx. Investigated three times with apitrace and RenderDoc; the framebuffer, view id and texture binding are all provably correct, yet the content never appears. Genuinely unsolved — a good puzzle for someone who knows GL/bgfx internals.
Bgfx custom ShaderEffect support
Bgfx reached full 2D+3D pixel-verified parity with EasyGL and Vulkan, but custom GLSL/SPIR-V ShaderEffect source compilation is still unsupported — CreateEffectBackend returns nullptr because bgfx wants precompiled binary shaders. Knowledge of bgfx's shader toolchain required.
BGFX rendering backend
The BGFX backend now has full 2D+3D pixel-verified parity with EasyGL and Vulkan. Remaining named gaps: custom ShaderEffect source compilation (above) and OcclusionQuery pixel-verified correctness, which can't be confirmed under this project's sandbox (software GL 2.1 driver, no dedicated-view architecture yet).
Windows CI
CNA builds on Windows with the SDL_RENDERER backend (MSVC 2022, clang-cl, or MinGW-w64) and is verified cross-compiled with MinGW-w64 plus running under Wine — but there's no native-hardware or CI coverage yet. Setting up a GitHub Actions Windows runner (CNA's existing CI currently covers only the Input and Devices/Sensors subsystems) would close a real gap.
macOS support
SDL3 supports macOS out of the box. CNA has no known macOS-specific blockers, but it has not been tested there. If you have a Mac, a build report or CI workflow would be very welcome.
Content pipeline / XNB parser
CNA has no XNB asset parser. The existing content loader accepts JSON-described assets. New loader types (fonts, tilesets, spritesheets) modelled on the existing pattern are always welcome, as is an XNB binary format reader.
Test coverage
4,373 unit tests exist and pass, but many XNA types and edge cases are uncovered. New GoogleTest unit tests for any Microsoft::Xna::Framework type or method are accepted without reservation — just follow the pattern in tests/. Separately, a 168-test EasyGL GPU/pixel integration suite passes 166/168 (2 documented pre-existing failures) — new pixel tests under examples/ are equally welcome.
Code style
- C++23 throughout. CNA requires GCC 12+, Clang 15+, or MSVC 2022 v17.8+. Use modern C++ features freely — structured bindings, ranges, concepts — but keep readability first.
- API shape is fixed. The
Microsoft::Xna::Frameworkpublic API mirrors XNA 4.0 exactly. Do not rename, remove, or add overloads to public methods without a compelling reason backed by FNA precedent. - Properties become getter/setter methods. C#
public int Width { get; set; }becomesintcs getWidth() constandvoid setWidth(intcs value)in C++. - Use
sharp-runtimetypes. Useintcs,bytecs,Single,String, events, and interfaces fromsharp-runtimeto match C# semantics. Avoid rawintorfloatat the public API boundary. - No extra runtime dependencies. The only permitted runtime dependencies are SDL3,
easy-gl(EASYGL backend), andsharp-runtime. Do not introduce new third-party libraries without prior discussion. - Mark non-XNA additions as
NOXNA. Any method or type added purely for C++ convenience must carry a// NOXNAcomment so that API coverage tooling stays accurate.
License and attribution
CNA is licensed under the Microsoft Public License (Ms-PL). All contributions must be compatible with the Ms-PL. By submitting a pull request you agree that your contribution will be distributed under the same license.
Deriving from FNA (C#): FNA is the authoritative XNA 4.0 reference and is also licensed under the Ms-PL. If you port logic from FNA's C# source into CNA, you must preserve the Ms-PL attribution. See NOTICE.md and THIRD_PARTY_NOTICES.md for the existing attribution text and the pattern to follow.