1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453 |
- ; OpenDoors Online Software Programming Toolkit
- ; (C) Copyright 1991 - 1999 by Brian Pirie.
- ;
- ; This library is free software; you can redistribute it and/or
- ; modify it under the terms of the GNU Lesser General Public
- ; License as published by the Free Software Foundation; either
- ; version 2 of the License, or (at your option) any later version.
- ;
- ; This library is distributed in the hope that it will be useful,
- ; but WITHOUT ANY WARRANTY; without even the implied warranty of
- ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- ; Lesser General Public License for more details.
- ;
- ; You should have received a copy of the GNU Lesser General Public
- ; License along with this library; if not, write to the Free Software
- ; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- ;
- ;
- ; File: ODSwap.asm
- ;
- ; Description: Performs EMS/disk swapping and low level spawning
- ; activities. This file should only be included when building
- ; the MS-DOS version of OpenDoors.
- ;
- ; Revisions: Date Ver Who Change
- ; ---------------------------------------------------------------
- ; Oct 13, 1994 6.00 BP New file header format.
- ; Feb 19, 1996 6.00 BP Changed version number to 6.00.
- ; Mar 03, 1996 6.10 BP Begin version 6.10.
- ; If you have increased the file handle table size so that more than 20 files
- ; may be open in the parent process, set FHTSZ to the new size.
- FHTSZ EQU 20
- IFDEF LCODE
- ARG_1 EQU 6
- ELSE
- ARG_1 EQU 4
- ENDIF
- arena struc ; arena header
- sig db 0 ; 'M' or 'Z' if last block
- own dw 0 ; PSP of owner or 0 if free
- siz dw 0 ; size not including header
- arena ends
- vector struc
- number db 0 ; vector number
- flag db 0 ; 0-CURRENT,1-IRET,2-free,3-end
- vseg dw 0 ; vector segment
- voff dw 0 ; vector offset
- vector ends
- _TEXT SEGMENT word public 'CODE'
- ASSUME cs:_TEXT
- ASSUME ds:nothing
- ASSUME es:nothing
- ASSUME ss:nothing
- ; The code between slidetop and slidebot constitutes the spawn kernel. The
- ; kernel is copied to the front of the parent process immediately following the
- ; parent's PSP. The environment passed to the child is copied to immediately
- ; following the kernel.
- slidetop:
- path db 79 dup (0) ; program to execute
- command db 128 dup (0) ; command-line
- file db 79 dup (0) ; swap file
- parmblk label byte ; parameter block
- environ dw 0 ; environment block
- cmd dw 0,0 ; command-line tail
- fcb1 dw 0,0 ; first file control block
- fcb2 dw 0,0 ; second file control block
- fcb5c db 10h dup (0) ; first file control block
- fcb6c db 10h dup (0) ; second file control block
- cntsvl dw 0 ; count save low
- cntsvh dw 0 ; count save high
- tmpcode dw 0 ; temporary return code
- env dw 0 ; environment segment
- envlen dw 0 ; environment length
- parsz dw 0 ; parent size
- ttlsz dw 0 ; total size
- oldsz dw 0 ; old size
- newsz dw 0 ; new size
- emsseg dw 0 ; EMS page frame segment
- handle dw 0 ; EMS handle
- useems db 0 ; if 0, use EMS
- save db 4 dup (0) ; save 4 bytes at DS:[2Eh]
- f1add dd 0 ; fnish1 address
- last db 0 ; if 0, last block swap
- IF FHTSZ - 20
- fhtsv db FHTSZ dup (0) ; file handle table save
- ENDIF
- errmsg db 'spawn error',0Dh,0Ah
- msglen EQU $-errmsg
- EVEN
- lclstk dw 64 dup (0) ; local stack
- stktop label word ; stack top
- slide1: mov ax,cs ; install local stack
- cli
- mov ss,ax
- mov sp,offset stktop - offset slidetop + 100h
- sti
- ; copy environment
- mov bx,offset slidebot - offset slidetop + 15 + 100h
- mov cl,4
- shr bx,cl ; convert to paragraphs
- add bx,ax ; add CS (actually PSP)
- index = offset environ - offset slidetop + 100h
- mov cs:[index],bx ; parameter block
- mov es,bx
- xor di,di
- index = offset env - offset slidetop + 100h
- mov ds,cs:[index]
- xor si,si
- index = offset envlen - offset slidetop + 100h
- mov cx,cs:[index]
- shr cx,1 ; translate to word count
- rep movsw ; CF set if one byte left over
- adc cx,cx ; CX = 1 or 0, depending CF
- rep movsb ; possible final byte
- dec ax ; PSP segment
- mov es,ax ; program arena header
- mov bx,es:[siz]
- index = offset oldsz - offset slidetop + 100h
- mov cs:[index],bx ; old size
- mov byte ptr es:[sig],'M' ; not last
- index = offset newsz - offset slidetop + 100h
- mov bx,cs:[index] ; new size
- mov es:[siz],bx
- inc ax ; PSP segment
- add ax,bx ; add new size
- mov es,ax ; new last arena header
- mov byte ptr es:[sig],'Z' ; last
- index = offset last - offset slidetop + 100h
- cmp byte ptr cs:[index],0
- je slide2 ; jump if last block swap
- mov byte ptr es:[sig],'M' ; not last
- slide2: mov word ptr es:[own],0 ; free
- index = offset ttlsz - offset slidetop + 100h
- mov ax,cs:[index] ; total size
- sub ax,bx ; subtract new size
- dec ax ; account for arena header
- mov es:[siz],ax
- ; save 4 bytes destroyed by DOS 2.0 at DS:2Eh
- mov ax,cs ; PSP segment
- mov es,ax
- mov bx,es:[2Eh]
- index = offset save - offset slidetop + 100h
- mov cs:[index],bx
- mov bx,es:[30h]
- index = offset save - offset slidetop + 102h
- mov cs:[index],bx
- mov bx,offset parmblk - offset slidetop + 100h
- mov ds,ax ; PSP segment
- mov dx,100h ; offset path
- mov ax,4B00h ; load and execute program
- int 21h
- jnc slide3 ; jump if no error
- index = offset tmpcode - offset slidetop + 100h
- mov cs:[index],ax ; temporary return code
- slide3: mov ax,cs ; install local stack
- cli
- mov ss,ax
- mov sp,offset stktop - offset slidetop + 100h
- sti
- ; restore 4 bytes destroyed by DOS 2.0 at DS:2Eh
- mov es,ax ; PSP segment
- index = offset save - offset slidetop + 100h
- mov bx,cs:[index]
- mov es:[2Eh],bx
- index = offset save - offset slidetop + 102h
- mov bx,cs:[index]
- mov es:[30h],bx
- index = offset oldsz - offset slidetop + 100h
- mov bx,cs:[index] ; old size
- mov ah,4Ah ; resize memory block
- int 21h
- jnc slide7
- index = offset useems - offset slidetop + 100h
- slide4: cmp byte ptr cs:[index],0
- jne slide6 ; jump if don't use EMS
- index = offset handle - offset slidetop + 100h
- mov dx,cs:[index] ; EMS handle
- slide5: mov ah,45h ; release handle and memory
- int 67h
- cmp ah,82h ; memory manager busy?
- je slide5 ; jump if busy
- slide6: jmp slide18 ; exit
- index = offset parsz - offset slidetop + 100h
- slide7: mov bx,cs:[index] ; parent size
- index = offset ttlsz - offset slidetop + 100h
- mov ax,cs:[index] ; total size
- sub ax,bx ; subtract parent size
- or ax,ax
- jz slide9
- mov dx,cs ; PSP segment
- add dx,bx ; add parent size
- mov es,dx ; new last arena header
- mov byte ptr es:[sig],'Z' ; last
- index = offset last - offset slidetop + 100h
- cmp byte ptr cs:[index],0
- je slide8 ; jump if last block swap
- mov byte ptr es:[sig],'M' ; not last
- slide8: mov word ptr es:[own],0 ; free
- dec ax ; account for arena header
- mov es:[siz],ax
- slide9: push cs ; PSP segment
- index = offset useems - offset slidetop + 100h
- cmp byte ptr cs:[index],0
- jne slide14 ; jump if don't use EMS
- pop es ; PSP segment
- mov di,offset slidebot - offset slidetop + 100h
- index = offset emsseg - offset slidetop + 100h
- mov ds,cs:[index] ; EMS page frame segment
- mov si,offset slidebot - offset slidetop
- index = offset handle - offset slidetop + 100h
- mov dx,cs:[index] ; EMS handle
- xor bx,bx ; logical page number
- mov cx,16384 - ( offset slidebot - offset slidetop )
- jmp short slide13
- index = offset cntsvl - offset slidetop + 100h
- slide10: sub cs:[index],cx
- index = offset cntsvh - offset slidetop + 100h
- sbb word ptr cs:[index],0
- xor al,al ; physical page number
- slide11: mov ah,44h ; map memory
- int 67h
- or ah,ah
- jz slide12
- cmp ah,82h ; memory manager busy?
- je slide11 ; jump if busy
- jmp slide4 ; exit
- slide12: shr cx,1 ; translate to word count
- rep movsw ; CF set if one byte left over
- adc cx,cx ; CX = 1 or 0, depending CF
- rep movsb ; possible final byte
- xor si,si
- mov cx,16384 ; assume copy full block
- inc bx ; logical page number
- cmp bx,1
- je slide13
- mov ax,es
- add ax,1024 ; 16384 bytes
- mov es,ax
- mov di,16640 ; 16384 + 100h
- index = offset cntsvh - offset slidetop + 100h
- slide13: cmp word ptr cs:[index],0
- jne slide10 ; jump if more than full block
- index = offset cntsvl - offset slidetop + 100h
- cmp cs:[index],cx
- jae slide10 ; jump if at least full block
- mov cx,cs:[index] ; CX = cntsvl
- cmp cx,0
- jne slide10 ; jump if more left to copy
- jmp short slide17
- slide14: pop ds ; PSP segment
- IF FHTSZ - 20
- ; restore the file handle table from the kernel
- mov si,offset fhtsv - offset slidetop + 100h
- mov es,ds:[36h] ; file handle table segment
- mov di,ds:[34h] ; file handle table offset
- mov cx,FHTSZ ; file handle table size
- rep movsb
- ENDIF
- mov dx,offset file - offset slidetop + 100h
- mov ax,3D00h ; open file read only
- int 21h
- jc slide18 ; exit if error
- mov bx,ax ; handle
- xor cx,cx
- mov dx,offset slidebot - offset slidetop
- mov ax,4200h ; move file pointer
- int 21h ; from beginning of file
- mov dx,offset slidebot - offset slidetop + 100h
- mov cx,65520 ; assume read full block
- jmp short slide16
- index = offset cntsvl - offset slidetop + 100h
- slide15: sub cs:[index],cx
- index = offset cntsvh - offset slidetop + 100h
- sbb word ptr cs:[index],0
- mov ah,3Fh ; read file
- int 21h
- jc slide18 ; exit if error
- cmp ax,cx
- jne slide18 ; exit if not all read
- mov ax,ds
- add ax,4095 ; 65520 bytes
- mov ds,ax
- index = offset cntsvh - offset slidetop + 100h
- slide16: cmp word ptr cs:[index],0
- jne slide15 ; jump if more than full block
- index = offset cntsvl - offset slidetop + 100h
- cmp word ptr cs:[index],65520
- jae slide15 ; jump if at least full block
- mov cx,cs:[index] ; CX = cntsvl
- cmp cx,0
- jne slide15 ; jump if more left to read
- index = offset tmpcode - offset slidetop + 100h
- slide17: mov ax,cs:[index] ; temporary return code
- index = offset f1add - offset slidetop + 100h
- jmp dword ptr cs:[index]
- slide18: push cs ; PSP segment
- pop ds
- mov dx,offset errmsg - offset slidetop + 100h
- mov cx,msglen ; errmsg length
- mov bx,2 ; standard error device handle
- mov ah,40h ; write error message
- int 21h
- mov ax,4C01h ; terminate with return code
- int 21h
- handler: iret ; interrupt handler
- slidebot:
- cntl dw 0 ; count low
- cnth dw 0 ; count high
- stks dw 0 ; original SS contents
- stkp dw 0 ; original SP contents
- psp dw 0 ; PSP segment
- s1add dd 0 ; slide1 address
- rcode dw 0 ; return code
- useems2 db 0 ; if 0, use EMS
- vtabseg dw 0 ; vectab1 segment
- vtaboff dw 0 ; vectab1 offset
- errmsg2 db 'spawn error',0Dh,0Ah
- msglen2 EQU $-errmsg2
- ;
- ; int _xspawn( char *, char *, char *, VECTOR *, int, int, char *, int );
- ;
- PUBLIC __xspawn
- IFDEF LCODE
- __xspawn PROC far
- ELSE
- __xspawn PROC near
- ENDIF
- push bp
- mov bp,sp
- push di ; preserve register variables
- push si
- push ds
- IFDEF LDATA
- lds si,dword ptr [bp+ARG_1]
- ELSE
- mov si,word ptr [bp+ARG_1]
- ENDIF
- mov di,offset path
- start1: mov al,ds:[si] ; copy path string
- mov cs:[di],al ; to code segment
- inc si
- inc di
- or al,al ; null char?
- jnz start1 ; no, get next char
- IFDEF LDATA
- lds si,dword ptr [bp+ARG_1+4]
- ELSE
- mov si,word ptr [bp+ARG_1+2]
- ENDIF
- mov bx,si ; preserve si
- mov di,offset command
- mov cx,2 ; account for count and '\r'
- add cl,byte ptr ds:[bx] ; add count byte
- start2: mov al,ds:[bx] ; copy command
- mov cs:[di],al ; to code segment
- inc bx
- inc di
- loop start2 ; get next char
- inc si ; skip count byte
- push cs
- pop es
- mov di,offset fcb5c
- mov ax,2901h ; parse filename
- int 21h ; skip leading separators
- mov di,offset fcb6c
- mov al,1 ; parse filename
- int 21h ; skip leading separators
- IFDEF LDATA
- mov ax,word ptr [bp+ARG_1+8]
- ELSE
- mov ax,word ptr [bp+ARG_1+4]
- ENDIF
- mov cl,4
- shr ax,cl ; convert to paragraphs
- IFDEF LDATA
- mov bx,word ptr [bp+ARG_1+10]
- ELSE
- mov bx,ds
- ENDIF
- add ax,bx
- mov cs:[env],ax ; environment segment
- IFDEF LDATA
- lds bx,dword ptr [bp+ARG_1+12] ; vectab1
- ELSE
- mov bx,word ptr [bp+ARG_1+6] ; vectab1
- ENDIF
- mov cs:[vtabseg],ds ; vectab1 segment
- mov cs:[vtaboff],bx ; vectab1 offset
- mov cs:[stks],ss ; original SS contents
- mov cs:[stkp],sp ; original SP contents
- mov cs:[rcode],0 ; assume success
- IFDEF LDATA
- mov ax,word ptr [bp+ARG_1+16]
- ELSE
- mov ax,word ptr [bp+ARG_1+8]
- ENDIF
- or ax,ax ; do swap?
- jz start3 ; yes, jump
- jmp noswap1
- IFDEF LDATA
- start3: mov ax,word ptr [bp+ARG_1+18]
- ELSE
- start3: mov ax,word ptr [bp+ARG_1+10]
- ENDIF
- mov cs:[envlen],ax ; environment length
- add ax,offset slidebot - offset slidetop + 30 + 100h
- mov cl,4
- shr ax,cl ; convert to paragraphs
- mov cs:[newsz],ax ; new size
- IFDEF LDATA
- lds si,dword ptr [bp+ARG_1+20]
- ELSE
- mov si,word ptr [bp+ARG_1+12]
- ENDIF
- mov di,offset file
- mov cs:[useems2],1 ; assume don't use EMS
- cmp byte ptr ds:[si],0
- jne start4
- mov cs:[useems2],0 ; use EMS
- start4: mov al,ds:[si] ; copy file string
- mov cs:[di],al ; to code segment
- inc si
- inc di
- or al,al ; null char?
- jnz start4 ; no, get next char
- ; save fnish1 address
- mov word ptr cs:[f1add+2],cs
- mov word ptr cs:[f1add],offset fnish1
- ; initialize parameter block
- mov ax,cs:[psp] ; PSP segment
- mov cs:[cmd],offset command - offset slidetop + 100h
- mov cs:[cmd+2],ax
- mov cs:[fcb1],offset fcb5c - offset slidetop + 100h
- mov cs:[fcb1+2],ax
- mov cs:[fcb2],offset fcb6c - offset slidetop + 100h
- mov cs:[fcb2+2],ax
- cld ; left to right direction
- mov ds,ax ; PSP segment
- IFDEF LDATA
- mov dx,word ptr [bp+ARG_1+24]
- ELSE
- mov dx,word ptr [bp+ARG_1+14]
- ENDIF
- IF FHTSZ - 20
- cmp word ptr ds:[32h],FHTSZ ; file handle table size
- je start5 ; jump if OK
- mov cs:[rcode],5
- jmp short start6
- ENDIF
- start5: mov ax,cs:[newsz] ; new size
- cmp ax,cs:[ttlsz] ; new size < total size?
- jb start8 ; yes, jump
- mov cs:[rcode],7 ; extremely unlikely
- start6: cmp cs:[useems2],0
- jne start7 ; jump if don't use EMS
- jmp fnish2
- start7: mov bx,dx ; file handle
- jmp fnish6
- start8: cmp cs:[useems2],0
- jne start12 ; jump if don't use EMS
- mov cs:[useems],0 ; use EMS
- mov cs:[handle],dx ; EMS handle
- mov es,cs:[emsseg] ; EMS page frame segment
- xor bx,bx ; logical page number
- jmp short start11
- start9: sub cs:[cntl],cx
- sbb cs:[cnth],0
- call mapems
- or ah,ah
- jz start10 ; jump if map succeeded
- jmp fnish2
- start10: mov si,100h
- xor di,di
- shr cx,1 ; translate to word count
- rep movsw ; CF set if one byte left over
- adc cx,cx ; CX = 1 or 0, depending CF
- rep movsb ; possible final byte
- inc bx ; logical page number
- mov ax,ds
- add ax,1024 ; 16384 bytes
- mov ds,ax
- start11: mov cx,16384 ; assume copy full block
- cmp cs:[cnth],0
- jne start9 ; jump if more than full block
- cmp cs:[cntl],16384
- jae start9 ; jump if at least full block
- mov cx,cs:[cntl]
- cmp cx,0
- jne start9 ; jump if more left to copy
- jmp short start17
- start12: mov cs:[useems],1 ; don't use EMS
- mov bx,dx ; handle
- mov dx,100h ; DS:DX segment:offset buffer
- mov cx,65520 ; assume write full block
- jmp short start16
- start13: sub cs:[cntl],cx
- sbb cs:[cnth],0
- mov ah,40h ; write file
- int 21h
- jc start14 ; jump if error
- cmp ax,cx
- je start15 ; jump if all written
- start14: mov ah,3Eh ; close file
- int 21h
- mov cs:[rcode],5
- jmp fnish7
- start15: mov ax,ds
- add ax,4095 ; 65520 bytes
- mov ds,ax
- start16: cmp cs:[cnth],0
- jne start13 ; jump if more than full block
- cmp cs:[cntl],65520
- jae start13 ; jump if at least full block
- mov cx,cs:[cntl]
- cmp cx,0
- jne start13 ; jump if more left to write
- mov ah,3Eh ; close file
- int 21h
- IF FHTSZ - 20
- ; save the file handle table in the kernel
- mov es,cs:[psp] ; PSP segment
- mov ds,es:[36h] ; file handle table segment
- mov si,es:[34h] ; file handle table offset
- push cs
- pop es
- mov di,offset fhtsv ; file handle table save
- mov cx,FHTSZ ; file handle table size
- rep movsb
- ENDIF
- start17: mov cx,cs
- mov dx,offset handler ; interrupt handler offset
- call safevect ; set vectors in vectab1
- ; time to copy the kernel
- mov es,cs:[psp] ; PSP segment
- mov di,100h
- mov ds,cx ; DS = CS
- mov si,offset slidetop
- mov cx,offset slidebot - offset slidetop
- shr cx,1 ; translate to word count
- rep movsw ; CF set if one byte left over
- adc cx,cx ; CX = 1 or 0, depending CF
- rep movsb ; possible final byte
- mov word ptr cs:[s1add+2],es ; PSP segment
- index = offset slide1 - offset slidetop + 100h
- mov word ptr cs:[s1add],index ; slide1 offset
- mov cx,es ; PSP segment
- index = offset handler - offset slidetop + 100h
- mov dx,index ; interrupt handler offset
- call safevect ; set vectors in vectab1
- jmp dword ptr cs:[s1add] ; jump to the kernel
- ; If all goes well, this is where we come back to from the kernel.
- fnish1: mov cs:[rcode],ax ; return code
- cli ; restore original stack
- mov ss,cs:[stks]
- mov sp,cs:[stkp]
- sti
- push ds ; maybe EMS page frame segment
- push dx ; maybe EMS handle
- push bx ; maybe swap file handle
- mov cx,cs
- mov dx,offset handler ; interrupt handler offset
- call safevect ; set vectors in vectab1
- pop bx
- pop dx
- pop ds
- cmp cs:[useems2],0
- jne fnish4 ; jump if don't use EMS
- ; DS = EMS page frame segment
- ; DX = EMS handle
- mov cx,offset slidebot - offset slidetop
- mov es,cs:[psp] ; PSP segment
- mov di,100h
- xor si,si
- xor bx,bx ; logical page number
- call mapems
- or ah,ah
- jnz fnish3 ; jump if map failed
- shr cx,1 ; translate to word count
- rep movsw ; CF set if one byte left over
- adc cx,cx ; CX = 1 or 0, depending CF
- rep movsb ; possible final byte
- fnish2: mov ah,45h ; release handle and memory
- int 67h
- cmp ah,82h ; memory manager busy?
- je fnish2 ; jump if busy
- jmp short fnish7
- fnish3: mov ah,45h ; release handle and memory
- int 67h
- cmp ah,82h ; memory manager busy?
- je fnish3 ; jump if busy
- jmp short fnish5 ; exit
- ; BX = swap file handle
- fnish4: xor cx,cx ; offset 0
- xor dx,dx ; offset 0
- mov ax,4200h ; move file pointer
- int 21h ; from beginning of file
- mov cx,offset slidebot - offset slidetop
- mov ds,cs:[psp] ; PSP segment
- mov dx,100h
- mov ah,3Fh ; read file
- int 21h
- jc fnish5 ; exit if error
- cmp ax,cx
- je fnish6
- fnish5: push cs
- pop ds
- mov dx,offset errmsg2
- mov cx,msglen2 ; errmsg2 length
- mov bx,2 ; standard error device handle
- mov ah,40h ; write error message
- int 21h
- mov ax,4C01h ; terminate with return code
- int 21h
- fnish6: mov ah,3Eh ; close file
- int 21h
- push cs
- pop ds
- mov dx,offset file
- mov ah,41h ; delete file
- int 21h
- fnish7: pop ds
- pop si ; restore register variables
- pop di
- pop bp
- mov ax,cs:[rcode] ; return code
- or ax,ax
- jz fnish11
- push ax
- mov ax,3000h ; get DOS version number
- int 21h
- cmp al,3 ; major version number
- pop ax
- jb fnish8
- cmp al,34 ; unknown error - 3.0
- jae fnish9
- cmp al,32 ; sharing violation
- jb fnish8
- mov al,5 ; access denied
- jmp short fnish10
- fnish8: cmp al,19 ; unknown error - 2.0
- jbe fnish10
- fnish9: mov al,19 ; unknown error - 2.0
- fnish10: xor ah,ah
- fnish11: ret
- ; If we are not swapping, we jump here.
- noswap1: mov ax,cs
- ; initialize parameter block
- mov bx,cs:[env]
- mov cs:[environ],bx
- mov cs:[cmd],offset command
- mov cs:[cmd+2],ax
- mov cs:[fcb1],offset fcb5c
- mov cs:[fcb1+2],ax
- mov cs:[fcb2],offset fcb6c
- mov cs:[fcb2+2],ax
- ; save 4 bytes destroyed by DOS 2.0 at DS:2Eh
- mov si,cs:[2Eh]
- mov word ptr cs:[save],si
- mov si,cs:[30h]
- mov word ptr cs:[save+2],si
- mov cx,cs
- mov dx,offset handler ; interrupt handler offset
- call safevect ; set vectors in vectab1
- mov es,cx ; ES = CS
- mov bx,offset parmblk
- mov ds,cx ; DS = CS
- mov dx,offset path
- mov ax,4B00h ; load and execute program
- int 21h
- jnc noswap2 ; jump if no error
- mov cs:[rcode],ax ; return code
- noswap2: cli ; restore original stack
- mov ss,cs:[stks]
- mov sp,cs:[stkp]
- sti
- ; restore 4 bytes destroyed by DOS 2.0 at DS:2Eh
- mov si,word ptr cs:[save]
- mov cs:[2Eh],si
- mov si,word ptr cs:[save+2]
- mov cs:[30h],si
- jmp fnish7
- __xspawn ENDP
- mapems PROC near
- ; DX = handle
- ; BX = logical page number
- xor al,al ; physical page number
- map1: mov ah,44h ; map memory
- int 67h
- cmp ah,82h ; memory manager busy?
- je map1 ; jump if busy
- ret
- mapems ENDP
- setvectsub PROC near
- ; ES = vector table segment
- ; BX = vector table offset
- mov ah,25h ; set interrupt vector
- setvectsub1: mov al,es:[bx+flag] ; 0-CURRENT,1-IRET,2-free,3-end
- cmp al,3 ; is it the end?
- je setvectsub3 ; yes, jump
- cmp al,2 ; is it free?
- je setvectsub2 ; yes, jump
- mov al,es:[bx+number] ; vector number
- mov ds,es:[bx+vseg] ; vector segment
- mov dx,es:[bx+voff] ; vector offset
- int 21h ; set interrupt vector
- setvectsub2: add bx,6 ; size of vector structure
- jmp setvectsub1 ; next
- setvectsub3: ret
- setvectsub ENDP
- safevect PROC near
- ; CX = handler segment
- ; DX = handler offset
- mov es,cs:[vtabseg] ; vectab1 segment
- mov bx,cs:[vtaboff] ; vectab1 offset
- safevect1: mov al,es:[bx+flag] ; 0-CURRENT,1-IRET,2-free,3-end
- cmp al,3 ; is it the end?
- je safevect3 ; yes, jump
- cmp al,1 ; is it IRET?
- jne safevect2 ; no, jump
- mov es:[bx+vseg],cx ; handler segment
- mov es:[bx+voff],dx ; handler offset
- safevect2: add bx,6 ; size of vector structure
- jmp safevect1 ; next
- safevect3: mov bx,cs:[vtaboff] ; vectab1 offset
- call setvectsub
- ret
- safevect ENDP
- ;
- ; int _xsize( unsigned int, long *, long * );
- ;
- PUBLIC __xsize
- IFDEF LCODE
- __xsize PROC far
- ELSE
- __xsize PROC near
- ENDIF
- push bp
- mov bp,sp
- push di ; preserve register variables
- push si
- push ds
- mov cs:[last],0 ; assume last block swap
- mov bx,word ptr [bp+ARG_1] ; PSP segment
- mov cs:[psp],bx
- mov dx,bx
- dec bx ; program arena header
- size1: mov es,bx ; current arena header
- mov ax,es:[own]
- or ax,ax ; is it free?
- jz size2 ; yes, count it
- cmp ax,dx ; do we own it?
- jne size4 ; no, jump
- mov cx,bx ; last owned block
- size2: inc bx
- add bx,es:[siz] ; block size
- jc size3 ; carry, arena is trashed
- mov al,es:[sig] ; get arena signature
- cmp al,'M' ; are we at end of memory?
- je size1 ; no, jump
- cmp al,'Z'
- je size5
- size3: mov bx,-1 ; request maximum memory
- mov ah,48h ; allocate memory block
- int 21h
- mov cs:[rcode],7
- jmp fnish7
- size4: mov cs:[last],1 ; not last block swap
- size5: sub bx,dx ; subtract PSP segment
- mov ax,cx ; last owned block
- mov es,cx
- inc ax
- add ax,es:[siz] ; block size
- sub ax,dx ; subtract PSP segment
- mov cs:[parsz],ax ; parent size
- sub ax,10h ; subtract PSP size
- xor dx,dx ; convert to bytes
- mov cx,4
- size6: shl ax,1
- rcl dx,1
- loop size6
- IFDEF LDATA
- lds si,dword ptr [bp+ARG_1+2]
- ELSE
- mov si,word ptr [bp+ARG_1+2]
- ENDIF
- mov ds:[si],ax ; swap size requirement
- mov ds:[si+2],dx
- mov cs:[cntl],ax ; count low
- mov cs:[cnth],dx ; count high
- mov cx,offset slidebot - offset slidetop
- sub ax,cx
- sbb dx,0
- mov cs:[cntsvl],ax ; count save low
- mov cs:[cntsvh],dx ; count save high
- mov cs:[ttlsz],bx ; total size
- xor dx,dx ; convert to bytes
- mov cx,4
- size7: shl bx,1
- rcl dx,1
- loop size7
- IFDEF LDATA
- lds si,dword ptr [bp+ARG_1+6]
- ELSE
- mov si,word ptr [bp+ARG_1+4]
- ENDIF
- mov ds:[si],bx ; parent and free memory
- mov ds:[si+2],dx
- pop ds
- pop si ; restore register variables
- pop di
- pop bp
- xor ax,ax
- ret
- __xsize ENDP
- ;
- ; int _chkems( char *, int * );
- ;
- PUBLIC __chkems
- IFDEF LCODE
- __chkems PROC far
- ELSE
- __chkems PROC near
- ENDIF
- push bp
- mov bp,sp
- ; determine whether expanded memory is available
- IFDEF LDATA
- push ds
- lds dx,dword ptr [bp+ARG_1] ; EMM device driver name
- ELSE
- mov dx,word ptr [bp+ARG_1] ; EMM device driver name
- ENDIF
- mov ax,3D00h ; open file read only
- int 21h
- IFDEF LDATA
- pop ds
- ENDIF
- jc check2 ; expanded memory unavailable
- ; determine whether we opened the EMM device driver or a file
- mov bx,ax ; handle
- mov ax,4400h ; IOCTL - get device info
- int 21h
- jc check1 ; expanded memory unavailable
- test dx,80h ; test bit 7
- jz check1 ; expanded memory unavailable
- mov ax,4407h ; IOCTL - get output status
- int 21h
- jc check1 ; expanded memory unavailable
- or al,al
- jz check1 ; expanded memory unavailable
- ; close EMM device driver to reclaim handle
- mov ah,3Eh ; close file
- int 21h
- ; determine whether the EMM is functional
- mov ah,40h ; get manager status
- int 67h
- or ah,ah
- jnz check2 ; expanded memory unavailable
- ; check EMM version
- mov ah,46h ; get EMM version
- int 67h
- or ah,ah
- jnz check2 ; expanded memory unavailable
- cmp al,32h ; version 3.2
- jb check2 ; expanded memory unavailable
- ; get page frame segment
- mov ah,41h ; get page frame segment
- int 67h
- or ah,ah
- jnz check2 ; expanded memory unavailable
- mov cs:[emsseg],bx ; segment
- ; get size of page map information
- mov ax,4E03h ; get size of page map info
- int 67h
- or ah,ah
- jnz check2 ; expanded memory unavailable
- IFDEF LDATA
- les bx,dword ptr [bp+ARG_1+4] ; mapsize address
- mov es:[bx],ax
- ELSE
- mov bx,word ptr [bp+ARG_1+2] ; mapsize address
- mov ds:[bx],ax
- ENDIF
- xor ax,ax ; expanded memory available
- pop bp
- ret
- ; close EMM device driver or file to reclaim handle
- check1: mov ah,3Eh ; close file
- int 21h
- check2: mov ax,1 ; expanded memory unavailable
- pop bp
- ret
- __chkems ENDP
- ;
- ; int _savemap( char * );
- ;
- PUBLIC __savemap
- IFDEF LCODE
- __savemap PROC far
- ELSE
- __savemap PROC near
- ENDIF
- push bp
- mov bp,sp
- push di ; preserve register variable
- IFDEF LDATA
- les di,dword ptr [bp+ARG_1] ; buffer address
- ELSE
- mov di,word ptr [bp+ARG_1] ; buffer address
- push ds
- pop es
- ENDIF
- mov ax,4E00h ; save page map
- int 67h
- pop di ; restore register variable
- pop bp
- ret
- __savemap ENDP
- ;
- ; int _restmap( char * );
- ;
- PUBLIC __restmap
- IFDEF LCODE
- __restmap PROC far
- ELSE
- __restmap PROC near
- ENDIF
- push bp
- mov bp,sp
- push ds
- push si ; preserve register variable
- IFDEF LDATA
- lds si,dword ptr [bp+ARG_1] ; buffer address
- ELSE
- mov si,word ptr [bp+ARG_1] ; buffer address
- ENDIF
- mov ax,4E01h ; restore page map
- int 67h
- xor al,al
- pop si ; restore register variable
- pop ds
- pop bp
- ret
- __restmap ENDP
- ;
- ; int _getems( int, int * );
- ;
- PUBLIC __getems
- IFDEF LCODE
- __getems PROC far
- ELSE
- __getems PROC near
- ENDIF
- push bp
- mov bp,sp
- mov bx,word ptr [bp+ARG_1] ; number of pages
- mov ah,43h ; get handle and allocate
- ; memory
- int 67h
- IFDEF LDATA
- les bx,dword ptr [bp+ARG_1+2] ; handle address
- mov es:[bx],dx ; handle
- ELSE
- mov bx,word ptr [bp+ARG_1+2] ; handle address
- mov ds:[bx],dx ; handle
- ENDIF
- xor al,al
- pop bp
- ret
- __getems ENDP
- ;
- ; int _dskspace( int, unsigned int *, unsigned int * );
- ;
- PUBLIC __dskspace
- IFDEF LCODE
- __dskspace PROC far
- ELSE
- __dskspace PROC near
- ENDIF
- push bp
- mov bp,sp
- push di ; preserve register variable
- mov ah,36h ; get free disk space
- mov dl,byte ptr [bp+ARG_1] ; drive code (0=default, 1=A)
- int 21h
- cmp ax,0FFFFh ; was drive invalid?
- je space1 ; yes, jump
- mul cx ; bytes per sector *
- ; sectors per cluster
- IFDEF LDATA
- les di,dword ptr [bp+ARG_1+2]
- mov es:[di],ax ; bytes per cluster
- ELSE
- mov di,word ptr [bp+ARG_1+2]
- mov ds:[di],ax ; bytes per cluster
- ENDIF
- IFDEF LDATA
- les di,dword ptr [bp+ARG_1+6]
- mov es:[di],bx ; number of available clusters
- ELSE
- mov di,word ptr [bp+ARG_1+4]
- mov ds:[di],bx ; number of available clusters
- ENDIF
- xor ax,ax
- space1: pop di ; restore register variable
- pop bp
- ret
- __dskspace ENDP
- ;
- ; int _getrc( void );
- ;
- PUBLIC __getrc
- IFDEF LCODE
- __getrc PROC far
- ELSE
- __getrc PROC near
- ENDIF
- mov ah,4Dh ; get child return code
- int 21h
- ret
- __getrc ENDP
- ;
- ; int _create( char *, int * );
- ;
- PUBLIC __create
- IFDEF LCODE
- __create PROC far
- ELSE
- __create PROC near
- ENDIF
- push bp
- mov bp,sp
- IFDEF LDATA
- push ds
- ENDIF
- mov ax,3000h ; get DOS version number
- int 21h
- IFDEF LDATA
- lds dx,dword ptr [bp+ARG_1] ; file
- ELSE
- mov dx,word ptr [bp+ARG_1] ; file
- ENDIF
- xor cx,cx ; normal attribute
- mov ah,5Bh ; create new file
- cmp al,3 ; major version number
- jae create1
- mov ah,3Ch ; create file
- create1: int 21h
- jc create2
- IFDEF LDATA
- lds bx,dword ptr [bp+ARG_1+4] ; handle address
- ELSE
- mov bx,word ptr [bp+ARG_1+2] ; handle address
- ENDIF
- mov ds:[bx],ax
- xor ax,ax
- create2:
- IFDEF LDATA
- pop ds
- ENDIF
- pop bp
- ret
- __create ENDP
- ;
- ; int _getcd( int, char * );
- ;
- PUBLIC __getcd
- IFDEF LCODE
- __getcd PROC far
- ELSE
- __getcd PROC near
- ENDIF
- push bp
- mov bp,sp
- push si ; preserve register variable
- IFDEF LDATA
- push ds
- ENDIF
- mov dl,byte ptr [bp+ARG_1] ; drive code (0=default, 1=A)
- IFDEF LDATA
- lds si,dword ptr [bp+ARG_1+2] ; buffer
- ELSE
- mov si,word ptr [bp+ARG_1+2] ; buffer
- ENDIF
- mov ah,47h ; get current directory
- int 21h
- jc getcd1
- xor ax,ax
- getcd1:
- IFDEF LDATA
- pop ds
- ENDIF
- pop si ; restore register variable
- pop bp
- ret
- __getcd ENDP
- ;
- ; int _getdrv( void );
- ;
- PUBLIC __getdrv
- IFDEF LCODE
- __getdrv PROC far
- ELSE
- __getdrv PROC near
- ENDIF
- mov ah,19h ; get default disk drive
- int 21h
- xor ah,ah
- ; AX = drive (0 = A, 1 = B, etc.)
- ret
- __getdrv ENDP
- ;
- ; void _getvect( int, unsigned int *, unsigned int * );
- ;
- PUBLIC __getvect
- IFDEF LCODE
- __getvect PROC far
- ELSE
- __getvect PROC near
- ENDIF
- push bp
- mov bp,sp
- push ds
- push si ; preserve register variable
- mov ah,35h ; get interrupt vector
- mov al,byte ptr [bp+ARG_1] ; interrupt number
- int 21h
- IFDEF LDATA
- lds si,dword ptr [bp+ARG_1+2]
- ELSE
- mov si,word ptr [bp+ARG_1+2]
- ENDIF
- mov ds:[si],es ; segment
- IFDEF LDATA
- lds si,dword ptr [bp+ARG_1+6]
- ELSE
- mov si,word ptr [bp+ARG_1+4]
- ENDIF
- mov ds:[si],bx ; offset
- pop si ; restore register variable
- pop ds
- pop bp
- ret
- __getvect ENDP
- ;
- ; void _setvect( VECTOR * );
- ;
- PUBLIC __setvect
- IFDEF LCODE
- __setvect PROC far
- ELSE
- __setvect PROC near
- ENDIF
- push bp
- mov bp,sp
- push ds ; modified in setvectsub
- IFDEF LDATA
- les bx,dword ptr [bp+ARG_1] ; vector table
- ELSE
- mov bx,word ptr [bp+ARG_1] ; vector table
- push ds
- pop es
- ENDIF
- call setvectsub
- pop ds
- pop bp
- ret
- __setvect ENDP
- ;
- ; void _setdrvcd(int drive, char * string);
- ;
- PUBLIC __setdrvcd
- IFDEF LCODE
- __setdrvcd PROC far
- ELSE
- __setdrvcd PROC near
- ENDIF
- push bp
- mov bp,sp
- IFDEF LDATA
- push ds
- ENDIF
- mov dl,byte ptr [bp+ARG_1] ; drive code (0=A, 1=B)
- mov ah,0eh
- int 21h
- IFDEF LDATA
- lds dx,dword ptr [bp+ARG_1+2] ; buffer
- ELSE
- mov dx,word ptr [bp+ARG_1+2] ; buffer
- ENDIF
- mov ah,3bh ; set current directory
- int 21h
- IFDEF LDATA
- pop ds
- ENDIF
- pop bp
- ret
- __setdrvcd ENDP
- _TEXT ENDS
- END
|