home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / msysjour / vol05 / 03 / keyboard / keyview.asm < prev    next >
Assembly Source File  |  1990-05-01  |  24KB  |  721 lines

  1.                TITLE   KEYVIEW.ASM
  2.                PAGE    60,132
  3.  
  4. ;-----------------------------------------------;
  5. ;  KeyView - Visual display of keyboard buffer. ;
  6. ;  Michael J. Mefford                           ;
  7. ;-----------------------------------------------;
  8.  
  9. BIOS_DATA      SEGMENT AT 40H
  10.  
  11.                ORG     1AH
  12.  
  13. BUFFER_HEAD    DW      ?
  14. BUFFER_TAIL    DW      ?
  15.  
  16.                ORG     71H
  17.  
  18. BIOS_BREAK     DB      ?
  19.  
  20.                ORG     80H
  21.  
  22. KBD_BUFF_START DB      ?
  23.  
  24. BIOS_DATA      ENDS
  25.  
  26.  
  27. _TEXT          SEGMENT PUBLIC 'CODE'
  28.                ASSUME  CS:_TEXT
  29.                ASSUME  DS:_TEXT
  30.  
  31.                ORG     100H
  32.  
  33. START:         JMP     MAIN
  34.  
  35. ;              DATA AREA
  36. ;              ---------
  37.                DB      CR,SPACE,SPACE,SPACE,CR,LF
  38.  
  39. COPYRIGHT      DB      "KEYVIEW 1.0 (c) 1990 "
  40.                DB      "Michael J. Mefford",CR,LF,LF,"$"
  41.                DB      CTRL_Z
  42.  
  43. CR             EQU     13
  44. LF             EQU     10
  45. CTRL_Z         EQU     26
  46. SPACE          EQU     32
  47. BOX            EQU     254
  48.  
  49. BUFFER_START   EQU     1EH
  50. BUFFER_END     EQU     3EH
  51.  
  52. UP_ARROW       EQU     24
  53. DN_ARROW       EQU     25
  54.  
  55. TRUE           EQU     1
  56. FALSE          EQU     0
  57.  
  58. BOX_ROW        EQU     8
  59. BOX_COL        EQU     7
  60. BOX_TWO        EQU     6
  61. CHAR_START     EQU     1400H
  62.  
  63. ESC_SCAN_CODE  EQU     1
  64. F1_SCAN_CODE   EQU     3BH
  65. F2_SCAN_CODE   EQU     3CH
  66.  
  67. PORT_A         EQU     60H
  68. PORT_B         EQU     61H
  69. COMMAND_PORT   EQU     20H
  70. EOI            EQU     20H
  71.  
  72. ;-------------------------;
  73.  
  74. BIOS_INT_9     DW      ?,?
  75.  
  76. NORMAL         EQU     07H
  77. INVERSE_BLUE   EQU     17H
  78. INVERSE        DB      70H
  79.  
  80. LAST_POS       DW      CHAR_START
  81.  
  82. LAST_HEAD      DW      BUFFER_START
  83. LAST_TAIL      DW      BUFFER_START
  84.  
  85. F1_FLAG        DB      FALSE
  86. ESC_FLAG       DB      FALSE
  87.  
  88. EXTENDED_CALL  EQU     10H
  89. KEY_SUPPORT    DB      0
  90. SUPPORT_FLAG   DB      0
  91.  
  92. HEAD           DB      "Head",DN_ARROW
  93. TAIL           DB      "Tail",UP_ARROW
  94. ERASE          DB      5 DUP (SPACE)
  95.  
  96. INVALID_MSG    DB      "Keyboard Buffer not supported",CR,LF,"$"
  97.  
  98. MENU           LABEL   BYTE
  99.  
  100. DB   "Press any key to add to keyboard buffer",CR,LF
  101. DB   "Press F1 to retrieve a character from buffer",CR,LF,"$"
  102.  
  103. INT_16_MSG     DB      "Press F2 to toggle extended keyboard "
  104.                DB      "support; Support is now: ",CR,LF,"$"
  105. INT_16_LEN     EQU     $ - INT_16_MSG - 3
  106.  
  107. ESC_MSG        DB      "Press Esc to Exit$"
  108.  
  109. INACTIVE_MSG   DB      "INACTIVE  "
  110. INACTIVE_LEN   EQU     $ - INACTIVE_MSG - 2
  111.  
  112. BUFFER_WINDOW  LABEL   BYTE
  113.  
  114. DB             201,7 DUP(7 DUP(205),203),7 DUP(205),187
  115. DB             2 DUP(186,7 DUP(7 DUP(32),186),7 DUP(32),186)
  116. DB             200,7 DUP(7 DUP(205),202),7 DUP(205),188
  117.  
  118.  
  119. ;              CODE AREA
  120. ;              ---------
  121. MAIN           PROC    NEAR
  122.  
  123. ;--------------------------------------;
  124. ; Exit with non-support message if     ;
  125. ; original keyboard buffer not active. ;
  126. ;--------------------------------------;
  127.  
  128.   MOV     AX,SEG BIOS_DATA        ;Point to BIOS data.
  129.   MOV     ES,AX
  130.   CMP     ES:KBD_BUFF_START,BUFFER_START   ;Original buffer active?
  131.   JZ      GOOD_BUFFER                      ;If yes, continue.
  132.   MOV     DX,OFFSET INVALID_MSG   ;Else, display invalid message.
  133.   CALL    PRINT_STRING
  134.   MOV     AX,4C01H                ;Exit with error level 1.
  135.   JMP     TERMINATE
  136.  
  137. GOOD_BUFFER:   
  138.   CLD                             ;All string moves forward.
  139.   CALL    VIDEO                   ;Check the video equip. and CLS.
  140.  
  141.   MOV     DX,OFFSET COPYRIGHT     ;Display copyright.
  142.   CALL    PRINT_STRING
  143.   MOV     DX,OFFSET MENU
  144.   CALL    PRINT_STRING
  145.  
  146. ;----------------------------------------------------------;
  147. ; BIOS Tech Ref recommended 101-keyboard detection method. ;
  148. ;----------------------------------------------------------;
  149.  
  150.   MOV     DL,2                    ;Make two attempts to write
  151.   MOV     CX,0FFFFH               ; char/scan code of FFFFh to
  152. KBD_WRITE:   
  153.   MOV     AH,05H                  ; buffer via extended keyboard
  154.   INT     16H                     ; write funtion.
  155.   OR      AL,AL                   ;Was it successful?
  156.   JZ      RETRIEVE                ;If yes, extended supported.
  157.   MOV     AH,10H                  ;Else, maybe buffer full. Make
  158.   INT     16H                     ; room by retrieving char.
  159.   DEC     DL                      ;Is this the second time through?
  160.   JNZ     KBD_WRITE               ;If no, try to write again.
  161.   JMP     SHORT MENU_END          ;Else, done here; no support.
  162.  
  163. RETRIEVE:   
  164.   MOV     CX,15                   ;Try 15 times to retrieve
  165. SEARCH_KBD:  
  166.   MOV     AH,11H                  ; the FFFFh scan code.
  167.   INT     16H                     ;Buffer empty?
  168.   JZ      MENU_END                ;If yes, no support.
  169.   MOV     AH,10H                  ;Else, extended Kbd read.
  170.   INT     16H
  171.   CMP     AX,0FFFFH               ;Did we find the FFFFh?
  172.   JZ      EXTENDED_KBD            ;If yes, extended Kbd support.
  173.   LOOP    SEARCH_KBD              ;Else, search all 15 possible.
  174.   JMP     SHORT MENU_END          ;If feel through, no support.
  175.  
  176. ;-------------------------------------------------------------;
  177. ; If 101-keyboard exists, display additional support message. ;
  178. ;-------------------------------------------------------------;
  179.  
  180. EXTENDED_KBD:
  181.   MOV     SUPPORT_FLAG,1          ;Flag that supported.
  182.   MOV     DX,OFFSET INT_16_MSG    ;Display support message.
  183.   CALL    PRINT_STRING
  184.   CALL    EXTENDED                ;Display "ACTIVE" message.
  185.   MOV     DX,600H                 ;Move cursor to next line.
  186.   CALL    SET_CURSOR
  187.  
  188. ;-----------------------------------------------------;
  189. ; Display Esc message regardless of keyboard support. ;
  190. ;-----------------------------------------------------;
  191.  
  192. MENU_END:   
  193.   MOV     DX,OFFSET ESC_MSG       ;Display Esc message.
  194.   CALL    PRINT_STRING
  195.  
  196. ;----------------------------------------------------------;
  197. ; Display my visual interpretation of the keyboard buffer. ;
  198. ;----------------------------------------------------------;
  199.  
  200.   MOV     DX,BOX_ROW SHL 8 + BOX_COL  ;Start pos. of first box.
  201.   MOV     BL,INVERSE                  ;Display in inverse color.
  202.   MOV     CX,2                        ;Two boxes to display.
  203.  
  204. NEXT_BOX:   
  205.   PUSH    CX                          ;Save counter.
  206.   MOV     CX,4                        ;Four rows per box.
  207.   MOV     SI,OFFSET BUFFER_WINDOW     ;Point to buffer box.
  208.  
  209. NEXT_ROW:    
  210.   PUSH    CX                      ;Save counter.
  211.   MOV     CX,65                   ;65 columns per box.
  212. NEXT_BYTE:   
  213.   LODSB                           ;Get a byte
  214.   CALL    WRITE_CHAR              ; and display it.
  215.   LOOP    NEXT_BYTE               ;Repeat for all 65 columns.
  216.   MOV     DL,BOX_COL              ;Box column start
  217.   INC     DH                      ;Next row.
  218.   POP     CX                      ;Retrieve counter.
  219.   LOOP    NEXT_ROW                ;Repeat for all four rows.
  220.  
  221.   MOV     DX,(BOX_ROW + BOX_TWO) SHL 8 + BOX_COL ;2nd box start.
  222.   POP     CX                                     ;Retrieve counter.
  223.   LOOP    NEXT_BOX                ;Do both boxes.
  224.  
  225.   CALL    INITIALIZE              ;Fill the visual buffer.
  226.  
  227. ;-------------------------;
  228. ; Hook our INT 9 handler. ;
  229. ;-------------------------;
  230.  
  231.   MOV     AX,3509H                ;Get keyboard interrupt.
  232.   INT     21H
  233.   MOV     BIOS_INT_9[0],BX        ;Save old interrupt.
  234.   MOV     BIOS_INT_9[2],ES
  235.  
  236.   MOV     DX,OFFSET KEYVIEW_INT_9 ;Install new interrupt.
  237.   MOV     AX,2509H
  238.   INT     21H
  239.  
  240.   MOV     AX,SEG BIOS_DATA        ;Point to BIOS data area.
  241.   MOV     ES,AX
  242.  
  243. ;--------------------------------------------------------------;
  244. ; Ready for action.  Hide the cursor off screen so it's not    ;
  245. ; distracting.  Retrieve characters if F1 pressed.  Toggle     ;
  246. ; extended support on/off if F2 pressed.  Clear visual buffer  ;
  247. ; if Ctrl Break detected.  Exit if Esc pressed.                ;
  248. ;--------------------------------------------------------------;
  249.  
  250. GET_KEY:    
  251.   MOV     DX,1900H                ;Hide the cursor off screen
  252.   CALL    SET_CURSOR              ; on row 25.
  253. CK_F1:       
  254.   CMP     F1_FLAG,TRUE            ;Was F1 pressed?
  255.   JZ      CK_AVAILABLE            ;If yes, retrieve a character.
  256.  
  257.   MOV     AH,1                    ;This will extract extended
  258.   OR      AH,KEY_SUPPORT          ; codes if extended support
  259.   INT     16H                     ; is not active.
  260.  
  261.   CMP     SUPPORT_FLAG,2          ;F2 pressed and extended
  262.   JZ      DO_F2                   ; support?  If yes, toggle.
  263.  
  264.   CMP     ESC_FLAG,TRUE           ;Was Esc pressed?
  265.   JZ      EXIT                    ;If yes, exit.
  266.  
  267.   TEST    ES:BIOS_BREAK,10000000B ;Was Ctrl Break pressed?
  268.   JNZ     CTRL_BREAK              ;If yes, clear visual buffer.
  269.  
  270.   CLI                             ;No interrupts.
  271.   MOV     DI,ES:BUFFER_TAIL       ;Retrieve buffer tail and head.
  272.   MOV     SI,ES:BUFFER_HEAD
  273.   STI                             ;Interrupts OK now.
  274.  
  275.   MOV     BP,LAST_TAIL            ;Retrieve last tail.
  276.   CMP     DI,BP                   ;Has the tail moved?
  277.   JZ      CK_HEAD                 ;If no, check head.
  278.   MOV     LAST_TAIL,DI            ;Else, store new tail.
  279.   MOV     SI,OFFSET TAIL          ;Indicate tail moved
  280.   JMP     SHORT DO_BUFFER         ; and update visual buffer.
  281.  
  282. CK_HEAD:     
  283.   MOV     BP,LAST_HEAD            ;Retrieve last head.
  284.   MOV     DI,SI                   ;Assume head moved.
  285.   CMP     DI,BP                   ;Has head moved?
  286.   JZ      CK_F1                   ;If no, nothing to do; Check F1.
  287.  
  288.   MOV     SI,BP                   ;Else, next head position.
  289.   INC     SI
  290.   INC     SI
  291.   CMP     SI,BUFFER_END           ;If moved past end of buffer
  292.   JNZ     STORE_HEAD              ; circle to beginning of buffer.
  293.   MOV     SI,BUFFER_START
  294.  
  295. STORE_HEAD:  
  296.   MOV     LAST_HEAD,SI            ;Store new head.
  297.   MOV     SI,OFFSET HEAD          ;Indicate head has moved
  298.  
  299. DO_BUFFER:   
  300.   CALL    UPDATE_BUFFER           ; and update visual buffer.
  301.   JMP     SHORT GET_KEY           ;Next key.
  302.  
  303. CK_AVAILABLE:
  304.   MOV     F1_FLAG,FALSE           ;Reset F1 flag.
  305.   MOV     AH,1                    ;Get keystroke status
  306.   OR      AH,KEY_SUPPORT          ; add in type keyboard support.
  307.   INT     16H
  308.   JNZ     DO_F1                   ;If key available, get it.
  309.  
  310.   MOV     AX,0E07H                ;Else, beep speaker.
  311.   INT     10H
  312.   JMP     SHORT CK_F1             ;Done here.
  313.  
  314. DO_F1:       
  315.   CALL    DISPLAY_CHAR            ;Retrieve character from buffer
  316.   JMP     GET_KEY                 ; and display; next key.
  317.  
  318. DO_F2:       
  319.   CALL    EXTENDED                ;Toggle extended support.
  320.   MOV     SUPPORT_FLAG,1          ;Reset support flag.
  321.   JMP     GET_KEY                 ;Next key.
  322.  
  323. CTRL_BREAK:  
  324.   AND     ES:BIOS_BREAK,NOT 80H   ;Reset Ctrl Break bit.
  325.   CALL    INITIALIZE              ;Clear the visual buffer.
  326.   JMP     GET_KEY                 ;Next key.
  327.  
  328. ;---------------------------------------------------------;
  329. ; Clear the buffer by setting head = tail.  Clear screen. ;
  330. ; Restore INT 9.                                          ;
  331. ;---------------------------------------------------------;
  332.  
  333. EXIT:       
  334.   CLI                                   ;No interrupts.
  335.   MOV     ES:BUFFER_HEAD,BUFFER_START   ;Set head = buffer start.
  336.   MOV     ES:BUFFER_TAIL,BUFFER_START   ;Set tail = buffer start.
  337.   STI                                   ;Interrupts OK now.
  338.  
  339.   CALL    VIDEO                   ;Clear screen.
  340.  
  341.   MOV     DX,BIOS_INT_9[0]        ;Restore old INT 9.
  342.   MOV     DS,BIOS_INT_9[2]
  343.   MOV     AX,2509H
  344.   INT     21H
  345.  
  346.   MOV     AX,4C00H                ;Error level zero.
  347. TERMINATE:
  348.   INT     21H
  349.  
  350. MAIN           ENDP
  351.  
  352.                ;***************;
  353.                ;* SUBROUTINES *;
  354.                ;***************;
  355.  
  356. ;-----------------------------------------------------;
  357. ; This subroutine will toggle the extended keyboard   ;
  358. ; support on/off and display ACTIVE/INACTIVE message. ;
  359. ;-----------------------------------------------------;
  360.  
  361. EXTENDED       PROC    NEAR
  362.  
  363.   MOV     DX,4 SHL 8 + INT_16_LEN    ;Row 4; column at end of msg.
  364.   MOV     CX,INACTIVE_LEN            ;Length of message.
  365.   MOV     BL,NORMAL                  ;Normal attribute.
  366.   MOV     SI,OFFSET INACTIVE_MSG     ;Assume INACTIVE msg.
  367.   XOR     KEY_SUPPORT,EXTENDED_CALL  ;Toggle support.
  368.   JZ      DISPLAY_EXT                ;If zero, guessed right.
  369.   INC     SI                         ;Else, bump pointer past "IN".
  370.   INC     SI
  371.  
  372. DISPLAY_EXT:
  373.   LODSB                              ;Display the message.
  374.   CALL    WRITE_CHAR
  375.   LOOP    DISPLAY_EXT
  376.   RET
  377.  
  378. EXTENDED       ENDP
  379.  
  380. ;------------------------------------------------------;
  381. ; All sixteen positions of visual buffer are updated   ;
  382. ; when program starts and when Ctrl Break is detected. ;
  383. ;------------------------------------------------------;
  384.  
  385. INITIALIZE     PROC    NEAR
  386.  
  387.   MOV     BP,LAST_TAIL            ;Retrieve last tail.
  388.   MOV     DI,ES:BUFFER_HEAD       ;Retrieve current head.
  389.   PUSH    DI                      ;Preserve last tail.
  390.   MOV     LAST_TAIL,DI            ;Make last tail = head.
  391.   MOV     SI,OFFSET TAIL          ;Point to tail msg.
  392.   CALL    UPDATE_BUFFER           ;Update the visual buffer.
  393.  
  394.   MOV     BP,LAST_HEAD            ;Retrieve last head.
  395.   MOV     AX,BP                   ;Save in AX
  396.  
  397. NEXT_INIT:   
  398.   PUSH    AX                      ;Preserve AX.
  399.   MOV     DI,BP                   ;Move head up one.
  400.   INC     DI
  401.   INC     DI
  402.   CMP     DI,BUFFER_END           ;If head = buffer end
  403.   JNZ     DO_INIT                 ; then head = buffer start.
  404.   MOV     DI,BUFFER_START
  405.  
  406. DO_INIT:     
  407.   MOV     SI,OFFSET HEAD          ;Point to head msg.
  408.   CALL    UPDATE_BUFFER           ;Update visual buffer.
  409.   MOV     BP,DI
  410.   POP     AX                      ;Retrieve last head.
  411.   CMP     BP,AX                   ;Did we do all 16 positions?
  412.   JNZ     NEXT_INIT               ;If not, continue until done.
  413.  
  414.   POP     DI                      ;Retrieve last tail.
  415.   MOV     LAST_HEAD,DI            ;Last head = last tail.
  416.   MOV     SI,OFFSET HEAD          ;Point to head msg.
  417.   CALL    UPDATE_BUFFER           ;Update visual buffer.
  418.  
  419.   RET
  420.  
  421. INITIALIZE     ENDP
  422.  
  423. ;----------------------------;
  424. ; This is the INT 9 handler. ;
  425. ;----------------------------;
  426.  
  427. KEYVIEW_INT_9  PROC    NEAR
  428.  
  429.   ASSUME  DS:NOTHING
  430.   STI                             ;Interrupts OK.
  431.   PUSH    AX                      ;AX will be destroyed; preserve.
  432.   IN      AL,PORT_A               ;Get the scan code.
  433.   CMP     AL,F1_SCAN_CODE         ;Is it F1 make?
  434.   JZ      RESET_MAKE              ;If yes, flag and reset KBD.
  435.   CMP     AL,F1_SCAN_CODE OR 80H  ;Else, is it F1 break?
  436.   JZ      RESET_BREAK             ;If yes, ignore.
  437.   CMP     AL,ESC_SCAN_CODE        ;Else, is it Esc?
  438.   JZ      ESC_EXIT                ;If yes, flag Esc.
  439.   CMP     SUPPORT_FLAG,1          ;Extended keyboard support?
  440.   JNZ     OLD_INT_9               ;If no, done here.
  441.   CMP     AL,F2_SCAN_CODE OR 80H  ;Else, is it F2 break?
  442.   JZ      RESET_BREAK             ;If yes, ignore.
  443.   CMP     AL,F2_SCAN_CODE         ;Else, is it F2 make?
  444.   JNZ     OLD_INT_9               ;If no, done here.
  445.  
  446.   MOV     SUPPORT_FLAG,2          ;Else, flag pressed.
  447.   JMP     SHORT RESET_BREAK       ;Reset the KBD.
  448.  
  449. ESC_EXIT:    
  450.   MOV     ESC_FLAG,TRUE           ;If Esc pressed, flag and exit.
  451.  
  452. OLD_INT_9:   
  453.   POP     AX                      ;Restore AX.
  454.   JMP     DWORD PTR BIOS_INT_9    ;Go to BIOS INT 9 routine.
  455.  
  456. ;------------------------------------------------------;
  457. ; If F1 or F2 pressed, don't let BIOS store character. ;
  458. ; Instead reset KBD and throw away the keystroke.      ;
  459. ;------------------------------------------------------;
  460.  
  461. RESET_MAKE:  
  462.   MOV     F1_FLAG,TRUE            ;Flag F1 pressed.
  463. RESET_BREAK: 
  464.   IN      AL,PORT_B               ;Retrieve Port B.
  465.   OR      AL,80H                  ;Turn bit 7 on to reset
  466.   JMP     $ + 2                   ;I/O delay.
  467.   OUT     PORT_B,AL               ;Reset KBD.
  468.   AND     AL,NOT 80H              ;Turn bit 7 back off.
  469.   JMP     $ + 2                   ;I/O delay.
  470.   OUT     PORT_B,AL               ;Restore port.
  471.  
  472.   CLI                             ;Interrupts off.
  473.   MOV     AL,EOI                  ;Send End Of Interrupt
  474.   OUT     COMMAND_PORT,AL         ; to 8259A PIC.
  475.  
  476.   POP     AX                      ;Restore AX.
  477.   IRET                            ;Interrupt return.
  478.   ASSUME  DS:_TEXT
  479.  
  480. KEYVIEW_INT_9  ENDP
  481.  
  482. ;-----------------------------------------------;
  483. ; When F1 is pressed, a character is retrieved  ;
  484. ; from the buffer and displayed.                ;
  485. ;-----------------------------------------------;
  486.  
  487. DISPLAY_CHAR   PROC    NEAR
  488.  
  489.   MOV     AX,LAST_POS             ;Get last char display column.
  490.   CMP     AL,78                   ;Was it column 78?
  491.   JBE     RESTORE_POS             ;If below or equal, OK.
  492.   MOV     CX,CHAR_START           ;Else, clear the line.
  493.   MOV     DX,CHAR_START + 78
  494.   MOV     BH,NORMAL
  495.   MOV     AX,600H
  496.   INT     10H
  497.   MOV     AX,CHAR_START           ;Start at beginning of line.
  498.  
  499. RESTORE_POS: 
  500.   MOV     DX,AX                   ;Cursor position in DX.
  501.   INC     AX                      ;Bump to new cursor position
  502.   MOV     LAST_POS,AX             ; and save for next time.
  503.   MOV     AH,0                    ;Retrieve character; include
  504.   OR      AH,KEY_SUPPORT          ; appropriate keyboard support.
  505.   INT     16H
  506.   MOV     BL,INVERSE              ;Display in inverse video.
  507.   CALL    WRITE_CHAR
  508.   RET
  509.  
  510. DISPLAY_CHAR   ENDP
  511.  
  512. ;------------------------------------;
  513. ; INPUT                              ;
  514. ;   BP = Last position.              ;
  515. ;   DI = New position.               ;
  516. ;   SI = OFFSET HEAD or OFFSET TAIL. ;
  517. ;------------------------------------;
  518.  
  519. UPDATE_BUFFER  PROC    NEAR
  520.  
  521.   MOV     DX,BP                   ;Last position in DX.
  522.   CALL    CURSOR_POS              ;Calculate cursor position.
  523.   PUSH    DX                      ;Preserve cursor position.
  524.  
  525.   ADD     DH,2                    ;Move two columns right.
  526.   MOV     AX,ES:[BP]              ;Retrieve last scan/char code.
  527.   MOV     BL,INVERSE              ;Display in inverse
  528.   CMP     SI,OFFSET TAIL          ; if tail moved.
  529.   JZ      DO_CHAR
  530.   MOV     BL,NORMAL               ;Else, head moved;display normal.
  531.  
  532. DO_CHAR:    
  533.   PUSH    DX                      ;Save cursor position.
  534.   CALL    SPACES                  ;Center char in top of box with
  535.   CALL    WRITE_CHAR              ; three spaces on either side.
  536.   CALL    SPACES
  537.  
  538.   POP     DX                      ;Retrieve cursor position.
  539.   INC     DH                      ;Next row.
  540.   XCHG    AL,AH                   ;Swap scan code and ASCII char.
  541.   PUSH    AX                      ;Preserve.
  542.   MOV     AL,SPACE                ;Display a space.
  543.   CALL    WRITE_CHAR
  544.   POP     BP                      ;Retrieve char/scan code.
  545.   CALL    HEX_OUTPUT              ;Display in hex.
  546.  
  547.   POP     DX                      ;Retrieve cursor position.
  548.   INC     DL                      ;Next column.
  549.   MOV     BL,NORMAL               ;Normal attribute.
  550.   CMP     SI,OFFSET HEAD          ;Erase either head or tail msg.
  551.   JZ      DO_ERASE
  552.   ADD     DH,5                    ;Tail at bottom of box.
  553.  
  554. DO_ERASE:    
  555.   PUSH    SI                      ;Save msg pointer.
  556.   MOV     SI,OFFSET ERASE         ;Erase old msg.
  557.   CALL    DISPLAY_POINT
  558.   MOV     DX,DI                   ;Move to new position.
  559.   CALL    CURSOR_POS
  560.   INC     DL                      ;Move right one column.
  561.   POP     SI
  562.   CMP     SI,OFFSET HEAD          ;Display either head or tail msg.
  563.   JZ      DO_POINTER
  564.   ADD     DH,5
  565. DO_POINTER:  
  566.   CALL    DISPLAY_POINT
  567.  
  568.   RET
  569.  
  570. UPDATE_BUFFER  ENDP
  571.  
  572. ;--------------------------;
  573.  
  574. SPACES         PROC    NEAR
  575.  
  576.   PUSH    AX                      ;Preserve AX.
  577.   MOV     CX,3                    ;Display three spaces.
  578.   MOV     AL,SPACE
  579. NEXT_SPACE:  
  580.   CALL    WRITE_CHAR
  581.   LOOP    NEXT_SPACE
  582.   POP     AX
  583.   RET
  584.  
  585. SPACES         ENDP
  586.  
  587. ;-----------------------------;
  588. ; INPUT                       ;
  589. ;   BP = Character/scan code. ;
  590. ;-----------------------------;
  591.  
  592. HEX_OUTPUT     PROC    NEAR
  593.  
  594.   MOV     CX,2                    ;Two codes to display.
  595. NEXT_NIBBLE:
  596.   PUSH    CX                      ;Preserve counter.
  597.   MOV     CX,204H                 ;4 positions/word; 4bits/char.
  598. ROTATE_HEX:  
  599.   ROL     BP,CL                   ;Move highest bits to lowest.
  600.   MOV     AX,BP                   ;Char/scan code in AX.
  601.   AND     AL,1111B                ;Mask off all but four lowest.
  602.   ADD     AL,"0"                  ;Convert to ASCII.
  603.   CMP     AL,"9"                  ;Is it alpha?
  604.   JLE     PRINT_HEX               ;If no, print it.
  605.   ADD     AL,7                    ;Else, adjust.
  606. PRINT_HEX:   
  607.   CALL    WRITE_CHAR              ;And write them.
  608.   DEC     CH                      ;Done all four positions?
  609.   JNZ     ROTATE_HEX              ;If no, get next.
  610.  
  611.   MOV     AL,SPACE                ;Delimit with a space.
  612.   CALL    WRITE_CHAR
  613.   POP     CX                      ;Do both char and scan code.
  614.   LOOP    NEXT_NIBBLE
  615.   RET
  616.  
  617. HEX_OUTPUT     ENDP
  618.  
  619. ;------------------------------;
  620. ; INPUT                        ;
  621. ;   SI points to pointer text. ;
  622. ;------------------------------;
  623.  
  624. DISPLAY_POINT  PROC    NEAR
  625.  
  626.   MOV     CX,5                    ;Five characters to pointer.
  627. NEXT_POINT:  
  628.   LODSB
  629.   CALL    WRITE_CHAR              ;Write them.
  630.   LOOP    NEXT_POINT
  631.   RET
  632.  
  633. DISPLAY_POINT  ENDP
  634.  
  635. ;--------------------------;
  636.  
  637. CURSOR_POS     PROC    NEAR
  638.  
  639.   SUB     DX,BUFFER_START         ;Difference = offset.
  640.   MOV     DH,BOX_ROW - 1          ;Point to starting row of box.
  641.   CMP     DL,16                   ;If offset less than 16 OK.
  642.   JB      GET_COLUMN
  643.   SUB     DL,16                   ;Else adjust offset.
  644.   ADD     DH,BOX_TWO              ;Point to second box.
  645. GET_COLUMN:  
  646.   SHL     DL,1                    ;Multiply by 4 to get cursor
  647.   SHL     DL,1                    ; column.
  648.   ADD     DL,BOX_COL + 1          ;Add offset of box start.
  649.   RET
  650.  
  651. CURSOR_POS     ENDP
  652.  
  653. ;-------------------------;
  654. ; INPUT                   ;
  655. ;   DX = cursor position. ;
  656. ;-------------------------;
  657.  
  658. SET_CURSOR:  
  659.   PUSH    AX                      ;Preserve AX.
  660.   XOR     BH,BH                   ;Page zero.
  661.   MOV     AH,2
  662.   INT     10H                     ;Set cursor position.
  663.   POP     AX                      ;Retrieve AX.
  664.   RET
  665.  
  666. ;-----------------------------;
  667. ; INPUT                       ;
  668. ;   DX = new cursor position. ;
  669. ;   AL = Character to write.  ;
  670. ;-----------------------------;
  671.  
  672. WRITE_CHAR     PROC    NEAR
  673.  
  674.   PUSH    AX                      ;Preserve AX and CX.
  675.   PUSH    CX
  676.   CALL    SET_CURSOR              ;Set cursor position.
  677.   MOV     CX,1                    ;One character to write.
  678.   MOV     AH,9
  679.   INT     10H
  680.   INC     DL
  681.   POP     CX                      ;Restore registers.
  682.   POP     AX
  683.   RET
  684.  
  685. WRITE_CHAR     ENDP
  686.  
  687.  
  688. ;--------------------------;
  689.  
  690. VIDEO          PROC    NEAR
  691.  
  692.   MOV     AH,0FH                  ;Retrieve current video mode.
  693.   INT     10H
  694.   CMP     AL,7                    ;Is it mono?
  695.   JZ      CLEAR_SCREEN            ;If yes, clear screen.
  696.   CMP     AL,2                    ;Is it black and white CGA?
  697.   JZ      CLEAR_SCREEN            ;If yes, clear screen.
  698.  
  699.   MOV     INVERSE,INVERSE_BLUE    ;Else, use color attributes.
  700.   MOV     AL,3                    ; and video mode CO80.
  701.  
  702. CLEAR_SCREEN:
  703.   XOR     AH,AH                   ;Set video mode.
  704.   INT     10H
  705.   MOV     AX,500H                 ;Set page zero.
  706.   INT     10H
  707.   RET
  708.  
  709. VIDEO          ENDP
  710.  
  711. ;--------------------------;
  712.  
  713. PRINT_STRING:
  714.   MOV     AH,9                    ;Print string via DOS.
  715.   INT     21H
  716.   RET
  717.  
  718.  
  719. _TEXT          ENDS
  720.                END     START
  721.