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

211 lines
3.2 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 keyboard part 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_real:
// Determine the device number
lda DFLTN
beq chrin_keyboard // #$00 - keyboard
// XXX add screen support
jsr iec_check_devnum
bcc chrin_iec
jmp lvs_device_not_found_error // 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 CRSW
beq read_from_keyboard
// Yes, we have input waiting at (LXSP)+CRSW
// When CRSW = INDX, then we return a carriage return
// and clear the flag
cmp INDX
bne not_end_of_input
// Return carriage return and clear pending input flag
lda #$00
sta CRSW
pla
tax
clc
lda #$0d
rts
not_end_of_input:
// Return next byte of waiting input and advance index
tay
pla
tax
lda (LXSP),y
jsr screen_code_to_petscii
inc CRSW
clc
rts
read_from_keyboard:
jsr enable_cursor
// Wait for a key
lda NDX
beq chrin_repeat
lda KEYD
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 PNT+0
sta LXSP+0
lda PNT+1
sta LXSP+1
// Calculate length
jsr get_current_line_logical_length
tay
iny
!: dey
bmi empty_line
lda (PNT),y
cmp #$20
beq !-
iny
sty INDX
lda #$01
sta CRSW
// Return first char of line
ldy #$00
pla
tax
lda (LXSP),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 KEYD
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 KEYD,y
sta KEYD,x
inx
iny
cpy XMAX
bne !-
dec NDX
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
// FALLTROUGH
not_vendor:
rts