-
Notifications
You must be signed in to change notification settings - Fork 31
MEGA65 special PRG inject format
The 'inject prg' feature is designed to quickly load a PRG file as it would be a simple LOAD
and auto-RUN
combined. It can be requested by the command line option -prg
or via the context-UI-menu.
However this document now is about a special variant of it, designed for software development for MEGA65 using Xemu/MEGA65 emulator. It uses the same command line option (or the context-menu activation), Xemu decides about the "special" format based on the content of the PRG file. The idea, is to allow to load data into any part of the MEGA65's memory, even at various, multiple places, and also allow to fine control how to start something then to execute.
The file size is limit is 32Mbytes. This must be well enough for everybody even with filling the "attic" RAM which is 8Mbyte in size. Xemu (because of design roots) needs to keep the PRG file in memory, thus allowing much more would be a bit dangerous and - IMHO - useless.
To easy emulation task not to invent a totally new code path, this special formatted "fake" PRG file has a very strict construction to be able to be recognized as such. Exactly these two formats are supported only being the first bytes of the file:
$01 $08 $00 $00 $00 $00 $00 $58 $65 $6d $75 $2f $4d $45 $47 $41 $36 $35
$01 $20 $00 $00 $00 $00 $00 $58 $65 $6d $75 $2f $4d $45 $47 $41 $36 $35
The first version causes RESET into C64 mode, and then process the file, the second for the default C65 mode. Any other file header causes Xemu to treat the PRG file as a straight PRG file (like even a C64 ...), not this special formatted one! The first two bytes of "load address" here is not a real load address any more, just to help to distinguish the mode (C64/C65) needed.
After this header, one or more sections follows, each section has a section header, and at least one (or more) bytes of data for the section. All sections have the very same section header format, however the section header fields can mean different thing for different type of sections.
(word = 16 bits long unsigned value, long-word = 28 bits - 4 highest bits must be zero - long unsigned value, both are in C64-native byte order)
size | field name | description |
---|---|---|
5 bytes | magic_bytes | magic bytes, $58 $65 $6D $75 $21
|
word | type-ID | type of the section aka type-ID |
long-word | length | length of data, cannot be zero |
long-word | offset | offset of the section in memory (starting address) |
n bytes | data | data, size is "length of the section data" (unless stated otherwise later!!) |
Note, that not all sections uses all the section header fields in the same way or at all.
Addresses are meant in MEGA65 physical address. Example: $0000D000 does not mean "I/O is mapped there" since that's only a consequence of memory banking already, and not physical addresses.
Note, that memory region $00020000
- $0003FFFF
is the ROM. You can overwrite it with the right section offset, however, your program won't be able to do that as its own! It's your task then, to remove ROM protection if you really want to modify ROM as your own too. The reason that MEGA65's ROM is actually RAM, but normally it's write protected to "fake" being a ROM. Enabling to writing it requires a hypervisor call, though the PRG loader can just "poke" the underlying memory without problem.
In theory you can also modify any part of MEGA65 memory map, even I/O area with the MEGA65 "high address" location of that regions, if you really want.
Processing of sections are done in order in the file, you can even re-write the same area twice, or more.
type-ID | Description |
---|---|
$0000 |
"Run/terminate" section, specifies address to start execution. Must be the last section! Only the low 16 bits of offset used, and in this very case, the actual mapping of emulated machine counts. Length word must be one meaning one section data byte which means: zero to disable interrupts before jump, or non-zero to not bother it. Processing of the special-formatted-PRG file is stopped after this section. If offset is zero, no jump will be performed it can be used to denote a "fill/copy memory only" kind of operation without actual execution. Every file must have a type-0 section, at the end. The machine initial state after execution will be the "boot state" of C64 or C65 mode, including memory mapping, and anything expect the mentioned IRQ disable ability. |
$0001 |
Data, used to put data into memory, "Data" describes the memory layout must be copied into the memory. |
$0002 |
Initialize memory region (ie: fill) with a byte (described by "data"). Length is special here: though it indicates the number of bytes to fill, for real, the section holds only a single byte as data, the filler byte. |
Some can even write a loader for this format for the MEGA65, so basically the same file can be loaded into Xemu and a real MEGA65 as well, allowing to reduce the needed amount of work to put development (done on Xemu) into production and/or testing phase on a real MEGA65.
Some compressed section data would be useful, though currently it's not supported.