Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

a8 – cannot create a XEX file that launches from somewhere else than the start #78

Open
zbyti opened this issue Oct 5, 2020 · 16 comments

Comments

@zbyti
Copy link
Contributor

zbyti commented Oct 5, 2020

java -jar /home/zbyti/Programs/Millfork/millfork.jar -Xr -t a8 mptplayer.mfk

XEX header:
Screenshot_2020-10-05_12-13-17

XEX end
Screenshot_2020-10-05_12-13-52

main routine address is $26b8, it isn't proper XEX file.

a8_mptmusic.zip

@zbyti zbyti changed the title a8 XEX - what am i doing wrong? a8 and XEX - what am I doing wrong? Oct 5, 2020
@zbyti zbyti changed the title a8 and XEX - what am I doing wrong? a8 and XEX header - what am I doing wrong? Oct 5, 2020
@KarolS
Copy link
Owner

KarolS commented Oct 5, 2020

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.

@zbyti
Copy link
Contributor Author

zbyti commented Oct 5, 2020

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 👍

@zbyti zbyti closed this as completed Oct 5, 2020
@KarolS KarolS changed the title a8 and XEX header - what am I doing wrong? a8 – cannot create a XEX file that launches from somewhere else than the start Oct 5, 2020
@KarolS
Copy link
Owner

KarolS commented Oct 5, 2020

I'm reopening it, as I want to solve the underlying deficiency, at least for those platforms where it is possible, like Atari.

@KarolS KarolS reopened this Oct 5, 2020
@zbyti
Copy link
Contributor Author

zbyti commented Oct 5, 2020

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)

@zbyti
Copy link
Contributor Author

zbyti commented Oct 5, 2020

FYI

OBJ files $ff,$ff,startaddr,endaddr
OBX files $ff,$ff,startaddr,endaddr ended with runaddr

@KarolS
Copy link
Owner

KarolS commented Oct 5, 2020

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.

@zbyti
Copy link
Contributor Author

zbyti commented Oct 5, 2020

Most of the XEX I've seen has a short header and ended with run address.

@zbyti
Copy link
Contributor Author

zbyti commented Oct 5, 2020

@KarolS
Copy link
Owner

KarolS commented Oct 5, 2020

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
    

@zbyti
Copy link
Contributor Author

zbyti commented Oct 5, 2020

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 ;)

@zbyti
Copy link
Contributor Author

zbyti commented Oct 6, 2020

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 ;)

@zbyti
Copy link
Contributor Author

zbyti commented Oct 8, 2020

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.

@zbyti
Copy link
Contributor Author

zbyti commented Oct 29, 2020

@KarolS well now I understand what you want to achieve with long header 👍

tebe6502/Mad-Assembler#1 (comment)

@zbyti
Copy link
Contributor Author

zbyti commented Nov 12, 2020

@KarolS
Copy link
Owner

KarolS commented Nov 14, 2020

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.

@zbyti
Copy link
Contributor Author

zbyti commented Nov 15, 2020

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.

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

No branches or pull requests

2 participants