Mirror of CollapseOS
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

285 lignes
5.5KB

  1. ; shell
  2. ;
  3. ; Runs a shell over an asynchronous communication interface adapter (ACIA).
  4. ; for now, this unit is tightly coupled to acia.asm, but it will eventually be
  5. ; more general than that.
  6. ; Status: incomplete. As it is now, it spits a welcome prompt, wait for input
  7. ; and compare the first 4 chars of the input with a command table and call the
  8. ; appropriate routine if it's found, an error if it's not.
  9. ;
  10. ; Commands, for now, are dummy.
  11. ;
  12. ; See constants below for error codes.
  13. ;
  14. ; All numerical values in the Collapse OS shell are represented and parsed in
  15. ; hexadecimal form, without prefix or suffix.
  16. ; *** CONSTS ***
  17. ; number of entries in shellCmdTbl
  18. SHELL_CMD_COUNT .equ 2
  19. ; The command that was type isn't known to the shell
  20. SHELL_ERR_UNKNOWN_CMD .equ 0x01
  21. ; Arguments for the command weren't properly formatted
  22. SHELL_ERR_BAD_ARGS .equ 0x02
  23. ; Size of the shell command buffer. If a typed command reaches this size, the
  24. ; command is flushed immediately (same as pressing return).
  25. SHELL_BUFSIZE .equ 0x20
  26. ; *** VARIABLES ***
  27. ; Memory address that the shell is currently "pointing at" for peek and deek
  28. ; operations. Set with seek.
  29. SHELL_MEM_PTR .equ SHELL_RAMSTART
  30. ; Used to store formatted hex values just before printing it.
  31. SHELL_HEX_FMT .equ SHELL_MEM_PTR+2
  32. ; Command buffer. We read types chars into this buffer until return is pressed
  33. ; This buffer is null-terminated and we don't keep an index around: we look
  34. ; for the null-termination every time we write to it. Simpler that way.
  35. SHELL_BUF .equ SHELL_HEX_FMT+2
  36. SHELL_RAMEND .equ SHELL_BUF+SHELL_BUFSIZE
  37. ; *** CODE ***
  38. shellInit:
  39. xor a
  40. ld (SHELL_MEM_PTR), a
  41. ld (SHELL_BUF), a
  42. ; print prompt
  43. ld hl, .prompt
  44. call printstr
  45. call printcrlf
  46. ret
  47. .prompt:
  48. .db "Collapse OS", 0
  49. shellLoop:
  50. ; First, let's wait until something is typed.
  51. call aciaGetC
  52. ; got it. Now, is it a CR or LF?
  53. cp ASCII_CR
  54. jr z, .do ; char is CR? do!
  55. cp ASCII_LF
  56. jr z, .do ; char is LF? do!
  57. ; Ok, gotta add it do the buffer
  58. ; save char for later
  59. ex af, af'
  60. ld hl, SHELL_BUF
  61. call findnull ; HL points to where we need to write
  62. ; A is the number of chars in the buf
  63. cp SHELL_BUFSIZE
  64. jr z, .do ; A == bufsize? then our buffer is full. do!
  65. ; bring the char back in A
  66. ex af, af'
  67. ; Buffer not full, not CR or LF. Let's put that char in our buffer and
  68. ; read again.
  69. ld (hl), a
  70. ; Now, write a zero to the next byte to properly terminate our string.
  71. inc hl
  72. xor a
  73. ld (hl), a
  74. jr shellLoop
  75. .do:
  76. ld hl, SHELL_BUF
  77. call shellParse
  78. ; empty our buffer by writing a zero to its first char
  79. xor a
  80. ld (hl), a
  81. jr shellLoop
  82. printcrlf:
  83. ld a, ASCII_CR
  84. call aciaPutC
  85. ld a, ASCII_LF
  86. call aciaPutC
  87. ret
  88. ; Parse command (null terminated) at HL and calls it
  89. shellParse:
  90. push af
  91. push bc
  92. push de
  93. push hl
  94. ld de, shellCmdTbl
  95. ld a, SHELL_CMD_COUNT
  96. ld b, a
  97. .loop:
  98. ld a, 4 ; 4 chars to compare
  99. call strncmp
  100. jr z, .found
  101. ld a, 6
  102. call addDE
  103. djnz .loop
  104. ; exhausted loop? not found
  105. ld a, SHELL_ERR_UNKNOWN_CMD
  106. call shellPrintErr
  107. jr .end
  108. .found:
  109. ; all right, we're almost ready to call the cmd. Let's just have DE
  110. ; point to the cmd jump line.
  111. ld a, 4
  112. call addDE
  113. ; Now, let's swap HL and DE because, welll because that's how we're set.
  114. ex hl, de ; HL = jump line, DE = cmd str pointer
  115. ; Before we call our command, we want to set up the pointer to the arg
  116. ; list. Normally, it's DE+5 (DE+4 is the space) unless DE+4 is null,
  117. ; which means no arg.
  118. ld a, 4
  119. call addDE
  120. ld a, (DE)
  121. cp 0
  122. jr z, .noarg ; char is null? we have no arg
  123. inc de
  124. .noarg:
  125. ; DE points to args, HL points to jump line. Ready to roll!
  126. call jumpHL
  127. .end:
  128. pop hl
  129. pop de
  130. pop bc
  131. pop af
  132. ret
  133. ; Print the error code set in A (in hex)
  134. shellPrintErr:
  135. push af
  136. push hl
  137. ld hl, .str
  138. call printstr
  139. ld hl, SHELL_HEX_FMT
  140. call fmtHexPair
  141. ld a, 2
  142. call printnstr
  143. call printcrlf
  144. pop hl
  145. pop af
  146. ret
  147. .str:
  148. .db "ERR ", 0
  149. ; *** COMMANDS ***
  150. ; When these commands are called, DE points to the first character of the
  151. ; command args.
  152. ; Set memory pointer to the specified address (word).
  153. ; Example: seek 01fe
  154. shellSeek:
  155. push af
  156. push de
  157. push hl
  158. ex de, hl
  159. call parseHexPair
  160. jr c, .error
  161. ; z80 is little endian. in a "ld hl, (nn)" op, L is loaded from the
  162. ; first byte, H is loaded from the second
  163. ld (SHELL_MEM_PTR+1), a
  164. inc hl
  165. inc hl
  166. call parseHexPair
  167. jr c, .error
  168. ld (SHELL_MEM_PTR), a
  169. jr .success
  170. .error:
  171. ld a, SHELL_ERR_BAD_ARGS
  172. call shellPrintErr
  173. jr .end
  174. .success:
  175. ld a, (SHELL_MEM_PTR+1)
  176. ld hl, SHELL_HEX_FMT
  177. call fmtHexPair
  178. ld a, 2
  179. call printnstr
  180. ld a, (SHELL_MEM_PTR)
  181. call fmtHexPair
  182. ld a, 2
  183. call printnstr
  184. call printcrlf
  185. .end:
  186. pop hl
  187. pop de
  188. pop af
  189. ret
  190. ; peek byte where memory pointer points to any display its value. If the
  191. ; optional numerical byte arg is supplied, this number of bytes will be printed
  192. ;
  193. ; Example: peek 2 (will print 2 bytes)
  194. shellPeek:
  195. push af
  196. push bc
  197. push de
  198. push hl
  199. ld b, 1 ; by default, we run the loop once
  200. ld a, (de)
  201. cp 0
  202. jr z, .success ; no arg? don't try to parse
  203. ex de, hl
  204. call parseHexPair
  205. jr c, .error
  206. cp 0
  207. jr z, .error ; zero isn't a good arg, error
  208. ld b, a ; loop the number of times specified in arg
  209. jr .success
  210. .error:
  211. ld a, SHELL_ERR_BAD_ARGS
  212. call shellPrintErr
  213. jr .end
  214. .success:
  215. ld hl, (SHELL_MEM_PTR)
  216. .loop: ld a, (hl)
  217. ex hl, de
  218. ld hl, SHELL_HEX_FMT
  219. call fmtHexPair
  220. ld a, 2
  221. call printnstr
  222. ex hl, de
  223. inc hl
  224. djnz .loop
  225. call printcrlf
  226. .end:
  227. pop hl
  228. pop de
  229. pop bc
  230. pop af
  231. ret
  232. ; Format: 4 bytes name followed by 2 bytes jump. fill names with zeroes
  233. shellCmdTbl:
  234. .db "seek"
  235. jr shellSeek
  236. .db "peek"
  237. jr shellPeek