Files
open-roms/c64/kernal/chrin.s
T

209 lines
3.5 KiB
ArmAsm

;;
;; Official Kernal routine, described in:
;;
;; - [RG64] C64 Programmer's Reference Guide - page 277/278
;; - [CM64] Compute's Mapping the Commodore 64 - page 228
;;
;; CPU registers that has to be preserved (see [RG64]): .Y
;;
;; XXX currently does not preserve register Y, to be fixed!
;; Reads a byte of input, unless from keyboard.
;; If from keyboard, then it gets a whole line of input, and returns the first char.
;; Repeated calls after that read out the successive bytes of the line of input.
chrin:
;; First determine the device number
lda DFLTN
beq chrin_keyboard ; #$00 - keyboard
;; XXX add screen support
jsr iec_devnum_check
bcs chrin_done_fail ; not a supported device
chrin_iec:
jsr JACPTR
bcs chrin_done_fail
;; FALLTROUGH
chrin_done:
clc ; indicate success
rts
chrin_done_fail:
sec ; indicate failure
rts
chrin_keyboard:
;; Save X
txa
pha
chrin_repeat:
;; Do we have a line of input we are currently returning?
;; If so, return the next byte, and clear the flag when we reach the end.
;; Do we have a line of input waiting?
lda keyboard_input_ready
beq read_from_keyboard
;; Yes, we have input waiting at (start_of_keyboard_input)+keyboard_input_ready
;; When keyboard_input_ready = end_of_input_line, then we return a carriage return
;; and clear the flag
cmp end_of_input_line
bne not_end_of_input
;; Return carriage return and clear pending input flag
lda #$00
sta keyboard_input_ready
pla
tax
clc
lda #$0d
rts
not_end_of_input:
;; Return next byte of waiting input and advance index
tay
pla
tax
lda (start_of_keyboard_input),y
jsr screen_code_to_petscii
inc keyboard_input_ready
clc
rts
read_from_keyboard:
jsr enable_cursor
;; Wait for a key
lda keys_in_key_buffer
beq chrin_repeat
lda keyboard_buffer
cmp #$0d
bne not_enter
jsr disable_cursor
jsr pop_keyboard_buffer
jsr hide_cursor_if_visible
;; It was enter.
;; Note that we have a line of input to return, and return the first byte thereof
;; after computing and storing its length.
;; (Compute's Mapping the 64, p96)
;; Set pointer to line of input
lda current_screen_line_ptr+0
sta start_of_keyboard_input+0
lda current_screen_line_ptr+1
sta start_of_keyboard_input+1
;; Calculate length
jsr get_current_line_logical_length
tay
iny
* dey
bmi empty_line
lda (current_screen_line_ptr),y
cmp #$20
beq -
iny
sty end_of_input_line
lda #$01
sta keyboard_input_ready
;; Return first char of line
ldy #$00
pla
tax
lda (start_of_keyboard_input),y
jsr screen_code_to_petscii
clc
rts
empty_line:
;; For an empty line, just return the carriage return
;; (and don't forget to actually print the carriage return, so that
;; the cursor advances and screen scrolls as required)
pla
tax
clc
lda #$0d
rts
not_enter:
;; Print character
lda keyboard_buffer
jsr chrout
jsr pop_keyboard_buffer
;; Keep looking for input from keyboard until carriage return
jmp chrin_repeat
pop_keyboard_buffer:
;; Pop key out of keyboard buffer
;; Disable interrupts while reading from keyboard buffer
;; so that no race conditions can occur
sei
ldx #$00
ldy #$01
* lda keyboard_buffer,y
sta keyboard_buffer,x
inx
iny
cpy key_buffer_size
bne -
dec keys_in_key_buffer
cli
rts
screen_code_to_petscii:
cmp #$1b
bcs not_alpha
clc
adc #$40
rts
not_alpha:
cmp #$40
bcs not_punctuation
rts
not_punctuation:
cmp #$5b
bcs not_shifted
clc
adc #$80
rts
not_shifted:
cmp #$80
bcs not_vendor
;; $60-$7F -> $A0-$BF
clc
adc #$40
rts
not_vendor:
rts