home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 January
/
usenetsourcesnewsgroupsinfomagicjanuary1994.iso
/
sources
/
games
/
volume16
/
nethack31
/
part18
< prev
next >
Wrap
Internet Message Format
|
1993-02-01
|
60KB
Path: uunet!news.tek.com!master!saab!billr
From: billr@saab.CNA.TEK.COM (Bill Randle)
Newsgroups: comp.sources.games
Subject: v16i018: nethack31 - display oriented dungeons & dragons (Ver. 3.1), Part18/108
Message-ID: <4301@master.CNA.TEK.COM>
Date: 28 Jan 93 19:14:22 GMT
Sender: news@master.CNA.TEK.COM
Lines: 2518
Approved: billr@saab.CNA.TEK.COM
Xref: uunet comp.sources.games:1574
Submitted-by: izchak@linc.cis.upenn.edu (Izchak Miller)
Posting-number: Volume 16, Issue 18
Archive-name: nethack31/Part18
Supersedes: nethack3p9: Volume 10, Issue 46-102
Environment: Amiga, Atari, Mac, MS-DOS, OS2, Unix, VMS, X11
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 18 (of 108)."
# Contents: src/worn.c sys/msdos/ovlmgr.asm
# Wrapped by billr@saab on Wed Jan 27 16:08:52 1993
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'src/worn.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/worn.c'\"
else
echo shar: Extracting \"'src/worn.c'\" \(8567 characters\)
sed "s/^X//" >'src/worn.c' <<'END_OF_FILE'
X/* SCCS Id: @(#)worn.c 3.1 92/12/13
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* NetHack may be freely redistributed. See license for details. */
X
X#include "hack.h"
X
Xstatic void FDECL(rel_1_obj, (struct monst *,struct obj *));
X
Xconst struct worn {
X long w_mask;
X struct obj **w_obj;
X} worn[] = {
X { W_ARM, &uarm },
X { W_ARMC, &uarmc },
X { W_ARMH, &uarmh },
X { W_ARMS, &uarms },
X { W_ARMG, &uarmg },
X { W_ARMF, &uarmf },
X#ifdef TOURIST
X { W_ARMU, &uarmu },
X#endif
X { W_RINGL, &uleft },
X { W_RINGR, &uright },
X { W_WEP, &uwep },
X { W_AMUL, &uamul },
X { W_TOOL, &ublindf },
X { W_BALL, &uball },
X { W_CHAIN, &uchain },
X { 0, 0 }
X};
X
Xvoid
Xsetworn(obj, mask)
Xregister struct obj *obj;
Xlong mask;
X{
X register const struct worn *wp;
X register struct obj *oobj;
X
X for(wp = worn; wp->w_mask; wp++) if(wp->w_mask & mask) {
X oobj = *(wp->w_obj);
X if(oobj && !(oobj->owornmask & wp->w_mask))
X impossible("Setworn: mask = %ld.", wp->w_mask);
X if(oobj) {
X oobj->owornmask &= ~wp->w_mask;
X /* leave as "x = x <op> y", here and below, for broken
X * compilers */
X u.uprops[objects[oobj->otyp].oc_oprop].p_flgs =
X u.uprops[objects[oobj->otyp].oc_oprop].p_flgs &
X ~wp->w_mask;
X if (oobj->oartifact) set_artifact_intrinsic(oobj, 0, mask);
X }
X *(wp->w_obj) = obj;
X if(obj) {
X obj->owornmask |= wp->w_mask;
X /* prevent getting intrinsics from wielding potions, etc... */
X /* wp_mask should be same as mask at this point */
X if(obj->oclass == WEAPON_CLASS || mask != W_WEP) {
X u.uprops[objects[obj->otyp].oc_oprop].p_flgs =
X u.uprops[objects[obj->otyp].oc_oprop].p_flgs |
X wp->w_mask;
X if (obj->oartifact) set_artifact_intrinsic(obj,1,mask);
X } else if(obj->oartifact)
X set_artifact_intrinsic(obj,1,mask);
X }
X }
X}
X
X/* called e.g. when obj is destroyed */
Xvoid
Xsetnotworn(obj)
Xregister struct obj *obj;
X{
X register const struct worn *wp;
X
X if (!obj) return;
X for(wp = worn; wp->w_mask; wp++)
X if(obj == *(wp->w_obj)) {
X *(wp->w_obj) = 0;
X u.uprops[objects[obj->otyp].oc_oprop].p_flgs =
X u.uprops[objects[obj->otyp].oc_oprop].p_flgs &
X ~wp->w_mask;
X obj->owornmask &= ~wp->w_mask;
X if (obj->oartifact)
X set_artifact_intrinsic(obj, 0, wp->w_mask);
X }
X}
X
X#ifdef MUSE
Xint
Xfind_mac(mon)
Xregister struct monst *mon;
X{
X register struct obj *obj;
X int base = mon->data->ac;
X long mwflags = mon->misc_worn_check;
X
X for(obj = mon->minvent; obj; obj = obj->nobj) {
X if (obj->owornmask & mwflags)
X base -= ARM_BONUS(obj);
X }
X return base;
X}
X
X/* Wear first object of that type it finds, and never switch unless it
X * has none at all. This means that monsters with leather armor never
X * switch to plate mail, but it also avoids the overhead of having seven
X * struct obj *s for every monster in the game, more if we ever extend this.
X */
Xvoid
Xm_dowear(mon, creation)
Xregister struct monst *mon;
Xboolean creation;
X{
X register struct obj *obj;
X
X /* Note the restrictions here are the same as in dowear in do_wear.c
X * except for the additional restriction on intelligence. (Players
X * are always intelligent, even if polymorphed).
X */
X if (verysmall(mon->data) || nohands(mon->data)) return;
X if (is_animal(mon->data) || mindless(mon->data)) return;
X
X for(obj = mon->minvent; obj; obj = obj->nobj) {
X long flag;
X
X# ifdef TOURIST
X if (obj->otyp == HAWAIIAN_SHIRT) flag = W_ARMU;
X else
X# endif
X if (is_cloak(obj)) flag = W_ARMC;
X else if (is_helmet(obj)) flag = W_ARMH;
X else if (is_shield(obj)) {
X if (MON_WEP(mon) && bimanual(MON_WEP(mon)))
X continue;
X flag = W_ARMS;
X } else if (is_gloves(obj)) {
X if (MON_WEP(mon) && MON_WEP(mon)->cursed)
X continue;
X flag = W_ARMG;
X } else if (is_boots(obj)) flag = W_ARMF;
X else if (obj->oclass == ARMOR_CLASS) {
X#ifdef POLYSELF
X if (cantweararm(mon->data))
X continue;
X#endif
X flag = W_ARM;
X } else continue;
X if (mon->misc_worn_check & flag) continue;
X /* already wearing one */
X if (!creation && canseemon(mon)) {
X pline("%s puts on %s.", Monnam(mon),
X distant_name(obj, doname));
X mon->mfrozen = objects[obj->otyp].oc_delay;
X if (mon->mfrozen) mon->mcanmove = 0;
X }
X mon->misc_worn_check |= flag;
X obj->owornmask |= flag;
X }
X}
X
Xstruct obj *
Xwhich_armor(mon, flag)
Xstruct monst *mon;
Xlong flag;
X{
X register struct obj *obj;
X
X for(obj = mon->minvent; obj; obj = obj->nobj)
X if (obj->owornmask & flag) return obj;
X return((struct obj *)0);
X}
X
Xstatic void
Xrel_1_obj(mon, obj)
Xstruct monst *mon;
Xstruct obj *obj;
X{
X struct obj *otmp;
X struct obj *backobj = (struct obj *)0;
X
X for(otmp = mon->minvent; otmp; otmp = otmp->nobj) {
X if (obj == otmp) {
X if (!backobj) mon->minvent = otmp->nobj;
X else backobj->nobj = otmp->nobj;
X place_object(otmp, mon->mx, mon->my);
X otmp->nobj = fobj;
X fobj = otmp;
X if (cansee(mon->mx, mon->my)) newsym(mon->mx, mon->my);
X return;
X }
X backobj = otmp;
X }
X impossible("%s has %s missing?", Monnam(mon), xname(obj));
X}
X
Xvoid
Xmon_break_armor(mon)
Xstruct monst *mon;
X{
X register struct obj *otmp;
X struct permonst *mdat = mon->data;
X boolean vis = cansee(mon->mx, mon->my);
X const char *pronoun, *ppronoun;
X
X switch(gender(mon)) {
X case 0: pronoun = "him"; ppronoun = "his"; break;
X case 1: pronoun = ppronoun = "her"; break;
X default: pronoun = "it"; ppronoun = "its"; break;
X }
X if (breakarm(mdat)) {
X if (otmp = which_armor(mon, W_ARM)) {
X if (vis)
X pline("%s breaks out of %s armor!", Monnam(mon), ppronoun);
X else
X You("hear a cracking sound.");
X mon->misc_worn_check &= ~W_ARM;
X m_useup(mon, otmp);
X }
X if (otmp = which_armor(mon, W_ARMC)) {
X if (otmp->oartifact) {
X if (vis)
X pline("%s cloak falls off!", s_suffix(Monnam(mon)));
X mon->misc_worn_check &= ~W_ARMC;
X otmp->owornmask &= ~W_ARMC;
X rel_1_obj(mon, otmp);
X } else {
X if (vis)
X pline("%s cloak tears apart!", s_suffix(Monnam(mon)));
X else
X You("hear a ripping sound.");
X mon->misc_worn_check &= ~W_ARMC;
X m_useup(mon, otmp);
X }
X }
X# ifdef TOURIST
X if (otmp = which_armor(mon, W_ARMU)) {
X if (vis)
X pline("%s shirt rips to shreds!", s_suffix(Monnam(mon)));
X else
X You("hear a ripping sound.");
X mon->misc_worn_check &= ~W_ARMU;
X m_useup(mon, otmp);
X }
X# endif
X } else if (sliparm(mdat)) {
X if (otmp = which_armor(mon, W_ARM)) {
X if (vis)
X pline("%s armor falls around %s!",
X s_suffix(Monnam(mon)), pronoun);
X else
X You("hear a thud.");
X mon->misc_worn_check &= ~W_ARM;
X otmp->owornmask &= ~W_ARM;
X rel_1_obj(mon, otmp);
X }
X if (otmp = which_armor(mon, W_ARMC)) {
X if (vis)
X if (is_whirly(mon->data))
X pline("%s cloak falls, unsupported!",
X s_suffix(Monnam(mon)));
X else
X pline("%s shrinks out of %s cloak!", Monnam(mon),
X ppronoun);
X mon->misc_worn_check &= ~W_ARMC;
X otmp->owornmask &= ~W_ARMC;
X rel_1_obj(mon, otmp);
X }
X# ifdef TOURIST
X if (otmp = which_armor(mon, W_ARMU)) {
X if (vis)
X if (sliparm(mon->data))
X pline("%s seeps right through %s shirt!",
X Monnam(mon), ppronoun);
X else
X pline("%s becomes much too small for %s shirt!",
X Monnam(mon), ppronoun);
X mon->misc_worn_check &= ~W_ARMU;
X otmp->owornmask &= ~W_ARMU;
X rel_1_obj(mon, otmp);
X }
X# endif
X }
X if (nohands(mdat) || verysmall(mdat)) {
X if (otmp = which_armor(mon, W_ARMG)) {
X if (vis)
X pline("%s drops %s gloves%s!", Monnam(mon), ppronoun,
X MON_WEP(mon) ? " and weapon" : "");
X possibly_unwield(mon);
X mon->misc_worn_check &= ~W_ARMG;
X otmp->owornmask &= ~W_ARMG;
X rel_1_obj(mon, otmp);
X }
X if (otmp = which_armor(mon, W_ARMS)) {
X if (vis)
X pline("%s can no longer hold %s shield!", Monnam(mon),
X ppronoun);
X else
X You("hear a clank.");
X mon->misc_worn_check &= ~W_ARMS;
X otmp->owornmask &= ~W_ARMS;
X rel_1_obj(mon, otmp);
X }
X if (otmp = which_armor(mon, W_ARMH)) {
X if (vis)
X pline("%s helmet falls to the floor!",
X s_suffix(Monnam(mon)));
X else
X You("hear a clank.");
X mon->misc_worn_check &= ~W_ARMH;
X otmp->owornmask &= ~W_ARMH;
X rel_1_obj(mon, otmp);
X }
X if (otmp = which_armor(mon, W_ARMF)) {
X if (vis) {
X if (is_whirly(mon->data))
X pline("%s boots fall away!",
X s_suffix(Monnam(mon)));
X else pline("%s boots %s off %s feet!",
X s_suffix(Monnam(mon)),
X verysmall(mdat) ? "slide" : "are pushed", ppronoun);
X }
X mon->misc_worn_check &= ~W_ARMF;
X otmp->owornmask &= ~W_ARMF;
X rel_1_obj(mon, otmp);
X }
X }
X}
X#endif
X
X/*worn.c*/
END_OF_FILE
if test 8567 -ne `wc -c <'src/worn.c'`; then
echo shar: \"'src/worn.c'\" unpacked with wrong size!
fi
# end of 'src/worn.c'
fi
if test -f 'sys/msdos/ovlmgr.asm' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'sys/msdos/ovlmgr.asm'\"
else
echo shar: Extracting \"'sys/msdos/ovlmgr.asm'\" \(46506 characters\)
sed "s/^X//" >'sys/msdos/ovlmgr.asm' <<'END_OF_FILE'
X; SCCS Id: @(#)ovlmgr.asm 91/09/04
X; Copyright (c) 1989, 1990, 1991, 1992, 1993 Pierre Martineau and
X; Stephen Spackman. All Rights Reserved.
X; This product may be freely redistributed. See NetHack license for details.
X
XVERSION EQU 3100h
X
X PAGE 57,132
X TITLE 'DOS Overlay Manager for MSC 5.1+'
X SUBTTL 'Copyright (c) 1989, 1990, 1991, 1992, 1993 Pierre Martineau and Stephen Spackman. All Rights Reserved.'
X
X; Multiple overlay file support for v30a0 by Norm Meluch with some input from Stephen.
X
X; acknowledgements: - Many thanks to Norm Meluch for his invaluable help
X; - No thanks to Microsoft
X; - alltrsidsctysti!!!
X; - izchak and friends for impetus
X; - us for brilliance
X; - coffee for speed
X; - others as necessary
X
X; assumptions: - all registers are preserved including flags
X; - the stack is preserved
X; - re-entrancy is not required
X
X; options: /Di386 use 80386-specific opcodes
X; (faster, but no good for weaker machines)
X; /DNOEMS omit EMS support
X; (needed if application uses EMS)
X; /DNOSPLIT omit support for external .OVL files
X
XDOSALLOC EQU 48h ; memory allocation
XDOSFREE EQU 49h ; free allocated memory
XDOSREALLOC EQU 4ah ; modify memory block
XDOSREAD EQU 3fh ; read bytes from handle
XDOSSEEK EQU 42h ; logical handle seek
XDOSOPEN EQU 3dh ; open handle
XDOSCLOSE EQU 3eh ; close handle
XDOSSETDTA EQU 1ah ; Set Data transfer area
XDOSGETDTA EQU 2fh ; Get Data transfer area
XDOSSEARCH EQU 4eh ; Search for 1st file match
XDOSNEXTFILE EQU 4fh ; Search for next file match
XDOSEXEC EQU 4bh ; exec child process
XDOSPUTC EQU 02h ; print a char
XDOSVERSION EQU 30h ; get version number
XDOSGETVEC EQU 35h ; get interrupt vector
XDOSGETSWITCH EQU 3700h ; get DOS switchar
XDOS EQU 21h ; Dos interrupt #
XPRINT EQU 09h ; print string
XTERMINATE EQU 4ch ; terminate process
XEMM EQU 67h ; EMM handler int vector
XEMMSTATUS EQU 40h ; get EMM status
XEMMFRAME EQU 41h ; get EMM page frame
XEMMTOTALS EQU 42h ; get EMM pages available
XEMMALLOC EQU 43h ; allocate EMM pages
XEMMMAP EQU 44h ; map EMM pages
XEMMFREE EQU 45h ; free EMM pages
XMAXNAMESIZE EQU 50h ; max path name size
XMAXFILES EQU 0Eh ; max # of *.OVL files
XEXESIGNUM EQU 5a4dh ; Exe header signature
XCR EQU 0dh
XLF EQU 0ah
XESCAPE EQU 1bh
XBELL EQU 07h
XPARSIZ EQU 10h ; this is the size of a paragraph - this better not change!
XFAERIE EQU 00h ; Used for dummy segment allocation
X
XNOERR EQU 0
XDOSERR EQU 1
XFILEERR EQU 2
XNOMEMERR EQU 3
XFILEIOERR EQU 4
XVICTIMERR EQU 5
XRELERR EQU 6
XEMSERR EQU 7
XHDRERR EQU 8
XNAMERR EQU 9
XOVLERR EQU 10
XNOHDRERR EQU 11
X
X; The following EXTRNs are supplied by the linker
X
XEXTRN $$OVLBASE:BYTE ; segment of OVERLAY_AREA
XEXTRN $$MPGSNOVL:BYTE ; ^ to module table
XEXTRN $$MPGSNBASE:WORD ; ^ to module segment fixups
XEXTRN $$INTNO:BYTE ; interrupt number to be used
XEXTRN $$COVL:WORD ; number of physical overlays
XEXTRN $$CGSN:WORD ; number of modules
XEXTRN $$MAIN:FAR ; ^ to function main()
X
XPUBLIC $$OVLINIT ; Our entry point
X ; called by the c startup code
XIFDEF i386
XOP32 MACRO ; 32 bit operand override
X DB 066h
X ENDM
X
Xpusha MACRO ; push all registers
X DB 060h
X ENDM
X
Xpopa MACRO ; pop all registers
X DB 061h
X ENDM
XENDIF
X
Xovlflgrec RECORD locked:1=0,ems:1=0,loaded:1=0,file:4=0,pad:1 ; overlay flags
X ; "file" is the overlay file this overlay is in; 0 is the .EXE
X ; itself. Otherwise, the numbers are arbitrary.
X
X; This is a dirty hack. What we need is a virtual segment that will be built
X; by the (our) loader in multiple copies, one per overlay. Unfortunately, this
X; doesn't seem to be a sensible idea in the minds of the folks at Microsoft.
X; Declaring this segment AT will ensure that it never appears in the exefile,
X; and ASSUME is dumb enough to be fooled.
X;
X; The reason we want to do this is also not-to-be-tried-at-home: it turns out
X; that we can code a faster interrupt handler if we map overlay numbers to
X; segment values. Normally we would consider this unacceptable programming
X; practise because it is 86-mode specific, but the *need* for this entire
X; programme is 86-mode specific, anyway.
X
Xpspseg SEGMENT PARA AT FAERIE ; dummy segment for psp
X ORG 2ch ; ^ to segment of environmemt in psp
Xpspenv LABEL WORD
Xpspseg ENDS
X
Xovltbl SEGMENT PARA AT FAERIE ; Dummy segment definition for overlay table
X
X; NOTE: This segment definition MUST be exactly 16 bytes long
X
Xovlflg ovlflgrec <0,0,0,0,0> ; overlay flags
Xovlinvcnt DB ? ; invocation count
Xovlmemblk DW ? ; ^ to allocated memory block
Xovllrudat DD ? ; misc lru data (pseudo time stamp)
Xovlemshdl DW ? ; ovl ems memory handle
Xovlfiloff DW ? ; ovl file offset in pages (512 bytes)
Xovlsiz DW ? ; ovl size in paragraphs
Xovlhdrsiz DW ? ; hdr size in paragraphs
X
XIF1
XIF ($ - ovlflg) GT PARSIZ
X .ERR
X %OUT This segment MUST be no more than 16 bytes, REALLY!!!
XENDIF
XENDIF
X
XOVLSEGSIZ EQU PARSIZ ; this had better be true!!! (16 bytes)
X
Xovltbl ENDS
X
XDTASTRUC STRUC ; internal DTA for ovlmgr
X DB 21 DUP (0)
Xfile_attr DB 0
Xfile_time DW 0
Xfile_date DW 0
Xfile_size DD 0
Xfile_name DB 9 DUP (0)
Xfile_ext DB 3 DUP (0)
Xdtapad DB 86 DUP (0) ; Pad to 128 bytes
XDTASTRUC ENDS
X
XEXEHDR STRUC ; structure of an EXE header
Xexesign DW EXESIGNUM ; signature
Xexelstpgesiz DW ? ; last page size (512 byte pages)
Xexesiz DW ? ; total pages (including partial last page)
Xrelocitems DW ? ; number of relocation entries
Xhdrparas DW ? ; number of paragraphs in the header
Xminalloc DW ? ; minimum paragraph allocation
Xmaxalloc DW ? ; maximum patagraph allocation
Xexess DW ? ; initial stack segment
Xexesp DW ? ; initial stack pointer
Xexechksum DW ? ; checksum
Xexeip DW ? ; initial instruction pointer
Xexecs DW ? ; initial code segment
Xreloctbloff DW ? ; offset from beginning of header to relocation table
Xexeovlnum DW ? ; overlay number
XEXEHDR ENDS
X
XMASK_used EQU 1 ; memory block flag
X
XMEMCTLBLK STRUC ; memory block structure
Xmemblkflg DB ? ; flags
Xmemblkpad1 DB ? ; go ahead, delete me!
Xmemblknxt DW ? ; ^ to next block
Xmemblkprv DW ? ; ^ to previous block
Xmemblkovl DW ? ; ^ to overlay occupying this block
Xmemblksiz DW ? ; size in paragraphs
Xmemblkpad DB PARSIZ - memblkpad MOD PARSIZ DUP (?) ; pad to 16 bytes
XMEMCTLBLK ENDS
X
XMEMCTLBLKSIZ EQU TYPE MEMCTLBLK / PARSIZ ; should equal 1 paragraph
X
X;-------------------------------------------------------------------------------
X
Xcode SEGMENT PUBLIC
X
X; NOTE: the following order is optimum for alignment purposes across the
X; entire INTEL 80x86 family of processors.
X
Xovltim DD ? ; pseudo-lru time variable
Xfarcall DD ? ; internal trampoline.
Xoldvec DD -1 ; saved interrupt vector
Xoldint21 DD -1 ; saved int 21 vector
Xsireg DW ? ; temp save area
XIFDEF i386
X DW ? ; for esi
XENDIF
Xdsreg DW ? ; temp save area
Xssreg DW ?
Xspreg DW ?
Xovlfilhdl DW MAXFILES+1 DUP (-1) ; always-open file handles for .EXE, .OVL
Xovltblbse DW -1 ; segment of first overlay descriptor
Xmemblks DW 16 DUP (-1) ; allocated memory blocks
Xmemblk1st DW ? ; first memory block
Xemsmemblks DW 16 DUP (-1) ; ems allocated memory blocks (64K each)
Xcuremshandle DW -1 ; currently mapped handle
Xovlcnt DW ? ; # overlays
Xmodcnt DW ? ; # of modules
Xovlrootcode DW ? ; logical segment of OVERLAY_AREA
Xovldata DW ? ; logical segment of OVERLAY_END
Xpspadd DW ? ; our psp address + 10h (for relocations)
Xemsframe DW ? ; EMM page frame segment
Xmoduletbl DD 256 DUP (?) ; module lookup table (256 modules)
Xcurovl DW OFFSET stkframe ; ^ into stack frame
Xstkframe DW 256*3 DUP (?) ; internal stack (256 ovls deep)
Xtempmem DW 16 DUP (-1) ; temp mem block storage
Xintnum DW ? ; ovlmgr int number
Xhdr EXEHDR <> ; EXE header work area
X DB 512-TYPE EXEHDR DUP (?) ; exe hdr buffer for relocations
XEXEHDRTMPSIZ EQU $ - hdr ; size of temp reloc buffer
Xfilestring DB MAXNAMESIZE DUP (0) ; string space for file specs
Xpathlen DW ? ; path length of file spec
Xnamelen DW ? ; length of file names
Xovldta DTASTRUC <> ; DTA for ovlmgr use
Xdtaseg DW ? ; DTA segment for program
Xdtaoffset DW ? ; DTA offset for program
Xerrortbl DW -1 ; error message pointers
X DW OFFSET baddos
X DW OFFSET nofile
X DW OFFSET noroom
X DW OFFSET badio
X DW OFFSET nocore
X DW OFFSET nocore
X DW OFFSET badems
X DW OFFSET badhdr
X DW OFFSET badnam
X DW OFFSET noovl
X DW OFFSET nohdr
X DW OFFSET unknown
X DW OFFSET unknown
X DW OFFSET unknown
X DW OFFSET unknown
Xemmname DB "EMMXXXX0" ; EMM device driver name
Xemmtot DW 0 ; total emm blocks free
Xemmframesiz DW 4 ; frame size in blocks
Xemmflg DB 0 ; EMM present flag
X
Xi386code DB '386 specific code enabled.',CR,LF,'$'
Xmemavl DB 'Conventional memory available: $'
Xparagraphs DB 'H paragraphs.',CR,LF,'$'
Xemsavl DB 'EMS memory available: $'
Xpages DB 'H 16K-pages.',CR,LF,'$'
Xbaddos DB 'Incorrect DOS version. Must be 3.00 or later.$'
Xnofile DB 'Inaccessible EXE file. Can',39,'t load overlays.$'
Xnoroom DB 'Not enough free memory left to run this program.$'
Xbadio DB 'File I/O error.$'
Xnocore DB 'Internal memory allocation failure.$'
Xbadems DB 'EMS memory manager error.$'
Xbadhdr DB 'Executable or overlay header missing or damaged.$'
Xbadnam DB 'Unable to resolve overlay file names.$'
Xnoovl DB 'Inaccessible OVL file. Can',39,'t load overlays.$'
Xnohdr DB 'Incomplete executable. OVL files missing?$'
Xunknown DB 'Unknown error!$'
Xmsghead DB ESCAPE,'[0m',ESCAPE,'[K',CR,LF,ESCAPE,'[K',ESCAPE,'[1mOVLMGR:',ESCAPE,'[0m $'
Xdiag DB ESCAPE,'[K',CR,LF,ESCAPE,'[K',' ($'
Xmsgtail DB ESCAPE,'[K',CR,LF,ESCAPE,'[K',BELL,'$'
Xovlext DB '?.OVL',0
X
X;-------------------------------------------------------------------------------
X
X$$OVLINIT PROC FAR ; Init entry point
X
X ASSUME CS:code,DS:pspseg,ES:NOTHING
X
X push ax
X push bx
X push cx
X push dx
X push si
X push di
X push bp
X push ds
X push es ; save the world
X
X cld
X mov ax,ds ; get our psp
X add ax,10h
X mov pspadd,ax ; save it
X mov ah,DOSVERSION
X int DOS
X cmp al,3 ; DOS 3.0 or later
X jnc doenvthing
X mov al,DOSERR ; incorrect version of dos
X jmp putserr
Xdoenvthing:
X mov ds,pspenv ; get environment segment
X mov si,-1
Xenvloop: ; search for end of environment
X inc si
X cmp WORD PTR [si],0
X jnz envloop
X add si,4 ; point to EXE filename
X
X call openfiles ; Search & open overlay files
XIFNDEF NOEMS
Xchkems:
X mov ah,DOSGETVEC
X mov al,EMM
X int DOS
X mov ax,cs
X mov ds,ax
X mov di,0ah
X mov si,OFFSET emmname
X mov cx,8
X repe cmpsb
X mov al,0
X jnz setemmflg
X mov al,-1
Xsetemmflg:
X mov emmflg,al
X jnz noemshere
X mov ah,EMMFRAME
X int EMM
X mov emsframe,bx
X mov ah,EMMTOTALS
X int EMM
X mov emmtot,bx
Xnoemshere:
XENDIF
X mov ax,SEG $$OVLBASE ; OVERLAY_AREA segment
X mov ovlrootcode,ax
X mov ax,SEG $$COVL ; segment of DGROUP
X mov ds,ax
X mov bx,$$CGSN ; number of modules
X mov modcnt,bx ; save for later use
X mov bx,$$COVL ; number of physical overlays
X mov ovlcnt,bx ; save for later use
X
X; Now allocate memory
X mov ah,DOSALLOC ; bx contains # paras needed for ovltbl
X int DOS
X jnc gotovlram
X jmp buyram
Xgotovlram:
X mov ovltblbse,ax ; overlay descriptor table begins at start of memory block
X
X mov cx,ovlcnt
Xzeromem:
X mov es,ax
X mov es:ovlflg,0 ; initialise ovl flags
X mov es:ovlinvcnt,0 ; initialise invocation count
X mov es:ovlmemblk,0
X mov WORD PTR es:ovllrudat,0 ; initialise ovl lru
X mov WORD PTR es:ovllrudat+2,0
X mov es:ovlemshdl,-1
X mov es:ovlfiloff,0 ; initialize file offset
X mov es:ovlsiz,0 ; initialize overlay size
X mov es:ovlhdrsiz,0
X inc ax
X loop zeromem
X
X mov ax,cs
X mov ds,ax
XIFDEF DEBUG
XIFDEF i386
X mov ah,print
X mov dx,OFFSET msghead
X int DOS
X mov ah,print
X mov dx,OFFSET i386code
X int DOS
XENDIF
X mov ah,print
X mov dx,OFFSET msghead
X int DOS
X mov ah,print
X mov dx,OFFSET memavl
X int DOS
X mov ax,0a000h
X sub ax,ovltblbse
X call itoa
X mov ah,print
X mov dx,OFFSET paragraphs
X int DOS
XIFNDEF NOEMS
X mov ah,print
X mov dx,OFFSET msghead
X int DOS
X mov ah,print
X mov dx,OFFSET emsavl
X int DOS
X mov ax,emmtot
X call itoa
X mov ah,print
X mov dx,OFFSET pages
X int DOS
XENDIF
XENDIF
X ASSUME ES:ovltbl
X
X xor bp,bp
X xor di,di
X xor si,si ; file handle loop ctr
Xfilsegtbllpp: ; initialise ovl table
X call gethdr ; get an EXE header
X
X mov ax,ovltblbse
X add ax,hdr.exeovlnum
X mov es,ax ; ^ to ovl table entry
XIFNDEF NOSPLIT
X mov cx,si ; set file # in ovlflg
X shl cx,1
X mov ovlflg,cl
XENDIF
X mov ax,hdr.exesiz
X shl ax,1
X shl ax,1
X shl ax,1
X shl ax,1
X shl ax,1 ; * 32
X mov dx,hdr.exelstpgesiz
X or dx,dx
X jz emptypage
X shr dx,1
X shr dx,1
X shr dx,1
X shr dx,1 ; / 16
X inc dx
X sub ax,20h
X add ax,dx
Xemptypage:
X sub ax,hdr.hdrparas ; actual size of code
X mov ovlsiz,ax ; overlay size in paragraphs
X cmp hdr.exeovlnum,0 ; skip if ovl 0 (root code)
X jz notlargest
X cmp ax,di ; find largest ovl
X jc notlargest
X mov di,ax
Xnotlargest:
X mov ax,hdr.hdrparas
X shl ax,1
X shl ax,1
X shl ax,1
X shl ax,1
X mov ovlhdrsiz,ax ; hdr size in bytes
X mov ovlfiloff,bp ; initialise ovl file offset
X add bp,hdr.exesiz ; ^ to next overlay
X mov dx,bp
X mov cl,dh
X mov dh,dl
X xor ch,ch
X xor dl,dl
X shl dx,1
X rcl cx,1 ; cx:dx = bp * 512
X mov al,0
X mov ah,DOSSEEK ; seek to next ovl
X int DOS
X
X mov cx,ovlcnt ; check if all overlays found
X mov ax,ovltblbse
X dec cx ; ovlcnt includes root
X add ax,cx
Xovloop:
X mov es,ax
XIFNDEF NOSPLIT
X mov bl,ovlflg
X and bx,MASK file
X
X cmp bx,0 ; if file # is 0
X jne again
XENDIF
X cmp ovlfiloff,0 ; and offset is 0
X jne again
X jmp filsegtbllpp ; then we're still looking
Xagain:
X dec ax
X loop ovloop
X
X ASSUME ES:nothing ; prepare first memory block
X
X mov ax,ovlrootcode ; OVERLAY_AREA segment
X mov memblk1st,ax ; save pointer to first mem block
X mov es,ax
X mov es:memblkflg,0 ; clear mem flags
X mov es:memblknxt,0 ; set next to nothing
X mov es:memblkprv,0 ; set previous to nothing
X mov es:memblkovl,0 ; no overlay loaded
X mov es:memblksiz,di ; di contains OVERLAY_AREA size in paragraphs
X add ax,di
X mov ovldata,ax ; end of OVERLAY_END
X push di
X mov es,ovltblbse ; temporary
X call getemsmem ; see if any ems available
X mov es:ovlemshdl,-1 ; fix these!
X and es:ovlflg,NOT MASK ems
X push dx
X call getmoreram ; see if there are any other pieces lying around
X pop ax
X pop di
X or ax,ax ; any ems?
X jnz noramcheck
X inc di
X cmp dx,di
X jc buyram
Xnoramcheck:
X mov WORD PTR ovltim,0 ; initialise global lru time stamp
X mov WORD PTR ovltim+2,0
X mov di,OFFSET stkframe
X mov WORD PTR cs:[di],-1 ; initialise stack frame
X add di,6
X mov ax,ovltblbse
X mov cs:[di],ax
X mov curovl,di ; initialise stack frame pointer
X mov es,ax
X mov es:ovlflg,MASK locked OR MASK loaded ; set flags on ovl 0
X jmp short chgintvec
Xbuyram:
X mov al,NOMEMERR ; free up some TSRs or something
X jmp putserr
Xchgintvec:
X mov ax,SEG $$INTNO
X mov ds,ax
X mov al,$$INTNO ; get int number to use
X xor ah,ah
X shl ax,1
X shl ax,1
X mov intnum,ax
X call setvectors ; set up interrupt vectors
X mov cx,modcnt ; module count
X mov ax,SEG $$MPGSNBASE
X mov es,ax
X mov ax,cs
X mov ds,ax
X
X ASSUME DS:code
X
X mov bx,OFFSET $$MPGSNBASE ; ^ to linker provided overlay segment fixups
X mov si,OFFSET $$MPGSNOVL ; ^ to linker provided module table
X mov di,OFFSET moduletbl ; ^ to our module table
Xmodloop:
X mov al,es:[si] ; real physical ovl number
X xor ah,ah
X add ax,ovltblbse ; ovlctlseg address
X mov [di],ax ; save in module table
X mov ax,es:[bx] ; get seg fixup
X sub ax,ovlrootcode ; adjust for relative reference
X mov [di+2],ax ; save in module table
X add di,4
X add bx,2
X inc si
X loop modloop
X pop es
X pop ds
X pop bp
X pop di
X pop si
X pop dx
X pop cx
X pop bx
X pop ax ; restore the world
X jmp $$MAIN ; And away we go!
X
X$$OVLINIT ENDP
X
X;-------------------------------------------------------------------------------
X
Xovlmgr PROC FAR ; This is the it!
X
X ASSUME DS:NOTHING,ES:NOTHING
X
XIFDEF i386
X OP32
XENDIF
X mov sireg,si ; preserve si
X mov dsreg,ds ; and ds
X pop si ; retrieve caller ip
X pop ds ; " " cs
X push ax
X push bx
X cld
X lodsb ; module # to call
X xor ah,ah
X mov bx,ax
X lodsw ; offset in ovl to call
X mov WORD PTR farcall,ax ; into trampoline
X mov ax,si
X mov si,curovl ; get stack frame pointer
X add si,6 ; update stack
X mov cs:[si-4],ds ; save return seg
X mov cs:[si-2],ax ; and return offset
X
X shl bx,1
X shl bx,1 ; * 4 (2 words/entry in module tbl)
X add bx,OFFSET moduletbl
X mov ds,cs:[bx] ; ovl tbl entry
X mov ax,cs:[bx+2] ; segment fixup
X mov cs:[si],ds ; ovl entry into stack frame
X mov curovl,si
X
X ASSUME DS:ovltbl
X
XIFDEF i386
X OP32
XENDIF
X mov si,WORD PTR ovltim ; lru time stamp
XIFDEF i386
X OP32
XENDIF
X inc si ; time passes!
XIFDEF i386
X OP32
XENDIF
X mov WORD PTR ovltim,si ; update global clock
XIFDEF i386
X OP32
XENDIF
X mov WORD PTR ovllrudat,si ; as well as ovl clock
XIFNDEF i386
X mov si,WORD PTR ovltim+2
X jz ininc ; dword increment
Xcryupcdon:
X mov WORD PTR ovllrudat+2,si ; as well as ovl clock
XENDIF
X test ovlflg,MASK loaded ; ovl loaded?
X jz inload ; load it or map it then.
Xovlloadedupc:
X inc ovlinvcnt
X add ax,ovlmemblk ; add fixup and segment address
X mov WORD PTR farcall+2,ax ; into trampoline
XIFDEF i386
X OP32
XENDIF
X mov si,sireg ; retore all registers
X mov ds,dsreg
X pop bx
X pop ax
X popf ; don't forget these!
X call DWORD PTR farcall ; and GO
X pushf ; preserve registers again!
X mov dsreg,ds
XIFDEF i386
X OP32
XENDIF
X mov sireg,si
X mov si,curovl ; stack frame pointer
X mov ds,cs:[si]
X dec ovlinvcnt
X sub si,6 ; adjust stack
X mov ds,cs:[si] ; retrieve ovl tbl entry
X push cs:[si+2] ; set return address
X push cs:[si+4]
X mov curovl,si
XIFDEF i386
X OP32
XENDIF
X mov si,WORD PTR ovltim ; do the lru thing again
XIFDEF i386
X OP32
XENDIF
X inc si
XIFDEF i386
X OP32
XENDIF
X mov WORD PTR ovltim,si
XIFDEF i386
X OP32
XENDIF
X mov WORD PTR ovllrudat,si
XIFNDEF i386
X mov si,WORD PTR ovltim+2
X jz outinc
Xcrydncdon:
X mov WORD PTR ovllrudat+2,si
XENDIF
X test ovlflg,MASK loaded ; ovl loaded?
X jz outload ; better get it before someone notices
Xjmpback:
XIFDEF i386
X OP32
XENDIF
X mov si,sireg ; get registers back
X mov ds,dsreg
X iret ; and GO back
X
XIFNDEF i386
Xininc:
X inc si
X mov WORD PTR ovltim+2,si ; update global and
X jmp cryupcdon
XENDIF
X
Xinload:
X test ovlflg,MASK ems
X jz infile
X push ax
X mov ax,ovlemshdl
X call mappage
X pop ax
X jmp ovlloadedupc
Xinfile:
X call loadoverlay ; self explanatory
X jmp ovlloadedupc
X
XIFNDEF i386
Xoutinc:
X inc si
X mov WORD PTR ovltim+2,si
X jmp crydncdon
XENDIF
X
Xoutload:
X test ovlflg,MASK ems
X jz outfile
X push ax
X mov ax,ovlemshdl
X call mappage
X pop ax
X jmp jmpback
Xoutfile:
X call loadoverlay
X jmp jmpback
X
Xovlmgr ENDP
X
X;-------------------------------------------------------------------------------
X
Xloadoverlay PROC NEAR ; load overlay pointed to by es
X
X ASSUME DS:NOTHING,ES:ovltbl
X
XIFDEF i386
X OP32
X pusha ; eax,ecx,edx,ebx,esp,ebp,esi,edi
XELSE
X push ax
X push cx
X push dx
X push bx
X push bp
X push si
X push di
XENDIF
X push ds
X push es ; just in case
X mov ax,ds
X mov es,ax
X cmp ovlinvcnt,0
X jnz fxdadr ; Yup, it's a toughie
X mov ax,ovlsiz ; How much?
X call getpages ; never fail mem alloc, you bet.
X jmp gleaner
Xfxdadr:
X call releasepages ; free memory where this ovl should be loaded
Xgleaner:
X add ax,MEMCTLBLKSIZ ; skip mem ctl blk
X mov ovlmemblk,ax ; memory block to use
X mov ds,ax
X mov dx,ovlfiloff ; where in the file is it?
X mov cl,dh
X mov dh,dl
X xor ch,ch
X xor dl,dl
X shl dx,1
X rcl cx,1 ; cx:dx = dx * 512
X mov ax,ovlhdrsiz
X push cx
X push dx
X add dx,ax
X adc cx,0 ; position to code
X mov ah,DOSSEEK ; lseek to code
X mov al,0 ; from beginning of file
X mov bl,ovlflg
X and bx,MASK file
X mov bx,ovlfilhdl[bx] ; never closing handle
X int DOS
X jc burnhead ; oops!
X xor dx,dx ; buf = ds:0
X mov cx,ovlsiz ; number of paragraphs to load
X shl cx,1
X shl cx,1
X shl cx,1
X shl cx,1 ; * 16 = number of bytes
X mov ah,DOSREAD ; prevent random DOS behaviour
X int DOS ; read in code
X jc burnhead ; double oops!
X pop dx
X pop cx ; position of hdr
X mov ah,DOSSEEK ; lseek to hdr
X mov al,0 ; from beginning of file
X mov bl,ovlflg
X and bx,MASK file
X mov bx,ovlfilhdl[bx] ; never closing handle
X int DOS
X jc burnhead ; oops!
X mov cx,EXEHDRTMPSIZ ; reloc buffer size
X mov dx,OFFSET hdr
X push ds
X mov ax,cs
X mov ds,ax
X mov ah,DOSREAD ; prevent random DOS behaviour
X int DOS ; read in header
X pop ds
X jc burnhead ; double oops!
X
X call ovlrlc ; perform relocation normally done by DOS EXE loader
X pop es ; retrieve ovl tbl entry
X pop ds
X
X ASSUME DS:ovltbl,ES:NOTHING
X
X or ovlflg,MASK loaded ; because it is now
XIFDEF i386
X OP32
X popa
XELSE
X pop di
X pop si
X pop bp
X pop bx
X pop dx
X pop cx
X pop ax
XENDIF
X ret
X
Xburnhead:
X mov al,FILEIOERR ; some kind of I/O error
X jmp putserr
X
Xloadoverlay ENDP
X
X;-------------------------------------------------------------------------------
X
Xovlrlc PROC NEAR ; ds:0 -> the overlay to relocate
X
X ASSUME DS:NOTHING,ES:ovltbl
X
X mov si,OFFSET hdr
X mov bp,si
X add bp,EXEHDRTMPSIZ ; ^ to end of buf+1
X mov cx,cs:[si.relocitems] ; roto-count
X jcxz relocdone ; not such a good idea, after all
X mov di,ds
X sub di,ovlrootcode ; segment fixup value
X add si,cs:[si.reloctbloff] ; ^ relocation table
Xdorelocs: ; labels don't GET comments
X cmp si,bp ; past the end ?
X jc getoffsetl
X call getnxtreloc ; get another hunk
Xgetoffsetl:
X mov bl,cs:[si] ; offset into load module
X inc si
X cmp si,bp ; past the end ?
X jc getoffseth
X call getnxtreloc ; get another hunk
Xgetoffseth:
X mov bh,cs:[si] ; offset into load module
X inc si
X cmp si,bp ; past the end ?
X jc getsegmentl
X call getnxtreloc ; get another hunk
Xgetsegmentl:
X mov al,cs:[si] ; segment in load module (zero reference)
X inc si
X cmp si,bp ; past the end ?
X jc getsegmenth
X call getnxtreloc ; get another hunk
Xgetsegmenth:
X mov ah,cs:[si] ; segment in load module (zero reference)
X inc si
X add ax,pspadd ; now it is psp relative
X add ax,di ; and now it is relative to the actual load address
X mov ds,ax
X mov ax,[bx] ; pickup item to relocate
X add ax,pspadd ; make it psp relative
X cmp ax,ovlrootcode ; is it below the OVERLAY_AREA?
X jc reloccomputed ; yup. it's relocated
X cmp ax,ovldata ; is it above OVERLAY_AREA
X jnc reloccomputed ; yup. it's relocated
X add ax,di ; it's in OVERLAY_AREA, this one's ours.
Xreloccomputed:
X mov [bx],ax ; RAM it home!?!
X loop dorelocs ; what goes around, comes around.
Xrelocdone: ret
X
Xovlrlc ENDP
X
X;-------------------------------------------------------------------------------
X
Xgetnxtreloc PROC NEAR
X
X ASSUME DS:NOTHING,ES:ovltbl
X
X push bx
X push cx
X push di
X push bp
X push ds
X push es
X mov cx,EXEHDRTMPSIZ ; reloc buffer size
X mov dx,OFFSET hdr
X mov ax,cs
X mov ds,ax
X mov bl,ovlflg
X and bx,MASK file
X mov bx,ovlfilhdl[bx] ; never closing handle
X mov ah,DOSREAD ; prevent random DOS behaviour
X int DOS ; read in header
X jnc nxtrelocok
X jmp burnhead ; double oops!
Xnxtrelocok:
X mov si,OFFSET hdr
X pop es
X pop ds
X pop bp
X pop di
X pop cx
X pop bx
X ret
X
Xgetnxtreloc ENDP
X
X;-------------------------------------------------------------------------------
X
Xgetvictim PROC NEAR ; select a victim to discard (and free up some memory)
X
X ASSUME DS:ovltbl,ES:NOTHING
X
X push bx
X push cx
X push dx
X push si
X push di
X push bp
X push ds
X mov ds,ovltblbse ; ^ ovl tbl
XIFDEF i386
X OP32
XENDIF
X xor ax,ax ; will contain the low word of lru
XIFDEF i386
X OP32
XENDIF
X mov dx,ax ; will contain the high word of lru
X mov bp,ax ; will contain ovl tbl entry
X mov bx,ax ; ovl tbl ptr
X mov cx,ovlcnt
Xfoon1:
X test ovlflg[bx],MASK locked
X jnz skip1
X test ovlflg[bx],MASK ems
X jnz foon2
X test ovlflg[bx],MASK loaded
X jz skip1
Xfoon2:
XIFDEF i386
X OP32
XENDIF
X mov si,WORD PTR ovltim
XIFNDEF i386
X mov di,WORD PTR ovltim+2
XENDIF
XIFDEF i386
X OP32
XENDIF
X sub si,WORD PTR ovllrudat[bx]
XIFNDEF i386
X sbb di,WORD PTR ovllrudat[bx+2]
XENDIF
XIFDEF i386
X OP32
X cmp dx,si
XELSE
X cmp dx,di
XENDIF
XIFDEF i386
X jnc skip1
XELSE
X jc better1
X jnz skip1
X cmp ax,si
X jnc skip1
XENDIF
Xbetter1:
XIFDEF i386
X OP32
X mov dx,si
XELSE
X mov ax,si
X mov dx,di
XENDIF
X mov bp,bx
Xskip1:
X add bx,OVLSEGSIZ
X loop foon1
X or bp,bp ; were we more successful this time?
X jnz gotvictim ; now we got one.
Xnomoremem:
X mov al,VICTIMERR ; were really %$# now!
X jmp putserr
Xgotvictim:
X shr bp,1 ; convert offset to segment
X shr bp,1
X shr bp,1
X shr bp,1
X mov ax,ds
X add ax,bp
X pop ds
X pop bp
X pop di
X pop si
X pop dx
X pop cx
X pop bx
X ret
X
Xgetvictim ENDP
X
X;-------------------------------------------------------------------------------
X
Xint21 PROC FAR
X
X; free almost all overlay memory if app. tries to call the DOS exec function.
X
X cmp ah,DOSEXEC
X jz freeall
X cmp ah,TERMINATE
X jz saybyebye
Xnotours:
X jmp cs:oldint21
Xsaybyebye:
X mov al,NOERR ; return code 0
X jmp putserr
Xfreeall:
X or al,al ; is it load and exec?
X jnz notours
X push ax
X push cx
X push dx
X push bx
X push bp
X push si
X push di
X push es
X push ds ; preserve calling env.
X
X ASSUME DS:NOTHING,ES:ovltbl
X
X mov es,ovltblbse
X mov cx,ovlcnt ; unload all overlays that are
X mov bx,OVLSEGSIZ ; in EMS or are in alloced mem.
X dec cx
Xmemunloadlp:
X test [bx.ovlflg],MASK ems
X jnz memunload
X test [bx.ovlflg],MASK loaded
X jz nxtmemunload
X mov ax,[bx.ovlmemblk]
X sub ax,MEMCTLBLKSIZ
X cmp ax,memblks ; allocated memory ?
X jc nxtmemunload
Xmemunload:
X and [bx.ovlflg],NOT MASK loaded ; you're outta there!
Xnxtmemunload:
X add bx,OVLSEGSIZ
X loop memunloadlp
X
X mov curemshandle,-1 ; no current handle anymore
X
X mov ax,memblks
X cmp ax,-1
X jz nosecondblk
X mov es,ax ; ^ to second mem blk
X mov es,es:memblkprv ; get previous pointer
X mov es:memblknxt,0 ; no other blocks after this one
Xnosecondblk:
X mov cx,16 ; do all allocated mem blocks
X mov si,OFFSET memblks
Xfreememblklp:
X mov ax,cs:[si] ; get memory blk segment
X cmp ax,-1 ; was one ever allocated?
X jz nxtmemblklp ; nope
X mov es,ax
X mov ah,DOSFREE ; must free it.
X int DOS
X mov WORD PTR cs:[si],-1
Xnxtmemblklp:
X add si,2
X loop freememblklp
X
X call rstvectors ; restore all int vectors
X
X mov bp,sp
X push [bp+22] ; ensure returned flags are based on user's!
X popf
X pop ds
X pop es
X pop di
X pop si
X pop bp
X pop bx
X pop dx
X pop cx
X pop ax
X
X mov ssreg,ss ; preserve these due to a
X mov spreg,sp ; DOS bug.
X
X int DOS ; allow DOS to continue!
X
X mov ss,ssreg
X mov sp,spreg
X
X push ax
X push cx
X push dx
X push bx
X push bp
X push si
X push di
X push es
X push ds ; preserve calling env.
X mov bp,sp
X pushf
X pop [bp+22] ; fix return flags
X
X call getmoreram ; re-allocate our memory
X call setvectors ; patch vectors again
X
X pop ds
X pop es
X pop di
X pop si
X pop bp
X pop bx
X pop dx
X pop cx
X pop ax
X iret
X
Xint21 ENDP
X
X;-------------------------------------------------------------------------------
X
Xreleasepages PROC NEAR ; Arg in es, result in ax
X
X; release any memory (and overlays) where this overlay should reside
X
X ASSUME DS:NOTHING,ES:ovltbl
X
X mov bx,ovlmemblk ; start of memory to release
X sub bx,MEMCTLBLKSIZ
X mov dx,bx
X add dx,es:ovlsiz
X add dx,MEMCTLBLKSIZ ; end of memory to release
X mov ax,ovlemshdl
X cmp ax,-1
X jz doitagain
X call mappage
X or ovlflg,MASK ems
X mov ax,emsframe
X jmp dvart
Xdoitagain:
X mov ax,memblk1st ; first memory blk
X jmp dvart
Xdvartloop:
X mov ds,ax ; memory blk to check
X cmp bx,ax ; does it start below the memory to release?
X jnc dvartsmaller ; yup
X cmp ax,dx ; does it start above?
X jnc dvartnocore ; yup
X call killmem ; it's in the way. Zap it.
X jmp dvartloop
Xdvartsmaller:
X add ax,ds:memblksiz ; end of this memory blk
X cmp bx,ax ; does it end below the memory to release?
X jnc dvartsilly ; yup
X test ds:memblkflg,MASK_used
X jz dvartfree
X call killmem ; Oh well, zap it too.
X add ax,ds:memblksiz ; end of this memory blk
Xdvartfree:
X cmp ax,dx ; does it end in the memory to be released?
X jc dvartsilly
Xdvartgotblk:
X mov ax,ds ; this is it!
X mov cx,bx
X sub cx,ax ; # of paragraphs between start of memory to release and mem blk
X jz unsplit
X push es
X call splitblk
X or es:memblkflg,MASK_used ; set high block used
X call mergemem ; merge remaining free memory
X mov ax,es
X mov ds,ax
X pop es
Xunsplit:
X mov cx,es:ovlsiz
X add cx,MEMCTLBLKSIZ ; paragraphs needed to load ovl
X jmp splitblklow ; split remaining block
Xdvartsilly:
X mov ax,ds:memblknxt
Xdvart:
X or ax,ax ; end of mem list?
X jz dvartnocore
X jmp dvartloop ; play it again Sam.
Xdvartnocore:
X mov al,RELERR ; super OOPS!
X jmp putserr
X
Xreleasepages ENDP
X
X;-------------------------------------------------------------------------------
X
Xgetpages PROC NEAR ; get enough memory to load ovl
X
X ASSUME DS:NOTHING,ES:ovltbl
X
X mov ovlemshdl,-1 ; clear any EMS stuff
X and ovlflg,NOT MASK ems
X mov cx,ax
X add cx,MEMCTLBLKSIZ ; total paragraphs needed
Xdorkagain:
X call largestmem ; find largest free blk
X cmp dx,cx ; large enough?
X jnc gotdork ; yup.
X call getemsmem ; try to allocate ems
X cmp dx,cx ; any available ?
X jnc gotdork
Xdorkkill:
X call getvictim ; select a victim to release
X call killovl ; kill the selected victim
X jmp dorkagain
Xgotdork:
X jmp splitblklow ; split the free blk
X
Xgetpages ENDP
X
X;-------------------------------------------------------------------------------
X
Xsplitblklow PROC NEAR
X
X; split a block of memory returning the lower one to be used.
X
X ASSUME DS:NOTHING,ES:NOTHING
X
X push es
X or ds:memblkflg,MASK_used ; set low block used
X call splitblk
X jc splitlowdone
X push ds
X mov ax,es
X mov ds,ax
X call mergemem ; merge remaining free memory
X pop ds
Xsplitlowdone:
X pop es
X mov ds:memblkovl,es ; fix ptr to ovl
X mov ax,ds ; return lower blk segment
X ret
X
Xsplitblklow ENDP
X
X;-------------------------------------------------------------------------------
X
Xsplitblk PROC NEAR
X
X ASSUME DS:NOTHING,ES:NOTHING
X
X mov ax,ds
X add ax,cx
X mov es,ax ; ^ to upper blk to be created
X mov ax,ds:memblksiz
X sub ax,cx
X jbe nofix ; must be at least 1 para remaining to split
X mov ds:memblksiz,cx ; fix blk sizes
X mov es:memblksiz,ax
X mov ax,ds:memblknxt ; fix pointers
X mov es:memblknxt,ax
X mov ds:memblknxt,es
X mov es:memblkprv,ds
X mov es:memblkflg,0 ; set upper to not used
X mov ax,es:memblknxt
X or ax,ax
X jz nofix
X push ds
X mov ds,ax ; fix blk after upper to point to upper
X mov ds:memblkprv,es
X pop ds
X clc
X ret
Xnofix:
X stc
X ret
X
Xsplitblk ENDP
X
X;-------------------------------------------------------------------------------
X
Xlargestmem PROC NEAR ; returns seg in ax, size in dx
X ; retruns first block that's large enough if possible
X
X ASSUME DS:NOTHING,ES:ovltbl
X
X mov ax,memblk1st ; first mem blk
X xor dx,dx ; largest size found
X jmp gook
Xgookloop:
X mov ds,ax
X test ds:memblkflg,MASK_used ; is this blk used?
X jnz gookme ; yup
X cmp ds:memblksiz,cx ; is it large enough?
X jc gookme ; nope
X mov dx,ds:memblksiz ; got one!
X ret
Xgookme:
X mov ax,ds:memblknxt
Xgook:
X or ax,ax ; end of list?
X jnz gookloop ; around and around
X ret
X
Xlargestmem ENDP
X
X;-------------------------------------------------------------------------------
X
Xkillmem PROC NEAR
X
X ASSUME DS:NOTHING,ES:ovltbl
X
X test ds:memblkflg,MASK_used ; is it used?
X jz memnotused ; don't kill ovl
X push es
X mov es,ds:memblkovl
X and ovlflg,NOT MASK loaded ; zap ovl associated with this blk
X and ovlflg,NOT MASK ems
X pop es
Xmemnotused:
X jmp mergemem ; merge free memory
X
Xkillmem ENDP
X
X;-------------------------------------------------------------------------------
X
Xkillovl PROC NEAR ; preserves bx
X
X ASSUME DS:ovltbl,ES:NOTHING
X
X mov ds,ax
X and ovlflg,NOT MASK loaded ; ovl no longer loaded
X test ovlflg,MASK ems ; was it in ems ?
X jz noemskill
X and ovlflg,NOT MASK ems ; no longer in ems
X mov ax,ovlemshdl
X call mappage
Xnoemskill:
X mov ax,ovlmemblk ; get mem blk
X sub ax,MEMCTLBLKSIZ
X mov ds,ax
X jmp mergemem ; merge free memory
X
Xkillovl ENDP
X
X;-------------------------------------------------------------------------------
X
Xmergemem PROC NEAR
X
X; merge physically adjacent free memory blocks. Preserves es. ds -> a free block.
X
X ASSUME DS:NOTHING,ES:NOTHING
X
X push dx
X push es
X and ds:memblkflg,NOT MASK_used ; set current free
X mov ax,ds:memblkprv ; get previous blk
X or ax,ax ; was there a previous blk?
X jz gibber ; nope
X mov es,ax
X test es:memblkflg,MASK_used ; is the previous blk used?
X jnz gibber ; yup
X add ax,es:memblksiz ; end of previous blk
X mov dx,ds
X cmp dx,ax ; physically adjacent?
X jnz gibber ; nope
X mov ax,ds:memblksiz
X add es:memblksiz,ax ; adjust size of new larger blk
X mov ax,ds:memblknxt ; fix pointers
X mov es:memblknxt,ax
X or ax,ax
X jz almostgibber
X mov ds,ax ; fix pointer of next blk
X mov ds:memblkprv,es
Xalmostgibber:
X mov ax,es
X mov ds,ax ; new blk segment
Xgibber:
X mov ax,ds:memblknxt ; get next blk
X or ax,ax ; was there a next blk?
X jz killdone ; nope
X mov es,ax
X test es:memblkflg,MASK_used ; is the nxt blk used?
X jnz killdone ; yup
X mov ax,ds
X add ax,ds:memblksiz ; end of this blk
X mov dx,es
X cmp ax,dx ; physically adjacent?
X jnz killdone ; nope
X mov ax,es:memblksiz
X add ds:memblksiz,ax ; adjust size of new larger blk
X mov ax,es:memblknxt ; fix pointers
X mov ds:memblknxt,ax
X or ax,ax
X jz killdone
X mov es,ax ; fix pointer of blk after nxt
X mov es:memblkprv,ds
Xkilldone:
X and ds:memblkflg,NOT MASK_used ; make sure it's free
X pop es
X pop dx
X mov ax,ds
X ret
X
Xmergemem ENDP
X
X;-------------------------------------------------------------------------------
X
Xgetmoreram PROC NEAR ; try to alloc remaining pieces
X ; of memory if any
X ASSUME DS:NOTHING,ES:NOTHING ; return dx = biggest block
X
X push cx
X push bx
X push si
X push di
X push ds
X push es
X xor dx,dx
X mov ax,memblk1st
Xnxtlowblk:
X mov ds,ax
X mov ax,ds:memblknxt
X or ax,ax
X jnz nxtlowblk
X
X mov si,OFFSET memblks ; a place to store the handles
X mov di,OFFSET tempmem ; a place to store the rejects
X mov cx,16 ; 16 more max
Xgetramlp:
X mov ah,DOSALLOC
X mov bx,0ffffh ; Everything
X int DOS
X cmp bx,10h ; nothing smaller than .25k please
X jc gotallram
X mov ah,DOSALLOC ; allocate our own memory
X int DOS
X jc gotallram ; oops!
X cmp ax,ovltblbse ; is it after our first mem blk?
X jc releaseblk
X cmp dx,bx
X jnc notbigger
X mov dx,bx
Xnotbigger:
X mov cs:[si],ax ; save it
X mov es,ax
X mov es:memblkflg,0 ; clear mem flags
X mov es:memblknxt,0 ; set next to nothing
X mov es:memblkovl,0 ; no overlays loaded
X mov es:memblkprv,ds ; point to previous
X mov es:memblksiz,bx ; allocated memory block size
X mov ds:memblknxt,es ; point to next
X add si,2
X mov ds,ax
X jmp short getnxtram
Xreleaseblk:
X mov cs:[di],ax
X add di,2
Xgetnxtram:
X loop getramlp
Xgotallram:
X mov si,OFFSET tempmem
X mov cx,16
Xreleaselp:
X mov ax,cs:[si]
X cmp ax,-1
X jz relnext
X mov es,ax
X mov ah,DOSFREE
X int DOS
X mov WORD PTR cs:[si],-1
Xrelnext:
X add si,2
X loop releaselp
X pop es
X pop ds
X pop di
X pop si
X pop bx
X pop cx
X ret
X
Xgetmoreram ENDP
X
X;-------------------------------------------------------------------------------
X
Xgetemsmem PROC NEAR
X
X ASSUME DS:NOTHING,ES:ovltbl
X
X xor dx,dx ; no ems memory
X cmp emmflg,-1
X jz testemsslots
X ret
Xtestemsslots:
X mov curemshandle,-1
X mov di,OFFSET emsmemblks
X mov bx,cx
X mov cx,16
Xemsfreeslot:
X mov ax,cs:[di]
X cmp ax, -1
X jz gotemsslot
X call mappage
X cmp ax,bx
X jnc foundpage
X add di,2
X loop emsfreeslot
X mov cx,bx
X xor dx,dx
X ret
Xgotemsslot:
X mov cx,bx
X mov bx,4
X mov ah,EMMALLOC
X push cx ; paranoia ! shouldn't be necessary.
X push di
X push es
X int EMM
X pop es
X pop di
X pop cx
X or ah,ah
X jz gotsomeems
X xor dx,dx
X ret
Xgotsomeems:
X mov cs:[di],dx
X mov ovlemshdl,dx
X or ovlflg,MASK ems
X mov ax,dx
X call mapemspages
X mov ax,emsframe
X mov ds,ax
X mov ds:memblkflg,0 ; clear mem flags
X mov ds:memblknxt,0 ; set next to nothing
X mov ds:memblkprv,0 ; set previous to nothing
X mov ds:memblkovl,0 ; no overlay loaded
X mov dx,1000h
X mov ds:memblksiz,dx
X ret
X
Xfoundpage:
X mov cx,bx
X mov ds,si
X mov dx,ax
X mov ax,cs:[di]
X mov ovlemshdl,ax
X or ovlflg,MASK ems
X ret
X
Xgetemsmem ENDP
X
X;-------------------------------------------------------------------------------
X
Xmappage PROC NEAR ; map a 64K block of EMS mem.
X
X ASSUME DS:NOTHING,ES:ovltbl
X
X cmp ax,curemshandle
X jnz doems
X ret
Xdoems:
X push bx
X push dx
X push ds
X push es
X call mapemspages
X mov ax,emsframe
X xor dx,dx
X xor si,si
Xemsset:
X mov ds,ax
X test ds:memblkflg,MASK_used ; mem blk used ?
X jz emsfreeblk
X mov es,ds:memblkovl
X or ovlflg,MASK ems OR MASK loaded
X jmp emsnext
Xemsfreeblk:
X mov ax,ds:memblksiz
X cmp dx,ax
X jnc emsnext
X mov dx,ax
X mov si,ds
Xemsnext:
X mov ax,ds:memblknxt
X or ax,ax
X jnz emsset
X
X mov ax,dx
X pop es
X pop ds
X pop dx
X pop bx
X ret
X
Xmappage ENDP
X
X;-------------------------------------------------------------------------------
X
Xmapemspages PROC NEAR
X
X ASSUME DS:NOTHING,ES:ovltbl
X
X push es
X push bx
X push cx
X push dx
X mov curemshandle,ax
X mov dx,ax
X mov ah,EMMMAP
X xor al,al ; physical page 0
X xor bx,bx ; logical page 0
X push dx
X int EMM
X pop dx
X or ah,ah
X jnz emmerror
X mov ah,EMMMAP
X mov al,1 ; physical page 1
X mov bx,1 ; logical page 1
X push dx
X int EMM
X pop dx
X or ah,ah
X jnz emmerror
X mov ah,EMMMAP
X mov al,2 ; physical page 2
X mov bx,2 ; logical page 2
X push dx
X int EMM
X pop dx
X or ah,ah
X jnz emmerror
X mov ah,EMMMAP
X mov al,3 ; physical page 3
X mov bx,3 ; logical page 3
X int EMM
X or ah,ah
X jnz emmerror
X mov es,ovltblbse
X mov cx,ovlcnt
X xor bx,bx
Xtestems:
X test ovlflg[bx],MASK ems
X jz nxttestems
X and ovlflg[bx],NOT MASK loaded
Xnxttestems:
X add bx,OVLSEGSIZ
X loop testems
X pop dx
X pop cx
X pop bx
X pop es
X ret
X
Xemmerror:
X mov al,EMSERR ; ems manager error
X jmp putserr
X
Xmapemspages ENDP
X
X;-------------------------------------------------------------------------------
X
Xgethdr PROC NEAR ; read EXE header from handle
X
X ASSUME DS:NOTHING,ES:NOTHING
X
X mov dx,OFFSET hdr ; a place to put it
X mov bx,si
X shl bx,1
X mov bx,ovlfilhdl[bx] ; the file handle
Xreadagain:
X mov cx,TYPE EXEHDR ; header size in bytes
X mov ah,DOSREAD
X int DOS ; read from file
X jc exegone ; oops?
X cmp ax,cx ; got correct number of bytes?
X je gothdr
XIFNDEF NOSPLIT
X cmp ax,0 ; Anything?
X je gotonxtfil
XENDIF
X jmp exerotten
XIFNDEF NOSPLIT
Xgotonxtfil:
X inc si
X cmp si,MAXFILES+1
X je exegone ; We're out of files!
X mov bx,si
X shl bx,1
X cmp ovlfilhdl[bx],-1 ; Any more files?
X je gotonxtfil ; not here.
X
X mov bx,ovlfilhdl[bx] ; Slide in new handle
X xor bp,bp ; reset file offset
X jmp readagain
XENDIF
Xgothdr:
X cmp hdr.exesign,EXESIGNUM ; sanity check
X jne exerotten
X
X ret ; Wow, it worked!
Xexegone:
X mov al,NOHDRERR ; missing overlays!
X jmp putserr ; You lose!
XIFNDEF NOSPLIT
Xexerotten:
X mov al,HDRERR ; corruption!
X jmp putserr ; You lose!
XENDIF
X
Xgethdr ENDP
X
X;-------------------------------------------------------------------------------
X
Xopenfiles PROC NEAR ; Find our cohorts in crime
X
X push es
XIFNDEF NOSPLIT
X mov ah,DOSGETDTA ; Pick up DTA
X int DOS ; and
X mov dtaseg,es ; store
X mov dtaoffset,bx ; it
X
X push ds
X mov dx,OFFSET ovldta ; Set new DTA for file search
X mov ax,cs
X mov ds,ax ; point to the right seg
X mov ah,DOSSETDTA
X int DOS
X pop ds ; set this back for upcoming lodsb
XENDIF
X mov cx,MAXNAMESIZE/2
X mov bx,cs
X mov es,bx
X mov di, OFFSET filestring
X
X rep movsw ; load path from si to di
XIFNDEF NOSPLIT
X mov di, OFFSET filestring
X mov al,0
X mov cx,MAXNAMESIZE
X cld
X repne scasb ; search null for end of string
X
X sub cx,MAXNAMESIZE
X neg cx
X mov bx,cx
X
X cmp cx,MAXNAMESIZE
X je checkslash
X
X dec bx ; keep string length
X dec di ; cause were past null now
X
X cmp bx,7
X jle patherr ; "C:\.EXE" = 7
Xcheckslash:
X mov ax,DOSGETSWITCH ; divine switchar
X int DOS ; it influences the path
X
X mov al,'\' ; if swichar = '/' pathsep = '\'
X cmp dl,'/'
X je searchslash
X mov al,'/' ; else pathsep = '/'
Xsearchslash:
X std
X repne scasb ; search back for '\'
X cld
X
X mov dx,bx
X sub dx,cx ; keep file name length
X dec dx
X
X mov cx,0 ; reset for upcoming loop
X mov pathlen,bx ; hold these for recall
X mov namelen,dx
X cmp dx,12 ; "LONGNAME.EXE" = 12
X jle openroot ; Path name too long?
Xpatherr:
X mov al,NAMERR ; real problems here.
X jmp putserr
Xopenroot:
XENDIF
X mov ax,cs
X mov ds,ax ; set ds to code
X
X mov dx, OFFSET filestring ; open root code
X mov al,0 ; access code
X mov ah,DOSOPEN
X int DOS ; open sez me
X jnc dontdie
X
X mov al,FILEERR ; can't open root
X jmp putserr
Xdontdie:
X mov ovlfilhdl[0],ax ; save handle in array
XIFNDEF NOSPLIT
X cmp namelen,11 ; Max sized exe name (8.3)?
X jg bigfilename ; if not
X inc pathlen ; add one to path length
X inc namelen
Xbigfilename:
X mov di,OFFSET filestring ; es is still code
X add di,pathlen
X sub di,5 ; append
X mov si,OFFSET ovlext ; wildcard extension
X mov cx,6 ; and null
X rep movsb ; to filestring
X
X mov cx,0 ; Match "normal" files
X mov dx,OFFSET filestring
X mov ah,DOSSEARCH
X int DOS ; Set DTA with Wildcard.
X jc aok ; Not a single match
X mov cx,MAXFILES ; set upcoming loop
X mov dx,namelen
X sub pathlen,dx ; shorten absolute path
Xopenloop:
X push cx
X mov bx,pathlen
X mov di,OFFSET filestring ; es is still in code
X add di,bx
X mov si,OFFSET ovldta.file_name
X mov cx,namelen ; since this *should* be
X rep movsb
X pop cx
X
X mov dx,OFFSET filestring ; path to overlay file
X mov al,0 ; access code
X mov ah,DOSOPEN
X int DOS ; open overlay file
X jnc dontdie2
Xfileopenerr:
X call itoa
X
X mov al,OVLERR ; can't open file!
X jmp putserr
Xdontdie2:
X mov bx,cx ; put file number in bx
X shl bx,1 ; 2 * bx for array index
X mov ovlfilhdl[bx],ax ; save handle in array
X
X mov ah,DOSNEXTFILE ; Look for more files
X int DOS
X jc aok
X
X loop openloop ; open only 15 overlays
Xaok:
X mov dx,dtaoffset ; Time to unset DTA
X mov ds,dtaseg
X mov ah,DOSSETDTA
X int DOS
XENDIF
X pop es
X
X ret
X
Xopenfiles ENDP
X
X;-------------------------------------------------------------------------------
X
Xputserr PROC NEAR
X
X; display error msg, close file, restore int vectors, free mem and return to DOS.
X
X ASSUME DS:NOTHING,ES:NOTHING
X
X xor ah,ah
X push ax ; keep return code for later
X push cs
X pop ds
X mov bx,ax
X shl bx,1
X add bx,OFFSET errortbl
X mov dx,[bx]
X cmp dx,-1
X jz freeints
X push dx
X mov dx,OFFSET msghead
X mov ah,PRINT
X int DOS
X pop dx
X mov ah,PRINT
X int DOS ; display error msg
X
X mov ah,PRINT
X mov dx,OFFSET diag
X int DOS
X pop ax
X push ax
X call itoa ; error number
X mov ah,DOSPUTC
X mov dl,':'
X int DOS
X mov ax,VERSION
X call itoa ; version number
X mov ah,DOSPUTC
X mov dl,':'
X int DOS
X mov ax,0a000h
X sub ax,ovltblbse ; conventional memory
X call itoa
X mov ah,DOSPUTC
X mov dl,':'
X int DOS
X mov si,OFFSET emsmemblks
X mov cx,16
X xor ax,ax
Xemstotlp:
X cmp WORD PTR cs:[si],-1
X jz gotemstot
X add ax,emmframesiz
X add si,2
X loop emstotlp
Xgotemstot:
X call itoa ; ems usage in blocks
X mov ah,DOSPUTC
X mov dl,')'
X int DOS
X
X mov dx,OFFSET msgtail
X mov ah,PRINT
X int DOS
Xfreeints:
X call rstvectors ; restore all int vectors
X
X mov ax,ovltblbse
X cmp ax,-1
X jz freememblks
X mov es,ax
X mov ah,DOSFREE
X int DOS
Xfreememblks:
X mov cx,16 ; do all allocated mem blocks
X mov si,OFFSET memblks
Xfreememlp:
X mov ax,cs:[si] ; get memory blk segment
X cmp ax,-1 ; was one ever allocated?
X jz nxtmemlp ; nope
X mov es,ax
X mov ah,DOSFREE ; must free it.
X int DOS
Xnxtmemlp:
X add si,2
X loop freememlp
X mov cx,16 ; do all allocated ems blocks
X mov si,OFFSET emsmemblks
Xfreeemsmemlp:
X mov dx,cs:[si] ; get memory blk segment
X cmp dx,-1 ; was one ever allocated?
X jz nxtemsmemlp ; nope
X mov ah,EMMFREE ; must free it.
X int EMM
Xnxtemsmemlp:
X add si,2
X loop freeemsmemlp
Xclosefile:
XIFNDEF NOSPLIT
X mov cx,MAXFILES+1
Xnextfile:
X mov bx,cx
X dec bx
X shl bx,1
X mov bx,ovlfilhdl[bx] ; get file handle
XELSE
X mov bx,ovlfilhdl[0]
XENDIF
X cmp bx,-1 ; was the file ever opened?
X jz byebye ; nope
X mov ah,DOSCLOSE ; close it
X int DOS
Xbyebye:
XIFNDEF NOSPLIT
X loop nextfile
XENDIF
X pop ax ; return code in al
X mov ah,TERMINATE
X int DOS ; terminate this process
X
Xputserr ENDP
X
X;-------------------------------------------------------------------------------
X
Xitoa PROC NEAR
X
X push ax
X xchg ah,al
X call putbyte
X pop ax
X jmp putbyte
X
Xitoa ENDP
X
X;-------------------------------------------------------------------------------
X
Xputbyte PROC NEAR
X
X push ax
X shr al,1
X shr al,1
X shr al,1
X shr al,1
X call nibble
X pop ax
X jmp nibble
X
Xputbyte ENDP
X
X;-------------------------------------------------------------------------------
X
Xnibble PROC NEAR
X
X push ax
X and al,0fh
X add al,30h
X cmp al,3ah
X jc nibok
X add al,7
Xnibok:
X push dx
X mov dl,al
X mov ah,DOSPUTC
X int DOS
X pop dx
X pop ax
X ret
X
Xnibble ENDP
X
X;-------------------------------------------------------------------------------
X
Xsetvectors PROC NEAR
X
X push ds
X xor ax,ax
X mov ds,ax
X mov si,cs:intnum
X cli
X mov ax,[si]
X mov WORD PTR cs:oldvec,ax ; save original vector
X mov ax,[si+2]
X mov WORD PTR cs:oldvec+2,ax
X mov ax,OFFSET ovlmgr ; point to ovlmgr
X mov [si],ax ; set int vector
X mov [si+2],cs
X
X mov si,DOS*4
X mov ax,[si]
X mov WORD PTR cs:oldint21,ax ; save original vector
X mov ax,[si+2]
X mov WORD PTR cs:oldint21+2,ax
X mov ax,OFFSET int21 ; point to new int21
X mov [si],ax ; set int vector
X mov [si+2],cs
X sti
X pop ds
X ret
X
Xsetvectors ENDP
X
X;-------------------------------------------------------------------------------
X
Xrstvectors PROC NEAR
X
X push ds
X xor ax,ax
X mov ds,ax
X mov si,DOS*4
X cli
X mov ax,WORD PTR cs:oldint21 ; put back dos vector
X cmp ax,-1
X jz rstvec
X mov [si],ax
X mov ax,WORD PTR cs:oldint21+2
X mov [si+2],ax
Xrstvec:
X mov si,cs:intnum
X mov ax,WORD PTR cs:oldvec ; put back ovlmgr vector
X cmp ax,-1
X jz rstdone
X mov [si],ax
X mov ax,WORD PTR cs:oldvec+2
X mov [si+2],ax
X sti
Xrstdone:
X pop ds
X ret
X
Xrstvectors ENDP
X
Xcode ENDS
X
X END
END_OF_FILE
if test 46506 -ne `wc -c <'sys/msdos/ovlmgr.asm'`; then
echo shar: \"'sys/msdos/ovlmgr.asm'\" unpacked with wrong size!
fi
# end of 'sys/msdos/ovlmgr.asm'
fi
echo shar: End of archive 18 \(of 108\).
cp /dev/null ark18isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 \
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 \
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 \
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 \
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 \
101 102 103 104 105 106 107 108 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 108 archives.
echo "Now execute 'rebuild.sh'"
rm -f ark10[0-8]isdone ark[1-9]isdone ark[1-9][0-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0