Rev 129 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
6 | lvd | 1 | #include <avr/io.h> |
2 | #include <avr/pgmspace.h> |
||
129 | chrv | 3 | |
4 | #include "mytypes.h" |
||
5 | #include "main.h" |
||
6 | lvd | 6 | #include "depacker_dirty.h" |
7 | |||
8 | |||
9 | UWORD dbpos; // current position in buffer (wrappable) |
||
10 | |||
11 | UBYTE bitstream; |
||
12 | UBYTE bitcount; |
||
13 | |||
14 | void depacker_dirty(void) |
||
15 | { |
||
16 | UBYTE j; |
||
17 | |||
18 | UBYTE bits; |
||
19 | WORD disp; |
||
20 | |||
21 | |||
22 | dbpos=0; |
||
23 | |||
24 | // get first byte of packed file and write to output |
||
25 | put_byte(NEXT_BYTE); |
||
26 | |||
27 | |||
28 | // second byte goes to bitstream |
||
29 | bitstream=NEXT_BYTE; |
||
30 | bitcount=8; |
||
31 | |||
32 | |||
33 | // actual depacking loop! |
||
34 | do |
||
35 | { |
||
36 | j=0; |
||
37 | |||
38 | // get 1st bit - either OUTBYTE or beginning of LZ code |
||
39 | if( get_bits_dirty(1) ) |
||
40 | { // OUTBYTE |
||
41 | put_byte(NEXT_BYTE); |
||
42 | } |
||
43 | else |
||
44 | { // LZ code |
||
45 | switch( get_bits_dirty(2) ) |
||
46 | { |
||
47 | case 0: // 000 |
||
48 | repeat( 0xFFF8|get_bits_dirty(3) ,1); |
||
49 | break; |
||
50 | case 1: // 001 |
||
51 | repeat( 0xFF00|NEXT_BYTE ,2); |
||
52 | break; |
||
53 | case 2: // 010 |
||
54 | repeat(get_bigdisp_dirty(),3); |
||
55 | break; |
||
56 | case 3: // 011 |
||
57 | // extract num of length bits |
||
58 | do j++; while( !get_bits_dirty(1) ); |
||
59 | |||
60 | if( j<8 ) // check for exit code |
||
61 | { |
||
62 | // get length bits itself |
||
63 | bits=get_bits_dirty(j); |
||
64 | disp=get_bigdisp_dirty(); |
||
65 | repeat(disp,2+(1<<j)+bits); |
||
66 | } |
||
67 | break; |
||
68 | } |
||
69 | } |
||
70 | |||
71 | } while( j<8 ); |
||
72 | |||
73 | |||
74 | if( (DBMASK&dbpos) ) |
||
75 | { |
||
76 | put_buffer(DBMASK&dbpos); |
||
77 | } |
||
78 | |||
79 | } |
||
80 | |||
81 | |||
82 | |||
83 | |||
84 | void repeat(WORD disp,UBYTE len) |
||
85 | { // repeat len bytes with disp displacement (negative) |
||
86 | // uses dbpos & dbuf |
||
87 | |||
88 | UBYTE i; // since length is no more than 255 |
||
89 | |||
90 | for(i=0;i<len;i++) |
||
91 | { |
||
92 | put_byte(dbuf[DBMASK&(dbpos+disp)]); |
||
93 | } |
||
94 | } |
||
95 | |||
96 | |||
97 | |||
98 | |||
99 | void put_byte(UBYTE byte) |
||
100 | { |
||
101 | dbuf[dbpos]=byte; |
||
102 | dbpos = DBMASK & (dbpos+1); |
||
103 | |||
104 | if( !dbpos ) |
||
105 | { |
||
106 | put_buffer(DBSIZE); |
||
107 | } |
||
108 | } |
||
109 | |||
110 | |||
111 | UBYTE get_bits_dirty(UBYTE numbits) |
||
112 | { // gets bits in a byte-wise style, no checks |
||
113 | // numbits must be >0 |
||
114 | |||
115 | UBYTE bits; |
||
116 | |||
117 | bits=0; |
||
118 | |||
119 | do |
||
120 | { |
||
121 | if( !(bitcount--) ) |
||
122 | { |
||
123 | bitcount=7; |
||
124 | bitstream=NEXT_BYTE; |
||
125 | } |
||
126 | |||
127 | bits = (bits<<1)|(bitstream>>7); // all shifts byte-wise |
||
128 | bitstream<<=1; |
||
129 | |||
130 | } while (--numbits); |
||
131 | |||
132 | return bits; |
||
133 | } |
||
134 | |||
135 | WORD get_bigdisp_dirty(void) |
||
136 | { // fetches 'big' displacement (-1..-4352) |
||
137 | // returns negative displacement |
||
138 | |||
139 | UBYTE bits; |
||
140 | |||
141 | if( get_bits_dirty(1) ) |
||
142 | { // longer displacement |
||
143 | bits=get_bits_dirty(4); |
||
144 | return (((0xF0|bits)-1)<<8)|NEXT_BYTE; |
||
145 | } |
||
146 | else |
||
147 | { // shorter displacement |
||
148 | return 0xFF00|NEXT_BYTE; |
||
149 | } |
||
150 | } |
||
151 |