billr@saab.CNA.TEK.COM (Bill Randle) (07/12/90)
Submitted-by: Izchak Miller <izchak@linc.cis.upenn.edu>
Posting-number: Volume 10, Issue 57
Archive-name: nethack3p9/Part12
Supersedes: NetHack3: Volume 7, Issue 56-93
#! /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 12 (of 56)."
# Contents: Install.ami others/ovlmgr.asm
# Wrapped by billr@saab on Wed Jul 11 17:11:06 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'Install.ami' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'Install.ami'\"
else
echo shar: Extracting \"'Install.ami'\" \(16878 characters\)
sed "s/^X//" >'Install.ami' <<'END_OF_FILE'
X
X Instructions for compiling and installing NetHack 3.0
X on an AMIGA system
X =====================================================
X Last Revision: 27 May 1990
X
XOverview
X--------
X This file contains the procedure to follow when installing NetHack 3.0
X on an Amiga computer system. It also includes some procedures and hints
X for individuals desiring to create a binary from the source. This
X document is divided into 4 sections. Section I deals with installing
X already existing binaries and data files to create a working NetHack
X game disk (or directory, in the case of a hard drive). Section II
X describes, in general, how to produce working binaries from the source.
X Section III and IV are compiler specific sections, with section III
X designed for Lattice users, and section IV for Manx/Aztec users.
X
XRequirements
X------------
X Amiga 500,1000,2000,2500 running WorkBench 1.3 and KickStart 1.2 or 1.3.
X (As of this time, the Amiga 3000 running beta-release versions of
X WorkBench 2.0 are not supported. While the core of the game appears to
X function, the custom font is not recognized by the operating system.
X The NetHack team welcomes reports of specific problems and solutions on
X this [or any other] subject.)
X one meg of RAM and one floppy drive (painful, but functional)
Xor one meg of RAM and two floppy drives (much better)
Xor more than one meg of RAM and a hard disk with 2+ meg free (best)
X
XCredits
X-------
X Olaf Seibert first ported NetHack 2.3 and 3.0 to the Amiga. Richard
X Addison, Jochen Erwied, Mark Gooderum, Ken Lorber, Greg Olson, Mike
X Passaretti, and Gregg Wonderly polished and extended the 3.0 port.
X
XSection I - Installation Guide
X-------------------------------
X This section assumes you have the following handy:
X
X * NetHack (executable code)
X * Rumors file
X * Oracle file
X * All of the various help and informational files (help, opthelp, etc)
X * Special level files (castle, tower1, tower2, tower3, endgame)
X * Amiga with at least 1 meg memory (may be optimistic....)
X
X And optionally:
X
X * Icons if WorkBench interface is to be used. These files include
X + NetHack.info
X + NewGame.info
X + NetHackScore.info
X + Guidebook.info
X + default.icon
X * Special NetHack font (files hack.font and 8).
X
X Installation Steps:
X
X 1) If you have a hard disk, create a directory named NetHack.
X Assign Nethack: to be the path to this directory. If you have a
X floppy, format a disk named NetHack. (If you have a hard disk
X but only one meg of memory, you will probably not have enough
X memory: you may need to run from a floppy.)
X
X 2) If you have a hard disk, assign HackExe: to the above directory.
X If you have a floppy, format an additional disk named HackExe.
X
X 3) Copy Nethack, NetHack.info, NewGame.info, and NetHackScore.info
X to HackExe. Create an empty file called NewGame (WorkBench
X refuses to Duplicate a project icon without a file attached).
X
X 4) Copy the remainder of the files to NetHack:. If you are using
X the optional font, create a Hack subdirectory on NetHack:, and
X copy "8" into it. Be sure that Guidebook and Guidebook.info are
X in the same directory, and that the Default Tool field points to
X the More program (found on your AmigaDos System disk in the
X Utilities directory). Depending on where you got your copy of
X NetHack, the Guidebook file may be called Guidebook.mss.
X
X 5) Configure NetHack.cnf as per your configuration. Remember not
X to set GRAPHICS if you are not using the optional font. If you
X have only one meg of ram, do not use a ram disk.
X
X That's all there is to it! If you are using the CLI interface, make sure
X that the stack is set fairly large (at LEAST 40000 bytes). Move to the
X NetHack: directory, and type NetHack <cmd line options>. If you're
X using the WorkBench interface, click on the NetHack directory/disk.
X You should see 3 icons. Select the "NewGame" option, and "Duplicate" from
X the WorkBench pull down menu. This icon now represents your personal
X profile. You can now rename this icon, and tailor it to your liking
X as described below. If you start a game from the WorkBench interface,
X saving the game will automatically tie the personal file icon to the
X saved game. So the next time you select your icon, the game will be
X restored.
X
X As mentioned above, the icon representing your personal profile can be
X customized. This is done via the the Info command available from
X WorkBench. You can adjust the following using the ToolTypes from the
X WorkBench info command:
X
X * OPTIONS=<options> - Options as avaliable in the NetHack.cnf file.
X
X * HACKDIR=<directory> - Set NetHack working directory to be this
X directory.
X
X * RAMDISK=<ram disk> - Set up ram disk option.
X
X * LEVELS=<levels> - Intermediate level saving device/directory.
X
X * PATH=<path> - To search for files such as rumors, help, etc.
X
X * CMDLINE=<args> - Arguments as passed on the CLI command line.
X Note: only the following flags are valid: n, X, D, and r.
X
X * SCORE <options> - Display the record of scores. Options as
X available on the CLI command line after a -s flag.
X
X Note that the NetHack.cnf file is read first, then the ToolTypes. This
X means that the options specified in the NetHack.cnf act as defaults
X which can be overridden by an individual's personal icon's ToolTypes.
X Thus the system oriented entries (HACKDIR, RAMDISK, LEVELS, and PATH)
X should generally be set only in NetHack.cnf. NetHack.cnf should have
X default values for OPTIONS, which will generally be overridden by
X ToolTypes entries.
X
X Also, there is one additional option that may be specified in the
X NetHack.cnf file or on an OPTIONS line: flush. When enabled, flush
X discards all characters in the queue except the first, which limits
X but does NOT completely eliminate the "accidents" which can occur if
X you get ahead of the game when typing. The default setting is noflush.
X
XSection II - General Compilation Instructions
X---------------------------------------------
X
X 1) Before doing any compilation, read the README files distributed
X with the source. These should familiarize you with the source tree
X layout, and what files are shared with what computers. Generally,
X everything in the amiga directory is used exclusively by the Amiga.
X
X 2) Create the sub-directories, and name them as indicated in the source
X README file. If you have a hard drive, this is fairly trivial
X (create a directory, and corresponding NetHack sub-directories).
X If you have only floppies, you'll have to be a bit more clever.
X The makefile (Makefile.ami) is set up to depend upon certain
X assignments, providing the developer with a fairly flexible
X environment. The main directory with which a floppy user will have
X problems is the src directory. In order to fit all of the source on
X to floppies, the src directory has been split into logical units.
X For example, the makefile expects:
X
X Src1: contains src [a-l]*.c
X Src2: contains src [m-po]*.c
X Src3: contains src [pr-z]*.c
X
X See makefile.ami for assignment assumptions.
X
X 3) Edit config.h to your liking and system configuration. The following
X are strong suggestions for certain #define values.
X
X + UNIX - DO NOT DEFINE
X + MSDOS - DO NOT DEFINE HERE, IT WILL BE DONE LATER FOR YOU
X + COMPRESS - DO NOT DEFINE
X + ZEROCOMP - DEFINE
X + CHDIR - RECOMMENDED
X + HACKDIR - "NetHack:" MANDATORY
X + BITFIELDS - DO NOT DEFINE IF YOU HAVE MANX3.6
X + CLIPPING - DO NOT DEFINE
X
X 4) Edit amiconf.h to your liking. It is recommended you leave
X everything as is with the following exceptions:
X
X + TEXTCOLOR - Will allow the use of colors for text objects in
X the game. For instance, red gems will be red. Unfortunately,
X at this time this is only configurable at compile time, when
X it really should be configurable at run time. Note also that
X there is a slight bug when running textcolor, namely that when
X you are polymorphed, the color you are is not correct because
X the cursor overlays the default monster color. You can see
X yourself fine, but you do not represent the correct monster color.
X
X + HACKFONT - Enable if you want to use the special NetHack font,
X disable otherwise.
X
X + AMIGA_WBENCH - Enable if you want the WorkBench interface to
X be compiled into the code. This does NOT preclude you from
X running from CLI.
X
X 5) If you have significant spare ram, you may wish to make your
X compiler resident (Lattice 5.05's lc, lc1, and lc2 need about
X 215K while Manx's cc and as need about 135K).
X
X 6) At this point, you're almost ready to begin a compile. Read VERY
X CAREFULLY through the Makefile to familiarize yourself with which
X assignments are assumed. Otherwise, you're going to get something
X like "Insert O_Src1: in any drive." requestors. If you have the
X uudecode program and need to uudecode the various *.uu files from
X the Amiga: directory (font and icons), define the UUDEC symbol
X at the appropriate place in the makefile. The first thing
X Makefile.ami does is build a program called 'makedefs', which
X handles a variety of data file generation, and a program called
X 'lev_comp' which compiles the special levels. Makedefs will then be
X run to create a few files, followed by an alphabetically sorted
X compilation of the entire source tree. This compilation process
X will compile selected files from Amiga:, Others:, Src1:, Src2:,
X and Src3: directories. If all goes well, all of the objects will
X be linked together to form a binary. With all of the options
X enabled, the Manx 3.6 executable runs about 790K, and the Lattice
X executable runs about 750K (without debug hunks, or about 1025K
X with debug hunks - see below). After building the main binary,
X the makefile will build and install the auxiliary files including
X help files, special levels, icons, and the font files.
X
XSECTION III - Lattice Compilation Instructions
X----------------------------------------------
X
X If you're a Lattice user, you should be pretty well set up at this point.
X If you have some spare ram, you may wish to examine the Amiga:compact.lat
X script. This script will reduce your compile time by using Lattice's
X lcompact utility to pre-scan the header files and place compacted copies
X onto the Ram: disk. Read through the comments in that script if you
X wish to utilize it.
X
X Due to a problem with versions 5.04 and 5.05, you must make one change:
X edit the file Others:lev_lex.c. At (or near) line 1003 is the definition
X for the function yyunput. Delete the word "register" from this line.
X Note that if you neglect to do this, you will get an Error 72 at line 319
X of file lev_comp.l (this is the correct message - lev_lex.c is flex output).
X Save the changed file. Later compiler versions may or may not need this
X fix.
X
X Type 'CD NetHack:' and then type "lmk -f Amiga:Makefile.ami". If all
X goes well, you'll have a working binary a couple of hours later (depending
X on your hardware configuration). A couple of notes and warnings from the
X Lattice users on the team:
X
X * The primary Lattice compiler used on the Amiga port was version
X 5.05. Previous versions of NetHack have been successfully compiled
X with 5.04 and 5.04a.
X
X * The function monsndx, in file mondata.c, has a section of code
X which Lattice 5.04 compiles incorrectly. A hack has been written
X around this so that Lattice will generate the correct code. It is
X recommended that you leave this in place, and not attempt to
X "improve" it. This fix "does the right thing" in version 5.05.
X
X * Included in the Lattice port is code for generating a SnapShot.tb
X file upon catching various internal disasters. That is why the
X -d1 flag is in the makefile. This adds about 270K to the disk
X image, but it does not increase the run time memory requirements.
X Floppy users will have to delete -d1 flag, or the binary won't
X fit on a single disk.
X
X * The optimizer seems to work, but no extensive testing has been
X done with it. (Note: optimizing objnam.c takes several hours.)
X
X * There are a large number of warnings under Lattice, which are
X harmless.
X
XSECTION IV - AZTEC/MANX Compilation Instructions
X-------------------------------------------------
X
X NetHack 3.0 compiles and runs fine under Aztec 3.6, but a little bit
X of work is necessary. The problem is that the Aztec pre-processor
X is fairly stupid, and doesn't recognize the defined() pre-processor
X function. Unfortunately, this function is laced throughout the NetHack
X code, hence removing it would be quite a chore, and end up rendering the
X code much more unreadable.
X
X There are a couple solutions to this problem. The first solution is to
X run every source file through some c pre-processor which understands
X defined() (the Decus cpp works fine). The problem with this solution is
X that the time it takes to compile/recompile is (at least) doubled. My
X configuration is a 33 meg hard drive and 2 1/2 megs of ram, and it still
X takes over 4 hours to generate a binary from scratch! Also note that
X Makefile.ami was not built to support cpp, and so you'll have to modify
X the makefile to add this step.
X
X But don't despair, have we got a deal for you! The Apple NetHackers also
X had a similar problem with defined, which led them to developing a
X defined() hack (located in config.h). This hack basically adds
X the defined() functionality to the Aztec pre-processor, with the exception
X of performing this operation on strings. Fortunately, using defined() on
X strings is done very rarely, and they are handled on an individual basis.
X (The only one I can think of right now is WIZARD/WIZARD_NAME). What's the
X catch, you ask? Well, there is one. The problem is as follows.
X
X The Aztec compiler doesn't know how to handle const, volatile, and signed
X data types. Normally, this can be fixed by sticking a #define const
X before const is used, thereby rendering it disabled. Unfortunately, the
X Aztec pre-processor, in its infinite wisdom, WILL NOT LET YOU REDEFINE
X these strings.
X
X The solution to this is not quite as elegant as the solution to the
X defined() problem above. It requires a one time modification to the
X Aztec cc binary. (DO THIS TO A BACKUP COPY OF CC!!) Find a disk zapper,
X NewZap works fine. Then do a search for the string 'const'. Change
X the const, signed and volatile strings to __nst, __gned and __latile.
X (It's really not as bad as it sounds....)
X
X A couple of warnings regarding the 3.6 compiler/NetHack:
X
X * The 3.6 Manx bitfield handling is buggy at best. Though I can't
X specifically cite a flaw when NetHack is compiled with it, I
X don't trust it. I recommend you don't either.
X
X * If your signal.h (in your Manx include directory) has SIGINT
X commented out, go ahead and uncomment it.
X
X * If you use the cpp method, pass -DAZTEC_C and -DMCH_AMIGA to
X the cpp. These are defined automatically by Aztec C, but are
X ineffective if the source is run through a filter first.
X
X * There will be a few harmless warnings in the compile process.
X These warnings will be in amidos.c, and pickup.c. There may also
X be a warning when defining lev_lex.c that LEV_LEX is redefined. This
X is OK. Any other warnings should be investigated.
X
X * I haven't tried sdb on it, as I can't affort the disk space. (You'll
X have to save the intermediate cpp files if you cpp). Unless you've
X got a whopping amount of memory, I suspect it's going to be too large.
X
X * There are 2 versions of lev_lex.c that are being distributed; one
X generated by (unix) lex, and one generated by gnu flex. The gnu
X flex lev_lex.c should work without modification. If you use the
X lex lev_lex.c, you will get 4 warnings regarding ptr/int conversions.
X Change the masks from (int) to (long) to generate a clean binary.
X
X * Unfortunately, Manx 5.0 arrived too late to integrate into patch
X level 7, but merging will occur in the next few weeks. Contact us
X (below) for progress/hints. (Postscript for PL8: the situation is
X very much improved, but there may be some problems remaining).
X
X - - - - - - - - - - - -
X
XIf you have problems or questions, email to nethack-bugs@linc.cis.upenn.edu,
Xor directly to Greg Olson (golson@sundown.sun.com) for Manx questions,
Xto Ken Lorber (keni@dtix.dt.navy.mil) for Lattice questions, or to
XRichard Addison (addison@pollux.usc.edu) for either. Have fun!!
END_OF_FILE
if test 16878 -ne `wc -c <'Install.ami'`; then
echo shar: \"'Install.ami'\" unpacked with wrong size!
fi
# end of 'Install.ami'
fi
if test -f 'others/ovlmgr.asm' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'others/ovlmgr.asm'\"
else
echo shar: Extracting \"'others/ovlmgr.asm'\" \(40486 characters\)
sed "s/^X//" >'others/ovlmgr.asm' <<'END_OF_FILE'
X; SCCS Id: @(#)ovlmgr.asm 90/05/27
X; Copyright (c) 1989, 1990 Pierre Martineau and Stephen Spackman. All Rights Reserved.
X; This product may be freely redistributed. See NetHack license for details.
X
XVERSION EQU 3081h
X
X PAGE 57,132
X TITLE 'DOS Overlay Manager for MSC 5.1+'
X SUBTTL 'Copyright (c) 1989, 1990 Pierre Martineau and Stephen Spackman. All Rights Reserved.'
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
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
XDOSEXEC EQU 4bh ; exec child process
XDOSPUTC EQU 02h ; print a char
XDOSVERSION EQU 30h ; get version number
XDOSGETVEC EQU 35h ; get interrupt vector
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
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
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 ; overlay flags
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> ; 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
XEXEHDR STRUC ; structure of an EXE header
Xexesign DW 5a4dh ; 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 ?
Xovlexefilhdl DW -1 ; always-open file handle of our .EXE
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
Xerrortbl DW -1 ; error message pointers
X DW OFFSET baddos
X DW OFFSET nofile
X DW OFFSET noroom
X DW OFFSET nofile
X DW OFFSET nocore
X DW OFFSET nocore
X DW OFFSET badems
X DW OFFSET nofile
X DW OFFSET unknown
X DW OFFSET unknown
X DW OFFSET unknown
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,'$'
Xnoroom DB 'Not enough free memory left to run this program.$'
Xnocore DB 'Internal memory allocation failure.$'
Xnofile DB 'Inaccessible EXE file. Can',27,'t load overlays.$'
Xbaddos DB 'Incorrect DOS version. Must be 3.00 or later.$'
Xbadems DB 'EMS memory manager error.$'
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,'$'
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 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 mov al,0 ; access code
X mov ah,DOSOPEN
X mov dx,si
X int DOS ; open EXE
X jnc dontdie
X mov al,FILEERR ; can't open file!
X jmp putserr
Xdontdie:
X mov ovlexefilhdl,ax ; save handle
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 push cs
X pop ds
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
Xfilsegtbllpp: ; initialise ovl table
X call gethdr ; get an EXE header
X mov ax,ovltblbse
X add ax,hdr.exeovlnum
X mov es,ax ; ^ to ovl table entry
X xor ax,ax
X mov WORD PTR ovllrudat,ax ; initialise ovl lru
X mov WORD PTR ovllrudat+2,ax
X mov ovlflg,al ; initialise ovl flags
X mov ovlinvcnt,al ; initialise invocation count
X mov ovlemshdl,-1
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 mov ax,ovlcnt
X dec ax
X cmp ax,hdr.exeovlnum ; all overlays done?
X jz makmemblk
X jmp filsegtbllpp ; Nope, go for more.
Xmakmemblk:
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 bx,ovlexefilhdl ; 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 bx,ovlexefilhdl ; 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:NOTHING
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 es,ax
X mov ax,es:[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 es:[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:NOTHING
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 bx,ovlexefilhdl ; 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 nosplit
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
Xnosplit:
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 push cx
X push ds
X mov ax,cs
X mov ds,ax
X mov dx,OFFSET hdr ; a place to put it
X mov bx,ovlexefilhdl ; the file handle
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 jnz exegone ; nope
X pop ds
X pop cx
X ret ; Wow, it worked!
Xexegone:
X mov al,HDRERR ; You lose!
X jmp putserr
X
Xgethdr 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:
X mov bx,ovlexefilhdl ; get file handle
X cmp bx,-1 ; was the file ever opened?
X jz byebye ; nope
X mov ah,DOSCLOSE ; close it
X int DOS
Xbyebye:
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 and al,0fh
X add al,30h
X cmp al,3ah
X jc nibok
X add al,7
Xnibok:
X mov dl,al
X mov ah,DOSPUTC
X int DOS
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 40486 -ne `wc -c <'others/ovlmgr.asm'`; then
echo shar: \"'others/ovlmgr.asm'\" unpacked with wrong size!
fi
# end of 'others/ovlmgr.asm'
fi
echo shar: End of archive 12 \(of 56\).
cp /dev/null ark12isdone
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 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 56 archives.
rm -f 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