compile.z80 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. ;If the numbers are 1 digit, the output will be larger :(
  2. ;If the numbers are 2 digits, the output will be the same size :|
  3. ;If the number is 3 digits, less than 256, the output will be smaller! (3 digits, but >=256 is same size :|)
  4. ;All other numbers will be more compact!
  5. ;
  6. ;When a comment/label is parsed, we need to instead copy it to an LUT at the back, along with the address where it would be inserted.
  7. ;If the "Lbl " command is come across, first search for if the label has already found.
  8. ; If yes, just replace it with a pointer value
  9. ; If no, then store a pointer of 0x0000, and in another LUT, if the name does not exist yet, add it along with the address, else append the address to it.
  10. ;Move Strings to the data section
  11. ;
  12. ;Parse through the source, looking for '.' or 'Lbl ' (0x3A and 0xD6, respectively)
  13. compile:
  14. ;A is passed in as the byte to parse
  15. ;DE is where to output
  16. ;HL is where the input is
  17. ;Be careful not to overlap or exceed data_top
  18. inc hl ;We are going to do nothing :P
  19. inc de
  20. ret
  21. cp 2Ah
  22. jp z,compile_string
  23. sub 3Ah
  24. add a,10
  25. jp c,compile_number
  26. inc hl
  27. inc de
  28. ret
  29. compile_string:
  30. ;move the string to the data section and replace with a relative pointer
  31. ;We are removing the starting quote, but adding 3 bytes for the pointer. Net gain of two bytes.
  32. ;We need to verify that we have two bytes available
  33. ld bc,2
  34. call enoughmem
  35. jp c,err_LowMem
  36. ;The easy way to do this is to copy the string to the data section, and leave a gap between the in_head and out_head
  37. ;However, if we only have three bytes or RAM available, and the string is 4 bytes, we'll be overwriting stuff!
  38. ;Instead, we'll copy the string to saveSScreen in up to 768 byte chunks, shift the source down copy the string to the end of the source (essentially rotating), then move the string data to the end
  39. ;It's slower, but better on RAM usage :)
  40. ;Save the pointers of the output and input
  41. inc hl
  42. push de
  43. ld (TempWord1),hl
  44. call GetGrammerStr
  45. inc bc
  46. ld hl,(TempWord1)
  47. ld (TempWord2),bc
  48. compile_str_loop:
  49. ld a,b
  50. sub 3
  51. jr c,compile_str_finalchunk
  52. ld b,a
  53. push bc
  54. ld bc,768
  55. ld de,saveSScreen
  56. ldir
  57. ;So now we move (end_of_src)-HL bytes at DE to (TempWord1)
  58. push de
  59. ex de,hl
  60. ld hl,(end_of_src)
  61. or a
  62. sbc hl,de
  63. ld b,h
  64. ld c,l
  65. pop hl
  66. ld de,(TempWord1)
  67. jr z,+_
  68. ldir
  69. _:
  70. pop bc
  71. jr compile_str_loop
  72. compile_str_finalchunk:
  73. ld a,b
  74. or c
  75. ld de,saveSScreen
  76. jr z,compile_str_adjust
  77. ldir
  78. ;So now we move (end_of_src)-HL bytes at DE to (TempWord1)
  79. push de
  80. ex de,hl
  81. ld hl,(end_of_src)
  82. or a
  83. sbc hl,de
  84. ld b,h
  85. ld c,l
  86. pop hl
  87. ld de,(TempWord1)
  88. jr z,compile_str_adjust
  89. ldir
  90. compile_str_adjust:
  91. ld hl,(data_top)
  92. ld bc,(TempWord2)
  93. or a
  94. sbc hl,bc
  95. ld (data_top),hl
  96. ex de,hl
  97. ld hl,(end_of_src)
  98. ld bc,(TempWord2)
  99. or a
  100. sbc hl,bc
  101. ld (end_of_src),hl
  102. ld a,b
  103. or c
  104. jr z,+_
  105. ldir
  106. _:
  107. ;Now we need to insert two bytes at (TempWord1)
  108. ld de,(TempWord1)
  109. ld hl,(end_of_src)
  110. sbc hl,de
  111. jr z,+_
  112. ld b,h
  113. ld c,l
  114. add hl,de
  115. ld d,h
  116. ld e,l
  117. inc de
  118. dec hl
  119. ldir
  120. _:
  121. ld hl,(end_of_src)
  122. inc hl
  123. inc hl
  124. ld (end_of_src),hl
  125. ld hl,(end_of_buffer)
  126. ld de,(data_top)
  127. sbc hl,de
  128. ex de,hl
  129. ;DE is the relative pointer
  130. ld hl,(TempWord2)
  131. dec hl
  132. ld (hl),tok_NegRelPtr
  133. inc hl
  134. ld (hl),e
  135. inc hl
  136. ld (hl),d
  137. inc hl
  138. ld d,h
  139. ld e,l
  140. ret
  141. compile_number:
  142. ;If it is an int, we need to replace with a uint8, uint16
  143. ;If it is a float, we need to move it to the data section and replace with a relative pointer
  144. inc hl
  145. inc de
  146. ret
  147. enoughmem:
  148. ;Returns nc if there are at least BC bytes available. Preserves registers.
  149. ;Need data_top-end_of_src>=BC
  150. ;We'll check data_top>=BC+end_of_src
  151. ;preserve HL
  152. push hl
  153. ld hl,(end_of_src)
  154. add hl,bc
  155. jr c,+_ ;checking for wayyy too much RAM
  156. ;preserve DE
  157. push de
  158. ex de,hl
  159. ld hl,(data_top)
  160. sbc hl,bc
  161. pop de
  162. _:
  163. pop hl
  164. ret