Category : Pascal Source Code
Archive   : TSRSRC33.ZIP
Filename : FMARK.ASM
;FMARK.ASM - mark a position in memory,
; above which TSRs will later be cleared by RELEASE
; this version leaves a minimal size MARK in memory,
; storing the rest on disk
; requires a single command line parameter naming
; the file where the mark will be stored
;
; Syntax: FMARK [/Q] [d:][path]filename
;==============================================================================
; written for TASM
; by Kim Kokkonen, TurboPower Software
; Copyright (c) 1986,1991 Kim Kokkonen, TurboPower Software.
; May be freely distributed but not sold except by permission.
; telephone: 719-260-6641, Compuserve 76004,2611
;==============================================================================
; version 2.0 6/17/86
; start at a version number compatible with other TSR utilities
; :
; long intervening history
; :
; version 3.0 9/24/91
; add Quiet option
; version 3.1 11/4/91
; no change
; version 3.2 11/22/91
; change method of accessing high memory
; store parent len as well as parent segment
; version 3.3 1/8/92
; detect full disk while writing mark file
; erase partial mark file if any error occurs during execution
;==============================================================================
;
Cseg segment public para
assume cs:Cseg, ds:Cseg, es:Cseg
locals @@
org 016H ;access to parent's PSP
parpsp label word
org 02CH
envseg label word ;access to environment segment
org 80H
cmdlen label byte ;command line length
org 81H
cmdlin label byte ;first character of command line
org 100H
fmark proc near
;deallocate environment block of this mark
push es
mov ax,envseg ;environment segment
mov es,ax ; into es
mov ah,49H
int 21H ;deallocate, no reason for an error to occur
pop es
;find first mcb in high memory, if any
mov ax,3000h ;get DOS version
int 21H
cmp al,3
jb @@7 ;no XMS driver possible
mov ax,4300h
int 2Fh ;multiplex call for XMS
cmp al,80h ;proper signature?
jne @@7 ;no XMS driver
mov ax,4310h ;get XMS control address
int 2Fh
mov xmsxxx,bx ;save it
mov xmsxxx[2],es
mov ah,10h
mov dx,0FFFFh
call dword ptr xmsadr ;ask to allocate FFFF paras of UMB
cmp bl,0B0h ;will fail with B0 if UMBs avail
je @@0
cmp bl,0B1h ;will fail with B1 if UMBs all allocated
jne @@7 ;no UMBs exist
@@0: int 12H
mov cl,6
shl ax,cl ;get segment of top of memory
@@1: mov es,ax
cmp byte ptr es:[0000h],'M' ;potential mcb?
jnz @@6 ;not an mcb, try next segment
@@2: mov cx,ax ;save potential start mcb in cx
@@3: inc ax
add ax,es:[0003h] ;ax = start of next mcb
jc @@5 ;can't be an mcb if we wrapped
mov es,ax ;address of next mcb
mov dl,es:[0000h]
cmp dl,'M'
jz @@3 ;good start mcb
cmp dl,'Z'
jz @@9 ;good end mcb
@@5: mov ax,cx ;restore last start segment
@@6: cmp ax,0FFFFh ;top of memory?
je @@7
inc ax ;try next segment
jmp @@1
@@7: xor cx,cx ;no matching UMB
@@9: mov firsthimcb,cx ;store first high mcb
;parse command line for file name
push cs
pop es
mov si,offset cmdlin ;point to command line
mov di,offset filnm ;point to filename storage string
cld
get1: lodsb ;get first non-blank
cmp al,32 ;skip space
je get1
cmp al,9 ;skip tab
je get1
cmp al,13 ;check for end of input
jne geto ;got a non-blank, now get the parameter
cmp di,offset filnm ;filename already specified?
jne gotit ;done if so
jmp error ;no parameter --> error
geto: cmp al,'/' ;check for option
je getoc
cmp al,'-'
jne get2
getoc: lodsb
call upcase
cmp al,'Q'
jnz operr
mov quiet,1 ;set quiet option
jmp get1 ;loop around
operr: mov dx,offset badopt ;bad option
jmp errmsg
get2: cmp di,offset filnm ;filename already specified?
jne operr ;error if so
get2a: call upcase ;upcase char in al
stosb ;store the non-blank character
lodsb ;get next character
cmp al,32
je get1 ;loop back around for blank
cmp al,9
je get1 ;loop back around for tab
cmp al,13
je gotit ;terminate for
jmp short get2a ;keep adding characters to filename
;create the specified file
gotit: mov al,0
stosb ;terminate ASCIIZ pathname
mov dx,offset filnm
xor cx,cx ;normal attribute
mov ah,3CH
int 21H ;DOS CREAT
jae store
mov dx,offset badfil ;bad file name
jmp errmsg
;store the interrupt vector table
store: mov bx,ax ;keep file handle in bx
push ds ;save ds
mov cx,400H ;1024 bytes to store
xor ax,ax
mov ds,ax ;segment 0
assume ds:nothing
mov dx,ax ;offset 0
call blockwrite ;write interrupts to file
assume ds:cseg
;store the EGA save pointer
egasav: push ds ;save ds
mov cx,0008H ;8 bytes to store
mov ax,0040H
mov ds,ax ;BIOS data segment
assume ds:nothing
mov dx,00A8H ;EGA save table pointer
call blockwrite ;write save pointers to file
assume ds:cseg
;store the interapplications communications area
intcom: push ds ;save ds
mov cx,0010H ;16 bytes to store
mov ax,0040H
mov ds,ax ;BIOS data segment
assume ds:nothing
mov dx,00F0H ;interapplications communication area
call blockwrite ;write interapp communications area to file
assume ds:cseg
;store the parent's psp
parent: push ds
mov cx,2 ;2 bytes to store
mov dx,offset parpsp ;point to parent's psp
call blockwrite ;write parent psp to file
assume ds:cseg
parlen: push ds
mov ax,ds:[parpsp]
dec ax
mov ds,ax
assume ds:nothing
mov dx,3 ;ds:dx -> parent's length
mov cx,2
call blockwrite ;write parent psp to file
assume ds:cseg
;determine whether EMS is present
ems: push bx ;temporarily store the file handle
xor bx,bx ;zero the EMS handle count in case EMS not present
mov dx,offset emsnm
mov ax,3D00H
int 21H
jb sthand ;EMS driver not installed
;EMS present, close the open "handle" first
mov bx,ax ;EMS handle into bx
mov ah,3EH
int 21H ;close handle
;get the current EMS page map
mov ah,4DH
mov di,offset emsmap ;es=cs already
xor bx,bx ;required by some versions of EMM (bug workaround)
cld ;required by some versions of EMM
int 67H
or ah,ah
jz sthand ;result ok
xor bx,bx ;error, return zero EMS handles
;store the number of active handles
sthand: mov emscnt,bx ;count of active handles
;write the handle table to disk
shl bx,1
shl bx,1 ;4 bytes per handle
inc bx
inc bx ;2 more bytes for the handle count
mov cx,bx ;number of bytes to write
pop bx ;get file handle back
mov dx,offset emscnt ;what we're writing
push ds
call blockwrite ;write EMS table to file
assume ds:cseg
;write the allocated mcb chain
stomcb: push bx ;save file handle
mov ah,52H ;get first mcb segment
int 21H
mov ax,es:[bx-2] ;ax=first mcb
push cs
pop es ;es=cs
mov di,emscnt ;get starting address of mcbmap
shl di,1
shl di,1
add di,offset emsmap
mov si,di ;cs:[si] -> mcbcnt
add di,2 ;cs:[di] -> mcbmap
xor cx,cx ;cx will count mcbs
cld
push ds
assume ds:nothing
mcbnext:stosw ;store mcb segment held by ax
mov ds,ax ;ds:[0] points to mcb
mov ax,ds:[1] ;get mcb owner
stosw ;store it
inc cx ;increment count
cmp byte ptr ds:[0],'Z' ;end of mcb chain?
je mcbdone
mov ax,ds ;restore ax to mcb segment
inc ax ;skip over mcb itself
add ax,ds:[3] ;add length of memory block
jmp mcbnext
mcbdone:mov ax,cs:firsthimcb ;check for high memory
or ax,ax
jz mcbend
mov cs:firsthimcb,0 ;only do it once
jmp mcbnext
mcbend: pop ds
assume ds:cseg
mov [si],cx ;store number of mcbs
sub di,si ;di=number of bytes in mcb group table
mov cx,di ;count of bytes in cx
mov dx,si ;what we're writing (mcbcnt+mcbmap)
pop bx ;get file handle back
push ds
call blockwrite ;write mcb table to file
assume ds:cseg
;close up the table file
closfl: mov ah,3EH
int 21H ;close handle
jae idstr ;ok, continue
mov dx,offset badcls ;error while closing file
jmp delfil
;put a standard ID string into the PSP for RELEASE to check
idstr: mov si,offset id
mov di,60H ;unused area of the PSP
mov cx,idlen ;characters in ID string
cld
rep movsb ;copy string
;copy the filename into the command tail
mov si,offset filnm
mov di,offset cmdlin
xor cx,cx
nxtf: lodsb
or al,al
jz donf
inc cx
stosb
jmp nxtf
donf: mov cmdlen,cl
;print message and TSR
gores: cmp quiet,0 ;check quiet flag
jnz gores1
mov dx,offset didit
mov ah,9
int 21H ;write success message including filename
mov dx,offset crlf ;newline
mov ah,9
int 21H
gores1: xor dx,dx ;get number of paragraphs to keep
mov dl,cmdlen ;length of command line
add dx,0090H ;rest of PSP plus paragraph margin
mov cl,4
shr dx,cl ;convert to paragraphs
mov ax,3100H
int 21H ;terminate but stay resident
;close mark file, delete it, show error message
errclo: mov ah,3EH
int 21H ;close handle, ignore error
;delete mark file and show error message
assume ds:cseg
delfil: push dx
mov dx,offset filnm
mov ah,41H
int 21H
pop dx
;error output - show syntax line
;dx has offset of error message
errmsg: mov ah,9
int 21H
error:
mov dx,offset syntax
mov ah,9
int 21H
mov ax,4C01H
int 21H
fmark endp
;blockwrite assumes that ds was pushed before the call
blockwrite proc near
mov ah,40H
int 21H ;write block to file
pop dx ;get return address
pop ds ;get ds back
assume ds:cseg
push dx ;return address back on stack
mov dx,offset nowrit
jc errclo ;jump if error during write
cmp ax,cx
jne errclo ;jump if not all bytes written
ret
blockwrite endp
upcase proc near
cmp al,'a'
jb noup
cmp al,'z'
ja noup
and al,0DFH ;uppercase
noup: ret
upcase endp
emsnm db 'EMMXXXX0',0 ;file name for testing EMS presence
id db 'FM3.3 TSR' ;id string for RELEASE check
idlen equ $-id
;messages
badfil db 13,10,'Could not open file for writing',36
nowrit db 13,10,'Error while writing',36
badcls db 13,10,'Error closing table file',36
badopt db 13,10,'Bad command line option',36
syntax db 13,10,'Syntax: FMARK [/Q] [d:][path]filename'
crlf db 13,10,36
didit db 'FMARK 3.3, Copyright 1991 TurboPower Software',13,10
didit2 db 'Marked current memory position in '
;data storage area
filnm db 50H dup (36) ;mark file name
quiet db 0 ;quiet flag
xmsadr label dword ;XMS control address
xmsxxx dw 2 dup (0)
firsthimcb dw 0 ;segment of first mcb in high mem
emscnt dw 0 ;holds number of active pages in map that follows
emsmap = $ ;EMS page map (up to 1024 bytes)
mcbcnt = emsmap+400H ;number of allocated mcbs
mcbmap = mcbcnt+2 ;MCB map (up to 1024 bytes)
Cseg ends
end Fmark
Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!
This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.
But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/