home *** CD-ROM | disk | FTP | other *** search
/ Transactor / Transactor_27_1988_Transactor_Publishing.d64 / ml.sda / HUFF.SRC (.txt) next >
Commodore BASIC  |  2023-02-26  |  10KB  |  342 lines

  1. 10 rem save"huff.src"
  2. 20 sys700
  3. 30 *=49152
  4. 40 .opt oo
  5. 50 fstat = $90; file status
  6. 100 getin = $ffe4
  7. 101 chkin = $ffc6
  8. 102 chrin = $ffcf
  9. 103 clrchn = $ffcc
  10. 104 close = $ffc3
  11. 105 chkout = $ffc9
  12. 106 chrout = $ffd2
  13. 149 bb = $c500
  14. 150 cfreqlo = bb+0;  characters' frequency
  15. 151 cfreqhi = bb+$100
  16. 152 ccode = bb+$200; code (00=0, ff=1)
  17. 153 cpnode = bb+$300;  parent node
  18. 154 nfreqlo = bb+$400;  nodes' freq
  19. 155 nfreqhi = bb+$500
  20. 156 ncode = bb+$600; code
  21. 157 npnode = bb+$700; parent (0=top)
  22. 158 list = bb+$800;  sorted list
  23. 159 type = bb+$900;  type 00=char, ff=node
  24. 160 hbits = bb+$a00;  my own stack
  25. 170 ch0type = bb+0;  reused variable space--child 0 type
  26. 172 ch0name = bb+$100;  child 0 name
  27. 174 ch1type = bb+$200
  28. 176 ch1name = bb+$300
  29. 200 jmp epass1; encode pass one
  30. 210 jmp epass2; encode pass two
  31. 220 jmp decode; decode
  32. 230 ;
  33. 250 epass1 = *
  34. 260 ldx #2:jsr chkin;  open channel 2 for input
  35. 265 jsr zeromem;  zero out memory
  36. 270 jsr countem;  count the bytes
  37. 272 lda #2:jsr close:jsr clrchn;  close up channel 2
  38. 275 jsr sortem;  sort the list
  39. 280 jsr maketree;  build the tree
  40. 285 jsr node0;  the tip of the tree
  41. 290 rts
  42. 299 ;
  43. 300 zeromem = *
  44. 310 lda #0:tay
  45. 320 zeloop sta cfreqlo,y
  46. 321 sta cfreqhi,y
  47. 322 sta ccode,y
  48. 323 sta cpnode,y
  49. 324 sta ncode,y
  50. 325 sta type,y
  51. 326 sta list,y
  52. 327 dey:bne zeloop
  53. 330 sta filelen:sta filelen+1:sta numchar:sta numnode
  54. 335 inc numnode;  save node 0 for the top
  55. 340 rts
  56. 349 ;
  57. 350 countem = *
  58. 360 jsr chrin;  get a character from disk
  59. 364 tax;  index by .x
  60. 366 inc cfreqlo,x;  one more in that slot
  61. 368 bne bytecount:inc cfreqhi,x;  if 0, then inc the high byte
  62. 370 bytecount inc filelen:bne cotest:inc filelen+1
  63. 380 cotest ldy fstat; file status (0 = more to come)
  64. 382 beq countem;  (NULL) back for more bytes
  65. 383 ldx filelen:lda filelen+1:jsr $bdcd:lda #62:jsr chrout; print length, >
  66. 384 rts;
  67. 399 ;
  68. 400 sortem = *
  69. 410 ldy #0
  70. 412 sty listlen;  used by the isort routine
  71. 413 sty lc
  72. 415 soloop ldy lc:lda cfreqlo,y:ora cfreqhi,y;  check if freq <> 0
  73. 416 beq nochar;  if eq, then no characters
  74. 418 tya;  add it to the list
  75. 420 ldy numchar:sta list,y;  this is the ascii code
  76. 422 inc numchar;  one more character
  77. 424 jsr isort;  insertion sort
  78. 426 inc listlen;  the list has one more member
  79. 428 nochar inc lc:bne soloop;  keep (NULL)ing with lc 0 to 255
  80. 430 rts
  81. 440 isort = *
  82. 450 ldy listlen;  length of the list
  83. 452 bne is01;
  84. 454 rts;  if = 0, skip this
  85. 456 is01 lda list,y:sta islist:tax:lda type,y:sta istype;  save these values
  86. 458 bne anode;  if <>0, it's a node
  87. 460 lda cfreqlo,x:sta islo:lda cfreqhi,x:sta ishi; save frequencies
  88. 462 jmp is02;  (NULL) compare them
  89. 464 anode lda nfreqlo,x:sta islo:lda nfreqhi,x:sta ishi; save frequencies
  90. 466 is02 = *
  91. 468 dey;  count backward in the list
  92. 470 ldx list,y:lda type,y
  93. 472 bne anode2;  another node
  94. 474 lda cfreqlo,x:sta testlo:lda cfreqhi,x:sta testhi:jmp is03
  95. 476 anode2 lda nfreqlo,x:sta testlo:lda nfreqhi,x:sta testhi
  96. 478 is03 = *
  97. 480 lda ishi:cmp testhi;  compare
  98. 482 bcc insert;  insert in the list here
  99. 484 bne is04;  keep looping, maybe
  100. 486 lda islo:cmp testlo;  not sure, so check low byte
  101. 488 beq insert;  if equal, insert
  102. 490 bcc insert;  if islo < testlo, insert
  103. 492 ;  else drop through
  104. 494 is04 cpy #0:bne is02;  if .y = 0, drop through to insert
  105. 496 dey
  106. 498 insert = *
  107. 500 iny:sty tempy;  save the value
  108. 501 cpy listlen:bne doit:rts
  109. 502 doit ldy listlen;  start at the end
  110. 504 isloop dey:lda list,y:iny:sta list,y:dey
  111. 506 lda type,y:iny:sta type,y:dey
  112. 508 cpy tempy:bne isloop
  113. 510 lda islist:sta list,y:lda istype:sta type,y
  114. 512 rts
  115. 549 ;
  116. 550 maketree = *
  117. 560 ldx numchar:dex:stx listlen
  118. 565 mamain ldy listlen
  119. 570 jsr fixcn;  fix the codes & nodes for y and y-1
  120. 572 jsr fixfreq;  fix the new node's frequency
  121. 574 jsr addnode;  add the node to the list
  122. 576 jsr isort;  sort it
  123. 578 inc numnode
  124. 580 lda listlen:cmp #1:bne mamain;  quit when only two nodes remain
  125. 582 rts
  126. 584 fixcn = *
  127. 586 ldy listlen
  128. 588 lda #$ff;  this means code = 1
  129. 590 jsr fixsr;  set the code/node
  130. 591 dey:lda #0:jsr fixsr; code = 0 on the left
  131. 592 rts
  132. 600 fixsr ldx type,y:beq tsachar;  itsa char
  133. 601 ldx list,y
  134. 602 sta ncode,x;  it's a node
  135. 604 lda numnode:sta npnode,x:rts
  136. 606 tsachar ldx list,y:sta ccode,x:lda numnode:sta cpnode,x:rts
  137. 620 fixfreq = *
  138. 630 ldy listlen
  139. 632 ldx type,y:beq anotchar;  another char
  140. 634 ldx list,y:lda nfreqlo,x:sta low1:lda nfreqhi,x:sta hi1
  141. 636 jmp ahead
  142. 638 anotchar ldx list,y:lda cfreqlo,x:sta low1:lda cfreqhi,x:sta hi1
  143. 640 ahead dey:ldx type,y:beq itschar;  another char
  144. 642 ldx list,y:lda nfreqlo,x:sta low2:lda nfreqhi,x:sta hi2
  145. 644 jmp addem
  146. 646 itschar ldx list,y:lda cfreqlo,x:sta low2:lda cfreqhi,x:sta hi2
  147. 648 addem ldx numnode:clc:lda low1:adc low2:sta nfreqlo,x
  148. 650 lda hi1:adc hi2:sta nfreqhi,x
  149. 652 rts
  150. 654 ;
  151. 670 addnode = *
  152. 672 dec listlen
  153. 674 ldx listlen:lda #$ff:sta type,x;  type of a parent is always a node
  154. 676 lda numnode:sta list,x;  add the node number to the list
  155. 678 rts
  156. 699 ;
  157. 700 node0 = *
  158. 710 ldy #1
  159. 712 ldx list,y
  160. 714 lda #$ff:sta ncode,x
  161. 716 lda #0:sta npnode,x;  the parent is node 0 at the top
  162. 718 dey:ldx list,y
  163. 720 sta ncode,x:sta npnode,x
  164. 722 rts
  165. 799 ;
  166. 800 epass2 = *
  167. 812 ldx #4:jsr chkout;  channel 4 for writing
  168. 814 lda #0:sta outlen:sta outlen+1;  zero out file length
  169. 816 jsr header;  send the header bytes
  170. 818 jsr encfile;  send the encoded file
  171. 820 lda #4:jsr close:lda #3:jsr close
  172. 822 jsr clrchn
  173. 824 ldx outlen:lda outlen+1:jsr $bdcd;  print crunched length
  174. 826 rts
  175. 828 ;
  176. 840 header = *
  177. 850 lda filelen:jsr chrout:lda filelen+1:jsr chrout;  length of input file
  178. 852 ldy #0:ldx #0
  179. 854 char0 lda cfreqlo,x:ora cfreqhi,x;  is this char in file
  180. 855 beq head0;  if no freq, doesn't exist
  181. 856 lda ccode,x:bne head0;  ignore $ff
  182. 857 txa:sta hbits,y:iny;  push on temp stack
  183. 858 head0 inx:bne char0
  184. 859 tya:pha:jsr chrout:jsr sendchar;  send # of 0children and then names
  185. 860 ;
  186. 862 ldy #0:ldx #0
  187. 866 char1 lda ccode,x:beq head1;  ignore $00
  188. 867 txa:sta hbits,y:iny;  push on temp stack
  189. 868 head1 inx:bne char1
  190. 869 tya:pha:jsr chrout:jsr sendchar;  send # of 1children and then names
  191. 870 ;
  192. 872 ldy #0:ldx #1
  193. 876 pnode0 lda ncode,x:bne head2;  ignore $ff
  194. 877 txa:sta hbits,y:iny;  push on temp stack
  195. 878 head2 inx:cpx numnode:bne pnode0
  196. 879 tya:pha:jsr chrout:jsr sendnode;  send # of 0nodes and then names
  197. 880 ;
  198. 882 ldy #0:ldx #1
  199. 886 pnode1 lda ncode,x:beq head3;  ignore $00
  200. 887 txa:sta hbits,y:iny;  push on temp stack
  201. 888 head3 inx:cpx numnode:bne pnode1
  202. 889 tya:pha:jsr chrout:jsr sendnode;  send # of 1nodes and then names
  203. 890 ;
  204. 891 ldy #4
  205. 892 addloop pla:clc:adc outlen:sta outlen
  206. 893 lda #0:adc outlen+1:sta outlen+1:dey:bne addloop
  207. 894 asl outlen:rol outlen+1:clc:lda outlen:adc #6:sta outlen
  208. 895 lda #0:adc outlen+1:sta outlen+1:rts
  209. 896 ;
  210. 902 sendchar dey:ldx hbits,y:lda cpnode,x:jsr chrout;  send parent's name
  211. 903 txa:jsr chrout;  send name
  212. 904 cpy #0:bne sendchar:rts
  213. 905 ;
  214. 906 sendnode dey:ldx hbits,y:lda npnode,x:jsr chrout;  send parent's name
  215. 907 txa:jsr chrout;  send name
  216. 908 cpy #0:bne sendnode:rts
  217. 909 ;
  218. 950 encfile = *
  219. 960 inc filelen+1
  220. 970 lda #8:sta outbits;  8 bits in a byte
  221. 972 enloop jsr walkup;  walk up the tree
  222. 974 jsr walkdown;  output the byte
  223. 976 dec filelen:bne enloop
  224. 978 dec filelen+1:bne enloop;  keep (NULL)ing while the characters are coming
  225. 980 ldx outbits:cpx #8:beq finish
  226. 982 lastone asl outbyte:dex:bne lastone
  227. 984 ldx #4:jsr chkout:lda outbyte:jsr chrout;  send the last one
  228. 985 inc outlen:bne finish:inc outlen+1
  229. 986 finish rts
  230. 988 ;
  231. 990 walkup = *
  232. 1000 ldx #3:jsr chkin:jsr chrin:tax;  get the next input byte
  233. 1002 ldy #0
  234. 1004 lda ccode,x:sta hbits,y:iny;  first code
  235. 1006 lda cpnode,x:beq upout;  if parent is zero, exit
  236. 1008 uploop tax
  237. 1010 lda ncode,x:sta hbits,y:iny;  get the code and save it
  238. 1012 lda npnode,x:bne uploop;  branch if not parent 0
  239. 1014 upout dey:rts
  240. 1016 ;
  241. 1020 walkdown = *
  242. 1030 lda hbits,y
  243. 1032 rol:rol outbyte;  build a byte a bit at a time
  244. 1034 dec outbits
  245. 1036 beq (NULL)tabyte;  if outbits = 0, 8 bits are ready
  246. 1038 downtest dey:cpy #255:bne walkdown
  247. 1040 rts;  end of walkdown
  248. 1042 ;
  249. 1044 (NULL)tabyte sty tempy
  250. 1045 ldx #4:jsr chkout:lda outbyte:jsr chrout;  send a character
  251. 1046 ldy tempy:inc outlen;  increment length of output file
  252. 1048 bne reset8:inc outlen+1
  253. 1050 reset8 lda #8:sta outbits
  254. 1052 bne downtest;  branch always
  255. 1054 ;
  256. 1100 decode = *
  257. 1110 ldx #5:jsr chkin;  channel 5 is input
  258. 1120 jsr chrin:sta filelen:jsr chrin:sta filelen+1:inc filelen+1
  259. 1122 chi0 jsr chrin;  how many child0's
  260. 1124 beq chi1:sta lc;  loop counter
  261. 1126 delp1 jsr chrin:tax:jsr chrin
  262. 1128 sta ch0name,x:lda #0:sta ch0type,x
  263. 1129 dec lc:bne delp1
  264. 1130 ;
  265. 1132 chi1 jsr chrin;  how many child1's
  266. 1134 beq par0:sta lc;  loop counter
  267. 1136 delp2 jsr chrin:tax:jsr chrin
  268. 1138 sta ch1name,x:lda #0:sta ch1type,x
  269. 1139 dec lc:bne delp2
  270. 1140 ;
  271. 1142 par0 jsr chrin;  how many parent0's
  272. 1144 beq par1:sta lc;  loop counter
  273. 1146 delp3 jsr chrin:tax:jsr chrin
  274. 1148 sta ch0name,x:lda #$ff:sta ch0type,x
  275. 1149 dec lc:bne delp3
  276. 1150 ;
  277. 1152 par1 jsr chrin;  how many parent1's
  278. 1154 beq bitter:sta lc;  loop counter
  279. 1156 delp4 jsr chrin:tax:jsr chrin
  280. 1158 sta ch1name,x:lda #$ff:sta ch1type,x
  281. 1159 dec lc:bne delp4
  282. 1160 ;
  283. 1170 bitter = *
  284. 1180 lda #0:sta node
  285. 1182 outloop ldx #5:jsr chkin:jsr chrin
  286. 1184 sta huffer;  (NULL)t 8 bits
  287. 1188 lda #8:sta numbits
  288. 1190 inloop ldy node;  the node is the parent
  289. 1192 rol huffer;  get a bit into carry
  290. 1194 bcs itsa1;  if cs, the bit is 1
  291. 1196 itsa0 = *
  292. 1198 lda ch0name,y;  get the name of child 0
  293. 1200 sta node;  who is the new parent/node
  294. 1202 ldx ch0type,y;  does it terminate
  295. 1204 beq printit;  yes, (NULL) print
  296. 1206 nextbit = *
  297. 1208 dec numbits
  298. 1210 bne inloop
  299. 1212 beq outloop
  300. 1216 ;
  301. 1220 itsa1 = *
  302. 1222 lda ch1name,y;  get the name of child 1
  303. 1224 sta node;  who is the new parent/node
  304. 1226 ldx ch1type,y;  does it terminate
  305. 1228 beq printit;  yes, (NULL) print
  306. 1230 bne nextbit
  307. 1240 ;
  308. 1250 printit = *
  309. 1260 ldx #6:jsr chkout
  310. 1262 lda node:jsr chrout
  311. 1264 dec filelen:bne tothetop:dec filelen+1
  312. 1266 tothetop lda #0:sta node;  back up to node 0 at the top
  313. 1268 lda filelen:ora filelen+1:bne nextbit
  314. 1270 ;
  315. 1280 cleanup = *
  316. 1290 lda #5:jsr close:lda #6:jsr close
  317. 1292 jsr clrchn
  318. 1294 rts
  319. 1296 ;
  320. 9000 filelen = *;  length of src file
  321. 9002 numchar = *+2;  # of chars
  322. 9004 numnode = *+3;  # of nodes
  323. 9006 lc = *+4;  loop counter
  324. 9008 listlen = *+5;  length of list, used by isort routine
  325. 9010 islist = *+6;  temporary storage for list, type, freqlo, and freqhi
  326. 9012 istype = *+7
  327. 9014 islo = *+8
  328. 9016 ishi = *+9
  329. 9018 testlo = *+10;  islo/hi is tested against testlo/hi for insertion sort
  330. 9020 testhi = *+11
  331. 9022 tempy = *+12;  temp storage for .y
  332. 9024 low1 = islo
  333. 9026 hi1 = ishi
  334. 9028 low2 = testlo
  335. 9030 hi2 = testhi
  336. 9040 outlen = *+13;  output file length
  337. 9042 outbyte = *+15;  the (crunched) huffman byte to send out
  338. 9044 outbits = *+16;  number of bits (when it = 8, the byte gets sent)
  339. 9046 huffer = islo;  huffman byte (when uncrunching)
  340. 9048 node = ishi;  the child node (either another node or a char)
  341. 9050 numbits = testlo;  number of bits
  342.