Restructured according to review
Restructured according to review in pull request #567. The "inputc" function was moved in slightly modified form to kbhit.s and replaces the old keyboard scanner. cgetc() uses the new kbhit() to read a character.
This commit is contained in:
committed by
greg-king5
parent
e2007d0743
commit
eb2317d014
@@ -2,236 +2,40 @@
|
|||||||
; char cgetc (void);
|
; char cgetc (void);
|
||||||
;
|
;
|
||||||
|
|
||||||
.constructor initcgetc
|
|
||||||
.export _cgetc
|
.export _cgetc
|
||||||
.export inputc
|
|
||||||
.import cursor
|
.import cursor
|
||||||
|
.import _kbhit
|
||||||
|
|
||||||
.include "osic1p.inc"
|
.include "osic1p.inc"
|
||||||
.include "extzp.inc"
|
.include "extzp.inc"
|
||||||
.include "zeropage.inc"
|
.include "zeropage.inc"
|
||||||
|
|
||||||
; Internal state that needs to be preserved across calls.
|
; Input routine, show cursor if enabled
|
||||||
; These variables are named after the original memory locations used by the
|
|
||||||
; 65V PROM MONITOR, until the actual meaning is determined.
|
|
||||||
.segment "EXTZP" : zeropage
|
|
||||||
|
|
||||||
KB0213: .res 1
|
|
||||||
KB0214: .res 1
|
|
||||||
KB0215: .res 1
|
|
||||||
KB0216: .res 1
|
|
||||||
|
|
||||||
; Initialize one-character buffer that is filled by kbhit()
|
|
||||||
.segment "ONCE"
|
|
||||||
initcgetc:
|
|
||||||
lda #$00
|
|
||||||
sta CHARBUF ; No character in buffer initially
|
|
||||||
|
|
||||||
sta KB0213 ; Initialize keyboard state
|
|
||||||
sta KB0214
|
|
||||||
sta KB0215
|
|
||||||
sta KB0216
|
|
||||||
|
|
||||||
rts
|
|
||||||
|
|
||||||
; Input routine from 65V PROM MONITOR, show cursor if enabled
|
|
||||||
.code
|
.code
|
||||||
_cgetc:
|
_cgetc:
|
||||||
lda CHARBUF ; character in buffer available?
|
ldx CHARBUF ; character in buffer available?
|
||||||
beq nobuffer
|
bne done
|
||||||
tax ; save character in X
|
|
||||||
lda #$00
|
|
||||||
sta CHARBUF ; empty buffer
|
|
||||||
beq restorex ; restore X and return
|
|
||||||
nobuffer:
|
|
||||||
lda cursor ; show cursor?
|
lda cursor ; show cursor?
|
||||||
beq nocursor
|
beq nocursor
|
||||||
ldy CURS_X
|
ldy CURS_X
|
||||||
lda (SCREEN_PTR),y ; fetch current character
|
lda (SCREEN_PTR),y ; fetch current character
|
||||||
sta tmp1 ; save it
|
sta tmp1 ; save it
|
||||||
lda #$A1 ; full white square
|
lda #$A1 ; full white square
|
||||||
sta (SCREEN_PTR),y ; store at cursor position
|
sta (SCREEN_PTR),y ; store at cursor position^
|
||||||
|
|
||||||
nocursor:
|
nocursor:
|
||||||
jsr inputc ; get input character in A
|
jsr _kbhit ; get input character in A
|
||||||
ldx cursor
|
tax ; save A in X, set flags
|
||||||
|
beq nocursor ; until a key is actually pressed
|
||||||
|
lda cursor
|
||||||
beq done ; was cursor on?
|
beq done ; was cursor on?
|
||||||
tax ; save A in X
|
|
||||||
lda tmp1 ; fetch saved character
|
lda tmp1 ; fetch saved character
|
||||||
ldy CURS_X
|
ldy CURS_X
|
||||||
sta (SCREEN_PTR),y ; store at cursor position
|
sta (SCREEN_PTR),y ; store at cursor position
|
||||||
|
|
||||||
restorex:
|
|
||||||
txa ; restore saved character from X
|
|
||||||
done:
|
done:
|
||||||
|
lda #$00
|
||||||
|
sta CHARBUF ; empty buffer
|
||||||
|
txa ; restore saved character from X
|
||||||
ldx #$00 ; high byte of int return value
|
ldx #$00 ; high byte of int return value
|
||||||
rts
|
rts
|
||||||
|
|
||||||
; Routine to get character from keyboard and return it in A.
|
|
||||||
; Based on the OSI ROM routine at $FD00 but uses different
|
|
||||||
; storage locations to avoid corrupting CC65 run-time code.
|
|
||||||
|
|
||||||
inputc: txa ; Save X on stack.
|
|
||||||
pha
|
|
||||||
tya ; Save Y on stack.
|
|
||||||
pha
|
|
||||||
LFD04: lda #$80 ; Bit mask for initial keyboard row
|
|
||||||
LFD06: jsr LFCBE ; Write keyboard row
|
|
||||||
jsr LFCC6 ; Read keyboard column
|
|
||||||
bne LFD13 ; Branch if a key in this column was pressed
|
|
||||||
lsr a ; Otherwise shift mask to next row
|
|
||||||
bne LFD06 ; If not done yet, check next row
|
|
||||||
beq LFD3A ; Branch if last row reached and no key pressed
|
|
||||||
LFD13: lsr a ; Have a key press. Shift LSB into carry
|
|
||||||
bcc LFD1F ; Branch if no key pressed in column 0
|
|
||||||
txa ; Key pressed in row zero. Get the column data
|
|
||||||
and #$20 ; Mask only the bit for <ESC> as it is the only key in row zero that returns key press
|
|
||||||
beq LFD3A ; Branch if <ESC> was not the key
|
|
||||||
lda #$1B ; Set character to <ESC>
|
|
||||||
bne LFD50 ; Do more processing
|
|
||||||
LFD1F: jsr LFE86 ; Shift to find bit that is set (in Y)
|
|
||||||
tya ; Get bit
|
|
||||||
sta KB0215 ; Save it
|
|
||||||
asl a ; Multiply by 7 by shifting left three times (X8)...
|
|
||||||
asl a
|
|
||||||
asl a
|
|
||||||
sec ; ...then subtracting one
|
|
||||||
sbc KB0215
|
|
||||||
sta KB0215 ; Save value*7 for later lookup in table
|
|
||||||
txa ; Get the keyboard column
|
|
||||||
lsr a ; Shift out bit zero (only key there is <SHIFT LOCK>)
|
|
||||||
asl a ; And shift back
|
|
||||||
jsr LFE86 ; Shift to find bit that is set (in Y)
|
|
||||||
beq LFD47 ; Branch if no keys pressed
|
|
||||||
lda #$00
|
|
||||||
LFD3A: sta KB0216 ; Save state of <CTRL> and shift keys
|
|
||||||
LFD3D: sta KB0213
|
|
||||||
lda #$02 ; Count used for key debouncing
|
|
||||||
sta KB0214
|
|
||||||
bne LFD04 ; Go back and scan keyboard again
|
|
||||||
LFD47: clc
|
|
||||||
tya ; Get bit number of pressed key
|
|
||||||
adc KB0215 ; Add previously calculated offset for keyboard row*7
|
|
||||||
tay
|
|
||||||
lda LFF3B,y ; Read ASCII code for key from table
|
|
||||||
LFD50: cmp KB0213 ; Debounce - same as last key scan?
|
|
||||||
bne LFD3D ; If not, try again
|
|
||||||
dec KB0214 ; Decrement debounce counter
|
|
||||||
beq LFD5F ; Branch if done debouncing
|
|
||||||
jsr LFCDF ; Wait for short delay to debounce keyboard
|
|
||||||
beq LFD04 ; Go back and scan keyboard.
|
|
||||||
LFD5F: ldx #$64 ; Was <CONTROL> key down?
|
|
||||||
cmp KB0216
|
|
||||||
bne LFD68 ; Branch if not
|
|
||||||
ldx #$0F
|
|
||||||
LFD68: stx KB0214
|
|
||||||
sta KB0216
|
|
||||||
cmp #$21
|
|
||||||
bmi LFDD0 ; Done, return key
|
|
||||||
cmp #$5F
|
|
||||||
beq LFDD0 ; Done, return key
|
|
||||||
lda #$01
|
|
||||||
jsr LFCBE ; Write keyboard row
|
|
||||||
jsr LFCCF ; Read keyboard column
|
|
||||||
sta KB0215
|
|
||||||
and #$01
|
|
||||||
tax
|
|
||||||
lda KB0215
|
|
||||||
and #$06
|
|
||||||
bne LFDA2
|
|
||||||
bit KB0213
|
|
||||||
bvc LFDBB
|
|
||||||
txa
|
|
||||||
eor #$01
|
|
||||||
and #$01
|
|
||||||
beq LFDBB
|
|
||||||
lda #$20
|
|
||||||
bit KB0215
|
|
||||||
bvc LFDC3
|
|
||||||
lda #$C0
|
|
||||||
bne LFDC3
|
|
||||||
LFDA2: bit KB0213
|
|
||||||
bvc LFDAA
|
|
||||||
txa
|
|
||||||
beq LFDBB
|
|
||||||
LFDAA: ldy KB0213
|
|
||||||
cpy #$31
|
|
||||||
bcc LFDB9
|
|
||||||
cpy #$3C
|
|
||||||
bcs LFDB9
|
|
||||||
lda #$F0
|
|
||||||
bne LFDBB
|
|
||||||
LFDB9: lda #$10
|
|
||||||
LFDBB: bit KB0215
|
|
||||||
bvc LFDC3
|
|
||||||
clc
|
|
||||||
adc #$C0
|
|
||||||
LFDC3: clc
|
|
||||||
adc KB0213
|
|
||||||
and #$7F
|
|
||||||
bit KB0215
|
|
||||||
bpl LFDD0
|
|
||||||
ora #$80
|
|
||||||
LFDD0: sta KB0215 ; Save pressed key
|
|
||||||
pla
|
|
||||||
tay ; Restore saved Y value
|
|
||||||
pla
|
|
||||||
tax ; Restore saved Y value
|
|
||||||
lda KB0215 ; Get pressed key and return in A
|
|
||||||
rts
|
|
||||||
|
|
||||||
; Write keyboard row with value in A.
|
|
||||||
; Invert the bits before writing.
|
|
||||||
; Returns original value of A.
|
|
||||||
|
|
||||||
LFCBE: eor #$FF
|
|
||||||
sta KBD
|
|
||||||
eor #$FF
|
|
||||||
rts
|
|
||||||
|
|
||||||
; Read keyboard column and return in X.
|
|
||||||
; Sets Z flag if no keys were pressed.
|
|
||||||
; Saves current value of A.
|
|
||||||
|
|
||||||
LFCC6: pha ; Save A
|
|
||||||
jsr LFCCF ; Read keyboard column
|
|
||||||
tax ; Save in X
|
|
||||||
pla ; Restore A
|
|
||||||
dex ; Decrement and then increment to
|
|
||||||
inx ; preserve value of X but set flags
|
|
||||||
rts
|
|
||||||
|
|
||||||
; Read keyboard column.
|
|
||||||
; Invert the bits (pressed key(s) will show up as ones).
|
|
||||||
|
|
||||||
LFCCF: lda KBD ; Read keyboard hardware
|
|
||||||
eor #$FF ; Invert the bits
|
|
||||||
rts
|
|
||||||
|
|
||||||
; Short fixed delay routine.
|
|
||||||
|
|
||||||
LFCDF: ldy #$10
|
|
||||||
LFCE1: ldx #$40
|
|
||||||
LFCE3: dex
|
|
||||||
bne LFCE3
|
|
||||||
dey
|
|
||||||
bne LFCE1
|
|
||||||
rts
|
|
||||||
|
|
||||||
; Shift A left until we find a 1 in the most significant bit.
|
|
||||||
; Return the bit number in Y.
|
|
||||||
|
|
||||||
LFE86: ldy #$08
|
|
||||||
LFE88: dey
|
|
||||||
asl a
|
|
||||||
bcc LFE88
|
|
||||||
rts
|
|
||||||
|
|
||||||
; Lookup table of keyboard keys for each scan row.
|
|
||||||
LFF3B: .byte $BD
|
|
||||||
.byte 'P', ';', '/', ' ', 'Z', 'A', 'Q'
|
|
||||||
.byte ',', 'M', 'N', 'B', 'V', 'C', 'X'
|
|
||||||
.byte 'K', 'J', 'H', 'G', 'F', 'D', 'S'
|
|
||||||
.byte 'I', 'U', 'Y', 'T', 'R', 'E', 'W'
|
|
||||||
.byte $00, $00, $0D, $0A, 'O', 'L', '.'
|
|
||||||
.byte $00, '_', '-', ':', '0', '9', '8'
|
|
||||||
.byte '7', '6', '5', '4', '3', '2', '1'
|
|
||||||
|
|||||||
@@ -10,39 +10,197 @@
|
|||||||
; in tmp1 and that is set to zero after the first round.
|
; in tmp1 and that is set to zero after the first round.
|
||||||
;
|
;
|
||||||
|
|
||||||
|
.constructor initkbhit
|
||||||
.export _kbhit
|
.export _kbhit
|
||||||
.import inputc
|
|
||||||
.include "osic1p.inc"
|
.include "osic1p.inc"
|
||||||
.include "extzp.inc"
|
.include "extzp.inc"
|
||||||
.include "zeropage.inc"
|
.include "zeropage.inc"
|
||||||
|
|
||||||
_kbhit:
|
; Internal state that needs to be preserved across calls.
|
||||||
lda #%11011111 ; Mask for only checking the column for the
|
.segment "EXTZP" : zeropage
|
||||||
sta tmp1 ; ESC key in the first keyboard row.
|
|
||||||
|
LASTSCAN: .res 1 ; Result of previous keyboard scan
|
||||||
|
DBNCCNT: .res 1 ; Debounce counter
|
||||||
|
KBDTMP: .res 1 ; Temporary values
|
||||||
|
CTRLSHIFT: .res 1 ; State of CTRL and SHIFT keys
|
||||||
|
|
||||||
|
; Initialize one-character buffer that is filled by kbhit()
|
||||||
|
.segment "ONCE"
|
||||||
|
initkbhit:
|
||||||
|
lda #$00
|
||||||
|
sta CHARBUF ; No character in buffer initially
|
||||||
|
|
||||||
|
sta LASTSCAN ; Initialize keyboard state
|
||||||
|
sta DBNCCNT
|
||||||
|
sta KBDTMP
|
||||||
|
sta CTRLSHIFT
|
||||||
|
|
||||||
lda #%11111110 ; Mask for first keyboard row
|
|
||||||
scan:
|
|
||||||
sta KBD ; Select keyboard row
|
|
||||||
tax ; Save A
|
|
||||||
lda KBD ; Read keyboard columns
|
|
||||||
ora tmp1 ; Mask out uninteresting keys (only relevant in
|
|
||||||
; first row)
|
|
||||||
cmp #$FF ; No keys pressed?
|
|
||||||
bne keypressed
|
|
||||||
lda #$00 ; For remaining rows no keys masked
|
|
||||||
sta tmp1
|
|
||||||
txa ; Restore A
|
|
||||||
sec ; Want to shift in ones
|
|
||||||
rol a ; Rotate row select to next bit position
|
|
||||||
cmp #$FF ; Done?
|
|
||||||
bne scan ; If not, continue
|
|
||||||
lda #$00 ; Return false
|
|
||||||
tax ; High byte of return is also zero
|
|
||||||
sta CHARBUF ; No character in buffer
|
|
||||||
rts
|
rts
|
||||||
keypressed:
|
|
||||||
jsr inputc ; Get input character in A
|
; Routine to get character from keyboard and return it in A.
|
||||||
sta CHARBUF ; Save in buffer
|
; Based on the OSI ROM routine at $FD00 but uses different
|
||||||
|
; storage locations to avoid corrupting CC65 run-time code.
|
||||||
|
|
||||||
|
_kbhit: lda CHARBUF ; Check for previously saved character
|
||||||
|
beq LFD05
|
||||||
ldx #$00 ; High byte of return is always zero
|
ldx #$00 ; High byte of return is always zero
|
||||||
lda #$01 ; Return true
|
rts ; A contains non-zero character code meaning true
|
||||||
|
LFD05: lda #$80 ; Bit mask for initial keyboard row
|
||||||
|
LFD06: jsr LFCBE ; Write keyboard row
|
||||||
|
jsr LFCC6 ; Read keyboard column
|
||||||
|
bne LFD13 ; Branch if a key in this column was pressed
|
||||||
|
lsr a ; Otherwise shift mask to next row
|
||||||
|
bne LFD06 ; If not done yet, check next row
|
||||||
|
beq LFD3A ; Branch if last row reached and no key pressed
|
||||||
|
LFD13: lsr a ; Have a key press. Shift LSB into carry
|
||||||
|
bcc LFD1F ; Branch if no key pressed in column 0
|
||||||
|
txa ; Key pressed in row zero. Get the column data
|
||||||
|
and #$20 ; Mask only the bit for <ESC> as it is the only key in row zero that returns key press
|
||||||
|
beq LFD3A ; Branch if <ESC> was not the key
|
||||||
|
lda #$1B ; Set character to <ESC>
|
||||||
|
bne LFD50 ; Do more processing
|
||||||
|
LFD1F: jsr LFE86 ; Shift to find bit that is set (in Y)
|
||||||
|
tya ; Get bit
|
||||||
|
sta KBDTMP ; Save it
|
||||||
|
asl a ; Multiply by 7 by shifting left three times (X8)...
|
||||||
|
asl a
|
||||||
|
asl a
|
||||||
|
sec ; ...then subtracting one
|
||||||
|
sbc KBDTMP
|
||||||
|
sta KBDTMP ; Save value*7 for later lookup in table
|
||||||
|
txa ; Get the keyboard column
|
||||||
|
lsr a ; Shift out bit zero (only key there is <SHIFT LOCK>)
|
||||||
|
asl a ; And shift back
|
||||||
|
jsr LFE86 ; Shift to find bit that is set (in Y)
|
||||||
|
beq LFD47 ; Branch if no keys pressed STM: IS THIS CORRECT?
|
||||||
|
lda #$00
|
||||||
|
LFD3A: sta CTRLSHIFT ; Save state of <CTRL> and shift keys
|
||||||
|
LFD3D: sta LASTSCAN
|
||||||
|
lda #$02 ; Count used for key debouncing
|
||||||
|
sta DBNCCNT
|
||||||
|
ldx #$00 ; High byte of return is always zero
|
||||||
|
lda #$00 ; Return false
|
||||||
rts
|
rts
|
||||||
|
LFD47: clc
|
||||||
|
tya ; Get bit number of pressed key
|
||||||
|
adc KBDTMP ; Add previously calculated offset for keyboard row*7
|
||||||
|
tay
|
||||||
|
lda LFF3B,y ; Read ASCII code for key from table
|
||||||
|
LFD50: cmp LASTSCAN ; Debounce - same as last key scan?
|
||||||
|
bne LFD3D ; If not, try again
|
||||||
|
dec DBNCCNT ; Decrement debounce counter
|
||||||
|
beq LFD5F ; Branch if done debouncing
|
||||||
|
jsr LFCDF ; Wait for short delay to debounce keyboard
|
||||||
|
beq _kbhit ; Go back and scan keyboard.
|
||||||
|
LFD5F: ldx #$64 ; Was <CONTROL> key down?
|
||||||
|
cmp CTRLSHIFT
|
||||||
|
bne LFD68 ; Branch if not
|
||||||
|
ldx #$0F
|
||||||
|
LFD68: stx DBNCCNT
|
||||||
|
sta CTRLSHIFT
|
||||||
|
cmp #$21
|
||||||
|
bmi LFDD0 ; Done, return key
|
||||||
|
cmp #$5F
|
||||||
|
beq LFDD0 ; Done, return key
|
||||||
|
lda #$01
|
||||||
|
jsr LFCBE ; Write keyboard row
|
||||||
|
jsr LFCCF ; Read keyboard column
|
||||||
|
sta KBDTMP
|
||||||
|
and #$01
|
||||||
|
tax
|
||||||
|
lda KBDTMP
|
||||||
|
and #$06
|
||||||
|
bne LFDA2
|
||||||
|
bit LASTSCAN
|
||||||
|
bvc LFDBB
|
||||||
|
txa
|
||||||
|
eor #$01
|
||||||
|
and #$01
|
||||||
|
beq LFDBB
|
||||||
|
lda #$20
|
||||||
|
bit KBDTMP
|
||||||
|
bvc LFDC3
|
||||||
|
lda #$C0
|
||||||
|
bne LFDC3
|
||||||
|
LFDA2: bit LASTSCAN
|
||||||
|
bvc LFDAA
|
||||||
|
txa
|
||||||
|
beq LFDBB
|
||||||
|
LFDAA: ldy LASTSCAN
|
||||||
|
cpy #$31
|
||||||
|
bcc LFDB9
|
||||||
|
cpy #$3C
|
||||||
|
bcs LFDB9
|
||||||
|
lda #$F0
|
||||||
|
bne LFDBB
|
||||||
|
LFDB9: lda #$10
|
||||||
|
LFDBB: bit KBDTMP
|
||||||
|
bvc LFDC3
|
||||||
|
clc
|
||||||
|
adc #$C0
|
||||||
|
LFDC3: clc
|
||||||
|
adc LASTSCAN
|
||||||
|
and #$7F
|
||||||
|
bit KBDTMP
|
||||||
|
bpl LFDD0
|
||||||
|
ora #$80
|
||||||
|
LFDD0: sta KBDTMP ; Save pressed key and return in A
|
||||||
|
sta CHARBUF
|
||||||
|
rts
|
||||||
|
|
||||||
|
; Write keyboard row with value in A.
|
||||||
|
; Invert the bits before writing.
|
||||||
|
; Returns original value of A.
|
||||||
|
|
||||||
|
LFCBE: eor #$FF
|
||||||
|
sta KBD
|
||||||
|
eor #$FF
|
||||||
|
rts
|
||||||
|
|
||||||
|
; Read keyboard column and return in X.
|
||||||
|
; Sets Z flag if no keys were pressed.
|
||||||
|
; Saves current value of A.
|
||||||
|
|
||||||
|
LFCC6: pha ; Save A
|
||||||
|
jsr LFCCF ; Read keyboard column
|
||||||
|
tax ; Save in X
|
||||||
|
pla ; Restore A
|
||||||
|
dex ; Decrement and then increment to
|
||||||
|
inx ; preserve value of X but set flags
|
||||||
|
rts
|
||||||
|
|
||||||
|
; Read keyboard column.
|
||||||
|
; Invert the bits (pressed key(s) will show up as ones).
|
||||||
|
|
||||||
|
LFCCF: lda KBD ; Read keyboard hardware
|
||||||
|
eor #$FF ; Invert the bits
|
||||||
|
rts
|
||||||
|
|
||||||
|
; Short fixed delay routine.
|
||||||
|
|
||||||
|
LFCDF: ldy #$10
|
||||||
|
LFCE1: ldx #$40
|
||||||
|
LFCE3: dex
|
||||||
|
bne LFCE3
|
||||||
|
dey
|
||||||
|
bne LFCE1
|
||||||
|
rts
|
||||||
|
|
||||||
|
; Shift A left until we find a 1 in the most significant bit.
|
||||||
|
; Return the bit number in Y.
|
||||||
|
|
||||||
|
LFE86: ldy #$08
|
||||||
|
LFE88: dey
|
||||||
|
asl a
|
||||||
|
bcc LFE88
|
||||||
|
rts
|
||||||
|
|
||||||
|
; Lookup table of keyboard keys for each scan row.
|
||||||
|
LFF3B: .byte $BD
|
||||||
|
.byte 'P', ';', '/', ' ', 'Z', 'A', 'Q'
|
||||||
|
.byte ',', 'M', 'N', 'B', 'V', 'C', 'X'
|
||||||
|
.byte 'K', 'J', 'H', 'G', 'F', 'D', 'S'
|
||||||
|
.byte 'I', 'U', 'Y', 'T', 'R', 'E', 'W'
|
||||||
|
.byte $00, $00, $0D, $0A, 'O', 'L', '.'
|
||||||
|
.byte $00, '_', '-', ':', '0', '9', '8'
|
||||||
|
.byte '7', '6', '5', '4', '3', '2', '1'
|
||||||
|
|||||||
Reference in New Issue
Block a user