home *** CD-ROM | disk | FTP | other *** search
/ TopWare Tools / TOOLS.iso / tools / top1190 / showtsrs.asm < prev    next >
Encoding:
Assembly Source File  |  1989-05-31  |  62.0 KB  |  1,257 lines

  1.         Title   SHOWTSRS - Program to scroll MAPMEM data
  2. Comment ~                           31-May-1989 00:03:10
  3.         Author:     Tom Gilbert's Heart&Mind
  4.                     7127 Lafayette Avenue
  5.                     Kansas City, KS 66109
  6.                     (913) 299-2701
  7.  
  8.         Copyright   (c) 1988/9 by Heart & Mind
  9.                     for NON-Commercial Use ONLY
  10.                     Use and distribution in the
  11.                     Public Domain is encouraged
  12.         ~
  13.         DOSSEG
  14.         .MODEL  small
  15.         .STACK  100h
  16.         .DATA
  17. headline    DB  " >ShowTSRs [anything for HELP]  -  Version 3.1  - "
  18.             DB  " by Tom Gilbert's Heart&Mind",13,10," ",13,10
  19.  
  20.             DB  " PSP  MCB  files bytes   owner     command line   "
  21.             DB  " chained/hooked INT vectors",13,10
  22.             DB  " ---- ---- ----- ----- --------- ---------------- "
  23.             DB  " --------------------------",13,10
  24. helpdat label   byte
  25. DB 13,10,"        "
  26. DB "ShowTSRs displays a map of memory blocks and interrupts used"
  27. DB 13,10,"        "
  28. DB "     by TurboPower DISABLE and RELEASE or UnMark and ReMark."
  29. DB 13,10,13,10,"        "
  30. DB 'The "PSP" is the Segment of a program, environment or "trapped"'
  31. DB 13,10,"                       memory block."
  32. DB 13,10,13,10,"        "
  33. DB 'The "MCB" (Memory Control Block) is located one paragraph before'
  34. DB 13,10,"                   the block it controls."
  35. DB 13,10,13,10,"        "
  36. DB 'The "files" include the 5 standard DOS devices.'
  37. DB 13,10,13,10,"        "
  38. DB 'The "bytes" are block lengths in decimal.'
  39. DB 13,10,13,10,"        "
  40. DB 'The "owner" names other than "DOS", "TSR WATCHER", "LoadTSR" and'
  41. DB 13,10,"        "
  42. DB 'those for [F]Marks come from the environment.  The name "command"'
  43. DB 13,10,"        "
  44. DB 'appears when NO "owner" is found in the environment.'
  45. DB 13,10,13,10,"        "
  46. DB 'The "command line" is reproduced for the first 16 bytes.'
  47. DB 13,10,"        "
  48. DB "Those followed by an elipsis (...) exceed 16 bytes."
  49. DB 13,10,13,10,"        "
  50. DB 'The "vectors" which are "chained" from program to program will be'
  51. DB 13,10,"        "
  52. DB "displayed if WATCH is installed.  Otherwise, only those at the top"
  53. DB 13,10,'        of the chain ("hooked") are displayed.'
  54. DB 13,10,13,10,"        "
  55. DB "EGA Info 8 bytes and Inter-application Communication"
  56. DB 13,10,"        "
  57. DB "Area 16 bytes are provided in HEX & ASCII dump format."
  58. DB 13,10,13,10,"        "
  59. DB "If expanded memory is installed, the Manager's Version number,"
  60. DB 13,10,"        "
  61. DB "Page Frame Segment (through which memory is windowed) and block"
  62. DB 13,10,"        "
  63. DB "information will be shown.  User names are shown if provided."
  64. DB 13,10,13,10,"  "
  65. DB "                     ***** End of ShowTSRs Help *****",13,10
  66. helplen equ $-helpdat
  67. statline    DB  " Line:    of   "
  68.             DB  " Move:   PGUP PGDN HOME END or Use ESC key to"
  69.             DB  " Exit: ShowTSRs "
  70. cmdparam    DB  " ",13
  71. datf        DB      0           ; Command flag 0 = Data else HELP
  72. spsp        DW      ?           ; Segment of ProgramSegmentPrefix
  73. fmem        DW      ?           ; Free System Conventional RAM
  74. pbuffer     DW      0           ; Position in buffer (offset)
  75. sbuffer     DW      ?           ; Base of buffer (segment)
  76. lbuffer     DW      ?           ; Length of buffer
  77. linenum     DW      ?           ; Data buffer line
  78. lastnum     DW      ?           ; Last buffer line
  79. columns    EQU      80          ; Number of columns used per row
  80. rows        DW      24          ; Number of last row for display
  81. datrows     DW      20          ; Number of data rows per page
  82. lastrow     DW      24          ; Number of last display row
  83. cell    LABEL   WORD            ; Cell (character and attribute)
  84. char        DB  " "             ; Initialize to space
  85. attr        DB      ?           ; Attribute
  86. mode        DB      ?           ; Initial mode
  87. pag         DB      ?           ; Initial display page
  88. newvid      DB      0           ; Video change flag
  89. cga         DB      1           ; CGA flag - default yes
  90. vidadr      DW    0B800h        ; Video buffer address - default CGA
  91. mono       EQU    0B000h        ; Monochrome address
  92. statatr     DB      030h        ; Color default - black on cyan
  93. bwstat     EQU      070h        ; B&W default - black on white
  94. scrnatr     DB      017h        ; Color default - white on blue
  95. bwscrn     EQU      007h        ; B&W default - white on black
  96.  
  97. exkeys      DB 71,72,73,79,80,81; Extended key codes
  98. lexkeys    EQU     $-exkeys     ; Table of keys
  99. extable     DW  homek,upk,pgupk,endk,downk,pgdnk,nonek
  100.  
  101. EgaHdg  DB " EGA Information Area at 0040:00A8 "
  102. EgaLen EQU $-EgaHdg
  103. IcaHdg  DB " Inter-application Communications Area:",13,10," 0040:00F0 "
  104. IcaLen EQU $-IcaHdg
  105. EmsName DB "EMMXXXX0"           ; EMM standard Name
  106. tpages  DW 0                    ; Page accumulator
  107. emserm  DB 13,10
  108.         DB "   *** Expanded Memory NOT Installed or NOT Working ***"
  109. emerml  EQU $-emserm
  110. emmshdg DB " block    pages   KBytes   UserName  "
  111.         DB "  (Expanded Memory - Version "
  112. emmlen1 EQU $-emmshdg
  113.         DB ")",13,10
  114. dashes  DB " -----    -----   ------   --------   "
  115.         DB " (LIM page frame address - "
  116. emmlen2 EQU $-emmshdg-emmlen1
  117. totlm   DB " total"
  118. freem   DB "  free"
  119. fmark   DB "FMark TSR"          ; [F]Mark ID - Now using " TSR"
  120.  
  121. doscm   DB "DOS<command.com><CONFIG.SYS> <environment><trapped>"
  122. disam   DB "***  D I S A B L E D  ***"
  123. disalen EQU $-disam
  124. LoadTSR DB "Load"               ; LoadTSR Command Identification
  125. WatchS  DB "TSR WATCHER"        ; WATCH Command Line Parameter
  126. WatchF  DW  0                   ; MCB Index to WATCH PSP if Set
  127. startl  DW  0                   ; Destination Index at Line Start
  128. vpos    DW  ?                   ; WATCH Next PSP Position
  129. MCB     STRUC
  130. pspa    DW  0                   ; Program Segment Prefix or Mark Address
  131. mcba    DW  0                   ; Memory Allocation Block Address
  132. mcbl    DW  0                   ; Length in paragraphs to next MCB
  133. mcbf    DW  0                   ; Flags 0=Trapped, FF=Env, FF00=PGM
  134. MCB     ENDS                    ;   and Special Blocks are FFFF
  135. MCBS    MCB   100 DUP (<>)      ; Array of MCB Structures
  136.             .CODE
  137. Main        PROC
  138.             mov     ax,@data            ; Destination is data
  139.             mov     es,ax               ; flag with length of
  140.             mov     di,OFFSET datf      ; command line
  141.             mov     si,80h              ; parameter
  142.             movsb
  143.             mov     es:spsp,ds          ; Preserve PSP Segment and
  144.             mov     bx,ds:[2]           ; Use Total System RAM to
  145.             sub     bx,es:spsp          ; Calculate Free Memory
  146.             mov     ds,ax               ; Set DS Register to DATA
  147.             mov     fmem,bx             ; Store Free Memory
  148.  
  149.             cli                         ; Turn off interrupts
  150.             mov     ss,ax               ; Make SS and
  151.             mov     sp,OFFSET STACK     ;   SP relative to DGROUP
  152.             sti                         ; Re-Enable interrupts
  153.  
  154.             mov     bx,sp               ; Convert stack pointer to
  155.             mov     cl,4                ; number of stack paragraphs
  156.             shr     bx,cl
  157.             add     ax,bx               ; Add SS to get end of program
  158.             sub     ax,spsp             ; Subtract start to get length
  159.             mov     es,spsp             ; Modify Memory
  160.             mov     bx,ax               ; New Block Size
  161.             mov     ah,4Ah              ; through DGROUP
  162.             int     21h
  163.             mov     bx,0FFFFh
  164. GetMore:    mov     ah,48h              ; Request all
  165.             int     21h                 ; remaining
  166.             jc      GetMore             ; memory
  167.             mov     es,ax               ; Set Es Register to Block
  168.             mov     sbuffer,ax          ; Save buffer segment and
  169.             mov     lbuffer,bx          ; actual length allocated
  170.             xor     di,di               ; Point to beginning and
  171.             mov     cx,lbuffer          ; fill data buffer
  172.             mov     al," "              ; With Spaces
  173.             rep     stosb
  174.             xor     di,di
  175.             test    datf,0FFh           ; If command parameter
  176.             jnz     HelpOpt             ; then provide HELP
  177.             xor     dx,dx               ; else zero index
  178.             call    GetData             ; Get and Show
  179.             jmp     SHORT EndData       ; scrollable data
  180.  
  181. HelpOpt:    mov     cmdparam,"?"        ; Show HELP requested
  182.             mov     si,OFFSET helpdat   ; and store help data
  183.             mov     cx,helplen          ; for scrollable display
  184.             rep     movsb
  185. EndData:    call    EndCount            ; Count buffer
  186.             mov     ax,linenum          ; data lines and
  187.             mov     lastnum,ax          ; store the count
  188.             mov     lbuffer,di          ; and store length
  189.             call    Video               ; Adjust for mode & adapter
  190.             mov     dx,2B00h            ; Hide cursor off screen
  191.             xor     bh,bh
  192.             mov     ah,2
  193.             int     10h
  194.             call    homek               ; Display 1st Page
  195.             mov     ax,datrows          ; If more data
  196.             sub     ax,lastnum          ; lines to show
  197.             jc      nextkey             ; then accept keys
  198.             sub     datrows,ax          ; else modify last
  199.             sub     lastrow,ax          ; row for ending
  200. nextkey:    mov     ah,7                ; Get a key
  201.             int     21h
  202.             cmp     al,0                ; If a null
  203.             je      extended            ; then Must be extended code
  204.             cmp     al,27               ; else If NOT ESCape
  205.             jne     nextkey             ; then Ignore unknown command
  206.  
  207. quit:       mov     es,sbuffer          ; Release buffer
  208.             mov     ah,49h
  209.             int     21h
  210.             cmp     newvid,1            ; If video not changed
  211.             jne     thatsall            ; then that's all
  212.             mov     al,mode             ; else Restore video mode,
  213.             xor     ah,ah
  214.             int     10h
  215.             mov     al,pag              ; page,
  216.             mov     ah,5
  217.             int     10h                 ; and cursor
  218. thatsall:   mov     cx,lastrow          ; Load last row and
  219.             mov     ax,rows             ; Calculate rows to
  220.             sub     ax,cx               ; be scrolled blank
  221.             xchg    cl,ch               ; Set Upper Left and
  222.             mov     dx,cx               ; copy in order to
  223.             add     dh,al               ; adjust Lower Right
  224.             mov     dl,columns-1        ; corner of window
  225.             mov     ah,6                ; Call ROM BIOS to
  226.             mov     bh,7                ; clear the window
  227.             int     10h
  228.             mov     dx,cx               ; Set cursor above
  229.             dec     dh                  ; window so prompt
  230.             xor     bh,bh               ; is on last line
  231.             mov     ah,2                ; when Exit to DOS
  232.             int     10h
  233.             mov     ax,4C00h            ; Zero Error Level
  234.             int     21h                 ; For => DOS 2.00
  235.                                         ; RED SWITCH for 1
  236.  
  237. extended:   mov     ah,7                ; Get extended code
  238.             int     21h
  239.             push    es
  240.             push    ds                  ; Load DS into ES
  241.             pop     es
  242.             mov     di,OFFSET exkeys    ; Load address and
  243.             mov     cx,lexkeys+1        ; length of key list
  244.             repne   scasb               ; Find position
  245.             pop     es
  246.             sub     di,(OFFSET exkeys)+1; Point to key and adjust
  247.             shl     di,1                ; pointer for word addresses
  248.             call    extable[di]         ; Call appropriate procedure
  249.             jmp     nextkey
  250. homek:      mov     pbuffer,0           ; HOME - Zero the buffer
  251.             mov     ax,pbuffer          ; position for 1st page
  252.             jmp     SHORT GoPage
  253. upk:        mov     ax,-1               ; UP - GoBack one line if room
  254.             jmp     SHORT GoPage
  255. pgupk:      mov     ax,datrows          ; PGUP - Page back
  256.             neg     ax                  ; Up to page lines
  257.             jmp     SHORT GoPage
  258. endk:       mov     ax,lbuffer          ; END - Get last byte of file
  259.             mov     pbuffer,ax          ; Make it the file position
  260.             mov     ax,datrows          ; Go Backward enough
  261.             neg     ax                  ; lines for last page
  262.             jmp     SHORT GoPage
  263. downk:      mov     ax,1                ; GoForward 1 line if room
  264.             jmp     SHORT GoPage
  265. pgdnk:      mov     ax,datrows          ; PGDN - Go forward <= page
  266. GoPage:     push    ax
  267.             call    Pager
  268. nonek:      retn                        ; Ignore unknown key
  269. Main        ENDP
  270.  
  271. Video       PROC
  272.             push    es                  ; Preserve Extra Segment
  273.             mov     ah,12h              ; Call EGA status function
  274.             mov     bl,10h
  275.             sub     cx,cx               ; With Clear status bits
  276.             int     10h
  277.             sub     ax,ax               ; If status is still Clear
  278.             jcxz    modechk
  279.             mov     es,ax               ; or if EGA is NOT active
  280.             test    BYTE PTR es:[487h],1000b
  281.             jnz     modechk             ; then check CGA or Mono Mode
  282.             mov     ax,1130h            ; else get EGA information
  283.             int     10h
  284.             mov     al,dl               ; Make lines per screen
  285.             cbw                         ; into a Word Value
  286.             mov     rows,ax             ; Reset number of the
  287.             mov     lastrow,ax          ; last row and number
  288.             sub     ax,4                ; of rows available for
  289.             mov     datrows,ax          ; data from their defaults
  290.             dec     cga                 ; Clear the CGA Flag
  291. modechk:    pop     es                  ; Restore Extra Segment
  292.             mov     ah,0Fh              ; Get video mode
  293.             int     10h
  294.             mov     mode,al             ; Save initial
  295.             mov     pag,bh              ; mode and page
  296.             mov     dl,al               ; Work on copy
  297.             cmp     dl,7                ; If mono 7
  298.             je      loadmono            ; then Set mono
  299.             cmp     dl,15               ; else if NOT mono 15
  300.             jne     graphchk            ; then Check graphics
  301. loadmono:   mov     vidadr,mono         ; else Load mono address
  302.             mov     statatr,bwstat      ; Set B&W defaults for status
  303.             mov     scrnatr,bwscrn      ; line and screen background
  304.             dec     cga                 ; Set as NOT CGA
  305.             cmp     al,15               ; If NOT mono 15
  306.             jne     VidExit             ; then Done
  307.             mov     dl,7                ; else Set standard mono
  308.             jmp     SHORT chmode
  309. graphchk:   cmp     dl,7                ; If 7 or higher
  310.             jg      color               ; then color or done
  311.             cmp     dl,4                ; else 5 and 6 are
  312.             jg      bnw                 ; usually black and white
  313.             je      color               ; 4 is color
  314.             test    dl,1                ; AND
  315.             jz      bnw                 ; 0 and 2 are black and white
  316. color:      cmp     dl,3                ; If mode 3
  317.             je      VidExit             ; then Done
  318.             mov     dl,3                ; else use color text mode
  319.             jmp     SHORT chmode
  320. bnw:        mov     statatr,bwstat      ; Set B&W defaults for status
  321.             mov     scrnatr,bwscrn      ; line and screen background
  322.             cmp     dl,2                ; If mode 2
  323.             je      VidExit             ; then Done
  324.             mov     dl,2                ; else use B&W text mode
  325. chmode:     mov     al,dl               ; Set video mode
  326.             xor     ah,ah
  327.             int     10h
  328.             mov     ax,0500h            ; Set video page 0
  329.             int     10h
  330.             mov     newvid,1            ; Set flag
  331. VidExit:    ret
  332. Video       ENDP
  333.  
  334. ; Procedure EndCount - Go backward to count lines in file
  335. ; Input     ES:DI has buffer position
  336. ; Output    Modifies "linenum"
  337.  
  338. EndCount    PROC
  339.             push    di
  340.             std                         ; Go backwards to
  341.             mov     al,13               ; Search for CR
  342.             mov     linenum,0           ; Initialize line count
  343. findstrt:   mov     cx,0FFh             ; Load maximum character count
  344.             cmp     cx,di               ; If NOT Near start of buffer
  345.             jl      notnear2            ; then use maximum count
  346.             mov     cx,di               ; else search
  347.             jcxz    found               ; only to start
  348.  
  349. notnear2:   repne   scasb               ; If previous CR NOT found
  350.             jcxz    found               ; then must be at start
  351.             inc     linenum             ; else adjust line count
  352.             jmp     SHORT findstrt      ;  and continue search
  353.  
  354. found:      pop     di                  ; Restore index
  355.             cld                         ; and direction
  356.             ret
  357. EndCount    ENDP
  358.  
  359. ; Procedure Pager - Displays status and text lines
  360. ; Input     Stack variable: lines to scroll (negative up, positive down)
  361. ; Output    Displays status plus "datrows" number of data lines
  362.  
  363. Pager       PROC
  364.             push    bp
  365.             mov     bp,sp
  366.             mov     di,pbuffer          ; Index to buffer position
  367.             mov     cx,[bp+4]           ; Get count argument for
  368.             mov     ax,10               ; linefeeds to count and
  369.             or      cx,cx               ; If No lines to count
  370.             jz      show                ; then show the page
  371.             jg      forward             ; else Count Forward
  372.             call    GoBack              ; or Backward if neg
  373.             jmp     SHORT show          ; before showing page
  374.  
  375. forward:    call    GoForwd
  376. show:       call    EndCount            ; Count to first
  377.             mov     ax,linenum          ; line number to show
  378.             add     ax,datrows          ; Adjust to bottom line
  379.             cmp     ax,lastnum          ; If NOT past last
  380.             jle     lineok              ; then number is ok
  381.             mov     ax,lastnum          ; else make it last
  382.  
  383. lineok:     push    ds                  ; Set Status Line DATA as
  384.             pop     es                  ; Destination for Values
  385.             mov     di,OFFSET statline[9]
  386.             xor     dx,dx               ; Make 32-bit
  387.             call    BinToDStr           ; Line Number
  388.             mov     ax,lastnum          ;  and Last
  389.             add     di,6                ; Line Number
  390.             call    BinToDStr           ; Restore
  391.             mov     es,sbuffer          ; ES to sbuffer
  392.  
  393.             mov     bl,statatr          ; Set attribute for
  394.             mov     BYTE PTR cell[1],bl ; status & headings
  395.             xor     bx,bx               ; Initialize counter
  396.             mov     si,OFFSET headline  ; for heading lines
  397. hdloop:     push    bx                  ; Preserve counter
  398.             push    ds                  ; Arg 1 - Segment
  399.             push    si                  ; Arg 2 - Offset
  400.             push    bx                  ; Arg 3 - Display Line
  401.             push    cell                ; Arg 4 - Char/Attrib
  402.             call    CellWrt             ; Write one line
  403.             push    ss                  ; Restore DGroup
  404.             pop     ds                  ; into DS register
  405.             pop     bx                  ; Restore line count and
  406.             mov     si,ax               ; get returned position
  407.             inc     bx                  ; Count the heading line
  408.             cmp     bx,4                ; If NOT yet 4 lines
  409.             jc      hdloop              ; then loop until 4
  410.             mov     al,scrnatr          ; Change attribute for
  411.             mov     BYTE PTR cell[1],al ; data buffer display
  412.             mov     si,pbuffer          ; Index to pbuffer
  413. datloop:    push    bx                  ; Preserve counter
  414.             push    sbuffer             ; Arg 1 - Segment
  415.             push    si                  ; Arg 2 - Offset
  416.             push    bx                  ; Arg 3 - Display Line
  417.             push    cell                ; Arg 4 - Char/Attrib
  418.             call    CellWrt             ; Write line
  419.             push    ss                  ; Restore DGroup
  420.             pop     ds                  ; into DS register
  421.             pop     bx                  ; Restore counter and
  422.             inc     bx                  ; Count row displayed
  423.             cmp     ax,lbuffer          ; If position => end
  424.             jnc     pagedone            ; then page is done
  425.             mov     si,ax               ; else update pointer
  426.             cmp     bx,rows             ; If short of last row
  427.             jc      datloop             ; then loop Until done
  428.  
  429. pagedone:   mov     al,statatr          ; Load attribute for
  430.             mov     BYTE PTR cell[1],al ; writing status line
  431.             mov     si,OFFSET statline
  432.             push    ds                  ; Arg 1 - Segment
  433.             push    si                  ; Arg 2 - Offset
  434.             push    bx                  ; Arg 3 - Display Line
  435.             push    cell                ; Arg 4 - Char/Attrib
  436.             call    CellWrt             ; Write status line
  437.             mov     es,sbuffer          ; Restore ES to buffer
  438.             pop     bp                  ; Discard stack
  439.             ret     2                   ; count argument
  440. Pager       ENDP
  441.  
  442. ; Procedure Retrace
  443. ; Purpose   Writes cell during horizontal retrace (CGA)
  444. ; Input     ES:DI has screen buffer position, AX has cell
  445. ; Output    Character to screen buffer
  446.  
  447. Retrace     PROC
  448.             push    bx
  449.             mov     bx,ax               ; Save character
  450.  
  451. lscan2:     in      al,dx               ; Look in the port
  452.             shr     al,1                ;   until it goes low
  453.             jc      lscan2
  454.             cli
  455. hscan2:     in      al,dx               ; Look in the port
  456.             shr     al,1                ;   until it goes high
  457.             jnc     hscan2
  458.             mov     ax,bx               ; Restore and write it
  459.             stosw
  460.             sti
  461.             pop     bx
  462.             ret
  463. Retrace     ENDP
  464.  
  465. ; Procedure CellWrt - Writes a line to screen buffer
  466. ; Input     Stack variables (segment,offset,line,cell)
  467. ; Output    Line to screen buffer
  468.  
  469. CellWrt     PROC
  470.             push    bp
  471.             mov     bp,sp
  472.             sub     dx,dx               ; Clear as flag for scan
  473.             cmp     cga,1               ; If NOT CGA
  474.             jne     noscan              ; then leave zero
  475.             mov     dx,03DAh            ; else load port #
  476. noscan:     mov     es,vidadr           ; Load screen buffer segment
  477.             mov     ds,[bp+10]          ; Buffer segment
  478.             mov     si,[bp+8]           ; Buffer position
  479.             mov     cx,80               ; Cells per row
  480.             mov     ax,[bp+6]           ; Starting row
  481.             mov     bx,80*2             ; Bytes per row
  482.             mul     bl                  ; Figure columns per row
  483.             mov     di,ax               ; Load as destination
  484.             mov     ax,[bp+4]           ; Set Attribute
  485. movechar:   lodsb                       ; Get character
  486.             cmp     al,13               ; If End of Data Line
  487.             je      fillspc             ; then end display line
  488.             or      dx,dx               ; else if NOT CGA
  489.             je      notCGA              ; then Write without delay
  490.             call    Retrace             ; else Write during retrace
  491.             loop    movechar            ; until End of Data Line
  492.             jmp     SHORT nextline      ; or end of display line
  493.  
  494. notCGA:     stosw
  495.             loop    movechar            ; If end of display line
  496.             jmp     SHORT nextline      ; then find End of Data Line
  497.  
  498. fillspc:    mov     al," "              ; Fill with space
  499.             or      dx,dx               ; If NOT CGA
  500.             je      space2              ; then direct
  501. space1:     call    Retrace             ; else Write during retrace
  502.             loop    space1              ; until end of display line
  503.             inc     si                  ; Adjust for Data line LF
  504.             jmp     SHORT exit          ; Done
  505.  
  506. space2:     rep     stosw               ; Write
  507.             inc     si                  ; Adjust for LF
  508.             jmp     SHORT exit          ; Done
  509. nextline:   mov     ah,10               ; Search for Data line feed
  510.  
  511. chklf:      lodsb                       ; Load and compare
  512.             cmp     al,ah               ; If NOT Data Line LF
  513.             loopne  chklf               ; then contine until
  514. exit:       mov     ax,si               ; Return position
  515.             pop     bp
  516.             ret     8
  517. CellWrt     ENDP
  518.  
  519. GoForwd     PROC    ; Search Forward through buffer
  520. ; Input     CX has number of lines; ES:DI has buffer position
  521. ; Output    Updates "pbuffer" and DI index
  522.  
  523.             cld                         ; Go forward
  524. findf:      mov     pbuffer,cx          ; Preserve count
  525.             mov     cx,0FFh             ; Load maximum character count
  526.             repne   scasb               ; If next LF NOT found
  527.             jcxz    atend               ; then must be at end
  528.             mov     cx,pbuffer          ; else If past end
  529.             cmp     di,lbuffer          ; then make at end
  530.             jae     atend               ; else loop until
  531.             loop    findf               ; at end or found
  532.             mov     pbuffer,di
  533.             call    EndCount            ; Get line number
  534.             mov     cx,lastnum          ; If last number
  535.             sub     cx,datrows          ; minus display
  536.             cmp     cx,linenum          ; is => linenum
  537.             jnc     GoForX              ; then pbuffer Ok
  538.  
  539. atend:      mov     di,lbuffer          ; Set index to end
  540.             mov     cx,datrows          ; Set page lines to
  541.             neg     cx                  ; back-up during
  542.             mov     al,10               ; GoBack procedure
  543.             call    GoBack
  544. GoForX:     ret                         ; Return pbuffer
  545. GoForwd     ENDP
  546.  
  547. GoBack      PROC    ; Search Backward through buffer
  548.             std                         ; Go backward
  549.             neg     cx                  ; Make count positive
  550.             inc     cx                  ; Use one extra going up
  551. findb:      push    cx                  ; Preserve counter
  552.             mov     cx,0FFh             ; Load maximum character count
  553.             cmp     cx,di               ; If NOT near start of buffer
  554.             jc      scanb               ; then use maximum count
  555.             mov     cx,di               ; else search only to start
  556.  
  557. scanb:      repne   scasb               ; If previous LF NOT found
  558.             jcxz    atstart             ; then must be at start
  559.             pop     cx                  ; else loop until start/done
  560.             loop    findb
  561.             add     di,2                ; Adjust for cr/lf
  562.             jmp     SHORT GoBackX       ; Return position
  563. atstart:    pop     cx
  564.             sub     di,di               ; Set index and
  565. GoBackX:    mov     pbuffer,di          ; pointer and
  566.             ret                         ; Return position
  567. GoBack      ENDP
  568.  
  569. BinToDStr   PROC
  570.             Comment ~   Right Justified Decimal ASCII String
  571.                         Call With:  DX:AX = 32-bit value
  572.                                     DS:DI after destination
  573.                         Returns:    Registers UnChanged
  574.                     ~
  575.             push    ax                  ; Preserve
  576.             push    bx                  ; All the
  577.             push    cx                  ; Registers
  578.             push    dx                  ; Used by
  579.             push    di                  ; procedure
  580.             mov     cx,10               ; Set Divisor
  581. DivLoop:    call    Divide              ; Divide and
  582.             add     bl,"0"              ; Store ASCII
  583.             dec     di                  ; Decimal Digit
  584.             mov     es:[di],bl          ; Right to Left
  585.             mov     bx,ax               ; If 32-bits
  586.             or      bx,dx               ; NOT yet 0
  587.             jnz     DivLoop             ; Then Continue
  588.             pop     di                  ; Else Restore
  589.             pop     dx                  ; Registers to
  590.             pop     cx                  ; Values on
  591.             pop     bx                  ; Entry to
  592.             pop     ax                  ; BinToDStr
  593.             ret
  594. BinToDStr   ENDP
  595.  
  596. Divide      PROC
  597.             push    ax                  ; Preserve LSW
  598.             mov     ax,dx               ; Divide MSW as
  599.             xor     dx,dx               ; 32-bit Value
  600.             div     cx                  ; Quotient
  601.             mov     bx,ax               ; in DX:BX
  602.             pop     ax                  ; Divide LSW and
  603.             div     cx                  ; Return DX:AX
  604.             xchg    bx,dx               ; Quotient and
  605.             ret                         ; BX Remainder
  606. Divide      ENDP
  607.  
  608. Val2ASCh    PROC
  609.             mov     ah,al               ; Preserve byte value
  610.             and     al,0F0h             ; Isolate high
  611.             shr     al,1                ; nibble
  612.             shr     al,1                ; into
  613.             shr     al,1                ; low
  614.             shr     al,1                ; nibble
  615.             call    Val2Dig             ; Convert and Store
  616.             mov     al,ah               ; Restore byte value
  617.             and     al,0Fh              ; Isolate low nibble
  618. Val2Dig:    add     al,30h              ; Convert to display
  619.             cmp     al,3Ah              ; If decimal digit
  620.             jc      V2DI                ; then ASCII numeral
  621.             add     al,7                ; else make HEX alpha
  622. V2DI:       stosb                       ; Store ASCII HEX
  623.             ret
  624. Val2ASCh    ENDP
  625.  
  626. ShoWord     PROC
  627.             push    ax                  ; Preserve LSB
  628.             mov     al,ah               ; Isolate MSB
  629.             call    Val2ASCh            ; Store Digits 1 & 2
  630.             pop     ax                  ; Restore LSB and
  631.             push    ax                  ; save the Word
  632.             call    Val2ASCh            ; Store Digits 3 & 4
  633.             inc     di                  ; plus a space
  634.             pop     ax                  ; Return Word
  635.             ret
  636. ShoWord     ENDP
  637.  
  638. SortMCBs    PROC
  639.             mov     cx,bp               ; Restore Count of
  640.             dec     cx                  ; Blocks Minus 1
  641.             xor     bx,bx               ; Zero Index and
  642.             xor     dx,dx               ; Flag NO Swaps
  643. SortLoop:   add     bx,8                ; Advance MCB Index
  644.             mov     ax,MCBS[bx].mcbf    ; Store
  645.             mov     MCBS.mcbf,ax        ; Flags
  646.             mov     ax,MCBS[bx].mcbl    ; length
  647.             mov     MCBS.mcbl,ax        ; MCB
  648.             mov     ax,MCBS[bx].mcba    ; and
  649.             mov     MCBS.mcba,ax        ; PSP
  650.             mov     ax,MCBS[bx].pspa    ; Addresses in
  651.             mov     MCBS.pspa,ax        ; base array member
  652.             cmp     ax,MCBS[bx+8].pspa  ; If PSPs Ascending
  653.             jle     LoopSort            ; then loop until done
  654.             dec     dx                  ; else set sort flag
  655.             mov     ax,MCBS[bx+8].pspa  ;  and
  656.             mov     MCBS[bx].pspa,ax    ; swap
  657.             mov     ax,MCBS[bx+8].mcba  ; the
  658.             mov     MCBS[bx].mcba,ax    ; data
  659.             mov     ax,MCBS[bx+8].mcbl  ; for
  660.             mov     MCBS[bx].mcbl,ax    ; the
  661.             mov     ax,MCBS[bx+8].mcbf  ; two
  662.             mov     MCBS[bx].mcbf,ax    ; data
  663.             mov     ax,MCBS.mcbf        ; word
  664.             mov     MCBS[bx+8].mcbf,ax  ; table
  665.             mov     ax,MCBS.mcbl        ; array
  666.             mov     MCBS[bx+8].mcbl,ax  ; block
  667.             mov     ax,MCBS.mcba        ; members
  668.             mov     MCBS[bx+8].mcba,ax  ; until
  669.             mov     ax,MCBS.pspa        ; all
  670.             mov     MCBS[bx+8].pspa,ax  ; compared
  671. LoopSort:   loop    SortLoop
  672.             or      dx,dx               ; If Swaps
  673.             jnz     SortMCBs            ; Then Sort Again
  674.             ret                         ; Until NO Swaps
  675. SortMCBs    ENDP
  676.  
  677. Chk4TSR     PROC
  678.             push    ax                  ; Preserve
  679.             push    cx                  ; Registers
  680.             push    di                  ; Index and
  681.             push    es                  ; Extra Segment
  682.             mov     di,es               ; Advance to
  683.             inc     di                  ; Controlled Block
  684.             mov     es,di               ; Segment and Area
  685.             mov     di,60h              ; for TSR Signature
  686.             mov     si,OFFSET WatchS    ; "TSR WATCHER"
  687.             lodsb                       ; If NO "T"
  688.             mov     cx,11               ; in 11 bytes
  689.             repne   scasb               ; Then Check
  690.             jne     C4Watch             ;  for Watch
  691.             cmpsw                       ; Else If next 2
  692.             je      C4Texit             ; Then Exit Equal
  693. C4Watch:    mov     si,OFFSET WatchS    ; "TSR WATCHER"
  694.             mov     di,81h              ; COMMAND LINE
  695.             mov     cx,11               ; PARAMETER
  696.             rep     cmpsb               ; RETURNS E or NE
  697. C4Texit:    pop     es                  ; Restore Segment
  698.             pop     di                  ; Index and
  699.             pop     cx                  ; General
  700.             pop     ax                  ; Registers
  701.             ret
  702. Chk4TSR     ENDP
  703.  
  704. IsEnviron   PROC
  705.             mov     cx,MCBS[bx].mcba    ; Convert Environment
  706.             inc     cx                  ; MCBA to Environment
  707.             mov     es,cx               ; Segment and
  708.             mov     ax,MCBS[bx].mcbl    ; Convert Length in
  709.             mov     cl,4                ; Paragraphs to
  710.             shl     ax,cl               ; Length in
  711.             mov     cx,ax               ; Bytes
  712.             xor     di,di               ; Scan for
  713.             xor     ax,ax               ; Double Null
  714. SearchL:    repne   scasb               ; If First NOT
  715.             dec     cx                  ; Followed by 2nd
  716.             scasb                       ; Then Search
  717.             jcxz    NoFname             ; Until Environment End
  718.             jne     SearchL             ; OR Until Double Null
  719.             mov     al,"."              ; Scan for ".EXT"
  720.             repne   scasb               ; If NO Extent DOT
  721.             jcxz    NoFname             ; Then NO File Name
  722.             mov     cx,10               ; Else Look-Back for
  723.             mov     ax,":\"             ; Path Delimiter
  724. FnameLp:    dec     di                  ; Until
  725.             cmp     es:[di-1],al        ; Either
  726.             je      NameEnd             ; Find OR
  727.             cmp     es:[di-1],ah        ; Fail to
  728.             je      NameEnd             ; Find Start of
  729.             loop    FnameLp             ; File Name
  730.  
  731. NoFname:    push    ds                  ; Put Data Segment into
  732.             pop     es                  ; Extra Segment Register
  733.             mov     di,OFFSET doscm+4   ; Point into
  734.             mov     cx,3                ; "DOS<command..."
  735.  
  736. NameEnd:    mov     si,di               ; Set Source to Name
  737.             push    ds                  ; Preserve Data Segment
  738.             push    es                  ; Transfer ES after
  739.             mov     es,sbuffer          ; Restoring Buffer Segment
  740.             pop     ds                  ; into DS Register and
  741.             mov     di,bp               ; Restore MapData Pointer
  742.             mov     dx,10               ; Calculate
  743.             sub     dx,cx               ; filename
  744.             xchg    dx,cx               ; length and
  745.             rep     movsb               ; store Owner and
  746.             add     di,dx               ; space to command line
  747.             pop     ds                  ; Restore Data Segment
  748.             mov     si,OFFSET doscm+29  ; Point to "<environment>"
  749.             mov     cx,13               ; Store its length
  750.             rep     movsb               ; into command line and
  751.             add     di,6                ; advance to vectors
  752.             ret
  753. IsEnviron   ENDP
  754.  
  755. IsProgram   PROC
  756.             push    ax                  ; Preserve PSP and
  757.             push    bx                  ; MCBS Index Pointer
  758.             sub     bx,8                ; Backup to Environment MCB
  759.             call    IsEnviron           ; Get Owner Information
  760.             mov     cx,19               ; Backup to
  761.             sub     di,cx               ; Command and
  762.             mov     al," "              ; Space-It-Out
  763.             rep     stosb
  764.             sub     di,20               ; Restore Data
  765.             pop     bx                  ; Pointer, MCBS
  766.             pop     ax                  ; Index and PSP
  767.             ret
  768. IsProgram   ENDP
  769.  
  770. OwnComVec   PROC
  771.             push    cx                  ; Preserve StoLoop Counter
  772.             inc     di                  ; Advance to Owner
  773.             mov     bp,di               ; Preserve Pointer
  774.             mov     ax,MCBS[bx].mcbf    ; If Flags Show
  775.             or      ax,ax               ; is Trapped
  776.             jz      DOSblock            ; Then is DOS
  777.             mov     cx,MCBS[16].pspa    ; Else If DOS
  778.             cmp     cx,MCBS[bx].pspa    ; Is Below PSP
  779.             jc      Ck4Spec             ; Then check if Special
  780. DOSblock:   mov     si,OFFSET doscm     ; Else IS DOS
  781.             mov     cx,3                ; copy
  782.             rep     movsb               ; "DOS" and
  783.             add     di,7                ; space to command
  784.             or      ax,ax               ; If NOT Trapped
  785.             jnz     Which?              ; Then Check Which DOS
  786.             add     si,39               ; Else Advance to
  787.             mov     cx,9                ; "<trapped>"
  788.             jmp     SHORT MoveCmd
  789. Which?:     mov     cx,13               ; If Second MCB
  790.             cmp     bx,16               ; Then "<command.com>"
  791.             je      MoveCmd             ; Else If First MCB
  792.             mov     si,OFFSET doscm+16  ; Then "<CONFIG.SYS> "
  793.             jc      MoveCmd             ; Else Must Be
  794.             add     si,cx               ; "<environment>"
  795.  
  796. MoveCmd:    rep     movsb               ; Move Command and
  797.             jmp     OCVExit             ; End the Line
  798.  
  799. Ck4Spec:    cmp     ax,-1               ; If NOT Special
  800.             jne     CkEnvir             ; Then Check If Environment
  801.             mov     ax,MCBS[bx].pspa    ; Else Load PSP
  802.             mov     es,MCBS[bx].mcba    ; Point to MCB
  803.             call    Chk4TSR             ; If TSR WATCHER
  804.             cmp     si,OFFSET WatchS+11 ; NOT Matched
  805.             jne     Ck4Mark             ; Then NOT Watch
  806.             mov     es,sbuffer          ; Else Restore
  807.             mov     cx,11               ; Buffer and Copy
  808.             mov     si,OFFSET WatchS    ; "TSR WATCHER"
  809.             rep     movsb               ; as Owner Name
  810.             push    ds                  ; Set-Up for
  811.             mov     ax,17               ; Vectors
  812.             jmp     Go2Vecs
  813. CkEnvir:    cmp     ax,0FFh             ; If NOT Environment
  814.             jne     Program             ; Then Must be Program
  815.             call    IsEnviron           ; Else IS Environment
  816.             jmp     OCVExit
  817. Program:    mov     ax,MCBS[bx].pspa    ; Load the
  818.             call    IsProgram           ; Program PSP
  819.             push    ds                  ; Preserve Data Segment
  820.             mov     ds,ax               ; Set to PSP and
  821.             jmp     SHORT CmdParm       ; Get Command Line
  822.  
  823. Ck4Mark:    push    ds                  ; Preserve Data Segment
  824.             mov     es,ax               ; Point into PSP at
  825.             mov     di,65h              ; [F]Mark signature
  826.             mov     si,OFFSET fmark+5   ; If "[F]M?.? TSR"
  827.             mov     cx,4                ; signature last
  828.             rep     cmpsb               ; 4 bytes match
  829.             jcxz    IsFMark             ; then is [F]Mark
  830.             dec     di                  ; else check for LoadTSR
  831.             rep     cmpsb               ; MenuTSR Identification
  832.             pop     ds                  ; Restore Data and
  833.             mov     es,sbuffer          ; MapData Buffer Segments
  834.             mov     di,bp               ; Restore MapData Pointer
  835.             mov     si,OFFSET doscm+4   ; Point to "command"
  836.             mov     cx,7                ; bytes and copy
  837.             jne     CyOwner             ; unless LoadTSR
  838.             mov     si,OFFSET LoadTSR   ; is the real
  839. CyOwner:    rep     movsb               ; Owner Area of MapData
  840.             je      OCVExit
  841.             add     di,2                ; Advance to Command Line
  842.             push    ds                  ; Preserve Data Segment
  843.             mov     ds,ax               ; Set to PSP and
  844.             jmp     SHORT CmdParm       ; Get Command Line
  845.  
  846. IsFMark:    push    es                  ; Put PSP Segment AFTER
  847.             mov     es,sbuffer          ; Restore MapData Buffer
  848.             pop     ds                  ; into DS Register
  849.             mov     si,di               ; Set Source Index to
  850.             mov     cx,9                ; beginning of the
  851.             sub     si,cx               ; [F]Mark signature
  852.             mov     di,bp               ; Segment and Pointer
  853.             rep     movsb               ; Copy FMark Signature
  854. CmdParm:    inc     di                  ; Presume NO White Space
  855.             mov     si,81h              ; Get Command Length and
  856.             mov     cx,[si-1]           ; 1st Command Line Byte
  857.             cmp     ch,"!"              ; Check for White Space OR
  858.             mov     ch,0                ; If NO Parameter Length
  859.             jcxz    Go2Vecs             ; Then Adjust to Vectors
  860.             jnc     NoSpace             ; Else Ready with No Space
  861.             dec     di                  ; Else Make Room for Space
  862. NoSpace:    cmp     cx,19               ; If Don't Need elipsis
  863.             jle     CopyCmd             ; Then copy all bytes
  864.             mov     cx,16               ; else copy 16 bytes
  865.             mov     ax,".."             ; adding continuation
  866. CopyCmd:    cmp     byte ptr ds:[si]," "
  867.             jc      NotCopy             ; If Printable
  868.             movsb                       ; Then Copy
  869.             jmp     Short CpyLoop       ;  and Loop
  870.  
  871. NotCopy:    inc     si                  ; Else Replace
  872.             inc     di                  ; With Space
  873. CpyLoop:    loop    CopyCmd             ;  and Loop
  874.             cmp     ax,".."             ; If NOT continuation
  875.             jne     Go2Vecs             ; Then Vectors
  876.             stosw                       ; Else continue
  877.             stosb                       ; elipsis (...)
  878. Go2Vecs:    pop     ds                  ; Restore Data Segment
  879.             mov     ax,MCBS[bx].mcba    ; If Memory Control Block
  880.             inc     ax                  ; Segment Address + 1
  881.             cmp     ax,MCBS[bx].pspa    ; is NOT EQUAL to PSP
  882.             jne     OCVExit             ; then NO Interrupts
  883.             call    Vectors             ; else store vectors
  884. OCVExit:    mov     ax,0A0Dh            ; End the Data
  885.             stosw                       ; Storage Line
  886.             pop     cx                  ; Restore StoLoop Counter
  887.             ret
  888. OwnComVec   ENDP
  889.  
  890. GetData     PROC
  891.             mov     ah,52h              ; Use reserved DOS
  892.             int     21h                 ; Interrupt to get
  893.             mov     bp,es:[bx-2]        ; Start MCB Address
  894.             xchg    bx,dx               ; Zero Array Index
  895. MCBLoop:    add     bx,8                ; Advance Index
  896.             mov     es,bp               ; Locate MCB and
  897.             inc     bp                  ; Block Segments
  898.             mov     ax,es:[1]           ; Get PSP and
  899.             mov     cx,es:[3]           ; Block Length
  900.             cmp     ax,bx               ; If CONGIG PSP
  901.             je      FixPSP              ; Then Fix to MCB+1
  902.             or      ax,ax               ; Else If NOT Trapped
  903.             jnz     CkBlock             ; Then Flag NOT 0
  904.             xor     dx,dx               ; Else Zero MCBS Flag
  905. FixPSP:     mov     ax,bp               ; Set Block = MCB+1
  906.             jmp     SHORT PutTable
  907. CkBlock:    cmp     ax,bp               ; If PSP NOT MCB+1
  908.             mov     dx,0FFh             ; Then Flag Environment
  909.             jnz     PutTable            ;  for MCB Table Item
  910.             xchg    dh,dl               ; Else Flag as Program
  911.             call    Chk4TSR             ; If NOT [F]Mark, Watch, etc
  912.             jne     PutTable            ; Then Flag as "Program"
  913.             mov     dl,dh               ; Else Flag as "Special"
  914. PutTable:   mov     MCBS[bx].mcba,es    ; Store MCB Address
  915.             mov     MCBS[bx].pspa,ax    ; Store PSP Address
  916.             mov     MCBS[bx].mcbl,cx    ; Length of Block and
  917.             mov     MCBS[bx].mcbf,dx    ; Flag Word of Type Block
  918.             cmp     BYTE PTR es:[0],"Z" ; If Last MCB
  919.             je      LastMCB             ; Then MCBs done
  920.             add     bp,cx               ; Else Next MCB
  921.             jmp     short MCBLoop       ; Until Last
  922. LastMCB:    mov     es,sbuffer          ; Set Buffer Segment
  923.             mov     cx,3                ; Calculate and
  924.             shr     bx,cl               ; Store Block
  925.             mov     bp,bx               ; Count
  926.             call    SortMCBs            ; Sort Blocks by PSP
  927.             mov     cx,bp               ; ReStore Counter and
  928.             xor     bx,bx               ; Index to Beginning
  929. StoLoop:    add     bx,8                ; Advance MCB Index
  930.             mov     ax,MCBS[bx].pspa    ; Get PSP Address Word
  931.             mov     startl,di           ; UpDate Start of Line
  932.             inc     di                  ; Start with a space
  933.             call    ShoWord             ; Display PSP in HEX
  934.             mov     ax,MCBS[bx].mcba    ; Get MCB Address Word
  935.             call    ShoWord             ; Display 4 HEX Digits
  936.             mov     ax,MCBS[bx].pspa    ; Restore PSP
  937.             cmp     spsp,ax             ; If ShowTSRs
  938.             je      WasLast             ; Then End Table
  939.             mov     dx,MCBS[bx].mcbf    ; If Flag Shows
  940.             cmp     dh,0FFh             ; NOT TSR Program
  941.             jne     FilExit             ; then skip files
  942.             mov     es,ax               ; Point to Segment and
  943.             mov     di,18h              ; Offset of DOS Files
  944.             mov     cx,20               ; Initialize Counter
  945.             mov     al,0FFh             ; Looking for closed
  946.             repne   scasb               ; Preserve position
  947.             mov     ax,di               ; after search
  948.             mov     es,sbuffer          ; Restore Data Buffer
  949.             sub     ax,19h              ; Calculate open files
  950.             xor     dx,dx               ; as a double word to
  951.             mov     di,startl           ; place under "l" in
  952.             add     di,14               ; "file" heading
  953.             call    BinToDStr
  954. FilExit:    mov     ax,MCBS[bx].mcbl    ; Store length as
  955.             jmp     SHORT P2Bytes       ; decimal bytes
  956.  
  957. WasLast:    mov     ax,fmem             ; Store free
  958.             mov     si,offset freem+2   ; "free" RAM
  959.             mov     cx,4                ; message
  960.             rep     movsb               ; Counter = 0 to END
  961.  
  962. P2Bytes:    push    cx                  ; Preserve Counter
  963.             xor     dx,dx               ; Clear top and
  964.             mov     cx,10h              ; multiply into
  965.             mul     cx                  ; double word
  966.             mov     di,startl           ; value for
  967.             add     di,22               ; "bytes"
  968.             call    BinToDStr
  969.             pop     cx                  ; If Counter is Zero
  970.             jcxz    EndMCBs             ; then MCBs are done
  971.             call    OwnComVec           ; else finish line
  972.             jmp     StoLoop             ; Until Last Line
  973.  
  974. EndMCBs:    mov     ax,0A0Dh            ; End the
  975.             stosw                       ; Last Line
  976.             call    InfoMap             ; Add EGA & ICA Info
  977.             mov     si,OFFSET EmsName   ; and If Driver Found
  978.             call    EmmsMap             ; add EMS Information
  979.             ret
  980. GetData     ENDP
  981.  
  982. DoIMdata    PROC
  983.             push    ds                  ; Preserve Data Segment
  984.             push    ax                  ; and Pointer to DOS Data
  985.             mov     si,ax               ; Initialize Source Index
  986.             mov     cx,8                ; Pointer and Counter
  987.             mov     ax,40h              ; Set DOS data segment in
  988.             mov     ds,ax               ; Data Segment Register
  989.             cmp     si,0A8h             ; If EGA Info Area
  990.             jz      IMAOk               ; then bytes IS 8
  991.             add     cx,8                ; else bytes is 16
  992. IMAOk:      push    cx                  ; Preserve byte counter
  993.  
  994. IMdigL:     inc     di                  ; Space before
  995.             lodsb                       ; and Store 2
  996.             call    Val2ASCh            ; HEX ASCII digits
  997.             loop    IMdigL              ; until count complete
  998.             pop     cx                  ; Restore byte counter
  999.             pop     si                  ; and DOS data pointer
  1000.             add     di,2                ; Add 2 spaces
  1001.             cmp     si,0A8h             ; If NOT 8 byte EGA
  1002.             jnz     IMascL              ; then ready for ASCII
  1003.             add     di,8                ; else need 8 spaces
  1004. IMascL:     lodsb                       ; Get a byte
  1005.             cmp     al,20h              ; If => space
  1006.             jnc     CkHigh              ; then check delete
  1007. UseDot:     mov     al,"."              ; else use a dot
  1008.  
  1009. CkHigh:     cmp     al,7Fh              ; If => space
  1010.             jnc     UseDot              ; then use a dot
  1011.             stosb                       ; Send to MapData
  1012.             loop    IMascL              ; until CX 'em
  1013.             pop     ds                  ; Restore Data Segment
  1014.             mov     ax,0A0Dh            ; End the line
  1015.             stosw
  1016.             ret
  1017. DoIMdata    ENDP
  1018.  
  1019. InfoMap     PROC
  1020.             call    Underline           ; Underline block data
  1021.             mov     si,OFFSET EgaHdg    ; Transfer EGA Info
  1022.             mov     cx,EgaLen           ; Area Heading
  1023.             rep     movsb
  1024.             mov     ax,0A8h             ; Point to and
  1025.             call    DoIMdata            ; transfer EGA data
  1026.             mov     si,OFFSET IcaHdg    ; Transfer Inter-
  1027.             mov     cx,IcaLen           ; Application Area
  1028.             rep     movsb               ; Heading bytes
  1029.             mov     ax,0F0h             ; Point to and
  1030.             call    DoIMdata            ; get ICA data
  1031. Underline:  mov     ax,"- "
  1032.             stosb                       ; Space plus
  1033.             mov     al,ah               ; Minus sign
  1034.             mov     cx,76               ; Underlines
  1035.             rep     stosb
  1036.             mov     ax,0A0Dh            ; End the
  1037.             stosw                       ; underline
  1038.             ret
  1039. InfoMap     ENDP
  1040.  
  1041. EmmsMap     PROC
  1042.             mov     ax,3567h            ; Get Vector for
  1043.             int     21h                 ; Function 67hex
  1044.             push    di                  ; Preserve store pointer
  1045.             mov     di,000Ah            ; If Device
  1046.             mov     cx,8                ; Name is NOT
  1047.             rep     cmpsb               ; "EMMXXXX0"
  1048.             mov     es,sbuffer          ; after restore
  1049.             pop     di                  ; storage ES:DI
  1050.             jne     EmsErrX             ; then Error Exit
  1051.             mov     ah,46h              ; or if version
  1052.             int     67h                 ; number request
  1053.             or      ah,ah               ; returns error
  1054.             jnz     EmsErrX             ; then Error Exit
  1055.             mov     si,OFFSET emmshdg   ; else store 1st
  1056.             mov     cx,emmlen1          ; heading line
  1057.             rep     movsb               ; with Version
  1058.             call    Val2ASCh            ; Major Number
  1059.             mov     ah,"."              ; plus dot and
  1060.             xchg    al,ah               ; Minor Number
  1061.             dec     di
  1062.             stosw
  1063.             mov     cx,emmlen2          ; Add 2nd heading
  1064.             rep     movsb               ; line lead-in to
  1065.             mov     ah,41h              ; EMS Page Frame
  1066.             int     67h                 ; If Page Frame
  1067.             or      ah,ah               ; Request Fails
  1068.             jnz     EmsErrX             ; then Error Exit
  1069.             mov     al,bh               ; else store HEX
  1070.             call    Val2ASCh            ; first two digits
  1071.             mov     al,bl               ; third and fourth
  1072.             call    Val2ASCh            ; plus ending
  1073.             mov     al,")"              ; parenthesis
  1074.             stosb
  1075.             mov     ax,0A0Dh            ; End the line
  1076.             stosw
  1077.             mov     ah,4Bh              ; Get Handle
  1078.             int     67h                 ; Count in BX
  1079.             or      ah,ah               ; If Response
  1080.             jz      EmPages             ; then Map Pages
  1081. EmsErrX:    mov     si,OFFSET emserm    ; else store
  1082.             mov     cx,emerml           ; E M S
  1083.             rep     movsb               ; Error
  1084.             jmp     EmmExit             ; Message
  1085.  
  1086. EmPages:    mov     cx,bx               ; Set Handle Counter
  1087.             inc     cx                  ; for zero thru [bx]
  1088.             xor     dx,dx               ; Count up from 0
  1089. HndLoop:    mov     startl,di           ; Save Start of Line
  1090.             mov     ah,4Ch              ; Get Assigned
  1091.             int     67h                 ; Handle Pages
  1092.             or      ah,ah               ; If Error
  1093.             jnz     NoPages             ; then skip
  1094.             or      bx,bx               ; else if > 0
  1095.             jnz     PagesOk             ; then store
  1096. NoPages:    inc     dx                  ; else loop until
  1097.             loop    HndLoop             ; CX handles done
  1098.             jmp     SHORT HndExit
  1099. PagesOk:    add     di,6                ; Position for
  1100.             push    dx                  ; Handle Number
  1101.             xor     ax,ax               ; Double Word
  1102.             xchg    ax,dx               ; Digit(s)
  1103.             call    BinToDStr
  1104.             add     di,9                ; Position for
  1105.             mov     ax,bx               ; Handle Pages
  1106.             call    BinToDStr
  1107.             add     tpages,ax           ; Accumulate Total
  1108.             add     di,9                ; Position for
  1109.             mov     bx,16               ; Kilo
  1110.             mul     bx                  ; Bytes
  1111.             call    BinToDStr
  1112.             pop     dx                  ; Restore Handle
  1113.             add     di,3                ; Position for
  1114.             mov     ax,5300h            ; User Name
  1115.             int     67h                 ; Advance Past
  1116.             add     di,8                ; Name Area and
  1117.             mov     ax,0A0Dh            ; End the line
  1118.             stosw
  1119.             inc     dx                  ; Increment Handle
  1120.             loop    HndLoop             ; until CX'em done
  1121.  
  1122. HndExit:    mov     ah,42h              ; Get Free
  1123.             int     67h                 ; Pages
  1124.             mov     ax,tpages           ; Calculate and
  1125.             add     ax,bx               ; Preserve
  1126.             push    ax                  ; Total Pages
  1127.             mov     si,OFFSET freem     ; Store the
  1128.             mov     cx,6                ; "  free"
  1129.             rep     movsb               ; lead-in
  1130.             add     di,9                ; Position for
  1131.             mov     ax,bx               ; Free Pages
  1132.             xor     dx,dx               ; DoubleWord
  1133.             call    BinToDStr
  1134.             add     di,9                ; Position for
  1135.             mov     bx,16               ; Free Kilo
  1136.             mul     bx                  ; Bytes
  1137.             call    BinToDStr
  1138.             mov     si,OFFSET dashes+24 ; Space Over
  1139.             mov     cx,11               ; and dash-out
  1140.             rep     movsb               ; UserName
  1141.             mov     ax,0A0Dh            ; End the line
  1142.             stosw
  1143.             mov     si,OFFSET totlm     ; Store
  1144.             mov     cx,6                ; " total"
  1145.             rep     movsb               ; lead-in
  1146.             add     di,9                ; Position for
  1147.             pop     ax                  ; Total
  1148.             call    BinToDStr           ; Pages
  1149.             add     di,9                ; Position for
  1150.             mul     bx                  ; Total Bytes
  1151.             call    BinToDStr
  1152.             mov     si,OFFSET dashes+24 ; Space Over
  1153.             mov     cx,11               ; and dash-out
  1154.             rep     movsb               ; UserName
  1155.  
  1156. EmmExit:    mov     ax,0A0Dh            ; End the line
  1157.             stosw
  1158.             ret
  1159. EmmsMap     ENDP
  1160.  
  1161. Vectors     PROC
  1162.             mov     si,OFFSET WatchS    ; If the
  1163.             mov     di,startl           ; Owner
  1164.             add     di,23               ; Name was NOT
  1165.             mov     cx,11               ; "TSR WATCHER"
  1166.             rep     cmpsb               ; Then Check If
  1167.             jnz     CkWatch             ; Already Installed
  1168.             mov     WatchF,ax           ; Else Flag Installed
  1169. CkWatch:    mov     di,startl           ; Position Index to
  1170.             add     di,51               ; Start of Vector Area
  1171.             cmp     WatchF,0            ; If NO TSR WATCHER Installed
  1172.             jz      UseHook             ; Then Use Hooked Vectors
  1173.             push    ds                  ; Else Use Chained
  1174.             mov     ds,WatchF           ; Vectors from Watch
  1175.             mov     dx,ax               ; Copy Program PSP
  1176.             mov     si,104h             ; Get Next Vector
  1177.             lodsw                       ; Position in
  1178.             mov     si,218h             ; Vector Change
  1179.             add     ax,220h             ; Storage Area
  1180.             mov     vpos,ax             ; Store for Comparison
  1181.             xor     bp,bp               ; Zero Vector Counter
  1182. FFLoop:     add     si,8                ; If Next Record
  1183.             cmp     si,vpos             ; Is => Table End
  1184.             jnc     WatchX              ; then exit done
  1185.             cmp     BYTE PTR [si],0FFh  ; else if NOT pspid
  1186.             jne     FFLoop              ; or if PSP
  1187.             cmp     [si+2],dx           ; is NOT desired PSP
  1188.             jne     FFLoop              ; then keep looking
  1189. WatchL:     add     si,8                ; If Next Record
  1190.             cmp     si,vpos             ; is => Table End
  1191.             jnc     WatchX              ; Then exit done
  1192.             cmp     WORD PTR [si],-1    ; Else If Next pspid
  1193.             jnc     WatchX              ; then exit done
  1194.             cmp     BYTE PTR [si+1],1   ; else if NOT disabled
  1195.             jne     WatchV              ; then put vectors
  1196.             pop     ds                  ; else restore data
  1197.             mov     si,OFFSET disam     ; segment of message
  1198.             mov     cx,disalen          ; ***D I S A B L E D
  1199.             rep     movsb               ; *** and exit
  1200.             jmp     SHORT INTExit
  1201. WatchV:     cmp     bp,9                ; If NOT to last column
  1202.             jc      WatchW              ; then store Vector
  1203.             mov     WORD PTR es:[di],0A0Dh
  1204.             add     di,53               ; else start new line
  1205.             xor     bp,bp               ;  and update counter
  1206. WatchW:     mov     ax,[si]             ; Get Vector Number
  1207.             call    Val2ASCh            ; Store 2 HEX ASCII
  1208.             inc     di                  ; digits plus a space
  1209.             inc     bp                  ; Count Vector
  1210.             jmp     SHORT WatchL        ; Loop until exit
  1211. WatchX:     pop     ds                  ; Restore Data
  1212.             jmp     SHORT INTExit       ; Segment and Exit
  1213.  
  1214. UseHook:    mov     bp,di               ; Copy Pointer
  1215.             xor     di,di               ; Point ES:DI to
  1216.             mov     es,di               ; DOS INT Vectors
  1217.             mov     cx,512              ; Set Word Count
  1218.             mov     dx,4                ; and INT Divisor
  1219. INTLoop:    mov     ax,MCBS[bx].pspa    ; Scan for PSP in
  1220.             repne   scasw               ; DOS Vector Table
  1221.             mov     es,sbuffer          ; Restore ES:DI to Buffer
  1222.             xchg    bp,di               ; If at End of Vector Table
  1223.             jcxz    INTExit             ; then Vectors are Done
  1224.             mov     ax,bp               ; else Calculate
  1225.             div     dl                  ; Vector Number
  1226.             dec     ax                  ; Zero - Based
  1227.             call    Val2ASCh            ; Display 2 HEX ASCII
  1228.             inc     di                  ; digits plus a space
  1229.             xor     ax,ax               ; Reset Extra Segment
  1230.             mov     es,ax               ; and Pointer to Vectors
  1231.             xchg    bp,di               ; preserving MapData Pointer
  1232.             mov     ax,startl           ; If start of current row
  1233.             add     ax,columns-3        ; to position after end
  1234.             cmp     bp,ax               ; is greater than pointer
  1235.             jc      INTLoop             ; then loop until end/done
  1236.             mov     WORD PTR es:[bp],0A0Dh
  1237.             add     bp,53               ; else start new line
  1238.             jmp     SHORT INTLoop       ; Loop Until Vectors Done
  1239.  
  1240. INTExit:    ret
  1241.  
  1242. Vectors     ENDP
  1243.  
  1244.             END     Main
  1245.  
  1246.         This Version 3.1 revision began with a complaint that
  1247.         "garbage was displayed" for certain TSR command lines.
  1248.  
  1249.         The cause was a programming error in that a 0 Length
  1250.         command line was NOT skipped.  The revision result is
  1251.         a ShowTSRs that reverts to the original purpose.  It
  1252.         is again compatible with all [F]MarkS, WatchS, etc...
  1253.         whether from TurboPower or Tom Gilbert's Heart & Mind.
  1254.  
  1255.         We are learning from the experience and will welcome comments
  1256.         or criticism...  I lied!  We'd rather have help and praise...
  1257.