CNA is a C++ reimplementation of the XNA 4.0 programming model, built on SDL3 and a pluggable graphics backend layer.
It is a framework/runtime and abstraction layer—not a game—designed to preserve XNA-style APIs (Microsoft::Xna::Framework) while using modern C++ internals.
CNA demonstrates engine-level C++ architecture, graphics abstraction design, and backend-oriented systems engineering.
git submodule update --init --recursive
cmake -S . -B build -DCNA_GRAPHICS_BACKEND=EASYGL
cmake --build build --target CNA CnaTests
ctest --test-dir build --output-on-failureLooking for a specific doc?
docs/has 57 files — seedocs/README.mdfor an index of what's current vs. historical.
Microsoft::Xna::Framework::Graphicsmilestone: qualified ~90% XNA/FNA compatibility, test-execution-verified (not estimated) — every one of the ~26 major Graphics classes is present, implemented, and tested. As of 2026-07-11, all 5 confirmed bugs behind the original 2026-07-09 milestone declaration are fixed (VulkanBlendState, EasyGL anisotropic filtering,IndexElementSize's numeric values,Model's root-bone override,SpriteBatch::Draw's optional source rectangle), and VulkanOcclusionQuery(previously architecturally blocked) is fixed too.docs/graphics-compatibility-report.mdis a dated snapshot from that declaration, kept for its methodology, not current status — seeNEXT.md§5 for the actively-maintained bug list. What's left to 100% is a smaller set of individually-tracked issues plus a handful of project-owner architecture decisions (e.g. SDL_RendererTextureAddressMode::Wrap/Mirror,Texture3D/TextureCubesampler-bind architecture) — none silent or undocumented.- Overall XNA 4.0 API surface: 227 of 245 public FNA types are present in CNA (92.7%, computed 2026-07-11 by diffing FNA's public type list against CNA's headers) — 100% for
Graphics/Audio/Input(+Touch)/Storage; the real gap is.Content(4/12 — no.xnbreader, by design) and.Media(25/25 present, but 14 are shells). Seedocs/xna-4-api-coverage.md. Note this is a different metric from the Graphics bullet above — this one counts whether a type/class exists at all across every XNA namespace (a raw presence count), while the Graphics "~90%" figure is a narrower, bug-weighted quality gate scoped to just the ~26 major Graphics classes (it also counts behavioral correctness, not just presence — Graphics itself is 91/91 = 100% present). The two numbers measuring different things is expected, not a typo or a contradiction. - The two gaps that matter most to a real port: no
.xnbcontent pipeline (CNA loads raw assets + JSON descriptors instead) and no compiled.fxshader bytecode support (Effect(GraphicsDevice&, byte[])) — the latter is the single biggest real gap, blocking 23 of the 86 official XNA samples in../cna-samples. Seedocs/migration-guide.md. SDL_RENDERERbackend: Implemented path focused on practical 2D rendering workflows; 2D-only by design (3D calls throw).EASYGLbackend: Most mature backend overall — implemented OpenGL-based path througheasy-gl, full 2D+3D pixel-verified coverage.VULKANbackend: Real, working 3D rendering (all 5 stock effects, render targets, depth/stencil state,BlendState,OcclusionQuery) — second-most mature backend; the one remaining named gap is an isolatedRasterizerState.DepthBiassub-case. Seedocs/xna-4-api-coverage.md's per-backend table for current detail.BGFXbackend: Broad 2D+3D functionality, largely pixel-verified parity with EasyGL/Vulkan as of this project's Phase 72 — but not unqualified full parity: known real limitations remain, including aDepth24Stencil8-attachedRenderTargetCubeface producing no colour output (Task 952, deferred, root cause not yet found),DrawIndexedPrimitivesExsilently discardingstartIndex/baseVertexon a sub-range indexed draw (Task 954), and occlusion-query pixel-count correctness that can't be verified under this project's own sandbox's software GL driver. SeeNEXT.md§5 for the current, complete list.WEBGPUbackend: Experimental fifth backend using nativewgpu-native. The current baseline covers device/surface setup, clear/present, RGBA8Texture2D, vertex/index uploads and WGSL SpriteBatch rendering. It is not yet a 3D-parity replacement for EasyGL/Vulkan/Bgfx; seedocs/webgpu-backend.mdandplan_webgpu.md.D3D9backend: Windows-only native Direct3D 9 backend targeting real XNA 4.0 pixel authenticity, not just feature parity — it runs Microsoft's own vendored Stock Effects HLSL bytecode, cross-compiled via MinGW-w64 and verified through Wine+DXVK on a real GPU (14 CTest binaries). A checked-in 31-scene oracle corpus diffs CNA's render against the real XNA 4.0 runtime's own render of the same scene at--tolerance 0: 0/31 scenes currently diverge.GraphicsProfile.Reach/.HiDefenforcement is real (the only CNA backend where it is). Render targets sampled as textures, non-ColorSurfaceFormat, and real-Windows hardware verification are still open. Seedocs/d3d9-backend.md,docs/d3d9-divergence-report.md, andplan_dx9.md.D3D11backend: Windows-only native Direct3D 11 backend, cross-compiled via MinGW-w64 and verified through Wine+DXVK on a real GPU (6 CTest binaries, 96+ checks) — all 10 stock HLSL shader variants (BasicEffect/AlphaTestEffect/DualTextureEffect/EnvironmentMapEffect/SkinnedEffect), textures/render targets (MRT/MSAA/occlusion queries), state objects, SpriteBatch, and a runtime-D3DCompile()customShaderEffectpath are real and pixel-verified. Real-Windows hardware verification (device-lost recovery, WARP fallback, driver-specific parity) is still open. Seedocs/d3d11-backend.mdandplan_dx.md.D3D12backend: Windows-only native Direct3D 12 backend, cross-compiled via MinGW-w64 and verified through Wine+vkd3d-proton on a real GPU, off-screen only (D3D12_SmokeCTest, 80/80 checks) — device/queue/heaps/command-lists/fences/barriers/PSOs/root-signatures are real, all 10 stock HLSL shader variants (same DXBC asD3D11) and a realSpriteBatchare pixel-verified off-screen, and device-removed recovery is real and functionally proven. Swap-chain presentation is a known, real, unresolved gap on this dev loop (genuine Wine/vkd3d-protondxgi.dllarchitecture mismatch, not a CNA bug); runtime-settable blend/depth-stencil/rasterizer state, per-slotSamplerState, render targets,Texture3D, occlusion queries, and real-Windows hardware verification are all still open. Seedocs/d3d12-backend.mdandplan_dx.md.CANVASbackend: Emscripten-only HTML Canvas 2D backend (SpriteBatch/Texture2D/SpriteFont/RenderTarget2Donly, 2D-only by design likeSDL_RENDERER) —SpriteBatch(incl. rotation/origin/flip/tint/transform), textures/render targets,BlendState/SamplerStatemapping, andSpriteFontare all implemented and structurally reviewed, verified via a realemcmake/emcc6.0.2 configure+build (CnaTestslinks and a backend-agnostic GTest suite genuinely passes undernode). Not yet pixel-verified in a real browser — this dev loop has no DOM/CanvasRenderingContext2Dat all (nodehas none;SDL_Init(SDL_INIT_VIDEO)itself throws under Emscripten/node). Seedocs/canvas-backend.md(incl. a manual browser verification checklist) andplan_canvas.md.ASCIIbackend: SDL-windowed retro glyph-grid backend — not a real terminal/TTY backend, a thin decorator aroundSDL_RENDERER's own implementation. The game draws normally into a private offscreen target;Present()quantizes that frame into a glyph/color grid (a hand-authored, license-free 10-glyph density ramp, no vendored font asset) and draws it onto the real window. Two runtime modes (CNA_ASCII_MODE=BLACKWHITE|COLOR, no rebuild needed). 2D-only by design, same asSDL_RENDERER; fully pixel-verified (6 CTest binaries, real window + real readback, noneeds_humangate unlike the GPU backends above). Seedocs/ascii-backend.mdandplan_ascii.md.DX3backend: Cross-platform (genuinely — builds and runs via ordinary/usr/bin/c++, no MinGW/Wine needed) DirectDraw-shaped 2D backend fronting../free-direct, a sibling project's own DirectDraw reimplementation. 2D-only by design, same spirit asSDL_RENDERER. All 8 plan phases complete: real device/window bring-up with a CPU-owned "shadow backbuffer" (working around a realLock()-on-primary gap infree-directitself), texture/render-target backends, a CPUSpriteBatchcompositor (BltFastfast path + a from-scratch edge-function rasterizer for everything else), all 4 realBlendStatepresets with genuinely distinct formulas (not one collapsed baseline), bilinear filtering, and realWrap/Mirrortexture addressing — the latter two are a real capability win overSDL_RENDERER, which hasWrap/Mirror⛔ BLOCKED. Seedocs/dx3-backend.mdandplan_dx3.md.- Verification methodology: differential testing against a real, running
FNA.dllreference implementation (tools/fna-reference/), disputed behavior settled against genuine XNA 4.0 on a Windows 7 VM, and a compile-timeNOXNApurity check (a dedicated CMake build option that turns every non-XNA-tagged declaration into a[[deprecated]]warning under-Werror) — seeCHECKLIST.md's "NOXNA markers" section andCMakeLists.txt. - CI is Linux-only and partial (see
.github/workflows/): it currently runs only theInputandDevices/Sensorsgtest suites — not the full ~4,370-test unit suite and not the ~490-test GPU pixel-test suite across the 4 established graphics backends; the experimental WebGPU backend does not yet have pixel-test coverage. Everything Graphics-related in this README is verified by running the suites locally and by hand, not by an automated Graphics CI gate; there is currently no Windows, macOS, or Android CI at all (Windows/Android are verified manually, per §7/§9 below).
- Recreate the XNA developer experience in native C++.
- Provide a native C++ path for teams that like the XNA/MonoGame model but need non-managed runtime/toolchain control.
- Mirror core XNA namespaces and API patterns while implementing them incrementally.
- Decouple gameplay-facing API from rendering backend implementation details.
- Enable one high-level API surface across different rendering technologies.
- Keep SDL/OpenGL/Vulkan-level concerns behind framework abstractions.
- Public API uses XNA-style namespaces, especially under
Microsoft::Xna::Framework. - Core game loop and framework primitives are available (
Game,GameTime, graphics types, input/audio surfaces). - Compatibility is partial and evolving; implementation status is tracked progressively in source.
Keyboard,Mouse(incl.MouseCursor),GamePad(up to 4 players),TouchPanel/TouchCollection, and theGestureDetectorgesture recognizer (Tap/DoubleTap/Hold/Drag/Flick/Pinch) — all underMicrosoft::Xna::Framework::Input, matching FNA/XNA 4.0 behavior member-for-member. Seeplan_input.mdfor the full FNA-parity audit record.- NOXNA extensions beyond stock XNA:
TextInputEXT(IME composition), rumble/trigger-rumble/light-bar/ gyro/accelerometer onGamePad, rawCNA::Input::Joysticks(distinct fromGamePad's mapped view), device-levelCNA::Input::Sensors/Power, andCNA::Input::Hapticsfor standalone haptic devices. - Single SDL event funnel (
SdlInputBridge::ProcessEvent), backend-agnostic — Input behavior is identical across all 4 graphics backends (EasyGL/Vulkan/bgfx/SDL_RENDERER), verified by theCnaTestsinput suite.
GraphicsDeviceabstraction with backend delegation.SpriteBatchAPI withBegin(...)/Draw(...)/End()workflow.Texture2Dabstraction with backend-owned texture resources.
- SDL3-based platform foundation for windowing/input/audio integration.
- Backend abstraction supports targeting multiple rendering paths from one API layer.
- Windows support via the
SDL_RENDERERbackend (MSVC, clang-cl, or MinGW-w64) — cross-compiled with MinGW-w64 and verified running under Wine. - Linux support via
EASYGL(OpenGL) orSDL_RENDERER. - Web (Emscripten) and Android (NDK) targets are implemented and verified, not just
architecturally planned — see section 7 (Networking, Services & Avatar) below for real
cross-platform
Netverification on both.
- Native C++23 codebase and explicit control over memory/lifetime.
- Interface-driven backend boundaries to keep hot rendering paths backend-specific.
- Lightweight gameplay-facing API over backend-specific implementations.
CNA is organized into clear layers with strict responsibility boundaries:
+-----------------------------------------------------------+
| Game / Application Code |
| (uses Microsoft::Xna::Framework API) |
+------------------------------+----------------------------+
|
v
+-----------------------------------------------------------+
| API Layer (XNA-style public surface) |
| include/Microsoft/Xna/Framework/... |
| - Game, GraphicsDevice, SpriteBatch, Texture2D, ... |
+------------------------------+----------------------------+
|
v
+-----------------------------------------------------------+
| CNA Internal Layer (abstractions/factories) |
| include/CNA/Internal/Backends + src/CNA/Internal/Backends |
| - IGraphicsBackend, ISpriteBatchBackend, ITextureBackend |
+------------------------------+----------------------------+
|
v
+-----------------------------------------------------------+
| Backend Implementations |
| src/CNA/Internal/Backends/{SdlRenderer,EasyGL,Vulkan} |
+-----------------------------------------------------------+
- Public API lives under
include/Microsoft/...and stays framework-facing. - Backend contracts live under
CNA::Internal::Backendsinterfaces. - Backend implementations live under
src/CNA/Internal/Backends/.... GraphicsDeviceconstructs backends via factory (CreateGraphicsBackend(...)) based on build-time backend selection.
SpriteBatch is the primary 2D rendering abstraction.
- You create it against a
GraphicsDevice. - Call
Begin(...)to start a draw pass. - Issue
Draw(...)calls for textures/sprites. - Call
End()to close the batch.
The API surface is backend-agnostic, while rendering behavior is executed by backend-specific ISpriteBatchBackend implementations.
This keeps game code stable while allowing backend-specific optimizations in SDL renderer, EasyGL, or future Vulkan paths.
CNA supports backend selection at build-time via CNA_GRAPHICS_BACKEND (choose one backend per build configuration):
SDL_RENDEREREASYGLBGFXVULKANWEBGPUHEADLESSSOFTWARED3D11(Windows-only)D3D12(Windows-only)CANVAS(Emscripten only)ASCIIDX3
-
SDL_Renderer backend
- Simpler integration and broad SDL portability.
- Good for straightforward 2D workflows.
-
EasyGL backend (OpenGL-based path through
easy-gl)- Custom shader-driven rendering path.
- Better control over rendering behavior and extensibility than fixed SDL renderer usage.
-
BGFX backend
- Dedicated backend option with the same public rendering API coverage as other backends.
- Integrates through CNA backend abstraction and can be selected via
CNA_GRAPHICS_BACKEND=BGFX. - Uses native
bgfxAPI (window/platform init, texture creation, sprite draws, frame submission), notSDL_Rendererrendering. bgfxis integrated in CMake for this backend viaFetchContent(bgfx.cmake).
-
Vulkan backend
- Present as an architecture target/scaffold.
- Current implementation is incomplete and contains TODO/stub areas.
Beyond graphics, CNA ports the XNA 4.0 GamerServices and Net namespaces (and, within
GamerServices, the Avatar subsystem), with real cross-platform networking behind them.
- Complete XNA-shaped port of the Xbox LIVE-era gamer services API surface:
Gamer,SignedInGamer,GamerProfile,FriendGamer/FriendCollection, leaderboards (LeaderboardReader/LeaderboardWriter/LeaderboardEntry),Guide, achievements, and more. - Not binary-compatible with real Xbox Live — reimplements the public API shape with local/synthetic semantics, matching how FNA itself already handles this namespace.
- Complete
NetworkSessionAPI surface (5 enums + 18 classes). - Real networking for
NetworkSessionType::SystemLink, backed by ENet (reliable UDP, vendored directly underthird_party/enet) — hosting, joining, LAN discovery,AppDatarelay, disconnect handling, andStartGame/EndGamestate broadcast all run over a genuine transport, not a stub. Every otherNetworkSessionTyperemains a synthetic (non-networked) stub, matching upstream XNA/FNA behavior. - Verified real networking across four platforms:
- Linux — native ENet/UDP, including a genuine two-OS-process loopback test.
- Windows — native ENet/UDP via WinSock2; cross-compiled with MinGW-w64 and verified running under Wine.
- Web (Emscripten) — real ENet traffic carried over actual WebSocket connections. A browser tab can only ever be a network client (browsers cannot open listening sockets at all); real hosting requires a Node.js-run process.
- Android (NDK) — native ENet/UDP via bionic libc's genuine POSIX sockets, verified on a real x86_64 emulator — no platform-specific transport workarounds needed at all, unlike Web.
AvatarAnimation,AvatarDescription,AvatarRenderer, and their supporting enums/types (all withinMicrosoft::Xna::Framework::GamerServices) are ported from a decompiled real Microsoft XNA 4.0 reference assembly — FNA itself never implemented Avatar, since real avatar rendering required Xbox Live's cloud avatar-editor service. The API shape is complete, with the real (occasionally surprising, always-inert) stubbed behavior of the original assembly preserved faithfully rather than "improved."
- Language: C++23
- Core platform/runtime library: SDL3 (vendored via Git submodule at
third_party/SDL) - Media integration:
SDL3_image,SDL3_mixer(vendored via Git submodules) - Graphics dependency:
easy-gl(forEASYGLbackend) - Networking: ENet (vendored directly at
third_party/enet) — reliable-UDP transport backingMicrosoft::Xna::Framework::Net'sSystemLinksessions - Utility/runtime layer:
sharp-runtime - Build system: CMake
- Tests: GoogleTest (
CnaTeststarget)
- CMake 3.20+
- C++23-capable compiler (GCC 12+ or Clang 15+)
- Dependency directories available to CMake:
../sharp-runtime../easy-gl(only needed forEASYGLbackend)
- SDL3, SDL3_image, and SDL3_mixer are built from vendored submodules by default — no system SDL packages required.
- CMake 3.20+
- One of:
- MSVC 2022 (Visual Studio 2022, v17.8+, with C++20/23 support)
- clang-cl (LLVM for Windows, targeting MSVC ABI)
- MinGW-w64 (either natively on Windows or cross-compiled from Linux)
- Dependency directories:
../sharp-runtime(no external dependencies — builds cleanly on Windows)
- SDL3, SDL3_image, and SDL3_mixer are built from vendored submodules by default — no pre-built SDL binaries or
CMAKE_PREFIX_PATHconfiguration required.
Before the first build, initialise the vendored SDL submodules:
git submodule update --init --recursiveThis populates third_party/SDL, third_party/SDL_image, and third_party/SDL_mixer.
After that, no system SDL packages are required.
Building from a source zip/tarball instead of a Git clone? GitHub's "Download ZIP" and release archives do not include submodule contents, so
third_party/SDLwill be empty and CMake aborts with a clear error (Missing vendored 'SDL' … Run: git submodule update --init --recursive, fromcmake/ThirdPartySDL.cmake). Either clone with Git and run the command above, or set-DCNA_USE_SYSTEM_SDL=ONto use system-installed SDL3 packages.
git submodule update --init --recursive
cmake -S . -B build -DCNA_GRAPHICS_BACKEND=EASYGL
cmake --build build --target CNA CnaTestsgit submodule update --init --recursive
cmake -S . -B build-sdlrenderer -DCNA_GRAPHICS_BACKEND=SDL_RENDERER
cmake --build build-sdlrenderer --target CNA CnaTestsOn Windows the SDL_RENDERER backend is selected automatically when no backend is
explicitly specified. SDL is built from the vendored submodule — no pre-built SDL
binaries or CMAKE_PREFIX_PATH needed.
git submodule update --init --recursive
cmake -S . -B build-win -DCNA_GRAPHICS_BACKEND=SDL_RENDERER
cmake --build build-win --target CNA CnaTests# Install cross toolchain
sudo apt install mingw-w64
git submodule update --init --recursive
cmake -S . -B build-windows \
-DCMAKE_TOOLCHAIN_FILE=cmake/toolchains/mingw-w64.cmake \
-DCNA_GRAPHICS_BACKEND=SDL_RENDERER
cmake --build build-windows --target CNA CnaTestsIf you prefer to link against system-installed SDL3 packages instead of the
vendored submodules, pass -DCNA_USE_SYSTEM_SDL=ON:
cmake -S . -B build -DCNA_USE_SYSTEM_SDL=ON -DCNA_GRAPHICS_BACKEND=SDL_RENDERER
cmake --build build --target CNA CnaTestsThis calls find_package(SDL3 REQUIRED), find_package(SDL3_image REQUIRED),
and find_package(SDL3_mixer REQUIRED) and requires those packages to be present
on the system (e.g. installed via your package manager).
cmake -S . -B build -DCNA_GRAPHICS_BACKEND=BGFX
cmake -S . -B build -DCNA_GRAPHICS_BACKEND=VULKANA native Direct3D 9 backend, Windows-only (hard-FATAL_ERROR-gated at configure time, same as
D3D11/D3D12), targeting real XNA 4.0 pixel authenticity rather than just feature parity —
see docs/d3d9-backend.md for what that means and why. Developed and
verified on this repo's own Debian dev machine via the same MinGW-w64 cross toolchain the other
Windows backends use, tested locally through Wine + DXVK (scripts/run-wine-dxvk9.sh). See
docs/d3d9-backend.md and plan_dx9.md for full detail.
# Install cross toolchain (same package D3D11/D3D12/SDL_RENDERER's own Windows cross-build uses)
sudo apt install mingw-w64
git submodule update --init --recursive
cmake -S . -B cmake-build-d3d9 \
-DCMAKE_TOOLCHAIN_FILE=cmake/toolchains/mingw-w64.cmake \
-DCNA_GRAPHICS_BACKEND=D3D9 \
-DCNA_BUILD_TESTS=ON
cmake --build cmake-build-d3d9 --target CNARunning the resulting .exes needs a Wine + DXVK dev-loop, in a prefix separate from D3D11's own
(docs/d3d9-backend.md has full setup steps); CTest wires this in automatically:
ctest --test-dir cmake-build-d3d9 -L D3D9 --output-on-failureA native Direct3D 11 backend, Windows-only (hard-FATAL_ERROR-gated at configure time on any other
CMAKE_SYSTEM_NAME). Developed and verified on this repo's own Debian dev machine via the same
MinGW-w64 cross toolchain SDL_RENDERER uses, tested locally through Wine + DXVK
(scripts/run-wine-dxvk.sh) before any real-Windows verification pass. See
docs/d3d11-backend.md and plan_dx.md for full detail.
# Install cross toolchain (same package SDL_RENDERER's own Windows cross-build uses)
sudo apt install mingw-w64
git submodule update --init --recursive
cmake -S . -B cmake-build-d3d11 \
-DCMAKE_TOOLCHAIN_FILE=cmake/toolchains/mingw-w64.cmake \
-DCNA_GRAPHICS_BACKEND=D3D11 \
-DCNA_BUILD_TESTS=ON
cmake --build cmake-build-d3d11 --target CNARunning the resulting .exes needs a Wine + DXVK dev-loop (docs/d3d11-backend.md has full setup
steps); CTest wires this in automatically:
ctest --test-dir cmake-build-d3d11 -R D3D11 --output-on-failureA native Direct3D 12 backend, Windows-only (hard-FATAL_ERROR-gated at configure time, same as
D3D11). Also developed and verified on this repo's own Debian dev machine via the same MinGW-w64
cross toolchain, but tested locally through Wine + vkd3d-proton (scripts/run-wine-vkd3d.sh),
not DXVK — D3D12 needs a different Windows-D3D-to-Vulkan translation layer than D3D11, with its own
dedicated Wine prefix. Every check currently runs off-screen only — swap-chain presentation is
a known, real, unresolved gap on this dev loop (see docs/d3d12-backend.md). See
docs/d3d12-backend.md and plan_dx.md for full detail.
# Install cross toolchain (same package D3D11/SDL_RENDERER's own Windows cross-build uses)
sudo apt install mingw-w64
git submodule update --init --recursive
cmake -S . -B cmake-build-d3d12 \
-DCMAKE_TOOLCHAIN_FILE=cmake/toolchains/mingw-w64.cmake \
-DCNA_GRAPHICS_BACKEND=D3D12 \
-DCNA_BUILD_TESTS=ON
cmake --build cmake-build-d3d12 --target CNARunning the resulting .exes needs a Wine + vkd3d-proton dev-loop, in a prefix separate from
D3D11's own (docs/d3d12-backend.md has full setup steps); CTest wires this in automatically:
ctest --test-dir cmake-build-d3d12 -R D3D12 --output-on-failureThis repository intentionally prioritizes framework/runtime development over shipping a bundled game demo executable.
Use these commands for quick environment and rendering-path verification:
ctest --test-dir build --output-on-failure
cmake --build build --target hello-triangle-sdl| Platform | Compiler | Backend | Status |
|---|---|---|---|
| Linux x86_64 | GCC 12+ | EASYGL, SDL_RENDERER | ✅ |
| Linux x86_64 | Clang 15+ | EASYGL, SDL_RENDERER | ✅ |
| Windows x86_64 | MSVC 2022 | SDL_RENDERER | planned |
| Windows x86_64 (native) | MinGW-w64 | SDL_RENDERER | planned |
| Linux → Windows (cross) | MinGW-w64 | SDL_RENDERER | ✅ verified building + full test suite under Wine |
| Linux → Windows (cross) | MinGW-w64 | D3D9 | ✅ verified building + D3D9 CTest suite (14 tests) under Wine+DXVK on a real GPU — 0/31 oracle scenes diverge from real XNA 4.0 at --tolerance 0; real Windows hardware verification still open, see docs/d3d9-backend.md |
| Linux → Windows (cross) | MinGW-w64 | D3D11 | ✅ verified building + D3D11 CTest suite (6 tests, 96+ checks) under Wine+DXVK on a real GPU — real Windows hardware verification still open, see docs/d3d11-backend.md |
| Linux → Windows (cross) | MinGW-w64 | D3D12 | ✅ verified building + D3D12 CTest suite (1 test, 80/80 checks, off-screen only) under Wine+vkd3d-proton on a real GPU — swap-chain presentation and real Windows hardware verification both still open, see docs/d3d12-backend.md |
| Web (Emscripten) | emcc/Clang (emsdk) | EASYGL | ✅ verified building + running under Node.js |
| Android (NDK) | Clang (NDK 29/30) | EASYGL | ✅ verified building + running on a real x86_64 emulator |
Minimal XNA-style game skeleton in CNA:
#include <memory>
#include "Microsoft/Xna/Framework/Game.hpp"
#include "Microsoft/Xna/Framework/Color.hpp"
#include "Microsoft/Xna/Framework/Graphics/GraphicsDeviceManager.hpp"
#include "Microsoft/Xna/Framework/Graphics/SpriteBatch.hpp"
#include "Microsoft/Xna/Framework/Graphics/Texture2D.hpp"
using namespace Microsoft::Xna::Framework;
using namespace Microsoft::Xna::Framework::Graphics;
class MyGame final : public Game {
public:
MyGame()
: graphics_(this)
{
}
protected:
void LoadContent() override
{
spriteBatch_ = std::make_unique<SpriteBatch>(getGraphicsDeviceProperty());
logo_ = std::make_unique<Texture2D>("assets/logo.png", getGraphicsDeviceProperty());
}
void Update(GameTime& gameTime) override
{
(void)gameTime;
// Update game state here.
}
void Draw(const GameTime& gameTime) override
{
(void)gameTime;
auto& device = getGraphicsDeviceProperty();
device.Clear(CornflowerBlue);
spriteBatch_->Begin();
spriteBatch_->Draw(*logo_, 100.0f, 80.0f);
spriteBatch_->End();
device.Present();
}
private:
GraphicsDeviceManager graphics_;
std::unique_ptr<SpriteBatch> spriteBatch_;
std::unique_ptr<Texture2D> logo_;
};
int main()
{
MyGame game;
game.Run();
return 0;
}- API mirroring strategy: Public classes follow XNA naming and namespace conventions to reduce conceptual migration cost from XNA/MonoGame-style code.
- Abstraction design: Gameplay-facing rendering APIs (
GraphicsDevice,SpriteBatch,Texture2D) delegate to backend interfaces instead of exposing low-level renderer objects. - Separation of concerns: Public framework API, internal contracts, and backend implementations are physically separated in directory structure and ownership.
- Backend-oriented architecture: Backend can be swapped at build-time with a single CMake option while keeping high-level game code stable.
- Performance-minded C++ implementation: Native code path enables tighter control over memory, lifetime, and rendering behavior than managed runtime abstractions.
- Continue expanding XNA API coverage and behavior parity (incremental, class-by-class).
- Implement compiled
.fxshader bytecode support (Effect(GraphicsDevice&, byte[])) — the single biggest real gap; it blocks 23 of the 86 official XNA samples in../cna-samples. - Consider a real
.xnbcontent-pipeline reader (currently a deliberate design choice, not a bug — CNA loads raw assets + JSON descriptors instead). - Close the remaining named architecture-decision gaps (SDL_Renderer
TextureAddressMode::Wrap/Mirror, SDL_RendererTexture3D/TextureCubeconstruction, EasyGL non-ColorSurfaceFormatGPU forwarding,Texture3D/TextureCubesampler-bind architecture) — seeNEXT.md§5 anddocs/graphics-backend-feature-matrix.md. - Strengthen cross-platform execution targets and validation coverage.
CNA is licensed under the Microsoft Public License (Ms-PL). See the LICENSE file for details.
Portions of CNA are derived from or based on FNA, which is also licensed under the Microsoft Public License (Ms-PL).