]>
git.zerfleddert.de Git - rsbs2/blob - rsb-lz.c
c771b894ffa4ddc314635bf23e1677de0d3cf687
9 #include "filesystem.h"
11 void err_exit(const char *fname
)
13 fprintf(stderr
,"%s: error extracting...\n", fname
);
29 unsigned char get_next_in_byte(struct data_in_s
*data_in
)
33 if (data_in
->stop
< data_in
->start
)
36 byte
= *(data_in
->start
);
42 unsigned char get_next_bit(struct data_in_s
*data_in
)
46 if (data_in
->bitpos
== 0x80) {
47 data_in
->byte
= get_next_in_byte(data_in
);
50 bitval
= data_in
->bitpos
& data_in
->byte
;
52 data_in
->bitpos
>>= 1;
53 if (data_in
->bitpos
== 0) {
54 data_in
->bitpos
= 0x80;
63 unsigned int get_next_bits(struct data_in_s
*data_in
, unsigned int bits
)
66 unsigned int next_bits
;
68 bit
= 1 << (bits
- 1);
72 if (data_in
->bitpos
== 0x80) {
73 data_in
->byte
= get_next_in_byte(data_in
);
76 if ((data_in
->bitpos
& data_in
->byte
) != 0)
77 next_bits
= next_bits
| bit
;
81 data_in
->bitpos
>>= 1;
83 if(data_in
->bitpos
== 0) {
84 data_in
->bitpos
= 0x80;
91 void write_byte(unsigned char byte
, struct data_out_s
*data_out
)
93 if (data_out
->pos
> data_out
->end
) {
97 *(data_out
->pos
) = byte
;
101 void lz_expand(struct data_in_s
*data_in
, struct data_out_s
*data_out
)
104 unsigned int wordoffset
;
107 unsigned int wordlen
;
108 unsigned char buf
[1024];
114 /* Compressed/uncompressed? */
115 if (get_next_bit(data_in
) == 0)
118 /* Uncompressed byte */
119 byte
= get_next_bits(data_in
, 8);
121 write_byte(byte
, data_out
);
123 /* Save byte in buffer, to be reused later */
125 pos
= (pos
+ 1) & 0x3ff;
128 /* offset for start of dictionary word */
129 wordoffset
= get_next_bits(data_in
, 0x0a);
133 /* length of dictionary word used */
134 wordlen
= get_next_bits(data_in
, 0x04) + 1;
135 for (i
= 0; i
<= wordlen
; i
++) {
136 /* lookup dictionary byte */
137 byte
= buf
[(wordoffset
+ i
) & 0x3ff];
138 write_byte(byte
, data_out
);
139 /* Save byte in buffer, to be reused later */
141 pos
= (pos
+ 1) & 0x3ff;
146 void set_next_bit(unsigned char *buf
, unsigned int set
, unsigned int *currbit
) {
148 unsigned char bitpos
;
151 pos
= buf
+ ((*currbit
) / 8);
152 bitpos
= 0x80 >> ((*currbit
) % 8);
156 *currbit
= *currbit
+ 1;
159 void write_bits(unsigned char *buf
, unsigned int data
, unsigned int bits
, unsigned int *currbit
) {
163 bitpos
= 1 << (bits
- 1);
165 for (i
= 0; i
< bits
; i
++) {
166 set_next_bit(buf
, data
& bitpos
, currbit
);
171 unsigned char *compress_lz(unsigned char *inbuf
, int inlen
, int *outlen
)
173 unsigned char *end
= inbuf
+ inlen
;
174 unsigned char *outbuf
;
175 unsigned char window
[1024];
178 unsigned int currbit
= 0;
184 if ((outbuf
= malloc((inlen
* 2) + 4)) == NULL
) {
188 *((unsigned int*)outbuf
) = LZ_MAGIC
;
193 for (wordlen
= 17; wordlen
> 1; wordlen
--) {
194 for (offset
= 1; offset
< ((fill
< 1023) ? fill
: 1023); offset
++) {
196 (wordlen
+ offset
> fill
))
199 for (i
= 0; i
< wordlen
; i
++) {
200 if (inbuf
[i
] != window
[(offset
+ i
) & 0x3ff]) {
212 write_bits(outbuf
, 0x00, 0x01, &currbit
);
213 write_bits(outbuf
, offset
, 0x0a, &currbit
);
214 write_bits(outbuf
, wordlen
- 1, 0x04, &currbit
);
215 for (i
= 0; i
< wordlen
; i
++) {
216 window
[pos
] = *(inbuf
+ i
);
217 pos
= (pos
+ 1) & 0x3ff;
221 if (fill
< sizeof(window
))
224 write_bits(outbuf
, 0x01, 0x01, &currbit
);
225 write_bits(outbuf
, *inbuf
, 0x08, &currbit
);
226 window
[pos
] = *inbuf
;
227 pos
= (pos
+ 1) & 0x3ff;
229 if (fill
< sizeof(window
))
234 write_bits(outbuf
, 0x00, 0x01, &currbit
);
235 write_bits(outbuf
, 0x00, 0x0a, &currbit
);
237 *outlen
= (currbit
/ 8) + 1;
239 *((unsigned int*)(outbuf
+ 4)) = *outlen
;
244 /* Checksum is only used for the compressed firmware in 'firmware' */
245 unsigned int crc_check(unsigned char *buf
, unsigned int len
, unsigned int magic
)
247 unsigned int file_crc
;
250 unsigned int my_magic
;
252 my_len
= *((unsigned int*)(buf
+ 0x20));
253 my_magic
= *((unsigned int*)(buf
+ 0x24));
255 if (my_magic
!= magic
) {
256 printf("\nmagic: 0x%08x <-> 0x%08x\n", my_magic
, magic
);
263 crc
= ~rsb_crc(~0x00, buf
, len
);
264 file_crc
= *((unsigned int*)(buf
+ len
));
266 if (file_crc
!= crc
) {
267 printf("\nChecksums: 0x%08x <-> 0x%08x!\n", crc
, file_crc
);
274 void extract_lz_file(unsigned char *inbuf
, unsigned char *name
, unsigned char check_crc
)
277 unsigned char *outbuf
;
278 struct data_in_s data_in
;
279 struct data_out_s data_out
;
281 if (*((unsigned int*)inbuf
) != LZ_MAGIC
)
284 len
= *((unsigned int*)(inbuf
+ 4));
285 printf(", length: %d", len
);
287 if ((outbuf
= malloc(len
)) == NULL
) {
294 data_in
.start
= inbuf
+ 8;
295 data_in
.stop
= inbuf
+ len
;
297 data_in
.bitpos
= 0x80;
299 data_out
.pos
= outbuf
;
300 data_out
.end
= outbuf
+ len
;
302 lz_expand(&data_in
, &data_out
);
308 crclen
= *((unsigned int*)(outbuf
+ 0x20));
310 if ((ret
= crc_check(outbuf
, crclen
, 0x46335053)) != 0) {
311 printf("crc_check return: %d\n", ret
);
315 write_file(extracted_file((char*)name
), outbuf
, len
);