[Back to DOS SWAG index] [Back to Main SWAG index] [Original]
{
With this unit, it doesn't matter if the overlay is separate,
or tacked onto the end of the .EXE file -- the program will
run either way.
As written, this unit also uses OVERXMS, a PD unit written
Wilbert Van Leijen.  Floating around the BBS's as OVERXMS.ZIP
You may delete the references to XMS.
The XMS stuff is in there because the program I copied this
code from will run on a 486 and just about all of the college
machines have XMS memory -- few if any have EMS. }
{$A-,B+,D-,F+,I-,L-,N-,O-,Q+,R-,S-,V-}
UNIT RVOVRLAY;
{ This unit starts the overlay manager }
INTERFACE
Const
  ovrNoXMSDriver = -7;   { No XMS driver installed }
  ovrNoXMSMemory = -8;   { Insufficient XMS memory available }
IMPLEMENTATION
USES DOS, OVERLAY;
{ OVERXMS - Loads overlays in XMS.
  Assembly-language portion written by Wilbert van Leijen }
Procedure OvrInitXMS; External;
{$L OVERXMS.OBJ }
Function Exist(Filename:string):boolean;
{returns true if file exists}
var Inf: SearchRec;
begin
  FindFirst(Filename,AnyFile,Inf);
  Exist := (DOSError = 0);
end;  {Func Exist}
Procedure S_Write (Msg : string);
BEGIN  {Dirty trick to generate less code}
  Write (msg);
END;
Procedure WriteOvrErrMsg;
VAR
  garbage:char;
BEGIN
  WRITE ('Overlay error: ',OvrResult,'  ');
  IF (OvrResult = ovrOk) THEN S_WRITE ('Ok - No error');
  IF (OvrResult = ovrError) THEN S_WRITE ('Missing Overlay error');
  IF (OvrResult = ovrNotFound) THEN S_WRITE ('Overlay file not found');
  IF (OvrResult = ovrNoMemory) THEN S_WRITE ('No Memory for overlays');
  IF (OvrResult = ovrIOError) THEN S_WRITE ('Overlay IO Error');
  IF (OvrResult = ovrNoEMSDriver) THEN S_WRITE ('No EMS Driver');
  IF (OvrResult = ovrNoEMSMemory) THEN S_WRITE ('No EMS Memory');
  IF (OvrResult = ovrNoXMSDriver) THEN S_WRITE ('No XMS Driver');
  IF (OvrResult = ovrNoXMSMemory) THEN S_WRITE ('No XMS Memory');
  S_WRITE (^M^J);
  read (garbage);
  If OvrResult <> OvrOK THEN HALT (98);
END;  { Procedure WriteOvrErrMsg }
BEGIN      { main }
  IF (lo(DosVersion) < 3) THEN
    BEGIN
      WriteLn ('You are using DOS version ',Lo(DosVersion),
               '.',Hi(DosVersion));
      Writeln ('Mulesoft Revenge requires DOS v3.0 or greater.');
      HALT (99);
    END;
  { Start overlay manager and assume that overlay is in
    the .EXE file.  If not found in .EXE file, assume the
    overlay file is separate from the .EXE file. }
  OVRINIT (paramstr(0));
  If (OvrResult = ovrError) THEN  { Overlay not at end of .EXE file }
    OVRINIT (copy(paramstr(0), 1, Length(paramstr(0))-3) + 'OVR');
  IF (OvrResult <> OvrOk) THEN
      WriteOvrErrMsg
  ELSE     { Try to load the overlay into XMS memory }
    BEGIN
      OvrInitXms;
      IF (OvrResult <> OvrOk) THEN
        OvrInitEms;
    END;
END.
{------------------------- snip, snip ----------------------------}
   Here is the .OBJ file that goes with this file ...
   you will need XX3402 o decode this output:
   Cut this out to a file named OVERXMS.XX.
   Execute XX3402 d OVERXMS.XX
   You will then get the file OVERXMS.OBJ to compile this unit
