        TTL     AmigaDOS 68000 overlay supervisor
**********************************************************
*                                                        *
* This version of the overlay supervisor is callable     *
* from C or Assembler; it will not work for MCC Pascal   *
* or BCPL which use a calling sequence where the called  *
* routine's address is saved on the stack. A different   *
* version of the overlay supervisor is available for     *
* case.                                                  *
*                                                        *
* The main overlay algorithm used here was originally    *
* described by Richard Evans at Cambridge University     *
* in about 1979. This code implementation was done by    *
* Tim King of Metacomco.                                 *
*                                                        *
* Two main data structures are used:                     *
*                                                        *
*   1. The hunk table                                    *
*                                                        *
*        This table, giving the base addresses of all    *
*          hunks currently loaded, is manufactured by    *
*          the loader.  Its address is planted in HTAB,  *
*          and its first word is the address of hunk 0.  *
*          Note that the addresses it contains are those *
*          of the link word of each hunk - not the first *
*          data word.                                    *
*                                                        *
*   2. The overlay table                                 *
*                                                        *
*        This table is manufactured by the linkage       *
*          editor, and its address is planted in OVTAB   *
*          by the loader.   It consists of two main      *
*          parts, the ordinate table, and the overlay    *
*          data table.  The former is a table which is   *
*          used to remember the ordinate number of each  *
*          segment that is currently loaded. If n is the *
*          maximum level number, then the table contains *
*          n+1 entries, and the first word is n+2. The   *
*          extra entry is required because a scan        *
*          through the table below is terminated by a    *
*          zero entry.  All the entries are initially    *
*          cleared by the linkage editor.  The address   *
*          of the overlay table, plus the contents of    *
*          its first word (n+2), gives the address of    *
*          the overlay data table, which is indexed by   *
*          overlay number.  Each entry in this table     *
*          contains the following information, not       *
*          necessarily in this order:                    *
*                                                        *
*            1. A file mark, generated by 'note', giving *
*                the position of the segment to be       *
*                loaded.                                 *
*            2. The overlay level of the segment.        *
*            3. The overlay ordinate of the segment.     *
*            4. The initial hunk number of the segment.  *
*            5. The number of the hunk containing the    *
*                symbol.                                 *
*            6. The offset of the symbol in the hunk.    *
*                                                        *
* If an error is detected during overlaying, there is a  *
* limited choice of sensible actions, since the overlay  *
* supervisor can make no assumptions concerning the      *
* environment it was entered from.  The action on an     *
* error is to call an Alert with the code for invalid    *
* overlay request.                                       *
*                                                        *
* Note that the value in HTAB is a long word address,    *
* whilst that in OVTAB is a machine address.  Each entry *
* in the table is four bytes long.                       *
*                                                        *
**********************************************************
*  Change History:
*
*       CARL 05SEP85
*            1) Changes made (suggested by Paul) to the handling
*               of seek and loadseg errors.  When an error
*               occurs, the program will retry until it is
*               successful.
*            2) Changed bra.s to just bra in OVENT and OVENT2
*               macro definitions.
*            3) Added the OVERLAYS equate and the necessary OVENT2
*               table entries (conditionally assembled).
*            4) Eliminated unnecessary include files.
*       CARL 06SEP85
*            1) CALL macro modified.
*            2) CALL use modified.
*       DTM  15JUN87
*            1) modified to either define or use static OCVs, or
*               Overlay Call Vectors, as we now call them.
*            2) changed entry name to "_ovlyMgr" (note that the
*               underscore is added automatically, and case IS
*               very important
*            3) added instruction to make sure that only lower
*               16 bits of d0 are used in indexing into table;
*               the new dynamic OCVs only pass a word in d0,
*               although it's still multiplied by 8 and > 0.
*            4) Basically all of this increase the total number
*               of OCVs to 8k, and furthermore makes it
*               possible to put this code into a library



        section NTRYHUNK,CODE

        INCLUDE "exec/types.i"
        INCLUDE "exec/tasks.i"
        INCLUDE "exec/libraries.i"
        INCLUDE "exec/alerts.i"
        INCLUDE "libraries/dos.i"

        xdef    ovlyMgr

FUNCDEF         MACRO   * function
_LVO\1          EQU     FUNC_CNT
FUNC_CNT        SET     FUNC_CNT-6
                ENDM

FUNC_CNT        SET     LIB_NONSTD

        INCLUDE "exec/exec_lib.i"
        INCLUDE "libraries/dos_lib.i"


* Offsets within the overlay table.
SysBase EQU         4

OTMARK  EQU         0                   File position
OTLEVL  EQU        12                   Level
OTORD   EQU        16                   Ordinate
OTIHNK  EQU        20                   Initial hunk for load
OTRHNK  EQU        24                   Hunk containing symbol
OTOFF   EQU        28                   Offset of symbol
LIBWORD EQU        23456


* A macro to call a LIBRARY routine:
CALLS   MACRO
        MOVEA.L    SysBase.w,A6
        JSR        _LVO\1(A6)
        ENDM

* Call a library, save and restore A6.
CALL    MACRO      ; CALL <library_vector_offset>,<library_pointer>
        MOVE.L     A6,-(SP)
        MOVE.L     \2,A6
        JSR        _LVO\1(A6)
        MOVE.L     (SP)+,A6
        ENDM


* Now for the first word of the program.

