* Keyboard Buffer Routines¢*¢* Written by Nancy A. Durgin¢*¢* Loads into page 6¢* Call from BASIC with X=USR(1536)¢*¢***********************************************************¢* ¢* This program sets up a keyboard buffer and associated ¢* handler routines. The vector to the Keyboard interrupt ¢* routine (VKEYBD) is changed to transfer control to a ¢* new routine, which stores characters that are 'typed ¢* ahead' into a 60 character buffer. A VBLANK routine ¢* checks to see if the current character (in CH - $02FC)¢* has been processed, and if it has, moves the next ¢* character out of the buffer.¢*¢***********************************************************¢*¢* SYSTEM EQUATES¢*¢KBCODE = $D209 ;Code for the key just pressed¢CH1 = $02F2 ;Code for last key pressed¢CH = $02FC ;Key waitng to be processed by E:¢KEYDEL = $02F1 ;Keyboard "debounce" counter¢ATRACT = $004D ;Attract mode counter¢SRTIMR = $022B ;Key Auto-repeat counter¢VVBLKI = $0222 ;Vector to VBLANKI routines ¢SYSVBV = $E45F ;Vector to system VBLANK routines¢VKEYBD = $0208 ;Vector to keybd intrupt routine¢SSFLAG = $02FF ;Screen STOP/START flag ¢*¢* PROGRAM EQUATES¢*¢BUF = $CB ;Contains address of buffer¢BUFIN = $CD ;IN pointer for buffer ¢ ;points to next free location¢BUFOUT = $CE ;OUT pointer for buffer¢ ;points to next data byte¢BUFLEN = $3C ;Buffer length = 60¢CTRL1 = $9F ;Keycode for CTRL-1¢CTRL0 = $B2 ;Keycode for CTRL-0¢*¢* INITIALIZATION ROUTINE¢*¢* Initializes the routine by placing the correct values in¢* the PAGE ZERO locations, and by substituting program ¢* vector addresses for the system keyboard interrupt and ¢* VBLANK handlers.¢*¢ ORG $0600¢INIT PLA ;Remove argument count from stack¢ LDA #$00 ¢ STA BUFIN ;BUFIN=0¢ STA BUFOUT ;BUFOUT=0¢ LDA #LOW BUFFER¢ STA BUF ;Store buffer address¢ LDA #HIGH BUFFER¢ STA BUF+1¢ LDA #LOW KEYVB ;LO byte of new VBLANK routine¢ STA VVBLKI ;Store at vectr address¢ LDA #HIGH KEYVB ;HI byte¢ STA VVBLKI+1¢ LDA #LOW KEYINT ;LO byte of new handler¢ STA VKEYBD ;Store at vector address¢ LDA #HIGH KEYINT ;HI byte¢ STA VKEYBD+1¢ RTS ;RETURN¢*¢* KEYBOARD INTERRUPT HANDLER ROUTINE¢*¢* New handler for keyboard interrupts. This routine does¢* everything the old OS handler did, except that it stores¢* new character values in the buffer, instead of directly¢* into location CH.¢* If this routine detects a CTRL-0, it resets the buffer by¢* setting the IN and OUT pointers to 0, and putting an $FF ¢* in location CH.¢*¢KEYINT TYA ;Save Y register¢ PHA¢ LDA KBCODE ;Get internal code of key¢ CMP CH1 ;Compare to last key pressed¢ BNE NOTSAME ;Skip debounce routine¢ LDA KEYDEL ;Load timer value¢ BNE EXIT ;Treat this code as a bounce¢NOTSAME LDA KBCODE ;Get code again¢ CMP #CTRL1 ;See if it is a CTRL-1¢ BNE NCTRL1 ;Skip if not a CTRL-1¢ LDA SSFLAG ;Load STOP/START flag¢ EOR #$FF ;Reverse flag status¢ STA SSFLAG ;Store new flag value¢ BCS EXIT ;Don't process key¢NCTRL1 CMP #CTRL0 ;See if it is a CTRL-0¢ BNE NCTRL0 ;Skip if not¢ LDA #$00 ;Purge buffer ---¢ STA BUFIN ;Reset IN pointer¢ STA BUFOUT ;Reset OUT pointer¢ LDA #$FF ¢ STA CH ;Reset CH ¢ BCS EXIT ;Don't Process key¢NCTRL0 STA CH1 ;Update last key pressed¢ LDA #$03¢ STA KEYDEL ;Reset debounce timer¢ LDA #$00 ¢ STA ATRACT ;Reset attract mode timer¢ LDA BUFIN ;Load IN pointer¢ CMP BUFOUT ;Subtract OUT pointer¢ BEQ EMPTY ;IN=OUT --> Buffer is empty¢ LDY BUFIN ;See if buffer is full¢ INY ;Add 1 to IN and see if it = OUT¢ TYA¢ CMP BUFOUT¢ BEQ EXIT ;IN=OUT-1 --> Buffer is full¢ LDA BUFIN ;Get IN pointer¢ BPL PUTBUF ;Skip this next part¢EMPTY LDA CH ;Get key code¢ CMP #$FF ;See if last code has been used¢ BNE PUTBUF ;Skip if CH has keycode in it¢ LDA KBCODE ;Get key code¢ STA CH ;Store at CH¢ BCS EXIT ;Jump to exit¢PUTBUF LDA KBCODE ;Get key code¢ LDY BUFIN ;Get IN pointer¢ STA (BUF),Y ;Store in buffer¢ INY ;Increment pointer¢ TYA¢ CMP #BUFLEN ;See if pointer is at end¢ BNE STORIN ;Skip if not at end¢ LDA #$00 ;Set to 0¢STORIN STA BUFIN¢EXIT LDA #$30 ¢ STA SRTIMR ;Reset auto-repeat timer¢ PLA¢ TAY¢ PLA¢ RTI¢*¢* VBLANK ROUTINE¢*¢* Checks to see if CH=$FF, which would mean the current¢* key has been processed. If it has been processed, then¢* the next data byte is moved out of the buffer into CH.¢* The appropriate pointers are updated.¢* If the buffer is not empty, then the auto-repeat feature¢* is disabled by putting a $30 in location SRTIMR.¢*¢KEYVB LDA BUFIN ;Get IN pointer¢ CMP BUFOUT ;Subtract OUT pointer¢ BEQ EXIT2 ;IN=OUT --> buffer is empty¢ LDA #$30¢ STA SRTIMR ;Reset auto-repeat timer¢ LDA CH ;Get value at CH¢ CMP #$FF ;See if it is 255¢ BNE EXIT2 ;Skip this if it isn't¢ LDY BUFOUT ;Get OUT pointer¢ LDA (BUF),Y ;Get character from buffer¢ STA CH ;Store character at CH¢ INY ;Increment OUT pointer¢ TYA¢ CMP #BUFLEN ;See if pointer is at end¢ BNE STOROUT ;Skip if not at end¢ LDA #$00 ;Set to 0¢STOROUT STA BUFOUT ¢EXIT2 JMP SYSVBV ;Jump to system VBLANK vector¢*¢* RESERVE BUFFER SPACE¢*¢BUFFER DS BUFLEN¢*¢* END¢*¢ END¢