123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494 |
- | TIGCC Program Starter - ttunpack decompression support
- | Copyright (C) 2004-2005 Samuel Stearley, Kevin Kofler
- |
- | THE LICENSE:
- |
- | wxWindows Library Licence, Version 3.1
- | ======================================
- |
- | Copyright (C) 1998-2005 Julian Smart, Robert Roebling et al
- |
- | Everyone is permitted to copy and distribute verbatim copies
- | of this licence document, but changing it is not allowed.
- |
- | WXWINDOWS LIBRARY LICENCE
- | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
- |
- | This library is free software; you can redistribute it and/or modify it
- | under the terms of the GNU Library General Public Licence as published by
- | the Free Software Foundation; either version 2 of the Licence, or (at
- | your option) any later version.
- |
- | This library is distributed in the hope that it will be useful, but
- | WITHOUT ANY WARRANTY; without even the implied warranty of
- | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library
- | General Public Licence for more details.
- |
- | You should have received a copy of the GNU Library General Public Licence
- | along with this software, usually in a file named COPYING.LIB. If not,
- | write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- | Boston, MA 02111-1307 USA.
- |
- | EXCEPTION NOTICE
- |
- | 1. As a special exception, the copyright holders of this library give
- | permission for additional uses of the text contained in this release of
- | the library as licenced under the wxWindows Library Licence, applying
- | either version 3.1 of the Licence, or (at your option) any later version of
- | the Licence as published by the copyright holders of version
- | 3.1 of the Licence document.
- |
- | 2. The exception is that you may use, copy, link, modify and distribute
- | under your own terms, binary object code versions of works based
- | on the Library.
- |
- | 3. If you copy code from files distributed under the terms of the GNU
- | General Public Licence or the GNU Library General Public Licence into a
- | copy of this library, as this licence permits, the exception does not
- | apply to the code that you add in this way. To avoid misleading anyone as
- | to the status of such modified files, you must delete this exception
- | notice from such code and/or adjust the licensing conditions notice
- | accordingly.
- |
- | 4. If you write modifications of your own for this library, it is your
- | choice whether to permit this exception to apply to your modifications.
- | If you do not wish that, you must delete the exception notice from such
- | code and/or adjust the licensing conditions notice accordingly.
- | GET_UNCOMPRESSED_SIZE inline function
- | INPUT: %a3.l: pointer to compressed data
- | OUTPUT: %d6.l: uncompressed size
- | SIDE EFFECTS: throws a Data Type error if not a valid compressed program
- | may throw a Memory error
- | may advance %a3 for later decompression
- | DESTROYS: %d0-%d2/%a0-%a1
- .macro GET_UNCOMPRESSED_SIZE
- | Get the length of the variable.
- moveq.l #0,%d6
- move.w (%a3)+,%d6
- | Get a pointer to the data type of the variable.
- lea.l -1(%a3,%d6.l),%a0
- | Check if it has type "ppg".
- cmp.b #0xf8,(%a0)
- jbne invalid_archive
- tst.b -(%a0)
- jbne invalid_archive
- cmp.b #'g',-(%a0)
- jbne invalid_archive
- moveq.l #'p',%d0
- cmp.b -(%a0),%d0
- jbne invalid_archive
- cmp.b -(%a0),%d0
- jbne invalid_archive
- tst.b -(%a0)
- jbeq valid_archive
- | We don't need to check the magic number in the ttunpack header,
- | the decompression routine does that already.
- invalid_archive:
- .word 0xA000+210 | ER_DATATYPE
- valid_archive:
- | Get the uncompressed size.
- move.w (%a3),%d6
- rol.w #8,%d6
- .endm
- | MEM_TO_MEM_DECOMPRESS inline function
- | INPUT: %a3.l: pointer to compressed data
- | %a0.l: pointer to buffer for uncompressed data
- | %d6.l: uncompressed size
- | OUTPUT: %a4.l: pointer to uncompressed data
- | SIDE EFFECTS: may throw a Memory or Data Type error
- | DESTROYS: %d0-%d2/%a0-%a2
- .macro MEM_TO_MEM_DECOMPRESS
- move.l %a0,%a4 | satisfy output constraint
- jbsr ttunpack_decompress
- tst.w %d0
- jbne invalid_archive
- .endm
- |-----------------------------------------------------------------------
- |INTRODUCTION:
- |
- | This is a 100% assembly version of the ttunpack routine, which is
- | based on code by Pasi 'Albert' Ojala, albert@cs.tut.fi, then
- | reduced by Thomas Nussbaumer to fit his needs. For a full details
- | on the algorithm see:
- |
- | http://www.cs.tut.fi/~albert/Dev/pucrunch/index.html
- |
- | Version: 2.33 Super Small, Improper Return Value
- | Requires even alignment
- | Register Parameters, a0 -> dest, a3 -> source
- | Removed optional delta_lz code
- | Fixed a bug in header error checks
- |
- | 2006-03-20 Kevin Kofler: Ported to GNU as.
- |
- |THE LICENSE:
- |
- | Copyright (C) 2004-2005 Samuel Stearley
- |
- | wxWindows Library Licence, Version 3.1
- | ======================================
- |
- | Copyright (C) 1998-2005 Julian Smart, Robert Roebling et al
- |
- | Everyone is permitted to copy and distribute verbatim copies
- | of this licence document, but changing it is not allowed.
- |
- | WXWINDOWS LIBRARY LICENCE
- | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
- |
- | This library is free software; you can redistribute it and/or modify it
- | under the terms of the GNU Library General Public Licence as published by
- | the Free Software Foundation; either version 2 of the Licence, or (at
- | your option) any later version.
- |
- | This library is distributed in the hope that it will be useful, but
- | WITHOUT ANY WARRANTY; without even the implied warranty of
- | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library
- | General Public Licence for more details.
- |
- | You should have received a copy of the GNU Library General Public Licence
- | along with this software, usually in a file named COPYING.LIB. If not,
- | write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- | Boston, MA 02111-1307 USA.
- |
- | EXCEPTION NOTICE
- |
- | 1. As a special exception, the copyright holders of this library give
- | permission for additional uses of the text contained in this release of
- | the library as licenced under the wxWindows Library Licence, applying
- | either version 3.1 of the Licence, or (at your option) any later version of
- | the Licence as published by the copyright holders of version
- | 3.1 of the Licence document.
- |
- | 2. The exception is that you may use, copy, link, modify and distribute
- | under your own terms, binary object code versions of works based
- | on the Library.
- |
- | 3. If you copy code from files distributed under the terms of the GNU
- | General Public Licence or the GNU Library General Public Licence into a
- | copy of this library, as this licence permits, the exception does not
- | apply to the code that you add in this way. To avoid misleading anyone as
- | to the status of such modified files, you must delete this exception
- | notice from such code and/or adjust the licensing conditions notice
- | accordingly.
- |
- | 4. If you write modifications of your own for this library, it is your
- | choice whether to permit this exception to apply to your modifications.
- | If you do not wish that, you must delete the exception notice from such
- | code and/or adjust the licensing conditions notice accordingly.
- |
- |
- |NOTES:
- |
- |1) There were several other names associated with this, but not
- | anymore ;)
- |
- |
- |2) The code was written with wordpad. It might look better if
- | opened with that program.
- |----------------------------------------------------------------------
- .include "os.h"
- |------------------------------------------------------------------
- |The data structure defines and error return values
- |------------------------------------------------------------------
- .equ osize_lo,0 |original size lowbyte
- .equ osize_hi,1 |original size highbyte
- .equ magic1,2 |must be equal to UNPACK_MAGIC1
- .equ magic2,3 |must be equal to UNPACK_MAGIC2
- .equ csize_lo,4 |compressed size lowbyte
- .equ csize_hi,5 |compressed size lowbyte
- .equ esc1,6 |escape >> (8-escBits)
- .equ notused3,7 |
- .equ notused4,8 |
- .equ esc2,9 |escBits
- .equ gamma1,10 |maxGamma + 1
- .equ gamma2,11 |(1<<maxGamma)
- .equ extralz,12 |extraLZPosBits
- .equ notused1,13 |
- .equ notused2,14 |
- .equ rleentries,15 |rleUsed
- .equ HEADER_SIZE,16
- .equ __MAGIC_CHAR1,0x54
- .equ __MAGIC_CHAR2,0x50
- .equ __ERRPCK_OKAY,0
- .equ __ERRPCK_NOESCFOUND,8 |248
- .equ __ERRPCK_ESCBITS,7 |249
- .equ __ERRPCK_MAXGAMMA,6 |250
- .equ __ERRPCK_EXTRALZP,5 |251
- .equ __ERRPCK_NOMAGIC,4 |252
- .equ __ERRPCK_OUTBUFOVERRUN,3 |253
- .equ __ERRPCK_LZPOSUNDERRUN,2 |254
- |-----------------------------------------------------------------------
- |Notes on register useage, might be good Idea to print this.
- |
- | a0 => Input: The destination buffer
- | a1 => Points to the next byte of the compressed data.
- | udated when d7 overflows.
- | a2 => NOT USED
- | a3 => Input: The source data
- | Used during error checking, will point to extralz bits
- | Used to access 'bytecodevec' table
- | a4 => NOT USED
- | a5 => NOT USED
- | a6 => NOT USED
- |
- | d0 => Trashing, output of __GetBits and __GetValue
- | d1 => Trashing, input to __GetBits
- | d2 => Trashing by __GetValue
- | d3 => Trashing but only by the main routine, not the subroutines
- | d4 => # of escape bits
- | d5 => Start escape
- | d6 => Current byte of data.
- | d7 => Which bit we are at in the compressed data.
- |
- |-----------------------------------------------------------------------
- ttunpack_decompress:
- movem.l %d3-%d7/%a2-%a6,-(%a7)
- | move.l 4+10*4(%a7),%a3
- | move.l 8+10*4(%a7),%a0
- |--------------------------------------------------------
- | startesc = cth->esc1; //d5
- | bytecodevec = &src[15]; //a3
- | __imask__ = 0x80; //d7
- |
- |These are initialized here to insure that certain
- |branches can use the short form.
- |--------------------------------------------------------
- move.b esc1(%a3),%d5 |'StartEsc'
- moveq #-128,%d7 |which bit i am at.
- |-------------------------------------------------------------------------------------------------
- | if (cth->magic1 != __MAGIC_CHAR1 || cth->magic2 != __MAGIC_CHAR2) return __ERRPCK_NOMAGIC;
- | if (cth->gamma1 != 8 || cth->gamma2 != 128) return __ERRPCK_MAXGAMMA;
- | if ((escbits = cth->esc2) > 8) return __ERRPCK_ESCBITS;
- | if ((extralzposbits = cth->extralz) > 4) return __ERRPCK_EXTRALZP;
- |-------------------------------------------------------------------------------------------------
- moveq #8,%d0 |code for error is non-zero
- addq.l #2,%a3
- cmp.w #__MAGIC_CHAR1*256+__MAGIC_CHAR2,(%a3)+
- bne.s __ReturnError
- addq.l #5,%a3 |point to esc2
- move.b (%a3)+,%d4 |get esc2 and point to gamma1
- cmp.b %d0,%d4
- bhi.s __ReturnError
- cmp.w #8*256+128,(%a3)+ |gamma1 = 8 and gamma2 = 128?
- bne.s __ReturnError
- |--------------------------------------------------------
- | __ibuffer__ = src + sizeof(__PACKHEADER) + cth->rleentries; //a1
- |--------------------------------------------------------
- add.b 3(%a3),%d0 |upper bytes of d0.l = 0, add (not load) in case a3 points to a zero
- lea 4-8(%a3,%d0.l),%a1 | because d0 is the error code must not be zero.
- cmp.b #5,(%a3)
- bcs.s __DecompressLoop |jump into the loop if 4..0
- |---------------------------------------------------------
- |And when all is done branch here
- | If success d0 will be zero
- |---------------------------------------------------------
- __ReturnError:
- __WeAreDone:
- movem.l (%a7)+,%d3-%d7/%a2-%a6
- rts
- |-----------------------------------------------------------------
- | newesc = __GetBits(escbits);
- | *outbuffer++ = (startesc<<escbits8) | __GetBits(escbits8);
- | startesc = newesc;
- | continue;
- |-----------------------------------------------------------------
- __NextBitIsClear_EscapeFromEscape:
- bsr.s __GetBits_D4Input |d0 is 'newesc'
- exg %d0,%d5 |'startesc' = 'newesc'; and d0 = OLD_startesc
- |---------------------------------------------------------
- | *outbuffer++ = (sel<<escbits8) | __GetBits(escbits8);
- | continue;
- |---------------------------------------------------------
- __SelIsNOTStartEscape:
- moveq #8,%d1
- sub.b %d4,%d1 |'escbits8'
- bsr.s __GetBits_D0_IS_Loaded_For_Shifting
- move.b %d0,(%a0)+
- |---------------------------------------------------------
- |The while(1) loop, just a label ;)
- |---------------------------------------------------------
- __DecompressLoop:
- |---------------------------------------------------------
- | sel = (escbits) ? __GetBits(escbits) : startesc;
- | if (sel == startesc) {
- |---------------------------------------------------------
- bsr.s __GetBits_D4Input |get the bits, input is in d4
- cmp.b %d5,%d0 |did __getBits return 'startesc' into 'sel'?
- bne.s __SelIsNOTStartEscape
- |---------------------------------------------------------
- |The following code is entered if sel = start escape
- |but it does not actually use the sel variable
- |
- | lzlen = __GetValue();
- | if (lzlen != 1) {
- |---------------------------------------------------------
- __SelIsStartEscape:
- bsr.s __GetValue |get a value for 'lzlen', d1 will be negative from above __GetBits
- | as a side effect d1 will be negative
- move.w %d0,%d3 |save 'lzlen'
- subq.w #1,%d0 |does 'lzlen' == 1 ?
- beq.s __RleDecoding |this destination requires d0 = 0
- |---------------------------------------------------------
- |Zip decoding
- |
- | lzposhi = __GetValue() - 1;
- | if (lzposhi == 254) {
- |---------------------------------------------------------
- bsr.s __GetValue |if it equals 254, then lzlen must be > 3 because
- addq.b #1,%d0 | there is no other possiblity because Delta decompression
- beq.s __WeAreDone | is not being used. It the branch is not taken it
- | drops through to the __LzPosHi_IsNot254
- | This __GetValue relies on d1 = negative from above __GetValue
- |----------------------------------------------------------------------------------------
- | if (extralzposbits) lzposhi = (lzposhi<<extralzposbits) | __GetBits(extralzposbits);
- | lzposlo = __Get8Bit() ^ 0xff;
- | lzpos = COMBINE_LOWHIGH(lzposlo,lzposhi);
- |
- | d0= lzPosHi, d3.w = lzlen, d2.l =lzpos
- |----------------------------------------------------------------------------------------
- __LzPosHi_IsNot254:
- subq.b #2,%d0 |undo the addq.b #1 and do the subtract that wasn't done
- move.b (%a3),%d1 |get 'extralzposbits'
- bsr.s __GetBits_D0_IS_Loaded_For_Shifting
- __NextBitClear_DoZipAfterAll: |to jump here be sure that d0.l = 0
- moveq #7,%d1
- bsr.s __GetBits_D0_IS_Loaded_For_Shifting_D1_is_not_Variable
- |-----------------------------------------------------------------------------------
- | for (i=0; i<=lzlen; i++) {
- | *outbuffer = *(outbuffer - lzpos - 1); //no 'add' variable
- | outbuffer++;
- | }
- |
- | d0.l must be lzpos
- | d3.w must be lzlen
- |------------------------------------------------------------------------------------
- not.b %d0
- neg.l %d0
- __WriteDataLoop:
- move.b -1(%a0,%d0.l),(%a0)+ |18 cycles
- __UseZipCopyLoop: |entrance for the rle code
- dbra %d3,__WriteDataLoop
- bra.s __DecompressLoop |continue
- |-------------------------------------------------------------
- | __GetValue returns an 8 bit value in d0.l It can be used
- | as an:
- | unsigned character
- | unsigned short
- | unsigned long
- |
- | __GetBits takes as its input d1.b, returns a value in d0.w
- | There is a limit on it being 16 bit output. With the
- | upper bits being 0 so it can be used as an:
- | unsigned character, if 8 bits or less are requested.
- | unsigned short
- | unsigned long
- |
- | __GetBits has two other entrances, that assume a value in d0
- | is ready to be shifted up as bits are shifted in. This is
- | limited to 16 bit values, with no guarantee about the upper
- | bits.
- |
- | '__GetBits_D0_IS_Loaded_For_Shifting_D1_is_not_Variable' is
- | used when there is no possiblity that the input is 0. For
- | example: __getBits(3)
- |
- |--------------------------------------------------------------
- __GetBits_D4Input:
- move.b %d4,%d1
- __GetBits:
- moveq #0,%d0
- bra.s __IntoLoop
- __GetBits_D0_IS_Loaded_For_Shifting_D1_is_not_Variable:
- __inl_loop0:
- __CheckBitProceed: |to call this like the old 'CheckBitProceed' make sure d1 = negative
- rol.b #1,%d7
- bcc.s __NotInNext
- move.b (%a1)+,%d6
- __NotInNext:
- add.b %d6,%d6
- addx.w %d0,%d0
- __GetBits_D0_IS_Loaded_For_Shifting:
- __IntoLoop:
- subq.b #1,%d1 |must be byte valued, if d1.b = negative then drop through
- bpl.s __inl_loop0
- move %d0,%ccr |put the last bit into the carry flag.
- rts
- __GetValue:
- moveq #6,%d2
- __inl_loop1:
- bsr.s __CheckBitProceed
- dbcc %d2,__inl_loop1
- moveq #6,%d1
- sub.w %d2,%d1
- moveq #1,%d0
- bra.s __GetBits_D0_IS_Loaded_For_Shifting
- |---------------------------------------------------------
- |RLE decoding
- |---------------------------------------------------------
- __RleDecoding: |important! at this point d0=0 and d1 = -1
- bsr.s __CheckBitProceed |will modify d0 if the bit is set
- bcc.s __NextBitClear_DoZipAfterAll |if it branches d0 is still 0, the destination requires this!
- bsr.s __CheckBitProceed
- bcc.s __NextBitIsClear_EscapeFromEscape
- |-----------------------------------------------------------------
- | rlelen = __GetValue();
- | if (rlelen >= 128) {
- | rlelen = ((rlelen-128)<<1) | __GetBits(1);
- | rlelen |= (((__GetValue())-1)<<8);
- | }
- |------------------------------------------------------------------
- __NextBitIsSet_RunLengthEncoding:
- bsr.s __GetValue |get 'rlelen' into d0, limited to 8 bit values. d1 = is still negative!
- | it gets the value and d1 is negative again
- move.b %d0,%d3 |copy it and check sign bit to see if >= 128
- bpl.s __LessThan128
- bsr.s __CheckBitProceed |__getBits(1), important d1 is negative
- move.w %d0,-(%a7)
- bsr.s __GetValue |relies on d1 being negative ! Satisfied by above __GetValue
- subq.b #1,%d0
- move.b %d0,(%a7) |overwrites the high bit that is should be cleared by
- move.w (%a7)+,%d3 | by the rlelen-128
- |-------------------------------------------------------------------
- |Need the byte to copy
- |
- | bytecode = __GetValue();
- | if (bytecode < 32) byte = bytecodevec[bytecode];
- | else byte = ((bytecode-32)<<3) | __GetBits(3);
- |-------------------------------------------------------------------
- __LessThan128:
- bsr.s __GetValue |get 'bytecode'
- subq.b #2,%d2 |d2= (6- # of bits retireved) jump if 5 ,6, or 7
- bmi.s __GreaterThanOrEqual32 | bits retrieved means that it is >= 32
- move.b 3(%a3,%d0.w),%d0 |byte = bytecodevec[bytecode];
- bra.s __RleCopy
- __GreaterThanOrEqual32:
- moveq #2,%d1
- bsr.s __GetBits_D0_IS_Loaded_For_Shifting_D1_is_not_Variable
- |--------------------------------------------------------
- | for (i=0; i<=rlelen; i++) *outbuffer++ = byte;
- | continue; // continue the main loop ...
- |
- |Rle loop expects
- | d0 = byte
- | d3 = number of em to copy, no need to subtract 1 for
- | dbra
- |--------------------------------------------------------
- __RleCopy:
- move.b %d0,(%a0)+
- moveq #0,%d0
- bra.s __UseZipCopyLoop
|