Skip to content

SpartaDOS X #17

Open
Open

Description

@epi

I might submit a PR with support for SDX binaries, but I'd like to know your opinion about the scope first:

  1. Won't accept anyway, other assemblers can do it.
  2. Fast Assembler / MADS style blk and smb directives. Relatively easy with small diff surface, limited to SDX.
  3. Emit llvm-mos-like ELF or obj65 first, add a linker with SDX target. May end up nice, or never finished rabbit hole.
  4. other?

Everything below this line will be updated as the spec is refined.

Summary

Add support for the SpartaDOS X binary format: relocatable code blocks, allocation blocks, symbol imports and exports, with type-checked relocation.

The work starts by moving object-file generation (block headers, gap filling, the trailer written at the end) out of the assembler core into one class per output format. SpartaDOS X is the first new class. ELF (llvm-mos conventions) and o65 are reserved names in this issue: the syntax, the value typing and the class interface are designed so that they can be added later as new classes only, without touching the directives or the evaluator.

Reference: SpartaDOS X Programming Guide V. 4.50, chapter 2 (file format), 3.4 (program extended area), 3.6 (memory indices), 19.1.3.1 (control byte).

        opt 'output=spartadosx'
printf  xrf 'PRINTF'            ; import a system symbol
gets    xrf 'GETS'
bufsz   equ 32

        rel 'text'              ; relocatable block named TEXT, in main memory
hello   xdf '@HELLO'            ; export this location; @ makes it a shell command
        jsr printf
        dta c'Type your name: ',0
        lda whov
        ldx whov+1
        ldy #bufsz
        jsr gets
        bmi quit
        jsr printf
        dta $9b,c'Hello, %s!',$9b,0
quit    rts
whov    dta a(who)              ; relocated automatically

        bss 'bss'               ; allocation-only block named BSS
who     org *+bufsz

Output settings

