XEX(5)

NAME
xex - Atari 8-bit executable file format.

DESCRIPTION

This manual describes the Atari 8-bit binary load format, commonly known as ".xex" or "binary load".

The file format consists of one or more segments, each having its own load address. This is an absolute address in the Atari's memory map, and there's no facility for relocating the code.

  File Structure

In pseudo-EBNF, the file structure looks like:

•   ffff_header = "$FF", "$FF"

•   initial_segment = ffff_header, segment

•   segment = start_address, end_address, data

•   file = initial_segment, [ (initial_segment | segment) ... ]

    In English:

    Each segment has a 4- or 6-byte header. The first segment in the file must use the 6-byte header. Further segments can use either the 4-byte or 6-byte header.

    The 6-byte header consists of:

•   2 bytes set to $FF.

•   The 2-byte load address of the segment, in standard LSB-first 6502 order.

•   The 2-byte end address of the segment, in standard LSB-first 6502 order. This address must be greater than or equal to the load address.

    The 4-byte header is the same as the 6-byte header, except it lacks the initial $FF, $FF bytes.

    The rest of each segment just consists of the data to be loaded, exactly (end_address - load_address) + 1 bytes.

  Initialization

It's possible to run code in the middle of loading the file. Such code is usually referred to as an an "init routine". A XEX file can have multiple init routines, or none at all.

Init routines are normal segments. An init address is also a normal segment: 2 bytes loaded at address $02E2, aka INITAD. As soon as this segment is loaded, the DOS will jump (actually JSR) to this address, which should exit back to DOS with an RTS instruction. After the routine exits, DOS will continue loading the file normally.

  Run Address

A .xex file can (and usually does) also have a run address. Unlike init addresses, there can be only one run address. If the file contains more than one run address, only the last one loaded has any effect. The program loader jumps to the run address after the file is done loading. It's possible for the program to exit via the 6502 RTS instruction, though many program (especially games) never exit.

The run address segment is the one that loads the 2-byte run address into address $02E0, aka RUNAD.

  Raw Data Blocks

When init code runs, the file is still being loaded. It's open on IOCB #1, and the init code can read some or all of the rest of the file itself, before returning to DOS. The part of the file read by an init segment doesn't have to conform to the regular XEX file structure, so they're referred to here as raw data blocks.

Raw data blocks usually occur in files created with "packer" or "compressor" programs, or occasionally in other large programs (Turbo BASIC is an example). Raw data blocks are generally found just after an init address segment. If you have an executable that loads just fine on a real Atari or emulator, but fails with xexcat and xexamine, a raw data block is usually the reason why.

Files with raw data blocks also can't be loaded by simple bootloaders such as Fenders 3-sector loader.

EXAMPLES

  Assembly

Here is a simple assembly language program that changes the background of the GRAPHICS 0 text screen to black, and the text to high-intensity white:

1000     *=  $0600
1010 START
1020     LDA #0
1030     STA 710
1040     LDA #$0F
1050     STA 709
1060     RTS
2000     *=  $02E0   ; AKA RUNAD
2010     .WORD START

To assemble this with either Atari's Assembler/Editor or OSS Mac/65, the command is:

ASM ,,#D:COLORS.XEX

This will create a binary file that looks like this:

offset  0: FF FF 00 06 0A 06 A9 00
offset  8: 8D C6 02 A9 0F 8D C5 02
offset 16: 60 E0 02 E1 02 00 06

This is a complete (though short) XEX file, and it can be loaded from the DOS menu (or D1: prompt, if you use a command-line-based DOS).

The first 2 bytes ($FF, $FF) are the signature for the initial segment header.

The next 2 bytes ($00, $06) are the load address of the first segment ($0600, in 6502-style LSB-first notation).

The next 2 bytes ($0A, $06) are the end address ($060A).

