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.

258 lines
4.6KB

  1. ; core
  2. ;
  3. ; Routines used by pretty much all parts. You will want to include it first
  4. ; in your glue file.
  5. ; *** CONSTS ***
  6. .equ ASCII_BS 0x08
  7. .equ ASCII_CR 0x0d
  8. .equ ASCII_LF 0x0a
  9. .equ ASCII_DEL 0x7f
  10. ; *** DATA ***
  11. ; Useful data to point to, when a pointer is needed.
  12. P_NULL: .db 0
  13. ; *** REGISTER FIDDLING ***
  14. ; add the value of A into DE
  15. addDE:
  16. push af
  17. add a, e
  18. jr nc, .end ; no carry? skip inc
  19. inc d
  20. .end:
  21. ld e, a
  22. pop af
  23. noop: ; piggy backing on the first "ret" we have
  24. ret
  25. ; copy (HL) into DE, then exchange the two, utilising the optimised HL instructions.
  26. ; ld must be done little endian, so least significant byte first.
  27. intoHL:
  28. push de
  29. ld e, (hl)
  30. inc hl
  31. ld d, (hl)
  32. ex de, hl
  33. pop de
  34. ret
  35. intoDE:
  36. ex de, hl
  37. call intoHL
  38. ex de, hl ; de preserved by intoHL, so no push/pop needed
  39. ret
  40. intoIX:
  41. push ix
  42. ex (sp), hl ;swap hl with ix, on the stack
  43. call intoHL
  44. ex (sp), hl ;restore hl from stack
  45. pop ix
  46. ret
  47. ; add the value of A into HL
  48. addHL:
  49. push af
  50. add a, l
  51. jr nc, .end ; no carry? skip inc
  52. inc h
  53. .end:
  54. ld l, a
  55. pop af
  56. ret
  57. ; subtract the value of A from HL
  58. subHL:
  59. push af
  60. ; To avoid having to swap L and A, we sub "backwards", that is, we add
  61. ; a NEGated value. This means that the carry flag is inverted
  62. neg
  63. add a, l
  64. jr c, .end ; if carry, no carry. :)
  65. dec h
  66. .end:
  67. ld l, a
  68. pop af
  69. ret
  70. ; Compare HL with DE and sets Z and C in the same way as a regular cp X where
  71. ; HL is A and DE is X.
  72. ; A is preserved through some register hocus pocus: having cpHLDE destroying
  73. ; A bit me too many times.
  74. cpHLDE:
  75. push bc
  76. ld b, a ; preserve A
  77. ld a, h
  78. cp d
  79. jr nz, .end ; if not equal, flags are correct
  80. ld a, l
  81. cp e
  82. ; flags are correct
  83. .end:
  84. ; restore A but don't touch flags
  85. ld a, b
  86. pop bc
  87. ret
  88. ; Write the contents of HL in (DE)
  89. writeHLinDE:
  90. push af
  91. ld a, l
  92. ld (de), a
  93. inc de
  94. ld a, h
  95. ld (de), a
  96. dec de
  97. pop af
  98. ret
  99. ; Call the method (IX) is a pointer to. In other words, call intoIX before
  100. ; callIX
  101. callIXI:
  102. push ix
  103. call intoIX
  104. call callIX
  105. pop ix
  106. ret
  107. ; jump to the location pointed to by IX. This allows us to call IX instead of
  108. ; just jumping it. We use IX because we seldom use this for arguments.
  109. callIX:
  110. jp (ix)
  111. callIY:
  112. jp (iy)
  113. ; Ensures that Z is unset (more complicated than it sounds...)
  114. unsetZ:
  115. push bc
  116. ld b, a
  117. inc b
  118. cp b
  119. pop bc
  120. ret
  121. ; *** STRINGS ***
  122. ; Fill B bytes at (HL) with A
  123. fill:
  124. push bc
  125. push hl
  126. .loop:
  127. ld (hl), a
  128. inc hl
  129. djnz .loop
  130. pop hl
  131. pop bc
  132. ret
  133. ; Increase HL until the memory address it points to is equal to A for a maximum
  134. ; of 0xff bytes. Returns the new HL value as well as the number of bytes
  135. ; iterated in A.
  136. ; If a null char is encountered before we find A, processing is stopped in the
  137. ; same way as if we found our char (so, we look for A *or* 0)
  138. ; Set Z if the character is found. Unsets it if not
  139. findchar:
  140. push bc
  141. ld c, a ; let's use C as our cp target
  142. ld a, 0xff
  143. ld b, a
  144. .loop: ld a, (hl)
  145. cp c
  146. jr z, .match
  147. or a ; cp 0
  148. jr z, .nomatch
  149. inc hl
  150. djnz .loop
  151. .nomatch:
  152. call unsetZ
  153. jr .end
  154. .match:
  155. ; We ran 0xff-B loops. That's the result that goes in A.
  156. ld a, 0xff
  157. sub b
  158. cp a ; ensure Z
  159. .end:
  160. pop bc
  161. ret
  162. ; Format the lower nibble of A into a hex char and stores the result in A.
  163. fmtHex:
  164. and 0xf
  165. cp 10
  166. jr nc, .alpha ; if >= 10, we have alpha
  167. add a, '0'
  168. ret
  169. .alpha:
  170. add a, 'A'-10
  171. ret
  172. ; Formats value in A into a string hex pair. Stores it in the memory location
  173. ; that HL points to. Does *not* add a null char at the end.
  174. fmtHexPair:
  175. push af
  176. ; let's start with the rightmost char
  177. inc hl
  178. call fmtHex
  179. ld (hl), a
  180. ; and now with the leftmost
  181. dec hl
  182. pop af
  183. push af
  184. and 0xf0
  185. rra \ rra \ rra \ rra
  186. call fmtHex
  187. ld (hl), a
  188. pop af
  189. ret
  190. ; Compares strings pointed to by HL and DE up to A count of characters. If
  191. ; equal, Z is set. If not equal, Z is reset.
  192. strncmp:
  193. push bc
  194. push hl
  195. push de
  196. ld b, a
  197. .loop:
  198. ld a, (de)
  199. cp (hl)
  200. jr nz, .end ; not equal? break early. NZ is carried out
  201. ; to the called
  202. cp 0 ; If our chars are null, stop the cmp
  203. jr z, .end ; The positive result will be carried to the
  204. ; caller
  205. inc hl
  206. inc de
  207. djnz .loop
  208. ; We went through all chars with success, but our current Z flag is
  209. ; unset because of the cp 0. Let's do a dummy CP to set the Z flag.
  210. cp a
  211. .end:
  212. pop de
  213. pop hl
  214. pop bc
  215. ; Because we don't call anything else than CP that modify the Z flag,
  216. ; our Z value will be that of the last cp (reset if we broke the loop
  217. ; early, set otherwise)
  218. ret
  219. ; Transforms the character in A, if it's in the a-z range, into its upcase
  220. ; version.
  221. upcase:
  222. cp 'a'
  223. ret c ; A < 'a'. nothing to do
  224. cp 'z'+1
  225. ret nc ; A >= 'z'+1. nothing to do
  226. ; 'a' - 'A' == 0x20
  227. sub 0x20
  228. ret