aboutsummaryrefslogtreecommitdiff
path: root/xex.inc
diff options
context:
space:
mode:
authorB. Watson <urchlay@slackware.uk>2022-12-10 18:08:27 -0500
committerB. Watson <urchlay@slackware.uk>2022-12-10 18:08:27 -0500
commit2c420394ee7a5d177e2485828c4fdb4dd35a28f8 (patch)
treebe2b14bf9f74b2230ce669b3daa33b7d22e5def3 /xex.inc
downloadtmu45tools-2c420394ee7a5d177e2485828c4fdb4dd35a28f8.tar.gz
Initial commit.
Diffstat (limited to 'xex.inc')
-rw-r--r--xex.inc166
1 files changed, 166 insertions, 0 deletions
diff --git a/xex.inc b/xex.inc
new file mode 100644
index 0000000..184b2f9
--- /dev/null
+++ b/xex.inc
@@ -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