This is a Linux host build chain for Dave Dunfield's CUBIX 6809 operating
system and its application suite, replacing the original DOS-hosted
DDS XASM09 workflow (macro + asm09, driven by hand or by GOASM.BAT)
with a single make.
It covers exactly two things:
- Building what's here — the demo OS and the full application suite, for the standard CUBIX memory map.
- Porting CUBIX to different hardware — which, per Dunfield's own
porting guide (
DOCS/PORT.TXT), means editing source and rebuilding, not patching a binary. See Porting to new hardware.
If you just want to build, skip to Quick start. If you're
adapting this to a board with a different memory map or I/O hardware, read
Porting to new hardware — that's the part that
actually requires decisions, not just make.
Cubix/
Makefile top-level build: tools / apps / os / all / clean
MACROS SSR macro + OSRAM/OSEND/OSUTIL, included by every UTIL/* app
GOASM.BAT original DOS build-one-app batch file (kept for reference)
UTIL/ application/utility source (COPY, ED, EDT, FORTH, ...)
OS/ operating system source (CUBIX, FILESYS.OS, COMMAND.OS,
COMFILE.OS, SAMPLE.SYS, SIMULATE.SYS)
DOCS/ Dunfield's original documentation (CUBIX.TXT, PORT.TXT, ASM.TXT, ...)
BIN/ pre-built reference .HEX files shipped with the archive
— a legitimate diff target for validating `tools/`
changes; see ERRATA.md before assuming a mismatch
means "different source revision" (it usually doesn't)
tools/ host build tools, ported to Linux from Dunfield's original sources
asm09.c 6809 cross-assembler
macro.c macro pre-processor (SSR macro, conditional assembly)
hexfmt.c ROM checksum / hex-format utility
portab.h shared Linux portability shims
xasm.h shared header for asm09.c/macro.c
build/ build output (git-ignorable), created by `make`
apps/*.ASM *.HEX
os/CUBIX.ASM CUBIX.HEX
make all # tools, all 26 apps, and a checksummed OS ROMOr individually:
make tools # build tools/asm09, tools/macro, tools/hexfmt
make apps # -> build/apps/*.HEX (one per UTIL/* source)
make os # -> build/os/CUBIX.HEX (checksummed, bootable image)
make clean # remove build/ and the built toolsVariables (override on the command line):
make os ASMODE=dist # distribution build (no bundled driver source)
make os OSVER=2.0 # embedded "CUBIX version X.X" stringASMODE selects one of the ifeq asmode,... blocks at the top of
OS/CUBIX (demo — the default, builds against SAMPLE.SYS — or dist,
which leaves HWINIT undefined for you to link in separately). test also
exists in the source but isn't a general-purpose target.
Three tools, two build products:
UTIL/<app> ──┐
├─► macro (expands SSR, resolves OSRAM/OSEND/OSUTIL) ─► <app>.ASM ─► asm09 ─► <app>.HEX
MACROS ──┘
OS/CUBIX ─────┐
FILESYS.OS │
COMMAND.OS ├─► macro (asmode=demo|dist, osver=X.X) ─► CUBIX.ASM ─► asm09 ─► CUBIX.HEX ─► hexfmt (checksum) ─► CUBIX.HEX
COMFILE.OS │
SAMPLE.SYS ──┘
macrois a text preprocessor: it expands theSSR nmacro toSWI/FCB n, evaluatesifeq/ifne/setconditionals, and resolvesincludedirectives. It does not understand 6809 mnemonics at all — its output is plain assembler source.asm09is the actual two-pass 6809 cross-assembler. It turns that source into a Motorola S-record.HEXfile.hexfmtoperates purely on the finished.HEXfile: it sums a byte range and pokes the 16-bit result back in as a checksum. This step only applies to the OS ROM, not the apps.
Two things about macro matter enough to call out explicitly, because they
affect how the Makefile is written and how you should think about paths if
you extend it:
includeis resolved relative to the current working directory, not relative to the file doing the including. This is whymake oscds intobuild/osbefore runningmacro—OS/CUBIX'sinclude filesys.osline has to findfilesys.ossitting right next to it.- Nothing about
macroorasm09cares about file extensions on input —UTIL/COPY, with no extension, is normal.asm09defaults to reading<name>.ASMand writing<name>.HEX/<name>.LSTonly when you don't give it an extension yourself.
Read DOCS/PORT.TXT in full before starting — this section is a map of it,
not a replacement for it. Dunfield draws a hard line between two kinds of
port, and only one of them is something a build chain can help with.
| Minor port | Major port | |
|---|---|---|
| What changes | A binary ROM image, patched in place | Source, reassembled from scratch |
| When it applies | Target already uses the standard memory map ($2000-$DFFF RAM, $E000-$FFFF ROM) |
Target uses a different memory map, or your tools can't produce an absolute-address ROM image |
| Mechanism | Hex-patch the HWINIT jump at ROM offset $0008 and the SWI vector HWINIT fills in, both pointing at your driver code appended after the OS in the same ROM |
Add driver source directly into OS/CUBIX, change the ROM/RAM/USRRAM/USREND EQUs, reassemble everything |
| Tooling | A hex editor / EPROM programmer | macro + asm09 (+ hexfmt) |
This build chain only does major ports. That's not a missing feature —
a minor port is inherently a binary-patching workflow on an already-built
ROM image, not a compile step, so it doesn't fit into a make target the
way source assembly does. If your target hardware already matches the
standard memory map, you may not need to touch this Makefile at all;
follow §9 of PORT.TXT and patch the shipped ROM directly.
If you're changing the memory map, adding non-standard I/O, or your
assembler can't place code at absolute ROM addresses (not a concern here —
asm09 can) — that's a major port, and the rest of this section is for
you.
1. Write your I/O drivers.
Per PORT.TXT §2–4, your driver source must supply a HWINIT routine that:
- fills in the table pointed to by register
Yon entry (DCBs, console device numbers, serial vectors, disk routine vectors, interrupt vectors, default drive/directory — the full layout is inPORT.TXT§2.1), initializes your hardware, and preps the console; - provides serial input/output drivers (
PORT.TXT§3) and the four disk primitives — home head, read sector, write sector, format (PORT.TXT§4) — if your target has disks.
OS/SAMPLE.SYS (6551 UART + µPD765-style disk) and OS/SIMULATE.SYS
(D6809 simulator I/O) are two working examples of this shape — read
whichever is closer to your hardware before writing from scratch.
2. Add a new asmode block to OS/CUBIX.
Near the top of OS/CUBIX you'll find:
ifeq asmode,dist
ROM EQU $E000
RAM EQU ROM-1024
USRRAM EQU $2000
USREND EQU ROM-1
endif
ifeq asmode,demo
ROM EQU $E000
RAM EQU ROM-1024
USRRAM EQU $2000
USREND EQU ROM-1
dr_file set sample.sys
endifAdd your own block, e.g. ifeq asmode,myboard, with:
ROM— your ROM base (8K, and it must still end at$FFFF— the 6809 reset/interrupt vectors are hardwired to live at$FFF2-$FFFF, soROMis really "$FFFF minus 8191").RAM— a 1K scratch block for OS internals, normally the top 1K of your general RAM, belowROM.USRRAM— the lowest address available for applications.USREND— highest address the power-on memory test checks (usuallyRAM+1023unless your OS and application RAM aren't contiguous).dr_file set yourdriver.sys— pointing at the driver file you wrote in step 1.
Then put your driver's source file in OS/ alongside FILESYS.OS etc.
3. Update MACROS if USRRAM/USREND changed.
The root MACROS file has its own copies of the RAM boundaries, used only
by applications:
OSRAM EQU $2000 USER APPLICATION RAM STARTS HERE
OSEND EQU $DBFF LAST LOCATION OF USER (NON-SYSTEM) RAM
OSUTIL EQU $D000 RAM FOR UTILITY PROGRAM USAGEThese are EQU, not SET — they can't be overridden from the macro
command line the way asmode=/osver= can (that's how macro itself is
written, not a limitation of the Makefile). If your USRRAM/USREND
differ from the standard $2000/$DBFF, edit this file directly to match.
OSUTIL should stay OSEND - $0BFF (top 3K reserved for utility
overlays), unless you have a specific reason to change that ratio.
4. Update the checksum range in the Makefile if your ROM size changed.
The os target's checksum step is currently hardcoded for the standard 8K
ROM:
$hexfmt CUBIX.HEX 'c=$0002,$1FFF,$0000'This says: sum bytes $0002–$1FFF (i.e., offsets 2 through 8191 — the
whole ROM after the checksum field itself), store the 16-bit result at
offset $0000. If you ever legitimately need a ROM size other than the
architecturally-mandated 8K, change $1FFF to match (size - 1). You
should not need to touch this for a same-size port to different hardware —
only the contents of the 8K ROM change, not its size.
5. Rebuild.
make os ASMODE=myboard
make apps # apps don't take ASMODE; they only need MACROS to be correctApps only care about OSRAM/OSEND/OSUTIL from MACROS, so they need
rebuilding whenever those change, regardless of ASMODE. They're
independent of ROM/RAM (which are OS-only), and independent of which
I/O drivers you wrote.
6. Verify.
make os prints the checksum it computed:
Checksum from 0002 to 1fff at 0000 is 6c07
There's no automated test beyond that — verifying a new port actually
works means running it on real (or emulated) hardware. hexfmt only
guarantees the ROM image is internally consistent, not that HWINIT
correctly drives your board.
Bugs, near-misses, and false starts found while building and validating
this port — several with a wrong turn taken and corrected along the way.
Read ERRATA.md in full before you touch tools/; skimming this project
without it is how the same mistakes get repeated. Highlights: a silent
16-bit-wraparound bug that briefly caused three branch instructions to be
mispatched (reverted, root-caused, fixed at the source of the bug
instead); a related class of digit-accumulation/quote-literal overflow
bugs, DOS-confirmed and fixed; and a case-sensitivity trap in OS/CUBIX's
include/dr_file lines.
- Minor (binary) ports. As above — that's a hex-editing workflow on a finished ROM, not a build step.
tools/hexfmt's other output formats. It supports Intel hex and raw binary output (-I,-B) and other options (-Ttruncate,L=/R=/F=tuning); the Makefile only uses the checksum feature, matchingOS/README.TXT's documented invocation. Runtools/hexfmtwith no arguments for the full option list if you need one of those.
David Dunfield released his code for any purpose as a retirement project.
You can read about that here:
https://dunfield.themindfactory.com "Daves Old Computers"
Please read COPY.TXT or LICENSE in the root of this repository for details on this. As such its free for any use but COPY.TXT states, myself or David are not responsible for any use of this code (though I have tested it, and found it to work for its intended purpose.)
For the most part, Have fun! this is a CPU released in 1979! here is a full OS and development environment for you to play with