Mirror of CollapseOS
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

217 lines
4.6KB

  1. ; stdio
  2. ;
  3. ; Allows other modules to print to "standard out", and get data from "standard
  4. ; in", that is, the console through which the user is connected in a decoupled
  5. ; manner.
  6. ;
  7. ; *** Consts ***
  8. ; Size of the readline buffer. If a typed line reaches this size, the line is
  9. ; flushed immediately (same as pressing return).
  10. .equ STDIO_BUFSIZE 0x20
  11. ; *** Variables ***
  12. ; Used to store formatted hex values just before printing it.
  13. .equ STDIO_HEX_FMT STDIO_RAMSTART
  14. .equ STDIO_GETC STDIO_HEX_FMT+2
  15. .equ STDIO_PUTC STDIO_GETC+2
  16. ; Line buffer. We read types chars into this buffer until return is pressed
  17. ; This buffer is null-terminated and we don't keep an index around: we look
  18. ; for the null-termination every time we write to it. Simpler that way.
  19. .equ STDIO_BUF STDIO_PUTC+2
  20. ; Index where the next char will go in stdioGetC.
  21. .equ STDIO_BUFIDX STDIO_BUF+STDIO_BUFSIZE
  22. .equ STDIO_RAMEND STDIO_BUFIDX+1
  23. ; Sets GetC to the routine where HL points to and PutC to DE.
  24. stdioInit:
  25. ld (STDIO_GETC), hl
  26. ld (STDIO_PUTC), de
  27. xor a
  28. ld (STDIO_BUF), a
  29. ld (STDIO_BUFIDX), a
  30. ret
  31. stdioGetC:
  32. ld ix, (STDIO_GETC)
  33. jp (ix)
  34. stdioPutC:
  35. ld ix, (STDIO_PUTC)
  36. jp (ix)
  37. ; print null-terminated string pointed to by HL
  38. printstr:
  39. push af
  40. push hl
  41. .loop:
  42. ld a, (hl) ; load character to send
  43. or a ; is it zero?
  44. jr z, .end ; if yes, we're finished
  45. call stdioPutC
  46. inc hl
  47. jr .loop
  48. .end:
  49. pop hl
  50. pop af
  51. ret
  52. ; print B characters from string that HL points to
  53. printnstr:
  54. push bc
  55. push hl
  56. .loop:
  57. ld a, (hl) ; load character to send
  58. call stdioPutC
  59. inc hl
  60. djnz .loop
  61. .end:
  62. pop hl
  63. pop bc
  64. ret
  65. printcrlf:
  66. push af
  67. ld a, ASCII_CR
  68. call stdioPutC
  69. ld a, ASCII_LF
  70. call stdioPutC
  71. pop af
  72. ret
  73. ; Print the hex char in A
  74. printHex:
  75. push bc
  76. push hl
  77. ld hl, STDIO_HEX_FMT
  78. call fmtHexPair
  79. ld b, 2
  80. call printnstr
  81. pop hl
  82. pop bc
  83. ret
  84. ; Print the hex pair in HL
  85. printHexPair:
  86. push af
  87. ld a, h
  88. call printHex
  89. ld a, l
  90. call printHex
  91. pop af
  92. ret
  93. ; Call stdioGetC and put the result in the buffer. Sets Z according to whether
  94. ; the buffer is "complete", that is, whether CR or LF have been pressed or if
  95. ; the the buffer is full. Z is set if the line is "complete", unset if not.
  96. ; The next call to stdioReadC after a completed line will start a new line.
  97. ;
  98. ; This routine also takes care of echoing received characters back to the TTY.
  99. ;
  100. ; This routine doesn't wait after a typed char. If nothing is typed, we return
  101. ; immediately with Z flag unset.
  102. ;
  103. ; Note that this routine doesn't bother returning the typed character.
  104. stdioReadC:
  105. ; Let's wait until something is typed.
  106. call stdioGetC
  107. ret nz ; nothing typed? nothing to do
  108. ; got it. Now, is it a CR or LF?
  109. cp ASCII_CR
  110. jr z, .complete ; char is CR? buffer complete!
  111. cp ASCII_LF
  112. jr z, .complete
  113. cp ASCII_DEL
  114. jr z, .delchr
  115. cp ASCII_BS
  116. jr z, .delchr
  117. ; Echo the received character right away so that we see what we type
  118. call stdioPutC
  119. ; Ok, gotta add it do the buffer
  120. ; save char for later
  121. ex af, af'
  122. ld a, (STDIO_BUFIDX)
  123. push hl ; --> lvl 1
  124. ld hl, STDIO_BUF
  125. ; make HL point to dest spot
  126. call addHL
  127. ; Write our char down
  128. ex af, af'
  129. ld (hl), a
  130. ; follow up with a null char
  131. inc hl
  132. xor a
  133. ld (hl), a
  134. pop hl ; <-- lvl 1
  135. ; inc idx, which still is in AF'
  136. ex af, af'
  137. inc a
  138. cp STDIO_BUFSIZE-1 ; -1 is because we always want to keep our
  139. ; last char at zero.
  140. jr z, .complete ; end of buffer reached? buffer is full.
  141. ; not complete. save idx back
  142. ld (STDIO_BUFIDX), a
  143. ; Z already unset
  144. ret
  145. .complete:
  146. ; The line in our buffer is complete.
  147. ; But before we do that, let's take care of a special case: the empty
  148. ; line. If we didn't add any character since the last "complete", then
  149. ; our buffer's content is the content from the last time. Let's set this
  150. ; to an empty string.
  151. ld a, (STDIO_BUFIDX)
  152. or a
  153. jr nz, .completeSkip
  154. ld (STDIO_BUF), a
  155. .completeSkip:
  156. xor a ; sets Z
  157. ld (STDIO_BUFIDX), a
  158. ret
  159. .delchr:
  160. ld a, (STDIO_BUFIDX)
  161. or a
  162. jp z, unsetZ ; buf empty? nothing to do
  163. ; buffer not empty, let's go back one char and set a null char there.
  164. dec a
  165. ld (STDIO_BUFIDX), a
  166. push hl ;<|
  167. ld hl, STDIO_BUF ; |
  168. ; make HL point to dest spot |
  169. call addHL ; |
  170. xor a ; |
  171. ld (hl), a ; |
  172. pop hl ;<|
  173. ; Char deleted in buffer, now send BS + space + BS for the terminal
  174. ; to clear its previous char
  175. ld a, ASCII_BS
  176. call stdioPutC
  177. ld a, ' '
  178. call stdioPutC
  179. ld a, ASCII_BS
  180. call stdioPutC
  181. jp unsetZ
  182. ; Make HL point to the line buffer. It is always null terminated.
  183. stdioGetLine:
  184. ld hl, STDIO_BUF
  185. ret
  186. ; Repeatedly call stdioReadC until Z is set, then make HL point to the read
  187. ; buffer.
  188. stdioReadLine:
  189. call stdioReadC
  190. jr nz, stdioReadLine
  191. ld hl, STDIO_BUF
  192. ret