a8 – cannot create a XEX file that launches from somewhere else than the start
java -jar /home/zbyti/Programs/Millfork/millfork.jar -Xr -t a8 mptplayer.mfk
XEX header:

XEX end

main routine address is $26b8, it isn't proper XEX file.
At the moment, the Atari executable is defined as $FF,$FF,$E0,$02,$E1,$02,startaddr,startaddr,endaddr,allocated so the launch address is always the first byte of the output. I agree this is not ideal, as if you want to put something else near the beginning, it doesn't work.
There are several other platforms affected by the same issue:
-
CoCo, TRS-80, Z1013 and ZX Spectrum, like Atari, have both a load address and a launch address, and Millfork sets them to the same value
-
Commodore has a Basic stub that jumps to a fixed address; if main() is shifted elsewhere due to putting something else at that location, the code won't work
-
several platforms always launch the loaded file from the beginning; with those, the issue is not solvable in these cases
I think I should add a way to mark the launch address separately.
As far as I know proper XEX may looks like:
header $ff,$ff,startaddr,endaddr
end of binary runaddr
Ok. It's fine answer to my question :+1:
I'm reopening it, as I want to solve the underlying deficiency, at least for those platforms where it is possible, like Atari.
OK :] anyway this code works for me:
const word ADDRMUS = $a000
const word ADDRPLA = $b000
byte stop @ ADDRPLA + $62d
asm void comm(byte register(a) a, byte register(x) x, byte register(y) y) @ ADDRPLA extern
asm void takt() @ ADDRPLA+3 extern
void main(){
comm(0,ADDRMUS.hi,0)
comm(4,0,0)
while os_CH == $ff {
if antic_vcount == $10 {
antic_wsync = $e
gtia_colbk = $e
takt()
gtia_colbk = 0
}
}
stop = 0
}
const array player @ ADDRPLA = file("data/mpt_player.obj", 6)
const array music @ ADDRMUS = file("data/bitter_reality_4.mpt", 6)
FYI
OBJ files $ff,$ff,startaddr,endaddr
OBX files $ff,$ff,startaddr,endaddr ended with runaddr
I've read somewhere that Atari will launch the program if the start address is written to $02E0/$02E1, and this is what I'm doing.
Most of the XEX I've seen has a short header and ended with run address.
http://atariki.krap.pl/index.php/Binarny_plik_DOSu
http://atariki.krap.pl/index.php/COM
http://atariki.krap.pl/index.php/ATR
I checked some XEX files I have and they all end with a chunk with the launch address: E0 02 E1 02 YY XX. Since it doesn't matter what order the chunks are in the file, I put that chunk first. I guess this is against the tradition, but it still works.
Millfork currently creates two-chunk XEX files: one chunk for the launch address, one for the actual program. In other words:
-
The most common layout (
SHSL: data start,EHEL: data end,RHRL: launch address):FF FF header SL SH EL EH DD DD DD chunk from:$SHSL to:$EHEL data:DDDDDD (sometimes more chunks) E0 02 E1 02 RL RH chunk from:$02E0 to:$02E1 data:$RHRL -
Millfork (with
RHRL=SHSL):FF FF header E0 02 E1 02 RL RH chunk from:$02E0 to:$02E1 data:$RHRL SL SH EL EH DD DD DD chunk from:$SHSL to:$EHEL data:DDDDDD
My experience come from Atar800 emulator monitor:
WRITE [XEX] startaddr endaddr [runaddr] [file]
- Write memory block to a file (memdump.dat).
With XEX, writes an Atari executable with
optional run address (no init addr, sorry).
[file] may begin with |, to pipe to a command
and XEX produced by Action! compiler https://github.com/zbyti/a8-action-playground and XEX produced by Mad Pascal compiler https://github.com/zbyti/a8-mad-pascal-playground
I do not know theory well ;)
I asked a friend who is an experienced and longtime Atari800 programmer (including Sparta DOS) and he said that a short header
$ff,$ff,startaddr,endaddr and binary ended with runaddr is sufficient for OBX aka XEX alias COM ;)
some INIT vs. START discussion https://atariage.com/forums/topic/235338-creating-a-binary-file-with-an-init-address-from-mac65/
I don't agree that Sparta is wrong; it does handle the INIT address properly. The INIT address is to allow something to execute before the main program runs, either via $02E0 or jumping to the load address. It's a design mistake in Action! to have used $02E2 as the run address, since there is no initialization required for the Action! runtime code.
@KarolS well now I understand what you want to achieve with long header :+1:
https://github.com/tebe6502/Mad-Assembler/issues/1#issuecomment-709283588
https://atariage.com/forums/topic/313212-funkheld-kickc-questions/?do=findComment&comment=4675562
Currently, Millfork always outputs contiguous memory ranges, so I guess the powers of the Atari exe format are underutilised. I'll think about outputting multiple non-contiguous chunk, as it might be useful, at least on platforms that support it.
https://gitlab.com/jespergravgaard/kickass-plugin-atari-xex
I have also integrated the plugin into KickC.
So in the next release KickC will be able to create XEX-files where each memory block is stored as a seperate segment in the XEX-file.
This will help you to get smaller XEX-files if you for instance have some code in $1000 and some data in $3000 with an empty gap in between.