home *** CD-ROM | disk | FTP | other *** search
- ; SCCS Id: @(#)ovlmgr.asm 91/09/04
- ; Copyright (c) 1989, 1990, 1991, 1992, 1993 Pierre Martineau and
- ; Stephen Spackman. All Rights Reserved.
- ; This product may be freely redistributed. See NetHack license for details.
-
- VERSION EQU 3100h
-
- PAGE 57,132
- TITLE 'DOS Overlay Manager for MSC 5.1+'
- SUBTTL 'Copyright (c) 1989, 1990, 1991, 1992, 1993 Pierre Martineau and Stephen Spackman. All Rights Reserved.'
-
- ; Multiple overlay file support for v30a0 by Norm Meluch with some input from Stephen.
-
- ; acknowledgements: - Many thanks to Norm Meluch for his invaluable help
- ; - No thanks to Microsoft
- ; - alltrsidsctysti!!!
- ; - izchak and friends for impetus
- ; - us for brilliance
- ; - coffee for speed
- ; - others as necessary
-
- ; assumptions: - all registers are preserved including flags
- ; - the stack is preserved
- ; - re-entrancy is not required
-
- ; options: /Di386 use 80386-specific opcodes
- ; (faster, but no good for weaker machines)
- ; /DNOEMS omit EMS support
- ; (needed if application uses EMS)
- ; /DNOSPLIT omit support for external .OVL files
-
- DOSALLOC EQU 48h ; memory allocation
- DOSFREE EQU 49h ; free allocated memory
- DOSREALLOC EQU 4ah ; modify memory block
- DOSREAD EQU 3fh ; read bytes from handle
- DOSSEEK EQU 42h ; logical handle seek
- DOSOPEN EQU 3dh ; open handle
- DOSCLOSE EQU 3eh ; close handle
- DOSSETDTA EQU 1ah ; Set Data transfer area
- DOSGETDTA EQU 2fh ; Get Data transfer area
- DOSSEARCH EQU 4eh ; Search for 1st file match
- DOSNEXTFILE EQU 4fh ; Search for next file match
- DOSEXEC EQU 4bh ; exec child process
- DOSPUTC EQU 02h ; print a char
- DOSVERSION EQU 30h ; get version number
- DOSGETVEC EQU 35h ; get interrupt vector
- DOSGETSWITCH EQU 3700h ; get DOS switchar
- DOS EQU 21h ; Dos interrupt #
- PRINT EQU 09h ; print string
- TERMINATE EQU 4ch ; terminate process
- EMM EQU 67h ; EMM handler int vector
- EMMSTATUS EQU 40h ; get EMM status
- EMMFRAME EQU 41h ; get EMM page frame
- EMMTOTALS EQU 42h ; get EMM pages available
- EMMALLOC EQU 43h ; allocate EMM pages
- EMMMAP EQU 44h ; map EMM pages
- EMMFREE EQU 45h ; free EMM pages
- MAXNAMESIZE EQU 50h ; max path name size
- MAXFILES EQU 0Eh ; max # of *.OVL files
- EXESIGNUM EQU 5a4dh ; Exe header signature
- CR EQU 0dh
- LF EQU 0ah
- ESCAPE EQU 1bh
- BELL EQU 07h
- PARSIZ EQU 10h ; this is the size of a paragraph - this better not change!
- FAERIE EQU 00h ; Used for dummy segment allocation
-
- NOERR EQU 0
- DOSERR EQU 1
- FILEERR EQU 2
- NOMEMERR EQU 3
- FILEIOERR EQU 4
- VICTIMERR EQU 5
- RELERR EQU 6
- EMSERR EQU 7
- HDRERR EQU 8
- NAMERR EQU 9
- OVLERR EQU 10
- NOHDRERR EQU 11
-
- ; The following EXTRNs are supplied by the linker
-
- EXTRN $$OVLBASE:BYTE ; segment of OVERLAY_AREA
- EXTRN $$MPGSNOVL:BYTE ; ^ to module table
- EXTRN $$MPGSNBASE:WORD ; ^ to module segment fixups
- EXTRN $$INTNO:BYTE ; interrupt number to be used
- EXTRN $$COVL:WORD ; number of physical overlays
- EXTRN $$CGSN:WORD ; number of modules
- EXTRN $$MAIN:FAR ; ^ to function main()
-
- PUBLIC $$OVLINIT ; Our entry point
- ; called by the c startup code
- IFDEF i386
- OP32 MACRO ; 32 bit operand override
- DB 066h
- ENDM
-
- pusha MACRO ; push all registers
- DB 060h
- ENDM
-
- popa MACRO ; pop all registers
- DB 061h
- ENDM
- ENDIF
-
- ovlflgrec RECORD locked:1=0,ems:1=0,loaded:1=0,file:4=0,pad:1 ; overlay flags
- ; "file" is the overlay file this overlay is in; 0 is the .EXE
- ; itself. Otherwise, the numbers are arbitrary.
-
- ; This is a dirty hack. What we need is a virtual segment that will be built
- ; by the (our) loader in multiple copies, one per overlay. Unfortunately, this
- ; doesn't seem to be a sensible idea in the minds of the folks at Microsoft.
- ; Declaring this segment AT will ensure that it never appears in the exefile,
- ; and ASSUME is dumb enough to be fooled.
- ;
- ; The reason we want to do this is also not-to-be-tried-at-home: it turns out
- ; that we can code a faster interrupt handler if we map overlay numbers to
- ; segment values. Normally we would consider this unacceptable programming
- ; practise because it is 86-mode specific, but the *need* for this entire
- ; programme is 86-mode specific, anyway.
-
- pspseg SEGMENT PARA AT FAERIE ; dummy segment for psp
- ORG 2ch ; ^ to segment of environmemt in psp
- pspenv LABEL WORD
- pspseg ENDS
-
- ovltbl SEGMENT PARA AT FAERIE ; Dummy segment definition for overlay table
-
- ; NOTE: This segment definition MUST be exactly 16 bytes long
-
- ovlflg ovlflgrec <0,0,0,0,0> ; overlay flags
- ovlinvcnt DB ? ; invocation count
- ovlmemblk DW ? ; ^ to allocated memory block
- ovllrudat DD ? ; misc lru data (pseudo time stamp)
- ovlemshdl DW ? ; ovl ems memory handle
- ovlfiloff DW ? ; ovl file offset in pages (512 bytes)
- ovlsiz DW ? ; ovl size in paragraphs
- ovlhdrsiz DW ? ; hdr size in paragraphs
-
- IF1
- IF ($ - ovlflg) GT PARSIZ
- .ERR
- %OUT This segment MUST be no more than 16 bytes, REALLY!!!
- ENDIF
- ENDIF
-
- OVLSEGSIZ EQU PARSIZ ; this had better be true!!! (16 bytes)
-
- ovltbl ENDS
-
- DTASTRUC STRUC ; internal DTA for ovlmgr
- DB 21 DUP (0)
- file_attr DB 0
- file_time DW 0
- file_date DW 0
- file_size DD 0
- file_name DB 9 DUP (0)
- file_ext DB 3 DUP (0)
- dtapad DB 86 DUP (0) ; Pad to 128 bytes
- DTASTRUC ENDS
-
- EXEHDR STRUC ; structure of an EXE header
- exesign DW EXESIGNUM ; signature
- exelstpgesiz DW ? ; last page size (512 byte pages)
- exesiz DW ? ; total pages (including partial last page)
- relocitems DW ? ; number of relocation entries
- hdrparas DW ? ; number of paragraphs in the header
- minalloc DW ? ; minimum paragraph allocation
- maxalloc DW ? ; maximum patagraph allocation
- exess DW ? ; initial stack segment
- exesp DW ? ; initial stack pointer
- exechksum DW ? ; checksum
- exeip DW ? ; initial instruction pointer
- execs DW ? ; initial code segment
- reloctbloff DW ? ; offset from beginning of header to relocation table
- exeovlnum DW ? ; overlay number
- EXEHDR ENDS
-
- MASK_used EQU 1 ; memory block flag
-
- MEMCTLBLK STRUC ; memory block structure
- memblkflg DB ? ; flags
- memblkpad1 DB ? ; go ahead, delete me!
- memblknxt DW ? ; ^ to next block
- memblkprv DW ? ; ^ to previous block
- memblkovl DW ? ; ^ to overlay occupying this block
- memblksiz DW ? ; size in paragraphs
- memblkpad DB PARSIZ - memblkpad MOD PARSIZ DUP (?) ; pad to 16 bytes
- MEMCTLBLK ENDS
-
- MEMCTLBLKSIZ EQU TYPE MEMCTLBLK / PARSIZ ; should equal 1 paragraph
-
- ;-------------------------------------------------------------------------------
-
- code SEGMENT PUBLIC
-
- ; NOTE: the following order is optimum for alignment purposes across the
- ; entire INTEL 80x86 family of processors.
-
- ovltim DD ? ; pseudo-lru time variable
- farcall DD ? ; internal trampoline.
- oldvec DD -1 ; saved interrupt vector
- oldint21 DD -1 ; saved int 21 vector
- sireg DW ? ; temp save area
- IFDEF i386
- DW ? ; for esi
- ENDIF
- dsreg DW ? ; temp save area
- ssreg DW ?
- spreg DW ?
- ovlfilhdl DW MAXFILES+1 DUP (-1) ; always-open file handles for .EXE, .OVL
- ovltblbse DW -1 ; segment of first overlay descriptor
- memblks DW 16 DUP (-1) ; allocated memory blocks
- memblk1st DW ? ; first memory block
- emsmemblks DW 16 DUP (-1) ; ems allocated memory blocks (64K each)
- curemshandle DW -1 ; currently mapped handle
- ovlcnt DW ? ; # overlays
- modcnt DW ? ; # of modules
- ovlrootcode DW ? ; logical segment of OVERLAY_AREA
- ovldata DW ? ; logical segment of OVERLAY_END
- pspadd DW ? ; our psp address + 10h (for relocations)
- emsframe DW ? ; EMM page frame segment
- moduletbl DD 256 DUP (?) ; module lookup table (256 modules)
- curovl DW OFFSET stkframe ; ^ into stack frame
- stkframe DW 256*3 DUP (?) ; internal stack (256 ovls deep)
- tempmem DW 16 DUP (-1) ; temp mem block storage
- intnum DW ? ; ovlmgr int number
- hdr EXEHDR <> ; EXE header work area
- DB 512-TYPE EXEHDR DUP (?) ; exe hdr buffer for relocations
- EXEHDRTMPSIZ EQU $ - hdr ; size of temp reloc buffer
- filestring DB MAXNAMESIZE DUP (0) ; string space for file specs
- pathlen DW ? ; path length of file spec
- namelen DW ? ; length of file names
- ovldta DTASTRUC <> ; DTA for ovlmgr use
- dtaseg DW ? ; DTA segment for program
- dtaoffset DW ? ; DTA offset for program
- errortbl DW -1 ; error message pointers
- DW OFFSET baddos
- DW OFFSET nofile
- DW OFFSET noroom
- DW OFFSET badio
- DW OFFSET nocore
- DW OFFSET nocore
- DW OFFSET badems
- DW OFFSET badhdr
- DW OFFSET badnam
- DW OFFSET noovl
- DW OFFSET nohdr
- DW OFFSET unknown
- DW OFFSET unknown
- DW OFFSET unknown
- DW OFFSET unknown
- emmname DB "EMMXXXX0" ; EMM device driver name
- emmtot DW 0 ; total emm blocks free
- emmframesiz DW 4 ; frame size in blocks
- emmflg DB 0 ; EMM present flag
-
- i386code DB '386 specific code enabled.',CR,LF,'$'
- memavl DB 'Conventional memory available: $'
- paragraphs DB 'H paragraphs.',CR,LF,'$'
- emsavl DB 'EMS memory available: $'
- pages DB 'H 16K-pages.',CR,LF,'$'
- baddos DB 'Incorrect DOS version. Must be 3.00 or later.$'
- nofile DB 'Inaccessible EXE file. Can',39,'t load overlays.$'
- noroom DB 'Not enough free memory left to run this program.$'
- badio DB 'File I/O error.$'
- nocore DB 'Internal memory allocation failure.$'
- badems DB 'EMS memory manager error.$'
- badhdr DB 'Executable or overlay header missing or damaged.$'
- badnam DB 'Unable to resolve overlay file names.$'
- noovl DB 'Inaccessible OVL file. Can',39,'t load overlays.$'
- nohdr DB 'Incomplete executable. OVL files missing?$'
- unknown DB 'Unknown error!$'
- msghead DB ESCAPE,'[0m',ESCAPE,'[K',CR,LF,ESCAPE,'[K',ESCAPE,'[1mOVLMGR:',ESCAPE,'[0m $'
- diag DB ESCAPE,'[K',CR,LF,ESCAPE,'[K',' ($'
- msgtail DB ESCAPE,'[K',CR,LF,ESCAPE,'[K',BELL,'$'
- ovlext DB '?.OVL',0
-
- ;-------------------------------------------------------------------------------
-
- $$OVLINIT PROC FAR ; Init entry point
-
- ASSUME CS:code,DS:pspseg,ES:NOTHING
-
- push ax
- push bx
- push cx
- push dx
- push si
- push di
- push bp
- push ds
- push es ; save the world
-
- cld
- mov ax,ds ; get our psp
- add ax,10h
- mov pspadd,ax ; save it
- mov ah,DOSVERSION
- int DOS
- cmp al,3 ; DOS 3.0 or later
- jnc doenvthing
- mov al,DOSERR ; incorrect version of dos
- jmp putserr
- doenvthing:
- mov ds,pspenv ; get environment segment
- mov si,-1
- envloop: ; search for end of environment
- inc si
- cmp WORD PTR [si],0
- jnz envloop
- add si,4 ; point to EXE filename
-
- call openfiles ; Search & open overlay files
- IFNDEF NOEMS
- chkems:
- mov ah,DOSGETVEC
- mov al,EMM
- int DOS
- mov ax,cs
- mov ds,ax
- mov di,0ah
- mov si,OFFSET emmname
- mov cx,8
- repe cmpsb
- mov al,0
- jnz setemmflg
- mov al,-1
- setemmflg:
- mov emmflg,al
- jnz noemshere
- mov ah,EMMFRAME
- int EMM
- mov emsframe,bx
- mov ah,EMMTOTALS
- int EMM
- mov emmtot,bx
- noemshere:
- ENDIF
- mov ax,SEG $$OVLBASE ; OVERLAY_AREA segment
- mov ovlrootcode,ax
- mov ax,SEG $$COVL ; segment of DGROUP
- mov ds,ax
- mov bx,$$CGSN ; number of modules
- mov modcnt,bx ; save for later use
- mov bx,$$COVL ; number of physical overlays
- mov ovlcnt,bx ; save for later use
-
- ; Now allocate memory
- mov ah,DOSALLOC ; bx contains # paras needed for ovltbl
- int DOS
- jnc gotovlram
- jmp buyram
- gotovlram:
- mov ovltblbse,ax ; overlay descriptor table begins at start of memory block
-
- mov cx,ovlcnt
- zeromem:
- mov es,ax
- mov es:ovlflg,0 ; initialise ovl flags
- mov es:ovlinvcnt,0 ; initialise invocation count
- mov es:ovlmemblk,0
- mov WORD PTR es:ovllrudat,0 ; initialise ovl lru
- mov WORD PTR es:ovllrudat+2,0
- mov es:ovlemshdl,-1
- mov es:ovlfiloff,0 ; initialize file offset
- mov es:ovlsiz,0 ; initialize overlay size
- mov es:ovlhdrsiz,0
- inc ax
- loop zeromem
-
- mov ax,cs
- mov ds,ax
- IFDEF DEBUG
- IFDEF i386
- mov ah,print
- mov dx,OFFSET msghead
- int DOS
- mov ah,print
- mov dx,OFFSET i386code
- int DOS
- ENDIF
- mov ah,print
- mov dx,OFFSET msghead
- int DOS
- mov ah,print
- mov dx,OFFSET memavl
- int DOS
- mov ax,0a000h
- sub ax,ovltblbse
- call itoa
- mov ah,print
- mov dx,OFFSET paragraphs
- int DOS
- IFNDEF NOEMS
- mov ah,print
- mov dx,OFFSET msghead
- int DOS
- mov ah,print
- mov dx,OFFSET emsavl
- int DOS
- mov ax,emmtot
- call itoa
- mov ah,print
- mov dx,OFFSET pages
- int DOS
- ENDIF
- ENDIF
- ASSUME ES:ovltbl
-
- xor bp,bp
- xor di,di
- xor si,si ; file handle loop ctr
- filsegtbllpp: ; initialise ovl table
- call gethdr ; get an EXE header
-
- mov ax,ovltblbse
- add ax,hdr.exeovlnum
- mov es,ax ; ^ to ovl table entry
- IFNDEF NOSPLIT
- mov cx,si ; set file # in ovlflg
- shl cx,1
- mov ovlflg,cl
- ENDIF
- mov ax,hdr.exesiz
- shl ax,1
- shl ax,1
- shl ax,1
- shl ax,1
- shl ax,1 ; * 32
- mov dx,hdr.exelstpgesiz
- or dx,dx
- jz emptypage
- shr dx,1
- shr dx,1
- shr dx,1
- shr dx,1 ; / 16
- inc dx
- sub ax,20h
- add ax,dx
- emptypage:
- sub ax,hdr.hdrparas ; actual size of code
- mov ovlsiz,ax ; overlay size in paragraphs
- cmp hdr.exeovlnum,0 ; skip if ovl 0 (root code)
- jz notlargest
- cmp ax,di ; find largest ovl
- jc notlargest
- mov di,ax
- notlargest:
- mov ax,hdr.hdrparas
- shl ax,1
- shl ax,1
- shl ax,1
- shl ax,1
- mov ovlhdrsiz,ax ; hdr size in bytes
- mov ovlfiloff,bp ; initialise ovl file offset
- add bp,hdr.exesiz ; ^ to next overlay
- mov dx,bp
- mov cl,dh
- mov dh,dl
- xor ch,ch
- xor dl,dl
- shl dx,1
- rcl cx,1 ; cx:dx = bp * 512
- mov al,0
- mov ah,DOSSEEK ; seek to next ovl
- int DOS
-
- mov cx,ovlcnt ; check if all overlays found
- mov ax,ovltblbse
- dec cx ; ovlcnt includes root
- add ax,cx
- ovloop:
- mov es,ax
- IFNDEF NOSPLIT
- mov bl,ovlflg
- and bx,MASK file
-
- cmp bx,0 ; if file # is 0
- jne again
- ENDIF
- cmp ovlfiloff,0 ; and offset is 0
- jne again
- jmp filsegtbllpp ; then we're still looking
- again:
- dec ax
- loop ovloop
-
- ASSUME ES:nothing ; prepare first memory block
-
- mov ax,ovlrootcode ; OVERLAY_AREA segment
- mov memblk1st,ax ; save pointer to first mem block
- mov es,ax
- mov es:memblkflg,0 ; clear mem flags
- mov es:memblknxt,0 ; set next to nothing
- mov es:memblkprv,0 ; set previous to nothing
- mov es:memblkovl,0 ; no overlay loaded
- mov es:memblksiz,di ; di contains OVERLAY_AREA size in paragraphs
- add ax,di
- mov ovldata,ax ; end of OVERLAY_END
- push di
- mov es,ovltblbse ; temporary
- call getemsmem ; see if any ems available
- mov es:ovlemshdl,-1 ; fix these!
- and es:ovlflg,NOT MASK ems
- push dx
- call getmoreram ; see if there are any other pieces lying around
- pop ax
- pop di
- or ax,ax ; any ems?
- jnz noramcheck
- inc di
- cmp dx,di
- jc buyram
- noramcheck:
- mov WORD PTR ovltim,0 ; initialise global lru time stamp
- mov WORD PTR ovltim+2,0
- mov di,OFFSET stkframe
- mov WORD PTR cs:[di],-1 ; initialise stack frame
- add di,6
- mov ax,ovltblbse
- mov cs:[di],ax
- mov curovl,di ; initialise stack frame pointer
- mov es,ax
- mov es:ovlflg,MASK locked OR MASK loaded ; set flags on ovl 0
- jmp short chgintvec
- buyram:
- mov al,NOMEMERR ; free up some TSRs or something
- jmp putserr
- chgintvec:
- mov ax,SEG $$INTNO
- mov ds,ax
- mov al,$$INTNO ; get int number to use
- xor ah,ah
- shl ax,1
- shl ax,1
- mov intnum,ax
- call setvectors ; set up interrupt vectors
- mov cx,modcnt ; module count
- mov ax,SEG $$MPGSNBASE
- mov es,ax
- mov ax,cs
- mov ds,ax
-
- ASSUME DS:code
-
- mov bx,OFFSET $$MPGSNBASE ; ^ to linker provided overlay segment fixups
- mov si,OFFSET $$MPGSNOVL ; ^ to linker provided module table
- mov di,OFFSET moduletbl ; ^ to our module table
- modloop:
- mov al,es:[si] ; real physical ovl number
- xor ah,ah
- add ax,ovltblbse ; ovlctlseg address
- mov [di],ax ; save in module table
- mov ax,es:[bx] ; get seg fixup
- sub ax,ovlrootcode ; adjust for relative reference
- mov [di+2],ax ; save in module table
- add di,4
- add bx,2
- inc si
- loop modloop
- pop es
- pop ds
- pop bp
- pop di
- pop si
- pop dx
- pop cx
- pop bx
- pop ax ; restore the world
- jmp $$MAIN ; And away we go!
-
- $$OVLINIT ENDP
-
- ;-------------------------------------------------------------------------------
-
- ovlmgr PROC FAR ; This is the it!
-
- ASSUME DS:NOTHING,ES:NOTHING
-
- IFDEF i386
- OP32
- ENDIF
- mov sireg,si ; preserve si
- mov dsreg,ds ; and ds
- pop si ; retrieve caller ip
- pop ds ; " " cs
- push ax
- push bx
- cld
- lodsb ; module # to call
- xor ah,ah
- mov bx,ax
- lodsw ; offset in ovl to call
- mov WORD PTR farcall,ax ; into trampoline
- mov ax,si
- mov si,curovl ; get stack frame pointer
- add si,6 ; update stack
- mov cs:[si-4],ds ; save return seg
- mov cs:[si-2],ax ; and return offset
-
- shl bx,1
- shl bx,1 ; * 4 (2 words/entry in module tbl)
- add bx,OFFSET moduletbl
- mov ds,cs:[bx] ; ovl tbl entry
- mov ax,cs:[bx+2] ; segment fixup
- mov cs:[si],ds ; ovl entry into stack frame
- mov curovl,si
-
- ASSUME DS:ovltbl
-
- IFDEF i386
- OP32
- ENDIF
- mov si,WORD PTR ovltim ; lru time stamp
- IFDEF i386
- OP32
- ENDIF
- inc si ; time passes!
- IFDEF i386
- OP32
- ENDIF
- mov WORD PTR ovltim,si ; update global clock
- IFDEF i386
- OP32
- ENDIF
- mov WORD PTR ovllrudat,si ; as well as ovl clock
- IFNDEF i386
- mov si,WORD PTR ovltim+2
- jz ininc ; dword increment
- cryupcdon:
- mov WORD PTR ovllrudat+2,si ; as well as ovl clock
- ENDIF
- test ovlflg,MASK loaded ; ovl loaded?
- jz inload ; load it or map it then.
- ovlloadedupc:
- inc ovlinvcnt
- add ax,ovlmemblk ; add fixup and segment address
- mov WORD PTR farcall+2,ax ; into trampoline
- IFDEF i386
- OP32
- ENDIF
- mov si,sireg ; retore all registers
- mov ds,dsreg
- pop bx
- pop ax
- popf ; don't forget these!
- call DWORD PTR farcall ; and GO
- pushf ; preserve registers again!
- mov dsreg,ds
- IFDEF i386
- OP32
- ENDIF
- mov sireg,si
- mov si,curovl ; stack frame pointer
- mov ds,cs:[si]
- dec ovlinvcnt
- sub si,6 ; adjust stack
- mov ds,cs:[si] ; retrieve ovl tbl entry
- push cs:[si+2] ; set return address
- push cs:[si+4]
- mov curovl,si
- IFDEF i386
- OP32
- ENDIF
- mov si,WORD PTR ovltim ; do the lru thing again
- IFDEF i386
- OP32
- ENDIF
- inc si
- IFDEF i386
- OP32
- ENDIF
- mov WORD PTR ovltim,si
- IFDEF i386
- OP32
- ENDIF
- mov WORD PTR ovllrudat,si
- IFNDEF i386
- mov si,WORD PTR ovltim+2
- jz outinc
- crydncdon:
- mov WORD PTR ovllrudat+2,si
- ENDIF
- test ovlflg,MASK loaded ; ovl loaded?
- jz outload ; better get it before someone notices
- jmpback:
- IFDEF i386
- OP32
- ENDIF
- mov si,sireg ; get registers back
- mov ds,dsreg
- iret ; and GO back
-
- IFNDEF i386
- ininc:
- inc si
- mov WORD PTR ovltim+2,si ; update global and
- jmp cryupcdon
- ENDIF
-
- inload:
- test ovlflg,MASK ems
- jz infile
- push ax
- mov ax,ovlemshdl
- call mappage
- pop ax
- jmp ovlloadedupc
- infile:
- call loadoverlay ; self explanatory
- jmp ovlloadedupc
-
- IFNDEF i386
- outinc:
- inc si
- mov WORD PTR ovltim+2,si
- jmp crydncdon
- ENDIF
-
- outload:
- test ovlflg,MASK ems
- jz outfile
- push ax
- mov ax,ovlemshdl
- call mappage
- pop ax
- jmp jmpback
- outfile:
- call loadoverlay
- jmp jmpback
-
- ovlmgr ENDP
-
- ;-------------------------------------------------------------------------------
-
- loadoverlay PROC NEAR ; load overlay pointed to by es
-
- ASSUME DS:NOTHING,ES:ovltbl
-
- IFDEF i386
- OP32
- pusha ; eax,ecx,edx,ebx,esp,ebp,esi,edi
- ELSE
- push ax
- push cx
- push dx
- push bx
- push bp
- push si
- push di
- ENDIF
- push ds
- push es ; just in case
- mov ax,ds
- mov es,ax
- cmp ovlinvcnt,0
- jnz fxdadr ; Yup, it's a toughie
- mov ax,ovlsiz ; How much?
- call getpages ; never fail mem alloc, you bet.
- jmp gleaner
- fxdadr:
- call releasepages ; free memory where this ovl should be loaded
- gleaner:
- add ax,MEMCTLBLKSIZ ; skip mem ctl blk
- mov ovlmemblk,ax ; memory block to use
- mov ds,ax
- mov dx,ovlfiloff ; where in the file is it?
- mov cl,dh
- mov dh,dl
- xor ch,ch
- xor dl,dl
- shl dx,1
- rcl cx,1 ; cx:dx = dx * 512
- mov ax,ovlhdrsiz
- push cx
- push dx
- add dx,ax
- adc cx,0 ; position to code
- mov ah,DOSSEEK ; lseek to code
- mov al,0 ; from beginning of file
- mov bl,ovlflg
- and bx,MASK file
- mov bx,ovlfilhdl[bx] ; never closing handle
- int DOS
- jc burnhead ; oops!
- xor dx,dx ; buf = ds:0
- mov cx,ovlsiz ; number of paragraphs to load
- shl cx,1
- shl cx,1
- shl cx,1
- shl cx,1 ; * 16 = number of bytes
- mov ah,DOSREAD ; prevent random DOS behaviour
- int DOS ; read in code
- jc burnhead ; double oops!
- pop dx
- pop cx ; position of hdr
- mov ah,DOSSEEK ; lseek to hdr
- mov al,0 ; from beginning of file
- mov bl,ovlflg
- and bx,MASK file
- mov bx,ovlfilhdl[bx] ; never closing handle
- int DOS
- jc burnhead ; oops!
- mov cx,EXEHDRTMPSIZ ; reloc buffer size
- mov dx,OFFSET hdr
- push ds
- mov ax,cs
- mov ds,ax
- mov ah,DOSREAD ; prevent random DOS behaviour
- int DOS ; read in header
- pop ds
- jc burnhead ; double oops!
-
- call ovlrlc ; perform relocation normally done by DOS EXE loader
- pop es ; retrieve ovl tbl entry
- pop ds
-
- ASSUME DS:ovltbl,ES:NOTHING
-
- or ovlflg,MASK loaded ; because it is now
- IFDEF i386
- OP32
- popa
- ELSE
- pop di
- pop si
- pop bp
- pop bx
- pop dx
- pop cx
- pop ax
- ENDIF
- ret
-
- burnhead:
- mov al,FILEIOERR ; some kind of I/O error
- jmp putserr
-
- loadoverlay ENDP
-
- ;-------------------------------------------------------------------------------
-
- ovlrlc PROC NEAR ; ds:0 -> the overlay to relocate
-
- ASSUME DS:NOTHING,ES:ovltbl
-
- mov si,OFFSET hdr
- mov bp,si
- add bp,EXEHDRTMPSIZ ; ^ to end of buf+1
- mov cx,cs:[si.relocitems] ; roto-count
- jcxz relocdone ; not such a good idea, after all
- mov di,ds
- sub di,ovlrootcode ; segment fixup value
- add si,cs:[si.reloctbloff] ; ^ relocation table
- dorelocs: ; labels don't GET comments
- cmp si,bp ; past the end ?
- jc getoffsetl
- call getnxtreloc ; get another hunk
- getoffsetl:
- mov bl,cs:[si] ; offset into load module
- inc si
- cmp si,bp ; past the end ?
- jc getoffseth
- call getnxtreloc ; get another hunk
- getoffseth:
- mov bh,cs:[si] ; offset into load module
- inc si
- cmp si,bp ; past the end ?
- jc getsegmentl
- call getnxtreloc ; get another hunk
- getsegmentl:
- mov al,cs:[si] ; segment in load module (zero reference)
- inc si
- cmp si,bp ; past the end ?
- jc getsegmenth
- call getnxtreloc ; get another hunk
- getsegmenth:
- mov ah,cs:[si] ; segment in load module (zero reference)
- inc si
- add ax,pspadd ; now it is psp relative
- add ax,di ; and now it is relative to the actual load address
- mov ds,ax
- mov ax,[bx] ; pickup item to relocate
- add ax,pspadd ; make it psp relative
- cmp ax,ovlrootcode ; is it below the OVERLAY_AREA?
- jc reloccomputed ; yup. it's relocated
- cmp ax,ovldata ; is it above OVERLAY_AREA
- jnc reloccomputed ; yup. it's relocated
- add ax,di ; it's in OVERLAY_AREA, this one's ours.
- reloccomputed:
- mov [bx],ax ; RAM it home!?!
- loop dorelocs ; what goes around, comes around.
- relocdone: ret
-
- ovlrlc ENDP
-
- ;-------------------------------------------------------------------------------
-
- getnxtreloc PROC NEAR
-
- ASSUME DS:NOTHING,ES:ovltbl
-
- push bx
- push cx
- push di
- push bp
- push ds
- push es
- mov cx,EXEHDRTMPSIZ ; reloc buffer size
- mov dx,OFFSET hdr
- mov ax,cs
- mov ds,ax
- mov bl,ovlflg
- and bx,MASK file
- mov bx,ovlfilhdl[bx] ; never closing handle
- mov ah,DOSREAD ; prevent random DOS behaviour
- int DOS ; read in header
- jnc nxtrelocok
- jmp burnhead ; double oops!
- nxtrelocok:
- mov si,OFFSET hdr
- pop es
- pop ds
- pop bp
- pop di
- pop cx
- pop bx
- ret
-
- getnxtreloc ENDP
-
- ;-------------------------------------------------------------------------------
-
- getvictim PROC NEAR ; select a victim to discard (and free up some memory)
-
- ASSUME DS:ovltbl,ES:NOTHING
-
- push bx
- push cx
- push dx
- push si
- push di
- push bp
- push ds
- mov ds,ovltblbse ; ^ ovl tbl
- IFDEF i386
- OP32
- ENDIF
- xor ax,ax ; will contain the low word of lru
- IFDEF i386
- OP32
- ENDIF
- mov dx,ax ; will contain the high word of lru
- mov bp,ax ; will contain ovl tbl entry
- mov bx,ax ; ovl tbl ptr
- mov cx,ovlcnt
- foon1:
- test ovlflg[bx],MASK locked
- jnz skip1
- test ovlflg[bx],MASK ems
- jnz foon2
- test ovlflg[bx],MASK loaded
- jz skip1
- foon2:
- IFDEF i386
- OP32
- ENDIF
- mov si,WORD PTR ovltim
- IFNDEF i386
- mov di,WORD PTR ovltim+2
- ENDIF
- IFDEF i386
- OP32
- ENDIF
- sub si,WORD PTR ovllrudat[bx]
- IFNDEF i386
- sbb di,WORD PTR ovllrudat[bx+2]
- ENDIF
- IFDEF i386
- OP32
- cmp dx,si
- ELSE
- cmp dx,di
- ENDIF
- IFDEF i386
- jnc skip1
- ELSE
- jc better1
- jnz skip1
- cmp ax,si
- jnc skip1
- ENDIF
- better1:
- IFDEF i386
- OP32
- mov dx,si
- ELSE
- mov ax,si
- mov dx,di
- ENDIF
- mov bp,bx
- skip1:
- add bx,OVLSEGSIZ
- loop foon1
- or bp,bp ; were we more successful this time?
- jnz gotvictim ; now we got one.
- nomoremem:
- mov al,VICTIMERR ; were really %$# now!
- jmp putserr
- gotvictim:
- shr bp,1 ; convert offset to segment
- shr bp,1
- shr bp,1
- shr bp,1
- mov ax,ds
- add ax,bp
- pop ds
- pop bp
- pop di
- pop si
- pop dx
- pop cx
- pop bx
- ret
-
- getvictim ENDP
-
- ;-------------------------------------------------------------------------------
-
- int21 PROC FAR
-
- ; free almost all overlay memory if app. tries to call the DOS exec function.
-
- cmp ah,DOSEXEC
- jz freeall
- cmp ah,TERMINATE
- jz saybyebye
- notours:
- jmp cs:oldint21
- saybyebye:
- mov al,NOERR ; return code 0
- jmp putserr
- freeall:
- or al,al ; is it load and exec?
- jnz notours
- push ax
- push cx
- push dx
- push bx
- push bp
- push si
- push di
- push es
- push ds ; preserve calling env.
-
- ASSUME DS:NOTHING,ES:ovltbl
-
- mov es,ovltblbse
- mov cx,ovlcnt ; unload all overlays that are
- mov bx,OVLSEGSIZ ; in EMS or are in alloced mem.
- dec cx
- memunloadlp:
- test [bx.ovlflg],MASK ems
- jnz memunload
- test [bx.ovlflg],MASK loaded
- jz nxtmemunload
- mov ax,[bx.ovlmemblk]
- sub ax,MEMCTLBLKSIZ
- cmp ax,memblks ; allocated memory ?
- jc nxtmemunload
- memunload:
- and [bx.ovlflg],NOT MASK loaded ; you're outta there!
- nxtmemunload:
- add bx,OVLSEGSIZ
- loop memunloadlp
-
- mov curemshandle,-1 ; no current handle anymore
-
- mov ax,memblks
- cmp ax,-1
- jz nosecondblk
- mov es,ax ; ^ to second mem blk
- mov es,es:memblkprv ; get previous pointer
- mov es:memblknxt,0 ; no other blocks after this one
- nosecondblk:
- mov cx,16 ; do all allocated mem blocks
- mov si,OFFSET memblks
- freememblklp:
- mov ax,cs:[si] ; get memory blk segment
- cmp ax,-1 ; was one ever allocated?
- jz nxtmemblklp ; nope
- mov es,ax
- mov ah,DOSFREE ; must free it.
- int DOS
- mov WORD PTR cs:[si],-1
- nxtmemblklp:
- add si,2
- loop freememblklp
-
- call rstvectors ; restore all int vectors
-
- mov bp,sp
- push [bp+22] ; ensure returned flags are based on user's!
- popf
- pop ds
- pop es
- pop di
- pop si
- pop bp
- pop bx
- pop dx
- pop cx
- pop ax
-
- mov ssreg,ss ; preserve these due to a
- mov spreg,sp ; DOS bug.
-
- int DOS ; allow DOS to continue!
-
- mov ss,ssreg
- mov sp,spreg
-
- push ax
- push cx
- push dx
- push bx
- push bp
- push si
- push di
- push es
- push ds ; preserve calling env.
- mov bp,sp
- pushf
- pop [bp+22] ; fix return flags
-
- call getmoreram ; re-allocate our memory
- call setvectors ; patch vectors again
-
- pop ds
- pop es
- pop di
- pop si
- pop bp
- pop bx
- pop dx
- pop cx
- pop ax
- iret
-
- int21 ENDP
-
- ;-------------------------------------------------------------------------------
-
- releasepages PROC NEAR ; Arg in es, result in ax
-
- ; release any memory (and overlays) where this overlay should reside
-
- ASSUME DS:NOTHING,ES:ovltbl
-
- mov bx,ovlmemblk ; start of memory to release
- sub bx,MEMCTLBLKSIZ
- mov dx,bx
- add dx,es:ovlsiz
- add dx,MEMCTLBLKSIZ ; end of memory to release
- mov ax,ovlemshdl
- cmp ax,-1
- jz doitagain
- call mappage
- or ovlflg,MASK ems
- mov ax,emsframe
- jmp dvart
- doitagain:
- mov ax,memblk1st ; first memory blk
- jmp dvart
- dvartloop:
- mov ds,ax ; memory blk to check
- cmp bx,ax ; does it start below the memory to release?
- jnc dvartsmaller ; yup
- cmp ax,dx ; does it start above?
- jnc dvartnocore ; yup
- call killmem ; it's in the way. Zap it.
- jmp dvartloop
- dvartsmaller:
- add ax,ds:memblksiz ; end of this memory blk
- cmp bx,ax ; does it end below the memory to release?
- jnc dvartsilly ; yup
- test ds:memblkflg,MASK_used
- jz dvartfree
- call killmem ; Oh well, zap it too.
- add ax,ds:memblksiz ; end of this memory blk
- dvartfree:
- cmp ax,dx ; does it end in the memory to be released?
- jc dvartsilly
- dvartgotblk:
- mov ax,ds ; this is it!
- mov cx,bx
- sub cx,ax ; # of paragraphs between start of memory to release and mem blk
- jz unsplit
- push es
- call splitblk
- or es:memblkflg,MASK_used ; set high block used
- call mergemem ; merge remaining free memory
- mov ax,es
- mov ds,ax
- pop es
- unsplit:
- mov cx,es:ovlsiz
- add cx,MEMCTLBLKSIZ ; paragraphs needed to load ovl
- jmp splitblklow ; split remaining block
- dvartsilly:
- mov ax,ds:memblknxt
- dvart:
- or ax,ax ; end of mem list?
- jz dvartnocore
- jmp dvartloop ; play it again Sam.
- dvartnocore:
- mov al,RELERR ; super OOPS!
- jmp putserr
-
- releasepages ENDP
-
- ;-------------------------------------------------------------------------------
-
- getpages PROC NEAR ; get enough memory to load ovl
-
- ASSUME DS:NOTHING,ES:ovltbl
-
- mov ovlemshdl,-1 ; clear any EMS stuff
- and ovlflg,NOT MASK ems
- mov cx,ax
- add cx,MEMCTLBLKSIZ ; total paragraphs needed
- dorkagain:
- call largestmem ; find largest free blk
- cmp dx,cx ; large enough?
- jnc gotdork ; yup.
- call getemsmem ; try to allocate ems
- cmp dx,cx ; any available ?
- jnc gotdork
- dorkkill:
- call getvictim ; select a victim to release
- call killovl ; kill the selected victim
- jmp dorkagain
- gotdork:
- jmp splitblklow ; split the free blk
-
- getpages ENDP
-
- ;-------------------------------------------------------------------------------
-
- splitblklow PROC NEAR
-
- ; split a block of memory returning the lower one to be used.
-
- ASSUME DS:NOTHING,ES:NOTHING
-
- push es
- or ds:memblkflg,MASK_used ; set low block used
- call splitblk
- jc splitlowdone
- push ds
- mov ax,es
- mov ds,ax
- call mergemem ; merge remaining free memory
- pop ds
- splitlowdone:
- pop es
- mov ds:memblkovl,es ; fix ptr to ovl
- mov ax,ds ; return lower blk segment
- ret
-
- splitblklow ENDP
-
- ;-------------------------------------------------------------------------------
-
- splitblk PROC NEAR
-
- ASSUME DS:NOTHING,ES:NOTHING
-
- mov ax,ds
- add ax,cx
- mov es,ax ; ^ to upper blk to be created
- mov ax,ds:memblksiz
- sub ax,cx
- jbe nofix ; must be at least 1 para remaining to split
- mov ds:memblksiz,cx ; fix blk sizes
- mov es:memblksiz,ax
- mov ax,ds:memblknxt ; fix pointers
- mov es:memblknxt,ax
- mov ds:memblknxt,es
- mov es:memblkprv,ds
- mov es:memblkflg,0 ; set upper to not used
- mov ax,es:memblknxt
- or ax,ax
- jz nofix
- push ds
- mov ds,ax ; fix blk after upper to point to upper
- mov ds:memblkprv,es
- pop ds
- clc
- ret
- nofix:
- stc
- ret
-
- splitblk ENDP
-
- ;-------------------------------------------------------------------------------
-
- largestmem PROC NEAR ; returns seg in ax, size in dx
- ; retruns first block that's large enough if possible
-
- ASSUME DS:NOTHING,ES:ovltbl
-
- mov ax,memblk1st ; first mem blk
- xor dx,dx ; largest size found
- jmp gook
- gookloop:
- mov ds,ax
- test ds:memblkflg,MASK_used ; is this blk used?
- jnz gookme ; yup
- cmp ds:memblksiz,cx ; is it large enough?
- jc gookme ; nope
- mov dx,ds:memblksiz ; got one!
- ret
- gookme:
- mov ax,ds:memblknxt
- gook:
- or ax,ax ; end of list?
- jnz gookloop ; around and around
- ret
-
- largestmem ENDP
-
- ;-------------------------------------------------------------------------------
-
- killmem PROC NEAR
-
- ASSUME DS:NOTHING,ES:ovltbl
-
- test ds:memblkflg,MASK_used ; is it used?
- jz memnotused ; don't kill ovl
- push es
- mov es,ds:memblkovl
- and ovlflg,NOT MASK loaded ; zap ovl associated with this blk
- and ovlflg,NOT MASK ems
- pop es
- memnotused:
- jmp mergemem ; merge free memory
-
- killmem ENDP
-
- ;-------------------------------------------------------------------------------
-
- killovl PROC NEAR ; preserves bx
-
- ASSUME DS:ovltbl,ES:NOTHING
-
- mov ds,ax
- and ovlflg,NOT MASK loaded ; ovl no longer loaded
- test ovlflg,MASK ems ; was it in ems ?
- jz noemskill
- and ovlflg,NOT MASK ems ; no longer in ems
- mov ax,ovlemshdl
- call mappage
- noemskill:
- mov ax,ovlmemblk ; get mem blk
- sub ax,MEMCTLBLKSIZ
- mov ds,ax
- jmp mergemem ; merge free memory
-
- killovl ENDP
-
- ;-------------------------------------------------------------------------------
-
- mergemem PROC NEAR
-
- ; merge physically adjacent free memory blocks. Preserves es. ds -> a free block.
-
- ASSUME DS:NOTHING,ES:NOTHING
-
- push dx
- push es
- and ds:memblkflg,NOT MASK_used ; set current free
- mov ax,ds:memblkprv ; get previous blk
- or ax,ax ; was there a previous blk?
- jz gibber ; nope
- mov es,ax
- test es:memblkflg,MASK_used ; is the previous blk used?
- jnz gibber ; yup
- add ax,es:memblksiz ; end of previous blk
- mov dx,ds
- cmp dx,ax ; physically adjacent?
- jnz gibber ; nope
- mov ax,ds:memblksiz
- add es:memblksiz,ax ; adjust size of new larger blk
- mov ax,ds:memblknxt ; fix pointers
- mov es:memblknxt,ax
- or ax,ax
- jz almostgibber
- mov ds,ax ; fix pointer of next blk
- mov ds:memblkprv,es
- almostgibber:
- mov ax,es
- mov ds,ax ; new blk segment
- gibber:
- mov ax,ds:memblknxt ; get next blk
- or ax,ax ; was there a next blk?
- jz killdone ; nope
- mov es,ax
- test es:memblkflg,MASK_used ; is the nxt blk used?
- jnz killdone ; yup
- mov ax,ds
- add ax,ds:memblksiz ; end of this blk
- mov dx,es
- cmp ax,dx ; physically adjacent?
- jnz killdone ; nope
- mov ax,es:memblksiz
- add ds:memblksiz,ax ; adjust size of new larger blk
- mov ax,es:memblknxt ; fix pointers
- mov ds:memblknxt,ax
- or ax,ax
- jz killdone
- mov es,ax ; fix pointer of blk after nxt
- mov es:memblkprv,ds
- killdone:
- and ds:memblkflg,NOT MASK_used ; make sure it's free
- pop es
- pop dx
- mov ax,ds
- ret
-
- mergemem ENDP
-
- ;-------------------------------------------------------------------------------
-
- getmoreram PROC NEAR ; try to alloc remaining pieces
- ; of memory if any
- ASSUME DS:NOTHING,ES:NOTHING ; return dx = biggest block
-
- push cx
- push bx
- push si
- push di
- push ds
- push es
- xor dx,dx
- mov ax,memblk1st
- nxtlowblk:
- mov ds,ax
- mov ax,ds:memblknxt
- or ax,ax
- jnz nxtlowblk
-
- mov si,OFFSET memblks ; a place to store the handles
- mov di,OFFSET tempmem ; a place to store the rejects
- mov cx,16 ; 16 more max
- getramlp:
- mov ah,DOSALLOC
- mov bx,0ffffh ; Everything
- int DOS
- cmp bx,10h ; nothing smaller than .25k please
- jc gotallram
- mov ah,DOSALLOC ; allocate our own memory
- int DOS
- jc gotallram ; oops!
- cmp ax,ovltblbse ; is it after our first mem blk?
- jc releaseblk
- cmp dx,bx
- jnc notbigger
- mov dx,bx
- notbigger:
- mov cs:[si],ax ; save it
- mov es,ax
- mov es:memblkflg,0 ; clear mem flags
- mov es:memblknxt,0 ; set next to nothing
- mov es:memblkovl,0 ; no overlays loaded
- mov es:memblkprv,ds ; point to previous
- mov es:memblksiz,bx ; allocated memory block size
- mov ds:memblknxt,es ; point to next
- add si,2
- mov ds,ax
- jmp short getnxtram
- releaseblk:
- mov cs:[di],ax
- add di,2
- getnxtram:
- loop getramlp
- gotallram:
- mov si,OFFSET tempmem
- mov cx,16
- releaselp:
- mov ax,cs:[si]
- cmp ax,-1
- jz relnext
- mov es,ax
- mov ah,DOSFREE
- int DOS
- mov WORD PTR cs:[si],-1
- relnext:
- add si,2
- loop releaselp
- pop es
- pop ds
- pop di
- pop si
- pop bx
- pop cx
- ret
-
- getmoreram ENDP
-
- ;-------------------------------------------------------------------------------
-
- getemsmem PROC NEAR
-
- ASSUME DS:NOTHING,ES:ovltbl
-
- xor dx,dx ; no ems memory
- cmp emmflg,-1
- jz testemsslots
- ret
- testemsslots:
- mov curemshandle,-1
- mov di,OFFSET emsmemblks
- mov bx,cx
- mov cx,16
- emsfreeslot:
- mov ax,cs:[di]
- cmp ax, -1
- jz gotemsslot
- call mappage
- cmp ax,bx
- jnc foundpage
- add di,2
- loop emsfreeslot
- mov cx,bx
- xor dx,dx
- ret
- gotemsslot:
- mov cx,bx
- mov bx,4
- mov ah,EMMALLOC
- push cx ; paranoia ! shouldn't be necessary.
- push di
- push es
- int EMM
- pop es
- pop di
- pop cx
- or ah,ah
- jz gotsomeems
- xor dx,dx
- ret
- gotsomeems:
- mov cs:[di],dx
- mov ovlemshdl,dx
- or ovlflg,MASK ems
- mov ax,dx
- call mapemspages
- mov ax,emsframe
- mov ds,ax
- mov ds:memblkflg,0 ; clear mem flags
- mov ds:memblknxt,0 ; set next to nothing
- mov ds:memblkprv,0 ; set previous to nothing
- mov ds:memblkovl,0 ; no overlay loaded
- mov dx,1000h
- mov ds:memblksiz,dx
- ret
-
- foundpage:
- mov cx,bx
- mov ds,si
- mov dx,ax
- mov ax,cs:[di]
- mov ovlemshdl,ax
- or ovlflg,MASK ems
- ret
-
- getemsmem ENDP
-
- ;-------------------------------------------------------------------------------
-
- mappage PROC NEAR ; map a 64K block of EMS mem.
-
- ASSUME DS:NOTHING,ES:ovltbl
-
- cmp ax,curemshandle
- jnz doems
- ret
- doems:
- push bx
- push dx
- push ds
- push es
- call mapemspages
- mov ax,emsframe
- xor dx,dx
- xor si,si
- emsset:
- mov ds,ax
- test ds:memblkflg,MASK_used ; mem blk used ?
- jz emsfreeblk
- mov es,ds:memblkovl
- or ovlflg,MASK ems OR MASK loaded
- jmp emsnext
- emsfreeblk:
- mov ax,ds:memblksiz
- cmp dx,ax
- jnc emsnext
- mov dx,ax
- mov si,ds
- emsnext:
- mov ax,ds:memblknxt
- or ax,ax
- jnz emsset
-
- mov ax,dx
- pop es
- pop ds
- pop dx
- pop bx
- ret
-
- mappage ENDP
-
- ;-------------------------------------------------------------------------------
-
- mapemspages PROC NEAR
-
- ASSUME DS:NOTHING,ES:ovltbl
-
- push es
- push bx
- push cx
- push dx
- mov curemshandle,ax
- mov dx,ax
- mov ah,EMMMAP
- xor al,al ; physical page 0
- xor bx,bx ; logical page 0
- push dx
- int EMM
- pop dx
- or ah,ah
- jnz emmerror
- mov ah,EMMMAP
- mov al,1 ; physical page 1
- mov bx,1 ; logical page 1
- push dx
- int EMM
- pop dx
- or ah,ah
- jnz emmerror
- mov ah,EMMMAP
- mov al,2 ; physical page 2
- mov bx,2 ; logical page 2
- push dx
- int EMM
- pop dx
- or ah,ah
- jnz emmerror
- mov ah,EMMMAP
- mov al,3 ; physical page 3
- mov bx,3 ; logical page 3
- int EMM
- or ah,ah
- jnz emmerror
- mov es,ovltblbse
- mov cx,ovlcnt
- xor bx,bx
- testems:
- test ovlflg[bx],MASK ems
- jz nxttestems
- and ovlflg[bx],NOT MASK loaded
- nxttestems:
- add bx,OVLSEGSIZ
- loop testems
- pop dx
- pop cx
- pop bx
- pop es
- ret
-
- emmerror:
- mov al,EMSERR ; ems manager error
- jmp putserr
-
- mapemspages ENDP
-
- ;-------------------------------------------------------------------------------
-
- gethdr PROC NEAR ; read EXE header from handle
-
- ASSUME DS:NOTHING,ES:NOTHING
-
- mov dx,OFFSET hdr ; a place to put it
- mov bx,si
- shl bx,1
- mov bx,ovlfilhdl[bx] ; the file handle
- readagain:
- mov cx,TYPE EXEHDR ; header size in bytes
- mov ah,DOSREAD
- int DOS ; read from file
- jc exegone ; oops?
- cmp ax,cx ; got correct number of bytes?
- je gothdr
- IFNDEF NOSPLIT
- cmp ax,0 ; Anything?
- je gotonxtfil
- ENDIF
- jmp exerotten
- IFNDEF NOSPLIT
- gotonxtfil:
- inc si
- cmp si,MAXFILES+1
- je exegone ; We're out of files!
- mov bx,si
- shl bx,1
- cmp ovlfilhdl[bx],-1 ; Any more files?
- je gotonxtfil ; not here.
-
- mov bx,ovlfilhdl[bx] ; Slide in new handle
- xor bp,bp ; reset file offset
- jmp readagain
- ENDIF
- gothdr:
- cmp hdr.exesign,EXESIGNUM ; sanity check
- jne exerotten
-
- ret ; Wow, it worked!
- exegone:
- mov al,NOHDRERR ; missing overlays!
- jmp putserr ; You lose!
- IFNDEF NOSPLIT
- exerotten:
- mov al,HDRERR ; corruption!
- jmp putserr ; You lose!
- ENDIF
-
- gethdr ENDP
-
- ;-------------------------------------------------------------------------------
-
- openfiles PROC NEAR ; Find our cohorts in crime
-
- push es
- IFNDEF NOSPLIT
- mov ah,DOSGETDTA ; Pick up DTA
- int DOS ; and
- mov dtaseg,es ; store
- mov dtaoffset,bx ; it
-
- push ds
- mov dx,OFFSET ovldta ; Set new DTA for file search
- mov ax,cs
- mov ds,ax ; point to the right seg
- mov ah,DOSSETDTA
- int DOS
- pop ds ; set this back for upcoming lodsb
- ENDIF
- mov cx,MAXNAMESIZE/2
- mov bx,cs
- mov es,bx
- mov di, OFFSET filestring
-
- rep movsw ; load path from si to di
- IFNDEF NOSPLIT
- mov di, OFFSET filestring
- mov al,0
- mov cx,MAXNAMESIZE
- cld
- repne scasb ; search null for end of string
-
- sub cx,MAXNAMESIZE
- neg cx
- mov bx,cx
-
- cmp cx,MAXNAMESIZE
- je checkslash
-
- dec bx ; keep string length
- dec di ; cause were past null now
-
- cmp bx,7
- jle patherr ; "C:\.EXE" = 7
- checkslash:
- mov ax,DOSGETSWITCH ; divine switchar
- int DOS ; it influences the path
-
- mov al,'\' ; if swichar = '/' pathsep = '\'
- cmp dl,'/'
- je searchslash
- mov al,'/' ; else pathsep = '/'
- searchslash:
- std
- repne scasb ; search back for '\'
- cld
-
- mov dx,bx
- sub dx,cx ; keep file name length
- dec dx
-
- mov cx,0 ; reset for upcoming loop
- mov pathlen,bx ; hold these for recall
- mov namelen,dx
- cmp dx,12 ; "LONGNAME.EXE" = 12
- jle openroot ; Path name too long?
- patherr:
- mov al,NAMERR ; real problems here.
- jmp putserr
- openroot:
- ENDIF
- mov ax,cs
- mov ds,ax ; set ds to code
-
- mov dx, OFFSET filestring ; open root code
- mov al,0 ; access code
- mov ah,DOSOPEN
- int DOS ; open sez me
- jnc dontdie
-
- mov al,FILEERR ; can't open root
- jmp putserr
- dontdie:
- mov ovlfilhdl[0],ax ; save handle in array
- IFNDEF NOSPLIT
- cmp namelen,11 ; Max sized exe name (8.3)?
- jg bigfilename ; if not
- inc pathlen ; add one to path length
- inc namelen
- bigfilename:
- mov di,OFFSET filestring ; es is still code
- add di,pathlen
- sub di,5 ; append
- mov si,OFFSET ovlext ; wildcard extension
- mov cx,6 ; and null
- rep movsb ; to filestring
-
- mov cx,0 ; Match "normal" files
- mov dx,OFFSET filestring
- mov ah,DOSSEARCH
- int DOS ; Set DTA with Wildcard.
- jc aok ; Not a single match
- mov cx,MAXFILES ; set upcoming loop
- mov dx,namelen
- sub pathlen,dx ; shorten absolute path
- openloop:
- push cx
- mov bx,pathlen
- mov di,OFFSET filestring ; es is still in code
- add di,bx
- mov si,OFFSET ovldta.file_name
- mov cx,namelen ; since this *should* be
- rep movsb
- pop cx
-
- mov dx,OFFSET filestring ; path to overlay file
- mov al,0 ; access code
- mov ah,DOSOPEN
- int DOS ; open overlay file
- jnc dontdie2
- fileopenerr:
- call itoa
-
- mov al,OVLERR ; can't open file!
- jmp putserr
- dontdie2:
- mov bx,cx ; put file number in bx
- shl bx,1 ; 2 * bx for array index
- mov ovlfilhdl[bx],ax ; save handle in array
-
- mov ah,DOSNEXTFILE ; Look for more files
- int DOS
- jc aok
-
- loop openloop ; open only 15 overlays
- aok:
- mov dx,dtaoffset ; Time to unset DTA
- mov ds,dtaseg
- mov ah,DOSSETDTA
- int DOS
- ENDIF
- pop es
-
- ret
-
- openfiles ENDP
-
- ;-------------------------------------------------------------------------------
-
- putserr PROC NEAR
-
- ; display error msg, close file, restore int vectors, free mem and return to DOS.
-
- ASSUME DS:NOTHING,ES:NOTHING
-
- xor ah,ah
- push ax ; keep return code for later
- push cs
- pop ds
- mov bx,ax
- shl bx,1
- add bx,OFFSET errortbl
- mov dx,[bx]
- cmp dx,-1
- jz freeints
- push dx
- mov dx,OFFSET msghead
- mov ah,PRINT
- int DOS
- pop dx
- mov ah,PRINT
- int DOS ; display error msg
-
- mov ah,PRINT
- mov dx,OFFSET diag
- int DOS
- pop ax
- push ax
- call itoa ; error number
- mov ah,DOSPUTC
- mov dl,':'
- int DOS
- mov ax,VERSION
- call itoa ; version number
- mov ah,DOSPUTC
- mov dl,':'
- int DOS
- mov ax,0a000h
- sub ax,ovltblbse ; conventional memory
- call itoa
- mov ah,DOSPUTC
- mov dl,':'
- int DOS
- mov si,OFFSET emsmemblks
- mov cx,16
- xor ax,ax
- emstotlp:
- cmp WORD PTR cs:[si],-1
- jz gotemstot
- add ax,emmframesiz
- add si,2
- loop emstotlp
- gotemstot:
- call itoa ; ems usage in blocks
- mov ah,DOSPUTC
- mov dl,')'
- int DOS
-
- mov dx,OFFSET msgtail
- mov ah,PRINT
- int DOS
- freeints:
- call rstvectors ; restore all int vectors
-
- mov ax,ovltblbse
- cmp ax,-1
- jz freememblks
- mov es,ax
- mov ah,DOSFREE
- int DOS
- freememblks:
- mov cx,16 ; do all allocated mem blocks
- mov si,OFFSET memblks
- freememlp:
- mov ax,cs:[si] ; get memory blk segment
- cmp ax,-1 ; was one ever allocated?
- jz nxtmemlp ; nope
- mov es,ax
- mov ah,DOSFREE ; must free it.
- int DOS
- nxtmemlp:
- add si,2
- loop freememlp
- mov cx,16 ; do all allocated ems blocks
- mov si,OFFSET emsmemblks
- freeemsmemlp:
- mov dx,cs:[si] ; get memory blk segment
- cmp dx,-1 ; was one ever allocated?
- jz nxtemsmemlp ; nope
- mov ah,EMMFREE ; must free it.
- int EMM
- nxtemsmemlp:
- add si,2
- loop freeemsmemlp
- closefile:
- IFNDEF NOSPLIT
- mov cx,MAXFILES+1
- nextfile:
- mov bx,cx
- dec bx
- shl bx,1
- mov bx,ovlfilhdl[bx] ; get file handle
- ELSE
- mov bx,ovlfilhdl[0]
- ENDIF
- cmp bx,-1 ; was the file ever opened?
- jz byebye ; nope
- mov ah,DOSCLOSE ; close it
- int DOS
- byebye:
- IFNDEF NOSPLIT
- loop nextfile
- ENDIF
- pop ax ; return code in al
- mov ah,TERMINATE
- int DOS ; terminate this process
-
- putserr ENDP
-
- ;-------------------------------------------------------------------------------
-
- itoa PROC NEAR
-
- push ax
- xchg ah,al
- call putbyte
- pop ax
- jmp putbyte
-
- itoa ENDP
-
- ;-------------------------------------------------------------------------------
-
- putbyte PROC NEAR
-
- push ax
- shr al,1
- shr al,1
- shr al,1
- shr al,1
- call nibble
- pop ax
- jmp nibble
-
- putbyte ENDP
-
- ;-------------------------------------------------------------------------------
-
- nibble PROC NEAR
-
- push ax
- and al,0fh
- add al,30h
- cmp al,3ah
- jc nibok
- add al,7
- nibok:
- push dx
- mov dl,al
- mov ah,DOSPUTC
- int DOS
- pop dx
- pop ax
- ret
-
- nibble ENDP
-
- ;-------------------------------------------------------------------------------
-
- setvectors PROC NEAR
-
- push ds
- xor ax,ax
- mov ds,ax
- mov si,cs:intnum
- cli
- mov ax,[si]
- mov WORD PTR cs:oldvec,ax ; save original vector
- mov ax,[si+2]
- mov WORD PTR cs:oldvec+2,ax
- mov ax,OFFSET ovlmgr ; point to ovlmgr
- mov [si],ax ; set int vector
- mov [si+2],cs
-
- mov si,DOS*4
- mov ax,[si]
- mov WORD PTR cs:oldint21,ax ; save original vector
- mov ax,[si+2]
- mov WORD PTR cs:oldint21+2,ax
- mov ax,OFFSET int21 ; point to new int21
- mov [si],ax ; set int vector
- mov [si+2],cs
- sti
- pop ds
- ret
-
- setvectors ENDP
-
- ;-------------------------------------------------------------------------------
-
- rstvectors PROC NEAR
-
- push ds
- xor ax,ax
- mov ds,ax
- mov si,DOS*4
- cli
- mov ax,WORD PTR cs:oldint21 ; put back dos vector
- cmp ax,-1
- jz rstvec
- mov [si],ax
- mov ax,WORD PTR cs:oldint21+2
- mov [si+2],ax
- rstvec:
- mov si,cs:intnum
- mov ax,WORD PTR cs:oldvec ; put back ovlmgr vector
- cmp ax,-1
- jz rstdone
- mov [si],ax
- mov ax,WORD PTR cs:oldvec+2
- mov [si+2],ax
- sti
- rstdone:
- pop ds
- ret
-
- rstvectors ENDP
-
- code ENDS
-
- END
-