Since the header says to load data from $0600 to $060A, there are 11 data bytes in the segment, beginning with $A9, $00 (the 6502 object code for the LDA #0 instruction), and extending to the $60 (RTS opcode) at offset 16.

The data from the first segment is immediately followed by the header of the next segment, at offset 17. A $FF, $FF signature would be allowed here, but in the example, the 2nd segment uses the 4-byte header.

At offset 17, the $E0, $02 (aka $02E0) is the load address. $E1, $02 ($02E1) is the end address. $02E0, $02E1 is known as RUNAD in the Atari world, and it's the address where DOS will find the entry point to the program when it's done being loaded.

The next (and last) 2 bytes are $00, $06 (aka $0600), which is the run address itself (to be deposited at RUNAD).

There are no more segments, since we've reached end of file.

  Data Only

Since a XEX file can load arbitrary data at arbitrary addresses, there's simpler way to accomplish the color changes. Instead of writing code to do the job, we just create a XEX file that loads the colors we want directly into the color shadow registers.

In BASIC, you'd say:

POKE 709,15
POKE 710,0

...but BASIC doesn't have an easy way to create a XEX file. An assembler is a more convenient tool. The code is:

1000  *= $02C5
1010  .BYTE $0F,$00

The binary looks like this:

ff ff C5 02 C6 02 0F 00

The file begins with $FF, $FF header, then the 2-byte load address ($C5, $02 for address $02C5), then the 2-byte end address ($C6, $02, aka $02C6), then the 2 bytes of data to be stored there ($0F, $00).

When loaded, this will store $0F at address $02C5 (aka COLOR0, the text luminance in GRAPHICS 0) and $00 at $02C6 (COLOR1, the GRAPHICS 0 background color).

Notice that there's no run or init address. That's because no code is executed; it's just 2 bytes of raw data.

HISTORY

The first Atari 8-bit binary load format was defined by Atari DOS 1.0, in 1979. This was a multi-segmented format, but not compatible with the DOS 2.0S binary load format (aka the XEX format). Specifically, files began with a $84, $09 header (rather than the $FF, $FF used by DOS 2.0S), and there was no such thing as an init routine (DOS 1 didn't use or define INITAD). DOS 1.0 also used AUTO.SYS rather than AUTORUN.SYS as the file to load at startup. Very few (or probably no) files in this format still exist today.

The format used by all other Atari and third-party DOSes was first defined by Atari DOS 2.0S. There was no standard filename extension. Files were usually named .OBJ, .BIN, or .COM... except the special filename AUTORUN.SYS, which was automatically loaded and run by the DOS at startup.

Some later third-party DOSes do use the filename extension .COM for their own external commands. Typing FOO at the SpartaDOS or DOS XL command prompt will load and run a file called FOO.COM, if it exists. The external command files that ship with SpartaDOS also don't have run or init addresses (so they won't run, if loaded by another DOS). SpartaDOS apparently uses the load address (or maybe a fixed address) as the entry point to .COM files.

The name "xex" and the filename extension ".xex" came into use on the early Internet in the 1990s, to distinguish Atari executables from e.g. MS-DOS executables. XEX stands for "XE eXecutable", although this is a double misnomer: there's nothing XE-specific about the file format (it applies to the 400/800 and XL machines, too), and technically a binary load file isn't necessarily an executable; it could just be a block of data without run or init addresses.

COPYRIGHT

WTFPL. See http://www.wtfpl.net/txt/copying/ for details.

AUTHOR

B.  Watson <urchlay@slackware.uk>; Urchlay on irc.libera.chat ##atari.

SEE ALSO

a8cat(1), a8eol(1), a8xd(1), atr2xfd(1), atrsize(1), axe(1), bas2aplus(1), blob2c(1), blob2xex(1), cart2xex(1), cxrefbas(1), dasm2atasm(1), diffbas(1), dumpbas(1), f2toxex(1), fenders(1), listbas(1), listamsb(1), protbas(1), renumbas(1), rom2cart(1), unmac65(1), unprotbas(1), vxrefbas(1), whichbas(1), xex1to2(1), xexamine(1), xexcat(1), xexsplit(1), xfd2atr(1), xex(5), atascii(7), fauxtari(7).

Any good Atari 8-bit book: De Re Atari, The Atari BASIC Reference Manual, the OS Users' Guide, Mapping the Atari, etc.