pst-ttup.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494
  1. | TIGCC Program Starter - ttunpack decompression support
  2. | Copyright (C) 2004-2005 Samuel Stearley, Kevin Kofler
  3. |
  4. | THE LICENSE:
  5. |
  6. | wxWindows Library Licence, Version 3.1
  7. | ======================================
  8. |
  9. | Copyright (C) 1998-2005 Julian Smart, Robert Roebling et al
  10. |
  11. | Everyone is permitted to copy and distribute verbatim copies
  12. | of this licence document, but changing it is not allowed.
  13. |
  14. | WXWINDOWS LIBRARY LICENCE
  15. | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
  16. |
  17. | This library is free software; you can redistribute it and/or modify it
  18. | under the terms of the GNU Library General Public Licence as published by
  19. | the Free Software Foundation; either version 2 of the Licence, or (at
  20. | your option) any later version.
  21. |
  22. | This library is distributed in the hope that it will be useful, but
  23. | WITHOUT ANY WARRANTY; without even the implied warranty of
  24. | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library
  25. | General Public Licence for more details.
  26. |
  27. | You should have received a copy of the GNU Library General Public Licence
  28. | along with this software, usually in a file named COPYING.LIB. If not,
  29. | write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  30. | Boston, MA 02111-1307 USA.
  31. |
  32. | EXCEPTION NOTICE
  33. |
  34. | 1. As a special exception, the copyright holders of this library give
  35. | permission for additional uses of the text contained in this release of
  36. | the library as licenced under the wxWindows Library Licence, applying
  37. | either version 3.1 of the Licence, or (at your option) any later version of
  38. | the Licence as published by the copyright holders of version
  39. | 3.1 of the Licence document.
  40. |
  41. | 2. The exception is that you may use, copy, link, modify and distribute
  42. | under your own terms, binary object code versions of works based
  43. | on the Library.
  44. |
  45. | 3. If you copy code from files distributed under the terms of the GNU
  46. | General Public Licence or the GNU Library General Public Licence into a
  47. | copy of this library, as this licence permits, the exception does not
  48. | apply to the code that you add in this way. To avoid misleading anyone as
  49. | to the status of such modified files, you must delete this exception
  50. | notice from such code and/or adjust the licensing conditions notice
  51. | accordingly.
  52. |
  53. | 4. If you write modifications of your own for this library, it is your
  54. | choice whether to permit this exception to apply to your modifications.
  55. | If you do not wish that, you must delete the exception notice from such
  56. | code and/or adjust the licensing conditions notice accordingly.
  57. | GET_UNCOMPRESSED_SIZE inline function
  58. | INPUT: %a3.l: pointer to compressed data
  59. | OUTPUT: %d6.l: uncompressed size
  60. | SIDE EFFECTS: throws a Data Type error if not a valid compressed program
  61. | may throw a Memory error
  62. | may advance %a3 for later decompression
  63. | DESTROYS: %d0-%d2/%a0-%a1
  64. .macro GET_UNCOMPRESSED_SIZE
  65. | Get the length of the variable.
  66. moveq.l #0,%d6
  67. move.w (%a3)+,%d6
  68. | Get a pointer to the data type of the variable.
  69. lea.l -1(%a3,%d6.l),%a0
  70. | Check if it has type "ppg".
  71. cmp.b #0xf8,(%a0)
  72. jbne invalid_archive
  73. tst.b -(%a0)
  74. jbne invalid_archive
  75. cmp.b #'g',-(%a0)
  76. jbne invalid_archive
  77. moveq.l #'p',%d0
  78. cmp.b -(%a0),%d0
  79. jbne invalid_archive
  80. cmp.b -(%a0),%d0
  81. jbne invalid_archive
  82. tst.b -(%a0)
  83. jbeq valid_archive
  84. | We don't need to check the magic number in the ttunpack header,
  85. | the decompression routine does that already.
  86. invalid_archive:
  87. .word 0xA000+210 | ER_DATATYPE
  88. valid_archive:
  89. | Get the uncompressed size.
  90. move.w (%a3),%d6
  91. rol.w #8,%d6
  92. .endm
  93. | MEM_TO_MEM_DECOMPRESS inline function
  94. | INPUT: %a3.l: pointer to compressed data
  95. | %a0.l: pointer to buffer for uncompressed data
  96. | %d6.l: uncompressed size
  97. | OUTPUT: %a4.l: pointer to uncompressed data
  98. | SIDE EFFECTS: may throw a Memory or Data Type error
  99. | DESTROYS: %d0-%d2/%a0-%a2
  100. .macro MEM_TO_MEM_DECOMPRESS
  101. move.l %a0,%a4 | satisfy output constraint
  102. jbsr ttunpack_decompress
  103. tst.w %d0
  104. jbne invalid_archive
  105. .endm
  106. |-----------------------------------------------------------------------
  107. |INTRODUCTION:
  108. |
  109. | This is a 100% assembly version of the ttunpack routine, which is
  110. | based on code by Pasi 'Albert' Ojala, albert@cs.tut.fi, then
  111. | reduced by Thomas Nussbaumer to fit his needs. For a full details
  112. | on the algorithm see:
  113. |
  114. | http://www.cs.tut.fi/~albert/Dev/pucrunch/index.html
  115. |
  116. | Version: 2.33 Super Small, Improper Return Value
  117. | Requires even alignment
  118. | Register Parameters, a0 -> dest, a3 -> source
  119. | Removed optional delta_lz code
  120. | Fixed a bug in header error checks
  121. |
  122. | 2006-03-20 Kevin Kofler: Ported to GNU as.
  123. |
  124. |THE LICENSE:
  125. |
  126. | Copyright (C) 2004-2005 Samuel Stearley
  127. |
  128. | wxWindows Library Licence, Version 3.1
  129. | ======================================
  130. |
  131. | Copyright (C) 1998-2005 Julian Smart, Robert Roebling et al
  132. |
  133. | Everyone is permitted to copy and distribute verbatim copies
  134. | of this licence document, but changing it is not allowed.
  135. |
  136. | WXWINDOWS LIBRARY LICENCE
  137. | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
  138. |
  139. | This library is free software; you can redistribute it and/or modify it
  140. | under the terms of the GNU Library General Public Licence as published by
  141. | the Free Software Foundation; either version 2 of the Licence, or (at
  142. | your option) any later version.
  143. |
  144. | This library is distributed in the hope that it will be useful, but
  145. | WITHOUT ANY WARRANTY; without even the implied warranty of
  146. | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library
  147. | General Public Licence for more details.
  148. |
  149. | You should have received a copy of the GNU Library General Public Licence
  150. | along with this software, usually in a file named COPYING.LIB. If not,
  151. | write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  152. | Boston, MA 02111-1307 USA.
  153. |
  154. | EXCEPTION NOTICE
  155. |
  156. | 1. As a special exception, the copyright holders of this library give
  157. | permission for additional uses of the text contained in this release of
  158. | the library as licenced under the wxWindows Library Licence, applying
  159. | either version 3.1 of the Licence, or (at your option) any later version of
  160. | the Licence as published by the copyright holders of version
  161. | 3.1 of the Licence document.
  162. |
  163. | 2. The exception is that you may use, copy, link, modify and distribute
  164. | under your own terms, binary object code versions of works based
  165. | on the Library.
  166. |
  167. | 3. If you copy code from files distributed under the terms of the GNU
  168. | General Public Licence or the GNU Library General Public Licence into a
  169. | copy of this library, as this licence permits, the exception does not
  170. | apply to the code that you add in this way. To avoid misleading anyone as
  171. | to the status of such modified files, you must delete this exception
  172. | notice from such code and/or adjust the licensing conditions notice
  173. | accordingly.
  174. |
  175. | 4. If you write modifications of your own for this library, it is your
  176. | choice whether to permit this exception to apply to your modifications.
  177. | If you do not wish that, you must delete the exception notice from such
  178. | code and/or adjust the licensing conditions notice accordingly.
  179. |
  180. |
  181. |NOTES:
  182. |
  183. |1) There were several other names associated with this, but not
  184. | anymore ;)
  185. |
  186. |
  187. |2) The code was written with wordpad. It might look better if
  188. | opened with that program.
  189. |----------------------------------------------------------------------
  190. .include "os.h"
  191. |------------------------------------------------------------------
  192. |The data structure defines and error return values
  193. |------------------------------------------------------------------
  194. .equ osize_lo,0 |original size lowbyte
  195. .equ osize_hi,1 |original size highbyte
  196. .equ magic1,2 |must be equal to UNPACK_MAGIC1
  197. .equ magic2,3 |must be equal to UNPACK_MAGIC2
  198. .equ csize_lo,4 |compressed size lowbyte
  199. .equ csize_hi,5 |compressed size lowbyte
  200. .equ esc1,6 |escape >> (8-escBits)
  201. .equ notused3,7 |
  202. .equ notused4,8 |
  203. .equ esc2,9 |escBits
  204. .equ gamma1,10 |maxGamma + 1
  205. .equ gamma2,11 |(1<<maxGamma)
  206. .equ extralz,12 |extraLZPosBits
  207. .equ notused1,13 |
  208. .equ notused2,14 |
  209. .equ rleentries,15 |rleUsed
  210. .equ HEADER_SIZE,16
  211. .equ __MAGIC_CHAR1,0x54
  212. .equ __MAGIC_CHAR2,0x50
  213. .equ __ERRPCK_OKAY,0
  214. .equ __ERRPCK_NOESCFOUND,8 |248
  215. .equ __ERRPCK_ESCBITS,7 |249
  216. .equ __ERRPCK_MAXGAMMA,6 |250
  217. .equ __ERRPCK_EXTRALZP,5 |251
  218. .equ __ERRPCK_NOMAGIC,4 |252
  219. .equ __ERRPCK_OUTBUFOVERRUN,3 |253
  220. .equ __ERRPCK_LZPOSUNDERRUN,2 |254
  221. |-----------------------------------------------------------------------
  222. |Notes on register useage, might be good Idea to print this.
  223. |
  224. | a0 => Input: The destination buffer
  225. | a1 => Points to the next byte of the compressed data.
  226. | udated when d7 overflows.
  227. | a2 => NOT USED
  228. | a3 => Input: The source data
  229. | Used during error checking, will point to extralz bits
  230. | Used to access 'bytecodevec' table
  231. | a4 => NOT USED
  232. | a5 => NOT USED
  233. | a6 => NOT USED
  234. |
  235. | d0 => Trashing, output of __GetBits and __GetValue
  236. | d1 => Trashing, input to __GetBits
  237. | d2 => Trashing by __GetValue
  238. | d3 => Trashing but only by the main routine, not the subroutines
  239. | d4 => # of escape bits
  240. | d5 => Start escape
  241. | d6 => Current byte of data.
  242. | d7 => Which bit we are at in the compressed data.
  243. |
  244. |-----------------------------------------------------------------------
  245. ttunpack_decompress:
  246. movem.l %d3-%d7/%a2-%a6,-(%a7)
  247. | move.l 4+10*4(%a7),%a3
  248. | move.l 8+10*4(%a7),%a0
  249. |--------------------------------------------------------
  250. | startesc = cth->esc1; //d5
  251. | bytecodevec = &src[15]; //a3
  252. | __imask__ = 0x80; //d7
  253. |
  254. |These are initialized here to insure that certain
  255. |branches can use the short form.
  256. |--------------------------------------------------------
  257. move.b esc1(%a3),%d5 |'StartEsc'
  258. moveq #-128,%d7 |which bit i am at.
  259. |-------------------------------------------------------------------------------------------------
  260. | if (cth->magic1 != __MAGIC_CHAR1 || cth->magic2 != __MAGIC_CHAR2) return __ERRPCK_NOMAGIC;
  261. | if (cth->gamma1 != 8 || cth->gamma2 != 128) return __ERRPCK_MAXGAMMA;
  262. | if ((escbits = cth->esc2) > 8) return __ERRPCK_ESCBITS;
  263. | if ((extralzposbits = cth->extralz) > 4) return __ERRPCK_EXTRALZP;
  264. |-------------------------------------------------------------------------------------------------
  265. moveq #8,%d0 |code for error is non-zero
  266. addq.l #2,%a3
  267. cmp.w #__MAGIC_CHAR1*256+__MAGIC_CHAR2,(%a3)+
  268. bne.s __ReturnError
  269. addq.l #5,%a3 |point to esc2
  270. move.b (%a3)+,%d4 |get esc2 and point to gamma1
  271. cmp.b %d0,%d4
  272. bhi.s __ReturnError
  273. cmp.w #8*256+128,(%a3)+ |gamma1 = 8 and gamma2 = 128?
  274. bne.s __ReturnError
  275. |--------------------------------------------------------
  276. | __ibuffer__ = src + sizeof(__PACKHEADER) + cth->rleentries; //a1
  277. |--------------------------------------------------------
  278. add.b 3(%a3),%d0 |upper bytes of d0.l = 0, add (not load) in case a3 points to a zero
  279. lea 4-8(%a3,%d0.l),%a1 | because d0 is the error code must not be zero.
  280. cmp.b #5,(%a3)
  281. bcs.s __DecompressLoop |jump into the loop if 4..0
  282. |---------------------------------------------------------
  283. |And when all is done branch here
  284. | If success d0 will be zero
  285. |---------------------------------------------------------
  286. __ReturnError:
  287. __WeAreDone:
  288. movem.l (%a7)+,%d3-%d7/%a2-%a6
  289. rts
  290. |-----------------------------------------------------------------
  291. | newesc = __GetBits(escbits);
  292. | *outbuffer++ = (startesc<<escbits8) | __GetBits(escbits8);
  293. | startesc = newesc;
  294. | continue;
  295. |-----------------------------------------------------------------
  296. __NextBitIsClear_EscapeFromEscape:
  297. bsr.s __GetBits_D4Input |d0 is 'newesc'
  298. exg %d0,%d5 |'startesc' = 'newesc'; and d0 = OLD_startesc
  299. |---------------------------------------------------------
  300. | *outbuffer++ = (sel<<escbits8) | __GetBits(escbits8);
  301. | continue;
  302. |---------------------------------------------------------
  303. __SelIsNOTStartEscape:
  304. moveq #8,%d1
  305. sub.b %d4,%d1 |'escbits8'
  306. bsr.s __GetBits_D0_IS_Loaded_For_Shifting
  307. move.b %d0,(%a0)+
  308. |---------------------------------------------------------
  309. |The while(1) loop, just a label ;)
  310. |---------------------------------------------------------
  311. __DecompressLoop:
  312. |---------------------------------------------------------
  313. | sel = (escbits) ? __GetBits(escbits) : startesc;
  314. | if (sel == startesc) {
  315. |---------------------------------------------------------
  316. bsr.s __GetBits_D4Input |get the bits, input is in d4
  317. cmp.b %d5,%d0 |did __getBits return 'startesc' into 'sel'?
  318. bne.s __SelIsNOTStartEscape
  319. |---------------------------------------------------------
  320. |The following code is entered if sel = start escape
  321. |but it does not actually use the sel variable
  322. |
  323. | lzlen = __GetValue();
  324. | if (lzlen != 1) {
  325. |---------------------------------------------------------
  326. __SelIsStartEscape:
  327. bsr.s __GetValue |get a value for 'lzlen', d1 will be negative from above __GetBits
  328. | as a side effect d1 will be negative
  329. move.w %d0,%d3 |save 'lzlen'
  330. subq.w #1,%d0 |does 'lzlen' == 1 ?
  331. beq.s __RleDecoding |this destination requires d0 = 0
  332. |---------------------------------------------------------
  333. |Zip decoding
  334. |
  335. | lzposhi = __GetValue() - 1;
  336. | if (lzposhi == 254) {
  337. |---------------------------------------------------------
  338. bsr.s __GetValue |if it equals 254, then lzlen must be > 3 because
  339. addq.b #1,%d0 | there is no other possiblity because Delta decompression
  340. beq.s __WeAreDone | is not being used. It the branch is not taken it
  341. | drops through to the __LzPosHi_IsNot254
  342. | This __GetValue relies on d1 = negative from above __GetValue
  343. |----------------------------------------------------------------------------------------
  344. | if (extralzposbits) lzposhi = (lzposhi<<extralzposbits) | __GetBits(extralzposbits);
  345. | lzposlo = __Get8Bit() ^ 0xff;
  346. | lzpos = COMBINE_LOWHIGH(lzposlo,lzposhi);
  347. |
  348. | d0= lzPosHi, d3.w = lzlen, d2.l =lzpos
  349. |----------------------------------------------------------------------------------------
  350. __LzPosHi_IsNot254:
  351. subq.b #2,%d0 |undo the addq.b #1 and do the subtract that wasn't done
  352. move.b (%a3),%d1 |get 'extralzposbits'
  353. bsr.s __GetBits_D0_IS_Loaded_For_Shifting
  354. __NextBitClear_DoZipAfterAll: |to jump here be sure that d0.l = 0
  355. moveq #7,%d1
  356. bsr.s __GetBits_D0_IS_Loaded_For_Shifting_D1_is_not_Variable
  357. |-----------------------------------------------------------------------------------
  358. | for (i=0; i<=lzlen; i++) {
  359. | *outbuffer = *(outbuffer - lzpos - 1); //no 'add' variable
  360. | outbuffer++;
  361. | }
  362. |
  363. | d0.l must be lzpos
  364. | d3.w must be lzlen
  365. |------------------------------------------------------------------------------------
  366. not.b %d0
  367. neg.l %d0
  368. __WriteDataLoop:
  369. move.b -1(%a0,%d0.l),(%a0)+ |18 cycles
  370. __UseZipCopyLoop: |entrance for the rle code
  371. dbra %d3,__WriteDataLoop
  372. bra.s __DecompressLoop |continue
  373. |-------------------------------------------------------------
  374. | __GetValue returns an 8 bit value in d0.l It can be used
  375. | as an:
  376. | unsigned character
  377. | unsigned short
  378. | unsigned long
  379. |
  380. | __GetBits takes as its input d1.b, returns a value in d0.w
  381. | There is a limit on it being 16 bit output. With the
  382. | upper bits being 0 so it can be used as an:
  383. | unsigned character, if 8 bits or less are requested.
  384. | unsigned short
  385. | unsigned long
  386. |
  387. | __GetBits has two other entrances, that assume a value in d0
  388. | is ready to be shifted up as bits are shifted in. This is
  389. | limited to 16 bit values, with no guarantee about the upper
  390. | bits.
  391. |
  392. | '__GetBits_D0_IS_Loaded_For_Shifting_D1_is_not_Variable' is
  393. | used when there is no possiblity that the input is 0. For
  394. | example: __getBits(3)
  395. |
  396. |--------------------------------------------------------------
  397. __GetBits_D4Input:
  398. move.b %d4,%d1
  399. __GetBits:
  400. moveq #0,%d0
  401. bra.s __IntoLoop
  402. __GetBits_D0_IS_Loaded_For_Shifting_D1_is_not_Variable:
  403. __inl_loop0:
  404. __CheckBitProceed: |to call this like the old 'CheckBitProceed' make sure d1 = negative
  405. rol.b #1,%d7
  406. bcc.s __NotInNext
  407. move.b (%a1)+,%d6
  408. __NotInNext:
  409. add.b %d6,%d6
  410. addx.w %d0,%d0
  411. __GetBits_D0_IS_Loaded_For_Shifting:
  412. __IntoLoop:
  413. subq.b #1,%d1 |must be byte valued, if d1.b = negative then drop through
  414. bpl.s __inl_loop0
  415. move %d0,%ccr |put the last bit into the carry flag.
  416. rts
  417. __GetValue:
  418. moveq #6,%d2
  419. __inl_loop1:
  420. bsr.s __CheckBitProceed
  421. dbcc %d2,__inl_loop1
  422. moveq #6,%d1
  423. sub.w %d2,%d1
  424. moveq #1,%d0
  425. bra.s __GetBits_D0_IS_Loaded_For_Shifting
  426. |---------------------------------------------------------
  427. |RLE decoding
  428. |---------------------------------------------------------
  429. __RleDecoding: |important! at this point d0=0 and d1 = -1
  430. bsr.s __CheckBitProceed |will modify d0 if the bit is set
  431. bcc.s __NextBitClear_DoZipAfterAll |if it branches d0 is still 0, the destination requires this!
  432. bsr.s __CheckBitProceed
  433. bcc.s __NextBitIsClear_EscapeFromEscape
  434. |-----------------------------------------------------------------
  435. | rlelen = __GetValue();
  436. | if (rlelen >= 128) {
  437. | rlelen = ((rlelen-128)<<1) | __GetBits(1);
  438. | rlelen |= (((__GetValue())-1)<<8);
  439. | }
  440. |------------------------------------------------------------------
  441. __NextBitIsSet_RunLengthEncoding:
  442. bsr.s __GetValue |get 'rlelen' into d0, limited to 8 bit values. d1 = is still negative!
  443. | it gets the value and d1 is negative again
  444. move.b %d0,%d3 |copy it and check sign bit to see if >= 128
  445. bpl.s __LessThan128
  446. bsr.s __CheckBitProceed |__getBits(1), important d1 is negative
  447. move.w %d0,-(%a7)
  448. bsr.s __GetValue |relies on d1 being negative ! Satisfied by above __GetValue
  449. subq.b #1,%d0
  450. move.b %d0,(%a7) |overwrites the high bit that is should be cleared by
  451. move.w (%a7)+,%d3 | by the rlelen-128
  452. |-------------------------------------------------------------------
  453. |Need the byte to copy
  454. |
  455. | bytecode = __GetValue();
  456. | if (bytecode < 32) byte = bytecodevec[bytecode];
  457. | else byte = ((bytecode-32)<<3) | __GetBits(3);
  458. |-------------------------------------------------------------------
  459. __LessThan128:
  460. bsr.s __GetValue |get 'bytecode'
  461. subq.b #2,%d2 |d2= (6- # of bits retireved) jump if 5 ,6, or 7
  462. bmi.s __GreaterThanOrEqual32 | bits retrieved means that it is >= 32
  463. move.b 3(%a3,%d0.w),%d0 |byte = bytecodevec[bytecode];
  464. bra.s __RleCopy
  465. __GreaterThanOrEqual32:
  466. moveq #2,%d1
  467. bsr.s __GetBits_D0_IS_Loaded_For_Shifting_D1_is_not_Variable
  468. |--------------------------------------------------------
  469. | for (i=0; i<=rlelen; i++) *outbuffer++ = byte;
  470. | continue; // continue the main loop ...
  471. |
  472. |Rle loop expects
  473. | d0 = byte
  474. | d3 = number of em to copy, no need to subtract 1 for
  475. | dbra
  476. |--------------------------------------------------------
  477. __RleCopy:
  478. move.b %d0,(%a0)+
  479. moveq #0,%d0
  480. bra.s __UseZipCopyLoop