Utilities to locate or relocate things into memory, or to establish memory location where to load different areas of a binary.
Memory Relocation Utilities | Utilities to locate or relocate things into memory, or to establish memory location where to load different areas of a binary. |
Macros | |
CPCT_ABSOLUTE_LOCATION_AREA | Macro that produces following code and data to be located at given absolute memory location MEM. |
CPCT_RELOCATABLE_AREA | Macro that produces following code to be automatically distributed by the linker amongst available memory space area, starting in the loading location defined by Z80CODELOC (see cfg/build_config.mk file) |
Macro that produces following code and data to be located at given absolute memory location MEM.
#define CPCT_ABSOLUTE_LOCATION_AREA (MEM)
(2B) MEM | Memory location where code produced next will be placed |
// This is the start of a file called music.c CPCT_ABSOLUTE_LOCATION_AREA(0x040); // Music data gets located at 0x040 const u8 music_data[100] = { 0x41, 0x54, 0x31, .... }; // Failing to add a relocation macro here will produce // the compiler to add a ".area _CODE" directive before // music data. This happens in data-only files. CPCT_RELOCATABLE_AREA(); // This is the end of the file music.c
1 byte
This macro is used to change the location where subsequent code or data will be located when the binary gets loaded. All code or data written after the call to this macro will be loaded from MEM on.
// // .. previous code, dynamically placed in memory by the compiler // CPCT_ABSOLUTE_LOCATION_AREA(0x0040); // 1000 bytes of music to be located staring at 0x0040 const u8 music_data[1000] = { 0x0A, 0x12, 0x5F, // ..... } CPCT_ABSOLUTE_LOCATION_AREA(0x8000); // Function code will be placed at 0x8000 void game_loop(u8 parameter) { // function code... }
Several absolutely located code areas may be created, but they should be placed at different memory locations.
This macro creates dummy functions and produces assembly code for relocation inside these dummy functions. These functions are not to be called by any means, nor it is required; they are required as the compiler prevents directives from being entered outside function scope. These functions are named as /dummy_absolute_MEM/ and /dummy_data_absorber_MEM/ and they cannot be duplicated, as they are proper functions for the compiler.
/dummy_data_absorber_MEM/ function is generated first, and its purpose is to make all previous data definitions (arrays, strings, etc) to be “absorbed”. With this function being defined, previous data gets placed by the compiler at the end of this “absorber” function, just before the new absolutely located area definition, as wanted. This function only contains a RET statement, and takes up 1 byte of space in the final binary. As this function is dummy and gets never called, this additional byte can be safely removed or overlapped if required. This may by done by placing next absolutely located area exactly where this byte lies, or by editing produced assembly code and removing the RET statement before compiling. Do these operations only if you know exactly what you are doing.
Macro that produces following code to be automatically distributed by the linker amongst available memory space area, starting in the loading location defined by Z80CODELOC (see cfg/build_config.mk file)
#define CPCT_RELOCATABLE_AREA (ID)
(identifier) ID | An optional identifier to distinguish container functions for relative location areas. |
1 byte
This macro restores normal code location behaviour. This normal behaviour sets the linker to decide where should code and data be placed, inside the relative code area. Relative code area starts at the binary loading point (Z80CODELOC) and extends from there to the end of memory. Starting place for this code area can be changed at compile-time by editing the file cfg/build_config.mk of your CPCtelera project, and assigning desired memory location to Z80CODELOC variable.
Every time this macro is called, following code will be added to the general _CODE area. This area is the global relocatable area. This means that all the code contained in this area can be relocated as linker considers.
// // First part of a C file. All code is added to _CODE area by // default, and located by the linker from Z80CODELOC onwards. // So, following code will be relocated by the linker as required. // void drawCompound(u8* sprite) { // .. Code for drawing a compound. Compiled code // .. will be placed by the linker in the _CODE area, // .. from Z80CODELOC onwards } CPCT_ABSOLUTE_LOCATION_AREA(0x0040); // // .. This array of data will be placed at 0x0040 absolute location onwards // const u8 music_data[1000] = { 0x0A, 0x12, 0x5F, // .. 1000 bytes of data }; CPCT_RELOCATABLE_AREA(); // // Next data and functions will be added to the _CODE area, // same as the drawCompound function. All will be placed by // the linker as it considers, inside the relocatable area // that starts at Z80CODELOC // const u8 character_info[5] = { 10, 52, 100, -1, 3 }; void game_loop(u8 parameter) { // function code... } CPCT_ABSOLUTE_LOCATION_AREA(0x1040); // // Next code will be placed from 0x1040 onwards, just after // music data (ensuring that it is not overlapped) // void playMusic() { // function code... } CPCT_RELOCATABLE_AREA(); // Main function will be placed in relative _CODE area managed // by the linker. void main() { // main code }
This macro may be used as many times as required. An indefinite number of code and data areas can be flagged as relative to be managed by the linker.
This macro creates dummy functions and produces assembly code for relocation inside these dummy functions. These functions are not to be called by any means, nor it is required; they are required as the compiler prevents directives from being entered outside function scope. These functions are named as /dummy_relative___LINE__ID/ and /dummy_data_absorber___LINE__ID/ and they cannot be duplicated, as they are proper functions for the compiler.
/dummy_data_absorber___LINE__ID/ function is generated first, and its purpose is to make all previous data definitions (arrays, strings, etc) to be “absorbed”. With this function being defined, previous data gets placed by the compiler at the end of this “absorber” function, just before the new absolutely located area definition, as wanted. This function only contains a RET statement, and takes up 1 byte of space in the final binary. As this function is dummy and gets never called, this additional byte can be safely removed or overlapped if required. This may by done by placing next absolutely located area exactly where this byte lies, or by editing produced assembly code and removing the RET statement before compiling. Do these operations only if you know exactly what you are doing.
When using this macro on different source code files, a compilation error may arise. On the event of having 2 uses of this macro, on the same source code line number, but in different files, they will produce the same function name, unless different IDs are provided. In this case, a compilation error will happen. There are 2 possible solutions,