Jump to content
Sign in to follow this  
fujidude

Binary object files on the Atari 8-bit

Recommended Posts

I've been digging about on binary object files and how they are put together. There are the standard kind, and then some SDX specific ones. To start with, I want to ask a question about the standard ones. I understand they start with:

 

FFFF then another word designating the start address to load into, then one more word with the end address. That's 6 bytes in that header. What I was wondering is if there are additional segments, do they all start with the same kind of 6 byte header, or do they just have the start and end address words and skip the FFFF. In other words, is the FFFF only at the start of the file but not on each segment?

Share this post


Link to post
Share on other sites

The $FFFF signature is only necessary at the top of the file (i.e. ahead of the first segment). However, while subsequent headers need only contain start and end (4 bytes), if they happen to also have the $FFFF header, it should ignored by the loader (and this is very trivial to do).

 

SDX binaries are a different matter, since the header signatures define the type of the segment which follows.

Share this post


Link to post
Share on other sites

so.. binary file:

 

FF FF FF FF FF FF FF

 

means load FF to FFFF adress :-)

Share this post


Link to post
Share on other sites

There's also the Init and Run procedure.

 

Any time a segment is loaded, an indirect call is made to whatever address is pointed to by $2E2 - this address is pre-initialized to point to an RTS before each segment read starts.

At the end of the file, the file is run by a JMP indirect through $2E0. No return is expected. Some Doses support return but it shouldn't be relied on.

  • Like 1

Share this post


Link to post
Share on other sites

so.. binary file:

 

FF FF FF FF FF FF FF

 

means load FF to FFFF adress :-)

 

Actually, no... it's treated as an empty EXE file by DOS 2.

 

Atari documented the details of the executable load format in the DOS 2 and 2.5 manuals. The key rule that allows FFFF before segments is that you are allowed to concatenate load files together with the Copy File command. Since the source files are required to begin with FFFF, this means that any segment in a load file can have it too. What they didn't document is that a load file is not required to have any segments, so that an executable file consisting solely of the FFFF signature is a valid one. This means that FFFF is never a valid segment start address and loaders have to skip them even if it occurs multiple times in a row. That's actually what DOS 2 does, if you check the CIO calls it does during a load.

 

That having been said, you do not want to make executables that have embedded FFFFs. Not all loaders handle them properly, and in particular some PC-based programs will crash if they encounter it.

 

The DOS manuals also precisely document the behavior of the run vector. It is always invoked at EOF, no matter when RUNAD is written during the load. No run vector is supposed to return to DOS, same as an RTS from the run vector. When multiple run vectors are present, only the last one takes effect. Many loaders don't support these behaviors, though.

 

Finally, DOS 2 defines IOCB #1 as the load IOCB. Also not universal.

 

What I haven't been able to find is authoritative documentation on aborting a load from an INIT vector. JMP (DOSVEC) seems to be the universal way of doing so, but I haven't found any official DOS reference for that yet.

  • Like 3

Share this post


Link to post
Share on other sites

Yeah, this from Mapping The Atari (revised edition):

 

738-739 ZE2-ZE3 INITAD
Initialization address read from the disk. An autoboot file must
load an address value into either RUNAD above or INITAD. The
code pointed to by INITAD will be run as soon as that location is
loaded. The code pointed to by RUNAD will be executed only
after the entire load process has been completed. To return
control to DOS after the execution of your program, end your
code with an RTS instruction.

Share this post


Link to post
Share on other sites

Atari documented the details of the executable load format in the DOS 2 and 2.5 manuals. The key rule that allows FFFF before segments is that you are allowed to concatenate load files together with the Copy File command. Since the source files are required to begin with FFFF, this means that any segment in a load file can have it too. What they didn't document is that a load file is not required to have any segments, so that an executable file consisting solely of the FFFF signature is a valid one. This means that FFFF is never a valid segment start address and loaders have to skip them even if it occurs multiple times in a row. That's actually what DOS 2 does, if you check the CIO calls it does during a load.

no, this means that before landing adress at FF FF signature FF FF is mandatory. and if DOS skip bytes after signature that means binary loader in DOS has bug. unless you agree that valid binary file signature is (FF FF) * N not FF FF :-)
---
besides... command: binary save in DOS properly create such binary file (eg: FF FF FF FF FF FF C0)
Edited by xxl

Share this post


Link to post
Share on other sites

 

no, this means that before landing adress at FF FF signature FF FF is mandatory. and if DOS skip bytes after signature that means binary loader in DOS has bug. unless you agree that valid binary file signature is (FF FF) * N not FF FF :-)
---
besides... command: binary save in DOS properly create such binary file (eg: FF FF FF FF FF FF C0)

 

 

No, this just means that DUP has poor validation. There's no reason for DOS to support a special case specifically for this, unless you believe there's an actual useful reason for or any possible way that DOS could load a single byte into the high byte of the IRQ vector.

Share this post


Link to post
Share on other sites

 

No, this just means that DUP has poor validation. There's no reason for DOS to support a special case specifically for this, unless you believe there's an actual useful reason for or any possible way that DOS could load a single byte into the high byte of the IRQ vector.

 

 

so you belive there's an actual useful reason for or any possible way that DOS could load a single byte into any rom area (C000-CFFF; D800-FFFF). if file has block that load data into rom that means it is not binary file?

Share this post


