zlz_comp.z80 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. zlz_comp:
  2. ;Inputs:
  3. ; HL points to the input data
  4. ; DE points to the output
  5. ; BC is the size of the input
  6. ;Outputs:
  7. ; HL points to the byte after the input
  8. ; DE points to the byte afterthe compressed data
  9. ; BC is 0
  10. ;Destroys:
  11. ; AF,IX
  12. ;
  13. ;This routine has input and output like LDIR,
  14. ;except if LDIR as compressing as it goes.
  15. ;
  16. ld a,ZLZ_MIN_RUN
  17. inc b
  18. dec b
  19. jr nz,+_
  20. cp c
  21. jr z,$+4
  22. jr c,+_
  23. ld a,c
  24. ld (de),a
  25. inc de
  26. inc c
  27. dec c
  28. ret z
  29. ldir
  30. ret
  31. _:
  32. ld (zlz_base),hl
  33. ld (zlz_runstart),hl
  34. add a,l
  35. ld l,a
  36. jr nc,$+3
  37. inc h
  38. ld a,c
  39. sub ZLZ_MIN_RUN
  40. ld c,a
  41. jr nc,$+3
  42. dec b
  43. zlz_comp_loop:
  44. push bc
  45. ld (zlz_head),hl
  46. call zlz_findmatch
  47. inc b
  48. dec b
  49. jr nz,zlz_matched
  50. ld a,c
  51. cp ZLZ_MIN_RUN
  52. jr nc,zlz_matched
  53. ld hl,(zlz_head)
  54. pop bc
  55. cpi
  56. jp pe,zlz_comp_loop
  57. zlz_write_run:
  58. ;need to write the run from (zlz_head), size HL-(zlz_head)
  59. push hl
  60. push bc
  61. ld hl,(zlz_head)
  62. ld bc,(zlz_runstart)
  63. or a
  64. sbc hl,bc
  65. jr z,zlz_write_run_done
  66. ld b,h
  67. ld c,l
  68. ld a,l
  69. add a,a \ rl h
  70. add a,a \ rl h
  71. jr z,+_
  72. scf
  73. _:
  74. rra
  75. rra
  76. ld (de),a
  77. inc de
  78. jr z,+_
  79. ld a,h
  80. ld (de),a
  81. inc de
  82. _:
  83. ld hl,(zlz_runstart)
  84. ldir
  85. zlz_write_run_done:
  86. pop bc
  87. pop hl
  88. ld (zlz_runstart),hl
  89. ret
  90. zlz_matched:
  91. push bc
  92. call zlz_write_run
  93. pop bc
  94. push bc
  95. ;size then pointer
  96. ;Make sure the size doesn't exceed 13 bits
  97. ld a,c
  98. add a,a \ rl b
  99. add a,a \ rl b
  100. jr z,+_
  101. scf
  102. _:
  103. rra
  104. scf
  105. rra
  106. ld (de),a
  107. inc de
  108. jr z,+_
  109. ld a,b
  110. ld (de),a
  111. inc de
  112. _:
  113. ;Now we need to write the pointer
  114. ;this is an offset back from the data
  115. ;we want (zlz_head)-HL
  116. ld b,h
  117. ld c,l
  118. ld hl,(zlz_head)
  119. ;or a ;the rra above will reset the carry since the bottom bit of A was 0
  120. sbc hl,bc
  121. ld a,l
  122. add a,a \ rl h
  123. jr z,+_
  124. scf
  125. _:
  126. rra
  127. ld (de),a
  128. inc de
  129. jr z,+_
  130. ld a,h
  131. ld (de),a
  132. inc de
  133. _:
  134. pop bc
  135. ld hl,(zlz_head)
  136. add hl,bc
  137. ex (sp),hl
  138. ;or a
  139. sbc hl,bc
  140. ld b,h
  141. ld c,l
  142. pop hl
  143. ld (zlz_runstart),hl
  144. jp nz,zlz_comp_loop
  145. ret
  146. zlz_findmatch:
  147. push de
  148. ld (zlz_match_base),hl
  149. add hl,bc
  150. ld (zlz_top),hl
  151. sbc hl,bc
  152. ld de,(zlz_base)
  153. xor a
  154. ld (zlz_match_size),a
  155. ld (zlz_match_size+1),a
  156. sbc hl,de
  157. ld bc,1-ZLZ_MIN_RUN
  158. add hl,bc
  159. ld b,h
  160. ld c,l
  161. ex de,hl
  162. jr zlz_findmatch_loop_begin
  163. zlz_findmatch_loop:
  164. push hl
  165. push bc
  166. call +_
  167. pop bc
  168. pop hl
  169. zlz_findmatch_loop_begin:
  170. ;DE points to the data to find
  171. ;HL points to the data to search
  172. ;BC is the size of the data to search
  173. ld de,(zlz_match_base)
  174. ld a,(de)
  175. cpir
  176. jp pe,zlz_findmatch_loop
  177. zlz_findmatch_done:
  178. ld bc,(zlz_match_size)
  179. ld hl,(zlz_match_loc)
  180. pop de
  181. ret
  182. _:
  183. ;now we compare the rest of the string
  184. push hl
  185. inc de
  186. ld hl,(zlz_top)
  187. or a
  188. sbc hl,de
  189. ld b,h
  190. ld c,l
  191. pop hl
  192. jr z,zlz_match_complete
  193. push hl
  194. _:
  195. ld a,(de)
  196. inc de
  197. cpi
  198. jp po,+_
  199. jr z,-_
  200. _:
  201. ld hl,(zlz_match_base)
  202. ex de,hl
  203. ;or a
  204. sbc hl,de
  205. ld bc,(zlz_match_size)
  206. ;if HL>=BC, save the new match (if it is the same size as the previous match, then this one is closer, which can be better)
  207. scf
  208. sbc hl,bc
  209. pop de
  210. ret c
  211. add hl,bc
  212. ld (zlz_match_size),hl
  213. dec de
  214. ld (zlz_match_loc),de
  215. ret
  216. zlz_match_complete:
  217. ;can't get better than this, so we'll exit early
  218. ld hl,(zlz_match_base)
  219. ex de,hl
  220. ;or a
  221. sbc hl,de
  222. ld b,h
  223. ld c,l
  224. pop af ;return address
  225. pop af ;size left
  226. pop hl ;pointer to match
  227. pop de ;saved DE
  228. ret