Depends on named opt settings (#23), the exact semantics may change.

        opt 'output=ataridos'   ; Atari DOS executable, $FFFF signature (default; opt h+)
        opt 'output=raw'        ; plain bytes, no headers (opt f-h-)
        opt 'output=rom'        ; plain bytes, gaps filled with $FF (opt f+h-)
        opt 'output=spartadosx' ; SpartaDOS X executable, $FFFA absolute blocks, sections allowed, no short `opt` syntax

Format capabilities

raw rom ataridos spartadosx elf (reserved) o65 (reserved)
absolute block signature none none $FFFF $FFFA n/a n/a
gap filling legacy f+ $FF legacy f+ never never never
rel/bss names error error error any identifier; memory attribute main, extended, program ELF section name text, data, bss, zero
xrf/xdf names error error error ≤8 chars, uppercased, space-padded any, case kept any, case kept
run/ini, org a:/f: error error yes yes; run fixed up, ini absolute only error error
mid-file o± yes (warning rule) yes (warning rule) yes (warning rule) error error error
legacy equivalent opt f-h- opt f+h- opt h+ none none none

Under spartadosx, a run word gets a fixup when it points into a section. An ini address must be absolute; an address in a section or an imported symbol is an error (see SDX output).

Directives

Four directives, one string operand each: rel/bss open sections, xrf imports a symbol (XREF, $FFFB) and xdf exports one (XDEF, $FFFC). The operand is parsed with the opt rules: comma-separated items, case-insensitive keys, no spaces. The first item is positional; the rest are key or key=value. The operand is always required. As with every xasm directive, the number of operands is fixed, so there's no bare rel or bss.

Directive Meaning
rel 'name[,attr,…]' Start a section that carries data, or reopen the section with that name.
bss 'name[,attr,…]' Same, but allocation-only. No data may be emitted; reserve space with org *+n.
label xrf 'NAME[,attr,…]' Import. label becomes a symbol-tagged value 0.
[label] xdf 'NAME[,attr,…]' Export the current location under NAME. The label is optional, as on any line.

All four are errors under raw, rom and ataridos. A label on a rel/bss line gets the section's current offset: 0 for a new section, the length so far for a reopened one.

Section names. The first item is the section's name. It's the key for reopening the section, in every format. The format parses it:

Format Name Recommended
spartadosx an identifier, read with readIdentifier: case-insensitive (Text and TEXT are the same section) text for rel, bss for bss, as in elf and o65
elf an ELF section name; . is allowed, e.g. .text, .rodata, .zp.bss .text, .bss
o65 one of text, data, bss, zero text, bss

Section names are a namespace of their own. They can't clash with labels or with xrf/xdf names.

Under spartadosx, each name is one $FFFE block:

  • Numbering: blocks are numbered from 1 in the order their names first appear, with at most 7 blocks per file, rel and bss together (see "Loader behaviour"). The listing shows the block number on the line that opens the block, so a program that reads the EXTENDED+3 table (guide 3.7) can rely on it.
  • Memory: the attribute main ($00, the default), extended ($02) or program ($04, SDX 4.47+). For example, rel 'drv,extended,align=256' gives control byte $42.
  • Reopening: it may repeat the attributes or leave them out (rel 'text'). If it gives them, they must match the first opening. Using one name for both a rel and a bss section is an error. A block that an ini flush has already written out can't be reopened; the error suggests using a new name.
  • Offsets: a reopened block continues at its current length. * and labels count from the start of the block, whatever part of the source they are in.

This lets code and data from several included sources go into one text block and one bss block, without the included files knowing anything about block numbers.

Attributes:

Attribute On spartadosx elf o65
main, extended, program rel, bss memory index $00, $02, $04; at most one; default main error error
align=N rel, bss only 256; sets $40 in the control byte (SDX 4.43+) section alignment header alignment mode
zp rel, bss error zero-page section; implied by a .zp name prefix implied by zero; an error elsewhere
weak xrf weak import (SDX 4.50+): bit 7 of the 8th name byte weak undefined error
zp xrf error 8-bit relocations zero-segment reference
weak xdf error weak definition error

Any other name, attribute or value is an error. The guide (3.6) says SDX memory indices other than $00, $02 and $04 (plus $40) are reserved with undefined behaviour.

Symbol names under spartadosx: 1 to 8 characters. @ is allowed only as the first character. The other characters are the ones allowed in xasm labels. Names are uppercased and padded with spaces.

  • An xdf name exported twice is an error.
  • Several xrf labels may import the same name; they share one $FFFB record.
  • An xrf that is never referenced writes no record and triggers the unused-label warning (opt u).

Activity

  1. pfusik commented on Sep 5, 2026

    @pfusik
    Owner

    This is all black magic to me and Atariki is down. Educate me. :)

  2. epi commented on Sep 5, 2026

    @epi
    ContributorAuthor

    Binary format description: https://trub.atari8.info/sdx_files/4.41/sdx-programming.pdf

    Key features:

    • relocatable text and bss blocks,
    • imported and exported symbol values (always 16-bit, keyed by 8-char space-padded identifiers),
    • fixup blocks: lists of locations in text blocks that need to be patched by adding a 16-bit load address or symbol value to the 16-bit value in text (no byte fixups).

    MMMG's Fast Assembler was a 90s'-era assembler with a syntax being a superset of QA's, adding:

    • blk directive that emits the various types of blocks.
    • sym that declares imported symbols.
    • dta v() for emitting relocatable addresses as data

    Documentation: https://github.com/HolgerJanz/FastAssembler/blob/main/FastAssembler.pdf

    Some examples:

    https://github.com/HolgerJanz/FastAssembler/blob/main/1.8/EXAMPLES/HI_SDX.ASM
    https://github.com/HolgerJanz/FastAssembler/blob/main/1.8/EXAMPLES/TSR.ASM

    I don't love that syntax, but:

    so I'd vote for using the same syntax anyway.

  3. pfusik commented on Sep 8, 2026

    @pfusik
    Owner

    Please do it! I don't like blk taking two to four arguments depending on the unquoted first argument, but let's be compatible.

  4. epi commented on Sep 15, 2026

    @epi
    ContributorAuthor

    On hold, because:

    • discussion on tgt may reveal a better way to spell this
    • newest SDX programming manual has spec additions not implemented by FA nor MADS (drac030's Elsa has them but under very different syntax)
  5. epi commented on Sep 22, 2026

    @epi
    ContributorAuthor

    There are a few more things in FA and MADS (syntax and beyond) that make me want to deliberately avoid compatibility with their syntax.

    1. The variable-length lists of unquoted arguments are foreign to xasm syntax.

    2. Support for program extended area ($04) (introduced in SDX 4.47) and page alignment (| $40) (SDX 4.43) isn't available in FA 1.8, and MADS offers it only via undocumented ELSA-style constant (blk reloc $44)

    3. FA doesn't allow allocating data in bss (blk empty) segments, instead encouraging the weird idiom that assumes the bss would be allocated right after the code segment (which nothing in SDX documentation guarantees, and which is specifically false for page-aligned bss):

    * Mad-Assembler-2.1.8/examples/SpartaDosX/cs.fas:344
    cname  equ *
    vbuff  equ cname+$90
    blkend equ vbuff+$24
           blk e blkend-cname m
    
    1. Weak symbols (ones which the loader allows to be undefined on import instead of aborting, SDX 4.50's addition) aren't supported in FA 1.8, and MADS uses a syntax that's again a bit foreign to xasm ( smb 'FOO'^)

    2. All the blk syntax quirks are modeled after SDX 4.22's file format, and would poorly extend to other relocatables, such as ELF or o65.

    There are more but I'm tired and I don't feel like explaining all of them.

    So I'd reject blk and smb '...'^ entirely, add a different set of directives, and require explicitly setting a relocatable format to enable them.

    I'll follow with a proposal in another comment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions