Commodore 64 cartridge image generator for use in a CI/CD environment.
Go to file
Bas v.d. Wiel 6a3ae69216 Add lockfile 2023-09-22 11:48:43 +02:00
src EasyFlash guide paragraph 3.5: empty bytes are now. 2023-09-05 15:50:27 +02:00
.gitignore Initial commit 2023-09-05 13:41:34 +02:00
Cargo.lock Add lockfile 2023-09-22 11:48:43 +02:00
Cargo.toml Update Cargo.toml 2023-09-22 09:47:30 +00:00
LICENSE Initial commit 2023-09-05 13:41:34 +02:00 Remove confusing example 2023-09-05 13:53:04 +02:00


The purpose of this tool is to do a single thing: convert a bunch of C64 PRG files into a valid EasyFlash-compatible .CRT cartridge image file. It doesn't concern itself with the contents of the PRG files at all. It's up to you to provide the properly working C64 internals.

This version of the tool was created for the sole purpose of having reproducible and automated builds of my Leisure Suit Larry C64 game. Anything else is out of scope, including user friendly error messages or sanity checking of any kind. The code is a mess but it works, which is good enough for me right now.

I will accept changes to this code and I may even take the software further if there's any sort of demand for a tool like this from the community. For now: use at your own risk. I only release this in the hope that it may be of use to someone besides myself.


Cartman is intended to be used in combination with a CI/CD pipeline. You feed it a YAML file for the cartridge's properties, and it gives you a .CRT file according to spec. The specification of the YAML file is described below (scroll down for example). The tool won't hold your hand, it'll just bomb out with a possibly unhelpful error message if something doesn't fit.

A cartridge image consists of a header, of which currently only the cartridge name is configurable, and a collection of CHIP packets which form the actual payload.

The cartridge name may be no longer than 32 upper case letters. The tool will take care of uppercasing, padding and converting the string to PETSCII for you, but that's it. The name will be truncated if it's too long and any invalid characters will simply be ignored.

The CHIP packets have a few configurable items:

Field Values
prg_file Name of the C64 PRG file, without its .prg extension.
chip_type ROM, RAM, EEPROM or Flash. Omit for ROM, which is fine most of the time.
bank_number CRT-file bank number. Defaults to 0 if you only have one.
rom_size Either 'Large' or 'Small' for 16KB or 8KB respectively.

Getting things to work

EasyFlash boots a C64 into UltiMax mode, which is one of the most braindead modes a C64 can ever find itself in. Most of the RAM is unavailable, none of the system ROM's are there and none of the hardware is initialized in any meaningful kind of way. In order to do anything useful at all, you need to put some memory in HIRAM so that you can intercept the RESET vector that's hard-wired into the 6510 CPU to be read from address $FFFC.

What this means: you put an address in there that the CPU can jump to, and you take the machine's complete bootstrap by the hand from there. I code in KickAssembler and a very bare-bones example looks like this:

*=$E000 "Bootstrap"
lda #$01
sta $D020
sta $D021
jmp hold
*=FFFC "RESET vector"
.byte $00,$E0

This code does nothing useful except turn your screen red. The red screen indicates that you can replace the code with something actually useful. Follow the EasyFlash documentation for that.

The most bare-bones cartridge image I got working is based on the following YAML:

  computer: C64
  file_header: 64
  version: 2
  hardware_type: EasyFlash
  hardware_subtype: 0
  exrom_line: 1
  game_line: 0
  - prg_file: coregame
    packet_length: 0
    chip_type: Flash
    bank_number: 0
    starting_load_address: 0x8000
    rom_size: Small
  - prg_file: bootstrap
    packet_length: 0
    chip_type: Flash
    bank_number: 0
    starting_load_address: 0xA000
    rom_size: Small

This contains the bootstrap code in the second CHIP package. EasyFlash expects there to be two 8KB banks in there, so you should provide them.