FIRST   BRA.W NextModule

* This next word serves to identify the overlay
* supervisor to 'unloader'.

        DC.L       $ABCD                Special value


* The loader plants values in the next locations.

STREAM  DC.L       0                    Overlay input stream
OVTAB   DC.L       0                    Overlay table (Machine address)
HTAB    DC.L       0                    Hunk table    (BCPL address)
GLBVEC  DC.L       0                    Global vector (Machine address)


*
* The main code of the program.
*
        CNOP       0,4
        DC.L       LIBWORD
        DC.B       7,'Overlay'

ovlyMgr
OV1     MOVEM.L    A2-A7/D2-D7,-(SP)
        MOVE.L     OVTAB(PC),A3         Address of overlay table
        MOVEA.L    A3,A4
        AND.L      #$0FFFF,D0           Make SURE that upper word is ZERO
        ADD.L      (A3),D0              Add value in first word of table
        LSL.L      #2,D0
        ADDA.L     D0,A3                Address of overlay entry
        MOVE.L     OTLEVL(A3),D0        Get required level
        LSL.L      #2,D0
        ADDA.L     D0,A4                Pointer to entry in ordinate table
        MOVE.L     OTORD(A3),D0         Get required ordinate
        CMP.L      (A4),D0              Compare with actual
        BEQ        GOTSEG               Branch if no load required

* Now clear other entries in the ordinate table

        MOVE.L     D0,(A4)+
OV2     TST.L      (A4)                 Table terminated by zero
        BEQ.S      OV3
        CLR.L      (A4)+
        BRA.S      OV2
*
OV3     MOVE.L     OTIHNK(A3),D0        First hunk number of overlay segment
        ADD.L      HTAB(PC),D0
        LSL.L      #2,D0                Address of entry in hunk table
        MOVEA.L    D0,A4
        MOVE.L     -4(A4),D0            Previous hunk
        LSL.L      #2,D0
        MOVEA.L    D0,A6
        CLR.L      (A6)                 Clear link field in case of error

* Now free all the unwanted hunks ...

OV4     TST.L      (A4)                 Scan is terminated by zero
        BEQ        OV5
        MOVE.L     (A4)+,D1             Address as argument for 'freevec'
FREEVEC   TST.L      D1
          BEQ.S      FVC1             Return if V = 0
          ASL.L      #2,D1            Back to mc address
          MOVEA.L    D1,A1
          MOVE.L     -(A1),D0         D0 = size
          MOVE.L     D0,D1            Take copy
          ANDI.L     #$FF000003,D1    Top byte and bottom 2 bits..
          BNE        OVERR            .. must be clear to be valid length
          CALL       FreeMem,SysBase.w
FVC1      BRA.S      OV4              and again

* Now save CIS and point the file

OV5
        LEA.L   LIBNAME(PC),A1
        MOVEQ   #0,D0
        CALL    OpenLibrary,SysBase.w
        MOVE.L  D0,D7
        BEQ.S   OVERR

        ADDA.L     #OTMARK,A3           Address of file mark

* Now seek to the segment and load it.  If we fail (probably because
* the user removed the disk, then retry until successful.  This has
* the effect of continually reprompting the user to insert the disk
* until he obeys.

OV_RETRY:
        MOVE.L     STREAM(PC),D1            New stream
        MOVE.L     (A3),D2
        MOVEQ      #OFFSET_BEGINNING,D3 Offset to be from beginning
        CALL       Seek,D7                 Call 'point(scb,mark,o)'
        TST.L      D0                   Check result
        BMI.S      OV_RETRY             Branch if error

        ; Now call the loader again:
        MOVE.L     HTAB(PC),D2          Hunk table (second parameter)
        MOVEQ      #0,D1                Zero parameter for overlay
        MOVE.L     STREAM(PC),D3
        CALL       LoadSeg,D7
        TST.L      D0                   Check result
        BMI.S      OV_RETRY             Branch if error

* Add new list to chain after previous one

        MOVE.L     D1,(A6)              Add new chain

* Here when segment is in store: A3 holds table entry, A1 and D0 are free

GOTSEG  MOVE.L     OTRHNK(A3),D0        Number of hunk containing symbol
        ADD.L      HTAB(PC),D0
        LSL.L      #2,D0                Machine address of entry in hunk table
        MOVEA.L    D0,A4
        MOVE.L     (A4),D0              BCPL address of hunk
        LSL.L      #2,D0
        ADD.L      OTOFF(A3),D0         Add in offset of symbol

* The address to jump to is now in D0. Place it in A1 and jump to it.
        MOVEA.L    D0,A1
        MOVEM.L    (SP)+,A2-A7/D2-D7    restore regs
        JMP        (A1)                 Jump to new code

* Come here on an error during the overlay

OVERR 
        MOVE.L #AN_BadOverlay,D7
        CALLS  Alert
        RTS

* The code here will cause us to jump to the next segment in the list,
* which should be the intended entry point.

NextModule
        LEA.L      FIRST(PC),A3         Pointer to start of module
        MOVE.L     -4(A3),D7            Next BCPL word ptr
        ASL.L      #2,D7                MC ptr to next module
        MOVE.L     D7,A3                Into address register
        JMP        4(A3)                Tally ho!

* Data Area

LIBNAME DC.B       'dos.library',0
        CNOP       0,4


        END
