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