home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / gnu / nethack-3.1 / sys / msdos / ovlmgr.asm < prev    next >
Encoding:
Assembly Source File  |  1993-01-18  |  45.4 KB  |  2,125 lines

  1. ;    SCCS Id: @(#)ovlmgr.asm         91/09/04
  2. ;  Copyright (c) 1989, 1990, 1991, 1992, 1993 Pierre Martineau and
  3. ;  Stephen Spackman.  All Rights Reserved.
  4. ;  This product may be freely redistributed.  See NetHack license for details.
  5.  
  6. VERSION     EQU    3100h
  7.  
  8.         PAGE    57,132
  9.         TITLE    'DOS Overlay Manager for MSC 5.1+'
  10.         SUBTTL    'Copyright (c) 1989, 1990, 1991, 1992, 1993 Pierre Martineau and Stephen Spackman. All Rights Reserved.'
  11.  
  12. ; Multiple overlay file support for v30a0 by Norm Meluch with some input from Stephen.
  13.  
  14. ; acknowledgements:   - Many thanks to Norm Meluch for his invaluable help
  15. ;              - No thanks to Microsoft
  16. ;              - alltrsidsctysti!!!
  17. ;              - izchak and friends for impetus
  18. ;              - us for brilliance
  19. ;              - coffee for speed
  20. ;              - others as necessary
  21.  
  22. ; assumptions:          - all registers are preserved including flags
  23. ;              - the stack is preserved
  24. ;              - re-entrancy is not required
  25.  
  26. ; options:          /Di386    use 80386-specific opcodes
  27. ;                (faster, but no good for weaker machines)
  28. ;              /DNOEMS    omit EMS support
  29. ;                (needed if application uses EMS)
  30. ;              /DNOSPLIT    omit support for external .OVL files
  31.  
  32. DOSALLOC    EQU    48h            ; memory allocation
  33. DOSFREE     EQU    49h            ; free allocated memory
  34. DOSREALLOC    EQU    4ah            ; modify memory block
  35. DOSREAD     EQU    3fh            ; read bytes from handle
  36. DOSSEEK     EQU    42h            ; logical handle seek
  37. DOSOPEN     EQU    3dh            ; open handle
  38. DOSCLOSE    EQU    3eh            ; close handle
  39. DOSSETDTA    EQU    1ah            ; Set Data transfer area
  40. DOSGETDTA    EQU    2fh            ; Get Data transfer area
  41. DOSSEARCH    EQU    4eh            ; Search for 1st file match
  42. DOSNEXTFILE    EQU    4fh            ; Search for next file match
  43. DOSEXEC     EQU    4bh            ; exec child process
  44. DOSPUTC     EQU    02h            ; print a char
  45. DOSVERSION    EQU    30h            ; get version number
  46. DOSGETVEC    EQU    35h            ; get interrupt vector
  47. DOSGETSWITCH    EQU    3700h            ; get DOS switchar
  48. DOS        EQU    21h            ; Dos interrupt #
  49. PRINT        EQU    09h            ; print string
  50. TERMINATE    EQU    4ch            ; terminate process
  51. EMM        EQU    67h            ; EMM handler int vector
  52. EMMSTATUS    EQU    40h            ; get EMM status
  53. EMMFRAME    EQU    41h            ; get EMM page frame
  54. EMMTOTALS    EQU    42h            ; get EMM pages available
  55. EMMALLOC    EQU    43h            ; allocate EMM pages
  56. EMMMAP        EQU    44h            ; map EMM pages
  57. EMMFREE     EQU    45h            ; free EMM pages
  58. MAXNAMESIZE    EQU    50h            ; max path name size
  59. MAXFILES    EQU    0Eh            ; max # of *.OVL files
  60. EXESIGNUM    EQU    5a4dh            ; Exe header signature
  61. CR        EQU    0dh
  62. LF        EQU    0ah
  63. ESCAPE        EQU    1bh
  64. BELL        EQU    07h
  65. PARSIZ        EQU    10h            ; this is the size of a paragraph - this better not change!
  66. FAERIE        EQU    00h            ; Used for dummy segment allocation
  67.  
  68. NOERR        EQU    0
  69. DOSERR        EQU    1
  70. FILEERR     EQU    2
  71. NOMEMERR    EQU    3
  72. FILEIOERR    EQU    4
  73. VICTIMERR    EQU    5
  74. RELERR        EQU    6
  75. EMSERR        EQU    7
  76. HDRERR        EQU    8
  77. NAMERR        EQU    9
  78. OVLERR        EQU    10
  79. NOHDRERR    EQU    11
  80.  
  81. ; The following EXTRNs are supplied by the linker
  82.  
  83. EXTRN        $$OVLBASE:BYTE            ; segment of OVERLAY_AREA
  84. EXTRN        $$MPGSNOVL:BYTE         ; ^ to module table
  85. EXTRN        $$MPGSNBASE:WORD        ; ^ to module segment fixups
  86. EXTRN        $$INTNO:BYTE            ; interrupt number to be used
  87. EXTRN        $$COVL:WORD            ; number of physical overlays
  88. EXTRN        $$CGSN:WORD            ; number of modules
  89. EXTRN        $$MAIN:FAR            ; ^ to function main()
  90.  
  91. PUBLIC        $$OVLINIT            ; Our entry point
  92.                         ; called by the c startup code
  93. IFDEF i386
  94. OP32        MACRO                ; 32 bit operand override
  95.         DB    066h
  96.         ENDM
  97.  
  98. pusha        MACRO                ; push all registers
  99.         DB    060h
  100.         ENDM
  101.  
  102. popa        MACRO                ; pop all registers
  103.         DB    061h
  104.         ENDM
  105. ENDIF
  106.  
  107. ovlflgrec    RECORD    locked:1=0,ems:1=0,loaded:1=0,file:4=0,pad:1 ; overlay flags
  108.         ; "file" is the overlay file this overlay is in; 0 is the .EXE
  109.         ; itself. Otherwise, the numbers are arbitrary.
  110.  
  111. ; This is a dirty hack. What we need is a virtual segment that will be built
  112. ; by the (our) loader in multiple copies, one per overlay. Unfortunately, this
  113. ; doesn't seem to be a sensible idea in the minds of the folks at Microsoft.
  114. ; Declaring this segment AT will ensure that it never appears in the exefile,
  115. ; and ASSUME is dumb enough to be fooled.
  116. ;
  117. ; The reason we want to do this is also not-to-be-tried-at-home: it turns out
  118. ; that we can code a faster interrupt handler if we map overlay numbers to
  119. ; segment values. Normally we would consider this unacceptable programming
  120. ; practise because it is 86-mode specific, but the *need* for this entire
  121. ; programme is 86-mode specific, anyway.
  122.  
  123. pspseg        SEGMENT PARA AT FAERIE        ; dummy segment for psp
  124.         ORG    2ch            ; ^ to segment of environmemt in psp
  125. pspenv        LABEL    WORD
  126. pspseg        ENDS
  127.  
  128. ovltbl        SEGMENT PARA AT FAERIE        ; Dummy segment definition for overlay table
  129.  
  130. ; NOTE: This segment definition MUST be exactly 16 bytes long
  131.  
  132. ovlflg        ovlflgrec    <0,0,0,0,0>     ; overlay flags
  133. ovlinvcnt    DB    ?            ; invocation count
  134. ovlmemblk    DW    ?            ; ^ to allocated memory block
  135. ovllrudat    DD    ?            ; misc lru data (pseudo time stamp)
  136. ovlemshdl    DW    ?            ; ovl ems memory handle
  137. ovlfiloff    DW    ?            ; ovl file offset in pages (512 bytes)
  138. ovlsiz        DW    ?            ; ovl size in paragraphs
  139. ovlhdrsiz    DW    ?            ; hdr size in paragraphs
  140.  
  141. IF1
  142. IF        ($ - ovlflg) GT PARSIZ
  143.         .ERR
  144.         %OUT This segment MUST be no more than 16 bytes, REALLY!!!
  145. ENDIF
  146. ENDIF
  147.  
  148. OVLSEGSIZ    EQU    PARSIZ            ; this had better be true!!! (16 bytes)
  149.  
  150. ovltbl        ENDS
  151.  
  152. DTASTRUC    STRUC                ; internal DTA for ovlmgr
  153.         DB    21 DUP (0)
  154. file_attr    DB    0
  155. file_time    DW    0
  156. file_date    DW    0
  157. file_size    DD    0
  158. file_name    DB    9 DUP (0)
  159. file_ext    DB    3 DUP (0)
  160. dtapad        DB    86 DUP (0)        ; Pad to 128 bytes
  161. DTASTRUC    ENDS
  162.  
  163. EXEHDR        STRUC                ; structure of an EXE header
  164. exesign     DW    EXESIGNUM        ; signature
  165. exelstpgesiz    DW    ?            ; last page size (512 byte pages)
  166. exesiz        DW    ?            ; total pages (including partial last page)
  167. relocitems    DW    ?            ; number of relocation entries
  168. hdrparas    DW    ?            ; number of paragraphs in the header
  169. minalloc    DW    ?            ; minimum paragraph allocation
  170. maxalloc    DW    ?            ; maximum patagraph allocation
  171. exess        DW    ?            ; initial stack segment
  172. exesp        DW    ?            ; initial stack pointer
  173. exechksum    DW    ?            ; checksum
  174. exeip        DW    ?            ; initial instruction pointer
  175. execs        DW    ?            ; initial code segment
  176. reloctbloff    DW    ?            ; offset from beginning of header to relocation table
  177. exeovlnum    DW    ?            ; overlay number
  178. EXEHDR        ENDS
  179.  
  180. MASK_used    EQU    1            ; memory block flag
  181.  
  182. MEMCTLBLK    STRUC                ; memory block structure
  183. memblkflg    DB    ?            ; flags
  184. memblkpad1    DB    ?            ; go ahead, delete me!
  185. memblknxt    DW    ?            ; ^ to next block
  186. memblkprv    DW    ?            ; ^ to previous block
  187. memblkovl    DW    ?            ; ^ to overlay occupying this block
  188. memblksiz    DW    ?            ; size in paragraphs
  189. memblkpad    DB    PARSIZ - memblkpad MOD PARSIZ DUP (?) ; pad to 16 bytes
  190. MEMCTLBLK    ENDS
  191.  
  192. MEMCTLBLKSIZ    EQU    TYPE MEMCTLBLK / PARSIZ ; should equal 1 paragraph
  193.  
  194. ;-------------------------------------------------------------------------------
  195.  
  196. code        SEGMENT PUBLIC
  197.  
  198. ; NOTE: the following order is optimum for alignment purposes across the
  199. ;    entire INTEL 80x86 family of processors.
  200.  
  201. ovltim        DD    ?            ; pseudo-lru time variable
  202. farcall     DD    ?            ; internal trampoline.
  203. oldvec        DD    -1            ; saved interrupt vector
  204. oldint21    DD    -1            ; saved int 21 vector
  205. sireg        DW    ?            ; temp save area
  206. IFDEF i386
  207.         DW    ?            ; for esi
  208. ENDIF
  209. dsreg        DW    ?            ; temp save area
  210. ssreg        DW    ?
  211. spreg        DW    ?
  212. ovlfilhdl    DW    MAXFILES+1 DUP (-1)      ; always-open file handles for .EXE, .OVL
  213. ovltblbse    DW    -1            ; segment of first overlay descriptor
  214. memblks     DW    16 DUP (-1)        ; allocated memory blocks
  215. memblk1st    DW    ?            ; first memory block
  216. emsmemblks    DW    16 DUP (-1)        ; ems allocated memory blocks (64K each)
  217. curemshandle    DW    -1            ; currently mapped handle
  218. ovlcnt        DW    ?            ; # overlays
  219. modcnt        DW    ?            ; # of modules
  220. ovlrootcode    DW    ?            ; logical segment of OVERLAY_AREA
  221. ovldata     DW    ?            ; logical segment of OVERLAY_END
  222. pspadd        DW    ?            ; our psp address + 10h (for relocations)
  223. emsframe    DW    ?            ; EMM page frame segment
  224. moduletbl    DD    256 DUP (?)        ; module lookup table (256 modules)
  225. curovl        DW    OFFSET stkframe     ; ^ into stack frame
  226. stkframe    DW    256*3 DUP (?)        ; internal stack (256 ovls deep)
  227. tempmem     DW    16 DUP (-1)        ; temp mem block storage
  228. intnum        DW    ?            ; ovlmgr int number
  229. hdr        EXEHDR    <>            ; EXE header work area
  230.         DB    512-TYPE EXEHDR DUP (?) ; exe hdr buffer for relocations
  231. EXEHDRTMPSIZ    EQU    $ - hdr         ; size of temp reloc buffer
  232. filestring    DB    MAXNAMESIZE DUP (0)    ; string space for file specs
  233. pathlen        DW    ?            ; path length of file spec
  234. namelen        DW    ?            ; length of file names
  235. ovldta        DTASTRUC <>            ; DTA for ovlmgr use
  236. dtaseg        DW    ?            ; DTA segment for program
  237. dtaoffset    DW    ?            ; DTA offset for program
  238. errortbl    DW    -1            ; error message pointers
  239.         DW    OFFSET baddos
  240.         DW    OFFSET nofile
  241.         DW    OFFSET noroom
  242.         DW    OFFSET badio
  243.         DW    OFFSET nocore
  244.         DW    OFFSET nocore
  245.         DW    OFFSET badems
  246.         DW    OFFSET badhdr
  247.         DW    OFFSET badnam
  248.         DW    OFFSET noovl
  249.         DW    OFFSET nohdr
  250.         DW    OFFSET unknown
  251.         DW    OFFSET unknown
  252.         DW    OFFSET unknown
  253.         DW    OFFSET unknown
  254. emmname     DB    "EMMXXXX0"              ; EMM device driver name
  255. emmtot        DW    0            ; total emm blocks free
  256. emmframesiz    DW    4            ; frame size in blocks
  257. emmflg        DB    0            ; EMM present flag
  258.  
  259. i386code    DB    '386 specific code enabled.',CR,LF,'$'
  260. memavl        DB    'Conventional memory available: $'
  261. paragraphs    DB    'H paragraphs.',CR,LF,'$'
  262. emsavl        DB    'EMS memory available: $'
  263. pages        DB    'H 16K-pages.',CR,LF,'$'
  264. baddos        DB    'Incorrect DOS version. Must be 3.00 or later.$'
  265. nofile        DB    'Inaccessible EXE file. Can',39,'t load overlays.$'
  266. noroom        DB    'Not enough free memory left to run this program.$'
  267. badio        DB    'File I/O error.$'
  268. nocore        DB    'Internal memory allocation failure.$'
  269. badems        DB    'EMS memory manager error.$'
  270. badhdr        DB    'Executable or overlay header missing or damaged.$'
  271. badnam        DB    'Unable to resolve overlay file names.$'
  272. noovl        DB    'Inaccessible OVL file. Can',39,'t load overlays.$'
  273. nohdr        DB    'Incomplete executable.  OVL files missing?$'
  274. unknown     DB    'Unknown error!$'
  275. msghead     DB    ESCAPE,'[0m',ESCAPE,'[K',CR,LF,ESCAPE,'[K',ESCAPE,'[1mOVLMGR:',ESCAPE,'[0m $'
  276. diag        DB    ESCAPE,'[K',CR,LF,ESCAPE,'[K','        ($'
  277. msgtail     DB    ESCAPE,'[K',CR,LF,ESCAPE,'[K',BELL,'$'
  278. ovlext        DB    '?.OVL',0
  279.  
  280. ;-------------------------------------------------------------------------------
  281.  
  282. $$OVLINIT    PROC    FAR            ; Init entry point
  283.  
  284.         ASSUME    CS:code,DS:pspseg,ES:NOTHING
  285.  
  286.         push    ax
  287.         push    bx
  288.         push    cx
  289.         push    dx
  290.         push    si
  291.         push    di
  292.         push    bp
  293.         push    ds
  294.         push    es            ; save the world
  295.  
  296.         cld
  297.         mov    ax,ds            ; get our psp
  298.         add    ax,10h
  299.         mov    pspadd,ax        ; save it
  300.         mov    ah,DOSVERSION
  301.         int    DOS
  302.         cmp    al,3            ; DOS 3.0 or later
  303.         jnc    doenvthing
  304.         mov    al,DOSERR        ; incorrect version of dos
  305.         jmp    putserr
  306. doenvthing:
  307.         mov    ds,pspenv        ; get environment segment
  308.         mov    si,-1
  309. envloop:                    ; search for end of environment
  310.         inc    si
  311.         cmp    WORD PTR [si],0
  312.         jnz    envloop
  313.         add    si,4            ; point to EXE filename
  314.  
  315.         call    openfiles        ; Search & open overlay files
  316. IFNDEF NOEMS
  317. chkems:
  318.         mov    ah,DOSGETVEC
  319.         mov    al,EMM
  320.         int    DOS
  321.         mov    ax,cs
  322.         mov    ds,ax
  323.         mov    di,0ah
  324.         mov    si,OFFSET emmname
  325.         mov    cx,8
  326.         repe    cmpsb
  327.         mov    al,0
  328.         jnz    setemmflg
  329.         mov    al,-1
  330. setemmflg:
  331.         mov    emmflg,al
  332.         jnz    noemshere
  333.         mov    ah,EMMFRAME
  334.         int    EMM
  335.         mov    emsframe,bx
  336.         mov    ah,EMMTOTALS
  337.         int    EMM
  338.         mov    emmtot,bx
  339. noemshere:
  340. ENDIF
  341.         mov    ax,SEG $$OVLBASE    ; OVERLAY_AREA segment
  342.         mov    ovlrootcode,ax
  343.         mov    ax,SEG $$COVL        ; segment of DGROUP
  344.         mov    ds,ax
  345.         mov    bx,$$CGSN        ; number of modules
  346.         mov    modcnt,bx        ; save for later use
  347.         mov    bx,$$COVL        ; number of physical overlays
  348.         mov    ovlcnt,bx        ; save for later use
  349.  
  350. ; Now allocate memory
  351.         mov    ah,DOSALLOC        ; bx contains # paras needed for ovltbl
  352.         int    DOS
  353.         jnc    gotovlram
  354.         jmp    buyram
  355. gotovlram:
  356.         mov    ovltblbse,ax        ; overlay descriptor table begins at start of memory block
  357.  
  358.         mov    cx,ovlcnt
  359. zeromem:
  360.         mov    es,ax
  361.         mov    es:ovlflg,0        ; initialise ovl flags
  362.         mov    es:ovlinvcnt,0        ; initialise invocation count
  363.         mov    es:ovlmemblk,0
  364.         mov    WORD PTR es:ovllrudat,0     ; initialise ovl lru
  365.         mov    WORD PTR es:ovllrudat+2,0
  366.         mov    es:ovlemshdl,-1
  367.         mov    es:ovlfiloff,0        ; initialize file offset
  368.         mov    es:ovlsiz,0        ; initialize overlay size
  369.         mov    es:ovlhdrsiz,0
  370.         inc    ax
  371.         loop    zeromem        
  372.  
  373.         mov    ax,cs
  374.         mov    ds,ax
  375. IFDEF DEBUG
  376. IFDEF i386
  377.         mov    ah,print
  378.         mov    dx,OFFSET msghead
  379.         int    DOS
  380.         mov    ah,print
  381.         mov    dx,OFFSET i386code
  382.         int    DOS
  383. ENDIF
  384.         mov    ah,print
  385.         mov    dx,OFFSET msghead
  386.         int    DOS
  387.         mov    ah,print
  388.         mov    dx,OFFSET memavl
  389.         int    DOS
  390.         mov    ax,0a000h
  391.         sub    ax,ovltblbse
  392.         call    itoa
  393.         mov    ah,print
  394.         mov    dx,OFFSET paragraphs
  395.         int    DOS
  396. IFNDEF NOEMS
  397.         mov    ah,print
  398.         mov    dx,OFFSET msghead
  399.         int    DOS
  400.         mov    ah,print
  401.         mov    dx,OFFSET emsavl
  402.         int    DOS
  403.         mov    ax,emmtot
  404.         call    itoa
  405.         mov    ah,print
  406.         mov    dx,OFFSET pages
  407.         int    DOS
  408. ENDIF
  409. ENDIF
  410.         ASSUME    ES:ovltbl
  411.  
  412.         xor    bp,bp
  413.         xor    di,di
  414.         xor    si,si            ; file handle loop ctr
  415. filsegtbllpp:                    ; initialise ovl table
  416.         call    gethdr            ; get an EXE header
  417.  
  418.         mov    ax,ovltblbse
  419.         add    ax,hdr.exeovlnum
  420.         mov    es,ax            ; ^ to ovl table entry
  421. IFNDEF NOSPLIT
  422.         mov    cx,si            ; set file # in ovlflg
  423.         shl    cx,1
  424.         mov    ovlflg,cl
  425. ENDIF
  426.         mov    ax,hdr.exesiz
  427.         shl    ax,1
  428.         shl    ax,1
  429.         shl    ax,1
  430.         shl    ax,1
  431.         shl    ax,1            ; * 32
  432.         mov    dx,hdr.exelstpgesiz
  433.         or    dx,dx
  434.         jz    emptypage
  435.         shr    dx,1
  436.         shr    dx,1
  437.         shr    dx,1
  438.         shr    dx,1            ; / 16
  439.         inc    dx
  440.         sub    ax,20h
  441.         add    ax,dx
  442. emptypage:
  443.         sub    ax,hdr.hdrparas     ; actual size of code
  444.         mov    ovlsiz,ax        ; overlay size in paragraphs
  445.         cmp    hdr.exeovlnum,0     ; skip if ovl 0 (root code)
  446.         jz    notlargest
  447.         cmp    ax,di            ; find largest ovl
  448.         jc    notlargest
  449.         mov    di,ax
  450. notlargest:
  451.         mov    ax,hdr.hdrparas
  452.         shl    ax,1
  453.         shl    ax,1
  454.         shl    ax,1
  455.         shl    ax,1
  456.         mov    ovlhdrsiz,ax        ; hdr size in bytes
  457.         mov    ovlfiloff,bp        ; initialise ovl file offset
  458.         add    bp,hdr.exesiz        ; ^ to next overlay
  459.         mov    dx,bp
  460.         mov    cl,dh
  461.         mov    dh,dl
  462.         xor    ch,ch
  463.         xor    dl,dl
  464.         shl    dx,1
  465.         rcl    cx,1            ; cx:dx = bp * 512
  466.         mov    al,0
  467.         mov    ah,DOSSEEK        ; seek to next ovl
  468.         int    DOS
  469.  
  470.         mov    cx,ovlcnt        ; check if all overlays found
  471.         mov    ax,ovltblbse
  472.         dec    cx            ; ovlcnt includes root
  473.         add    ax,cx
  474. ovloop:
  475.         mov    es,ax
  476. IFNDEF NOSPLIT
  477.         mov    bl,ovlflg
  478.         and    bx,MASK file
  479.  
  480.         cmp    bx,0            ; if file # is 0
  481.         jne    again
  482. ENDIF
  483.         cmp    ovlfiloff,0        ; and offset is 0
  484.         jne    again
  485.         jmp    filsegtbllpp        ; then we're still looking
  486. again:
  487.         dec    ax
  488.         loop    ovloop
  489.  
  490.         ASSUME    ES:nothing        ; prepare first memory block
  491.  
  492.         mov    ax,ovlrootcode        ; OVERLAY_AREA segment
  493.         mov    memblk1st,ax        ; save pointer to first mem block
  494.         mov    es,ax
  495.         mov    es:memblkflg,0        ; clear mem flags
  496.         mov    es:memblknxt,0        ; set next to nothing
  497.         mov    es:memblkprv,0        ; set previous to nothing
  498.         mov    es:memblkovl,0        ; no overlay loaded
  499.         mov    es:memblksiz,di     ; di contains OVERLAY_AREA size in paragraphs
  500.         add    ax,di
  501.         mov    ovldata,ax        ; end of OVERLAY_END
  502.         push    di
  503.         mov    es,ovltblbse        ; temporary
  504.         call    getemsmem        ; see if any ems available
  505.         mov    es:ovlemshdl,-1     ; fix these!
  506.         and    es:ovlflg,NOT MASK ems
  507.         push    dx
  508.         call    getmoreram        ; see if there are any other pieces lying around
  509.         pop    ax
  510.         pop    di
  511.         or    ax,ax            ; any ems?
  512.         jnz    noramcheck
  513.         inc    di
  514.         cmp    dx,di
  515.         jc    buyram
  516. noramcheck:
  517.         mov    WORD PTR ovltim,0    ; initialise global lru time stamp
  518.         mov    WORD PTR ovltim+2,0
  519.         mov    di,OFFSET stkframe
  520.         mov    WORD PTR cs:[di],-1    ; initialise stack frame
  521.         add    di,6
  522.         mov    ax,ovltblbse
  523.         mov    cs:[di],ax
  524.         mov    curovl,di        ; initialise stack frame pointer
  525.         mov    es,ax
  526.         mov    es:ovlflg,MASK locked OR MASK loaded ; set flags on ovl 0
  527.         jmp    short chgintvec
  528. buyram:
  529.         mov    al,NOMEMERR        ; free up some TSRs or something
  530.         jmp    putserr
  531. chgintvec:
  532.         mov    ax,SEG $$INTNO
  533.         mov    ds,ax
  534.         mov    al,$$INTNO        ; get int number to use
  535.         xor    ah,ah
  536.         shl    ax,1
  537.         shl    ax,1
  538.         mov    intnum,ax
  539.         call    setvectors        ; set up interrupt vectors
  540.         mov    cx,modcnt        ; module count
  541.         mov    ax,SEG $$MPGSNBASE
  542.         mov    es,ax
  543.         mov    ax,cs
  544.         mov    ds,ax
  545.  
  546.         ASSUME    DS:code
  547.  
  548.         mov    bx,OFFSET $$MPGSNBASE    ; ^ to linker provided overlay segment fixups
  549.         mov    si,OFFSET $$MPGSNOVL    ; ^ to linker provided module table
  550.         mov    di,OFFSET moduletbl    ; ^ to our module table
  551. modloop:
  552.         mov    al,es:[si]        ; real physical ovl number
  553.         xor    ah,ah
  554.         add    ax,ovltblbse        ; ovlctlseg address
  555.         mov    [di],ax         ; save in module table
  556.         mov    ax,es:[bx]        ; get seg fixup
  557.         sub    ax,ovlrootcode        ; adjust for relative reference
  558.         mov    [di+2],ax        ; save in module table
  559.         add    di,4
  560.         add    bx,2
  561.         inc    si
  562.         loop    modloop
  563.         pop    es
  564.         pop    ds
  565.         pop    bp
  566.         pop    di
  567.         pop    si
  568.         pop    dx
  569.         pop    cx
  570.         pop    bx
  571.         pop    ax            ; restore the world
  572.         jmp    $$MAIN            ; And away we go!
  573.  
  574. $$OVLINIT    ENDP
  575.  
  576. ;-------------------------------------------------------------------------------
  577.  
  578. ovlmgr        PROC    FAR            ; This is the it!
  579.  
  580.         ASSUME    DS:NOTHING,ES:NOTHING
  581.  
  582. IFDEF i386
  583.         OP32
  584. ENDIF
  585.         mov    sireg,si        ; preserve si
  586.         mov    dsreg,ds        ; and ds
  587.         pop    si            ; retrieve caller ip
  588.         pop    ds            ;     "      "    cs
  589.         push    ax
  590.         push    bx
  591.         cld
  592.         lodsb                ; module # to call
  593.         xor    ah,ah
  594.         mov    bx,ax
  595.         lodsw                ; offset in ovl to call
  596.         mov    WORD PTR farcall,ax    ; into trampoline
  597.         mov    ax,si
  598.         mov    si,curovl        ; get stack frame pointer
  599.         add    si,6            ; update stack
  600.         mov    cs:[si-4],ds        ; save return seg
  601.         mov    cs:[si-2],ax        ; and return offset
  602.  
  603.         shl    bx,1
  604.         shl    bx,1            ; * 4 (2 words/entry in module tbl)
  605.         add    bx,OFFSET moduletbl
  606.         mov    ds,cs:[bx]        ; ovl tbl entry
  607.         mov    ax,cs:[bx+2]        ; segment fixup
  608.         mov    cs:[si],ds        ; ovl entry into stack frame
  609.         mov    curovl,si
  610.  
  611.         ASSUME    DS:ovltbl
  612.  
  613. IFDEF i386
  614.         OP32
  615. ENDIF
  616.         mov    si,WORD PTR ovltim    ; lru time stamp
  617. IFDEF i386
  618.         OP32
  619. ENDIF
  620.         inc    si            ; time passes!
  621. IFDEF i386
  622.         OP32
  623. ENDIF
  624.         mov    WORD PTR ovltim,si    ; update global clock
  625. IFDEF i386
  626.         OP32
  627. ENDIF
  628.         mov    WORD PTR ovllrudat,si    ; as well as ovl clock
  629. IFNDEF i386
  630.         mov    si,WORD PTR ovltim+2
  631.         jz    ininc            ; dword increment
  632. cryupcdon:
  633.         mov    WORD PTR ovllrudat+2,si ; as well as ovl clock
  634. ENDIF
  635.         test    ovlflg,MASK loaded    ; ovl loaded?
  636.         jz    inload            ; load it or map it then.
  637. ovlloadedupc:
  638.         inc    ovlinvcnt
  639.         add    ax,ovlmemblk        ; add fixup and segment address
  640.         mov    WORD PTR farcall+2,ax    ; into trampoline
  641. IFDEF i386
  642.         OP32
  643. ENDIF
  644.         mov    si,sireg        ; retore all registers
  645.         mov    ds,dsreg
  646.         pop    bx
  647.         pop    ax
  648.         popf                ; don't forget these!
  649.         call    DWORD PTR farcall    ; and GO
  650.         pushf                ; preserve registers again!
  651.         mov    dsreg,ds
  652. IFDEF i386
  653.         OP32
  654. ENDIF
  655.         mov    sireg,si
  656.         mov    si,curovl        ; stack frame pointer
  657.         mov    ds,cs:[si]
  658.         dec    ovlinvcnt
  659.         sub    si,6            ; adjust stack
  660.         mov    ds,cs:[si]        ; retrieve ovl tbl entry
  661.         push    cs:[si+2]        ; set return address
  662.         push    cs:[si+4]
  663.         mov    curovl,si
  664. IFDEF i386
  665.         OP32
  666. ENDIF
  667.         mov    si,WORD PTR ovltim    ; do the lru thing again
  668. IFDEF i386
  669.         OP32
  670. ENDIF
  671.         inc    si
  672. IFDEF i386
  673.         OP32
  674. ENDIF
  675.         mov    WORD PTR ovltim,si
  676. IFDEF i386
  677.         OP32
  678. ENDIF
  679.         mov    WORD PTR ovllrudat,si
  680. IFNDEF i386
  681.         mov    si,WORD PTR ovltim+2
  682.         jz    outinc
  683. crydncdon:
  684.         mov    WORD PTR ovllrudat+2,si
  685. ENDIF
  686.         test    ovlflg,MASK loaded    ; ovl loaded?
  687.         jz    outload         ; better get it before someone notices
  688. jmpback:
  689. IFDEF i386
  690.         OP32
  691. ENDIF
  692.         mov    si,sireg        ; get registers back
  693.         mov    ds,dsreg
  694.         iret                ; and GO back
  695.  
  696. IFNDEF i386
  697. ininc:
  698.         inc    si
  699.         mov    WORD PTR ovltim+2,si    ; update global and
  700.         jmp    cryupcdon
  701. ENDIF
  702.  
  703. inload:
  704.         test    ovlflg,MASK ems
  705.         jz    infile
  706.         push    ax
  707.         mov    ax,ovlemshdl
  708.         call    mappage
  709.         pop    ax
  710.         jmp    ovlloadedupc
  711. infile:
  712.         call    loadoverlay        ; self explanatory
  713.         jmp    ovlloadedupc
  714.  
  715. IFNDEF i386
  716. outinc:
  717.         inc    si
  718.         mov    WORD PTR ovltim+2,si
  719.         jmp    crydncdon
  720. ENDIF
  721.  
  722. outload:
  723.         test    ovlflg,MASK ems
  724.         jz    outfile
  725.         push    ax
  726.         mov    ax,ovlemshdl
  727.         call    mappage
  728.         pop    ax
  729.         jmp    jmpback
  730. outfile:
  731.         call    loadoverlay
  732.         jmp    jmpback
  733.  
  734. ovlmgr        ENDP
  735.  
  736. ;-------------------------------------------------------------------------------
  737.  
  738. loadoverlay    PROC    NEAR            ; load overlay pointed to by es
  739.  
  740.         ASSUME    DS:NOTHING,ES:ovltbl
  741.  
  742. IFDEF i386
  743.         OP32
  744.         pusha                   ; eax,ecx,edx,ebx,esp,ebp,esi,edi
  745. ELSE
  746.         push    ax
  747.         push    cx
  748.         push    dx
  749.         push    bx
  750.         push    bp
  751.         push    si
  752.         push    di
  753. ENDIF
  754.         push    ds
  755.         push    es            ; just in case
  756.         mov    ax,ds
  757.         mov    es,ax
  758.         cmp    ovlinvcnt,0
  759.         jnz    fxdadr            ; Yup, it's a toughie
  760.         mov    ax,ovlsiz        ; How much?
  761.         call    getpages        ; never fail mem alloc, you bet.
  762.         jmp    gleaner
  763. fxdadr:
  764.         call    releasepages        ; free memory where this ovl should be loaded
  765. gleaner:
  766.         add    ax,MEMCTLBLKSIZ     ; skip mem ctl blk
  767.         mov    ovlmemblk,ax        ; memory block to use
  768.         mov    ds,ax
  769.         mov    dx,ovlfiloff        ; where in the file is it?
  770.         mov    cl,dh
  771.         mov    dh,dl
  772.         xor    ch,ch
  773.         xor    dl,dl
  774.         shl    dx,1
  775.         rcl    cx,1            ; cx:dx = dx * 512
  776.         mov    ax,ovlhdrsiz
  777.         push    cx
  778.         push    dx
  779.         add    dx,ax
  780.         adc    cx,0            ; position to code
  781.         mov    ah,DOSSEEK        ; lseek to code
  782.         mov    al,0            ; from beginning of file
  783.         mov    bl,ovlflg
  784.         and    bx,MASK file
  785.         mov    bx,ovlfilhdl[bx]     ; never closing handle
  786.         int    DOS
  787.         jc    burnhead        ; oops!
  788.         xor    dx,dx            ; buf = ds:0
  789.         mov    cx,ovlsiz        ; number of paragraphs to load
  790.         shl    cx,1
  791.         shl    cx,1
  792.         shl    cx,1
  793.         shl    cx,1            ; * 16 = number of bytes
  794.         mov    ah,DOSREAD        ; prevent random DOS behaviour
  795.         int    DOS            ; read in code
  796.         jc    burnhead        ; double oops!
  797.         pop    dx
  798.         pop    cx            ; position of hdr
  799.         mov    ah,DOSSEEK        ; lseek to hdr
  800.         mov    al,0            ; from beginning of file
  801.         mov    bl,ovlflg
  802.         and    bx,MASK file
  803.         mov    bx,ovlfilhdl[bx]     ; never closing handle
  804.         int    DOS
  805.         jc    burnhead        ; oops!
  806.         mov    cx,EXEHDRTMPSIZ     ; reloc buffer size
  807.         mov    dx,OFFSET hdr
  808.         push    ds
  809.         mov    ax,cs
  810.         mov    ds,ax
  811.         mov    ah,DOSREAD        ; prevent random DOS behaviour
  812.         int    DOS            ; read in header
  813.         pop    ds
  814.         jc    burnhead        ; double oops!
  815.  
  816.         call    ovlrlc            ; perform relocation normally done by DOS EXE loader
  817.         pop    es            ; retrieve ovl tbl entry
  818.         pop    ds
  819.  
  820.         ASSUME    DS:ovltbl,ES:NOTHING
  821.  
  822.         or    ovlflg,MASK loaded    ; because it is now
  823. IFDEF i386
  824.         OP32
  825.         popa
  826. ELSE
  827.         pop    di
  828.         pop    si
  829.         pop    bp
  830.         pop    bx
  831.         pop    dx
  832.         pop    cx
  833.         pop    ax
  834. ENDIF
  835.         ret
  836.  
  837. burnhead:
  838.         mov    al,FILEIOERR        ; some kind of I/O error
  839.         jmp    putserr
  840.  
  841. loadoverlay    ENDP
  842.  
  843. ;-------------------------------------------------------------------------------
  844.  
  845. ovlrlc        PROC    NEAR            ; ds:0 -> the overlay to relocate
  846.  
  847.         ASSUME    DS:NOTHING,ES:ovltbl
  848.  
  849.         mov    si,OFFSET hdr
  850.         mov    bp,si
  851.         add    bp,EXEHDRTMPSIZ     ; ^ to end of buf+1
  852.         mov    cx,cs:[si.relocitems]    ; roto-count
  853.         jcxz    relocdone        ; not such a good idea, after all
  854.         mov    di,ds
  855.         sub    di,ovlrootcode        ; segment fixup value
  856.         add    si,cs:[si.reloctbloff]    ; ^ relocation table
  857. dorelocs:                    ; labels don't GET comments
  858.         cmp    si,bp            ; past the end ?
  859.         jc    getoffsetl
  860.         call    getnxtreloc        ; get another hunk
  861. getoffsetl:
  862.         mov    bl,cs:[si]        ; offset into load module
  863.         inc    si
  864.         cmp    si,bp            ; past the end ?
  865.         jc    getoffseth
  866.         call    getnxtreloc        ; get another hunk
  867. getoffseth:
  868.         mov    bh,cs:[si]        ; offset into load module
  869.         inc    si
  870.         cmp    si,bp            ; past the end ?
  871.         jc    getsegmentl
  872.         call    getnxtreloc        ; get another hunk
  873. getsegmentl:
  874.         mov    al,cs:[si]        ; segment in load module (zero reference)
  875.         inc    si
  876.         cmp    si,bp            ; past the end ?
  877.         jc    getsegmenth
  878.         call    getnxtreloc        ; get another hunk
  879. getsegmenth:
  880.         mov    ah,cs:[si]        ; segment in load module (zero reference)
  881.         inc    si
  882.         add    ax,pspadd        ; now it is psp relative
  883.         add    ax,di            ; and now it is relative to the actual load address
  884.         mov    ds,ax
  885.         mov    ax,[bx]            ; pickup item to relocate
  886.         add    ax,pspadd        ; make it psp relative
  887.         cmp    ax,ovlrootcode        ; is it below the OVERLAY_AREA?
  888.         jc    reloccomputed        ; yup. it's relocated
  889.         cmp    ax,ovldata        ; is it above OVERLAY_AREA
  890.         jnc    reloccomputed        ; yup. it's relocated
  891.         add    ax,di            ; it's in OVERLAY_AREA, this one's ours.
  892. reloccomputed:
  893.         mov    [bx],ax            ; RAM it home!?!
  894.         loop    dorelocs        ; what goes around, comes around.
  895. relocdone:    ret
  896.  
  897. ovlrlc        ENDP
  898.  
  899. ;-------------------------------------------------------------------------------
  900.  
  901. getnxtreloc    PROC    NEAR
  902.  
  903.         ASSUME    DS:NOTHING,ES:ovltbl
  904.  
  905.         push    bx
  906.         push    cx
  907.         push    di
  908.         push    bp
  909.         push    ds
  910.         push    es
  911.         mov    cx,EXEHDRTMPSIZ     ; reloc buffer size
  912.         mov    dx,OFFSET hdr
  913.         mov    ax,cs
  914.         mov    ds,ax
  915.         mov    bl,ovlflg
  916.         and    bx,MASK file
  917.         mov    bx,ovlfilhdl[bx]     ; never closing handle
  918.         mov    ah,DOSREAD        ; prevent random DOS behaviour
  919.         int    DOS            ; read in header
  920.         jnc    nxtrelocok
  921.         jmp    burnhead        ; double oops!
  922. nxtrelocok:
  923.         mov    si,OFFSET hdr
  924.         pop    es
  925.         pop    ds
  926.         pop    bp
  927.         pop    di
  928.         pop    cx
  929.         pop    bx
  930.         ret
  931.  
  932. getnxtreloc    ENDP
  933.  
  934. ;-------------------------------------------------------------------------------
  935.  
  936. getvictim    PROC    NEAR            ; select a victim to discard (and free up some memory)
  937.  
  938.         ASSUME    DS:ovltbl,ES:NOTHING
  939.  
  940.         push    bx
  941.         push    cx
  942.         push    dx
  943.         push    si
  944.         push    di
  945.         push    bp
  946.         push    ds
  947.         mov    ds,ovltblbse        ; ^ ovl tbl
  948. IFDEF i386
  949.         OP32
  950. ENDIF
  951.         xor    ax,ax            ; will contain the low word of lru
  952. IFDEF i386
  953.         OP32
  954. ENDIF
  955.         mov    dx,ax            ; will contain the high word of lru
  956.         mov    bp,ax            ; will contain ovl tbl entry
  957.         mov    bx,ax            ; ovl tbl ptr
  958.         mov    cx,ovlcnt
  959. foon1:
  960.         test    ovlflg[bx],MASK locked
  961.         jnz    skip1
  962.         test    ovlflg[bx],MASK ems
  963.         jnz    foon2
  964.         test    ovlflg[bx],MASK loaded
  965.         jz    skip1
  966. foon2:
  967. IFDEF i386
  968.         OP32
  969. ENDIF
  970.         mov    si,WORD PTR ovltim
  971. IFNDEF i386
  972.         mov    di,WORD PTR ovltim+2
  973. ENDIF
  974. IFDEF i386
  975.         OP32
  976. ENDIF
  977.         sub    si,WORD PTR ovllrudat[bx]
  978. IFNDEF i386
  979.         sbb    di,WORD PTR ovllrudat[bx+2]
  980. ENDIF
  981. IFDEF i386
  982.         OP32
  983.         cmp    dx,si
  984. ELSE
  985.         cmp    dx,di
  986. ENDIF
  987. IFDEF i386
  988.         jnc    skip1
  989. ELSE
  990.         jc    better1
  991.         jnz    skip1
  992.         cmp    ax,si
  993.         jnc    skip1
  994. ENDIF
  995. better1:
  996. IFDEF i386
  997.         OP32
  998.         mov    dx,si
  999. ELSE
  1000.         mov    ax,si
  1001.         mov    dx,di
  1002. ENDIF
  1003.         mov    bp,bx
  1004. skip1:
  1005.         add    bx,OVLSEGSIZ
  1006.         loop    foon1
  1007.         or    bp,bp            ; were we more successful this time?
  1008.         jnz    gotvictim        ; now we got one.
  1009. nomoremem:
  1010.         mov    al,VICTIMERR        ; were really %$# now!
  1011.         jmp    putserr
  1012. gotvictim:
  1013.         shr    bp,1            ; convert offset to segment
  1014.         shr    bp,1
  1015.         shr    bp,1
  1016.         shr    bp,1
  1017.         mov    ax,ds
  1018.         add    ax,bp
  1019.         pop    ds
  1020.         pop    bp
  1021.         pop    di
  1022.         pop    si
  1023.         pop    dx
  1024.         pop    cx
  1025.         pop    bx
  1026.         ret
  1027.  
  1028. getvictim    ENDP
  1029.  
  1030. ;-------------------------------------------------------------------------------
  1031.  
  1032. int21        PROC    FAR
  1033.  
  1034. ; free almost all overlay memory if app. tries to call the DOS exec function.
  1035.  
  1036.         cmp    ah,DOSEXEC
  1037.         jz    freeall
  1038.         cmp    ah,TERMINATE
  1039.         jz    saybyebye
  1040. notours:
  1041.         jmp    cs:oldint21
  1042. saybyebye:
  1043.         mov    al,NOERR        ; return code 0
  1044.         jmp    putserr
  1045. freeall:
  1046.         or    al,al            ; is it load and exec?
  1047.         jnz    notours
  1048.         push    ax
  1049.         push    cx
  1050.         push    dx
  1051.         push    bx
  1052.         push    bp
  1053.         push    si
  1054.         push    di
  1055.         push    es
  1056.         push    ds            ; preserve calling env.
  1057.  
  1058.         ASSUME    DS:NOTHING,ES:ovltbl
  1059.  
  1060.         mov    es,ovltblbse
  1061.         mov    cx,ovlcnt        ; unload all overlays that are
  1062.         mov    bx,OVLSEGSIZ        ; in EMS or are in alloced mem.
  1063.         dec    cx
  1064. memunloadlp:
  1065.         test    [bx.ovlflg],MASK ems
  1066.         jnz    memunload
  1067.         test    [bx.ovlflg],MASK loaded
  1068.         jz    nxtmemunload
  1069.         mov    ax,[bx.ovlmemblk]
  1070.         sub    ax,MEMCTLBLKSIZ
  1071.         cmp    ax,memblks        ; allocated memory ?
  1072.         jc    nxtmemunload
  1073. memunload:
  1074.         and    [bx.ovlflg],NOT MASK loaded ; you're outta there!
  1075. nxtmemunload:
  1076.         add    bx,OVLSEGSIZ
  1077.         loop    memunloadlp
  1078.  
  1079.         mov    curemshandle,-1     ; no current handle anymore
  1080.  
  1081.         mov    ax,memblks
  1082.         cmp    ax,-1
  1083.         jz    nosecondblk
  1084.         mov    es,ax            ; ^ to second mem blk
  1085.         mov    es,es:memblkprv     ; get previous pointer
  1086.         mov    es:memblknxt,0        ; no other blocks after this one
  1087. nosecondblk:
  1088.         mov    cx,16            ; do all allocated mem blocks
  1089.         mov    si,OFFSET memblks
  1090. freememblklp:
  1091.         mov    ax,cs:[si]        ; get memory blk segment
  1092.         cmp    ax,-1            ; was one ever allocated?
  1093.         jz    nxtmemblklp        ; nope
  1094.         mov    es,ax
  1095.         mov    ah,DOSFREE        ; must free it.
  1096.         int    DOS
  1097.         mov    WORD PTR cs:[si],-1
  1098. nxtmemblklp:
  1099.         add    si,2
  1100.         loop    freememblklp
  1101.  
  1102.         call    rstvectors        ; restore all int vectors
  1103.  
  1104.         mov    bp,sp
  1105.         push    [bp+22]         ; ensure returned flags are based on user's!
  1106.         popf
  1107.         pop    ds
  1108.         pop    es
  1109.         pop    di
  1110.         pop    si
  1111.         pop    bp
  1112.         pop    bx
  1113.         pop    dx
  1114.         pop    cx
  1115.         pop    ax
  1116.  
  1117.         mov    ssreg,ss        ; preserve these due to a
  1118.         mov    spreg,sp        ; DOS bug.
  1119.  
  1120.         int    DOS            ; allow DOS to continue!
  1121.  
  1122.         mov    ss,ssreg
  1123.         mov    sp,spreg
  1124.  
  1125.         push    ax
  1126.         push    cx
  1127.         push    dx
  1128.         push    bx
  1129.         push    bp
  1130.         push    si
  1131.         push    di
  1132.         push    es
  1133.         push    ds            ; preserve calling env.
  1134.         mov    bp,sp
  1135.         pushf
  1136.         pop    [bp+22]         ; fix return flags
  1137.  
  1138.         call    getmoreram        ; re-allocate our memory
  1139.         call    setvectors        ; patch vectors again
  1140.  
  1141.         pop    ds
  1142.         pop    es
  1143.         pop    di
  1144.         pop    si
  1145.         pop    bp
  1146.         pop    bx
  1147.         pop    dx
  1148.         pop    cx
  1149.         pop    ax
  1150.         iret
  1151.  
  1152. int21        ENDP
  1153.  
  1154. ;-------------------------------------------------------------------------------
  1155.  
  1156. releasepages    PROC    NEAR            ; Arg in es, result in ax
  1157.  
  1158. ; release any memory (and overlays) where this overlay should reside
  1159.  
  1160.         ASSUME    DS:NOTHING,ES:ovltbl
  1161.  
  1162.         mov    bx,ovlmemblk        ; start of memory to release
  1163.         sub    bx,MEMCTLBLKSIZ
  1164.         mov    dx,bx
  1165.         add    dx,es:ovlsiz
  1166.         add    dx,MEMCTLBLKSIZ     ; end of memory to release
  1167.         mov    ax,ovlemshdl
  1168.         cmp    ax,-1
  1169.         jz    doitagain
  1170.         call    mappage
  1171.         or    ovlflg,MASK ems
  1172.         mov    ax,emsframe
  1173.         jmp    dvart
  1174. doitagain:
  1175.         mov    ax,memblk1st        ; first memory blk
  1176.         jmp    dvart
  1177. dvartloop:
  1178.         mov    ds,ax            ; memory blk to check
  1179.         cmp    bx,ax            ; does it start below the memory to release?
  1180.         jnc    dvartsmaller        ; yup
  1181.         cmp    ax,dx            ; does it start above?
  1182.         jnc    dvartnocore        ; yup
  1183.         call    killmem         ; it's in the way. Zap it.
  1184.         jmp    dvartloop
  1185. dvartsmaller:
  1186.         add    ax,ds:memblksiz     ; end of this memory blk
  1187.         cmp    bx,ax            ; does it end below the memory to release?
  1188.         jnc    dvartsilly        ; yup
  1189.         test    ds:memblkflg,MASK_used
  1190.         jz    dvartfree
  1191.         call    killmem         ; Oh well, zap it too.
  1192.         add    ax,ds:memblksiz     ; end of this memory blk
  1193. dvartfree:
  1194.         cmp    ax,dx            ; does it end in the memory to be released?
  1195.         jc    dvartsilly
  1196. dvartgotblk:
  1197.         mov    ax,ds            ; this is it!
  1198.         mov    cx,bx
  1199.         sub    cx,ax            ; # of paragraphs between start of memory to release and mem blk
  1200.         jz    unsplit
  1201.         push    es
  1202.         call    splitblk
  1203.         or    es:memblkflg,MASK_used    ; set high block used
  1204.         call    mergemem        ; merge remaining free memory
  1205.         mov    ax,es
  1206.         mov    ds,ax
  1207.         pop    es
  1208. unsplit:
  1209.         mov    cx,es:ovlsiz
  1210.         add    cx,MEMCTLBLKSIZ     ; paragraphs needed to load ovl
  1211.         jmp    splitblklow        ; split remaining block
  1212. dvartsilly:
  1213.         mov    ax,ds:memblknxt
  1214. dvart:
  1215.         or    ax,ax            ; end of mem list?
  1216.         jz    dvartnocore
  1217.         jmp    dvartloop        ; play it again Sam.
  1218. dvartnocore:
  1219.         mov    al,RELERR        ; super OOPS!
  1220.         jmp    putserr
  1221.  
  1222. releasepages    ENDP
  1223.  
  1224. ;-------------------------------------------------------------------------------
  1225.  
  1226. getpages    PROC    NEAR            ; get enough memory to load ovl
  1227.  
  1228.         ASSUME    DS:NOTHING,ES:ovltbl
  1229.  
  1230.         mov    ovlemshdl,-1        ; clear any EMS stuff
  1231.         and    ovlflg,NOT MASK ems
  1232.         mov    cx,ax
  1233.         add    cx,MEMCTLBLKSIZ     ; total paragraphs needed
  1234. dorkagain:
  1235.         call    largestmem        ; find largest free blk
  1236.         cmp    dx,cx            ; large enough?
  1237.         jnc    gotdork         ; yup.
  1238.         call    getemsmem        ; try to allocate ems
  1239.         cmp    dx,cx            ; any available ?
  1240.         jnc    gotdork
  1241. dorkkill:
  1242.         call    getvictim        ; select a victim to release
  1243.         call    killovl         ; kill the selected victim
  1244.         jmp    dorkagain
  1245. gotdork:
  1246.         jmp    splitblklow        ; split the free blk
  1247.  
  1248. getpages    ENDP
  1249.  
  1250. ;-------------------------------------------------------------------------------
  1251.  
  1252. splitblklow    PROC    NEAR
  1253.  
  1254. ; split a block of memory returning the lower one to be used.
  1255.  
  1256.         ASSUME    DS:NOTHING,ES:NOTHING
  1257.  
  1258.         push    es
  1259.         or    ds:memblkflg,MASK_used    ; set low block used
  1260.         call    splitblk
  1261.         jc    splitlowdone
  1262.         push    ds
  1263.         mov    ax,es
  1264.         mov    ds,ax
  1265.         call    mergemem        ; merge remaining free memory
  1266.         pop    ds
  1267. splitlowdone:
  1268.         pop    es
  1269.         mov    ds:memblkovl,es     ; fix ptr to ovl
  1270.         mov    ax,ds            ; return lower blk segment
  1271.         ret
  1272.  
  1273. splitblklow    ENDP
  1274.  
  1275. ;-------------------------------------------------------------------------------
  1276.  
  1277. splitblk    PROC    NEAR
  1278.  
  1279.         ASSUME    DS:NOTHING,ES:NOTHING
  1280.  
  1281.         mov    ax,ds
  1282.         add    ax,cx
  1283.         mov    es,ax            ; ^ to upper blk to be created
  1284.         mov    ax,ds:memblksiz
  1285.         sub    ax,cx
  1286.         jbe    nofix            ; must be at least 1 para remaining to split
  1287.         mov    ds:memblksiz,cx     ; fix blk sizes
  1288.         mov    es:memblksiz,ax
  1289.         mov    ax,ds:memblknxt     ; fix pointers
  1290.         mov    es:memblknxt,ax
  1291.         mov    ds:memblknxt,es
  1292.         mov    es:memblkprv,ds
  1293.         mov    es:memblkflg,0        ; set upper to not used
  1294.         mov    ax,es:memblknxt
  1295.         or    ax,ax
  1296.         jz    nofix
  1297.         push    ds
  1298.         mov    ds,ax            ; fix blk after upper to point to upper
  1299.         mov    ds:memblkprv,es
  1300.         pop    ds
  1301.         clc
  1302.         ret
  1303. nofix:
  1304.         stc
  1305.         ret
  1306.  
  1307. splitblk    ENDP
  1308.  
  1309. ;-------------------------------------------------------------------------------
  1310.  
  1311. largestmem    PROC    NEAR    ; returns seg in ax, size in dx
  1312.                 ; retruns first block that's large enough if possible
  1313.  
  1314.         ASSUME    DS:NOTHING,ES:ovltbl
  1315.  
  1316.         mov    ax,memblk1st        ; first mem blk
  1317.         xor    dx,dx            ; largest size found
  1318.         jmp    gook
  1319. gookloop:
  1320.         mov    ds,ax
  1321.         test    ds:memblkflg,MASK_used    ; is this blk used?
  1322.         jnz    gookme            ; yup
  1323.         cmp    ds:memblksiz,cx     ; is it large enough?
  1324.         jc    gookme            ; nope
  1325.         mov    dx,ds:memblksiz     ; got one!
  1326.         ret
  1327. gookme:
  1328.         mov    ax,ds:memblknxt
  1329. gook:
  1330.         or    ax,ax            ; end of list?
  1331.         jnz    gookloop        ; around and around
  1332.         ret
  1333.  
  1334. largestmem    ENDP
  1335.  
  1336. ;-------------------------------------------------------------------------------
  1337.  
  1338. killmem     PROC    NEAR
  1339.  
  1340.         ASSUME    DS:NOTHING,ES:ovltbl
  1341.  
  1342.         test    ds:memblkflg,MASK_used    ; is it used?
  1343.         jz    memnotused        ; don't kill ovl
  1344.         push    es
  1345.         mov    es,ds:memblkovl
  1346.         and    ovlflg,NOT MASK loaded    ; zap ovl associated with this blk
  1347.         and    ovlflg,NOT MASK ems
  1348.         pop    es
  1349. memnotused:
  1350.         jmp    mergemem        ; merge free memory
  1351.  
  1352. killmem     ENDP
  1353.  
  1354. ;-------------------------------------------------------------------------------
  1355.  
  1356. killovl     PROC    NEAR        ; preserves bx
  1357.  
  1358.         ASSUME    DS:ovltbl,ES:NOTHING
  1359.  
  1360.         mov    ds,ax
  1361.         and    ovlflg,NOT MASK loaded    ; ovl no longer loaded
  1362.         test    ovlflg,MASK ems     ; was it in ems ?
  1363.         jz    noemskill
  1364.         and    ovlflg,NOT MASK ems    ; no longer in ems
  1365.         mov    ax,ovlemshdl
  1366.         call    mappage
  1367. noemskill:
  1368.         mov    ax,ovlmemblk        ; get mem blk
  1369.         sub    ax,MEMCTLBLKSIZ
  1370.         mov    ds,ax
  1371.         jmp    mergemem        ; merge free memory
  1372.  
  1373. killovl     ENDP
  1374.  
  1375. ;-------------------------------------------------------------------------------
  1376.  
  1377. mergemem    PROC    NEAR
  1378.  
  1379. ; merge physically adjacent free memory blocks. Preserves es. ds -> a free block.
  1380.  
  1381.         ASSUME    DS:NOTHING,ES:NOTHING
  1382.  
  1383.         push    dx
  1384.         push    es
  1385.         and    ds:memblkflg,NOT MASK_used ; set current free
  1386.         mov    ax,ds:memblkprv     ; get previous blk
  1387.         or    ax,ax            ; was there a previous blk?
  1388.         jz    gibber            ; nope
  1389.         mov    es,ax
  1390.         test    es:memblkflg,MASK_used    ; is the previous blk used?
  1391.         jnz    gibber            ; yup
  1392.         add    ax,es:memblksiz     ; end of previous blk
  1393.         mov    dx,ds
  1394.         cmp    dx,ax            ; physically adjacent?
  1395.         jnz    gibber            ; nope
  1396.         mov    ax,ds:memblksiz
  1397.         add    es:memblksiz,ax     ; adjust size of new larger blk
  1398.         mov    ax,ds:memblknxt     ; fix pointers
  1399.         mov    es:memblknxt,ax
  1400.         or    ax,ax
  1401.         jz    almostgibber
  1402.         mov    ds,ax            ; fix pointer of next blk
  1403.         mov    ds:memblkprv,es
  1404. almostgibber:
  1405.         mov    ax,es
  1406.         mov    ds,ax            ; new blk segment
  1407. gibber:
  1408.         mov    ax,ds:memblknxt     ; get next blk
  1409.         or    ax,ax            ; was there a next blk?
  1410.         jz    killdone        ; nope
  1411.         mov    es,ax
  1412.         test    es:memblkflg,MASK_used    ; is the nxt blk used?
  1413.         jnz    killdone        ; yup
  1414.         mov    ax,ds
  1415.         add    ax,ds:memblksiz     ; end of this blk
  1416.         mov    dx,es
  1417.         cmp    ax,dx            ; physically adjacent?
  1418.         jnz    killdone        ; nope
  1419.         mov    ax,es:memblksiz
  1420.         add    ds:memblksiz,ax     ; adjust size of new larger blk
  1421.         mov    ax,es:memblknxt     ; fix pointers
  1422.         mov    ds:memblknxt,ax
  1423.         or    ax,ax
  1424.         jz    killdone
  1425.         mov    es,ax            ; fix pointer of blk after nxt
  1426.         mov    es:memblkprv,ds
  1427. killdone:
  1428.         and    ds:memblkflg,NOT MASK_used ; make sure it's free
  1429.         pop    es
  1430.         pop    dx
  1431.         mov    ax,ds
  1432.         ret
  1433.  
  1434. mergemem    ENDP
  1435.  
  1436. ;-------------------------------------------------------------------------------
  1437.  
  1438. getmoreram    PROC    NEAR            ; try to alloc remaining pieces
  1439.                         ; of memory if any
  1440.         ASSUME    DS:NOTHING,ES:NOTHING    ; return dx = biggest block
  1441.  
  1442.         push    cx
  1443.         push    bx
  1444.         push    si
  1445.         push    di
  1446.         push    ds
  1447.         push    es
  1448.         xor    dx,dx
  1449.         mov    ax,memblk1st
  1450. nxtlowblk:
  1451.         mov    ds,ax
  1452.         mov    ax,ds:memblknxt
  1453.         or    ax,ax
  1454.         jnz    nxtlowblk
  1455.  
  1456.         mov    si,OFFSET memblks    ; a place to store the handles
  1457.         mov    di,OFFSET tempmem    ; a place to store the rejects
  1458.         mov    cx,16            ; 16 more max
  1459. getramlp:
  1460.         mov    ah,DOSALLOC
  1461.         mov    bx,0ffffh        ; Everything
  1462.         int    DOS
  1463.         cmp    bx,10h            ; nothing smaller than .25k please
  1464.         jc    gotallram
  1465.         mov    ah,DOSALLOC        ; allocate our own memory
  1466.         int    DOS
  1467.         jc    gotallram        ; oops!
  1468.         cmp    ax,ovltblbse        ; is it after our first mem blk?
  1469.         jc    releaseblk
  1470.         cmp    dx,bx
  1471.         jnc    notbigger
  1472.         mov    dx,bx
  1473. notbigger:
  1474.         mov    cs:[si],ax        ; save it
  1475.         mov    es,ax
  1476.         mov    es:memblkflg,0        ; clear mem flags
  1477.         mov    es:memblknxt,0        ; set next to nothing
  1478.         mov    es:memblkovl,0        ; no overlays loaded
  1479.         mov    es:memblkprv,ds     ; point to previous
  1480.         mov    es:memblksiz,bx     ; allocated memory block size
  1481.         mov    ds:memblknxt,es     ; point to next
  1482.         add    si,2
  1483.         mov    ds,ax
  1484.         jmp    short getnxtram
  1485. releaseblk:
  1486.         mov    cs:[di],ax
  1487.         add    di,2
  1488. getnxtram:
  1489.         loop    getramlp
  1490. gotallram:
  1491.         mov    si,OFFSET tempmem
  1492.         mov    cx,16
  1493. releaselp:
  1494.         mov    ax,cs:[si]
  1495.         cmp    ax,-1
  1496.         jz    relnext
  1497.         mov    es,ax
  1498.         mov    ah,DOSFREE
  1499.         int    DOS
  1500.         mov    WORD PTR cs:[si],-1
  1501. relnext:
  1502.         add    si,2
  1503.         loop    releaselp
  1504.         pop    es
  1505.         pop    ds
  1506.         pop    di
  1507.         pop    si
  1508.         pop    bx
  1509.         pop    cx
  1510.         ret
  1511.  
  1512. getmoreram    ENDP
  1513.  
  1514. ;-------------------------------------------------------------------------------
  1515.  
  1516. getemsmem    PROC    NEAR
  1517.  
  1518.         ASSUME    DS:NOTHING,ES:ovltbl
  1519.  
  1520.         xor    dx,dx            ; no ems memory
  1521.         cmp    emmflg,-1
  1522.         jz    testemsslots
  1523.         ret
  1524. testemsslots:
  1525.         mov    curemshandle,-1
  1526.         mov    di,OFFSET emsmemblks
  1527.         mov    bx,cx
  1528.         mov    cx,16
  1529. emsfreeslot:
  1530.         mov    ax,cs:[di]
  1531.         cmp    ax, -1
  1532.         jz    gotemsslot
  1533.         call    mappage
  1534.         cmp    ax,bx
  1535.         jnc    foundpage
  1536.         add    di,2
  1537.         loop    emsfreeslot
  1538.         mov    cx,bx
  1539.         xor    dx,dx
  1540.         ret
  1541. gotemsslot:
  1542.         mov    cx,bx
  1543.         mov    bx,4
  1544.         mov    ah,EMMALLOC
  1545.         push    cx            ; paranoia ! shouldn't be necessary.
  1546.         push    di
  1547.         push    es
  1548.         int    EMM
  1549.         pop    es
  1550.         pop    di
  1551.         pop    cx
  1552.         or    ah,ah
  1553.         jz    gotsomeems
  1554.         xor    dx,dx
  1555.         ret
  1556. gotsomeems:
  1557.         mov    cs:[di],dx
  1558.         mov    ovlemshdl,dx
  1559.         or    ovlflg,MASK ems
  1560.         mov    ax,dx
  1561.         call    mapemspages
  1562.         mov    ax,emsframe
  1563.         mov    ds,ax
  1564.         mov    ds:memblkflg,0        ; clear mem flags
  1565.         mov    ds:memblknxt,0        ; set next to nothing
  1566.         mov    ds:memblkprv,0        ; set previous to nothing
  1567.         mov    ds:memblkovl,0        ; no overlay loaded
  1568.         mov    dx,1000h
  1569.         mov    ds:memblksiz,dx
  1570.         ret
  1571.  
  1572. foundpage:
  1573.         mov    cx,bx
  1574.         mov    ds,si
  1575.         mov    dx,ax
  1576.         mov    ax,cs:[di]
  1577.         mov    ovlemshdl,ax
  1578.         or    ovlflg,MASK ems
  1579.         ret
  1580.  
  1581. getemsmem    ENDP
  1582.  
  1583. ;-------------------------------------------------------------------------------
  1584.  
  1585. mappage     PROC    NEAR            ; map a 64K block of EMS mem.
  1586.  
  1587.         ASSUME    DS:NOTHING,ES:ovltbl
  1588.  
  1589.         cmp    ax,curemshandle
  1590.         jnz    doems
  1591.         ret
  1592. doems:
  1593.         push    bx
  1594.         push    dx
  1595.         push    ds
  1596.         push    es
  1597.         call    mapemspages
  1598.         mov    ax,emsframe
  1599.         xor    dx,dx
  1600.         xor    si,si
  1601. emsset:
  1602.         mov    ds,ax
  1603.         test    ds:memblkflg,MASK_used    ; mem blk used ?
  1604.         jz    emsfreeblk
  1605.         mov    es,ds:memblkovl
  1606.         or    ovlflg,MASK ems OR MASK loaded
  1607.         jmp    emsnext
  1608. emsfreeblk:
  1609.         mov    ax,ds:memblksiz
  1610.         cmp    dx,ax
  1611.         jnc    emsnext
  1612.         mov    dx,ax
  1613.         mov    si,ds
  1614. emsnext:
  1615.         mov    ax,ds:memblknxt
  1616.         or    ax,ax
  1617.         jnz    emsset
  1618.  
  1619.         mov    ax,dx
  1620.         pop    es
  1621.         pop    ds
  1622.         pop    dx
  1623.         pop    bx
  1624.         ret
  1625.  
  1626. mappage     ENDP
  1627.  
  1628. ;-------------------------------------------------------------------------------
  1629.  
  1630. mapemspages    PROC    NEAR
  1631.  
  1632.         ASSUME    DS:NOTHING,ES:ovltbl
  1633.  
  1634.         push    es
  1635.         push    bx
  1636.         push    cx
  1637.         push    dx
  1638.         mov    curemshandle,ax
  1639.         mov    dx,ax
  1640.         mov    ah,EMMMAP
  1641.         xor    al,al            ; physical page 0
  1642.         xor    bx,bx            ; logical page 0
  1643.         push    dx
  1644.         int    EMM
  1645.         pop    dx
  1646.         or    ah,ah
  1647.         jnz    emmerror
  1648.         mov    ah,EMMMAP
  1649.         mov    al,1            ; physical page 1
  1650.         mov    bx,1            ; logical page 1
  1651.         push    dx
  1652.         int    EMM
  1653.         pop    dx
  1654.         or    ah,ah
  1655.         jnz    emmerror
  1656.         mov    ah,EMMMAP
  1657.         mov    al,2            ; physical page 2
  1658.         mov    bx,2            ; logical page 2
  1659.         push    dx
  1660.         int    EMM
  1661.         pop    dx
  1662.         or    ah,ah
  1663.         jnz    emmerror
  1664.         mov    ah,EMMMAP
  1665.         mov    al,3            ; physical page 3
  1666.         mov    bx,3            ; logical page 3
  1667.         int    EMM
  1668.         or    ah,ah
  1669.         jnz    emmerror
  1670.         mov    es,ovltblbse
  1671.         mov    cx,ovlcnt
  1672.         xor    bx,bx
  1673. testems:
  1674.         test    ovlflg[bx],MASK ems
  1675.         jz    nxttestems
  1676.         and    ovlflg[bx],NOT MASK loaded
  1677. nxttestems:
  1678.         add    bx,OVLSEGSIZ
  1679.         loop    testems
  1680.         pop    dx
  1681.         pop    cx
  1682.         pop    bx
  1683.         pop    es
  1684.         ret
  1685.  
  1686. emmerror:
  1687.         mov    al,EMSERR        ; ems manager error
  1688.         jmp    putserr
  1689.  
  1690. mapemspages    ENDP
  1691.  
  1692. ;-------------------------------------------------------------------------------
  1693.  
  1694. gethdr        PROC    NEAR            ; read EXE header from handle
  1695.  
  1696.         ASSUME    DS:NOTHING,ES:NOTHING
  1697.  
  1698.         mov    dx,OFFSET hdr        ; a place to put it
  1699.         mov    bx,si
  1700.         shl    bx,1
  1701.         mov    bx,ovlfilhdl[bx]     ; the file handle
  1702. readagain:
  1703.         mov    cx,TYPE EXEHDR        ; header size in bytes
  1704.         mov    ah,DOSREAD
  1705.         int    DOS            ; read from file
  1706.         jc    exegone         ; oops?
  1707.         cmp    ax,cx            ; got correct number of bytes?
  1708.         je    gothdr
  1709. IFNDEF NOSPLIT
  1710.         cmp    ax,0            ; Anything?
  1711.         je    gotonxtfil
  1712. ENDIF
  1713.         jmp    exerotten
  1714. IFNDEF NOSPLIT
  1715. gotonxtfil:
  1716.         inc    si
  1717.         cmp    si,MAXFILES+1
  1718.         je    exegone            ; We're out of files!
  1719.         mov    bx,si
  1720.         shl    bx,1
  1721.         cmp    ovlfilhdl[bx],-1    ; Any more files?
  1722.         je    gotonxtfil        ; not here.
  1723.  
  1724.         mov    bx,ovlfilhdl[bx]    ; Slide in new handle
  1725.         xor    bp,bp            ; reset file offset
  1726.         jmp    readagain
  1727. ENDIF
  1728. gothdr:
  1729.         cmp    hdr.exesign,EXESIGNUM    ; sanity check
  1730.         jne    exerotten
  1731.  
  1732.         ret                ; Wow, it worked!
  1733. exegone:
  1734.         mov    al,NOHDRERR        ; missing overlays!
  1735.         jmp    putserr            ; You lose!
  1736. IFNDEF NOSPLIT
  1737. exerotten:
  1738.         mov    al,HDRERR        ; corruption!
  1739.         jmp    putserr            ; You lose!
  1740. ENDIF
  1741.  
  1742. gethdr        ENDP
  1743.  
  1744. ;-------------------------------------------------------------------------------
  1745.  
  1746. openfiles    PROC    NEAR            ; Find our cohorts in crime
  1747.  
  1748.         push    es
  1749. IFNDEF NOSPLIT
  1750.         mov    ah,DOSGETDTA        ; Pick up DTA
  1751.         int    DOS            ; and
  1752.         mov    dtaseg,es        ; store
  1753.         mov    dtaoffset,bx        ; it
  1754.  
  1755.         push    ds
  1756.         mov    dx,OFFSET ovldta    ; Set new DTA for file search
  1757.         mov    ax,cs
  1758.         mov    ds,ax            ; point to the right seg
  1759.         mov    ah,DOSSETDTA
  1760.         int    DOS
  1761.         pop    ds            ; set this back for upcoming lodsb
  1762. ENDIF
  1763.         mov    cx,MAXNAMESIZE/2
  1764.         mov    bx,cs
  1765.         mov    es,bx
  1766.         mov    di, OFFSET filestring
  1767.  
  1768.         rep     movsw                ; load path from si to di
  1769. IFNDEF NOSPLIT
  1770.         mov    di, OFFSET filestring
  1771.         mov    al,0
  1772.         mov    cx,MAXNAMESIZE
  1773.         cld
  1774.         repne    scasb            ; search null for end of string
  1775.  
  1776.         sub    cx,MAXNAMESIZE
  1777.         neg    cx
  1778.         mov    bx,cx
  1779.  
  1780.         cmp    cx,MAXNAMESIZE
  1781.         je    checkslash
  1782.  
  1783.         dec    bx            ; keep string length
  1784.         dec    di            ; cause were past null now
  1785.  
  1786.         cmp    bx,7
  1787.         jle    patherr            ; "C:\.EXE" = 7
  1788. checkslash:
  1789.         mov    ax,DOSGETSWITCH        ; divine switchar
  1790.         int    DOS            ; it influences the path
  1791.  
  1792.         mov    al,'\'            ; if swichar = '/' pathsep = '\'
  1793.         cmp    dl,'/'
  1794.         je    searchslash    
  1795.         mov    al,'/'            ; else pathsep = '/'
  1796. searchslash:
  1797.         std
  1798.         repne    scasb            ; search back for '\'
  1799.         cld
  1800.  
  1801.         mov    dx,bx
  1802.         sub    dx,cx            ; keep file name length
  1803.         dec    dx
  1804.  
  1805.         mov    cx,0            ; reset for upcoming loop
  1806.         mov    pathlen,bx        ; hold these for recall
  1807.         mov    namelen,dx
  1808.         cmp    dx,12            ; "LONGNAME.EXE" = 12
  1809.         jle    openroot        ; Path name too long?
  1810. patherr:
  1811.         mov    al,NAMERR        ; real problems here.
  1812.         jmp    putserr
  1813. openroot:
  1814. ENDIF
  1815.         mov    ax,cs
  1816.         mov    ds,ax            ; set ds to code
  1817.  
  1818.         mov    dx, OFFSET filestring    ; open root code
  1819.         mov    al,0            ; access code
  1820.         mov    ah,DOSOPEN
  1821.         int    DOS            ; open sez me
  1822.         jnc    dontdie
  1823.  
  1824.         mov    al,FILEERR        ; can't open root
  1825.         jmp    putserr
  1826. dontdie:
  1827.         mov    ovlfilhdl[0],ax        ; save handle in array
  1828. IFNDEF NOSPLIT
  1829.         cmp    namelen,11        ; Max sized exe name (8.3)?
  1830.         jg    bigfilename        ; if not
  1831.         inc    pathlen            ; add one to path length
  1832.         inc    namelen
  1833. bigfilename:
  1834.         mov    di,OFFSET filestring    ; es is still code
  1835.         add    di,pathlen
  1836.         sub    di,5            ; append
  1837.         mov    si,OFFSET ovlext    ; wildcard extension
  1838.         mov    cx,6            ; and null
  1839.         rep    movsb            ; to filestring
  1840.  
  1841.         mov    cx,0            ; Match "normal" files
  1842.         mov    dx,OFFSET filestring
  1843.         mov    ah,DOSSEARCH
  1844.         int    DOS            ; Set DTA with Wildcard.
  1845.         jc    aok            ; Not a single match
  1846.         mov    cx,MAXFILES        ; set upcoming loop
  1847.         mov    dx,namelen
  1848.         sub    pathlen,dx        ; shorten absolute path
  1849. openloop:
  1850.         push    cx
  1851.         mov    bx,pathlen
  1852.         mov    di,OFFSET filestring    ; es is still in code
  1853.         add    di,bx
  1854.         mov    si,OFFSET ovldta.file_name
  1855.         mov    cx,namelen         ; since this *should* be
  1856.         rep    movsb
  1857.         pop    cx
  1858.  
  1859.         mov    dx,OFFSET filestring    ; path to overlay file
  1860.         mov    al,0            ; access code
  1861.         mov    ah,DOSOPEN
  1862.         int    DOS            ; open overlay file
  1863.         jnc    dontdie2
  1864. fileopenerr:
  1865.         call    itoa
  1866.  
  1867.         mov    al,OVLERR        ; can't open file!
  1868.         jmp    putserr
  1869. dontdie2:
  1870.         mov    bx,cx            ; put file number in bx
  1871.         shl    bx,1            ; 2 * bx for array index
  1872.         mov    ovlfilhdl[bx],ax    ; save handle in array
  1873.  
  1874.         mov    ah,DOSNEXTFILE        ; Look for more files
  1875.         int    DOS
  1876.         jc    aok
  1877.  
  1878.         loop    openloop        ; open only 15 overlays
  1879. aok:
  1880.         mov    dx,dtaoffset        ; Time to unset DTA
  1881.         mov    ds,dtaseg
  1882.         mov    ah,DOSSETDTA
  1883.         int    DOS
  1884. ENDIF
  1885.         pop    es
  1886.  
  1887.         ret
  1888.  
  1889. openfiles    ENDP
  1890.  
  1891. ;-------------------------------------------------------------------------------
  1892.  
  1893. putserr     PROC    NEAR
  1894.  
  1895. ; display error msg, close file, restore int vectors, free mem and return to DOS.
  1896.  
  1897.         ASSUME    DS:NOTHING,ES:NOTHING
  1898.  
  1899.         xor    ah,ah
  1900.         push    ax            ; keep return code for later
  1901.         push    cs
  1902.         pop    ds
  1903.         mov    bx,ax
  1904.         shl    bx,1
  1905.         add    bx,OFFSET errortbl
  1906.         mov    dx,[bx]
  1907.         cmp    dx,-1
  1908.         jz    freeints
  1909.         push    dx
  1910.         mov    dx,OFFSET msghead
  1911.         mov    ah,PRINT
  1912.         int    DOS
  1913.         pop    dx
  1914.         mov    ah,PRINT
  1915.         int    DOS            ; display error msg
  1916.  
  1917.         mov    ah,PRINT
  1918.         mov    dx,OFFSET diag
  1919.         int    DOS
  1920.         pop    ax
  1921.         push    ax
  1922.         call    itoa            ; error number
  1923.         mov    ah,DOSPUTC
  1924.         mov    dl,':'
  1925.         int    DOS
  1926.         mov    ax,VERSION
  1927.         call    itoa            ; version number
  1928.         mov    ah,DOSPUTC
  1929.         mov    dl,':'
  1930.         int    DOS
  1931.         mov    ax,0a000h
  1932.         sub    ax,ovltblbse        ; conventional memory
  1933.         call    itoa
  1934.         mov    ah,DOSPUTC
  1935.         mov    dl,':'
  1936.         int    DOS
  1937.         mov    si,OFFSET emsmemblks
  1938.         mov    cx,16
  1939.         xor    ax,ax
  1940. emstotlp:
  1941.         cmp    WORD PTR cs:[si],-1
  1942.         jz    gotemstot
  1943.         add    ax,emmframesiz
  1944.         add    si,2
  1945.         loop    emstotlp
  1946. gotemstot:
  1947.         call    itoa            ; ems usage in blocks
  1948.         mov    ah,DOSPUTC
  1949.         mov    dl,')'
  1950.         int    DOS
  1951.  
  1952.         mov    dx,OFFSET msgtail
  1953.         mov    ah,PRINT
  1954.         int    DOS
  1955. freeints:
  1956.         call    rstvectors        ; restore all int vectors
  1957.  
  1958.         mov    ax,ovltblbse
  1959.         cmp    ax,-1
  1960.         jz    freememblks
  1961.         mov    es,ax
  1962.         mov    ah,DOSFREE
  1963.         int    DOS
  1964. freememblks:
  1965.         mov    cx,16            ; do all allocated mem blocks
  1966.         mov    si,OFFSET memblks
  1967. freememlp:
  1968.         mov    ax,cs:[si]        ; get memory blk segment
  1969.         cmp    ax,-1            ; was one ever allocated?
  1970.         jz    nxtmemlp        ; nope
  1971.         mov    es,ax
  1972.         mov    ah,DOSFREE        ; must free it.
  1973.         int    DOS
  1974. nxtmemlp:
  1975.         add    si,2
  1976.         loop    freememlp
  1977.         mov    cx,16            ; do all allocated ems blocks
  1978.         mov    si,OFFSET emsmemblks
  1979. freeemsmemlp:
  1980.         mov    dx,cs:[si]        ; get memory blk segment
  1981.         cmp    dx,-1            ; was one ever allocated?
  1982.         jz    nxtemsmemlp        ; nope
  1983.         mov    ah,EMMFREE        ; must free it.
  1984.         int    EMM
  1985. nxtemsmemlp:
  1986.         add    si,2
  1987.         loop    freeemsmemlp
  1988. closefile:
  1989. IFNDEF NOSPLIT
  1990.         mov    cx,MAXFILES+1
  1991. nextfile:
  1992.         mov    bx,cx
  1993.         dec    bx
  1994.         shl    bx,1
  1995.         mov    bx,ovlfilhdl[bx]     ; get file handle
  1996. ELSE
  1997.         mov    bx,ovlfilhdl[0]
  1998. ENDIF
  1999.         cmp    bx,-1            ; was the file ever opened?
  2000.         jz    byebye            ; nope
  2001.         mov    ah,DOSCLOSE        ; close it
  2002.         int    DOS
  2003. byebye:
  2004. IFNDEF NOSPLIT
  2005.         loop    nextfile
  2006. ENDIF
  2007.         pop    ax            ; return code in al
  2008.         mov    ah,TERMINATE
  2009.         int    DOS            ; terminate this process
  2010.  
  2011. putserr     ENDP
  2012.  
  2013. ;-------------------------------------------------------------------------------
  2014.  
  2015. itoa        PROC    NEAR
  2016.  
  2017.         push    ax
  2018.         xchg    ah,al
  2019.         call    putbyte
  2020.         pop    ax
  2021.         jmp    putbyte
  2022.  
  2023. itoa        ENDP
  2024.  
  2025. ;-------------------------------------------------------------------------------
  2026.  
  2027. putbyte     PROC    NEAR
  2028.  
  2029.         push    ax
  2030.         shr    al,1
  2031.         shr    al,1
  2032.         shr    al,1
  2033.         shr    al,1
  2034.         call    nibble
  2035.         pop    ax
  2036.         jmp    nibble
  2037.  
  2038. putbyte     ENDP
  2039.  
  2040. ;-------------------------------------------------------------------------------
  2041.  
  2042. nibble        PROC    NEAR
  2043.  
  2044.         push    ax
  2045.         and    al,0fh
  2046.         add    al,30h
  2047.         cmp    al,3ah
  2048.         jc    nibok
  2049.         add    al,7
  2050. nibok:
  2051.         push    dx
  2052.         mov    dl,al
  2053.         mov    ah,DOSPUTC
  2054.         int    DOS
  2055.         pop    dx
  2056.         pop    ax
  2057.         ret
  2058.  
  2059. nibble        ENDP
  2060.  
  2061. ;-------------------------------------------------------------------------------
  2062.  
  2063. setvectors    PROC    NEAR
  2064.  
  2065.         push    ds
  2066.         xor    ax,ax
  2067.         mov    ds,ax
  2068.         mov    si,cs:intnum
  2069.         cli
  2070.         mov    ax,[si]
  2071.         mov    WORD PTR cs:oldvec,ax    ; save original vector
  2072.         mov    ax,[si+2]
  2073.         mov    WORD PTR cs:oldvec+2,ax
  2074.         mov    ax,OFFSET ovlmgr    ; point to ovlmgr
  2075.         mov    [si],ax         ; set int vector
  2076.         mov    [si+2],cs
  2077.  
  2078.         mov    si,DOS*4
  2079.         mov    ax,[si]
  2080.         mov    WORD PTR cs:oldint21,ax ; save original vector
  2081.         mov    ax,[si+2]
  2082.         mov    WORD PTR cs:oldint21+2,ax
  2083.         mov    ax,OFFSET int21     ; point to new int21
  2084.         mov    [si],ax         ; set int vector
  2085.         mov    [si+2],cs
  2086.         sti
  2087.         pop    ds
  2088.         ret
  2089.  
  2090. setvectors    ENDP
  2091.  
  2092. ;-------------------------------------------------------------------------------
  2093.  
  2094. rstvectors    PROC    NEAR
  2095.  
  2096.         push    ds
  2097.         xor    ax,ax
  2098.         mov    ds,ax
  2099.         mov    si,DOS*4
  2100.         cli
  2101.         mov    ax,WORD PTR cs:oldint21 ; put back dos vector
  2102.         cmp    ax,-1
  2103.         jz    rstvec
  2104.         mov    [si],ax
  2105.         mov    ax,WORD PTR cs:oldint21+2
  2106.         mov    [si+2],ax
  2107. rstvec:
  2108.         mov    si,cs:intnum
  2109.         mov    ax,WORD PTR cs:oldvec    ; put back ovlmgr vector
  2110.         cmp    ax,-1
  2111.         jz    rstdone
  2112.         mov    [si],ax
  2113.         mov    ax,WORD PTR cs:oldvec+2
  2114.         mov    [si+2],ax
  2115.         sti
  2116. rstdone:
  2117.         pop    ds
  2118.         ret
  2119.  
  2120. rstvectors    ENDP
  2121.  
  2122. code        ENDS
  2123.  
  2124.         END
  2125.