|
- ; stdio
- ;
- ; Allows other modules to print to "standard out", and get data from "standard
- ; in", that is, the console through which the user is connected in a decoupled
- ; manner.
- ;
- ; *** Consts ***
- ; Size of the readline buffer. If a typed line reaches this size, the line is
- ; flushed immediately (same as pressing return).
- .equ STDIO_BUFSIZE 0x20
-
- ; *** Variables ***
- ; Used to store formatted hex values just before printing it.
- .equ STDIO_HEX_FMT STDIO_RAMSTART
- .equ STDIO_GETC STDIO_HEX_FMT+2
- .equ STDIO_PUTC STDIO_GETC+2
-
- ; Line buffer. We read types chars into this buffer until return is pressed
- ; This buffer is null-terminated and we don't keep an index around: we look
- ; for the null-termination every time we write to it. Simpler that way.
- .equ STDIO_BUF STDIO_PUTC+2
-
- ; Index where the next char will go in stdioGetC.
- .equ STDIO_BUFIDX STDIO_BUF+STDIO_BUFSIZE
- .equ STDIO_RAMEND STDIO_BUFIDX+1
-
- ; Sets GetC to the routine where HL points to and PutC to DE.
- stdioInit:
- ld (STDIO_GETC), hl
- ld (STDIO_PUTC), de
- xor a
- ld (STDIO_BUF), a
- ld (STDIO_BUFIDX), a
- ret
-
- stdioGetC:
- ld ix, (STDIO_GETC)
- jp (ix)
-
- stdioPutC:
- ld ix, (STDIO_PUTC)
- jp (ix)
-
- ; print null-terminated string pointed to by HL
- printstr:
- push af
- push hl
-
- .loop:
- ld a, (hl) ; load character to send
- or a ; is it zero?
- jr z, .end ; if yes, we're finished
- call stdioPutC
- inc hl
- jr .loop
-
- .end:
- pop hl
- pop af
- ret
-
- ; print B characters from string that HL points to
- printnstr:
- push bc
- push hl
- .loop:
- ld a, (hl) ; load character to send
- call stdioPutC
- inc hl
- djnz .loop
-
- .end:
- pop hl
- pop bc
- ret
-
- printcrlf:
- push af
- ld a, ASCII_CR
- call stdioPutC
- ld a, ASCII_LF
- call stdioPutC
- pop af
- ret
-
- ; Print the hex char in A
- printHex:
- push bc
- push hl
- ld hl, STDIO_HEX_FMT
- call fmtHexPair
- ld b, 2
- call printnstr
- pop hl
- pop bc
- ret
-
- ; Print the hex pair in HL
- printHexPair:
- push af
- ld a, h
- call printHex
- ld a, l
- call printHex
- pop af
- ret
-
- ; Call stdioGetC and put the result in the buffer. Sets Z according to whether
- ; the buffer is "complete", that is, whether CR or LF have been pressed or if
- ; the the buffer is full. Z is set if the line is "complete", unset if not.
- ; The next call to stdioReadC after a completed line will start a new line.
- ;
- ; This routine also takes care of echoing received characters back to the TTY.
- ;
- ; This routine doesn't wait after a typed char. If nothing is typed, we return
- ; immediately with Z flag unset.
- ;
- ; Note that this routine doesn't bother returning the typed character.
- stdioReadC:
- ; Let's wait until something is typed.
- call stdioGetC
- ret nz ; nothing typed? nothing to do
- ; got it. Now, is it a CR or LF?
- cp ASCII_CR
- jr z, .complete ; char is CR? buffer complete!
- cp ASCII_LF
- jr z, .complete
- cp ASCII_DEL
- jr z, .delchr
- cp ASCII_BS
- jr z, .delchr
-
- ; Echo the received character right away so that we see what we type
- call stdioPutC
-
- ; Ok, gotta add it do the buffer
- ; save char for later
- ex af, af'
- ld a, (STDIO_BUFIDX)
- push hl ; --> lvl 1
- ld hl, STDIO_BUF
- ; make HL point to dest spot
- call addHL
- ; Write our char down
- ex af, af'
- ld (hl), a
- ; follow up with a null char
- inc hl
- xor a
- ld (hl), a
- pop hl ; <-- lvl 1
- ; inc idx, which still is in AF'
- ex af, af'
- inc a
- cp STDIO_BUFSIZE-1 ; -1 is because we always want to keep our
- ; last char at zero.
- jr z, .complete ; end of buffer reached? buffer is full.
-
- ; not complete. save idx back
- ld (STDIO_BUFIDX), a
- ; Z already unset
- ret
-
- .complete:
- ; The line in our buffer is complete.
- ; But before we do that, let's take care of a special case: the empty
- ; line. If we didn't add any character since the last "complete", then
- ; our buffer's content is the content from the last time. Let's set this
- ; to an empty string.
- ld a, (STDIO_BUFIDX)
- or a
- jr nz, .completeSkip
- ld (STDIO_BUF), a
- .completeSkip:
- xor a ; sets Z
- ld (STDIO_BUFIDX), a
- ret
-
- .delchr:
- ld a, (STDIO_BUFIDX)
- or a
- jp z, unsetZ ; buf empty? nothing to do
- ; buffer not empty, let's go back one char and set a null char there.
- dec a
- ld (STDIO_BUFIDX), a
- push hl ;<|
- ld hl, STDIO_BUF ; |
- ; make HL point to dest spot |
- call addHL ; |
- xor a ; |
- ld (hl), a ; |
- pop hl ;<|
- ; Char deleted in buffer, now send BS + space + BS for the terminal
- ; to clear its previous char
- ld a, ASCII_BS
- call stdioPutC
- ld a, ' '
- call stdioPutC
- ld a, ASCII_BS
- call stdioPutC
- jp unsetZ
-
-
- ; Make HL point to the line buffer. It is always null terminated.
- stdioGetLine:
- ld hl, STDIO_BUF
- ret
-
- ; Repeatedly call stdioReadC until Z is set, then make HL point to the read
- ; buffer.
- stdioReadLine:
- call stdioReadC
- jr nz, stdioReadLine
- ld hl, STDIO_BUF
- ret
|