*XX3402-000913-020294--72--85-48736-----OVERXMS.OBJ--1-OF--1
U+o+0qxqNL7sPLAiEJBBFMUU++++53FpQa7j623nQqJhMalZQW+UJaJmQqZjPW+n9X8NW-A+
ECafC26Q0qxqNL7sPLAiEJBBnMU1+21dH7M0++-cW+A+E84IZUM+-2F-J234a+Q+G-c++U2-
ytM4++F1HoF3FNU5+0Wi+EA-+MKAJ++7I373FYZMIoJ5++V3K2ZII37DEk+7HpNGIYJHJIlI
++hDJZ71HoF3H2ZHJ++AHpNGF2xHG23CF2l3++dDJZ76FI3EHp75++dDJZ7GFI32EZJ4+0OE
2E+++UdDJZ77HYZIK2pHCE2+xcU2+20W+N4UgU20++093VU+h+fz5U++l+M2+8A++6k4+U19
Aw+nocgS+++15U++UwAEXgAa+kM6+6DG+0O95Us+0xhptfg+-DTnYY8o0TwS+++9k5E2WFMM
+ABJWymCFUMacEU+ckU+Aw0X0U0V4+0X1++acFM+cks+7e2M+8AE+1D+cl6+clE+7e2E+8AK
+9E9jUU+zls+++j+R+F6ukGEiDnzLQc0+0O93UU+xw6-+5E4EWPz-UU+WFM6+1D+ckc+ckk+
cks+cE++cl++cFU+cl6+WHsI+6YS3U0o0vs6+DwS+++1ycDH++j+R+9skzb1JMjgcE++AwY1
-U++-F++Xg-EEGOV1U+9k5LhAxgnzkRFcE++7eAE+0O75VU+7cYy3U-HJkM4zls+++RTKmP5
-V++++1rq566u4jzQUBNsgy9tJr1Aw+v-U++REF6uqOEi+-1nGwwU5E4iDbzupSEi--1nGy7
5U++X+M0+CWmzbI4iDXzunyEu5PzQl093VU+h+fz5U++iDnzumeEWls++9EynG55-U++HU0A
1U6+l+M++8A2+6k4-U15-U++++0A1U6+Aw0X++19RdnW+AE0J+5203E-l+lI+QED-U20l-A4
+E925+M--AEU-U2-l2BI+QF9J+52KJE-l3tI+QFVJ+52N3E-l4hI+QFmJ+52RpE-l5dI+QG-
J+52VZE-l6dI+QGiJ+52gpE-l9NI+QGtJ+52j+M--gGzJ+52kZE-lAJI+QH7J+52nJE-lB7I
+QHKJ+52uEM--AHj-U2-lEQ4+EP35EM--wIx-U23lJhI+QJTJ+53QpE-lLZI+QK1-U23lMg4
+ET3XJE0lN24+ET3ZEM-+gKMJ+53b3E-lO+4+E93cZE0lOM4+E93ekM-+z88+U++R+++
***** END OF BLOCK 1 *****
{---------------------         OVERXMS.ASM   --------------------- }
{                          NEED MASM,TASM to compile               }
TITLE Turbo Pascal XMS support for loading overlays - By Wilbert van Leijen
PAGE 65, 132
LOCALS @@
Data       SEGMENT Word Public
           ASSUME  DS:Data
;  XMS block move record
XmsMoveType STRUC
           BlkSize     DD    ?
           SrcHandle   DW    ?
           SrcOffset   DD    ?
           DestHandle  DW    ?
           DestOffset  DD    ?
XmsMoveType ENDS
;  TP overlay manager record
OvrHeader  STRUC
           ReturnAddr  DD    ?         ; Virtual return address
           FileOfs     DD    ?         ; Offset into overlay file
           CodeSize    DW    ?         ; Size of overlay
           FixupSize   DW    ?         ; Size of fixup table
           EntryPts    DW    ?         ; Number of procedures
           CodeListNext DW   ?         ; Segment of next overlay
           LoadSeg     DW    ?         ; Start segment in memory
           Reprieved   DW    ?         ; Loaded in memory flag
           LoadListNext DW   ?         ; Segment of next in load list
           XmsOffset   DD    ?         ; Offset into allocated XMS block
           UserData    DW    3 DUP(?)
OvrHeader  ENDS
XmsDriver  DD      ?                   ; Entry point of XMS driver
ExitSave   DD      ?                   ; Pointer to previous exit proc
XmsMove    XmsMoveType <>
OvrXmsHandle DW    ?                   ; Returned by XMS driver
           Extrn   PrefixSeg : Word
           Extrn   ExitProc : DWord
           Extrn   OvrResult : Word
           Extrn   OvrCodeList : Word
           Extrn   OvrDosHandle : Word
           Extrn   OvrHeapOrg : Word
           Extrn   OvrReadBuf : DWord
