home *** CD-ROM | disk | FTP | other *** search
/ Der Mediaplex Sampler - Die 6 von Plex / 6_v_plex.zip / 6_v_plex / DISK3 / DFUE_43 / 26HDCOM1.ZIP / 26HDCOM1.ASM next >
Assembly Source File  |  1990-12-06  |  50KB  |  1,227 lines

  1. ;-----------------------------------------------------------------------------|
  2. ;  ---- ScanSoft(tm) 26HDCOM (C)1991 Cornel Huth -- All Rights Reserved ----  |
  3. ;-----------------------------------------------------------------------------|
  4. ;  program:     26HDCOM.ASM                                                   |
  5. ;  version:     2.01                                                          |
  6. ;       by:     Cornel Huth                                                   |
  7. ;     date:     12/06/90                                                      |
  8. ; function:     display hard drive status and COM port status on              |
  9. ;                 line 26 of CGA, EGA, VGA (color) and line 1 of MDA (mono)   |
  10. ;   caller:     user timer interrupt 1Ch (18.2 times/sec)                     |
  11. ;      use:                                                                   |
  12. ;                                                                             |
  13. ;   C>HC       * install TSR to monitor status                                |
  14. ;     HC /U    * remove from memory                                           |
  15. ;     HC /S    * sleep mode                                                   |
  16. ;     HC /R    * restore status line and awaken if in sleep mode              |
  17. ;     HC /Cn   * monitor COM port (n=1-4  0=off)                              |
  18. ;     HC /Mn   * select controller BIOS data interpret mode (n=1-4)           |
  19. ;     HC /H    * help                                                         |
  20. ;                                                                             |
  21. ;       If you're using an MDA, press <Alt> to deactivate status display      |
  22. ;       on line 1.  Or, use Scroll Lock (on) for continuous non-display       |
  23. ;                                                                             |
  24. ;       Some older CGA monitors overscan a bit and may obscure the corners    |
  25. ;       in line 26.                                                           |
  26. ;                                                                             |
  27. ;-----------------------------------------------------------------------------|
  28.  
  29. BIOS_SEG        SEGMENT AT 0040h
  30.                 ORG 17h
  31. KBDflags1       db ?            ;keyboard toggle flags
  32. ;---------------
  33.                 ORG 41h
  34. status          db ?            ;floppy controller error byte
  35. drive           db ?            ;floppy drive
  36. headHD_1        db ?            ;HD head [mode 1]
  37. cylHI_1         label byte      ;bits 6 & 7 represent HI cylinder * 256 [mode 1]
  38. secHD_1         label byte      ;bits 0 - 5 represent sector of HD [mode 1]
  39. secHD_2         label byte      ;represents sector of HD [mode 2]
  40.                 db ?            ;ORG 44h
  41. trackFD         label byte      ;track of floppy
  42. cylLO_1         label byte      ;LO cylinder [mode 1]
  43. cylLO_2         label byte      ;LO cylinder [mode 2]
  44.                 db ?            ;ORG 45h
  45. headFD          label byte      ;head of floppy
  46. cylHI_2         label byte      ;HI cylinder * 256 [mode 2]
  47.                 db ?            ;ORG 46h
  48. secFD           label byte      ;sector of floppy
  49. headHD_2        label byte      ;head HD [mode 2]
  50.                 db ?            ;ORG 47h
  51. ;---------------
  52.                 ORG 49h
  53. modeCRT         db ?            ;current mode of video system
  54.                 ORG 63h
  55. addrCRTC        dw ?            ;CRTC address register I/O port
  56.                 ORG 74h
  57. HDerror         db ?            ;hard disk controller error byte
  58.                 ORG 84h
  59. rowsCRT         db ?            ;# rows -1 (should be 24 for valid EGA/VGA)
  60.                 ORG 87h
  61. EGAinfo         db ?            ;EGA info byte (0 only if 64K EGA or no EGA)
  62. EGAinfo2        db ?            ;checked if EGAinfo = 0 (this is 0 if no EGA)
  63. VGAinfo         db ?            ;VGA info byte used with EGAinfo...
  64.  
  65. BIOS_SEG        ENDS
  66.  
  67. CODE_SEG        SEGMENT PUBLIC 'CODE'
  68.                 ASSUME cs:CODE_SEG,ds:CODE_SEG,es:NOTHING
  69.  
  70.                 org 100h
  71.                 ;need 16 bytes of constant data after go: for DUP install check
  72. go:             jmp start
  73.  
  74. Copyright       db 13,10,'ScanSoft(tm)  26HDCOM v2.01 (C)1991 Cornel Huth'
  75.                 db 13,10,'Harddisk and communication port monitor',13,10,'$'
  76.                 db '12/06/90',13,10
  77.                 db 'HDmode:'
  78. HDmode          db '1...';interpret mode
  79. ;                   12345678901234567890123456
  80. ErrorMsgs       db 'OK                        ' ; 0h
  81.                 db 'BAD COMMAND               ' ; 1
  82.                 db 'ADDRESS MARK NOT FOUND    ' ; 2
  83.                 db 'WRITE PROTECT ERROR       ' ; 3
  84.                 db 'SECTOR NOT FOUND          ' ; 4
  85.                 db 'RESET FAILED              ' ; 5
  86.                 db 'DISKETTE REMOVED          ' ; 6
  87.                 db 'BAD PARAMETER TABLE       ' ; 7
  88.                 db 'DMA OVERRUN               ' ; 8
  89.                 db 'DMA ACROSS 64K BOUNDARY   ' ; 9
  90.                 db 'BAD SECTOR FLAG DETECTED  ' ; A
  91.                 db 'BAD TRACK FLAG DETECTED   ' ; B
  92.                 db 'BAD MEDIA TYPE            ' ; C
  93.                 db 'TOO MANY SECTORS ON FORMAT' ; D
  94.                 db 'CTRL DATA ADDR MARK FOUND ' ; E
  95.                 db 'DMA ARBTRA`N OUT-OF-RANGE ' ; F
  96.                 db 'UNCORRECTABLE ECC         ' ;10
  97.                 db 'ECC CORRECTED DATA FAILURE' ;11
  98.  
  99.                 db 'GENERAL CONTROLLER FAILURE' ;20->12
  100.                 db '3x - UNKNOWN ERROR        '
  101.                 db 'SEEK FAILED               ' ;40  14
  102.                 db '5x - UNKNOWN ERROR        '
  103.                 db '6x - UNKNOWN ERROR        '
  104.                 db '7x - UNKNOWN ERROR        '
  105.                 db 'TIME-OUT                  ' ;80  18
  106.                 db '9x - UNKNOWN ERROR        '
  107.                 db 'DRIVE NOT READY           ' ;AA  1A
  108.                 db 'UNDEFINED ERROR OCCURED   ' ;BB  1B
  109.                 db 'WRITE FAULT               ' ;CC  1C
  110.                 db 'Dx - UNKNOWN ERROR        '
  111.                 db 'STATUS ERROR/ERROR REG = 0' ;E0  1E
  112.                 db 'SENSE OPERATION FAILED    ' ;FF  1F
  113.  
  114. VGA_data        dw 7    ;registers to change for VGA (reg, data)
  115. VGA_26_data     db 11h,0Eh,06h,0CFh,12h,09Fh,15h,0A2h,10h,0ACh,16h,0A9h,11h,8Eh
  116. VGA_25_data     db 11h,0Eh,06h,0BFh,12h,08Fh,15h,096h,10h,09Ch,16h,0B9h,11h,8Eh
  117. VGA             db 0
  118.  
  119. EGA_data        dw 5    ;registers to change for EGA (reg, data)
  120. EGA_26_data     db 06h,07Ah,12h,06Bh,15h,06Ch,10h,06Ch,16h,000h
  121. EGA_25_data     db 06h,06Ch,12h,05Dh,15h,05Eh,10h,05eh,16h,00Ah
  122. EGA             db 0
  123.  
  124. CGA_data        dw 1    ;registers to change
  125. CGA_26_data     db 06h,26
  126. CGA_25_data     db 06h,25
  127. CGA             db 0    ;(MCGA may be compatible, not tested)
  128.  
  129. MDA_data        dw 0    ;registers to change (not enough RAM for 26 lines)
  130. MDA_26_data     db 0,0
  131. MDA_25_data     db 0,0
  132. MDA             db 1    ;MDA is 'worst' case (or anytime in mode 7)
  133.  
  134. VALIDMODE       db 0    ;= 1 if operating in a compatible video mode
  135. ;even though the PIC won't allow another timer tick until we're done let's...
  136. Busy1C          dw 0    ;= 1 if already in our New_1C routine
  137. OLD_1C          dd 0    ;interrupt vector for old user timer interrupt
  138. CRTCaddr        dw 0    ;CRTC reg addr
  139. Video_Seg       dw 0    ;segment of video diplay memory
  140. StatLnOff       dw 0    ;offset into video buffer of Status line (4000/26,0/1)
  141. StatLnAttr      db 0    ;character attribute of StatLn
  142. CmdLineParm     db 0    ;command line parameter  (preceded by a /)
  143. CmdLineValue    dw 0    ;command line value (follows :)
  144. ;                             1         2         3         4         5         6         7
  145. ;                   01234567890123456789012345678901234567890123456789012345678901234567890123456789
  146. ;               db 'C:1023 Hd:15 Sc:63  12345678901234567890123456 xxx
  147. StatLn          db 'Z:0000 Hd:00 Sc:00                                                              '
  148. StatLnend       equ $
  149.  
  150. ErrTrip         dw 36   ;ticks to count to and then release last disk error
  151. ErrTicks        dw 0    ;tick cnt since last disk error (to save error msg)
  152.  
  153. HDstat          db 0    ;hard disk status save
  154. LastDiskError   db 0    ;last disk error
  155. DoCom           db 0    ;= 1 then display com status
  156.  
  157. ComPort         dw 0
  158. PinText         DB 'DTRRTSCTSDSRRI DCD'
  159. Psettings       DB 'NONE'
  160. Pins            DB 0    ;bit 0=DTR,1=RTS,2=CTS,3=DSR,4=RI,5=DCD
  161. BaudRate        DW 0
  162. Parity          DB 0
  163. DataBits        DB 0
  164. StopBits        DB 0
  165. Dlab_reg        DB 0
  166.       
  167. New_1C          PROC FAR
  168.                 ASSUME  ds:NOTHING, es:NOTHING
  169.                 sti
  170.                 push    ax
  171.                 push    bx
  172.                 push    cx
  173.                 push    dx
  174.                 push    bp
  175.                 push    di
  176.                 push    si
  177.                 push    es
  178.                 push    ds
  179.                 cld
  180.                 mov     ax,cs
  181.                 mov     ds,ax
  182.                 ASSUME  ds:CODE_SEG
  183.  
  184.                 inc     ErrTicks        ;error save ticker
  185.                 cmp     Busy1C,0        ;are we BUSY?
  186.                 jne     New_1Cxit
  187.                 mov     Busy1C,1        ;no, make us BUSY
  188.  
  189.                 mov     ax,0040h
  190.                 mov     es,ax           ;point es to BIOS data
  191.                 ASSUME  es:NOTHING
  192.  
  193. New_1C1:        call    Xlate_BIOS      ;do DISK
  194.  
  195.                 cmp     DoCom,0         ;show COM status?
  196.                 je      New_1C2         ;nope
  197.  
  198.                 push    es
  199.                 call    SetParms        ;do COM
  200.                 call    Refresh
  201.                 pop     es
  202.  
  203. New_1C2:        call    Get_Video_Info
  204.  
  205.                 cmp     VALIDMODE,1     ;are we valid?
  206.                 jne     New_1Cxit       ;no
  207.                 mov     dx,offset StatLn
  208.                 mov     cx,offset StatLnend - offset StatLn
  209.                 mov     ah,StatLnAttr
  210.  
  211.                 cmp     MDA,1
  212.                 jne     New_1C3
  213.                 test    es:KBDflags1,18h ;is <Alt> down or <Scroll Lock> on?
  214.                 jnz     New_1Cxit        ;yes, no display of MDA status
  215.  
  216. New_1C3:        mov     bp,Video_Seg
  217.                 mov     es,bp
  218.                 ASSUME  es:NOTHING
  219.                 mov     bx,StatLnOff     ;add offset into video buff of StatLn
  220.                 mov     di,bx            ;es:di -> destination
  221.                 mov     si,dx            ;ds:si -> source
  222. New_1C4:        lodsb                    ;get a character from the write buffer
  223.                 stosw                    ;store it and the attribute
  224.                 loop    New_1C4          ;print cx char/attr pairs
  225.  
  226. New_1Cxit:      pop     ds
  227.                 pop     es
  228.                 ASSUME  ds:NOTHING,es:NOTHING
  229.                 pop     si
  230.                 pop     di
  231.                 pop     bp
  232.                 pop     dx
  233.                 pop     cx
  234.                 pop     bx
  235.                 pop     ax
  236.                 cli
  237.                 mov     cs:Busy1C,0
  238.                 jmp     cs:OLD_1C
  239. New_1C          ENDP
  240.  
  241. ; Get video system information
  242. ;  enter with es->BIOS data area
  243.  
  244. Get_Video_Info  PROC NEAR
  245.                 ASSUME  ds:CODE_SEG,es:NOTHING
  246.                 sub     ax,ax
  247.                 mov     VALIDMODE,al
  248.                 mov     CGA,al
  249.                 mov     EGA,al
  250.                 mov     VGA,al
  251.                 inc     ax
  252.                 mov     MDA,al          ;assume 'worst case'
  253.  
  254.                 mov     al,es:modeCRT   ;get current BIOS video mode
  255.                 cmp     al,3            ;valid modes= 2,3,7
  256.                 je      GVI0
  257.                 cmp     al,7
  258.                 je      GVI0
  259.                 cmp     al,2
  260.                 je      GVI0
  261. GVIjmp:         jmp     GVIxit          ;not a valid video mode
  262.  
  263.                 ; get the CRTC port address
  264.  
  265. GVI0:           cmp     es:addrCRTC,03D4h       ;color adapter?
  266.                 jne     GVI1 ;BTW, let's just stay on page 0
  267.  
  268.                 mov     MDA,0                   ;yes
  269.                 mov     Video_Seg,0B800h        ;video base segment of color
  270.                 mov     CRTCaddr,03D4h          ;its controller (std)
  271.                 mov     StatLnOff,4000          ;StatLn offset (line 26)
  272.                 mov     StatLnAttr,0+(2*16)     ;black on green
  273.                 jmp     short GVI2
  274.  
  275. GVI1:           mov     Video_Seg,0B000h        ;mono's video base segment
  276.                 mov     CRTCaddr,03B4h          ;its controller (std)
  277.                 mov     StatLnOff,0             ;StatLn offset (line 1)
  278.                 mov     StatLnAttr,70h          ;reverse video
  279.                 jmp     short GVI4
  280.  
  281. GVI2:           cmp     es:EGAinfo,0            ;64K EGA/VGA or no EGA/VGA?
  282.                 jne     GVI2a                   ;no, an EGA/VGA with >64K
  283.                 cmp     es:EGAinfo2,0           ;no EGA/VGA at all?
  284.                 je      GVI3                    ;should be a CGA
  285.                 cmp     es:rowsCRT,24           ;EGA or VGA should be in
  286.                 ja      GVIxit                  ; 25 line mode (not 43 or 50...)
  287. GVI2a:          test    es:VGAinfo,11h          ;400 scanlines & VGA active?
  288.                 jz      GVI2b                   ;no, it's not a valid VGA
  289.                 mov     VGA,1
  290.                 jmp     short GVI4
  291. GVI2b:          mov     EGA,1                   ;and should be an EGA
  292.                 jmp     short GVI4
  293. GVI3:           mov     CGA,1                   ;it's CGA
  294. GVI4:           mov     VALIDMODE,1
  295.  
  296. GVIxit:         ret
  297. Get_Video_Info  ENDP
  298.  
  299. Xlate_BIOS      PROC NEAR
  300.                 ASSUME  ds:CODE_SEG,es:NOTHING
  301.                 ;enter with es->BIOS SEG
  302.  
  303.                 mov     al,es:HDerror   ;get HD controller status
  304.                 mov     HDstat,al
  305.  
  306. XLB1:           cmp     al,11h          ;max linear error number
  307.                 jbe     XLB2
  308.                 mov     cl,4
  309.                 shr     al,cl
  310.                 add     al,10h          ;make 20h,40,80...to 12h,14h,18h...
  311.  
  312. XLB2:           xor     ah,ah
  313.                 cmp     al,LastDiskError ;same disk error as last?
  314.                 je      XLB2b            ;yes, reset error wait
  315.  
  316.                 ;we know it's a different error than last
  317.  
  318.                 or      al,al            ;an error?
  319.                 jnz     XLB2b            ;yes, must be new one
  320.  
  321. XLB2a:          mov     cx,ErrTicks     ;ticks since last disk error
  322.                 cmp     cx,ErrTrip      ;...more than ticks to wait?
  323.                 jb      XLB2c           ;no, wait some more
  324.  
  325. XLB2b:          mov     LastDiskError,al ;update last error
  326.                 mov     ErrTicks,0      ;zero error wait tick count
  327.                 mov     bx,26           ;bytes per error message
  328.                 mov     cx,bx           ;for count
  329.                 mul     bx              ;error offset into ErrorMsgs
  330.  
  331.                 mov     si,offset ErrorMsgs
  332.                 add     si,ax
  333.                 mov     di,offset StatLn+20
  334.  
  335.                 push    es
  336.                 push    cs
  337.                 pop     es              ;es:di -> write buffer
  338.                 ASSUME  es:NOTHING
  339.  
  340.                 rep     movsb           ;write the message to the write buffer
  341.                 pop     es              ;get back es->BIOS
  342.                 ASSUME  es:NOTHING
  343.  
  344. XLB2c:          cmp     HDmode,'4'        ;monitor second drive?
  345.                 mov     al,"D"
  346.                 sbb     al,0            ;if we're in mode 3,2,1 then use 'C'
  347.                 mov     [StatLn+0],al
  348.  
  349.                 cmp     HDmode,'3'
  350.                 je      XL_HD_3
  351.                 cmp     HDmode,'2'
  352.                 je      XL_HD_2
  353.                 cmp     HDmode,'1'
  354.                 je      XL_HD_1
  355.                 jmp     XL_HD_4
  356.  
  357. ;******* [MODE 1] *******
  358.  
  359. XL_HD_1:        mov     al,es:headHD_1  ;head
  360.                 add     al,'0'
  361.                 mov     [StatLn+11],al  ;(A)
  362.  
  363.                 mov     ah,es:cylHI_1   ;let's get the cyl hi
  364.                 rol     ah,1            ;move cyl hi bits @ 6&7 to bits 0&1
  365.                 rol     ah,1
  366.                 and     ah,00000011b    ;isolate cyl hi
  367.                 mov     al,es:cylLO_1   ;cylinder low (ax = 10 bit cylinder)
  368.                 mov     di,offset StatLn+2
  369.                 mov     cx,4            ;number of digits
  370.                 call    AX2DEC
  371.  
  372.                 mov     al,es:cylHI_1   ;isolate sector
  373.                 and     al,00111111b    ;bits 0 - 5
  374.                 xor     ah,ah
  375.                 inc     ax              ;make sector 1-based [mode 1 ONLY]
  376.                 mov     di,offset StatLn+16-2   ;-2 since cx = 4-2
  377.                 mov     cx,2
  378.                 call    AX2DEC
  379.                 ret
  380.  
  381. ;******* [MODE 2] *******
  382.  
  383. XL_HD_2:        mov     al,es:headHD_2  ;head
  384.                 and     al,00001111b
  385.                 add     al,'0'
  386.                 mov     [StatLn+11],al  ;(A)
  387.  
  388.                 mov     ah,es:cylHI_2   ;let's get the cyl hi
  389.                 mov     al,es:cylLO_2   ;cylinder low (ax = 10 bit cylinder)
  390.                 mov     di,offset StatLn+2
  391.                 mov     cx,4            ;number of digits
  392.                 call    AX2DEC
  393.  
  394.                 mov     al,es:secHD_2   ;controller updates less than mode 1
  395.                 and     al,00111111b    ;bits 0 - 5 will be valid
  396.                 xor     ah,ah
  397.                 mov     di,offset StatLn+16-2   ;-2 since cx = 4-2
  398.                 mov     cx,2
  399.                 call    AX2DEC
  400.                 ret
  401.  
  402. ;******* [MODE 3] *******
  403.  
  404. XL_HD_3:        mov     dx,01F6h
  405.                 in      al,dx           ;drive/head (io 1F6h)
  406.                 and     al,00001111b
  407.                 mov     di,offset StatLn+10-2
  408.                 mov     cx,2
  409.                 call    AX2DEC
  410.  
  411.                 mov     dx,01F5h
  412.                 in      al,dx           ;cyl hi (io 1F5h)
  413.                 and     al,00000011b
  414.                 mov     ah,al
  415.                 dec     dx
  416.                 in      al,dx           ;cyl lo (io 1F4h)
  417.                 mov     di,offset StatLn+2
  418.                 mov     cx,4            ;number of digits
  419.                 call    AX2DEC
  420.  
  421.                 mov     dx,01F3h
  422.                 in      al,dx           ;sector (io 1F3h)
  423.                 and     al,00111111b
  424.                 xor     ah,ah
  425.                 mov     di,offset StatLn+16-2   ;-2 since cx = 4-2
  426.                 mov     cx,2
  427.                 call    AX2DEC
  428.                 ret
  429.  
  430. ;******* [MODE 4] *******
  431.  
  432. XL_HD_4:        mov     dx,0176h
  433.                 in      al,dx           ;head (io 176h)
  434.                 and     al,00001111b
  435.                 mov     di,offset StatLn+10-2
  436.                 mov     cx,2
  437.                 call    AX2DEC
  438.  
  439.                 mov     dx,0175h
  440.                 in      al,dx           ;cyl hi (io 175h)
  441.                 and     al,00000011b
  442.                 mov     ah,al
  443.                 dec     dx
  444.                 in      al,dx           ;cyl lo (io 174h)
  445.                 mov     di,offset StatLn+2
  446.                 mov     cx,4            ;number of digits
  447.                 call    AX2DEC
  448.  
  449.                 mov     dx,0173h
  450.                 in      al,dx           ;sector (io 173h)
  451.                 and     al,00111111b
  452.                 xor     ah,ah
  453.                 mov     di,offset StatLn+16-2   ;-2 since cx = 4-2
  454.                 mov     cx,2
  455.                 call    AX2DEC
  456.                 ret
  457.  
  458. Xlate_BIOS      ENDP
  459.                     
  460. ;  ENTER with:
  461. ;       ax = int value 0-99999
  462. ;       cx = number of digits to interpret
  463. ;       di -> buffer
  464. ;  EXIT with:
  465. ;       ASCII value of ax in di->buffer
  466.  
  467. AX2DEC          PROC NEAR
  468.                 ASSUME  ds:CODE_SEG
  469.  
  470.                 ;divide by 10 - get remainder
  471.                 mov     bx,10                   ; divisor
  472.                 xor     dx,dx                   ; using AX as dividend
  473.                 div     bx                      ; remainder in dx
  474.                 add     dl,"0"                  ; to ASCII
  475.                 mov     byte ptr [di+3],dl      ; store it
  476.                 cmp     cx,1
  477.                 je      AX2DECxit
  478.                 ;tens
  479.                 xor     dx,dx
  480.                 div     bx
  481.                 add     dl,"0"
  482.                 mov     byte ptr [di+2],dl
  483.                 cmp     cx,2
  484.                 je      AX2DECxit
  485.                 ;hundreds
  486.                 xor     dx,dx
  487.                 div     bx
  488.                 add     dl,"0"
  489.                 mov     byte ptr [di+1],dl
  490.                 cmp     cx,3
  491.                 je      AX2DECxit
  492.                 ;thousands
  493.                 xor     dx,dx
  494.                 div     bx
  495.                 add     dl,"0"
  496.                 mov     byte ptr [di],dl
  497.                 cmp     cx,4            ;(A)
  498.                 je      AX2DECxit       ; |
  499.                 ;ten-thousands          ; |
  500.                 xor     dx,dx           ; |
  501.                 div     bx              ; |
  502.                 add     dl,"0"          ; |
  503.                 mov     byte ptr [di-1],dl
  504. AX2DECxit:      ret
  505.  
  506. AX2DEC          ENDP
  507.  
  508. ;
  509. ;COM routine adapted from LITES.ASM (PC MAG V8N5 p.315)
  510. ;
  511.  
  512. SETPARMS        PROC    NEAR
  513.                 ASSUME  ds:CODE_SEG
  514.                 MOV     DX,COMPORT              ;get UART base address
  515.                 ADD     DX,3                    ;point DX to Data Format
  516.                 PUSH    DX
  517.                 IN      AL,DX                   ;read Data Format byte
  518.                 MOV     DLAB_REG,AL             ;save it
  519.                 OR      AL,80H                  ;set DLAB
  520.                 OUT     DX,AL
  521.                 SUB     DX,3                    ;read divisor LSB
  522.                 IN      AL,DX
  523.                 MOV     BL,AL
  524.                 INC     DX
  525.                 IN      AL,DX                   ;read divisor MSB
  526.                 MOV     BH,AL
  527.                 OR      BX,BX                   ;don't divide if BX = 0
  528.                 JNZ     SP1
  529.                 MOV     WORD PTR BAUDRATE,0
  530.                 JMP     SHORT SP2
  531. SP1:            MOV     AX,0C200H               ;calculate Baud rate from
  532.                 MOV     DX,1                    ;  clock and divisor
  533.                 DIV     BX
  534.                 MOV     BAUDRATE,AX             ;save it
  535. SP2:            POP     DX                      ;restore Data Format register
  536.                 MOV     AL,DLAB_REG
  537.                 OUT     DX,AL
  538. ;
  539. ;Determine what the parity, data bits, and stop bits settings are.
  540. ;
  541.                 MOV     AL,DLAB_REG            ;data bits in bits 0 and 1
  542.                 AND     AL,3
  543.                 ADD     AL,5
  544.                 MOV     DATABITS,AL
  545.                 MOV     AL,DLAB_REG            ;stop bits in bit 2
  546.                 SHR     AL,1
  547.                 SHR     AL,1
  548.                 AND     AL,1
  549.                 ADD     AL,1
  550.                 MOV     STOPBITS,AL
  551.                 MOV     BL,DLAB_REG            ;parity in bits 3 and 4
  552.                 MOV     CL,3
  553.                 SHR     BL,CL
  554.                 AND     BL,3
  555.                 XOR     BH,BH
  556.                 MOV     AL,BYTE PTR PSETTINGS[BX]
  557.                 MOV     PARITY,AL
  558. ;
  559. ;Determine the states of the CTS, DSR, DCD, and RI input pins.
  560. ;
  561.                 MOV     DX,COMPORT              ;point DX to Modem Status
  562.                 ADD     DX,6
  563.                 IN      AL,DX                   ;read register
  564.                 AND     AL,0F0H                 ;mask off the lower 4 bits
  565.                 SHR     AL,1                    ;then save them
  566.                 SHR     AL,1
  567.                 MOV     PINS,AL
  568. ;
  569. ;Determine the states of the RTS and DTR output pins.
  570. ;
  571.                 SUB     DX,2                    ;point DX to Modem Control
  572.                 IN      AL,DX                   ;read register
  573.                 AND     AL,3                    ;strip the upper 6 bits
  574.                 OR      PINS,AL                 ;store in PINS byte
  575.                 RET
  576. SETPARMS        ENDP
  577.  
  578. REFRESH         PROC    NEAR
  579.                 ASSUME  ds:CODE_SEG
  580.                 MOV     AX,CS
  581.                 MOV     ES,AX                   ;es->our SEG
  582.                 ASSUME  es:nothing
  583. ;
  584. ;Construct the portion of the string pertaining to the 6 pins.
  585. ;
  586.                 MOV     SI,OFFSET PINTEXT               ;point SI to text
  587.                 MOV     DI,OFFSET StatLn + 48-1 ;(A)    ;point DI to buffer
  588.                 push    di
  589.                 mov     al,20h                  ;clear COM area
  590.                 mov     cx,33   ;(A)            ;32 bytes
  591.                 rep     stosb                   ;at es:di
  592.                 pop     di
  593.                 MOV     BL,1
  594.                 MOV     CX,6                    ;6 pins to test
  595. RLOOP1:         PUSH    CX
  596.                 PUSH    SI
  597.                 PUSH    DI
  598.                 TEST    PINS,BL                 ;copy pin name to buffer if
  599.                 JZ      PINLOW                  ;  corresponding bit is set
  600.                 MOV     CX,3
  601. RLOOP2:         LODSB
  602.                 STOSB
  603.                 LOOP    RLOOP2
  604. PINLOW:         POP     DI
  605.                 POP     SI
  606.                 SHL     BL,1
  607.                 ADD     SI,3
  608.                 ADD     DI,4
  609.                 POP     CX
  610.                 LOOP    RLOOP1                  ;loop until all 6 are done
  611. ;
  612. ;Add Baud rate, parity, data bits, and stop bits indicators to the string.
  613. ;
  614.                 MOV     AX,BAUDRATE             ;Baud rate
  615.                 mov     di,offset StatLn+48+24
  616.                 mov     cx,5    ;(A)
  617.                 call    AX2DEC
  618.                 MOV     DI,OFFSET StatLn + 48 + 29
  619.                 MOV     AL,PARITY               ;parity
  620.                 STOSB
  621.                 MOV     AL,DATABITS             ;data bits
  622.                 ADD     AL,30H
  623.                 STOSB
  624.                 MOV     AL,STOPBITS             ;stop bits
  625.                 ADD     AL,30H
  626.                 STOSB
  627.                 RET
  628. REFRESH         ENDP
  629.  
  630.                 ;================================================
  631.                 ;let's install it - CODE AFTER start: IS NOT KEPT
  632.                 ;================================================
  633.  
  634.                 ASSUME  cs:CODE_SEG,ds:CODE_SEG,ss:CODE_SEG
  635.  
  636. start:          cld
  637.                 mov     dx,offset Copyright
  638.                 mov     ah,9
  639.                 int     21h
  640.  
  641.                 call    GetParm
  642.  
  643.                 ;---------------------
  644.                 not     byte ptr go     ;modify to avoid self-match
  645.                 xor     bx,bx           ;start search at segment zero (really 1)
  646.                 mov     ax,cs           ;compare to current code segment
  647. start1:         inc     bx              ;look at next segment
  648.                 cmp     ax,bx           ;until reaching this code seg
  649.                 mov     es,bx
  650.                 je      start3
  651.                 mov     si,offset go    ;set up to compare strings
  652.                 mov     di,si
  653.                 mov     cx,16           ;16 bytes must match
  654.                 rep     cmpsb           ;compare ds:si to es:di
  655.                 or      cx,cx           ;did the strings match?
  656.                 jnz     start1          ;if no match, try next segment
  657.                                         ;else fall through (already installed)
  658.                                         ; with es -> matching code segment
  659.  
  660.                 and     CmdLineParm,255-32 ;make it UPPERCASE now
  661.                 cmp     CmdLineParm,'U' ;unchain
  662.                 jne     start?
  663.                 jmp     Unchain
  664. start?:         cmp     CmdLineParm,'H' ;help
  665.                 jne     startC
  666.                 mov     dx,offset Use
  667.                 mov     ah,9
  668.                 int 21h
  669.                 mov     al,0
  670.                 jmp     Exit4c
  671.  
  672. startC:         cmp     CmdLineParm,'C' ;do COM port
  673.                 jne     startR
  674.                 jmp     ComPortit
  675. startR:         cmp     CmdLineParm,'R' ;restore 26 lines; awaken if dormant
  676.                 jne     startD
  677.                 jmp     RedoStatLn
  678. startD:         cmp     CmdLineParm,'S' ;sleep
  679.                 jne     startM
  680.                 jmp     Sleep
  681. startM:         cmp     CmdLineParm,'M' ;controller interpret mode
  682.                 jne     startElse
  683.                 jmp     ModeSelect
  684. startElse:      mov     dx,offset UseBeep
  685.                 cmp     CmdLineParm,0
  686.                 jne     start2          ;invalid parm
  687.                 mov     dx,offset DupMsg;no parms?,(/) already installed msg
  688. start2:         mov     ah,9
  689.                 int 21h
  690.                 mov     al,1
  691.                 jmp     Exit4c
  692.  
  693. start3:         mov     dx,offset Use   ;we're not installed
  694.                 mov     ah,9
  695.                 int 21h
  696.                 jmp     notinstalled
  697.  
  698.                 ;---------------------
  699.                 ;es->match segment
  700.  
  701. ComPortit:      mov     di,offset StatLn + 48   ;point DI to buffer
  702.                 mov     al,20h                  ;clear COM area
  703.                 mov     cx,32                   ;32 bytes
  704.                 rep     stosb                   ;at es:di
  705.  
  706.                 mov     ax,CmdLineValue
  707.                 xchg    ah,al
  708.                 cmp     al,'0'                  ;0, turn it off
  709.                 je      ComPortit1
  710.                 mov     dx,offset NoComMsg
  711.                 jb      ComPortitErr            ;below 0
  712.                 cmp     al,'4'                  ;or
  713.                 ja      ComPortitErr            ;above 4 is an error
  714.                 jmp     short ComPortit2
  715.  
  716. ComPortit1:     mov     es:DoCom,0
  717.                 mov     dx,offset ComPortOffMsg
  718.                 jmp     ComPortitX
  719.  
  720. ComPortit2:     mov     ComPortM,al
  721.                 SUB     AL,"1"                  ;normalize the entry(0-based)
  722.                 MOV     BL,AL                   ;save it
  723.                 ;* THE NEXT 6 LINES ARE NOT ASSEMBLED BECAUSE IF YOU
  724.                 ;* ARE USING COM PORT 2 WITHOUT ANYTHING IN COM 1 THEN
  725.                 ;* YOU CAN'T USE /C:2 BECAUSE INT 11 RETURNS ONLY THE
  726.                 ;* NUMBER OF SERIAL DEVICES...
  727.                 ;INT     11H                     ;determine number of COM
  728.                 ;SHR     AH,1                    ;  ports installed
  729.                 ;AND     AH,07H
  730.                 ;MOV     DX,OFFSET NoComMsg
  731.                 ;CMP     AH,BL                   ;exit on error if COM port
  732.                 ;JNA     start2                  ;  number is invalid
  733.                 push    es
  734.                 MOV     BYTE PTR COMPORT,BL     ;save port designator
  735.                 MOV     AX,40H                  ;get UART address from BIOS
  736.                 MOV     ES,AX                   ;  data area using the port
  737.                 XOR     DI,DI                   ;  number as an index into
  738.                 MOV     BX,COMPORT              ;  the table
  739.                 SHL     BX,1                    ;IF YOU HAVE MORE THAN 4 SERIAL
  740.                 MOV     AX,WORD PTR ES:[DI][BX] ;DEVICES YOU HAVE TO FIND OUT
  741.                 pop     es                      ;WHERE THEIR BASE ADDR IS...
  742.                 MOV     es:COMPORT,AX           ;ID COM port in TSR
  743.                 mov     es:DoCom,1              ;flag COM port monitoring
  744.                 mov     dx,offset ComMsg
  745. ComPortitX:     mov     ah,9
  746.                 int 21h
  747.                 mov     al,0
  748.                 jmp     Exit4c
  749.  
  750. ComPortitErr:   mov     ah,9
  751.                 int 21h
  752.                 mov     al,2                    ;COM errorlevel = 2
  753.                 jmp     Exit4c
  754.  
  755.                 ;---------------
  756.  
  757. ModeSelect:     mov     ax,CmdLineValue
  758.                 cmp     ah,'1'
  759.                 jb      ModeSelectErr           ;below 1
  760.                 cmp     ah,'4'                  ;or
  761.                 ja      ModeSelectErr           ;above 4 is an error
  762.                 mov     ModeM,ah
  763.                 mov     es:HDmode,ah
  764.                 mov     dx,offset ModeMsg
  765.  
  766. ModeSelect1:    mov     ah,9
  767.                 int 21h
  768.                 mov     al,0
  769.                 jmp     Exit4c
  770.  
  771. ModeSelectErr:  mov     dx,offset BadModeMsg
  772.                 mov     ah,9
  773.                 int 21h
  774.                 mov     al,3            ;MODE errorlevel = 3
  775.                 jmp     Exit4c
  776.   
  777.                 ;---------------------
  778. Sleep:          push    es              ;save TSR's segment
  779.  
  780.                 mov     es:ErrTicks,0
  781.  
  782.                 mov     ax,351Ch        ;get current timer interrupt (1Ch)
  783.                 int     21h
  784.                 pop     ax
  785.                 mov     dx,es
  786.                 cmp     ax,dx           ;compare matched seg with 1Ch seg
  787.                 jne     Sleep2          ;cannot sleep since seg has changed
  788.                 push    ax
  789.                 pop     es              ;get back es
  790.                 mov     dx,es:word ptr Old_1C
  791.                 mov     ax,es:word ptr Old_1C+2
  792.                 mov     ds,ax
  793.                 mov     ax,251Ch
  794.                 int 21h
  795.                 mov     ax,cs           ;restore ds
  796.                 mov     ds,ax
  797.                 push    es              ;save es
  798.                 mov     ax,0040h
  799.                 mov     es,ax           ;requirement of Get_Video_Info
  800.                 call    Get_Video_Info
  801.                 pop     es              ;get it back
  802.                 cmp     VALIDMODE,1
  803.                 mov     ax,0
  804.                 push    ax              ;save errorlevel
  805.                 jne     Sleep1
  806.                 call    Set_Line25      ;only if in a valid mode
  807. Sleep1:         mov     dx,offset SleepMsg
  808.                 jmp     short Sleep3
  809. Sleep2:         mov     dx,offset NoSleepMsg
  810.                 mov     ax,4            ;sleep errorlevel = 4
  811.                 push    ax              ;save errorlevel
  812. Sleep3:         mov     ah,9
  813.                 int 21h
  814.                 pop     ax
  815.                 jmp     Exit4c
  816.                 
  817.                 ;---------------------
  818. RedoStatLn:     push    es              ;save es
  819.                 mov     ax,0040h
  820.                 mov     es,ax           ;requirement of Get_Video_Info
  821.                 call    Get_Video_Info
  822.                 pop     es              ;get it back
  823.                 cmp     VALIDMODE,1
  824.                 je      RedoStatLn1
  825.                 mov     dx,offset NoRestoreMsg
  826.                 mov     ah,9
  827.                 int 21h
  828.                 mov     al,5            ;RESTORE errorlevel = 5
  829.                 jmp     Exit4c
  830. RedoStatLn1:    call    Set_Line26
  831.                 mov     dx,offset Redo26Msg
  832.                 mov     ah,9
  833.                 int 21h
  834.                 push    es              ;save es
  835.                 mov     ax,351Ch        ;get current timer interrupt (1Ch)
  836.                 int     21h             ; since it may have changed
  837.                 mov     cx,es           ;save int 21h's es into cx
  838.                 pop     es              ;get back es
  839.                 mov     dx,es
  840.                 cmp     cx,dx           ;if interrupt 1Ch has changed
  841.                 jne     RedoStatLn2     ; then need to awaken
  842.                 je      RedoStatLn3
  843. RedoStatLn2:    mov     es:word ptr [Old_1C],bx    ;save current offset in TSR
  844.                 mov     es:word ptr [Old_1C+2],cx  ;save current segment
  845.                 mov     dx,offset New_1C
  846.                 push    es
  847.                 pop     ds              ;matching code seg
  848.                 ASSUME  ds:NOTHING
  849.                 mov     ax,251Ch
  850.                 int     21h             ;set interrupt (1Ch) (time to awaken)
  851.                 push    cs
  852.                 pop     ds              ;get back ds
  853.                 ASSUME  ds:CODE_SEG
  854. RedoStatLn3:    mov     ah,0
  855.                 jmp     Exit4c
  856.  
  857.                 ;---------------------
  858.                 ;es -> matching segment
  859. Unchain:        push    es              ;save TSR's segment
  860.                 mov     ax,351Ch        ;get current timer interrupt (1Ch)
  861.                 int     21h
  862.                 pop     ax
  863.                 mov     dx,es
  864.                 cmp     ax,dx           ;compare matched seg with 1Ch seg
  865.                 jne     Unchain4        ;cannot unchain since seg has changed
  866.                 mov     es,ax           ;get back es
  867.                 mov     dx,es:word ptr Old_1C
  868.                 mov     ax,es:word ptr Old_1C+2
  869.                 mov     ds,ax
  870.                 mov     ax,251Ch        ;set timer interrupt to interrupt valid
  871.                 int 21h                 ; when installed
  872.                 mov     ax,cs           ;restore ds
  873.                 mov     ds,ax
  874.  
  875.                 not     es:byte ptr go  ;precludes matching on next install
  876.  
  877.                 mov     cx,es           ;save es -> PSP/COM BLOCK (not in EXE's)
  878.                 mov     bx,es:[002Ch]   ;segment address of environment block
  879.                 mov     es,bx
  880.                 mov     ah,49h
  881.                 int 21h                 ;release the environment block
  882.                 jc      Unchain1        ;an error
  883.  
  884.                 mov     es,cx
  885.                 mov     ah,49h          ;release the TSR block
  886.                 int 21h
  887.                 jnc     Unchain2
  888.  
  889. Unchain1:       mov     dx,offset DeAllocMsg ;memory dealloc error
  890.                 mov     ah,9
  891.                 int     21h
  892.                 mov     al,7            ;REMOVE errorlevel = 7
  893.                 jmp     short Exit4c
  894.  
  895. Unchain2:       push    es              ;save es (though not needed)
  896.                 mov     ax,0040h
  897.                 mov     es,ax
  898.                 call    Get_Video_Info
  899.                 pop     es              ;get it back
  900.                 cmp     VALIDMODE,1
  901.                 jne     Unchain3
  902.                 call    Set_Line25      ;only if in a valid mode
  903.  
  904. Unchain3:       mov     dx,offset UniMsg
  905.                 mov     ah,9
  906.                 int 21h
  907.                 mov     al,0
  908.  
  909.                 ;---------------------
  910. Exit4c:         mov     ah,4Ch
  911.                 int 21h
  912.  
  913.                 ;---------------------
  914. Unchain4:       mov     dx,offset NoUnchain
  915.                 mov     ah,9
  916.                 int 21h
  917.                 mov     al,6            ;UNCHAIN errorlevel = 6
  918.                 jmp     short Exit4c
  919.  
  920.                 ;---------------------
  921. notinstalled:   cmp     CmdLineParm,0   ;not yet installed, should be no parms
  922.                 je      notinstalled1
  923.                 mov     dx,offset NotInstalledMsg
  924.                 mov     ah,9
  925.                 int 21h
  926.                 mov     al,1            ;INSTALL errorlevel = 1
  927.                 jmp     short Exit4c
  928.  
  929.                 ;---------------------
  930. notinstalled1:  push    es              ;save es (though not needed here)
  931.                 mov     ax,0040h
  932.                 mov     es,ax
  933.                 call    Get_Video_Info
  934.                 pop     es              ;get it back
  935.                 cmp     VALIDMODE,1     ;are we in a valid mode?
  936.                 je      notinstalled2
  937.                 mov     dx,offset NoInstallMsg
  938.                 mov     ah,9
  939.                 int 21h
  940.                 mov     al,1            ;INSTALL errorlevel = 1
  941.                 jmp     short Exit4c
  942.  
  943.                 ;---------------------
  944. notinstalled2:  mov     ax,351Ch        ;get timer interrupt (1Ch)
  945.                 int     21h
  946.                 mov     word ptr [Old_1C],bx    ;save offset
  947.                 mov     word ptr [Old_1C+2],es  ;save segment
  948.                 mov     dx,offset New_1C
  949.                 mov     ax,251Ch
  950.                 int     21h             ;set new interrupt (1Ch)
  951.  
  952.                 call    Set_Line26
  953.  
  954.                 call    EntryAt
  955.                 mov     dx,offset EntryAtMsg   ;1Ch entry address
  956.                 mov     ah,9
  957.                 int 21h
  958.  
  959.                 cmp     MDA,1           ;in mode 7?
  960.                 jne     notinstalled3
  961.                 mov     dx,offset MDAmsg
  962.                 mov     ah,9
  963.                 int 21h
  964.  
  965. notinstalled3:  mov     dx,offset start
  966.                 mov     cl,4
  967.                 shr     dx,cl
  968.                 inc     dx
  969.                 mov     ax,3100h
  970.                 int     21h     ;Terminate - stay resident (keep up to start)
  971.  
  972.                 ;---------------------
  973. GetParm:        mov     si,81h
  974.                 mov     CmdLineParm,0
  975.                 mov     CmdLineValue,0
  976. GetParm1:       mov     bl,[si]
  977.                 cmp     bl,0dh
  978.                 je      GetParm_Exit
  979.                 inc     si
  980.                 cmp     bl,'/'
  981.                 jne     GetParm1
  982.                 mov     bl,[si]
  983.                 mov     CmdLineParm,bl
  984.                 inc     si              ;get 2 ASCII bytes after the :
  985.                 mov     bx,[si]
  986.                 xchg    bl,bh           ;put them in normal order
  987.                 mov     CmdLineValue,bx
  988. GetParm_Exit:   ret
  989.  
  990. ;
  991. ; two-byte ASCII in ax to byte in al (al=0 if number invalid or entry was 0)
  992. ; ah=1st digit  al=2d digit
  993. ;
  994.  
  995. ConvASCIIw2Byte PROC NEAR
  996.                 ASSUME ds:CODE_SEG
  997.  
  998.                 cmp     al,0dh          ;ending CR (check this first)
  999.                 je      ConvAsingleL
  1000.                 cmp     al,' '          ;ending space
  1001.                 je      ConvAsingleL
  1002.                 cmp     ah,' '          ;leading space
  1003.                 je      ConvAsingleR
  1004.                 cmp     ah,'0'          ;leading zero
  1005.                 je      ConvAsingleR
  1006.  
  1007.                 ;convert 2-digit ASCII number to byte
  1008.  
  1009.                 cmp     ah,'9'          ;check bounds on ten's digit
  1010.                 ja      ConvAnull
  1011.                 cmp     ah,'0'
  1012.                 jb      ConvAnull
  1013.                 cmp     al,'9'          ;and on one's digit
  1014.                 ja      ConvAnull
  1015.                 cmp     al,'0'
  1016.                 jb      ConvAnull
  1017.                 sub     ah,'0'
  1018.                 sub     al,'0'          ;normalize
  1019.                 mov     cx,ax           ;save number
  1020.                 mov     al,ah           ;get ten's digit in al
  1021.                 mov     bl,10
  1022.                 mul     bl              ;ax = 10*ten's digit
  1023.                 add     al,cl           ;add in one's digit
  1024.                 ret
  1025.  
  1026. ConvAsingleL:   cmp     ah,'9'          ;AL was space or CR
  1027.                 ja      ConvAnull
  1028.                 cmp     ah,'0'
  1029.                 jb      ConvAnull
  1030.                 sub     ah,'0'
  1031.                 mov     al,ah
  1032.                 ret
  1033.  
  1034. ConvAsingleR:   cmp     al,'9'          ;AH was space or zero
  1035.                 ja      ConvAnull
  1036.                 cmp     ah,'0'
  1037.                 jb      ConvAnull
  1038.                 sub     al,'0'
  1039.                 ret
  1040.  
  1041. ConvAnull:      mov     al,0
  1042.                 ret
  1043.  
  1044. ConvASCIIw2Byte ENDP
  1045.  
  1046. ;
  1047. ; byte in al to two-byte ASCII hex in ax (A5 to 'A5')
  1048. ;
  1049.  
  1050. ConvByte2ASCII  PROC NEAR
  1051.                 ASSUME  ds:CODE_SEG
  1052.  
  1053.                 push    cx
  1054.                 mov     cl,4            ;mult x 16
  1055.                 xor     ah,ah           ;just the low-order byte
  1056.                 push    ax              ;save data passed in AX
  1057.                 and     al,0F0h         ;hi-order nybble
  1058.                 shr     al,cl           ;div hi-nybble by 16
  1059. ConvB:          cmp     al,9            ;hex letter?
  1060.                 jna     ConvBdec
  1061.                 add     al,55           ;10+55=65(A)
  1062.                 jmp     short ConvB1
  1063. ConvBdec:       add     al,'0'          ;adjust ASCII to decimal 9+30h(0)=39h(9)
  1064. ConvB1:         cmp     cl,0            ;done both ASCII bytes?
  1065.                 je      ConvB2          ;*** exit 2x loop here
  1066.                 xchg    al,ch           ;save it
  1067.                 pop     ax              ;get it again
  1068.                 and     al,0Fh          ;low-order nybble
  1069.                 mov     cl,0            ;make it last time around
  1070.                 jmp     short ConvB     ;do low-order nybble
  1071. ConvB2:         xchg    ch,ah           ;get hi-order
  1072.                 xchg    al,ah           ;put in correct order
  1073.                 clc                     ;and we're done
  1074.                 pop     cx
  1075.                 ret
  1076.  
  1077. ConvByte2ASCII  endp
  1078.  
  1079. ;
  1080. ; get 1Ch entry address
  1081. ;
  1082.  
  1083. EntryAt         PROC NEAR
  1084.                 ASSUME  ds:CODE_SEG
  1085.  
  1086.                 mov     bx,offset EntryAtMsg+10
  1087.                 mov     ax,cs
  1088.                 xchg    ah,al
  1089.                 call    ConvByte2ASCII  ;seg high byte
  1090.                 mov     word ptr [bx],ax
  1091.                 mov     ax,cs
  1092.                 call    ConvByte2ASCII  ;seg low byte
  1093.                 mov     word ptr [bx+2],ax
  1094.                 mov     ax,offset New_1C
  1095.                 xchg    ah,al
  1096.                 call    ConvByte2ASCII  ;off high byte
  1097.                 mov     word ptr [bx+5],ax
  1098.                 mov     ax,offset New_1C
  1099.                 call    ConvByte2ASCII  ;off low byte
  1100.                 mov     word ptr [bx+7],ax
  1101.  
  1102.                 mov     al,HDmode
  1103.                 mov     ModeM,al
  1104.                 ret
  1105.  
  1106. EntryAt         ENDP
  1107.  
  1108. ;
  1109. ; program CRTC to display 26 lines
  1110. ;
  1111.  
  1112. Set_Line26      PROC NEAR
  1113.                 ASSUME  ds:CODE_SEG
  1114.  
  1115.                 cmp     MDA,1                   ;skip if MDA
  1116.                 jne     SL261
  1117.                 ret
  1118. SL261:          mov     dx,CRTCaddr             ;CRTC port address
  1119.                 cmp     VGA,1
  1120.                 jne     SL26_EGA
  1121.                 mov     cx,VGA_data
  1122.                 mov     si,offset VGA_26_data
  1123.                 jmp     short SL26_LR
  1124. SL26_EGA:       cmp     EGA,1
  1125.                 jne     SL26_CGA
  1126.                 mov     cx,EGA_data
  1127.                 mov     si,offset EGA_26_data
  1128.                 jmp     short SL26_LR
  1129. SL26_CGA:       mov     cx,CGA_data
  1130.                 mov     si,offset CGA_26_data
  1131. SL26_LR:        cli                             ;interrupts off
  1132. SL26_LR1:       lodsb
  1133.                 out     dx,al                   ;CRTC register
  1134.                 lodsb
  1135.                 inc     dx
  1136.                 out     dx,al                   ;data
  1137.                 dec     dx
  1138.                 loop    SL26_LR1
  1139.                 sti                             ;interrupts on
  1140.                 ret
  1141. Set_Line26      ENDP
  1142.  
  1143. ;
  1144. ; program CRTC to display 25 lines
  1145. ;
  1146.  
  1147. Set_Line25      PROC NEAR
  1148.                 ASSUME  ds:CODE_SEG
  1149.  
  1150.                 cmp     MDA,1
  1151.                 jne     SL251
  1152.                 ret
  1153. SL251:          mov     dx,CRTCaddr
  1154.                 cmp     VGA,1
  1155.                 jne     SL25_EGA
  1156.                 mov     cx,VGA_data
  1157.                 mov     si,offset VGA_25_data
  1158.                 jmp     short SL25_LR
  1159. SL25_EGA:       cmp     EGA,1
  1160.                 jne     SL25_CGA
  1161.                 mov     cx,EGA_data
  1162.                 mov     si,offset EGA_25_data
  1163.                 jmp     short SL25_LR
  1164. SL25_CGA:       mov     cx,CGA_data
  1165.                 mov     si,offset CGA_25_data
  1166. SL25_LR:        cli
  1167. SL25_LR1:       lodsb
  1168.                 out     dx,al
  1169.                 lodsb
  1170.                 inc     dx
  1171.                 out     dx,al
  1172.                 dec     dx
  1173.                 loop    SL25_LR1
  1174.                 sti
  1175.                 ret
  1176. Set_Line25      ENDP
  1177.  
  1178. ;---------------
  1179. DeAllocMsg      db '*** Error in releasing memory - suggest a REBOOT ASAP!'
  1180.                 db 13,10,7,'$'
  1181. NoSleepMsg      db '*** Cannot become dormant - interrupt 1Ch has changed.'
  1182.                 db 13,10,7,'$'
  1183. NoInstallMsg    db '*** Cannot install - must be in BIOS video modes 2, 3, or 7 (25 lines).'
  1184.                 db 13,10,7,'$'
  1185. NoRestoreMsg    db '*** Cannot restore - must be in BIOS video modes 2, 3, or 7 (25 lines).'
  1186.                 db 13,10,7,'$'
  1187. NoUnchain       db '*** Cannot remove from memory - interrupt 1Ch has changed.'
  1188.                 db 13,10,7,'$'
  1189. NotInstalledMsg db '*** Parameter ignored - install program first.'
  1190.                 db 13,10,7,'$'
  1191. DupMsg          db '*** Already installed - use /R to restore, /H for help.'
  1192.                 db 13,10,7,'$'
  1193. NoComMsg        db '*** COM port parameter not valid (0-4).'
  1194.                 db 13,10,7,'$'
  1195. BadModeMsg      db '*** Invalid controller interpret mode (1-4).'
  1196.                 db 13,10,7,'$'
  1197.  
  1198. UseBeep         db 7
  1199. Use             db 'Use HC         * install TSR to monitor status',13,10
  1200.                 db '    HC /U      * uninstall & release memory',13,10
  1201.                 db '    HC /S      * sleep mode',13,10
  1202.                 db '    HC /R      * restore status line and awaken if in sleep mode',13,10
  1203.                 db '    HC /Cn     * monitor COM port (n=1-4  0=off)',13,10
  1204.                 db '    HC /Mn     * select controller BIOS data interpret mode (n=1-4)',13,10
  1205.                 db '    HC /H      * help',13,10
  1206.                 db 13,10,'$'
  1207. EntryAtMsg      db 'INT 1Ch:  0000:0000',13,10
  1208. ModeMsg         db 'Controller interpret mode:'
  1209. ModeM           db '0'
  1210.                 db 13,10,'$'
  1211. UniMsg          db 'Uninstalled & released from memory.'
  1212.                 db 13,10,'$'
  1213. SleepMsg        db 'Sleep mode.  Use /R to restore.'
  1214.                 db 13,10,'$'
  1215. Redo26Msg       db 'Restored.'
  1216.                 db 13,10,'$'
  1217. ComMsg          db 'COM'
  1218. ComPortM        db 'x: monitoring activated.'
  1219.                 db 13,10,'$'
  1220. ComPortOffMsg   db 'COM port monitoring deactivated.'
  1221.                 db 13,10,'$'
  1222. MDAmsg          db 13,10,'Use <Alt> or <Scroll Lock> to toggle display line.'
  1223.                 db 13,10,'$'
  1224.  
  1225. CODE_SEG        ENDS
  1226.                 END go
  1227.