        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.


OVERLAYS	EQU	20	number of overlays handled


        RORG       0                    Relocatable code


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

* XREFS (Not allowed)
*	xref	_LVOAlert
*	xref	_LVOFreeMem
*	xref	_LVOSeek
*	xref	_LVOOpenLibrary
*	xref	_LVOLoadSeg

* Kludge to determine the correct LVO XREF's:
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"


* Now declare some useful manifests for historical reasons

Z EQUR A0
P EQUR A1
G EQUR A2
L EQUR A3
B EQUR A4
S EQUR A5
R EQUR A6

* 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

OFFSET_BEGINNING    EQU -1

* A macro to call a LIBRARY routine:
CALLS   MACRO
        MOVEA.L    SysBase,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.L 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)


* Now the overlay entry points.
* Two versions, one for small offsets and one for large


OVENT   MACRO
        ENTRY      OVLY0\1
OVLY0\1 MOVEQ      #\1*8,D0             Overlay number times size of entry
        BRA        OV1                  Branch to start of code
        ENDM

OVENT2  MACRO
        ENTRY      OVLY0\1
OVLY0\1 MOVE.L     #\1*8,D0             Overlay number times size of entry
        BRA        OV1                  Branch to start of code
        ENDM

        OVENT      000
        OVENT      001
        OVENT      002
        OVENT      003
        OVENT      004
        OVENT      005
        OVENT      006
        OVENT      007
        OVENT      008
        OVENT      009
        OVENT      010
        OVENT      011
        OVENT      012
        OVENT      013
        OVENT      014
        OVENT      015
        OVENT2     016
        OVENT2     017
        OVENT2     018
        OVENT2     019
        OVENT2     020

   IFGT OVERLAYS-20
        OVENT2     021
        OVENT2     022
        OVENT2     023
        OVENT2     024
        OVENT2     025
        OVENT2     026
        OVENT2     027
        OVENT2     028
        OVENT2     029
        OVENT2     030
        OVENT2     031
        OVENT2     032
        OVENT2     033
        OVENT2     034
        OVENT2     035
        OVENT2     036
        OVENT2     037
        OVENT2     038
        OVENT2     039
        OVENT2     040
   ENDC

   IFGT OVERLAYS-40
        OVENT2     041
        OVENT2     042
        OVENT2     043
        OVENT2     044
        OVENT2     045
        OVENT2     046
        OVENT2     047
        OVENT2     048
        OVENT2     049
        OVENT2     050
        OVENT2     051
        OVENT2     052
        OVENT2     053
        OVENT2     054
        OVENT2     055
        OVENT2     056
        OVENT2     057
        OVENT2     058
        OVENT2     059
        OVENT2     060
   ENDC


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

OV1     MOVEM.L    A2-A7/D2-D7,-(SP)
        MOVE.L     OVTAB,L              Address of overlay table
        MOVEA.L    L,B
        ADD.L      (L),D0               Add value in first word of table
        LSL.L      #2,D0
        ADDA.L     D0,L                 Address of overlay entry
        MOVE.L     OTLEVL(L),D0         Get required level
        LSL.L      #2,D0
        ADDA.L     D0,B                 Pointer to entry in ordinate table
        MOVE.L     OTORD(L),D0          Get required ordinate
        CMP.L      (B),D0               Compare with actual
        BEQ        GOTSEG               Branch if no load required

* Now clear other entries in the ordinate table

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

* Now free all the unwanted hunks ...

OV4     TST.L      (B)                  Scan is terminated by zero
        BEQ        OV5
        MOVE.L     (B)+,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
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
        MOVE.L  D0,D7
        BEQ.S   OVERR

        ADDA.L     #OTMARK,L            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,D1            New stream
        MOVE.L     (L),D2
        MOVEQ      #OFFSET_BEGINNING,D3 Offset to be from beginning
        CALL       Seek,D7                 Call 'point(scb,mark,o)'
        TST.L      D1                   Check result
        BMI.S      OV_RETRY             Branch if error

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

* Add new list to chain after previous one

        MOVE.L     D1,(R)               Add new chain

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

GOTSEG  MOVE.L     OTRHNK(L),D0         Number of hunk containing symbol
        ADD.L      HTAB,D0
        LSL.L      #2,D0                Machine address of entry in hunk table
        MOVEA.L    D0,B
        MOVE.L     (B),D0               BCPL address of hunk
        LSL.L      #2,D0
        ADD.L      OTOFF(L),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,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
