CRM64Pro GDK v0.11.0
A free cross-platform game development kit built on top of SDL 3.0
Loading...
Searching...
No Matches
CRM64Pro GDK v0.11.0 Reference Guide

1. What's CRM64Pro GDK?

CRM64Pro is a free and open source cross-platform game development kit written in C++ and built on top of SDL 3.0.
It is distributed under zlib license.

Todo:

ext libs versions? video/audio backends? referrenced as C64? docs made by Doxygen 1.9.6

Show all modules? TileEngine modules test

1.1. Supported platforms

Microsoft Windows 7 or newer (64bits versions).
 
Linux distribution based on kernel 2.6.x or newer (64bits versions).
 
Android 5.x or newer.
 
macOS 10.12 or newer.
Todo:
Render and audio drivers availables for each platform?

1.2 High-level architecture


1.4. Changelog

Log of all notables changes mades to CRM64Pro GDK including the date, version and brief description for each change.
22 Feb 2024 - 0.11.0 - Maintenance (last stable version)
--------------------------------------------------------
- Updated copyright to 2024.
- Used libpng 1.6.42 (Jan-2024) library.
- Used zlib-ng 2.1.6 (Feb-2024) library.
- Used TinyXML 10.0.0 (Dec-2023) library.
- Used xxHash 0.8.2 (Feb-2024) library.
- Used SDL3_mixer 3.0.0 (Feb 2024) library.
- Used SDL 3.2.0 (Feb-2024) library.
- ABI is broken with previous version, due to the changes done in SDL3.
- SDL3 migration:
. Update the code for the new changes done in SDL3 and SDL3_mixer.
. Config Manager methods for enable/disable 2D batching sytem are removed as it is always enabled.
19 Sept 2023 - 0.10.0 - TileEngine II
-------------------------------------
- TileEngine:
. Tiled:
Fixed some issues when importing maps.
Fixed an issue with viewport.
Support for Tiled v1.10 maps. Check TileEngine documentation for more information.
Support for tile special effects.
Support for animated tiles.
Tilesets are stored in external .TSX files.
.Parallax effect is now split on x and y axis.
.The tileset created when importing an image now retains the proportional size of the individual tiles.
When converting an image to a tileset, it tries to find identical tiles (based on a max deviation parameter) and now uses OpenMP to parallelise this task.
.Color values are stored in #RGB(A) hex format.
- Tile Manager:
. Add new renderEx() method.
- Tool:
. Added new strHexToInt() method to convert a string with a number in hexadecimal format to int.
30 Jun 2023 - 0.9.0 - Migration to SDL3
---------------------------------------
- Adoption of http://semver.org/ versioning system.
- ABI is broken with previous version, mostly due to the migration to SDL3.
- SDL3 migration:
. Screen::eConfigScreenAspectRatio enum removed and using new SDL_RendererLogicalPresentation enum.
. Screen::setLogicalSize() method renamed to setLogicalPresentation() including SDL_ScaleMode.
. Screen::getLogicalSize() method renamed togetLogicalPresentation() including SDL_ScaleMode.
. Screen has been reworked due to the new fullscreen concept of SDL3.
. ConfigMgr::Setup() method didnt use "aspect_ratio" anymore and used new "logical_presentation_mode" and "logical_presentation_quality".
. CursorMgr reworked for supporting new logical presention.
. Timer: getTicks() and getTicksNow() methods now return 64bits instead of 32bits values.
. Audio: added support for FLAC and MP3. Removed support for AIFF.
. Enabled Direct3D12 renderer for Windows.
. Removed audio driver winmm for Windows.
- General Windows projects cleaning up (removing build options that are not used).
- Used libpng 1.6.40 (Jun-2023) library.
- Used zlib-ng 2.1.2 (Jun-2023) library (improved compression speed by +9% and decompression speed by +37%).
- Fixed known bug #0031: restore the screen clipping was failing causing rendering corruption.
13 Jun 2023 - 0.981 - General improvements
------------------------------------------
- Last version supporting SDL2.
- STL map is also supported with CMem.
- Config Manager:
. Fixed a bug on load() method, now properly load the mtfriendly value.
. Fixed a small bug when displaying CPU name.
. Fixed an issue when setting sound and music volume.
. Fixed an issue when getting the screen snapshot. Note there are still issues with Direct3D11 backend renderer.
- GUI Manager:
. Fixed known bug #0015: when removing a panel when using images/sprites with parent/child relationship.
. Improved ProgressBar widget when using image or sprite as background.
. When setting an image or sprite as background for a widget, the alpha value is inherited.
. Fixed an issue with TextBox widgets.
- Memory Manager:
. Fixed some issues when custom memory manager is not enabled.
- Image Manager:
. Added new exist() method for checking if a given image is present on a CDC.
- Audio Manager:
. Added new exist() method for checking if a given music/sound is present on a CDC.
- Tool:
. Added new strTovStr() and strDecToInt() methods for splitting a string into a vector of strings and convert a string to int.
4 May 2023 - 0.980 - Documentation
----------------------------------
- Used doxygen 1.9.6 and fixed some docs issues.
- Creation of auto deploy scripts.
- Config Manager:
. Added setup() method documentation describing how to customize the layout.
30 Apr 2023 - 0.975 - Config Manager III
----------------------------------------
- Config Manager:
. Added setup() method for opening a screen with configuration settings, there is a default one but can be customized
. Updated audioClose() and calls to audioInit() (for changing the audio features) now remove all music resources loaded so they must be reloaded.
. Fixed a bug on setLogicalSize() method.
- GUI Manager:
. Size and position of panels on different that default screen now work fine.
- Tool:
. Updated messageBox() method with a new optional parameter for setting up the screen to attach it.
- XML Manager:
. Added loadFromBuffer() method for loading a XML from a given buffer.
1 April 2023 - 0.973 - Maintenance
----------------------------------
- TileEngine
. Fixed an issue when exporting a map loaded from a CDC to Tiled format.
- Used TinyXML-2 9.0.0 (Jan-2023) library.
- Used libpng 1.6.39 (Nov-2022) library.
- Used SDL 2.26.4 (Mar-2023) library.
- Used SDL2_net 2.3.1 (Mar-2023) library.
- All projects migrated to Visual Studio 2022.
- Windows build used Windows SDK 10.0.22621.
- Removed from SDL2 joysticks, haptic and sensor modules.
- Note: Direct3D12 renderer is disabled as the performance is lower than Direct3D11.
12 Febrary 2022 - 0.972 - Memory Manager II
-------------------------------------------
- Memory Manager:
. Stats system fixed (Bug #0030).
. Fixed an issue with the histogram values.
. Method setMsgOutput() is exposed to users for increasing the versatibility of the memory stats system.
. Added method setModuleName() for assigning a custom name for an user memory module.
. Updated ltalloc: configured for minimizing memory fragmentation at the cost of wasting memory.
- SDL2 memory leaks fixed:
. Local thread storage (220 bytes) is free at termination. (Bug #0030).
. Applied a memory leak fix that will be available on 2.0.22+ (mouse related).
...
Complete Changelog


1.5. License

Copyright (C) 2013-2023 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.
CRM64Pro GDK.
Definition: AudioInfo.cpp:39


2. Installation

CRM64Pro GDK runtime library ("CRM64Pro.dll") should be shipped together with the application that uses it. In case you want to change the version, you can download the development libraries and extract the runtime library as needed.

2.1. Windows with Visual Studio

Requirements

  • Microsoft Windows 7, 10 or 11 (64bits versions).
  • Microsoft Visual Studio 2019 or newer.

Library installation

  • Unpack "CRM64Pro-X.Y-win-x64.zip" on a destination path (CRM64PRO_INST_DIR)
  • CRM64PRO_INST_DIR path must be in the system search path, the best way to do that is adding a new entry to the PATH environment variable:
    • For Windows 7:
      • right click on "My Computer"
      • click on Properties/Advanced/Environment Variables
      • under User variables, look for PATH entry, edit it adding CRM64PRO_INST_DIR value.
    • For Windows 10 or 11:
      • right click on "This PC"
      • click on Properties/Advanced system settings/Environment Variables
      • under User variables, look for PATH entry, edit it adding CRM64PRO_INST_DIR value.
  • From now on, "CRM64Pro.dll" is available for any application.

Compiling your own applications

  • To develop applications or compile the examples using Visual Studio, we have to add the CRM64PRO_INST_DIR to the include and library paths.
    Usually, Visual Studio manages these directories using Tools/Options/Directories accesible from the main IDE window
  • Include "CRM64Pro.h" at the beginning of your code
  • Link against the main library:
    • "CRM64Pro.lib" to use the dynamic library version("CRM64Pro.dll")
      or
    • "CRM64Pro.static.lib" to use the static library version

  • It is very important that runtime libraries on C/C++ code generation of Visual Studio will be set to "DLL multithreaded" (/MD switch) when you compile Release code or set to "DLL Debug multithreaded"(/MDd switch) when you compile Debug code.

2.3. Linux with GNU GCC/G++

2.4. macOS with GNU GCC/G++

3. Game development using C64

The computational power required for executing a traditional game can, at least, be divided on the following categories:
Audio
Graphics
Logic (physics, AI, game logic, etc.)
Network

Nowadays, in the multicore CPU era, using multiple threads is, on some cases, a really needed scenario. The "easy" way is to run the different computational categories on different threads that will run on the CPU cores, I said "easy" because multithreading development is all but easy task and good skills and planification are needed.

Fortunately, this C64 facilitates the usage of multithreading development:

Audio: thanks to SDL, the audio processing is executed on a separated thread and it&#39;s automatically done.
Graphics: this is a limitation of SDL: the graphics must be rendered on the main thread.
Logic: C64 provides methods for running the logic code separated of the Graphics code. Once the logic and graphics code are separated, nothing stop you to setup the logic on different threads
Network: C64 automatically uses different threads for the client and server code
In the following sections, we will focus on the Graphics/Logic categories, starting from simpliest to more advanced methods offered by C64.

3.1 Standard Graphics/Logic method

This is the simpliest method which can be used on small demos or applications, while you are learning to use C64 or if you are implementing a custom graphics/logic/timing method.
Logic and Graphics updates are executed in a sequential and synchronized way.

Code example:
// Initialization stuff
Main &mC64 = Main::Instance();
...
// Main loop
SDL_Event myEvent;
Uint8 bRunning = 1;
while(bRunning)
{
// My logic stuff
...
// My graphics stuff
...
// C64 main governor
while(mC64.update(&myEvent)
{
switch(myEvent.type)
{
case SDL_QUIT:
bRunning = 0;
break;
}
}
}

The "Main loop" will run at the maximum speed provided by the CPU (assuming ConfigMgr::iMTFriendly = 0), the "logic" will be executed, then the "graphics stuff" and then the "main governor loop" will do its tasks (Main::update()).

Although you can use CRM64Pro::ConfigMgr::iMTFriendly with a minimum of milliseconds to wait while Main::update() is executed, this is useful for giving back the execution control to the operating system and not eat the whole CPU probably doing a lot of unnecesary work.

Do not try to get a kind of "time control" using this parameter, let&#39;s say you use a value of 10ms, so 1000/10 = 100 executions of the "main loop" (in the best case), but these executions will not be equally distributed and also, not guaranted, as some iterations could take 10ms and others more, breaking the "smoothness" of the "main loop".

3.2 Advanced Graphics/Logic method I

This method can be used on menu screens or when you dont need to have a perfect "smoothness".
Logic and Graphics updates are executed in a sequential but asynchronized way.

Code example:
// Initialization stuff
Main &mC64 = Main::Instance();
mC64.ITimer().init();
mC64.ITimer().setRate(0,20); // Set the Logic Frame Rate to 20
...
// Main loop
SDL_Event myEvent;
Uint8 bRunning = 1;
while(bRunning)
{
// My logic stuff
...
// C64 main governor
while(mC64.update(&myEvent)
{
switch(myEvent.type)
{
case SDL_QUIT:
bRunning = 0;
break;
case EVENT_C64:
if(myEvent.user.code == EVENT_C64_RENDER)
{
// My graphics stuff
...
}
break;
}
}
}

The "Main loop" and "logic stuff" are running at the Logic Frame Rate of 20 executions per second (they are equally distributed across the timeline).

In this case, the "graphics stuff" is executed without limit (maximum CPU/GPU speed) using a custom event returned when a Render Frame occurred.

On fast systems, CRM64Pro::ConfigMgr::iMTFriendly can still be used in order to give the execution back to the operating system for avoiding to eat the whole CPU doing plenty of unnecesary graphics rendering.

3.3 Advanced Graphics/Logic method II

In C64 terminilogy, this method is known as the fixed virtual logic frame rate with interpolation and can be used on the game itself as provides the most advanced "smoothness".
Logic and Graphics updates are executed in a sequential but asynchronized way.

Code example:

// Initialization stuff
Main &mC64 = Main::Instance();
mC64.ITimer().init();
mC64.ITimer().setRate(0,20); // Set the Logic Frame Rate to 20
...
// Set a render callback for our main screen
Screen *mScreen = mC64.IConfigMgr().get();
mScreen->setRenderCallback(myRenderFunc);
// Main loop
SDL_Event myEvent;
Uint8 bRunning = 1;
while(bRunning)
{
// My logic stuff
...
// C64 main governor
while(mC64.update(&myEvent)
{
switch(myEvent.type)
{
case SDL_QUIT:
bRunning = 0;
break;
}
}
}
Sint32 myRenderFunc(Sint32 iMode)
{
// My graphics stuff
...
}

The "Main loop" and "logic stuff" are running at the Logic Frame Rate of 20 executions per second (they are equally distributed across the timeline).

In this case, the "graphics stuff" is executed without limit (maximum CPU/GPU speed) using a render callback function.
Using the callback function will produce a very smooth graphics output with some GDK modules (Sprite or the TileEngine). This callback function can be changed by other one or disabled using a nullptr function.

On fast systems, CRM64Pro::ConfigMgr::iMTFriendly can still be used in order to give the execution back to the operating system for avoiding to eat the whole CPU doing plenty of unnecesary graphics rendering.

4. Setup and configuration tool

For allowing final users to easily select the most important audio and video low-level settings as:

  • Video resolution.
  • Window mode.
  • Video driver.
  • Enable or disable audio output.
  • etc

C64 includes a CRM64Pro::ConfigMgr::setup method that has a default layout:

Then, the user can save the chosen configuration and using CRM64Pro::ConfigMgr::load method, can easly be loaded.

Code example of using setup() and load() methods:
// Initialization stuff
Main &mC64 = Main::Instance();
mC64.ITimer().init();
mC64.ITimer().setRate(0,20); // Set the Logic Frame Rate to 20
...
// Call to setup method
Sint32 iRet = mC64.IConfigMgr().setup("config.xml", "setup.cdc", "setup.xml");
// If configuration selected by user is saved and clicked on OK, then launch the application
if(iRet == 0)
{
if(!mC64.IConfigMgr().load("config.xml", "setup.cdc"))
{
mScreen = mC64.IConfigMgr().get();
if(!mScreen->show())
{
// main code
...
}
}
}

However, the layout can be easily modified for hidding some settings, force others, change the graphics, logo, etc.
Internally, there is a master XML describing the default layout and the attributes can be overriden using the optional "sCustomSetupXML" parameter. In the above code example, it is the "setup.xml" file.

As a reference, providing a "sCustomSetupXML" parameter with:

setup.xml file
<?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"/>
</general>
<video>
<wgScreenTitle text="AppCarrier"/>
<wgResolution5 state="0"/>
<wgSpecialVSync value="1"/>
<wgSpecialBatching value="0"/>
</video>
<audio>
<wgAudio value="0"/>
<wgSample32bits value="1"/>
</audio>
</c64_setup>

produced this video tab:

Where the title of the setup window has changed, the fifth resolution radio button has been removed, the logo has been changed and the value of vertical vsync is enabled. Also, the audio is disabled although is not shown on this tab.

4.1 Master Setup XML

Note
The XML elements should not be modified but all the attributes can. The values for the attributes are self explanatory and follow below rules:
  • state: 0(disabled) or 1(enabled).
  • name: the C64 Sprite resource name. (CRM64Pro::Sprite)
  • x and y: positions. Supports CRM64Pro::ePositionHelpers
  • value: for widgets, it is the value
  • text: for widgets, it is the text
  • action: for widgets: open a file or an url
Master Setup XML
<?xml version="1.0" encoding="UTF-8"?>
<c64_setup title="Setup" cursor="default" icon_img="default" font="default">
<!-- CRM64Pro GDK Setup Layout. MegaStorm Systems (c) -->
<!-- Attributes and values:
state: 0(disabled) or 1(enabled)
name: the sprite resource name.
x and y: positions. Supports CRM64Pro::ePositionHelpers
value: for widgets, it is the value
text: for widgets, it is the text
action: for widgets: open a file or an url
-->
<!-- The size of the setup screen is set by the size of the main name resource -->
<main name="default" x="0" y="0">
<logo state="1" name="default" x="59" y="10"/>
<!-- CheckBox widgets group for Tabs -->
<wgTabsGeneral name="default" x="28" y="98" value="1" text="General"/>
<wgTabsVideo name="default" x="94" y="98" value="0" text="Video"/>
<wgTabsAudio name="default" x="160" y="98" value="0" text="Audio"/>
<!-- Button widgets -->
<wgSave name="default" x="44" y="341" text="Save"/>
<wgOK name="default" x="178" y="341" text="OK"/>
<wgExit name="default" x="313" y="341" text="Exit"/>
<!-- Label widget -->
<wgInfoCopyright state="1" x="1627389952" y="1929379847" text="Setup Tool - CRM64Pro GDK - MegaStorm Systems (c)"/>
</main>
<general name="default" x="28" y="115">
<!-- Label widgets -->
<wgInfoCPU state="1" x="43" y="42" text="Processor: "/>
<wgInfoMemory state="1" x="43" y="72" text="Memory: "/>
<!-- CheckBox widget -->
<wgMTfriendly state="1" name="default" x="43" y="102" value="1" text=" Multitasking friendly"/>
<!-- Button widgets -->
<wgReadme state="1" name="default" x="73" y="164" text="Readme" action="readme.txt"/>
<wgWeb state="1" name="default" x="223" y="164" text="Website" action="http://www.megastormsystems.com"/>
</general>
<!-- Video configuration is only for "default" C64 screen -->
<video name="default" x="28" y="115">
<!-- Title for screen -->
<wgScreenTitle text="CRM64Pro GDK Application"/>
<!-- CheckBox widgets group for Renderers -->
<wgRendererSoftware state="1" name="default" x="70" y="11" value="1" text=" Software"/>
<wgRendererOpenGL state="1" name="default" x="135" y="11" value="0" text=" OpenGL"/>
<wgRendererDirect3D9 state="1" name="default" x="200" y="11" value="0" text=" D3D9"/>
<wgRendererX11 state="1" name="default" x="200" y="11" value="0" text=" X11"/>
<wgRendererDirect3D11 state="1" name="default" x="250" y="11" value="0" text=" D3D11"/>
<wgRendererDirect3D12 state="1" name="default" x="300" y="11" value="0" text=" D3D12"/>
<!-- CheckBox widgets group for Resolution -->
<wgResolution1 state="1" name="default" x="30" y="70" value="1" width="800" height="600" text=" 800x600"/>
<wgResolution2 state="1" name="default" x="30" y="90" value="0" width="1280" height="720" text=" 1280x720"/>
<wgResolution3 state="1" name="default" x="30" y="110" value="0" width="1920" height="1080" text=" 1920x1080"/>
<wgResolution4 state="1" name="default" x="30" y="130" value="0" width="2560" height="1440" text=" 2560x1440"/>
<wgResolution5 state="1" name="default" x="30" y="150" value="0" width="3840" height="2160" text=" 3840x2160"/>
<wgResolution6 state="0" name="default" x="30" y="170" value="0" width="c1" height="c1" text=" c1"/>
<!-- CheckBox widgets group for Mode -->
<wgModeWindow state="1" name="default" x="130" y="70" value="1" text=" Window"/>
<wgModeFullscreen state="1" name="default" x="130" y="90" value="0" text=" Fullscreen"/>
<wgModeFullscreenExclusive state="1" name="default" x="130" y="110" value="0" text=" Fullscreen exclusive"/>
<!-- CheckBox widgets -->
<wgSpecialVSync state="1" name="default" x="255" y="70" value="0" text=" Vertical-Sync"/>
<wgSpecialBatching state="1" name="default" x="255" y="90" value="0" text=" Render-Batching"/>
</video>
<audio name="default" x="28" y="115">
<!-- CheckBox widget -->
<wgAudio state="1" name="default" x="100" y="11" value="1" text=" Enable audio"/>
<!-- CheckBox widgets group for Sampling -->
<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"/>
<!-- CheckBox widgets group for Frequency -->
<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"/>
<!-- CheckBox widgets group for Mode -->
<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"/>
<wgModeSurrondPlus state="1" name="default" x="242" y="110" value="0" text=" Surround 6ch"/>
<!-- Horizontal slider widgets -->
<wgVolumeMusic state="1" name="default" x="100" y="145" value="64" text="Music volume:"/>
<wgVolumeSound state="1" name="default" x="100" y="175" value="64" text="Sound volume:"/>
</audio>
</c64_setup>