1. Introduction
The ultimate SDL3 companion for 2D games and tools.
CRM64Pro is a modern, free, cross-platform C++17 Game Development Kit built on SDL3, with rendering, particle effects, 2D lighting, audio, video, Scene tooling, CDC archives and the EditorC64 asset workflow. It is designed to help developers create high-performance 2D games, tools and interactive applications through a clean, modular and hardware-accelerated framework.
CRM64Pro is distributed under the zlib license.
Core
Modern C++17 framework built on SDL3, with a modular manager-based API. Independent logic and rendering rates, high-resolution timing, delta time and render interpolation. Platform-dependent rendering backends: Direct3D 9/11/12, Vulkan, Metal, GPU, OpenGL and OpenGL ES, with software rendering support.
Custom memory management with allocation tracking and engine-provided STL containers. Configurable logging, profiling and micro-benchmarking tools. Debug windows with live numeric and string watches, plus an embedded console with contextual auto-completion, quoted arguments, scrollback, command history and unified help.
CDCv2 asset archives with compression, support for files larger than 4 GB, validation, optional encrypted storage, streaming block access and defragmentation. Integrated XML parsing, xxHash hashing and pseudo-random number generation using WELL512, MWC and PCG32. Configuration management with a customizable graphical setup launcher.
|
EditorC64
Integrated resource editor for engine assets and CDC archives. Sprite animation preview, body and bounds alignment with Resize and Best fit options, and sprite sheet compaction with configurable margins.
Particle-effect authoring and live preview. Scene particle placement, object editing and direct map movement. Universal VTT map import with configurable blocking roles. Animated GIF, WebP and H.264 import into Tiled-compatible animated tilesets.
|
Graphics and media
Image, cursor, sprite, tile, font and drawing modules, with render target support. Sprite animation, sub-pixel positioning, interpolation, scaling, rotation and blending. Image loading for BMP, PNG, JPG/JPEG, PCX, TGA and WebP, with BMP and PNG saving. Built-in image filters for color adjustments, blur, distortion, pixelation and alpha processing.
Particle effects with presets, animated appearance, timed bursts, sub-emitters and collision. 2D lighting with ambient intensity, animated point and spot lights, glow effects and occluders. Persistent Physics collision sets supporting rectangles, circles, ellipses, segments and polygons.
Unified audio playback for music, sound effects, voice and ambient audio, supporting WAV, Ogg Vorbis, FLAC, MP3 and tracker modules such as MOD, XM, S3M and IT. H.264 video playback with seeking, metadata, audio integration and streamed CDC storage.
|
Scene system
Advanced 2D Scene and world management with native Tiled TMX/TSX support. Tile, image and object layers, animated tiles and custom object factories. Camera control, smooth scrolling, parallax, triggers and debug overlays. Scene loading from external files or CDC archives.
Runtime objects for animated lights, occluders, portals and independent particle emitters. Particle collision against tile layers and selected object shapes. Configurable overlays for object bounds, shapes, names and triggers.
|
GUI system
GUI panels with typed widgets, customizable themes, callbacks and flow layouts. Built-in labels, images, frames, buttons, check boxes, progress bars, sliders, text edits, number edits, lists and combo boxes.
Text alignment and configurable widget appearance and interaction states. Controls for in-game interfaces, editors, tools and configuration screens.
|
Networking
TCP/IP client/server networking with dedicated or in-application server operation. Asynchronous queues, diagnostics and configurable backpressure controls. Challenge-response login and optional AES-CTR session encryption.
Authoritative and non-authoritative modes. In authoritative mode, every user packet passes through the configured server callback using server-derived sender identity. Server shutdown restricted to the owning process.
|
Developed by MegaStorm Systems.
Visit the official website for updates and more projects and games. | |
2. Supported platforms
The GDK runs on major operating systems. Thanks to SDL3, it supports a wide variety of hardware-accelerated rendering and low-latency audio drivers.
| Platform | Requirements | Render drivers | Audio drivers |
|
| Windows 10 and 11
(64-bit only) | Direct3D 9
Direct3D 11
Direct3D 12
Vulkan
GPU
OpenGL
Software | WASAPI
DirectSound |
|
| Ubuntu 20+ or RHEL 8+
(Kernel 4.18+ and GLIBC 2.28, 64-bit only) | Vulkan
GPU
OpenGL
X11
Wayland
Software | PulseAudio
ALSA |
|
| macOS 10.15+
(Catalina or later for x86_64)
macOS 11+
(Big Sur or later for arm64) | Metal
Vulkan
GPU
OpenGL
Software | CoreAudio |
|
| Android
Not available yet
Android 5.0+ (API 21+) | OpenGL ES
Vulkan | AAudio
OpenSL ES |
3. Installation
This section describes how to install and configure the CRM64Pro GDK for development on the supported platforms.
3.1. Windows (Visual Studio 2022+)
|
|
| Windows Development
Executable Installer (Inno Setup)
|
1. Download and Install CRM64Pro is distributed as a standard Windows installer created with Inno Setup (for example: CRM64Pro-X.Y.Z-win-x64.exe).
The installer will deploy headers, libraries and the EditorC64 into the selected destination.
The following libraries are provided:
-
CRM64Pro.lib – Dynamic linking (DLL import library)
-
CRM64Pro.static.lib – Static linking (Release)
-
CRM64Pro.static-debug.lib – Static linking with debug information
2. Configure Visual Studio The installer creates the system environment variable CRM64ProLib, which points to the selected installation directory containing CRM64Pro.h and the library files.
For development from a source checkout, set CRM64ProLib in the Windows environment variables to the checkout's Lib/ directory, for example C:\CRM64Pro\Lib.
Use $(CRM64ProLib) in your Visual Studio project properties:
-
Right-click your project in Solution Explorer and select Properties.
-
Select All Configurations and x64 platform.
-
Add
$(CRM64ProLib) to C/C++ → General → Additional Include Directories.
-
Add
$(CRM64ProLib) to Linker → General → Additional Library Directories.
-
Add one of the following to Linker → Input → Additional Dependencies:
-
CRM64Pro.lib (Dynamic linking)
-
CRM64Pro.static.lib or CRM64Pro.static-debug.lib (Static linking)
3. Runtime (DLL) When using dynamic linking, ensure that CRM64Pro.dll is located next to your executable or available in the system PATH (the installer allows to update this automatically).
3.2. Linux (GCC 13+)
|
|
| Linux Development
Self-Extracting Bash Installer
|
1. Download and Install CRM64Pro for Linux is distributed as a self-extracting Bash installer (for example: CRM64Pro-X.Y.Z-linux-x64.sh).
Run the installer from a terminal:
chmod +x CRM64Pro-X.Y.Z-linux-x64.sh
sudo ./CRM64Pro-X.Y.Z-linux-x64.sh
The installer places headers and libraries in standard system locations (e.g. /usr/local/include and /usr/local/lib).
2. Compiling Once installed, CRM64Pro can be linked using standard compiler flags:
g++ main.cpp -o mygame -lCRM64Pro
3.3. macOS (Clang 13+)
|
|
| macOS Development
DMG Package (Universal Binary)
|
1. Download and Install CRM64Pro is distributed as a DMG package. The installer provides a universal library supporting both x86_64 and arm64 (Apple Silicon) architectures.
Headers and libraries are installed into standard locations (e.g. /usr/local or /Library).
2. Compiling You can compile from the terminal or configure Xcode normally:
clang++ main.cpp -o mygame -lCRM64Pro
4. Getting started
Ready to write code? Jump straight into development with the practical examples.
|
| First time using the GDK?
Follow the step-by-step guides to create your first window, render sprites, play audio files, etc. | View Tutorials >> |
5. Game architecture
CRM64Pro abstracts the complexity of modern game loops into a flexible "Governor" pattern (Main::update). This allows developers to choose the synchronization strategy that best fits their game genre, from simple variable time-step loops to high-precision interpolated fixed-step systems.
Threading and frame execution
The main application thread calls Main::update(), runs application logic, owns public GDK state and performs every render operation. Public methods are main-thread operations unless their documentation explicitly says otherwise. See Threading conventions for the API contract.
Internal work never changes that contract. Audio mixing and NetTCP socket I/O run independently, while particle workers run only during a synchronous ParticleMgr update batch. Scene layer state, object transforms, callbacks, resources and all GFX calls remain on the main thread.
Frame execution timeline
Particle update rule:
Update standalone emitters through ParticleMgr::update(). Scene-owned emitters are updated automatically by Scene::update(); do not update them separately through ParticleMgr. Calling ParticleEmitter::update() directly remains the main-thread serial alternative for a deliberately unmanaged emitter. Every update call returns only after its worker jobs complete.
|
| Game loop methods
From basic to professional approaches
|
Timing values
Main exposes three timing values. They are intentionally separate because logic updates and rendering do not always run at the same rate:
| Method | Use it for | Fixed logic mode | Variable logic mode |
| Main::getLogicDeltaTime() | Game simulation, physics, AI, particles, Scene updates and playback advancement. | Returns the fixed logic step, exactly 1.0 / LFR, for every consumed logic update. | Returns the current frame delta. |
| Main::getInterpolationFactor() | Render-only interpolation between the previous and current logic state. | Returns the accumulator fraction in the [0.0, 1.0) range. | Returns 0.0. |
| Main::getDeltaTime() | Wall-clock frame elapsed time, profiling, diagnostics, or effects that intentionally depend on real frame time. | Returns the last engine-frame elapsed time; this is not the logic step. | Returns the current frame delta. |
Rule:
Use Main::getLogicDeltaTime() inside logic code. Use Main::getInterpolationFactor() only while rendering. Use Main::getDeltaTime() only when actual elapsed wall-clock frame time is required.
When the application calls Scene::update(), Scene reads Main::getLogicDeltaTime() internally, so Scene simulation speed is independent from render rate. Video playback is advanced by Main with the same logic delta. Sprite position interpolation uses Main::getInterpolationFactor() during rendering; Sprite animation timing remains internally managed by the Sprite module.
5.1. Variable Time Step (Synchronous)
This is the classic "render-as-fast-as-possible" loop. Logic and Graphics updates occur sequentially in the same iteration. The "Main loop" will run at the maximum speed provided by the CPU.
-
Mechanism: update() processes events and returns control codes. You run logic when it returns 0, and render when the engine emits ::EC_RENDER.
-
Pros: Extremely simple to implement and debug.
-
Cons: Physics and game speed are tied to framerate. Requires carefully managed "Delta Time" for movement, or the game will run faster on better hardware.
-
Best for: Simple demos, visual novels, or learning projects.
Performance Note:
You can use CRM64Pro::ConfigMgr::setMTFriendly() to specify a minimum wait time (milliseconds) per frame. This yields execution control back to the operating system to avoid unnecessary 100% CPU usage.
Warning: Do not try to use this parameter for "time control" (e.g., setting it to 10ms to get 100fps). OS scheduling is not guaranteed; some iterations could take 10ms and others more, breaking the "smoothness" of the loop.
Code Example: Variable Step
Main &mC64 = Main::instance();
SDL_Event myEvent;
Sint32 iUpdate = 1;
Uint8 bRunning = 1;
while(bRunning)
{
while((iUpdate = mC64.update(&myEvent)) != 0)
{
if(iUpdate == SDL_EVENT_QUIT || myEvent.type == SDL_EVENT_QUIT) bRunning = 0;
}
if(!bRunning) break;
float fDeltaTime = mC64.getLogicDeltaTime();
MyGame_Update(fDeltaTime);
}
5.2. Fixed Logic Step with Independent Rendering
In this mode, logic runs at a guaranteed deterministic rate (e.g., 20 Hz), while rendering is scheduled independently on the main thread at the monitor's refresh rate (e.g., 144 Hz or VSync). This is scheduling, not a separate rendering thread.
-
Mechanism: You configure timer() with a target rate. The update() method manages the accumulator and triggers logic updates only when required. Graphics are executed via the ::EC_RENDER event.
-
Pros: Deterministic physics (essential for collision stability). Logic speed is independent of framerate.
-
Cons: Without interpolation, moving objects may appear to "jitter" or "stutter" if the render rate doesn't perfectly match the logic rate.
-
Best for: GUI-heavy applications.
Performance Note:
In this mode, the graphics logic runs without limit (max CPU/GPU speed). On fast systems, CRM64Pro::ConfigMgr::setMTFriendly() can still be used to yield execution back to the OS and avoid 100% CPU usage on unnecessary rendering frames.
Code Example: Fixed Step
Main &mC64 = Main::instance();
mC64.timer().init();
mC64.timer().setRate(0, 60);
SDL_Event myEvent;
Sint32 iUpdate = 1;
Uint8 bRunning = 1;
while(bRunning)
{
while((iUpdate = mC64.update(&myEvent)) != 0)
{
switch(myEvent.type)
{
case SDL_EVENT_QUIT: bRunning = 0; break;
case ET_C64:
if(myEvent.user.code == EC_RENDER)
{
}
break;
}
}
if(!bRunning) break;
float fDeltaTime = mC64.getLogicDeltaTime();
MyGame_UpdateFixed(fDeltaTime);
}
5.3. Fixed Time Step with Interpolation (Professional)
This is the gold standard for action games. Logic runs at a fixed, low frequency (e.g., 20 or 30 Hz) for stability, but the Engine renders at maximum framerate by interpolating positions between the previous and current logic states.
-
Mechanism: You provide a RenderCallback. The engine calls this automatically. CRM64Pro sprites and scrolling handle interpolation automatically.
-
Pros: "Buttery smooth" motion even with low CPU usage. High-performance physics stability. Separation of concerns.
-
Cons: Slightly more complex setup. You must not modify game state inside the render callback.
-
Best for: High-performance 2D worlds, complex ARPGs, platformers, and any game requiring pixel-perfect physics and cinematic camera logic.
Performance Note:
Using the callback function will produce a very smooth graphics output. This callback function can be changed dynamically or disabled using nullptr.
On fast systems, CRM64Pro::ConfigMgr::setMTFriendly() can still be used to avoid unnecessary 100% CPU usage.
Code Example: Interpolated
Main &mC64 = Main::instance();
mC64.timer().init();
mC64.timer().setRate(0,20);
Screen *mScreen = mC64.configMgr().get();
mScreen->setRenderCallback([](Sint32 iMode) -> Sint32
{
return 0;
});
SDL_Event myEvent;
Sint32 iUpdate = 1;
Uint8 bRunning = 1;
while(bRunning)
{
while((iUpdate = mC64.update(&myEvent)) != 0)
{
switch(myEvent.type)
{
case SDL_EVENT_QUIT:
bRunning = 0;
break;
}
}
if(!bRunning) break;
float fDeltaTime = mC64.getLogicDeltaTime();
MyGame_UpdateFixed(fDeltaTime);
}
6. Configuration system
|
| Configuration system
Built-in launcher and customization
|
CRM64Pro includes a built-in "Launcher" window (CRM64Pro::ConfigMgr::setup). This allows end-users to configure hardware settings (Resolution, Monitor, Audio Driver) before the engine initializes the full graphical context.
Default Setup Launcher
Key Features:
-
Video Resolution & Window Mode selection.
-
Graphics API & Monitor selection.
-
Audio Driver selection & Output toggling.
-
Automatic configuration saving/loading.
-
Application-defined checkboxes that return their keys as application arguments.
Workflow
-
Call setup(): Launches the GUI. Returns 0 if the user clicked "OK".
-
Call load(): Reads the saved configuration and initializes the system.
Code Example: Implementation
Main &mC64 = Main::instance();
mC64.timer().init();
mC64.timer().setRate(0,20);
vector<string> vSetupArguments;
Sint32 iRet = mC64.configMgr().setup("config.xml", "setup.cdc", "setup.xml", &vSetupArguments);
if(iRet == 0)
{
if(mC64.configMgr().load("config.xml", "setup.cdc") == 0)
{
Screen* mScreen = mC64.configMgr().get();
if(mScreen && mScreen->show() == 0)
{
}
}
}
Customization via XML
The launcher layout is data-driven. You can provide a custom XML file (e.g., setup.xml) to override the default look. This allows you to:
-
Change the logo (Sprite resource).
-
Hide specific options (e.g., force VSync or specific resolutions).
-
Rename window titles and labels.
Customized Launcher Example
In the example above, the window title was changed to "Validation Setup", the 5th resolution option was hidden, and the logo was replaced.
Code Example: setup.xml
<?xml version="1.0" encoding="UTF-8"?>
<c64_setup title="Validation Setup">
<!--
CRM64Pro GDK Setup Layout. MegaStorm Systems (c) -->
<main>
<logo state="1" name="milogo"/>
</main>
<general>
<wgMTfriendly value="10"/>
<checkbox key="classicMode" name="default" state="1" x="28" y="155" value="0" text="Classic mode"/>
<checkbox key="showFPS" name="default" state="1" x="28" y="175" value="1" text="Show FPS"/>
</general>
<video>
<wgScreenTitle text="AppCarrier"/>
<wgResolution5 state="5"/> <!-- Hide 5th resolution option -->
<wgSpecialVSync value="1"/>
<wgSpecialBatching value="0"/>
</video>
<audio>
<wgAudio value="0"/>
<wgSample32bits value="1"/>
</audio>
</c64_setup>
CRM64Pro GDK.
Definition AudioTrack.cpp:36
6.1 Master Setup XML Reference
The internal Master XML defines the built-in structure. Built-in element names cannot be modified, but their attributes can be overridden and custom <checkbox> elements can be added to <general>.
Attribute Reference
| Attribute | Description |
| state | 0 (Disabled/Shown), 1 (Enabled/Visible) or 5 (Disabled/Hidden). |
| name | The C64 Sprite resource name (e.g., for logo). |
| x, y | Widget position. Supports CRM64Pro::ePositionHelper. |
| value | The default value for the widget (Checkbox/Slider). |
| text | The label text displayed to the user. |
| action | Used for specific widgets to open a file or URL. |
Custom <checkbox> elements may be added directly to the <general> section. Their key must contain only letters, digits, _ or -. After successful setup, each checked checkbox adds its raw key to the optional output vector passed to ConfigMgr::setup(). Enabled checkbox values (state="1") are saved in the configuration XML and restored by key; value is used as their default until a saved value exists. A disabled/shown checkbox (state="0") emits its fixed checked value, while a hidden checkbox (state="5") emits nothing.
View Master Setup XML
<?xml version="1.0" encoding="UTF-8"?>
<c64_setup title="Setup" cursor="default" icon_img="default" font="default">
<main name="default" x="0" y="0">
<logo state="1" name="default" x="59" y="10"/>
<wgTabsGeneral name="default" x="28" y="98" text="General"/>
<wgTabsVideo state="1" name="default" x="94" y="98" text="Video"/>
<wgTabsAudio state="1" name="default" x="160" y="98" text="Audio"/>
<wgSave state="1" name="default" x="44" y="401" text="Save"/>
<wgOK state="1" name="default" x="178" y="401" text="OK"/>
<wgExit state="1" name="default" x="313" y="401" text="Exit"/>
<wgInfoCopyright state="1" x="70" y="439" text="Setup Tool - CRM64Pro GDK - MegaStorm Systems (c)"/>
</main>
<general name="default" x="28" y="115">
<wgInfoCPU state="1" x="43" y="35" text="Processor: "/>
<wgInfoMemory state="1" x="43" y="55" text="Memory: "/>
<wgInfoVideoCard state="1" x="43" y="75" text="Video card: --"/>
<wgInfoAudioCard state="1" x="43" y="95" text="Audio card: --"/>
<wgMTfriendly state="1" name="default" x="43" y="115" value="1" text=" Multithread-friendly scheduling"/>
<wgReadme state="1" name="default" x="73" y="166" text="Readme" action="readme.txt"/>
<wgWeb state="1" name="default" x="223" y="166" text="Website" action="http://www.megastormsystems.com"/>
<checkbox key="customOption" name="default" state="5" x="43" y="230" value="0" text=" Custom option"/>
</general>
<video name="default" x="28" y="115">
<wgScreenTitle text="CRM64Pro GDK Application"/>
<wgRendererSoftware state="1" name="default" x="70" y="15" value="1" text=" Software"/>
<wgRendererOpenGL state="1" name="default" x="142" y="15" value="0" text=" OpenGL"/>
<wgRendererVulkan state="1" name="default" x="214" y="15" value="0" text=" Vulkan"/>
<wgRendererGPU state="1" name="default" x="286" y="15" value="0" text=" GPU"/>
<wgRendererDirect3D9 state="1" name="default" x="70" y="35" value="0" text=" Direct3D9"/>
<wgRendererX11 state="1" name="default" x="70" y="35" value="0" text=" X11"/>
<wgRendererMetal state="1" name="default" x="70" y="35" value="0" text=" Metal"/>
<wgRendererDirect3D11 state="1" name="default" x="142" y="35" value="0" text=" Direct3D11"/>
<wgRendererDirect3D12 state="1" name="default" x="214" y="35" value="0" text=" Direct3D12"/>
<wgResolution1 state="1" name="default" x="30" y="100" value="1" width="800" height="600" text=" 800x600"/>
<wgResolution2 state="1" name="default" x="30" y="120" value="0" width="1280" height="720" text=" 1280x720"/>
<wgResolution3 state="1" name="default" x="30" y="140" value="0" width="1920" height="1080" text=" 1920x1080"/>
<wgResolution4 state="1" name="default" x="30" y="160" value="0" width="2560" height="1440" text=" 2560x1440"/>
<wgResolution5 state="1" name="default" x="30" y="180" value="0" width="3840" height="2160" text=" 3840x2160"/>
<wgResolution6 state="5" name="default" x="30" y="200" value="0" width="c1" height="c1" text=" CustomRes"/>
<wgModeWindow state="1" name="default" x="130" y="100" value="1" text=" Window"/>
<wgModeFullscreen state="1" name="default" x="130" y="120" value="0" text=" Fullscreen"/>
<wgModeFullscreenExclusive state="1" name="default" x="130" y="140" value="0" text=" Fullscreen exclusive"/>
<wgSpecialVSync state="1" name="default" x="255" y="100" value="0" text=" Vertical-Sync"/>
</video>
<audio name="default" x="28" y="115">
<wgAudio state="1" name="default" x="100" y="11" value="1" text=" Enable audio"/>
<wgSample8bits state="1" name="default" x="30" y="70" value="0" text=" 8bits"/>
<wgSample16bits state="1" name="default" x="30" y="90" value="1" text=" 16bits"/>
<wgSample32bits state="1" name="default" x="30" y="110" value="0" text=" 32bits"/>
<wgFrequency22Hz state="1" name="default" x="125" y="70" value="0" text=" 22050Hz"/>
<wgFrequency44Hz state="1" name="default" x="125" y="90" value="1" text=" 44100Hz"/>
<wgFrequency48Hz state="1" name="default" x="125" y="110" value="0" text=" 48000Hz"/>
<wgModeStereo state="1" name="default" x="242" y="70" value="1" text=" Stereo"/>
<wgModeSurround state="1" name="default" x="242" y="90" value="0" text=" Surround 4ch"/>
<wgModeSurroundPlus state="1" name="default" x="242" y="110" value="0" text=" Surround 6ch"/>
<wgVolumeMaster state="1" name="default" x="100" y="140" value="1.0" text="Master volume:"/>
<wgVolumeMusic state="1" name="default" x="100" y="170" value="1.0" text="Music volume:"/>
<wgVolumeSFX state="1" name="default" x="100" y="200" value="1.0" text="SFX volume:"/>
<wgVolumeVoice state="1" name="default" x="100" y="230" value="1.0" text="Voice volume:"/>
<wgVolumeCustom state="5" name="default" x="100" y="260" value="1.0" text="Custom volume:"/>
</audio>
</c64_setup>
7. High-level Architecture
CRM64Pro Architecture Diagram
8. Changelog
Log of all notable changes made to CRM64Pro GDK including the date, version, and brief description:
## 🚀 2026-10-06 – v0.80.0 – Console overhaul, safer networking and complete module tutorials
### Added
- GUI/Console:
- Improved console with contextual auto-completion, quoted arguments, scrollback and command history.
- Added consistent module console handlers, unified built-in commands and help.
- NetTCP:
- Authoritative callbacks now receive a server-derived, connection-scoped sender index, allowing applications to validate packets without trusting client-supplied identity fields.
- Font:
- Added optional smooth position interpolation through the new `bInterpolate` parameter of `Font::setPosition()`.
- Config:
- Added custom ConfigSetup application checkboxes with persistent values and returned checked keys.
- Sprite:
- Added `Sprite::replaceSheet()` to replace the image and cell dimensions while preserving animation settings.
- Documentation:
- Added complete web and Doxygen tutorials for all CRM64Pro modules, from Basic through Scene.
- Validation:
- Added focused Catch2 unit tests for CRM64Pro modules.
### Changed
- Migrated version control from Subversion (SVN) to Git.
- New CRM64Pro logo for the engine and EditorC64.
- Archive:
- CDC files now open read-only by default, with optional write access.
- NetTCP:
- Validates every user packet through the configured authoritative server callback.
- Server shutdown is now restricted to the process that owns the server, remote shutdown requests are rejected.
- Server callbacks must now be configured before starting the server and cannot be replaced during an active server lifecycle.
- Improved simulated round-trip latency and rejected unterminated login names.
- Updated dependencies:
- sdl3 3.5.0 (Oct-2026)
- sdl3_net 3.3.0 (Sept 2026)
- zlib-ng 2.3.90 (Sept 2026)
- yyjson 0.13.0 (Sept 2026)
- xxHash 0.8.4 (Sept-2026)
- libpng 1.6.59 (Sept-2026)
- sdl3_image 3.5.0 (Sept-2026)
- sdl3_mixer 3.3.0 (Sept-2026)
- dr_mp3 0.7.4 (Aug-2026)
- dr_flac 0.13.4 (Sept-2026)
- libxmp 4.7.3 (Sept-2026)
- ffmpeg 8.1.3 (Sept-2026)
### Fixed
- GUI:
- Fixed widget keyboard activation so assigned shortcuts fire once per press/release cycle without repeated callbacks or stuck pressed/action states.
### Breaking Changes
- Archive:
- `ArchiveMgr::load()` now has a new parameter to specify the access mode (`AOM_READ_ONLY` or `AOM_READ_WRITE`).
- NetTCP:
- Changed `NetTCP::CoreServerCallback` to `Sint32(void*, Sint32, Uint8 iSenderIdx, void*)`.
- Removed the `bIsQuery` parameter from `NetTCP::sendData()` and removed the client-controlled callback-bypass protocol path.
- `NetTCP::requestServerClose()` no longer sends a remote shutdown request and now returns `NR_NO_SERVER_RUNNING` when the local process does not own a running server.
- Older clients that use the removed bypass or remote-shutdown protocol messages are no longer compatible with those operations.
- Config:
- Renamed the screen XML attribute from sName to name in config loading and saving.
- Font:
- Changed the `Font::setPosition()` signature to include `bool bInterpolate = false`.
....
View the Complete Changelog.
9. License
CRM64Pro GDK
Copyright (C) 2013-2026 Roberto Prieto <contact@megastormsystems.com>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.