Link to post
Share on other sites

Yeah, this from Mapping The Atari (revised edition):

 

738-739 ZE2-ZE3 INITAD

Initialization address read from the disk. An autoboot file must

load an address value into either RUNAD above or INITAD. The

code pointed to by INITAD will be run as soon as that location is

loaded. The code pointed to by RUNAD will be executed only

after the entire load process has been completed. To return

control to DOS after the execution of your program, end your

code with an RTS instruction.

 

I am just curious,

What happens when a segment is loaded to addresses 735-741. Does this qualify as an INIT jump too?

Share this post


Link to post
Share on other sites

With Init and Run it doesn't matter how the data gets there. It can be loaded direct, it can be loaded overlayed as part of a bigger data chunk although it's not a good idea to just load big chunks into the OS work area.

It could also be set by the program.

 

e.g. an Init section could execute and set the Run address itself rather than have it loaded. Though in practice you'd have to question why, and I doubt many if anything would do it.

Setting the Init address inside the program should have no effect. When an Init section returns the Init address is reinitialized to point to an RTS.

Share this post


Link to post
Share on other sites
e.g. an Init section could execute and set the Run address itself rather than have it loaded. Though in practice you'd have to question why, and I doubt many if anything would do it.

 

I wonder if it was ever done to make cracking a program just a little less easy.

Share this post


Link to post
Share on other sites

so you belive there's an actual useful reason for or any possible way that DOS could load a single byte into any rom area (C000-CFFF; D800-FFFF). if file has block that load data into rom that means it is not binary file?

 

No, I'm saying that it's not a binary file because Atari never specifically documented it would work and it doesn't actually work.

 

It doesn't work on Atari DOS 2.0S.

It doesn't work on Atari DOS 2.5.

It doesn't work on SpartaDOS 3.2g.

It doesn't work on SpartaDOS 4.0.

It doesn't work on SpartaDOS 4.0 X.COM.

It doesn't work on MyDOS 4.55.

It doesn't work on Turbo-DOS XE.

 

In summary, using FFFF as a segment start address was never documented as supported, doesn't work on a large selection of contemporary DOSes, and doesn't have a use. Therefore, practically, it isn't supported in executable files.

Share this post


Link to post
Share on other sites

 

I wonder if it was ever done to make cracking a program just a little less easy.

Doubtful.

Most game software ever made booted up and read raw sector data. Using a Dos format wastes 3 bytes per sector plus means the overhead of having to keep at minimum a read-only filesystem in memory.

Though a rudimentary read-only Dos can be done very cheaply, if just file numbers are used instead of doing filename processing it could probably be done in under 300 bytes.

Share this post


Link to post
Share on other sites

In summary, using FFFF as a segment start address was never documented as supported

 

Atari did not specify what will work (Atari never specifically documented load adress f000 would work also) but outline a standard (signature is ffff not n*ffff), and fffff as the load address fits in the standard and DOS can create such file, can't load it.
what about starting address higher than end address - fit in standard? Atari documented it? binary load succeeds in spite of the creation such file in dos - reports an error.
so, you can not reason about the standard by what functions opetares because as I showed on two cases DOS not being able to handle a file created by himself and handle the file which he can not create.

Share this post


Link to post
Share on other sites

To me even though it makes little sense it should be valid to have a load start or end of $FFFF as valid.

 

Using the Low and High = $FF as a "skip signature" method to me is a shortcut to save a few bytes programming and also reeks of some of the Y2K paranoia where stuff like inputs of 9-99 99-9 etc had to be tested as well because in the old days were used as EOF flags.

 

Also, though it's not exactly a common thing to do, it's sometimes desirable to just point a section to Rom such that it's not actually loaded to Ram - either by quick/dirty mod to source or patching the object file.

 

OK, sort of contradictory by panning a kludge then promoting another but...

Share this post


Link to post
Share on other sites

But how would you propose to deal with optional binary signatures in any but the first segment aside from checking if Low AND High = $FF? It's only a shortcut if you don't set a flag once a single signature is skipped in order to avoid skipping next pair of bytes if they also happened to both equal $FF.

 

Pragmatically, it may be best practice to allow a segment to point at $FFFF, but in practical terms it's completely unnecessary. There are 14,335 other load addresses in ROM to choose from for patching purposes. Even if one wished to set the IRQ vector direct from the file, the start address would be $FFFE, so none of the above would even matter. Plus which, the matter is moot since - as Avery points out - almost no DOS will load the file correctly. So: create a file containing a segment with a load address of $FFFF and watch it fail on almost all binary loaders but the one which fixes the "issue". :)

Share this post


Link to post
Share on other sites
no, and I do not earn some extra theory but reason is simple - 7 bytes.



BLOAD

ldy #$FF - (_IDFFFF-_lbf) ; 2 bytes

_lbf sty _IDFFFF ; 3 bytes

jsr GET_BYTE

sta load_ptr

jsr _GET_BYTE

sta load_ptr+1

and load_ptr

ldy #$00 ; 2 bytes

cmp #$ff

beq _lbf

_IDFFFF equ *-1

Share this post


Link to post
Share on other sites

Sigh... I infer from this polemic that XBIOS supports loading a segment at $FFFF then.

Exactly :))))))

And how easy it is to protect against XBIOS loading now when we know - just add second $ff pair and blam, it hangs :)))))))))))))

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...