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

PathContents
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.

Open

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.

Open

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.

Open

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.

Parity (Phase 72)

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).

Needs native CI

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.

Unofficial

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.

Planned

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.

Always welcome

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::Framework public 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; } becomes intcs getWidth() const and void setWidth(intcs value) in C++.
  • Use sharp-runtime types. Use intcs, bytecs, Single, String, events, and interfaces from sharp-runtime to match C# semantics. Avoid raw int or float at the public API boundary.
  • No extra runtime dependencies. The only permitted runtime dependencies are SDL3, easy-gl (EASYGL backend), and sharp-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 // NOXNA comment 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.

View CNA on GitHub