diff options
author | B. Watson <urchlay@slackware.uk> | 2022-12-10 18:08:27 -0500 |
---|---|---|
committer | B. Watson <urchlay@slackware.uk> | 2022-12-10 18:08:27 -0500 |
commit | 2c420394ee7a5d177e2485828c4fdb4dd35a28f8 (patch) | |
tree | be2b14bf9f74b2230ce669b3daa33b7d22e5def3 /xex.inc | |
download | tmu45tools-2c420394ee7a5d177e2485828c4fdb4dd35a28f8.tar.gz |
Initial commit.
Diffstat (limited to 'xex.inc')
-rw-r--r-- | xex.inc | 166 |
1 files changed, 166 insertions, 0 deletions
@@ -0,0 +1,166 @@ +; xex.inc - easy way to generate an atari 8-bit executable with ca65, +; without dealing with ca65's linker scripts and segments. +; see xex.rst (or xex.html) for full documentation. + + .macro xex_failtarget target + .ifdef target + .fatal "must assemble with '-t none'" + .endif + .endmacro + + xex_failtarget __APPLE2__ + xex_failtarget __APPLE2ENH__ + xex_failtarget __ATARI2600__ + xex_failtarget __ATARI5200__ + xex_failtarget __ATARI__ + xex_failtarget __ATARIXL__ + xex_failtarget __ATMOS__ + xex_failtarget __BBC__ + xex_failtarget __C128__ + xex_failtarget __C16__ + xex_failtarget __C64__ + xex_failtarget __CBM__ + xex_failtarget __CBM510__ + xex_failtarget __CBM610__ + xex_failtarget __CX16__ + xex_failtarget __GEOS__ + xex_failtarget __GEOS_APPLE__ + xex_failtarget __GEOS_CBM__ + xex_failtarget __LUNIX__ + xex_failtarget __LYNX__ + xex_failtarget __NES__ + xex_failtarget __OSIC1P__ + xex_failtarget __PET__ + xex_failtarget __PLUS4__ + xex_failtarget __SIM6502__ + xex_failtarget __SIM65C02__ + xex_failtarget __SUPERVISION__ + xex_failtarget __VIC20__ + + .ifndef RUNAD + .include "atari.inc" + .endif + + .ifndef xex_verbose + xex_verbose=1 + .endif + + .ifndef xex_warnings + xex_warnings=1 + .endif + + xex_api_called .set 0 + xex_segcount .set 1 + xex_old_org .set -1 + + .macro xex_vprint arg + .if xex_verbose + .out .concat("xex.inc: ",arg) + .endif + .endmacro + + .macro xex_warn arg + .if xex_verbose + .warning .concat("xex.inc: ",arg) + .endif + .endmacro + + .macro xexstart startaddr, endaddr + .if xex_api_called = 0 + .fatal "xex.inc: don't call xexstart directly, use xex_org." + .endif + xex_api_called .set 0 + .if xex_old_org > -1 + xex_endseg + .endif + .org 0 ; can be anything really... + .ifndef xex_ffff_emitted + .byte $ff,$ff + xex_ffff_emitted=1 + xex_vprint .sprintf("starting segment %d at $%04x (with ffff header)", xex_segcount, startaddr) + .else + xex_vprint .sprintf("starting segment %d at $%04x", xex_segcount, startaddr) + .endif + .word startaddr + .word endaddr-1 + .org startaddr + ; we don't need a label here really, but define it so it shows up in + ; the VICE label file created by -Ln. + .ident(.sprintf("xex_startaddr_%d", xex_segcount)): + xex_segcount .set xex_segcount + 1 + .endmacro + + .macro xex_org startaddr,limit + xex_api_called .set 1 + xexstart startaddr,.ident(.sprintf("xex_endaddr_%d", xex_segcount)) + xex_old_org .set startaddr + .ifblank limit + xex_limit .set $10000 ; impossibly high + .else + xex_limit .set limit + .endif + .endmacro + + .macro xex_endseg + .local endaddr + endaddr = * - 1 + .if xex_old_org < 0 + xex_warn "xex_endseg called when not in a segment; harmless but redundant." + .exitmacro + .endif + .if endaddr < xex_old_org + .fatal .sprintf("cannot create an empty segment (start $%04x, end $%04x)", xex_old_org, endaddr) + .endif + .ident(.sprintf("xex_endaddr_%d", xex_segcount-1)): + xex_vprint .sprintf(" ending segment %d at $%04x, length $%04x", xex_segcount-1, endaddr, endaddr-xex_old_org+1) + xex_old_org .set -1 + .assert .not (endaddr >= xex_limit), error, .sprintf("xex.inc: segment %d exceeds user-requested limit $%04x, by $%04x bytes", xex_segcount-1, xex_limit, endaddr - xex_limit + 1) + xex_limit .set $10000 + .endmacro + + .macro xex_run runaddr + xex_org RUNAD + .word runaddr + xex_endseg + xex_vprint .sprintf(" run address: $%04x", runaddr) + .ifndef xex_run_addr + xex_run_addr .set runaddr + .else + xex_warn .sprintf("multiple run addresses (previous was $%04x)", xex_run_addr) + xex_run_addr .set runaddr + .endif + .endmacro + + .macro xex_init initaddr + xex_org INITAD + .word initaddr + xex_endseg + xex_vprint .sprintf(" init address: $%04x", initaddr) + .endmacro + + .macro xex_incbin addr, filename, offset, length + .local o + .ifblank offset + o = 0 + .else + o = offset + .endif + xex_org addr + .ifblank length + .incbin filename, o + .else + .incbin filename, o, length + .endif + xex_endseg + .endmacro + + ;;; THIS DOESN'T WORK! + .if 0 + .macro xex_include addr, filename + xex_org addr + .out .sprintf("before include %s: %04x", filename, *) + .include filename + .out .sprintf("after include: %04x", *) + xex_endseg + .endmacro + .endif |