BitMagic The Complete Development Environment for the Commander X16.

cc65 Library

How to import a library built with cc65 into a BitMagic project. The example uses Mooinglemur’s ZSMKit, a music playback library that plays exports from Furnace.

Before you start

ZSMKit is included as a submodule, so clone with --recurse-submodules. Build it with cc65 by following ZSMKit’s own instructions. zsmkit/lib/zsmkit.lib must exist, as that’s the file BitMagic imports.

How it works

The library’s ZSMKITLIB segment, which holds its code, is placed in the project’s main segment. Its ZSMKITBANK segment goes into a BitMagic segment in banked RAM. CC65.Exports writes the library’s routine addresses into the zsm scope.

    CC65.Code("ZSMKITLIB", obj);

    CC65.Exports(obj);

.segment ZSMBANK, $a000, $2000, _, zsm
    CC65.Code("ZSMKITBANK", obj);
.endsegment

ZSMKit is initialised to use bank 1. The program then loads SONG1.ZSM from the SD card into memory after its own code and points ZSMKit at it. The filename is a C# variable, so the same value is written into the source for SETNAM and used for its length:

var songFilename = "SONG1.ZSM";

    lda #@(songFilename.Length)
    ldx #<songname
    ldy #>songname
    jsr SETNAM

project.json copies the song to the SD card. Finally a loop waits for VSYNC and calls ZSMKit’s tick routine to play the music.

Importing a library

BitMagic ships with cc65library.bmasm for importing cc65 libraries:

import CC65="cc65library.bmasm";

; the library file, the scope name, and the base path for the source mapping
var obj = CC65.Parse(@"..\zsmkit\lib\zsmkit.lib", "zsm", @"..\zsmkit\");

The library’s routines are then in the zsm scope:

    lda #1
    jsr zsm:zsm_init_engine

The imported object has three methods.

Parse

Cc65Obj Parse(string filename, string scopeName, string sourcePath)

Loads a library file and returns the object that represents it.

Name Type Optional Description
filename string No The .lib file to load.
scopeName string No The scope to put the library’s exports in, to keep them apart from your code.
sourcePath string No The base path for the library’s source. If the library was built with debug information, BitMagic can step into the original code.

Code

void Code(string segmentName, Cc65Obj lib)

Writes the code for a segment of the library. Check the library’s documentation for the segment names it uses.

Note: segmentName is the library’s segment name, not a segment in the BitMagic project.

Exports

void Exports(Cc65Obj lib)

Writes the library’s exports, such as the addresses of its routines and variables, into the scope given to Parse.

Debugging the library

You can debug the library’s source the same way as a .bmasm file. Change the language of the library’s .s files to BitMagic X16 Asm: press Ctrl+K M and pick it from the list, or use the language selector in the bottom right of the editor. See the VSCode documentation for more.

Breakpoints in ZSMKit

View the source on GitHub