home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast2.iso / asmutil / d86bios4.zip / XBIOS.8 < prev    next >
Text File  |  1989-07-07  |  20KB  |  564 lines

  1. ;---------------
  2. ;  XBIOS test driver for BIOS.8
  3. ;---------------
  4.  
  5. ; Copyright 1987-88 Eric Isaacson.  All rights reserved.  Permission to
  6. ; copy and use this module is granted ONLY for machines registered for both
  7. ; the A86 assembler and the D86 debugger.
  8.  
  9. ; XBIOS is a program that exercises the BIOS.8 module.    I am providing it
  10. ; to assist those who wish to assist me in porting my D86 debugger to
  11. ; machines with non-IBM-compatible BIOSes.
  12. ;
  13. ; You may simulate the "B" switch of the D86 debugger by providing a digit
  14. ; in the command tail.  The digit must follow the single space following
  15. ; the XBIOS name; e.g. XBIOS 9 for Sirius/Victor.
  16.  
  17. ; You use this source module as follows:
  18. ;
  19. ;  1. Modify the module BIOS.8 to accommodate your specific machine.  You
  20. ;     should NOT need to modify this module, except possibly to add a
  21. ;     new HELP-key name just before the declcaration HELP_HELP below.
  22. ;
  23. ;  2. Assemble both modules with the command  A86 XBIOS.8 BIOS.8
  24. ;     (Command is provided as MAKX.BAT in this package; just type MAKX.)
  25. ;
  26. ;  3. Run the resulting program XBIOS.COM.  The program will run tests
  27. ;     of the BIOS function calls, and tell you about them.  If everything
  28. ;     looks good, then your BIOS.8 probably works.
  29. ;
  30. ;  4. The XBIOS program ends with an interactive mode, displaying keystrokes.
  31. ;     Please try every key on your keyboard, both with and without any
  32. ;     shift-style keys (ALT, SHIFT, CTRL, SECOND, etc.).  Write down the
  33. ;     codes that result.
  34. ;
  35. ;  5. Send me the codes you wrote down, together with your new BIOS.8.  I'll
  36. ;     incorporate it into D86.    Thanks!
  37.  
  38.  
  39.  
  40. ; This is a "quick-and-dirty" program.  It does not meet my standards for
  41. ; professionally-documented source code (no procedure-level comments).
  42.  
  43.  
  44. JMP MAIN
  45.  
  46. ALTF10_HELP:        ; HELP-key name for the IBM-PC
  47.   DB 'Alt-F10',0
  48. F11_HELP:        ; HELP-key name for the TI-PC
  49.   DB 'F11',0
  50. PF5_HELP:
  51.   DB 'Ctrl-PF5',0
  52. ALTJ_HELP:
  53.   DB 'Alt-J',0
  54. MENU_HELP:
  55.   DB 'Menu',0
  56.  
  57. ; If your machine uses a different HELP-KEY, declare its name above this line.
  58.  
  59. HELP_HELP:
  60.   DB 'HELP',0
  61.  
  62. SWITCH EQU B[$-'A']
  63.   DB 26 DUP 080
  64.  
  65. EGA_ATTRS   DW  04D1F     ; attribute bytes for EGA video
  66. CGA_ATTRS   DW  0F007     ; attribute bytes for CGA video
  67.  
  68. LAST_LINE    DW ?         ; variable stored by the D86 BIOS interface
  69. ENABLE_PORT  DW ?      ; BIOS specific, used by Wang for a port number
  70. V_FLAG         DB ?      ; debugger variable consulted by IBM BIOS_INIT
  71. WAVY_COUNT   DB ?      ; count of how many wavy messages have been output
  72.  
  73. ; DWB causes the initialization of alternating words and bytes
  74.  
  75. DWB MACRO #RX1L
  76.   DW #X
  77.   DB #AX
  78. #E2#EM
  79.  
  80. SKIP2 MACRO    ; skip over the following 2 opcode bytes
  81.   DB 03D       ; CMP AX,iw opcode will do the job
  82. #EM
  83.  
  84.  
  85. SCREEN_P EQU 08000  ; screen buffer is at 08000
  86.  
  87. ; The following are convenient prefix-abbreviations for returned key-codes.
  88.  
  89. CTRL EQU -040       ; e.g. CTRL'A'  -- WARNING CTRL'a' will be wrong!!
  90. FUNC EQU 59+111     ; e.g. FUNC 1 for the F1 function key
  91. SHIFT_F EQU 84+111  ; e.g. SHIFT_F 3 for the shifted F3 key
  92. CTRL_F EQU 94+111   ; e.g. CTRL_F 10 for the control-F10 key
  93. ALT_F EQU 104+111   ; e.g. ALT_F 4 for the Alt-F4 key
  94. ALT_N EQU 120+111   ; e.g. ALT_N 5 for the Alt-5 key
  95.  
  96. BIOS_CALLS:              ; pointers to BIOS-specific action routines
  97.   VID_COPY    DW MONO_COPY  ; video copy
  98.   VID_ATTR    DW IBM_ATTR   ; set attribute at DI to AL
  99.   VID_FIX    DW IBM_FIX    ; fix video screen
  100.   BIOS_BELL    DW IBM_BELL   ; ring bell
  101.   BIOS_KEY    DW IBM_KEY    ; fetch a keystroke
  102.   BIOS_SAVE     DW IBM_SAVE   ; save user's BIOS state (Sanyo only)
  103.   BIOS_RESTORE    DW IBM_RESTORE; restore the saved BIOS state (Sanyo only)
  104.   VIDEO_SEG    DW ?          ; pointer to physical video display segment
  105.   ATTR_BYTES    DW          ; hardware-dependent video codes
  106.    NORM_ATTR    DB 7          ; code for normal video display
  107.    REV_ATTR    DB 070          ; code for reversed-video display
  108. N_BIOS_CALLS EQU ($-BIOS_CALLS)/2
  109.  
  110.  
  111. ; CTRL_JUMPS defines the single-key commands recognized by the debugger.  Each
  112. ;   DW below is an address to be jumped to whenever the following DB byte is
  113. ;   taken as a single-key input by the debugger command processor.
  114.  
  115. CTRL EQU -040
  116.  
  117. CTRL_JUMPS:
  118.   DWB  F1_MSG,        FUNC 1
  119.   DWB  F2_MSG,        FUNC 2
  120.   DWB  F3_MSG,        FUNC 3
  121.   DWB  F4_MSG,        FUNC 4
  122.   DWB  F5_MSG,        FUNC 5
  123.   DWB  F6_MSG,        FUNC 6
  124.   DWB  F7_MSG,        FUNC 7
  125. N_FUNCS EQU ($-CTRL_JUMPS)/3
  126.  
  127. L1:                ; control-key functions start here
  128.   DWB  DOWN_MSG,    80+112
  129.   DWB  PGDN_MSG,    81+112
  130.   DWB  UP_MSG,        72+112
  131.   DWB  PGUP_MSG,    73+112
  132.   DWB  HOME_MSG,    71+112
  133.   DWB  SHF7_MSG, SHIFT_F 7
  134.   DWB  ALTF9_MSG,  ALT_F 9
  135. N_CONTROL_KEYS EQU ($-L1)/3
  136.  
  137.          DW F10_MSG
  138. SWITCH_KEY   DB FUNC 10   ; key code for FUNC 10 (switch screens)
  139.  
  140.          DW HELP_HELP
  141. HELP_KEY     DB ALT_F 10  ; key code for the debugger's HELP key
  142.  
  143.   DWB  0,        0FF     ; terminator for this table
  144.  
  145.  
  146.  
  147.  
  148.  
  149. MAIN:
  150.   CALL XBIOS_SWITCH     ; scan the command-tail switch, if any
  151.   CALL BIOS_INIT    ; initialize our specific BIOS
  152.   MOV DS,ES,SS        ; restore segment registers
  153.   CALL TEST_INIT    ; display the settings produced, prompt for key
  154.   CALL TEST_KEY_BELL    ; test the simple key input and bell functions
  155.   CALL TEST_VIDEO    ; test some simple video displays
  156.   CALL TEST_KEY_CODES    ; enter the interactive key-code display loop
  157.   MOV AX,04C00        ; MS-DOS codes for successful program exit
  158.   INT 33        ; exit back to the operating system
  159.  
  160.  
  161. FIRST_TESTING:
  162.   DB 'Survived BIOS_INIT.',0D,0A
  163.   DB 'Subdirectory character is set to "'
  164. SUBDIR_CHAR  DB '\'
  165.   DB '".',0D,0A
  166.   DB 'Video memory is at segment register value '
  167. VIDEO_DISPLAY:
  168.   DB 'xxxx.',0D,0A
  169.   DB 'The normal attribute byte is '
  170. NORM_DISP:
  171.   DB 'xx.',0D,0A
  172.   DB 'The reverse attribute byte is '
  173. REV_DISP:
  174.   DB 'xx.',0D,0A
  175.   DB 'The HELP key is labelled ',0
  176.  
  177. HELP_MSG     DW ALTF10_HELP
  178.  
  179. POST_HELP:
  180.   DB '.',0D,0A
  181.   DB 'Is this right?',0D,0A,0D,0A
  182.   DB 'First testing BIOS key input and bell-ringing.',0D,0A,0
  183.  
  184. TEST_INIT:        ; make initial display of BIOS variables
  185.   MOV BX,VIDEO_SEG    ; fetch the video segment register value
  186.   MOV DI,VIDEO_DISPLAY    ; point to it position in the display message
  187.   MOV AL,BH        ; fetch the high byte of the value
  188.   CALL HEX_AL        ; output the high byte
  189.   MOV AL,BL        ; fetch the low byte of the value
  190.   CALL HEX_AL        ; output the low byte
  191.   MOV DI,NORM_DISP    ; point to NORM_ATTR value in message
  192.   MOV AL,NORM_ATTR    ; fetch the value
  193.   CALL HEX_AL        ; put the hex value into the message
  194.   MOV DI,REV_DISP    ; point to REV_ATTR value in message
  195.   MOV AL,REV_ATTR    ; fetch the value
  196.   CALL HEX_AL        ; put the hex value into the message
  197.   MOV SI,FIRST_TESTING    ; point to the first message
  198.   CALL MESSAGE        ; output the message
  199.   MOV SI,HELP_MSG    ; point to the name of the HELP key
  200.   CALL MESSAGE        ; output the name
  201.   MOV SI,POST_HELP    ; point to the message after the HELP name
  202.   JMP MESSAGE        ; output the message
  203.  
  204. XBIOS_SWITCH:
  205.   MOV AX,[081]          ; fetch the command-tail switch, if any
  206.   CMP AL,0D             ; is there a command tail?
  207.   JE RET                ; return if not
  208.   MOV AL,AH
  209.   SUB AL,'0'            ; reduce digit to its binary value
  210.   JC RET                ; return if there was not a digit
  211.   MOV SWITCH'B',AL      ; there was a digit: set the B switch to its value
  212.   RET
  213.  
  214.  
  215. VID_TEST_MSG:
  216.   DB 'Now we''ll output directly to video memory.',0D,0A
  217.   DB 'Type any two keys--',0D,0A
  218.   DB 'The screen will go blank after the first keystroke.',0D,0A,0
  219.  
  220. ALPHABET_MSG:
  221.   DB 'Now letters A to X go down the left.',0
  222. H_MSG:
  223.   DB 'Reverse video on the H.',0
  224. AFTER_M_MSG:
  225.   DB 'Reverse video in second character beyond the M.',0
  226.  
  227. H_SPOT EQU  ('H'-'A') * 160
  228. AFTER_M_SPOT EQU ('M'-'A') * 160 + 4
  229.  
  230. TEST_VIDEO:
  231.   MOV SI,VID_TEST_MSG   ; point to the "Now testing video" message
  232.   CALL MESSAGE        ; output the message
  233.   CALL KEY_ONLY     ; take a keystroke
  234.   CALL FIRST_FILL    ; blank the screen
  235.   CALL GET_KEY        ; take another keystroke
  236.   CALL ALPHA_LINES    ; put out the alphabet along the side
  237.   MOV SI,ALPHABET_MSG    ; point to message telling about it
  238.   CALL TOP_LINE     ; output the message
  239.   CALL REFRESH        ; send it all to the video
  240.   CALL GET_KEY        ; take another key
  241.   MOV SI,H_MSG        ; point to cursor-on-H message
  242.   CALL TOP_LINE     ; output the message
  243.   CALL REFRESH        ; refresh the video memory
  244.   MOV ES,VIDEO_SEG    ; point to the video segment
  245.   MOV DI,H_SPOT         ; point to "H" character within that segment
  246.   MOV AL,REV_ATTR    ; load the reverse-attribute byte
  247.   CALL VID_ATTR     ; output the byte to the video segment
  248.   MOV ES,SS        ; restore ES
  249.   CALL GET_KEY        ; take another keystroke
  250.   MOV SI,AFTER_M_MSG    ; point to cursor-after-M message
  251.   CALL TOP_LINE     ; output the message
  252.   CALL REFRESH        ; refresh the video memory
  253.   MOV ES,VIDEO_SEG    ; point to the video segment
  254.   MOV DI,H_SPOT     ; point to the previous cursor position in segment
  255.   MOV AL,NORM_ATTR    ; load normal attribute
  256.   CALL VID_ATTR     ; cancel the previous cursor output
  257.   MOV DI,AFTER_M_SPOT    ; point to the new cursor position
  258.   MOV AL,REV_ATTR    ; load reverse-attribute byte
  259.   CALL VID_ATTR     ; output the new cursor
  260.   MOV ES,SS        ; restore ES
  261. GET_KEY:
  262.   CALL BIOS_RESTORE
  263.   CALL BIOS_KEY
  264.   RET
  265.  
  266.  
  267. PLEASE_TYPE:
  268.   DB 'Please type any key.',0D,0A,0
  269. KEY_ONLY_MSG:
  270.   DB 'The BIOS returned hex code '
  271. KEY_ONLY_HEXCODE:
  272.   DB 'xx.',0D,0A,0
  273.  
  274. KEY_ONLY:
  275.   MOV SI,PLEASE_TYPE      ; point to "Please type any key"
  276.   CALL MESSAGE            ; output "Please type any key"
  277.   MOV DI,KEY_ONLY_HEXCODE ; output goes to the key-value report
  278.   MOV SI,KEY_ONLY_MSG      ; point to start of key-value report
  279.   CALL GET_KEY          ; fetch a keystroke from the BIOS
  280.   CALL HEX_AL          ; place the hex code into the message
  281. MESSAGE:          ; output null-terminated SI-message to standard out
  282.   PUSH BX,CX,DX       ; save registers across call
  283.   MOV DX,SI          ; MS-DOS wants the message pointer in DX
  284. L1:              ; loop here to scan for the terminator
  285.   LODSB           ; fetch a string byte
  286.   TEST AL          ; is it the zero terminator?
  287.   JNZ L1          ; loop if not
  288.   LEA CX,[SI-1]       ; point CX to the terminator byte
  289.   SUB CX,DX          ; compute the number of characters in the message
  290.   MOV AH,040          ; MS-DOS function number for WRITE
  291.   MOV BX,1          ; handle number for standard output is 1
  292.   INT 33          ; call MS-DOS to make the output
  293.   POP DX,CX,BX          ; restore clobbered registers
  294.   RET
  295.  
  296.  
  297.  
  298. NOW_BELL:
  299.   DB 'Now we''re using BIOS to ring the bell...',0D,0A,0
  300. HEAR_IT?:
  301.   DB 'Did you hear it?',0D,0A,0
  302.  
  303. TEST_KEY_BELL:        ; take 4 test keystrokes
  304.   CALL KEY_ONLY     ; take key without bell
  305.   CALL KEY_ONLY     ; take second key, without bell
  306.   CALL KEY_BELL     ; take a key then ring the bell
  307. KEY_BELL:        ; prompt for key, then ring the bell
  308.   CALL KEY_ONLY     ; prompt for and take a keystroke
  309.   MOV SI,NOW_BELL    ; point to bell message
  310.   CALL MESSAGE        ; put out the bell message
  311.   CALL BIOS_BELL    ; ring the bell
  312.   MOV SI,HEAR_IT?    ; point to the post-bell message
  313.   JMP MESSAGE        ; output the post-bell message
  314.  
  315.  
  316.  
  317. ; REFRESH updates the console screen to the desired contents, as indicated by
  318. ;   the SCRBASE buffer.  The buffer is updated to show that the actual screen
  319. ;   contents matches the desired contents.
  320.  
  321. REFRESH:
  322.   PUSH BX,CX,DX,BP,SI,DI,ES,DS ; preserve all registers but AX
  323.   MOV ES,VIDEO_SEG           ; we will copy to the screen-segment
  324.   MOV AH,NORM_ATTR      ; characters will have the normal attribute
  325.   MOV SI,SCREEN_P      ; source pointer is our screen buffer
  326.   SUB DI,DI          ; offset of the screen is zero
  327.   MOV BL,24          ; BL will count down lines
  328. D86_LINES EQU B[$-1]
  329.   MOV CH,0          ; CX will always hold byte counts
  330. L1:              ; main loop for actual vs. desired comparison
  331.   MOV CL,80          ; count number of characters in a line
  332.   CALL VID_COPY       ; copy this line to the video buffer
  333.   OR SI,0FF          ; advance SI to the end of this buffer-page
  334.   INC SI          ; bump SI to the beginning of the next page
  335.   DEC BL          ; count down lines
  336.   JNZ L1          ; loop if there are more lines
  337.   POP DS,ES,DI,SI,BP,DX,CX,BX    ; restore all the registers
  338.   RET
  339.  
  340.  
  341.  
  342. ; This section of code defines the message-displays for the control keys.
  343.  
  344. MSG MACRO
  345. #1_MSG:
  346.   DB '#1',0
  347. #EM
  348.  
  349. MSG F1
  350. MSG F2
  351. MSG F3
  352. MSG F4
  353. MSG F5
  354. MSG F6
  355. MSG F7
  356. MSG F10
  357. MSG DOWN
  358. MSG PGDN
  359. MSG PGUP
  360. MSG UP
  361. MSG HOME
  362. MSG SHF7
  363. MSG ALTF9
  364.  
  365. ; HEX_AL outputs to DI-pointed memory the 2-digit hex number representing
  366. ;   the value of AL.
  367.  
  368. BINHEX_AL  MACRO
  369.   ADD AL,090H        ; these 4 lines convert AL into an ASCII hex digit,
  370.   DAA            ;     in an outrageously clever and incomprehensible
  371.   ADC AL,040H        ;     fashion!!!  (I got the 8080 version of this out
  372.   DAA            ;     of an early BYTE magazine.)
  373. #EM
  374.  
  375. HEX_AL:
  376.   AAM 16        ; unpack AL into nibbles AH and AL
  377.   CALL >L3        ; swap nibbles, then output new low nibble
  378. L3:            ; call here to output nibble AH
  379.   XCHG AL,AH        ; swap the nibble into AL
  380.   BINHEX_AL        ; convert AL to a hex digit
  381.   STOSB         ; output the digit
  382.   RET
  383.  
  384.  
  385.  
  386. FIRST_FILL:          ; fill the video screen with its first contents
  387.   MOV DI,SCREEN_P      ; point to our screen image
  388.   MOV CX,(24 BY 0)/2      ; load the number of words in the image buffer
  389.   SUB AX,AX          ; we will zero-fill the buffer
  390.   REP STOSW          ; buffer is initialized to all-zeroes
  391.   MOV AL,' '              ; now load a blank
  392.   CALL FILL_LINES      ; fill the character line-buffers with blanks
  393.   CALL VID_FIX          ; insure that this first screen was actually sent
  394.   CALL REFRESH          ; send our screen buffer to video memory
  395.   RET
  396.  
  397.  
  398.  
  399. ALPHA_LINES:          ; put alphabet A to X down the left side
  400.   MOV DI,SCREEN_P      ; point to the upper left corner
  401.   MOV CX,24          ; load the lines count
  402.   MOV AL,'A'              ; load the first letter
  403. L1:              ; loop here to output each letter
  404.   STOSB           ; output the letter
  405.   INC AX          ; increment to the next letter
  406.   ADD DI,255          ; advance output pointer to the next line
  407.   LOOP L1          ; loop to output the next letter
  408.   RET
  409.  
  410.  
  411.  
  412. FILL_LINES:          ; fill all 24 image-lines with AL
  413.   MOV DI,SCREEN_P      ; point to the start of the image-buffer
  414.   MOV BL,24          ; number of lines in the buffer
  415. L1:              ; loop here for each line
  416.   CALL FILL_LINE      ; fill the line with AL
  417.   DEC BL          ; count down lines
  418.   JNZ L1          ; loop to fill the next line
  419.   RET
  420.  
  421.  
  422.  
  423. FILL_LINE:          ; fill the DI-pointed line with AL, advance DI
  424.   MOV CX,80          ; number of characters in the line
  425.   REP STOSB          ; fill the line
  426.   ADD DI,256-80       ; advance output pointer to the next line buffer
  427.   RET
  428.  
  429.  
  430.  
  431. PRESS_KEY:
  432.   DB '   Press any key',0
  433.  
  434. TOP_LINE:                 ; put SI-message and "press key" on top line
  435.   MOV DI,SCREEN_P+3      ; point to the fourth character of the top line
  436.   CALL COPY_STRING        ; output the caller's SI-pointed message
  437.   MOV SI,PRESS_KEY        ; now point to our "press key" message
  438. COPY_LINE:
  439.   CALL COPY_STRING        ; output the "press key" message
  440.   MOV CX,DI          ; copy the beyond-output pointer to CX
  441.   MOV CL,80          ; advance the pointer to the end of the top line
  442.   SUB CX,DI          ; calculate the number of trailing bytes in the line
  443.   MOV AL,' '              ; load blank
  444.   REP STOSB          ; blank-fill the trailing bytes
  445.   RET
  446.  
  447.  
  448.  
  449. ALL_KEYS:
  450.   DB 'Now try out all possible keystrokes.',0
  451. CAP_Q:
  452.   DB 'Capital Q exits program; capital T trashes the screen.',0
  453. TRASH_MESSAGE:
  454.   DB 'The message is output via MS_DOS.',0D,0A
  455.   DB 'It will roll the screen, thereby trashing the display.',0D,0A
  456.   DB 'Type capital-F to fix the screen if it is trashed.',0D,0A,0
  457. KNOWN_MSG:
  458.   DB 'I recognize that function key, its name is '
  459. KNOWN_TAIL:
  460.   DB '               ',0
  461. UNKNOWN_MSG:
  462.   DB 'That key code is not in my table.  Its value is '
  463. UNKNOWN_HEXCODE:
  464.   DB 'xx',0
  465. DISPLAYING_MSG:
  466.   DB 'Displayable character was typed: the character is "'
  467. DISPLAYING_CHAR DB 'x"',0
  468.  
  469. TEST_KEY_CODES:       ; interactive routine for displaying key codes
  470.   MOV SI,ALL_KEYS      ; point to the main prompting message
  471.   MOV DI,SCREEN_P+3      ; point to the location in our buffer for message
  472.   CALL COPY_LINE      ; output the first line of the message
  473.   MOV SI,CAP_Q          ; point to second line of message
  474.   MOV DI,SCREEN_P+0103      ; point to location in buffer for that message
  475.   CALL COPY_LINE      ; output the second line
  476. L1:              ; loop here for each keystroke
  477.   CALL REFRESH          ; refresh the video screen
  478.   CALL GET_KEY          ; take a keystroke
  479.   CMP AL,'Q'              ; is it the exiting capital-Q?
  480.   JE RET          ; if yes then exit
  481.   CMP AL,'T'              ; is it the TRASH command?
  482.   JE >L6          ; jump if yes
  483.   CMP AL,'F'              ; is it the FIX command?
  484.   JE >L7          ; jump if yes
  485.   MOV BL,AL          ; copy character to BL for WAVY-function
  486.   CMP AL,' '              ; is the character a control character?
  487.   JB >L5          ; jump if yes
  488.   CMP AL,07E          ; is the character above the displaying range?
  489.   JA >L5          ; jump if yes
  490.   MOV DISPLAYING_CHAR,AL  ; character is displayable-- put it into message
  491.   MOV SI,DISPLAYING_MSG   ; point to the displayable message
  492.   JMP >L4          ; jump to propagate the message
  493.  
  494. L5:              ; keystroke is not a displayable character
  495.   MOV DI,CTRL_JUMPS+2      ; point to our table of function keys
  496. L2:              ; loop here to search each entry of function table
  497.   CMP B[DI],0FF       ; is the table exhausted?
  498.   JE >L3          ; jump if yes, key not in table
  499.   SCASB           ; does our key match the table entry?
  500.   LEA DI,[DI+2]       ; advance table pointer in case not
  501.   JNE L2          ; loop if not
  502.   MOV SI,[DI-5]       ; the key matches-- fetch the pointer from that record
  503.   MOV DI,KNOWN_TAIL      ; point to the end of the known-message
  504.   CALL COPY_STRING        ; tack the key's name onto the known-message
  505.   MOV AL,0          ; load terminator
  506.   STOSB           ; null-terminate the known-message
  507.   MOV SI,KNOWN_MSG      ; point to the start of the known-message
  508.   JMP >L4          ; jump to propagate the message
  509.  
  510. L3:              ; keystroke was not found in the function table
  511.   MOV DI,UNKNOWN_HEXCODE  ; point to hex-display part of unknown-message
  512.   CALL HEX_AL          ; output our keycode as hex digits
  513.   MOV SI,UNKNOWN_MSG      ; point to the start of the unknown message
  514. L4:              ; common output point
  515.   CALL WAVY_MESSAGES      ; output the SI-pointed message in a wavy display
  516.   JMP L1          ; loop to take another keystroke
  517.  
  518. L6:              ; capital T is seen
  519.   MOV SI,TRASH_MESSAGE      ; point to our message that trashes the screen
  520.   CALL MESSAGE          ; trash the screen with the message
  521.   CALL BIOS_SAVE
  522.   JMP L1          ; loop to take another keystroke
  523.  
  524. L7:              ; capital F is seen
  525.   CALL VID_FIX          ; fix up the trashed screen
  526.   JMP L1          ; loop to take another keystroke
  527.  
  528.  
  529.  
  530. COPY_STRING:          ; copy SI-pointed string to DI
  531.   LODSB           ; load the first character
  532. L1:              ; loop here for each nonzero character
  533.   STOSB           ; output the character
  534.   LODSB           ; fetch the next character
  535.   TEST AL          ; is it the terminating zero?
  536.   JNZ L1          ; loop if not
  537.   RET
  538.  
  539.  
  540. WAVY   DB  3,4,5,6,7,6,5,4
  541.  
  542. WAVY_MESSAGES:          ; make 20 copies of SI-message in a wavy pattern
  543.   INC WAVY_COUNT      ; increment display count
  544.   MOV DI,SCREEN_P+0404      ; point to the first line of the wavy display
  545.   MOV BH,20          ; load the count of lines to be output
  546. L1:              ; loop here to output each line
  547.   MOV CX,DI          ; fetch the output pointer
  548.   MOV CL,CH          ; low byte tells us a reltive line number
  549.   ADD CL,BL          ; add in character code, just to mix things up
  550.   SUB CL,WAVY_COUNT      ; now a repeat of same key will make waves
  551.   AND CX,7          ; waviness will have a period of 8 lines
  552.   XCHG BX,CX          ; swap the line-index into BX, for addressing
  553.   MOV BL,WAVY[BX]      ; translate line-index into an indetation count
  554.   XCHG CX,BX          ; swap the count back into CX
  555.   MOV AL,' '              ; load blank
  556.   REP STOSB          ; indent the message-- this creates the waviness
  557.   PUSH SI          ; save the message pointer for the next line
  558.   CALL COPY_LINE      ; copy the message to this line, with trailing blanks
  559.   POP SI          ; restore the message pointer
  560.   ADD DI,260-80       ; advance output to the next line
  561.   DEC BH          ; count down lines
  562.   JNZ L1          ; loop to output the next line
  563.   RET
  564.