Data       ENDS
Code       SEGMENT Byte Public
           ASSUME  CS:Code
           Public  OvrInitXMS
ovrIOError     EQU     -4
ovrNoXMSDriver EQU     -7
ovrNoXMSMemory EQU     -8
OvrXmsExit PROC
; Release handle and XMS memory
        MOV    DX, [OvrXmsHandle]
        MOV    AH, 10
        CALL   [XmsDriver]
; Restore pointer to previous exit procedure
        LES    AX, [ExitSave]
        MOV    Word Ptr [ExitProc], AX
        MOV    Word Ptr [ExitProc+2], ES
        RETF
OvrXmsExit ENDP
AllocateXms PROC
;  Determine the size of the XMS block to allocate:
;  Walk the CodeListNext chain
;  Store the total codesize in DX:AX
        XOR    AX, AX
        XOR    DX, DX
        MOV    BX, [OvrCodeList]
@@1:    ADD    BX, [PrefixSeg]
        ADD    BX, 10h
        MOV    ES, BX
        ADD    AX, ES:[OvrHeader.CodeSize]
        ADC    DX, 0
        MOV    BX, ES:[OvrHeader.CodeListNext]
        OR     BX, BX
        JNZ    @@1
;  Obtain number of kilobytes to allocate
        MOV    BX, 1024
        DIV    BX
        XCHG   DX, AX
        INC    DX
;  Allocate the block
        MOV    AH, 9
        CALL   [XmsDriver]
        OR     AX, AX
        JZ     @@2
        MOV    [OvrXmsHandle], DX
@@2:    RETN
AllocateXms ENDP
;  Function XmsReadFunc(OvrSeg : Word) : Integer; Far;
XmsReadFunc PROC
;  Swap the code from XMS to the heap
        PUSH   BP
        MOV    BP, SP
        MOV    ES, [BP+6]
        MOV    AX, ES:[OvrHeader.CodeSize]
        MOV    Word Ptr [XmsMove.BlkSize], AX
        XOR    AX, AX
        MOV    Word Ptr [XmsMove.BlkSize+2], AX
        MOV    AX, [OvrXmsHandle]
        MOV    [XmsMove.SrcHandle], AX
        MOV    AX, Word Ptr ES:[OvrHeader.XmsOffset]
        MOV    Word Ptr [XmsMove.SrcOffset], AX
        MOV    AX, Word Ptr ES:[OvrHeader.XmsOffset+2]
        MOV    Word Ptr [XmsMove.SrcOffset+2], AX
        XOR    AX, AX
        MOV    [XmsMove.DestHandle], AX
        MOV    Word Ptr [XmsMove.DestOffset], AX
        MOV    AX, ES:[OvrHeader.LoadSeg]
        MOV    Word Ptr [XmsMove.DestOffset+2], AX
        MOV    AH, 11
        LEA    SI, XmsMove
        CALL   [XmsDriver]
        OR     AX, AX
        JZ     @@1
        DEC    AX
        JMP    @@2
@@1:    MOV    AX, ovrIOError
@@2:    POP    BP
        RETF   2
XmsReadFunc ENDP
;  Copy an overlaid unit from the heap to XMS
;  If successful, carry flag is cleared
;  In/Out:
;    BX:DI = offset into XMS memory block
CopyUnitToXms PROC
;  XMS requires that an even number of bytes is moved
        MOV    DX, ES:[OvrHeader.CodeSize]
        TEST   DX, 1
        JZ     @@1
        INC    DX
        INC    ES:[OvrHeader.CodeSize]
;  Get the fields of the XMS block move structure
@@1:    MOV    Word Ptr [XmsMove.BlkSize], DX
        XOR    AX, AX
        MOV    Word Ptr [XmsMove.BlkSize+2], AX
        MOV    [XmsMove.SrcHandle], AX
        MOV    Word Ptr [XmsMove.SrcOffset], AX
        MOV    AX, [OvrHeapOrg]
        MOV    Word Ptr [XmsMove.SrcOffset+2], AX
        MOV    AX, [OvrXmsHandle]
        MOV    [XmsMove.DestHandle], AX
        MOV    Word Ptr [XmsMove.DestOffset], DI
        MOV    Word Ptr [XmsMove.DestOffset+2], BX
        MOV    AH, 11
        LEA    SI, XmsMove
        CALL   [XmsDriver]
