;==============================================================================
;FMARK.ASM - mark a position in memory,
;            above which TSRs will later be cleared by RELEASE.COM
;            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 [d:][path]filename
;==============================================================================
; written for MASM (version 4 or later) or TASM
; by Kim Kokkonen, TurboPower Software
; telephone: 408-438-8608, Compuserve 72457,2131
;==============================================================================
; VERSION 2.0  6/17/86
;   start at a version number compatible with other TSR utilities
; VERSION 2.1  7/18/86
;   keep consistent with RELEASE
; VERSION 2.2  3/4/87
;   add save area for BIOS data areas
;     40:A8 (8 bytes for EGA)
;     40:F0 (16 bytes for interapplications communications)
; VERSION 2.3  5/2/87
;   convert to MASM
; VERSION 2.4  5/17/87
;   for consistency with RELEASE
; VERSION 2.5  6/2/87
;   fix bug in memory allocated when command line is 15 bytes long
;   add version checking for consistency between FMARK and RELEASE
; VERSION 2.6  1/15/89
;   fix problem occurring when command processor is an EXE file,
;     by storing parent's PSP segment as part of MARK save area
;     (thanks to Tom Rawson for this code)
; VERSION 2.7
;   skipped
; VERSION 2.8
;   for consistency with MARKNET/RELNET
; VERSION 2.9
;   for consistency with MARKNET/RELNET
;==============================================================================
;
Cseg      segment public para
          assume  cs:Cseg, ds:Cseg, es:Cseg

          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

comentry:

;parse command line for file name
       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     get2             ;got a non-blank, now get the parameter
       jmp     error            ;no parameter --> error

get2:  cmp     al,'a'
       jl      sto1
       cmp     al,'z'
       jg      sto1
       and     al,0DFH          ;uppercase
sto1:  stosb                    ;store the non-blank character
       lodsb                    ;get next character
       cmp     al,32            ;terminate with blank, tab, or <cr>
       je      gotit
       cmp     al,9
       je      gotit
       cmp     al,13
       je      gotit
       jmp     short get2

;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
       mov     ah,9
       int     21H
       jmp     error

;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
       mov     ah,40H
       int     21H             ;write block to file
       pop     ds              ;get ds back
       assume  ds:cseg
       jae     egasav          ;ok, continue

       mov     dx,offset nowrit ;write error
       mov     ah,9
       int     21H
       jmp     error

;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
       mov     ah,40H
       int     21H             ;write block to file
       pop     ds              ;get ds back
       assume  ds:cseg
       jae     intcom          ;ok, continue

       mov     dx,offset nowrit ;write error
       mov     ah,9
       int     21H
       jmp     error

;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
       mov     ah,40H
       int     21H             ;write block to file
       pop     ds              ;get ds back
       assume  ds:cseg
       jae     parent          ;ok, continue

       mov     dx,offset nowrit ;write error
       mov     ah,9
       int     21H
       jmp     error

;store the parent's psp
parent:
       mov     cx,2            ;2 bytes to store
       mov     dx,offset parpsp  ;point to parent's psp
       mov     ah,40H
       int     21H             ;write block to file
       jae     ems             ;ok, continue

       mov     dx,offset nowrit ;write error
       mov     ah,9
       int     21H
       jmp     error

;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
       mov     ah,40H
       int     21H             ;write out the table
       jae     closfl          ;ok,continue

       mov     dx,offset nowrit ;error while writing
       mov     ah,9
       int     21H
       jmp     short error

;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
       mov     ah,9
       int     21H
       jmp     short error

;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

;deallocate environment block of this mark
deall: mov     ax,envseg       ;environment segment
       mov     es,ax           ;  into es
       mov     ah,49H
       int     21H             ;deallocate, no reason for an error to occur

;print message and TSR
gores: mov     dx,offset didit
       mov     ah,9
       int     21H             ;write success message including filename
       mov     dx,offset crlf  ;newline
       mov     ah,9
       int     21H

       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 and stay resident

;error output - show syntax line
error: mov     dx,offset syntax
       mov     ah,9
       int     21H

;exit with error
       mov     ax,4C01H
       int     21H

fmark  endp

emsnm  db      'EMMXXXX0',0    ;file name for testing EMS presence
id     db      'FM2.9 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
syntax db      13,10,'Syntax:  FMARK [d:][path]filename'
crlf   db      13,10,36
didit  db      'FMARK 2.9 - Marked current memory position in '

;data storage area
filnm  db      44H dup (36)    ;mark file name
emscnt dw      0               ;holds number of active pages in map that follows
emsmap db      0               ;holds EMS page map if installed
                               ;(note may extend 1K bytes past end of file in memory)

Cseg    ends
        end     ComEntry
