• OMF v1.0?

    From Kelvin Sherlock@21:1/5 to All on Thu Jun 25 03:08:39 2020
    Before OMF was the IIgs executable format, it was the 8-bit ORCA
    object module format.

    quoting the 8-bit ORCA/M Assembler 4.1 documentation (circa 1986):

    ORCA languages take source files as input and produce object modules
    as output. These object modules are then used as input to the link
    editor. Object modules are contained in a special file type with a
    file type number of $B1, which shows up as OBJ when cataloged from
    ORCA.

    There are now two versions of the object module format. The first,
    used with ORCA/M 4.0, is labeled as version zero in the header. The
    second, used by ORCA/M 4.1 on both eight and sixteen bit Apple II
    computers, and by the Apple IIGS Programmers Workshop on the Apple IIGS,
    has a one as the version number. ...

    --

    The Byte Works has a copy of Cortland Programmer's Workshop 4.1A11,
    the final version before it was APW. Note this is based on 8-bit ORCA/M
    and included library files are version 2.0 OMF.

    http://www.byteworks.us/Byte_Works/Morgue.html

    The RELEASE.NOTES mentions in the Change History:

    (V1.0 A2 3 Feb 86)
    Version number for load file is now 1.

    So if you want a version 1.0 file, you'll need to track down CPW Alpha 1
    or ORCA/M 4.0 (for object files)

    -------
    ProLine: kelvin@pro-kegs

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Stephen Heumann@21:1/5 to Stephen Heumann on Thu Jun 25 00:33:47 2020
    On 2020-06-25 03:15:35 +0000, Stephen Heumann said:
    I haven't tracked down the old eight-bit versions of ORCA/M to get
    examples of the OMF files they generate, but I think that's where you
    would have to look if you want to find them.

    I looked through Opus ][ a bit and was able to find one OMF "version 0"
    file on it:

    ByteWorks/Eight.Bit/ORCA4.1/LIBRARIES/A..CLIB.A

    This is the library for the eight-bit ORCA version of Small-C, which
    was probably compiled with ORCA/M 4.0. The source code for it is also
    on Opus ][, if you want to reference that.

    --
    Stephen Heumann

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Antoine Vignau@21:1/5 to All on Wed Jun 24 22:53:12 2020
    History and more within the single-sided document at http://www.brutaldeluxe.fr/documentation/cortland/v1_05_ObjectModuleFormatERS.pdf

    Antoine

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From olivier.zardini@cooperteam.eu@21:1/5 to All on Thu Jun 25 00:14:22 2020
    Le jeudi 25 juin 2020 01:15:41 UTC+2, Andy McFadden a écrit :

    Adding to my confusion is the Brutal Deluxe OMF Analyzer, which treats v1.0 the same way. I don't know if their code is based on the behavior of the system loader, or if they just saw my code and assumed I knew what I was doing. :-)

    I think my source of information for OMF Analyzer was a chapter in the Orca/M 2.0 Manual (+ GS/OS Reference book for 2.1 format).

    I can't exclude a look into your CiderPress source code at the time but I don't think so :-)

    Olivier

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From geoff body@21:1/5 to All on Thu Jun 25 07:47:36 2020
    Andy,
    I believe you are in the right section of the Apple IIgs Programmers Workshop Reading. Chapter 7 of the APW V1.0 draft, starting at 232-237 there is a clear definition of both OMF 1.0 and 2.0.
    Ciderpress interprets the version 1.0 OMF header correctly, but displays as Version as 2.0. The first item in the segment header is bytecnt for 2.0, while for 1.0 it is BLKcnt. Having looked at the disk for TML PASCAL for APW vers 1.0 using Ciderpress
    and using the descriptions from Chapter 7, the header for TMLPASCAL and sample compiled programs have 1 in the Version field. The file structure matches the OMF 1.0 with segments also starting on block boundaries.
    This confirms that The Version field in the segment header is the version number of the OMF.
    http://www.goldstarsoftware.com/applesite/Documentation/AppleIIgsProgrammersWorkshop.PDF

    Geoff B

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Andy McFadden@21:1/5 to geoff body on Thu Jun 25 08:22:42 2020
    On Thursday, June 25, 2020 at 7:47:38 AM UTC-7, geoff body wrote:
    Ciderpress interprets the version 1.0 OMF header correctly, but displays as Version as 2.0. The first item in the segment header is bytecnt for 2.0, while for 1.0 it is BLKcnt.

    Oh, if only. For VERSION=1, the first field is *either* BLKCNT or BYTECNT. For Load and Object files, it's a block count, and the overall file *usually* has a length that is a multiple of 512 (see e.g. BRIDGE.S16 on the Davex v1.23 disk for an example
    of a "short" binary). For static libraries, they apparently didn't want to waste space between segments, so it holds a byte count instead.

    You have to know the ProDOS file type to interpret the file contents unambiguously. (This annoys me deeply.)

    Anyway. I'm looking at the docs and think you're correct that I've mis-interepted the OMF version. The docs for OMF 2.0 and 2.1 (in the APW Ref and GS/OS ref, respectively) both say that the VERSION field is set to 2. The GS/OS ref also describes a
    REVISION field that is supposed to have the value 1, but declines to identify its location in the figure on page 447.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Andy McFadden@21:1/5 to olivier...@cooperteam.eu on Thu Jun 25 08:42:38 2020
    On Thursday, June 25, 2020 at 12:14:23 AM UTC-7, olivier...@cooperteam.eu wrote:
    I think my source of information for OMF Analyzer was a chapter in the Orca/M 2.0 Manual (+ GS/OS Reference book for 2.1 format).

    That would make sense. There's a comment in the CiderPress sources that says:

    * Orca/APW libs seem to use version 1 with a byte count in the
    * first field, but the "LLRE" app has version 1 with a block count.
    * The spec is pretty clear, so it looks like somebody's library
    * builder screwed up.

    This behavior is explained in the Apple IIgs Programmers Workshop Reference, so I was clearly getting my 1.0/2.0 info from somewhere else. I just couldn't figure out where. :-)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Andy McFadden@21:1/5 to Stephen Heumann on Thu Jun 25 08:26:52 2020
    On Wednesday, June 24, 2020 at 8:15:37 PM UTC-7, Stephen Heumann wrote:
    I think "Version 1", "Version 2.0", and "Version 2.1" (as defined in
    the ORCA/M manual) can all be found in various IIGS programs and object/library files. If you're asking about "Version 0" then AFAIK it
    was never used with IIGS stuff, only with eight-bit ORCA/M 4.0.
    According to the manual, that version is indeed missing the SEGNUM,
    ENTRY, DISPNAME, DISPDATA, and LOADNAME fields.

    This makes sense. CiderPress is interpreting the version field incorrectly.

    Since VERSION=0 wasn't really used for 16-bit code, it can be ignored entirely by the IIgs code formatter.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Stephen Heumann@21:1/5 to Andy McFadden on Thu Jun 25 13:41:56 2020
    On 2020-06-25 15:22:42 +0000, Andy McFadden said:
    Oh, if only. For VERSION=1, the first field is *either* BLKCNT or
    BYTECNT. For Load and Object files, it's a block count, and the
    overall file *usually* has a length that is a multiple of 512 (see e.g. BRIDGE.S16 on the Davex v1.23 disk for an example of a "short" binary).
    For static libraries, they apparently didn't want to waste space
    between segments, so it holds a byte count instead.

    You have to know the ProDOS file type to interpret the file contents unambiguously. (This annoys me deeply.)

    Well, static libraries would normally start with a library dictionary
    segment, which could be detected independently of the file type. Are
    there version 1 files where the presence or absence of a library
    dictionary segment does not line up with the use of BLKCNT vs. BYTECNT?

    Anyway. I'm looking at the docs and think you're correct that I've mis-interepted the OMF version. The docs for OMF 2.0 and 2.1 (in the
    APW Ref and GS/OS ref, respectively) both say that the VERSION field is
    set to 2. The GS/OS ref also describes a REVISION field that is
    supposed to have the value 1, but declines to identify its location in
    the figure on page 447.

    AFAIK that REVISION field doesn't really exist. I think the
    documentation updates for version 2.1 were done a bit sloppily. There
    are also a couple places in the GS/OS Reference where the specified
    offsets do not properly account for the tempORG field.

    --
    Stephen Heumann

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Andy McFadden@21:1/5 to Stephen Heumann on Thu Jun 25 13:01:55 2020
    On Thursday, June 25, 2020 at 11:41:58 AM UTC-7, Stephen Heumann wrote:
    You have to know the ProDOS file type to interpret the file contents unambiguously. (This annoys me deeply.)

    Well, static libraries would normally start with a library dictionary segment, which could be detected independently of the file type. Are
    there version 1 files where the presence or absence of a library
    dictionary segment does not line up with the use of BLKCNT vs. BYTECNT?

    My approach is to parse assuming it's not a library. If the parsing fails, or a LibDict segment is encountered, restart with the assumption that it is a library and see if that works.

    The basic premise of the file format -- that OMF is just a rough structure to hold various things, and you need to know what the thing is ahead of time -- annoys me, but it wouldn't be so bad if you could easily parse the outer container. Having to
    parse the contents of a segment to know how to find the next segment is Just Wrong(tm) when the file structure is supposed to be a chunk list.

    (FWIW, the specification says the library file "includes" a segment, but does not declare that it must appear first. In practice I think it will always be first because that's how the tools work.)

    AFAIK that REVISION field doesn't really exist. I think the
    documentation updates for version 2.1 were done a bit sloppily. There
    are also a couple places in the GS/OS Reference where the specified
    offsets do not properly account for the tempORG field.

    Yup, I think the only way to tell the difference is by DISPNAME > $2a.

    Figure F-2 also shows "blockCount" where it should say SEGNAME.

    ByteWorks/Eight.Bit/ORCA4.1/LIBRARIES/A..CLIB.A

    Thanks! CiderPress does handle that one. Interesting that the other libs in that dir use the newer OMF format.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Stephen Heumann@21:1/5 to Andy McFadden on Thu Jun 25 16:44:38 2020
    On 2020-06-25 20:01:55 +0000, Andy McFadden said:
    My approach is to parse assuming it's not a library. If the parsing
    fails, or a LibDict segment is encountered, restart with the assumption
    that it is a library and see if that works.

    That sounds reasonable, although I suspect that in practice the lib
    dict is always first.

    AFAIK that REVISION field doesn't really exist. I think the
    documentation updates for version 2.1 were done a bit sloppily. There
    are also a couple places in the GS/OS Reference where the specified
    offsets do not properly account for the tempORG field.

    Yup, I think the only way to tell the difference is by DISPNAME > $2a.

    DISPNAME is normally 44 ($2C) in OMF v2.0, and 48 ($30) in OMF v2.1.
    (But this may differ between segments--in particular, there are many
    files where the ~ExpressLoad segment has DISPNAME=44 but other segments
    have DISPNAME=48.)

    This is one of the points that the GS/OS reference gets wrong--it says "Currently, DISPNAME = 44" even though it's documenting OMF v2.1. It
    also shows DISPDATA and tempOrg as both being at offset $2A in Figure
    F-2, when tempOrg must actually be at offset $2C.

    ByteWorks/Eight.Bit/ORCA4.1/LIBRARIES/A..CLIB.A

    Thanks! CiderPress does handle that one. Interesting that the other
    libs in that dir use the newer OMF format.

    The other files in that directory are from ORCA/M 4.1, so they use
    OMFv1. ORCA Small-C was originally a separate product, and its library
    must have been built with ORCA/M 4.0.

    --
    Stephen Heumann

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Andy McFadden@21:1/5 to Stephen Heumann on Thu Jun 25 16:41:58 2020
    On Thursday, June 25, 2020 at 2:44:39 PM UTC-7, Stephen Heumann wrote:
    Yup, I think the only way to tell the difference is by DISPNAME > $2a.

    DISPNAME is normally 44 ($2C) in OMF v2.0
    [...]
    also shows DISPDATA and tempOrg as both being at offset $2A in Figure
    F-2, when tempOrg must actually be at offset $2C.

    See if you can guess which figure I was looking at when I wrote the above. :-)

    Sometimes I miss paper documentation... when something is wrong you can fix it with a pencil. I'm entirely too lazy to dig those out of the many boxes of stuff though, so I'll make do with the scans.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From geoff body@21:1/5 to All on Fri Jun 26 06:51:21 2020
    Having the File Type would help to minimise guessing
    Based on File Types should be able to locate types that have segments
    load segment header(s)
    check the version of OMF (1 or 2 are valid)
    Check KIND, which changes position and size based on OMF, OMF 1.0 at offset $0C (size 8 bits), or OMF 2.x at offset $14 (size 16 bits)
    KIND will help identify segment types which should make it easier to process a segment of a specific type.

    See page 236 of Apple IIgs Programmers Workshop for description of both versions of KIND
    eg. bits 0-4 of Kind = 08 -> library dictionary segment

    Geoff B

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Andy McFadden@21:1/5 to olivier...@cooperteam.eu on Sat Jun 27 10:25:31 2020
    On Thursday, June 25, 2020 at 12:14:23 AM UTC-7, olivier...@cooperteam.eu wrote:
    I think my source of information for OMF Analyzer was a chapter in the Orca/M 2.0 Manual (+ GS/OS Reference book for 2.1 format).

    For anyone else looking for this: on the Opus ][ CD, look in the "Documentation:PDF Documentation" folder. The file "GS-04 ORCA/M 2.0.pdf" is the relevant one. Appendix B describes OMF; page 488 shows v0, v1, and v2.1 side-by-side.

    It uses slightly different names (e.g. BLOCKCOUNT vs. BLKCNT), and doesn't describe the v1 Object/Library behavior, noting simply "several features that deal with relocatable code and libraries have been omitted." Only Load files are documented.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Andy McFadden@21:1/5 to All on Sun Jul 12 11:29:36 2020
    CiderPress has been updated. The fixed OMF version reporting is in a pre-release, v4.0.4-d2. https://github.com/fadden/ciderpress/releases if you're dying to see the correct value.

    The OMF viewer in SourceGen handles all versions, including "v0" (tested with the library mentioned earlier in this thread). It also goes deeper than CiderPress, decoding records in object and library files, so if you were curious to see expressions in
    compiler intermediates you can now do so from the comfort of Windows. :-)

    The OMF converter does more or less what the GS/OS system loader does, though I'm still a little vague on the interaction with some of the KIND flags when ORG is zero.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From geoff body@21:1/5 to All on Tue Oct 12 17:53:35 2021
    To anyone interested after having had a poke about MPW tool LinkIIgs there is a procedure check_header, the code is interesting with regard to revision field.
    It appears that the revision field for version 2.X reuses the LCBANK field from OMF 1.0.

    if ( *(Buf + 14) != 0x04
    || *(Buf + 32) != 0x00
    || *(Buf + 8) > 0x00FFFFFF
    || *(Buf + 24) > 0x00FFFFFF
    || *(Buf + 28) > 0x00FFFFFF
    || *(Buf + 36) > 0x00FFFFFF
    || *Buf < 48 )
    {
    fprintf(stderr, "%sBad Segment Header found in Segment $%hX in file \"%s\\r", );
    fatal(2, 0);
    }

    else if (*(Buf + 15) < 0x01 || *(Buf + 15) > 0x02)
    {
    fprintf(stderr, "%sUnsupported OMF Version (%hX) found in Segment $%hX in file \"%s\"\r");
    fatal(2, 0);
    }
    else
    {
    if ( *(Buf + 15) == 0x02)
    {
    if ( *(Buf + 33) > 0x01)
    {
    fprintf(stderr, "%sUnsupported OMF Revision (%hX) found in Segment $%hX in file \"%s\"\r",);
    fatal(2, 0);

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From fadden@21:1/5 to gbo...@bigpond.com on Wed Oct 13 15:54:25 2021
    On Tuesday, October 12, 2021 at 5:53:36 PM UTC-7, gbo...@bigpond.com wrote:
    It appears that the revision field for version 2.X reuses the LCBANK field from OMF 1.0.
    [...]
    {
    if ( *(Buf + 15) == 0x02)
    {
    if ( *(Buf + 33) > 0x01)
    {
    fprintf(stderr, "%sUnsupported OMF Revision (%hX) found in Segment $%hX in file \"%s\"\r",);

    Interesting... you think at some point the tools used the "undefined" (nee LCBANK) field to differentiate between v2.0 and v2.1 segments?

    It doesn't appear to be nonzero in the v2.1 files I've looked at that were generated on a IIgs. Maybe someone thought it *might* be used and planned ahead?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From geoff body@21:1/5 to All on Wed Oct 13 17:14:27 2021
    It doesn't appear to be nonzero in the v2.1 files I've looked at that were generated on a IIgs. Maybe someone thought it *might* be used and planned ahead?

    Do you have samples that you believe are OMF V2.1 files and where to find them?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From fadden@21:1/5 to gbo...@bigpond.com on Wed Oct 13 22:00:38 2021
    On Wednesday, October 13, 2021 at 5:14:28 PM UTC-7, gbo...@bigpond.com wrote:
    Do you have samples that you believe are OMF V2.1 files and where to find them?

    YankIt and the HardPressed PIF have OMF v2.1 segments. YankIt is here: https://fadden.com/apple2/dl/yanksrc.shk

    I'm looking at the header with the SourceGen OMF conversion tool. For example:

    BYTECNT $00e4f7 bytes
    RESSPC $000000
    LENGTH $00c962
    undefined $00
    LABLEN $00 variable length
    NUMLEN $04 must be 4
    VERSION $02 v2.1
    BANKSIZE $010000
    KIND $0000 Code
    undefined $0000
    ORG $000000 relocatable
    ALIGN $000000 no alignment
    NUMSEX $00 must be 0
    undefined $00
    SEGNUM $0002
    ENTRY $000000
    DISPNAME $0030
    DISPDATA $0045
    TEMPORG $000000
    LOADNAME
    SEGNAME

    The only way to tell v2.0 from v2.1 is by looking at DISPNAME. If it's 44 ($2c) then it's a v2.0 header, if it's greater than that then it has additional fields (TEMPORG). LCBANK is the undefined field after NUMSEX, but it always seems to hold zero.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From geoff body@21:1/5 to All on Fri Oct 15 21:25:14 2021
    Going to try and generate a OMF 2.1 segment with MPW AsmIIGS.
    Then see if it flows through the other tool(s) including the linker -> LinkIIgs.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From geoff body@21:1/5 to All on Sat Oct 16 07:52:11 2021
    Updated the sample link to just the file. https://drive.google.com/file/d/1zj-bhCGcZrOHe9_ZuFmbMtMCT5V6j-Pq/view?usp=sharing

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From geoff body@21:1/5 to All on Sat Oct 16 07:47:22 2021
    MPW AsmIIgs v1.1 generates Obj files with the TempOrg flagged in the header if used as a directive in the source.
    discussed in the manual for MPW AsmIIgs manual
    Linking produces output no longer needing the TempOrg detail.
    based on changes for the MPW IIgs tools Apple made changes to MakelibIIgs to handle output by produced by ORCA 2.0 that was adding an empty TempOrg, see reference below.


    MPW IIGS Tools V1.3

    MakeLibllGS:
    • ORCA 2.0 assembler is producing object files with the TempOrg field in the segment
    headers, even though it's not using the field. This offsets the dispName and dispData
    field values. MakeLib is not adjusting these values when it writes the segment headers
    out to the library file without the TempOrg field. Fixed by having WriteSegmentHeader
    calculate the proper values.

    LinkUGS:
    • LinklIGS v.1.1 is much faster and uses less memory than v.1.0.
    • LinklIGS will use MultiFinder memory during links if the '-mf option is specified. This allows
    the memory partition for MPW itself to be kept smaller, leaving more room for other applications
    when LinklIGS is not being used.
    • LinklIGS supports OMF Version 2.1 which includes: Object Segments having a tempORG
    (temporary origin); Skip Object Segments; and Bank Relative Object Segments.

    MPW sample files with associated MPW dumped segment headers. https://drive.google.com/drive/folders/1cY67HANwb6NsQhogJhc1Ijz2Y9ERM1p2?usp=sharing

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From fadden@21:1/5 to All on Sat Oct 16 15:36:20 2021
    ProDOS.FST.Obj has one v2.1 segment (BOOT_CODE), and sure enough:

    Alignment : $00000000 0
    Number sex : $00 0
    Revision : $01 1

    gquit.obj also has one v2.1 segment (LOAD_APP), also with a nonzero value. So the Mac tools appear to be using the "undefined" field that follows NUMSEX to be the minor version number.

    The v2.1 segments in YankIt/HP have a tempORG field with zero in it, which is probably what the remarks about "not using the field" mean. The segments are not technically v2.0, since the tempORG field didn't exist in the v2.0 definition... but if it's
    not really being used, does it count?

    Maybe the Orca-generated segments should be called v2.0.1?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From geoff body@21:1/5 to All on Sat Oct 16 21:33:35 2021
    According to GSOS reference V5.0 and later.
    tempORG A 4-byte field indicating the temporary origin of the Object segment. A nonzero value indicates that all references to globals within this segment
    will be interpreted as if the Object segment started at that location.
    However, the actual load address of the Object segment is still
    determined by the ORG field.

    It would appear that a OMF 2.1 header would/should only apply to these Object segments, which also includes Libraries that have included a OBJ with OMF 2.1.

    Maybe should ask Mike Westerfield if there is any further documentation on OMF 2.1 format.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)