billr@saab.CNA.TEK.COM (Bill Randle) (06/06/90)
Submitted-by: Izchak Miller <izchak@linc.cis.upenn.edu> Posting-number: Volume 10, Issue 38 Archive-name: NetHack3/Patch8t Patch-To: 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 20 (of 24)." # Contents: Install.mac do_patch8.sh others/ovlmgr.asm # vms/vmsmisc.c # Wrapped by billr@saab on Mon Jun 4 15:40:30 1990 PATH=/bin:/usr/bin:/usr/ucb ; export PATH echo shar: Extracting \"'Install.mac'\" \(14959 characters\) sed "s/^X//" >'Install.mac' <<'END_OF_FILE' X Macintosh NetHack 3.0 Installation Guide X ======================================== X last modification date: May 28th, 1990 X X(Original credit for porting NetHack 3.0 to the Macintosh goes to Johnny XLee and Michael Sokolov. David Hairston, Kevin Sitze, Andy Swanson, Jon XWatte and Tom West helped polish this port in later versions.) X X0. Some notes before getting started. These instructions work for the X Think C 4.0 compiler. Other Macintosh compilers should be okay (i.e. X Lightspeed C 3.0 and Manx Aztec C), however some work may be needed X to complete the build. For other compilers you can use the various X Makefiles and your compiler errors as guides in building the game. X X You should maintain the file/folder structure given in the distri- X bution file "Files". These notes assume the file structure listed X below. Place the "top" folder appropriately in your compilers X development folder. You'll need ~6M disk space for development. X top: X Files X Install.mac X Makefile.top X auxil: (... all files) {auxiliary support files} X include: (... all files) {header files} X mac: (... all files) {Macintosh specific files} X others: (pcconf.c, pcmain.c, pctty.c & random.c only) X src: (... all files) {generic source files} X X Now is a good time to decode the *.hqx files (mac folder), creating X 3 Think C 4.0 project files and 2 associated resource files. You may X use BinHex 4.0 or Stuffit 1.5.1 for this. These 5 files (*.proj and X *.rsrc) should be moved from the mac folder into the "top" folder. X X Use your favorite text editor to create an empty file of type "TEXT". X This file should be called "news" and should be placed in the auxil X folder. If you decide to use the news feature of NetHack you can X write an appropriate starting message in this file. X X Create a folder called "dungeon" in your "top" folder. This is where X we'll copy the final files needed to run NetHack. X X Finally, you should have no problem compiling the NetHack sources, as X distributed. However, if you intend to make changes to the sources you X should consider backing up your disk to prevent problems. Also, trash X (or perhaps alter the creator signature of) your old versions of NetHack X 3.0 to avoid conflicts. X X Okay, let's get started. We're going to make 3 applications, in order: X (1) makedefs, to create customized files for the game, (2) spec_lev, X to create special challenging maze-like levels and (3) nethack! The X full build from scratch takes less than an hour using Think C 4.0 . X X1a. Make sure all the NetHack files are in the appropriate folder structure. X You should have a top folder with subfolders auxil, include, mac, others, X and src. The provided Think C 4.0 projects assume this structure (as do X the provided Makefiles). X X1b. If your compiler doesn't handle subfolders you'll need to place all the X inter-related source (*.c) and header (*.h) files in a common folder. It X may require some work but you should be able to follow the dependencies X in the Makefiles to build the game. X X2. If your compiler utilizes the make/Makefile facilities, you'll need to X remove the tags from the Makefiles (auxil, src and top) and edit them X appropriately. The Makefiles are not needed if you can use the provided X Think C 4.0 project files. X X3. Edit the config.h file making the following changes to configure it X properly for the Macintosh: X X Section 1. OS Selection. X Comment out: #define UNIX X Uncomment : #define MACOS (bottom of the ifdef __MSDOS__ else clause). X X Within the #ifdef MACOS segment configure the #define's to choose your X compiler. The default is to use THINKC4. For now, skip the other X #define's there. Note that if your compiler is LSC or AZTEC, the KR1ED X compiler directive is automatically defined for you. This directive X allows these compilers to use the defined() construct. Additionally, X for the LSC a/o AZTEC compilers you'll also need to add the line: X #define defined(x) (-x-1 != -1) X before the first occurrence of #if defined(x) in random.c and mon.c! X X Section 2. Some global parameters and filenames. X For THINKC4 define the WIZARD name. A good choice is "debug" since X that is the purpose of this option. For LSC or AZTEC define the X WIZARD_NAME appropriately. This is the name that needs to appear in X your "NetHack Prefs" file (system folder) in order to use Wizard X (Debug) mode. X X Comment out: #define LOGFILE "logfile" X X Section 3. Definitions that may vary with system type. X The defaults are all okay here for THINKC4, LSC and AZTEC. X X Section 4. THE FUN STUFF!!! X uncomment: #define SCORE_ON_BOTL (This is optional. It will allow X you to see your current score on the bottom line during play.) X The rest of the #define's default to configuring a "full-featured" X NetHack game. X X Save the config.h file. X X If you intend to customize the game you will want to look at the files X macconf.h and system.h. This typically isn't needed for simply building X the game. X X4. Now we're going to build the makedefs application. This application X depends on various header files and the source files: X alloc.c macfile.c makedefs.c monst.c objects.c & panic.c . X If necessary look at the Makefile(.src) to determine the dependencies. X You'll need to load the libraries appropriate for your compiler. THINKC4 X users can simply open the "makedefs.proj" file. X X Re-edit the config.h file! Go to the #ifdef MACOS segment in section 1. X Comment out: #define CUSTOM_IO . X Uncomment : #define MAKEDEFS_C . X X Close the config.h file, saving the changes. X X Build the makedefs application. The Think C 4.0 project uses resources X from the "makedefs.proj.rsrc" file. Save the application in the "top" X folder. Close the project. Run the makedefs application, sequentially X choosing all seven options. This will require re-launching each time. X You've now created additional auxiliary files for the game and added X icons and signatures to these 12 files (auxil folder): cmdhelp, data, X help, hh, history, license, MacHelp, news, opthelp, oracles, record, X and rumors. These files can now be copied into the dungeon folder. X X If you decide to change features in the game, remember to always X rebuild makedefs first to setup the needed data structures and so on X for the game. X X5. Next, we're going to build the spec_lev application. This application X depends on various header files and the source files: X alloc.c lev_comp.c lev_lex.c lev_main.c macfile.c monst.c X objects.c & panic.c X If you copied the alternate file lev_lex.c in the "others" folder, you X should remove (or rename) it to avoid problems with src:lev_lex.c. The X dependencies here are similar to the ones for the makedefs project. X Again, if necessary, refer to the Makefile(.src) for help. You should X need the same libraries for this application as you did for makedefs. X THINKC4 users can simply open the "spec_lev.proj" file. X X The changes needed to build this application are more complicated than X before, however the checklist provided below should cover all the bases. X X *Edit config.h (Section 1. within the #ifdef MACOS segment) X Comment out: #define MAKEDEFS_C X Comment out: #define NEED_VARARGS {more on pre-compiled headers later} X Save the changes to config.h and close the file. X X *Edit lev_lex.c. These changes will appear sequentially: X Find Replace with X {... near the beginning ...} X int yyleng; extern char yytext[]; int yyleng; extern char *yytext; X int yymorfg; int yymorfg; X extern char *yysptr, yysbuf[]; extern char *yysptr, *yysbuf; X int yytchar; int yytchar; X File *yyin ={stdin}, *yyout ={stdout}; File *yyin =stdin, *yyout =stdout; X {... near the end ...} X {... If you're using LSC or THINKC4 comment out: ...} X {... #define NLSTATE yyprevious=YYNEWLINE ...} X char yytext[YYLMAX]; char *yytext; X {... Skip a line ...} X char yysbuf[YYLMAX]; char *yysbuf; X char *yysptr = yysbuf; char *yysptr; X Save the changes to lev_lex.c and close the file. X X *Edit lev_comp.c near the middle of the file. X Find Replace with X #endif not lint #endif /* not lint */ X Save the change to lev_comp.c and close the file. X X *Edit lev_main.c near the beginning of the file. X Uncomment: #include "hack.h" X Save the change to lev_main.c and close the file. X X Build the spec_lev application and save it into the "top" folder. X Close the spec_lev project. Now run the spec_lev application, it X will show you what file it is currently working on and create the X 5 special levels: castle, endgame, tower1, tower2 and tower3 in X the top folder. These 5 files should be moved into the dungeon X folder. X X If you're really motivated and want to create customized special X levels it should be possible to modify the special level compiler X to accomodate your efforts. You'll also want to edit the "descrip[]" X and "argc" variables, appropriately in lev_main.c within the ifdef X MACOS segments, to get the compiler to recognize your custom levels. X This is not trivial! You probably won't bother (no one has)! X X If you decide to change features in the game, remember to rebuild X the special levels compiler to reflect those changes and also X recreate the special levels. X X6. This is what you've been waiting for! Now we're going to build the X game. The file "Segments.mac" shows the source dependencies for this X application and suggests a workable scheme for creating properly sized X segments. THINKC4 users can simply open the "nethack.proj" file, other X users should build segments according to "Segments.mac" and also add X in the appropriate libraries. X X Follow the checklist below which indicates the changes needed to build X the game. X X *Edit topten.c near the beginning and set the following values: X #define POINTSMIN 51 X #define ENTRYMAX 50 X comment out: #define PERS_IS_UID X This will keep the size of the record file reasonable. Save your X changes and close topten.c . X X *Edit config.h within the #ifdef MACOS segment: X uncomment: #define CUSTOM_IO X uncomment: #define NEED_VARARGS X Save your changes to config.h and close the file. X X Since we're going to use pre-compiled headers in our THINKC4 project X a minor lexical change needs to be made to several files. The X affected files are: X alloc.c apply.c end.c extralev.c mkroom.c monmove.c X pager.c pctty.c pri.c priest.c save.c shk.c X sounds.c termcap.c topl.c topten.c X In these files we'll need to comment out the #define's that appear X before the first #include compiler directive. Usually this only X involves a single #define (end.c, monmove.c and topten.c are exceptions). X This can be done fairly easily using the regular expression search X feature of the "Find" command. Assuming that all files are in the project X invoke the "Find" command from the "Search" menu. Enter these fields: X Search For: Replace with: X ^\(#.*pre-compiled headers \*\/\) /*\1 X Check the "Grep" and "Multi-File Search" check boxes (you'll be X looking in all .c files) then click the "Don't Find" button. X Now repeat this sequence: X 1) Select "Find in Next File" from the "Search" menu. X 2) When it finally makes a match, Select "Replace All". X 3) Click the "Okay" button in the ensuing alert and go back to (1), X until there are no more matches. Save the changes to these files X and close them all (you may consider doing 6 at a time if having X too many open windows is a problem). X X Copy the files hack.h and config.h to oldhack.h. and oldconfig.h, X respectively. You'll need the old*.h files (properly renamed) if you X make changes to the game and need to rebuild the makedefs and spec_lev X applications. Trash the hack.h file and "Open" the "oldhack.h" file X for editing. Select "Precompile ..." fom the "Source menu and save the X result as "hack.h". Close the oldhack.h file. Now trash the "config.h" X file and "Open" the "oldconfig.h" file for editing. Again select X "Precompile ..." and save the result as "config.h". Close the file X oldconfig.h . Make sure that you aren't auto-including "MacHeaders" X by selecting the "Options ..." entry from the "Edit" menu. Click the X "Code Generation" radio button and make sure that "<MacHeaders>" is X not checked. X X Build the application, this make take a few minutes. Save the game X into the dungeon folder. Close the nethack project and you're ready X to play the game (I hope all went well). X XSpecial Note: If you are attempting to build Nethack 3.0 on a 1M Macintosh X using Think C 4.0, then memory may be a problem. It is suggested that X you turn off debugging info for monst.c and objects.c . Also, if for X some reason, compilation stops in the segment containing these two X files after they have been compiled, then you should drag these two X files into a separate segment, finish compiling the files of the X original segment and then restore these two files to the original X segment. Alternatively, you may decide to "Kompile" monst.c and X objects.c separately while preserving the given segmentation scheme. X X7. Cleanup. It's a good idea to always rebuild the makedefs and spec_lev X applications from scratch. Therefore you can trash these applications X and also remove the objects from their respective projects (Think C X compilers) to conserve disk space. The same can be done for your X nethack project. Consider the changes outlined above and undo them X as needed to rebuild the project, if you decide to modify the game. X If you're satisfied with the "full-featured" game you can trash all X the files for a real saving! X XNotes: X1. You should trash bones and save files from previous versions since X they will not work with this version. Record files will work but X notice that new scores will have a different format. It is easiest X to just start fresh with a new scoreboard (record file). X X2. If you can afford the RAM space you might consider giving the game X a 1M partition in Multifinder instead of the default 750k. X X We, the members of the Macintosh NetHack Development Team, hope you X enjoy the game. We've worked hard at porting and polishing it to X make it behave in the Macintosh way! END_OF_FILE if test 14959 -ne `wc -c <'Install.mac'`; then echo shar: \"'Install.mac'\" unpacked with wrong size! fi # end of 'Install.mac' echo shar: Extracting \"'do_patch8.sh'\" \(330 characters\) sed "s/^X//" >'do_patch8.sh' <<'END_OF_FILE' X#! /bin/sh X# script to call patch to apply diff files X# make sure all of the patch files (and this file) are in your top level X# NetHack directory X# Xecho "deleting outdated files" Xrm -f mac/NH3.proj.hqx mac/NH3.rsrc.hqx vms/Install.com Xecho "applying patch8" Xcat patch8.?? | patch -p Xecho "all patches applied, check for rejects" END_OF_FILE if test 330 -ne `wc -c <'do_patch8.sh'`; then echo shar: \"'do_patch8.sh'\" unpacked with wrong size! fi chmod +x 'do_patch8.sh' # end of 'do_patch8.sh' 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' echo shar: Extracting \"'vms/vmsmisc.c'\" \(386 characters\) sed "s/^X//" >'vms/vmsmisc.c' <<'END_OF_FILE' X/* SCCS Id: @(#)vmsmisc.c 3.0 90/22/02 X/* NetHack may be freely redistributed. See license for details. */ X X#include <ssdef.h> X#include <stsdef.h> X Xvoid Xvms_exit(status) Xint status; X{ X exit(status ? (SS$_ABORT | STS$M_INHIB_MSG) : SS$_NORMAL); X} X Xvoid Xvms_abort() X{ X (void) LIB$SIGNAL(SS$_DEBUG); X} X X#ifdef VERYOLD_VMS X#include "oldcrtl.c" /* "[-.vms]oldcrtl.c" */ X#endif END_OF_FILE if test 386 -ne `wc -c <'vms/vmsmisc.c'`; then echo shar: \"'vms/vmsmisc.c'\" unpacked with wrong size! fi # end of 'vms/vmsmisc.c' echo shar: End of archive 20 \(of 24\). cp /dev/null ark20isdone 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 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 24 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