I'm working on a development to optimize the memory management for the CX16, allowing to dynamically allocate and free memory space at run time in CX16 BANKED RAM (BRAM) and VERA RAM (VRAM).
The heap manager is being built using the kickc compiler of @Jesper Gravgaard, and we are working together to optimize this development for a larger audience (later).
The idea came while making my "space game", I really needed a mechanism to dynamically load and free memory in both RAM types on the fly at run time.
The complete source code of the heap manager van be found here:
https://gitlab.com/Flight_Control/kickc/-/blob/CX16_VERA/src/main/kc/lib/cx16-heap.c
This heap manager now allows to dynamically load graphics (files) into BRAM and when not needed anymore, to dynamically free these graphics from memory. Typically such activities would happen when switching between "levels" during gameplay,
or at certain transition moments. The heap manager has not implemented the logic to load the files, but a loader routine using CX16 kernal calls has been made, that uses the heap manager to dynamically allocate memory as graphics files are loaded.
This allows me to design the graphics flexibly, specifying the file properties, and the heap manager will allocate the required memory at run time in memory.
During gameplay or "on the fly", the heap manager covers the needed functionality to dynamically manage the limited memory space in VRAM, for tiles and sprites and other graphic objects.
The heap manager allows to dynamicall allocate required memory in VRAM during gameplay, and free up VRAM memory when the space is not anymore needed, freeing up memory for new graphic objects to be allocated in VRAM, on the fly.
On top, I've added CX16 library functions to copy memory between RAM, VRAM and BRAM. One such important function is to quickly copy memory from BRAM into VRAM. Typically this is used for sprites during gameplay.
In other words, the heap manager allows me to load up the graphics from disk during transition moments, filling the 512/1024/1536/2048 banked memory space in the CX16, which is slow loading.
But then, during gameplay, it allows me to quickly manage the VRAM memory space and copy graphics in and out from BRAM into VRAM on the fly.
The CX16 heap manager has been made with the following requirements in mind:
The heap manager needs a small code footprint, supporting both BRAM as VRAM dynamic memory allocations using the same code base, which is located in RAM.
Programmers will only use the heap manager to allocate larger portions of memory. For smaller dynamic memory allocations, other methods are to be used (like arrays, vectors).
Align the allocated memory with the BRAM BANKS or VRAM BANKS structure. No header information polluting the data. This is also very important to avoid VRAM having any header information! (We don't want sprite or bitmap info polluted with header blocks, do we...)
Minimize the size of the headers, as large headers quickly will consume a lot of memory.
Avoid memory fragmentation, which is resolved by coalescing the freed data blocks.
Relatively fast, but not super fast. Speed for dynamic memory allocation is not an issue. For games, allocating and freeing memory would happen between paused moment.
Use helper function(s) to address the memory, while traversing the memory space.
Easy use for the programmer, and improve the code readability, through a well defined API.
(Later) Allow the heap manager to be used by programmers using other languages, using an assembler library.
The CX16 heap manager has taken the following design decisions:
There are 16 memory segments that can handle the allocation of various data segments in CX16 BRAM and VERA VRAM.
Allocated blocks are aligned to 8 bytes in BRAM and VRAM. This should not be a problem, s
Header information is placed in BRAM, to avoid any HEAP dynamic allocated memory to be placed in CX16 MAIN RAM. So no dynamic memory is allocated in CX16 RAM before 0xA000.
Use handles instead of direct pointers to memory locations. This is important, since CX16 memory in BRAM is banked, and VERA memory cannot be addressed directly anyway! This will also allow for memory compression or re-alloc later. It also avoids the programmers code to have direct pointers being used, instead, using handles, the pointers will be "indirect". This has a small performance impact, but greatly improves memory management flexibility.
The header blocks are separated from the data blocks. This is important for VERA VRAM. Header information placed in VRAM would pollute the graphics!!! We don't want sprites set to be polluted with header information, do we?
Hope that this development will insprire others. Please contact me or @Jesper Gravgaard if the heap manager is of interest to you.
Note that this development is still work in progress and is evolving till i'm satisfied with the design of the overall API.