Hacker's Edge Game Guide: Programming/ld65 he-rom.cfg

ld65 he-rom.cfg
Nov. 15, 2017

If you plan on using a 3rd party toolkit like cc65 or ca65, then you will need to have one of these very handy files for your linker, ld65. While you do not technically require this config file for generating ROM and BootROM images for a machine, it will be required if you plan on targeting a specific operating system within the Hacker's Edge universe. This config file explains the memory layout of the machine or operating system which you are targeting, and if these values are incorrect, attempting to load such a program will result in failure or crashed machine. Let's start this by explaining the he-rom.cfg linker configuration file:

    ZP:   start =   $80, size =   $1A, file = "";
    RAM:  start =  $200, size = $0E00, define = yes;

    ZEROPAGE:  load = ZP,  type = zp,  define   = yes;
    STARTUP:   load = RAM, type = ro;
    ONCE:      load = RAM, type = ro   optional = yes;
    CODE:      load = RAM, type = ro;
    RODATA:    load = RAM, type = ro;
    DATA:      load = RAM, type = rw;
    BSS:       load = RAM, type = bss, define   = yes;

    CONDES: type    = constructor,
            label   = __CONSTRUCTOR_TABLE__,
            count   = __CONSTRUCTOR_COUNT__,
            segment = STARTUP;
    CONDES: type    = destructor,
            label   = __DESTRUCTOR_TABLE__,
            count   = __DESTRUCTOR_COUNT__,
            segment = RODATA;

    __STACKSIZE__:  value = $0200, type = weak;
    __IOBASE__:     value = $FF00, type = weak;

This may look pretty daunting at first, but don't worry. You most likely will never need to modify this file yourself unless you are a mission or OS designer. If you are a mission designer, you can specify entirely new machine types in-game with unique I/O map, and memory layouts. If you are a regular player, then perhaps you are interested in writing your own OS. In either of those cases, you may need to modify this file so that it can build code correctly.

Let's begin from the top, the first section we have here is MEMORY, which can define the ZEROPAGE, RAM, and ROM in various different memory configurations. In this specific example, we see that ZP starts at $80 in memory and can only be a total length of $1A. Our RAM starts at $200 in memory with a total size of $0E00. This file will be updated soon to reflect the nature of a BootROM, for now this is well suited to be loadable from within the 6502 Monitor program.

The next section defines our SEGMENTS. These are segments which will be used either by your assembly or C program code. Each segment has a memory location where it should be loaded, in this case all of them expect for ZP are loaded into RAM. Each segment is also assigned a type attribute. zp is for ZeroPage, ro/rw is if we can write there in our code, and bss defines our heap memory. Here is what each segment is normally for:

  • ZEROPAGE: This segment manages the 6502 ZeroPage memory area.
  • STARTUP: This is where the program startup/initialization code lives and is the first to run usually.
  • ONCE: This segment is optional and where code which may only run once can be placed.
  • CODE: This is the usually CODE segment, where all the code is placed.
  • RODATA: This segment contains static data like tables, constants, and string data. This data should not be changed at runtime.
  • DATA: This is data which can be changed at runtime by your program.
  • BSS: This is the heap, which is normally used by C code.

Additional custom segments can be added, and each segment is written to the output file in the order they are listed, which is where load comes from, you can have multiple output files, if your memory section provides for that.

The next section is FEATURES, this normally doesn't need to be modified and is used by the C runtime library to setup and destroy the library when the program starts and ends.

Finally we come to the SYMBOLS section. These are exported by the linker, and can be imported into your assembly code to perform various tasks. The __STACKSIZE__ is specifically used by the C runtime to manage it's stack, and __IOBASE__ is Hacker's Edge specific to tell the code where the I/O mapped devices are in memory.

And there you have it. Feel free to play around with some of these values and experiment with different output binaries. A separate cfg file should be used for specific operating systems in Hacker's Edge, or you won't be able to easily compile code targeted towards that specific OS. A cfg file for an OS target is a requirement, as an OS will reserve many memory pages for it's own use, and this cfg file tells your program what memory pages it can and cannot touch, along with where your program's load address should be.