aboutsummaryrefslogtreecommitdiff
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
downloadtmu45tools-2c420394ee7a5d177e2485828c4fdb4dd35a28f8.tar.gz
Initial commit.
-rw-r--r--.makepp/log173
-rw-r--r--.makepp/setmem.xex.mk13
-rw-r--r--.makepp/setmemr.xex.mk13
-rw-r--r--.makepp/setmemrx.xex.mk13
-rw-r--r--.makepp/setmemx.xex.mk13
-rw-r--r--.makepp/u256.xex.mk13
-rw-r--r--.makepp/u256r.xex.mk13
-rw-r--r--.makepp/u256rx.xex.mk13
-rw-r--r--.makepp/u256x.xex.mk13
-rw-r--r--.makepp/u512.xex.mk13
-rw-r--r--.makepp/u512r.xex.mk13
-rw-r--r--.makepp/u512rx.xex.mk13
-rw-r--r--.makepp/u512x.xex.mk13
-rw-r--r--.makepp/uoff.xex.mk13
-rw-r--r--.makepp/uoffx.xex.mk13
-rw-r--r--.makepp/ver.s.mk13
-rw-r--r--Makefile112
-rw-r--r--README.txt65
-rw-r--r--inv.inc53
-rw-r--r--mydos450.atrbin0 -> 92176 bytes
-rw-r--r--setmem.info62
-rw-r--r--setmem.orig.xexbin0 -> 877 bytes
-rw-r--r--setmem.s267
-rw-r--r--tmu45tools-0.0.2.atrbin0 -> 92176 bytes
-rw-r--r--tmu45tools-0.0.2.zipbin0 -> 20841 bytes
-rw-r--r--u.s199
-rw-r--r--ver.s1
-rw-r--r--xex.inc166
28 files changed, 1293 insertions, 0 deletions
diff --git a/.makepp/log b/.makepp/log
new file mode 100644
index 0000000..71c8143
--- /dev/null
+++ b/.makepp/log
@@ -0,0 +1,173 @@
+3/usr/bin/makepp
+VERSION2.0.99.25.34.0x86_64-linux-thread-multi
+DEBUG0
+LOAD13444f8Makefile1566970/home/urchlay/setmem1566970
+TRY13444f8
+USEdefault rule
+DEPEND13444f8
+UP_TO_DATE13444f8
+LOAD_INCL1d47bd0makepp_builtin_rules.mk133a8c0/usr/share/makepp13444f8
+LOAD_END13444f8
+TRY1d2d098all1566970
+USEdefault rule
+DEPEND1d2d0981d2d2a8setmems15669701d2d1d0utools1566970
+TRY1d2d2a8
+USEdefault rule
+DEPEND1d2d2a81d2d9e0setmem.xex15669701d2db18setmemr.xex15669701d2dd88setmemrx.xex15669701d2dc50setmemx.xex1566970
+TRY1d2d9e0
+USE/home/urchlay/setmem/Makefile:27
+SCAN_INFO1d2d9e0
+LEX_RULE1d2d9e0info not cached
+PARSEcl65 -g -t none --asm-define xex_verbose=0 -l setmem.xex.list -o setmem.xex setmem.s1566970/home/urchlay/setmem/Makefile:27
+TRY1d76258cl651d76180/usr/bin
+USEdefault rule
+DEPEND1d76258
+UP_TO_DATE1d76258
+PARSEcmp setmem.xex setmem.orig.xex1566970/home/urchlay/setmem/Makefile:27
+TRY1d0b328cmp1d76180
+USEdefault rule
+DEPEND1d0b328
+UP_TO_DATE1d0b328
+PARSEecho "OK: setmem.xex identical to setmem.orig.xex"1566970/home/urchlay/setmem/Makefile:27
+PARSEecho "*** setmem.s is broken (setmem.xex not identical to setmem.orig.xex)"1566970/home/urchlay/setmem/Makefile:27
+PARSEexit 11566970/home/urchlay/setmem/Makefile:27
+PARSEfi1566970/home/urchlay/setmem/Makefile:27
+DEPEND1d2d9e01d762581d0b3281d577f8inv.inc15669701d57cf0setmem.s15669701d57888xex.inc1566970
+TRY1d577f8
+USEdefault rule
+DEPEND1d577f8
+UP_TO_DATE1d577f8
+TRY1d57cf0
+USEdefault rule
+DEPEND1d57cf0
+UP_TO_DATE1d57cf0
+TRY1d57888
+USEdefault rule
+DEPEND1d57888
+UP_TO_DATE1d57888
+BUILD_NONE1d2d9e0
+SUCCESS/home/urchlay/setmem/Makefile:271d2d9e0
+TRY1d2db18
+USE/home/urchlay/setmem/Makefile:36
+SCAN_INFO1d2db18
+LEX_RULE1d2db18info not cached
+PARSEcl65 -g -t none --asm-define xex_verbose=0 --asm-define reverse_logic=1 -l setmemr.xex.list -o setmemr.xex setmem.s1566970/home/urchlay/setmem/Makefile:36
+DEPEND1d2db181d762581d577f81d57cf01d57888
+BUILD_NONE1d2db18
+SUCCESS/home/urchlay/setmem/Makefile:361d2db18
+TRY1d2dd88
+USE/home/urchlay/setmem/Makefile:42
+SCAN_INFO1d2dd88
+LEX_RULE1d2dd88info not cached
+PARSEcl65 -g -t none --asm-define xex_verbose=0 --asm-define reverse_logic=1 --asm-define coldstart=1 -l setmemrx.xex.list -o setmemrx.xex setmem.s1566970/home/urchlay/setmem/Makefile:42
+DEPEND1d2dd881d762581d577f81d57cf01d57888
+BUILD_NONE1d2dd88
+SUCCESS/home/urchlay/setmem/Makefile:421d2dd88
+TRY1d2dc50
+USE/home/urchlay/setmem/Makefile:39
+SCAN_INFO1d2dc50
+LEX_RULE1d2dc50info not cached
+PARSEcl65 -g -t none --asm-define xex_verbose=0 --asm-define coldstart=1 -l setmemx.xex.list -o setmemx.xex setmem.s1566970/home/urchlay/setmem/Makefile:39
+DEPEND1d2dc501d762581d577f81d57cf01d57888
+BUILD_NONE1d2dc50
+SUCCESS/home/urchlay/setmem/Makefile:391d2dc50
+BUILD_PHONY1d2d2a8
+SUCCESSdefault rule1d2d2a8
+TRY1d2d1d0
+USEdefault rule
+DEPEND1d2d1d01d366f0u256.xex15669701d37560u256r.xex15669701d47780u256rx.xex15669701d47510u256x.xex15669701d36828u512.xex15669701d472a0u512r.xex15669701d478b8u512rx.xex15669701d47648u512x.xex15669701d2dec0uoff.xex15669701d473d8uoffx.xex1566970
+TRY1d366f0
+USE/home/urchlay/setmem/Makefile:48
+SCAN_INFO1d366f0
+LEX_RULE1d366f0info not cached
+PARSEcl65 -g -t none --asm-define xex_verbose=0 --asm-define magic_value=2 -l u256.xex.list -o u256.xex u.s1566970/home/urchlay/setmem/Makefile:48
+DEPEND1d366f01d762581d57ea0u.s15669701d479d8ver.s15669701d57888
+TRY1d57ea0
+USEdefault rule
+DEPEND1d57ea0
+UP_TO_DATE1d57ea0
+TRY1d479d8
+USE/home/urchlay/setmem/Makefile:75
+SCAN_INFO1d479d8
+SCAN_CACHED1d479d8
+DEPEND1d479d8
+UP_TO_DATE1d479d8
+BUILD_NONE1d366f0
+SUCCESS/home/urchlay/setmem/Makefile:481d366f0
+TRY1d37560
+USE/home/urchlay/setmem/Makefile:54
+SCAN_INFO1d37560
+LEX_RULE1d37560info not cached
+PARSEcl65 -g -t none --asm-define xex_verbose=0 --asm-define magic_value=0 --asm-define reverse_logic=1 -l u256r.xex.list -o u256r.xex u.s1566970/home/urchlay/setmem/Makefile:54
+DEPEND1d375601d762581d57ea01d479d81d57888
+BUILD_NONE1d37560
+SUCCESS/home/urchlay/setmem/Makefile:541d37560
+TRY1d47780
+USE/home/urchlay/setmem/Makefile:69
+SCAN_INFO1d47780
+LEX_RULE1d47780info not cached
+PARSEcl65 -g -t none --asm-define xex_verbose=0 --asm-define coldstart=1 --asm-define magic_value=0 --asm-define reverse_logic=1 -l u256rx.xex.list -o u256rx.xex u.s1566970/home/urchlay/setmem/Makefile:69
+DEPEND1d477801d762581d57ea01d479d81d57888
+BUILD_NONE1d47780
+SUCCESS/home/urchlay/setmem/Makefile:691d47780
+TRY1d47510
+USE/home/urchlay/setmem/Makefile:63
+SCAN_INFO1d47510
+LEX_RULE1d47510info not cached
+PARSEcl65 -g -t none --asm-define xex_verbose=0 --asm-define coldstart=1 --asm-define magic_value=2 -l u256x.xex.list -o u256x.xex u.s1566970/home/urchlay/setmem/Makefile:63
+DEPEND1d475101d762581d57ea01d479d81d57888
+BUILD_NONE1d47510
+SUCCESS/home/urchlay/setmem/Makefile:631d47510
+TRY1d36828
+USE/home/urchlay/setmem/Makefile:51
+SCAN_INFO1d36828
+LEX_RULE1d36828info not cached
+PARSEcl65 -g -t none --asm-define xex_verbose=0 --asm-define magic_value=0 -l u512.xex.list -o u512.xex u.s1566970/home/urchlay/setmem/Makefile:51
+DEPEND1d368281d762581d57ea01d479d81d57888
+BUILD_NONE1d36828
+SUCCESS/home/urchlay/setmem/Makefile:511d36828
+TRY1d472a0
+USE/home/urchlay/setmem/Makefile:57
+SCAN_INFO1d472a0
+LEX_RULE1d472a0info not cached
+PARSEcl65 -g -t none --asm-define xex_verbose=0 --asm-define magic_value=2 --asm-define reverse_logic=1 -l u512r.xex.list -o u512r.xex u.s1566970/home/urchlay/setmem/Makefile:57
+DEPEND1d472a01d762581d57ea01d479d81d57888
+BUILD_NONE1d472a0
+SUCCESS/home/urchlay/setmem/Makefile:571d472a0
+TRY1d478b8
+USE/home/urchlay/setmem/Makefile:72
+SCAN_INFO1d478b8
+LEX_RULE1d478b8info not cached
+PARSEcl65 -g -t none --asm-define xex_verbose=0 --asm-define coldstart=1 --asm-define magic_value=2 --asm-define reverse_logic=1 -l u512rx.xex.list -o u512rx.xex u.s1566970/home/urchlay/setmem/Makefile:72
+DEPEND1d478b81d762581d57ea01d479d81d57888
+BUILD_NONE1d478b8
+SUCCESS/home/urchlay/setmem/Makefile:721d478b8
+TRY1d47648
+USE/home/urchlay/setmem/Makefile:66
+SCAN_INFO1d47648
+LEX_RULE1d47648info not cached
+PARSEcl65 -g -t none --asm-define xex_verbose=0 --asm-define coldstart=1 --asm-define magic_value=0 -l u512x.xex.list -o u512x.xex u.s1566970/home/urchlay/setmem/Makefile:66
+DEPEND1d476481d762581d57ea01d479d81d57888
+BUILD_NONE1d47648
+SUCCESS/home/urchlay/setmem/Makefile:661d47648
+TRY1d2dec0
+USE/home/urchlay/setmem/Makefile:45
+SCAN_INFO1d2dec0
+LEX_RULE1d2dec0info not cached
+PARSEcl65 -g -t none --asm-define xex_verbose=0 --asm-define magic_value=1 -l uoff.xex.list -o uoff.xex u.s1566970/home/urchlay/setmem/Makefile:45
+DEPEND1d2dec01d762581d57ea01d479d81d57888
+BUILD_NONE1d2dec0
+SUCCESS/home/urchlay/setmem/Makefile:451d2dec0
+TRY1d473d8
+USE/home/urchlay/setmem/Makefile:60
+SCAN_INFO1d473d8
+LEX_RULE1d473d8info not cached
+PARSEcl65 -g -t none --asm-define xex_verbose=0 --asm-define coldstart=1 --asm-define magic_value=1 -l uoffx.xex.list -o uoffx.xex u.s1566970/home/urchlay/setmem/Makefile:60
+DEPEND1d473d81d762581d57ea01d479d81d57888
+BUILD_NONE1d473d8
+SUCCESS/home/urchlay/setmem/Makefile:601d473d8
+BUILD_PHONY1d2d1d0
+SUCCESSdefault rule1d2d1d0
+BUILD_PHONY1d2d098
+SUCCESSdefault rule1d2d098
+N_FILES1430
diff --git a/.makepp/setmem.xex.mk b/.makepp/setmem.xex.mk
new file mode 100644
index 0000000..56155e1
--- /dev/null
+++ b/.makepp/setmem.xex.mk
@@ -0,0 +1,13 @@
+INCLUDE_SFXS=
+META_DEPS=/usr/bin/cl65/usr/bin/cmp
+IMPLICIT_TARGETS=
+ARCH=x86_64-linux-thread-multi
+COMMAND=cl65 -g -t none --asm-define xex_verbose=0 -l setmem.xex.list -o setmem.xex setmem.s@if cmp setmem.xex setmem.orig.xex; then echo "OK: setmem.xex identical to setmem.orig.xex"; else echo "*** setmem.s is broken (setmem.xex not identical to setmem.orig.xex)"; exit 1; fi
+SORTED_DEPS=/usr/bin/cl65/usr/bin/cmpinv.incsetmem.sxex.inc
+DEP_SIGS=1644100112,516481627926412,519121670699614,14371670700826,68991670699690,4145
+IMPLICIT_DEPS=
+BUILD_SIGNATURE=1670704007,877
+CWD=.
+INCLUDE_PATHS=
+SIGNATURE=1670704007,877
+END= \ No newline at end of file
diff --git a/.makepp/setmemr.xex.mk b/.makepp/setmemr.xex.mk
new file mode 100644
index 0000000..6a9bc64
--- /dev/null
+++ b/.makepp/setmemr.xex.mk
@@ -0,0 +1,13 @@
+ARCH=x86_64-linux-thread-multi
+COMMAND=cl65 -g -t none --asm-define xex_verbose=0 --asm-define reverse_logic=1 -l setmemr.xex.list -o setmemr.xex setmem.s
+META_DEPS=/usr/bin/cl65
+IMPLICIT_TARGETS=
+INCLUDE_SFXS=
+DEP_SIGS=1644100112,516481670699614,14371670700826,68991670699690,4145
+SORTED_DEPS=/usr/bin/cl65inv.incsetmem.sxex.inc
+CWD=.
+INCLUDE_PATHS=
+BUILD_SIGNATURE=1670704007,877
+IMPLICIT_DEPS=
+SIGNATURE=1670704007,877
+END= \ No newline at end of file
diff --git a/.makepp/setmemrx.xex.mk b/.makepp/setmemrx.xex.mk
new file mode 100644
index 0000000..75dc8a5
--- /dev/null
+++ b/.makepp/setmemrx.xex.mk
@@ -0,0 +1,13 @@
+DEP_SIGS=1644100112,516481670699614,14371670700826,68991670699690,4145
+SORTED_DEPS=/usr/bin/cl65inv.incsetmem.sxex.inc
+ARCH=x86_64-linux-thread-multi
+COMMAND=cl65 -g -t none --asm-define xex_verbose=0 --asm-define reverse_logic=1 --asm-define coldstart=1 -l setmemrx.xex.list -o setmemrx.xex setmem.s
+IMPLICIT_TARGETS=
+META_DEPS=/usr/bin/cl65
+INCLUDE_SFXS=
+SIGNATURE=1670704007,872
+CWD=.
+INCLUDE_PATHS=
+BUILD_SIGNATURE=1670704007,872
+IMPLICIT_DEPS=
+END= \ No newline at end of file
diff --git a/.makepp/setmemx.xex.mk b/.makepp/setmemx.xex.mk
new file mode 100644
index 0000000..76710db
--- /dev/null
+++ b/.makepp/setmemx.xex.mk
@@ -0,0 +1,13 @@
+BUILD_SIGNATURE=1670704007,872
+CWD=.
+INCLUDE_PATHS=
+IMPLICIT_DEPS=
+SIGNATURE=1670704007,872
+META_DEPS=/usr/bin/cl65
+IMPLICIT_TARGETS=
+ARCH=x86_64-linux-thread-multi
+COMMAND=cl65 -g -t none --asm-define xex_verbose=0 --asm-define coldstart=1 -l setmemx.xex.list -o setmemx.xex setmem.s
+INCLUDE_SFXS=
+DEP_SIGS=1644100112,516481670699614,14371670700826,68991670699690,4145
+SORTED_DEPS=/usr/bin/cl65inv.incsetmem.sxex.inc
+END= \ No newline at end of file
diff --git a/.makepp/u256.xex.mk b/.makepp/u256.xex.mk
new file mode 100644
index 0000000..36afdef
--- /dev/null
+++ b/.makepp/u256.xex.mk
@@ -0,0 +1,13 @@
+SORTED_DEPS=/usr/bin/cl65u.sver.sxex.inc
+DEP_SIGS=1644100112,516481670487139,41391670703925,251670699690,4145
+INCLUDE_SFXS=
+IMPLICIT_TARGETS=
+META_DEPS=/usr/bin/cl65
+COMMAND=cl65 -g -t none --asm-define xex_verbose=0 --asm-define magic_value=2 -l u256.xex.list -o u256.xex u.s
+ARCH=x86_64-linux-thread-multi
+SIGNATURE=1670704007,190
+IMPLICIT_DEPS=
+BUILD_SIGNATURE=1670704007,190
+INCLUDE_PATHS=
+CWD=.
+END= \ No newline at end of file
diff --git a/.makepp/u256r.xex.mk b/.makepp/u256r.xex.mk
new file mode 100644
index 0000000..e1b234f
--- /dev/null
+++ b/.makepp/u256r.xex.mk
@@ -0,0 +1,13 @@
+INCLUDE_PATHS=
+CWD=.
+BUILD_SIGNATURE=1670704007,191
+IMPLICIT_DEPS=
+SIGNATURE=1670704007,191
+COMMAND=cl65 -g -t none --asm-define xex_verbose=0 --asm-define magic_value=0 --asm-define reverse_logic=1 -l u256r.xex.list -o u256r.xex u.s
+ARCH=x86_64-linux-thread-multi
+META_DEPS=/usr/bin/cl65
+IMPLICIT_TARGETS=
+INCLUDE_SFXS=
+DEP_SIGS=1644100112,516481670487139,41391670703925,251670699690,4145
+SORTED_DEPS=/usr/bin/cl65u.sver.sxex.inc
+END= \ No newline at end of file
diff --git a/.makepp/u256rx.xex.mk b/.makepp/u256rx.xex.mk
new file mode 100644
index 0000000..41f13d1
--- /dev/null
+++ b/.makepp/u256rx.xex.mk
@@ -0,0 +1,13 @@
+IMPLICIT_DEPS=
+BUILD_SIGNATURE=1670704007,268
+CWD=.
+INCLUDE_PATHS=
+SIGNATURE=1670704007,268
+INCLUDE_SFXS=
+IMPLICIT_TARGETS=
+META_DEPS=/usr/bin/cl65
+ARCH=x86_64-linux-thread-multi
+COMMAND=cl65 -g -t none --asm-define xex_verbose=0 --asm-define coldstart=1 --asm-define magic_value=0 --asm-define reverse_logic=1 -l u256rx.xex.list -o u256rx.xex u.s
+SORTED_DEPS=/usr/bin/cl65u.sver.sxex.inc
+DEP_SIGS=1644100112,516481670487139,41391670703925,251670699690,4145
+END= \ No newline at end of file
diff --git a/.makepp/u256x.xex.mk b/.makepp/u256x.xex.mk
new file mode 100644
index 0000000..252a63f
--- /dev/null
+++ b/.makepp/u256x.xex.mk
@@ -0,0 +1,13 @@
+IMPLICIT_DEPS=
+INCLUDE_PATHS=
+CWD=.
+BUILD_SIGNATURE=1670704007,267
+SIGNATURE=1670704007,267
+INCLUDE_SFXS=
+COMMAND=cl65 -g -t none --asm-define xex_verbose=0 --asm-define coldstart=1 --asm-define magic_value=2 -l u256x.xex.list -o u256x.xex u.s
+ARCH=x86_64-linux-thread-multi
+IMPLICIT_TARGETS=
+META_DEPS=/usr/bin/cl65
+SORTED_DEPS=/usr/bin/cl65u.sver.sxex.inc
+DEP_SIGS=1644100112,516481670487139,41391670703925,251670699690,4145
+END= \ No newline at end of file
diff --git a/.makepp/u512.xex.mk b/.makepp/u512.xex.mk
new file mode 100644
index 0000000..f118254
--- /dev/null
+++ b/.makepp/u512.xex.mk
@@ -0,0 +1,13 @@
+SIGNATURE=1670704007,190
+CWD=.
+INCLUDE_PATHS=
+BUILD_SIGNATURE=1670704007,190
+IMPLICIT_DEPS=
+DEP_SIGS=1644100112,516481670487139,41391670703925,251670699690,4145
+SORTED_DEPS=/usr/bin/cl65u.sver.sxex.inc
+ARCH=x86_64-linux-thread-multi
+COMMAND=cl65 -g -t none --asm-define xex_verbose=0 --asm-define magic_value=0 -l u512.xex.list -o u512.xex u.s
+IMPLICIT_TARGETS=
+META_DEPS=/usr/bin/cl65
+INCLUDE_SFXS=
+END= \ No newline at end of file
diff --git a/.makepp/u512r.xex.mk b/.makepp/u512r.xex.mk
new file mode 100644
index 0000000..3e80e40
--- /dev/null
+++ b/.makepp/u512r.xex.mk
@@ -0,0 +1,13 @@
+SIGNATURE=1670704007,191
+IMPLICIT_DEPS=
+CWD=.
+INCLUDE_PATHS=
+BUILD_SIGNATURE=1670704007,191
+SORTED_DEPS=/usr/bin/cl65u.sver.sxex.inc
+DEP_SIGS=1644100112,516481670487139,41391670703925,251670699690,4145
+INCLUDE_SFXS=
+ARCH=x86_64-linux-thread-multi
+COMMAND=cl65 -g -t none --asm-define xex_verbose=0 --asm-define magic_value=2 --asm-define reverse_logic=1 -l u512r.xex.list -o u512r.xex u.s
+META_DEPS=/usr/bin/cl65
+IMPLICIT_TARGETS=
+END= \ No newline at end of file
diff --git a/.makepp/u512rx.xex.mk b/.makepp/u512rx.xex.mk
new file mode 100644
index 0000000..982f671
--- /dev/null
+++ b/.makepp/u512rx.xex.mk
@@ -0,0 +1,13 @@
+INCLUDE_SFXS=
+COMMAND=cl65 -g -t none --asm-define xex_verbose=0 --asm-define coldstart=1 --asm-define magic_value=2 --asm-define reverse_logic=1 -l u512rx.xex.list -o u512rx.xex u.s
+ARCH=x86_64-linux-thread-multi
+IMPLICIT_TARGETS=
+META_DEPS=/usr/bin/cl65
+SORTED_DEPS=/usr/bin/cl65u.sver.sxex.inc
+DEP_SIGS=1644100112,516481670487139,41391670703925,251670699690,4145
+IMPLICIT_DEPS=
+INCLUDE_PATHS=
+CWD=.
+BUILD_SIGNATURE=1670704007,268
+SIGNATURE=1670704007,268
+END= \ No newline at end of file
diff --git a/.makepp/u512x.xex.mk b/.makepp/u512x.xex.mk
new file mode 100644
index 0000000..06a9350
--- /dev/null
+++ b/.makepp/u512x.xex.mk
@@ -0,0 +1,13 @@
+DEP_SIGS=1644100112,516481670487139,41391670703925,251670699690,4145
+SORTED_DEPS=/usr/bin/cl65u.sver.sxex.inc
+IMPLICIT_TARGETS=
+META_DEPS=/usr/bin/cl65
+ARCH=x86_64-linux-thread-multi
+COMMAND=cl65 -g -t none --asm-define xex_verbose=0 --asm-define coldstart=1 --asm-define magic_value=0 -l u512x.xex.list -o u512x.xex u.s
+INCLUDE_SFXS=
+SIGNATURE=1670704007,267
+BUILD_SIGNATURE=1670704007,267
+CWD=.
+INCLUDE_PATHS=
+IMPLICIT_DEPS=
+END= \ No newline at end of file
diff --git a/.makepp/uoff.xex.mk b/.makepp/uoff.xex.mk
new file mode 100644
index 0000000..54a978e
--- /dev/null
+++ b/.makepp/uoff.xex.mk
@@ -0,0 +1,13 @@
+SIGNATURE=1670704007,196
+BUILD_SIGNATURE=1670704007,196
+CWD=.
+INCLUDE_PATHS=
+IMPLICIT_DEPS=
+DEP_SIGS=1644100112,516481670487139,41391670703925,251670699690,4145
+SORTED_DEPS=/usr/bin/cl65u.sver.sxex.inc
+IMPLICIT_TARGETS=
+META_DEPS=/usr/bin/cl65
+ARCH=x86_64-linux-thread-multi
+COMMAND=cl65 -g -t none --asm-define xex_verbose=0 --asm-define magic_value=1 -l uoff.xex.list -o uoff.xex u.s
+INCLUDE_SFXS=
+END= \ No newline at end of file
diff --git a/.makepp/uoffx.xex.mk b/.makepp/uoffx.xex.mk
new file mode 100644
index 0000000..835a2a3
--- /dev/null
+++ b/.makepp/uoffx.xex.mk
@@ -0,0 +1,13 @@
+SORTED_DEPS=/usr/bin/cl65u.sver.sxex.inc
+DEP_SIGS=1644100112,516481670487139,41391670703925,251670699690,4145
+INCLUDE_SFXS=
+IMPLICIT_TARGETS=
+META_DEPS=/usr/bin/cl65
+COMMAND=cl65 -g -t none --asm-define xex_verbose=0 --asm-define coldstart=1 --asm-define magic_value=1 -l uoffx.xex.list -o uoffx.xex u.s
+ARCH=x86_64-linux-thread-multi
+SIGNATURE=1670704007,273
+IMPLICIT_DEPS=
+BUILD_SIGNATURE=1670704007,273
+INCLUDE_PATHS=
+CWD=.
+END= \ No newline at end of file
diff --git a/.makepp/ver.s.mk b/.makepp/ver.s.mk
new file mode 100644
index 0000000..999034c
--- /dev/null
+++ b/.makepp/ver.s.mk
@@ -0,0 +1,13 @@
+BUILD_SIGNATURE=1670703925,25
+INCLUDE_SFXS=
+COMMAND=echo " .define VERSION \""0.0.2"\"" > ver.s
+META_DEPS=
+SORTED_DEPS=
+DEP_SIGS=
+INCLUDE_PATHS=
+CWD=.
+ARCH=x86_64-linux-thread-multi
+SIGNATURE=1670703925,25
+IMPLICIT_DEPS=
+IMPLICIT_TARGETS=ver.s
+END= \ No newline at end of file
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..4471d45
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,112 @@
+# Makefile for tmu45tools
+# Only seems to work with GNU make (not BSD, sorry).
+
+PROJECT=tmu45tools
+VERSION=0.0.2
+
+CL65=cl65
+CL65FLAGS=-g -t none
+
+# comment this out if you need to see start/run addresses
+CL65FLAGS+= --asm-define xex_verbose=0
+
+C=$(CL65) $(CL65FLAGS)
+MVAL0=--asm-define magic_value=0
+MVAL1=--asm-define magic_value=1
+MVAL2=--asm-define magic_value=2
+RLOGIC=--asm-define reverse_logic=1
+COLD=--asm-define coldstart=1
+
+UTOOLS=u256.xex u512.xex uoff.xex u256r.xex u512r.xex uoffx.xex u256x.xex u512x.xex u256rx.xex u512rx.xex
+SETMEMS=setmem.xex setmemr.xex setmemx.xex setmemrx.xex
+
+UDEPS=u.s ver.s xex.inc
+SMDEPS=setmem.s xex.inc inv.inc
+
+ZIP=zip
+ZIPFILE=$(PROJECT)-$(VERSION).zip
+
+AXE=axe
+ATRFILE=$(PROJECT)-$(VERSION).atr
+
+all: setmems utools
+
+utools: $(UTOOLS)
+
+setmems: $(SETMEMS)
+
+setmem.da65.s: setmem.xex setmem.info
+ da65 -i setmem.info
+
+setmem.xex: $(SMDEPS)
+ $(C) -l $@.list -o $@ $<
+ @if cmp setmem.xex setmem.orig.xex; then \
+ echo "OK: setmem.xex identical to setmem.orig.xex"; \
+ else \
+ echo "*** setmem.s is broken (setmem.xex not identical to setmem.orig.xex)"; \
+ exit 1; \
+ fi
+
+setmemr.xex: $(SMDEPS)
+ $(C) $(RLOGIC) -l $@.list -o $@ $<
+
+setmemx.xex: $(SMDEPS)
+ $(C) $(COLD) -l $@.list -o $@ $<
+
+setmemrx.xex: $(SMDEPS)
+ $(C) $(RLOGIC) $(COLD) -l $@.list -o $@ $<
+
+uoff.xex: $(UDEPS)
+ $(C) $(MVAL1) -l $@.list -o $@ $<
+
+u256.xex: $(UDEPS)
+ $(C) $(MVAL2) -l $@.list -o $@ $<
+
+u512.xex: $(UDEPS)
+ $(C) $(MVAL0) -l $@.list -o $@ $<
+
+u256r.xex: $(UDEPS)
+ $(C) $(MVAL0) $(RLOGIC) -l $@.list -o $@ $<
+
+u512r.xex: $(UDEPS)
+ $(C) $(MVAL2) $(RLOGIC) -l $@.list -o $@ $<
+
+uoffx.xex: $(UDEPS)
+ $(C) $(COLD) $(MVAL1) -l $@.list -o $@ $<
+
+u256x.xex: $(UDEPS)
+ $(C) $(COLD) $(MVAL2) -l $@.list -o $@ $<
+
+u512x.xex: $(UDEPS)
+ $(C) $(COLD) $(MVAL0) -l $@.list -o $@ $<
+
+u256rx.xex: $(UDEPS)
+ $(C) $(COLD) $(MVAL0) $(RLOGIC) -l $@.list -o $@ $<
+
+u512rx.xex: $(UDEPS)
+ $(C) $(COLD) $(MVAL2) $(RLOGIC) -l $@.list -o $@ $<
+
+ver.s:
+ echo " .define VERSION \"$(VERSION)\"" > ver.s
+
+clean:
+ rm -f *.o setmem.da65.s *.list $(UTOOLS) $(SETMEMS) README.1ST
+
+zip: $(ZIPFILE)
+
+atr: $(ATRFILE)
+
+$(ZIPFILE): atr
+ rm -f $(PROJECT)-$(VERSION).zip
+ $(ZIP) $(ZIPFILE) README.txt $(UTOOLS) $(SETMEMS) $(ATRFILE)
+
+$(ATRFILE): utools setmems README.1ST
+ rm -f $(ATRFILE)
+ cp mydos450.atr $(ATRFILE)
+ $(AXE) -w README.1ST $(ATRFILE)
+ for i in $(UTOOLS) $(SETMEMS); do $(AXE) -w $$i $(ATRFILE); done
+
+README.1ST: README.txt
+ perl -000 -ne 'print unless /https?:/' README.txt | fmt -w 40 | tr '\n' '\233' > README.1ST
+
+.PHONY: all setmems utools clean zip atr
diff --git a/README.txt b/README.txt
new file mode 100644
index 0000000..b13fcfc
--- /dev/null
+++ b/README.txt
@@ -0,0 +1,65 @@
+Tools for controlling tfhh's 512K SRAM memory upgrade (v4.5), or the
+576K 600XL upgrade (v2).
+
+Information on the upgrade can be found at:
+https://forums.atariage.com/topic/277204-some-new-not-really-hardware-made-by-tfhh/
+http://www.van-radecke.de/SRAM/512_KB_SRAM_memory_expansion.pdf
+http://www.van-radecke.de/STUFF/tfhh_HW_info.pdf
+
+The original setmem.xex tool can be downloaded from:
+http://www.van-radecke.de/SRAM/SETMEM.XEX
+
+The source for these tools, including a reverse-engineered source for
+SETMEM.XEX, can be found at https://slackware.uk/~urchlay/repos/tmu45tools
+
+Usage: under "regular" Atari DOSes (Atari DOS 2.x, MyDOS, etc), use:
+
+- UOFF.XEX to disable the memory upgrade.
+
+- U256.XEX to put the upgrade in 256K/Compy-shop/XE mode (separate
+ANTIC bank access).
+
+- U512.XEX to put the upgrade in 512K/RAMBO mode (*no* separate ANTIC
+bank access).
+
+These can be run standalone, or they can be prepended to some other
+executable. This is useful if e.g. you normally use RAMBO mode, but
+have a few demos/games that require separate ANTIC access. In this
+case, you'd make a copy of u256.xex, then append the game or demo to
+that copy to create an executable that changes the upgrade's mode,
+then loads/runs the game.
+
+Note that it's a *terrible* idea to change the upgrade's mode while
+a RAMdisk driver is loaded, especially if it's a 512KB RAMdisk
+and you're changing to 256K mode! Even worse would be disabling the
+upgrade... anyway there's no reason to change modes while a RAMdisk is
+active. Software that uses the extra RAM already wouldn't work with a
+RAMdisk, so you'd have to disable it anyway.
+
+For SpartaDOS X users:
+
+It's impossible to change the upgrade's mode under SDX without
+crashing the OS. Instead of the above, use UOFFX.XEX, U256X.XEX,
+U512X.XEX. These versions of the tools work the same as above, except
+they reboot (coldstart) the Atari after changing the mode. Also, they
+allow you to exit the tool without changing the mode or rebooting (to
+avoid accidents). It should also go without saying that the "prepend
+to a game" technique won't work with these.
+
+Reverse-Logic:
+
+The versions with "R" in the filename (U256R.XEX, U512R.XEX,
+U256RX.XEX, U512RX.XEX) are intended for users whose SRAM upgrade has
+"reverse logic", with the default mode being 256K/Compy-shop. The
+"RX" ones are coldstart versions. Unless you specifically ordered the
+upgrade like this, you don't need these (and you should probably just
+delete them to avoid confusion). The prompts are all that's different
+in the "R" versions, so you won't be missing anything useful.
+
+SETMEM:
+
+tf_hh's original SETMEM.XEX is included, too. Also included are
+reverse-logic and coldstarting patched versions (SETMEMR.XEX,
+SETMEMX.XEX, SETMEMRX.XEX). The original SETMEM.XEX crashes on exit
+under SpartaDOS X, so the coldstart version should be useful there.
+
diff --git a/inv.inc b/inv.inc
new file mode 100644
index 0000000..45f8d33
--- /dev/null
+++ b/inv.inc
@@ -0,0 +1,53 @@
+; 20221210 bkw:
+; Convert characters to inverse video (set bit 7). Actually, toggles
+; bit 7 (passing it inverse video characters turn them into normal ones).
+
+; Based on scrcode macro from cc65's atari.mac. Probably this should
+; ship with cc65...
+
+; Helper macro that converts and outputs one character
+.macro _inv char
+ .if char > $ff
+ .error "inverse: Character constant out of range"
+ .else
+ .byte char .bitxor $80
+ .endif
+.endmacro
+
+.macro inverse arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9
+
+ ; Bail out if next argument is empty
+ .if .blank (arg1)
+ .exitmacro
+ .endif
+
+ ; Check for a string
+ .if .match ({arg1}, "")
+
+ ; Walk over all string chars
+ .repeat .strlen (arg1), i
+ _inv {.strat (arg1, i)}
+ .endrepeat
+
+ ; Check for a number
+ .elseif .match (.left (1, {arg1}), 0)
+
+ ; Just output the number
+ _inv arg1
+
+ ; Check for a character
+ .elseif .match (.left (1, {arg1}), 'a')
+
+ ; Just output the character
+ _inv arg1
+
+ ; Anything else is an error
+ .else
+
+ .error "inv: invalid argument type"
+
+ .endif
+
+ ; Call the macro recursively with the remaining args
+ inverse arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9
+.endmacro
diff --git a/mydos450.atr b/mydos450.atr
new file mode 100644
index 0000000..020a638
--- /dev/null
+++ b/mydos450.atr
Binary files differ
diff --git a/setmem.info b/setmem.info
new file mode 100644
index 0000000..4e9edfe
--- /dev/null
+++ b/setmem.info
@@ -0,0 +1,62 @@
+global {
+ outputname "setmem.da65.s";
+ inputname "setmem.xex";
+ startaddr $3000;
+ pagelength 0;
+ comments 4;
+ inputoffs 6;
+ inputsize 865;
+};
+
+label { name "CONSOL"; addr $d01f; };
+label { name "NMIEN"; addr $d40e; };
+
+range { start $3000; end $30c4; type code; };
+range { start $30d3; end $3360; type texttable; };
+
+label { name "entrypoint"; addr $3000; };
+
+label { name "ICBLL"; addr $0348; };
+label { name "ICBLH"; addr $0349; };
+label { name "ICCOM"; addr $0342; };
+label { name "ICBAL"; addr $0344; };
+label { name "ICBAH"; addr $0345; };
+label { name "CIOV"; addr $E456; };
+
+label { name "msgptr"; addr $cc; size 2; };
+
+label { name "call_cio"; addr $30C2; };
+label { name "print_msg"; addr $3096; comment "print null-terinated ATASCII message pointed to by (msgptr)"; };
+label { name "nextchar"; addr $30AF; };
+label { name "zptr_hi_ok"; addr $30B8; };
+label { name "next_choice"; addr $300b; };
+label { name "magic_bits"; addr $30c6; comment "currently chosen option (default 1, range 0 to 2):"; };
+label { name "start_pressed"; addr $306b; comment "apply the current choice to the hardware"; };
+label { name "option_pressed"; addr $305b; comment "lda #<no_change_msg"; };
+label { name "_op"; addr $305f; comment "lda #>no_change_msg"; };
+label { name "select_pressed"; addr $3050; };
+label { name "read_consol"; addr $303f; };
+label { name "print_and_exit"; addr $3063; };
+label { name "choice_ok"; addr $301a; comment "lda #<startmsg"; };
+label { name "_ok"; addr $301e; comment "lda #>startmsg"; };
+label { name "wait_consol_release"; addr $307c; };
+label { name "magic_register"; addr $d3f3; };
+label { name "msg0_text"; addr $32bc; };
+label { name "msg1_text"; addr $32db; };
+label { name "msg2_text"; addr $32f9; };
+label { name "no_change_msg"; addr $3336; };
+label { name "mode_set_msg"; addr $330f; };
+label { name "_msmlo"; addr $308b; comment "lda #<mode_set_msg"; };
+label { name "_msmhi"; addr $308f; comment "lda #>mode_set_msg"; };
+
+range { name "choice"; start $30c5; end $30c6; type bytetable; comment "bits 0 and 1 will get ORed into magic_register:"; };
+label { name "startmsg"; addr $30d3; };
+range { name "msg0"; start $30c7; end $30c8; type addrtable; };
+range { name "magicbits_0"; start $30c9; end $30c9; type bytetable; };
+range { name "filler_0"; start $30ca; end $30ca; type bytetable; };
+range { name "msg1"; start $30cb; end $30cc; type addrtable; };
+range { name "magicbits_1"; start $30cd; end $30cd; type bytetable; };
+range { name "filler_1"; start $30ce; end $30ce; type bytetable; };
+range { name "msg1"; start $30cf; end $30d0; type addrtable; };
+range { name "magicbits_2"; start $30d1; end $30d1; type bytetable; };
+range { name "filler_2"; start $30d2; end $30d2; type bytetable; };
diff --git a/setmem.orig.xex b/setmem.orig.xex
new file mode 100644
index 0000000..e0ada27
--- /dev/null
+++ b/setmem.orig.xex
Binary files differ
diff --git a/setmem.s b/setmem.s
new file mode 100644
index 0000000..0b53c61
--- /dev/null
+++ b/setmem.s
@@ -0,0 +1,267 @@
+; 20221210 bkw: reverse-engineered "source" for setmem.xex.
+; originally created with da65 (cc65's disassembler), then
+; hand-edited to make it (hopefully) more human-readable.
+
+; By default, this builds the original setmem.xex, 877 bytes,
+; md5sum f7834eaf50e8b5d5314a20f6a5d83a0d.
+
+; I've added a couple of optional defines:
+; reverse_logic - For upgrades that have 256K/compy as the default.
+; coldstart - Reboot the Atari instead of exiting to DOS. For use
+; with SpartaDOS X, which crashes if we exit to DOS
+; after changing the mode.
+; See the Makefile for build options.
+
+ .include "atari.inc"
+ .include "xex.inc"
+ .include "inv.inc"
+
+; 2 byte ZP pointer used for printing text.
+msgptr = $cc
+
+; "Magic" hardware register. On an un-upgraded Atari, $d3f3 is just
+; a "mirror" of $d303 (aka PBCTL). It's special on the tfhh upgrade
+; though: changing it to $d303 here results in a non-functional setmem.xex.
+; Also note that writing to $d3f3 only affects the upgrade if the
+; Start key is pressed... and even when Start is pressed, writing
+; to $d3f3 still changes PBCTL.
+magic_register = $d3f3
+
+loadaddress = $3000
+
+ xex_org loadaddress
+
+entrypoint:
+ cld ; unnecessary.
+ lda #$08
+ sta CONSOL ; clicks the consol speaker (no idea why).
+ lda #$00
+ sta choice ; choice = 0 (but it immediately gets inc'd to 1).
+next_choice:
+ inc choice ; choice++;
+ lda choice
+ cmp #$03
+ bne choice_ok
+ lda #$00 ; if(choice == 3) choice = 0;
+ sta choice
+choice_ok:
+ lda #<banner_msg
+ sta msgptr
+ lda #>banner_msg
+ sta msgptr+1
+ jsr print_msg
+ lda choice
+ clc
+ asl a
+ asl a
+ tay ; Y = choice * 4;
+ lda msg0,y
+ sta msgptr
+ lda msg0+1,y
+ sta msgptr+1
+ lda magicbits_0,y
+ sta magic_bits
+ jsr print_msg
+read_consol:
+ lda CONSOL
+ and #$07
+ cmp #$03
+ beq option_pressed
+ cmp #$06
+ beq start_pressed
+ cmp #$05
+ bne read_consol
+select_pressed:
+ lda CONSOL
+ and #$07
+ cmp #$07
+ bne select_pressed
+ beq next_choice
+option_pressed:
+ lda #<no_change_msg
+ sta msgptr
+ lda #>no_change_msg
+ sta msgptr+1
+print_and_exit:
+ jsr print_msg
+ lda #$00
+ tax
+ tay
+ rts
+
+; apply the current choice to the hardware
+start_pressed:
+ sei ; disable IRQs
+ lda #$00
+ sta NMIEN ; disable NMIs
+ lda magic_register
+ and #$FC
+ ora magic_bits
+ sta magic_register
+wait_consol_release:
+ lda CONSOL
+ and #$07
+ cmp #$07
+ bne wait_consol_release
+ lda #$40
+ sta NMIEN ; re-enable NMIs
+ cli ; re-enable IRQs
+ .ifdef coldstart
+ jmp COLDSV
+ .else
+ lda #<mode_set_msg ; "Mode was set...."
+ sta msgptr
+ lda #>mode_set_msg
+ sta msgptr+1
+ jmp print_and_exit
+ .endif
+
+; print null-terminated ATASCII message pointed to by (msgptr).
+print_msg:
+ lda #$00
+ tax
+ tay
+ sta ICBLL,x
+ sta ICBLH,x
+ lda #PUTCHR
+ sta ICCOM,x
+ lda msgptr
+ sta ICBAL,x
+ lda msgptr+1
+ sta ICBAH,x
+nextchar:
+ lda (msgptr),y
+ beq call_cio
+ iny
+ bne zptr_hi_ok
+ inc msgptr+1
+zptr_hi_ok:
+ inc ICBLL,x
+ bne nextchar
+ inc ICBLH,x
+ bne nextchar
+call_cio:
+ jmp CIOV
+
+
+; R/W data (2 bytes):
+
+choice: .byte $00 ; Currently chosen option (default 1, range 0 to 2).
+
+; This gets set to one of disable_magic, compy_magic, or rambo_magic.
+; Bits 0 and 1 will get ORed into magic_register.
+magic_bits: .byte $00
+
+
+; R/O data (rest of file):
+
+ disable_magic = $01
+
+ .ifdef reverse_logic
+ compy_magic = $00
+ rambo_magic = $02
+ .else
+ compy_magic = $02
+ rambo_magic = $00
+ .endif
+
+; Table of 3 4-byte entries, one per choice. 4th byte is filler (always 0).
+msg0: .addr disable_msg
+magicbits_0: .byte disable_magic
+filler_0: .byte 0
+
+msg1: .addr compy_msg
+magicbits_1: .byte compy_magic
+filler_1: .byte 0
+
+msg2: .addr rambo_msg
+magicbits_2: .byte rambo_magic
+filler_2: .byte 0
+
+; Rest of the data is messages to be printed to IOCB#0 by print_msg.
+; These are null-terminated.
+banner_msg:
+ .byte CLS
+ .byte EOL
+ inverse " Setup tool for tfhh SRAM expansions "
+ .byte EOL,EOL
+
+ .ifdef reverse_logic
+ inverse "Reverse Logic"
+ .byte " - This"
+ .else
+ .byte "20210614"
+ .byte " - This tool"
+ .endif
+ .byte " works with:"
+
+ .byte EOL,EOL
+ .byte "- 512 KB SRAM memory expansion "
+ inverse "V4.5"
+ .byte EOL
+ .byte " (please check revision number!)"
+ .byte EOL,EOL
+ .byte "- 576 KB SRAM memory expansion "
+ inverse "V2"
+ .byte EOL
+ .byte " (only for the Atari 600XL, please"
+ .byte EOL
+ .byte " check the presence of "
+ .byte '"', "V2", '"', " printed", EOL
+ .byte " on the PCB)"
+ .byte EOL,EOL
+
+ .byte "Use console key "
+ inverse " SELECT "
+ .byte " to change"
+ .byte EOL
+ .byte "the desired mode, press "
+ inverse " OPTION "
+ .byte " to"
+ .byte EOL
+ .byte "quit this tool without any change"
+ .byte EOL
+ .byte "or press "
+ inverse " START "
+ .byte " to setup the SRAM"
+ .byte EOL
+ .byte "memory expansion as shown and"
+ .byte EOL
+ .ifdef coldstart
+ inverse "reboot"
+ .byte " the Atari."
+ .else
+ .byte "return to DOS."
+ .endif
+
+ .byte EOL,EOL
+ .byte "Expansion will be set to: "
+ .byte EOL,EOL
+ .byte "==> "
+ .byte 0
+
+disable_msg:
+ inverse " Memory Expansion switched off"
+ .byte 0
+
+compy_msg:
+ inverse " 256 KByte Compy-Shop/XE mode"
+ .byte 0
+
+rambo_msg:
+ inverse " 512 KByte RAMBO mode"
+ .byte 0
+
+mode_set_msg:
+ inverse " "
+ .byte EOL,EOL
+ .byte "Mode was set. Program terminated."
+ .byte EOL,EOL,0
+
+no_change_msg:
+ inverse " "
+ .byte EOL,EOL
+ .byte "Nothing changed. Programm terminated."
+ .byte EOL,EOL,0
+
+ xex_run entrypoint
diff --git a/tmu45tools-0.0.2.atr b/tmu45tools-0.0.2.atr
new file mode 100644
index 0000000..b9db869
--- /dev/null
+++ b/tmu45tools-0.0.2.atr
Binary files differ
diff --git a/tmu45tools-0.0.2.zip b/tmu45tools-0.0.2.zip
new file mode 100644
index 0000000..2f8ddd1
--- /dev/null
+++ b/tmu45tools-0.0.2.zip
Binary files differ
diff --git a/u.s b/u.s
new file mode 100644
index 0000000..f9e91c4
--- /dev/null
+++ b/u.s
@@ -0,0 +1,199 @@
+; Tool for controlling tf_hh's SRAM upgrade (512K v4.5, or 576K v2 for 600XL).
+
+; Gets built with various defines, see README.txt. Non-coldstart
+; builds can be prepended to another .xex file to set the upgrade's
+; mode automatically when that .xex is loaded.
+
+; Reverse-engineered by disassembling setmem.xex.
+
+; Note that the upgrade's mode can *only* be changed while the
+; Start key is held down, so this can't be 100% non-interactive.
+
+ .include "atari.inc"
+ .include "xex.inc"
+
+ .include "ver.s"
+
+ .ifndef magic_value
+ .error "You must define magic_value to 0, 1, or 2."
+ .endif
+
+ .define rambo_msg "for 512K/RAMBO mode"
+ .define compy_msg "for 256K/Compy mode"
+ .define disable_msg "to disable memory upgrade"
+
+ .if magic_value = 0
+ .ifdef reverse_logic
+ .define mode_msg compy_msg
+ .define xex_name "U256R"
+ .else
+ .define mode_msg rambo_msg
+ .define xex_name "U512"
+ .endif
+ .else
+ .if magic_value = 1
+ .define mode_msg disable_msg
+ .define xex_name "UOFF"
+ .else
+ .if magic_value = 2
+ .ifdef reverse_logic
+ .define mode_msg rambo_msg
+ .define xex_name "U512R"
+ .else
+ .define mode_msg compy_msg
+ .define xex_name "U256"
+ .endif
+ .else
+ .error .sprintf("Invalid magic_value (must be 0, 1, or 2, not %d)", magic_value)
+ .endif
+ .endif
+ .endif
+
+ .out .sprintf("Using magic_value %d, message '%s'", magic_value, mode_msg)
+
+ loadaddr = $8000
+
+ magic_register = $d3f3
+
+ xex_org loadaddr
+
+ ; runaddr is fake (just an RTS), put here so the tool can be run
+ ; standalone under "smart" DOSes like SDX that want to jump to the
+ ; load address.
+runaddr: rts
+
+magic_bits: .byte magic_value
+
+prompt_msg:
+ .byte xex_name
+ .ifdef coldstart
+ .byte "X"
+ .endif
+ .byte " v", VERSION, " by Urchlay", $9b, $9b, "Press Start ", mode_msg
+ .ifdef coldstart
+ .byte $9b, "The Atari will reboot!", $9b
+ .byte "Press any other key to abort.", $9b
+ .endif
+ .byte 0
+
+;;; subroutines
+
+printchr: ; print character in A register.
+ tay ; save A (character to print).
+ lda ICPTH ; set up stack, so it looks like a JSR to the
+ pha ; put-one-byte address for E:,
+ lda ICPTL ; which the OS has conveniently stashed
+ pha ; in IOCB #0.
+ tya ; restore A (put-one-byte argument).
+ rts ; "return" to put-one-byte, which will return to printchr's caller.
+
+printmsg: ; print message pointed to by A/X
+ sta FR0
+ stx FR0+1
+ lda #0
+ sta FR0+2
+pmloop:
+ ldy FR0+2
+ lda (FR0),y
+ beq pmdone
+ jsr printchr
+ inc FR0+2
+ bne pmloop
+pmdone:
+ rts
+
+; wait for CONSOL to equal A
+waitconsol:
+ cmp CONSOL
+ bne waitconsol
+ ; a bit of debouncing...
+ sta WSYNC
+ sta WSYNC
+ sta WSYNC
+ sta WSYNC
+ cmp CONSOL
+ bne waitconsol
+ rts
+
+;;; main program
+
+entrypoint:
+ ; print our prompt
+ lda #<prompt_msg
+ ldx #>prompt_msg
+ jsr printmsg
+
+.if 0
+ ; no idea why setmem.xex clicks the console speaker...
+ lda #8
+ sta CONSOL
+.endif
+
+ ; just in case: make sure Start's not being held down.
+ lda #7
+ jsr waitconsol
+
+ ; save previous contents of PBCTL and PORTB. diddling $d3f3
+ ; affects PBCTL whether Start is held down or not... and
+ ; changing PBCTL crashes SpartaDOS X.
+ ldx PBCTL
+ ldy PORTB
+
+ ; wait for the user to press Start. can't skip this, the magic
+ ; register can only be updated when Start is pressed.
+.ifdef coldstart
+ ; if the user presses any regular key, exit the program without
+ ; changing modes or rebooting.
+ lda #$ff
+ sta CH
+waitkey:
+ lda CH
+ cmp #$ff
+ beq wk_chkstart
+ lda #$ff
+ sta CH
+ rts
+wk_chkstart:
+ lda CONSOL
+ cmp #6
+ bne waitkey
+.else
+ lda #6
+ jsr waitconsol
+.endif
+
+ ; disable both IRQ and NMI interrupts.
+ sei
+ lda #0
+ sta NMIEN
+
+ ; update the magic, the same way setmem.xex does.
+ lda magic_register
+ and #$fc
+ ora magic_bits
+ sta magic_register
+
+ ; original code waits for the user to release the Start key before
+ ; re-enabling interrupts. I don't think this matters, but I'll do it.
+ lda #7
+ jsr waitconsol
+
+ ; restore previous PIA contents.
+ stx PBCTL
+ sty PORTB
+
+ ; re-enable interrupts and exit.
+ lda #$40
+ sta NMIEN
+ cli
+
+.ifdef coldstart
+ jmp COLDSV
+.else
+ rts
+.endif
+
+ xex_run runaddr
+
+ ; the real work gets done by an init routine.
+ xex_init entrypoint
diff --git a/ver.s b/ver.s
new file mode 100644
index 0000000..ed08527
--- /dev/null
+++ b/ver.s
@@ -0,0 +1 @@
+ .define VERSION "0.0.2"
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