diff src/genio.s @ 74:e74d00ac6b79

Split some code into separate files for easier management (2) Because the source for lwbasic is so large, split it into several different files to make it easier to navigate and modify. This is part two of the split. Also includes fix for dependency tracking related to the split in the make file.
author William Astle <lost@l-w.ca>
date Sun, 06 Aug 2023 00:36:48 -0600
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/genio.s	Sun Aug 06 00:36:48 2023 -0600
@@ -0,0 +1,126 @@
+                *pragmapush list
+                *pragma list
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; General I/O handling package
+;
+; These routines operate on the I/O channel specified by filenum. The defined values of filenum are:
+;
+; 0: keyboard/screen console
+;
+; Read a line from the active file into linebuff. The resulting line will be NUL terminated leading to at most
+; linbuffsize-1 character input. The trailing CR/LF will not be included. The input will be echoed if linebuffecho is
+; enabled. Exit with the length of the input line in B.
+readline        ldx #linebuff                   ; point to line input buffer
+                clr ,x                          ; make sure buffer is NUL terminated
+readline0       bsr readchr                     ; read an input character
+                bcs readline1                   ; brif not EOF
+                cmpa #0x0d                      ; CR (carriage return)
+                beq readline1                   ; brif so - return
+                cmpa #0x03                      ; BREAK?
+                bne readline3                   ; brif not
+                coma                            ; set carry for irregular exit
+                skip1
+readline1       clra                            ; clear carry for regular exit
+                pshs cc                         ; save carry state
+                lda readlinenoecho              ; are we echoing?
+                bne readline2                   ; brif not
+                lda #0x0d                       ; echo carriage return + line feed
+                bsr writechr
+readline2       tfr x,d                         ; get end address after input
+                subd #linebuff                  ; subtract start of buffer; D is now length and C is clear
+                clr ,x                          ; make sure line is NUL terminated
+                puls cc,pc                      ; restore BREAK flag (C) and return
+readline3       cmpa #0x08                      ; backspace?
+                bne readline4                   ; brif not
+                cmpx #linebuff                  ; at start of buffer?
+                beq readline0                   ; brif so - do nothing
+                leax -1,x                       ; move back buffer pointer
+                bsr readlinee                   ; write a BS
+                lda #0x20                       ; write a space
+                bsr readlinee
+                lda #0x08                       ; and finally a BS
+                bsr readlinee
+                bra readline0                   ; go process more characters
+readline4       cmpa #0x0c                      ; form feed?
+                bne readline5                   ; brif not
+                bsr readlinee                   ; go echo character if needed
+                bra readline                    ; go restart line entry
+readline5       cmpa #0x20                      ; is it non-printing?
+                blo readline0                   ; brif so - don't store it and continue
+                bsr readlines                   ; stash character in buffer and echo if necessary
+                bra readline0                   ; go get another character
+readlines       cmpx #linebuff+linebuffsize-1   ; is the line buffer full?
+                bhs readlinee0                  ; brif so - don't store character OR echo it
+                sta ,x+                         ; stash character
+readlinee       ldb readlinenoecho              ; are we echoing?
+                bne readlinee0                  ; brif not
+                bsr writechr                    ; echo the character
+readlinee0      rts
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Write a newline if not at left margin. This will unconditinally output a newline for devices where the horizontal
+; position is not knowable.
+writecondnl     lda filenum                     ; get file number
+                bne writenl                     ; brif not screen - we'll do it unconditionally
+                lda console_curptr+1            ; get LSB of cursor pointer
+                anda #0x1f                      ; keep only the low 5 bits (32 characters per line)
+                beq writecondnl0                ; brif no newline is needed
+                ; fallthrough intended
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Write a newline to the chosen device.
+writenl         lda #0x0d                       ; code for carriage return - will serve as newline
+                ; fallthrough intended
+; Write a character to the active file; all registers preserved but C will be set if the output file cannot handle
+; an output character (doesn't exist, etc.)
+writechr        tst filenum                     ; is it screen?
+                beq writechr_scr                ; brif writing to screen
+                orcc #1                         ; unknown device flag
+writecondnl0    rts
+; Handle output to the screen. This is where we convert CR to CRLF
+writechr_scr    jsr console_outchr              ; output the character
+                cmpa #0x0d                      ; was it CR?
+                bne writechr_scr0               ; brif not
+                lda #0x0a                       ; ouptut an LF
+                jsr console_outchr
+                lda #0x0d                       ; restore original value
+writechr_scr0   andcc #0xfe                     ; clear error flag
+                rts
+; Read a character from the active file and return it in A; in the event that EOF is detected, readeof will be nonzero
+; and the call will return with carry set.
+readchr         clr fileeof                     ; flag not end of file (and clear carry)
+                lda filenum                     ; get input file number
+                beq readchr_kb                  ; brif keyboard input
+                com fileeof                     ; flag end of file (C set and fileeof nonzero)
+                rts
+; Read character from keyboard; blink cursor while doing so
+readchr_kb      pshs b                          ; preserve B as temp storage
+                ldb [console_curptr]            ; get character at cursor
+                inc console_blnkdel             ; activate cursor blinking (first interrupt will cycle it)
+readchr_kb0     jsr keyb_getkey                 ; read keyboard
+                bcc readchr_kb1                 ; brif we got a result
+                cwai #0xaf                      ; wait for interrupt to scan keyboard
+                bra readchr_kb0                 ; see if we have something yet
+readchr_kb1     clr console_blnkdel             ; disable cursor blinking
+                stb [console_curptr]            ; restore screen character
+                clrb                            ; clear carry to indicate not eof
+                puls b,pc                       ; restore temp and return
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Write a character to the selected output device. If the device is one that does not support actual lower case, then
+; conver the character to upper case. Otherwise, pass it through as is. Currently, only the console screen falls into
+; this category. This *will* modify the character in A if a change is made.
+writechrconduc  tst filenum                     ; is it screen?
+                bne writechr                    ; brif not - just output it
+                tst console_truelc              ; does the current text screen support actual lower case?
+                bne writechr                    ; brif so - just output character
+                cmpa #'a                        ; is it lower case?
+                blo writechr                    ; brif not
+                cmpa #'z                        ; is it still lower case?
+                bhi writechr                    ; brif not
+                suba #0x20                      ; shift to upper case
+                bra writechr                    ; go output it
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Write a NUL terminated string at X to the screen. Conditionally convert to upper case based on the screen type.
+writestrconduc0 bsr writechrconduc              ; output the character
+writestrconduc  lda ,x+                         ; fetch character from string
+                bne writestrconduc0             ; brif not end of string
+                rts
+                *pragmapop list