;  Bump code size
        ADD    DI, DX
        ADC    BX, 0
;  Check return code from XMS driver
        OR     AX, AX
        JZ     @@2
        CLC
        RETN
@@2:    STC
        RETN
CopyUnitToXms ENDP
OvrXmsLoad PROC
        PUSH   BP
        MOV    BP, SP
;  Walk the CodeList chain
;  First segment is PrefixSeg+10h+OvrCodeList
;  Push each element of overlaid unit list on the stack
;  Keep the size of the linked list in CX
        MOV    AX, [OvrCodeList]
        XOR    CX, CX
@@1:    ADD    AX, [PrefixSeg]
        ADD    AX, 10h
        MOV    ES, AX
        PUSH   AX
        INC    CX
        MOV    AX, ES:[OvrHeader.CodeListNext]
        OR     AX, AX
        JNZ    @@1
;  Loop:
;    Pop each element of the overlaid unit list from the stack
        XOR    BX, BX
        XOR    DI, DI
@@2:    POP    ES
        PUSH   CX
        MOV    AX, [OvrHeapOrg]
        MOV    ES:[OvrHeader.LoadSeg], AX
        MOV    Word Ptr ES:[OvrHeader.XmsOffset+2], BX
        MOV    Word Ptr ES:[OvrHeader.XmsOffset], DI
;  Load overlay from disk
        PUSH   BX
        PUSH   DI
        PUSH   ES
        PUSH   ES
        CALL   [OvrReadBuf]
        POP    ES
        POP    DI
        POP    BX
;  Flag unit as 'unloaded'; check return code
        MOV    ES:[OvrHeader.LoadSeg], 0
        NEG    AX
        JC     @@3
        CALL   CopyUnitToXms
        JC     @@3
        POP    CX
        LOOP   @@2
@@3:    MOV    SP, BP
        POP    BP
        RETN
OvrXMSLoad ENDP
OvrInitXMS PROC
;  Make sure the file's been opened
        XOR    AX, AX
        CMP    AX, [OvrDOSHandle]
        JNE    @@1
        DEC    AX                      ; ovrError
        JMP    @@5
;  Check presence of XMS driver
@@1:    MOV    AX, 4300h
        INT    2Fh
        CMP    AL, 80h
        JE     @@2
        MOV    AX, ovrNoXmsDriver
        JMP    @@5
;  Get XMS driver's entry point
@@2:    MOV    AX, 4310h
        INT    2Fh
        MOV    Word Ptr [XmsDriver], BX
        MOV    Word Ptr [XmsDriver+2], ES
        CALL   AllocateXms
        JNZ    @@3
        MOV    AX, ovrNoXMSMemory
        JMP    @@5
;  Load the overlay into XMS
@@3:    CALL   OvrXmsLoad
        JNC    @@4
;  An error occurred.  Release handle and XMS memory
        MOV    DX, [OvrXmsHandle]
        MOV    AH, 10
        CALL   [XmsDriver]
        MOV    AX, ovrIOError
        JMP    @@5
;  Close file
@@4:    MOV    BX, [OvrDOSHandle]
        MOV    AH, 3Eh
        INT    21h
;  OvrReadBuf := XmsReadFunc
        MOV    Word Ptr [OvrReadBuf], Offset XmsReadFunc
        MOV    Word Ptr [OvrReadBuf+2], CS
;  ExitSave := ExitProc
;  ExitProc := OvrXmsExit
        LES    AX, [ExitProc]
        MOV    Word Ptr [ExitSave], AX
        MOV    Word Ptr [ExitSave+2], ES
        MOV    Word Ptr [ExitProc], Offset OvrXmsExit
        MOV    Word Ptr [ExitProc+2], CS
;  Return result of initialisation
        XOR    AX, AX
@@5:    MOV    [OvrResult], AX
        RETF
OvrInitXMS ENDP
Code       ENDS
           END
[Back to DOS SWAG index] [Back to Main SWAG index] [Original]