Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
hrydgard
GitHub Repository: hrydgard/ppsspp
Path: blob/master/Core/FileSystems/tlzrc.cpp
3186 views
1
2
// tlzrc.c: LZRC decodeer
3
// based on benhur's code, rewrite by tpu
4
5
// Copyright (c) 2012- PPSSPP Project.
6
7
// This program is free software: you can redistribute it and/or modify
8
// it under the terms of the GNU General Public License as published by
9
// the Free Software Foundation, version 2.0 or later versions.
10
11
// This program is distributed in the hope that it will be useful,
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
// GNU General Public License 2.0 for more details.
15
16
// A copy of the GPL 2.0 should have been included with the program.
17
// If not, see http://www.gnu.org/licenses/
18
19
// Official git repository and contact information can be found at
20
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
21
22
#include <stdio.h>
23
#include <stdlib.h>
24
#include <string.h>
25
26
#include "Common/Common.h"
27
#include "Common/Log.h"
28
29
/*************************************************************/
30
31
typedef unsigned int u32;
32
typedef unsigned short u16;
33
typedef unsigned char u8;
34
35
/*************************************************************/
36
37
typedef struct{
38
39
// input stream
40
u8 *input;
41
int in_ptr;
42
int in_len;
43
44
// output stream
45
u8 *output;
46
int out_ptr;
47
int out_len;
48
49
// range decode
50
u32 range;
51
u32 code;
52
u32 out_code;
53
u8 lc;
54
55
u8 bm_literal[8][256];
56
u8 bm_dist_bits[8][39];
57
u8 bm_dist[18][8];
58
u8 bm_match[8][8];
59
u8 bm_len[8][31];
60
}LZRC_DECODE;
61
62
/*************************************************************/
63
64
static u8 rc_getbyte(LZRC_DECODE *rc)
65
{
66
if(rc->in_ptr == rc->in_len){
67
_dbg_assert_msg_(false, "LZRC: End of input!");
68
}
69
70
return rc->input[rc->in_ptr++];
71
}
72
73
static void rc_putbyte(LZRC_DECODE *rc, u8 byte)
74
{
75
if(rc->out_ptr == rc->out_len){
76
_dbg_assert_msg_(false, "LZRC: Output overflow!");
77
}
78
79
rc->output[rc->out_ptr++] = byte;
80
}
81
82
static void rc_init(LZRC_DECODE *rc, void *out, int out_len, void *in, int in_len)
83
{
84
rc->input = (u8*)in;
85
rc->in_len = in_len;
86
rc->in_ptr = 0;
87
88
rc->output = (u8*)out;
89
rc->out_len = out_len;
90
rc->out_ptr = 0;
91
92
rc->range = 0xffffffff;
93
rc->lc = rc_getbyte(rc);
94
rc->code = (rc_getbyte(rc)<<24) |
95
(rc_getbyte(rc)<<16) |
96
(rc_getbyte(rc)<< 8) |
97
(rc_getbyte(rc)<< 0) ;
98
rc->out_code = 0xffffffff;
99
100
memset(rc->bm_literal, 0x80, 2048);
101
memset(rc->bm_dist_bits, 0x80, 312);
102
memset(rc->bm_dist, 0x80, 144);
103
memset(rc->bm_match, 0x80, 64);
104
memset(rc->bm_len, 0x80, 248);
105
106
}
107
108
109
110
/*************************************************************/
111
112
/* range decode */
113
114
static void normalize(LZRC_DECODE *rc)
115
{
116
if(rc->range<0x01000000){
117
rc->range <<= 8;
118
rc->code = (rc->code<<8)+rc->input[rc->in_ptr];
119
rc->in_ptr++;
120
}
121
}
122
123
/* Decode a bit */
124
static int rc_bit(LZRC_DECODE *rc, u8 *prob)
125
{
126
u32 bound;
127
128
normalize(rc);
129
130
bound = (rc->range>>8)*(*prob);
131
*prob -= *prob>>3;
132
133
if(rc->code < bound){
134
rc->range = bound;
135
*prob += 31;
136
return 1;
137
}else{
138
rc->code -= bound;
139
rc->range -= bound;
140
return 0;
141
}
142
}
143
144
/* Decode a bittree starting from MSB */
145
static int rc_bittree(LZRC_DECODE *rc, u8 *probs, int limit)
146
{
147
int number = 1;
148
149
do{
150
number = (number<<1)+rc_bit(rc, probs+number);
151
}while(number<limit);
152
153
return number;
154
}
155
156
157
/*
158
* decode a number
159
*
160
* a number are divide into three part:
161
* MSB 2bits
162
* direct bits (don't use probability modle)
163
* LSB 3bits
164
*/
165
static int rc_number(LZRC_DECODE *rc, u8 *prob, int n)
166
{
167
int i, number = 1;
168
169
if(n>3){
170
number = (number<<1)+rc_bit(rc, prob+3);
171
if(n>4){
172
number = (number<<1)+rc_bit(rc, prob+3);
173
if(n>5){
174
// direct bits
175
normalize(rc);
176
177
for(i=0; i<n-5; i++){
178
rc->range >>= 1;
179
number <<= 1;
180
if (rc->code < rc->range){
181
number += 1;
182
}else{
183
rc->code -= rc->range;
184
}
185
}
186
}
187
}
188
}
189
190
if(n>0){
191
number = (number<<1)+rc_bit(rc, prob);
192
if(n>1){
193
number = (number<<1)+rc_bit(rc, prob+1);
194
if(n>2){
195
number = (number<<1)+rc_bit(rc, prob+2);
196
}
197
}
198
}
199
200
return number;
201
}
202
203
204
int lzrc_decompress(void *out, int out_len, void *in, int in_len)
205
{
206
LZRC_DECODE rc;
207
int match_step, rc_state, len_state, dist_state;
208
int i, bit, byte, last_byte;
209
int match_len, len_bits;
210
int match_dist, dist_bits, limit;
211
u8 *match_src;
212
int round = -1;
213
214
rc_init(&rc, out, out_len, in, in_len);
215
216
if(rc.lc&0x80){
217
/* plain text */
218
int copySize = rc.code;
219
if (copySize > out_len) {
220
copySize = out_len;
221
}
222
memcpy(rc.output, rc.input+5, copySize);
223
return copySize;
224
}
225
226
rc_state = 0;
227
last_byte = 0;
228
229
while (1) {
230
round += 1;
231
match_step = 0;
232
233
bit = rc_bit(&rc, &rc.bm_match[rc_state][match_step]);
234
if (bit==0) {
235
/* 0 -> raw char */
236
if(rc_state>0)
237
rc_state -= 1;
238
239
byte = rc_bittree(&rc, &rc.bm_literal[((last_byte>>rc.lc)&0x07)][0], 0x100);
240
byte -= 0x100;
241
242
rc_putbyte(&rc, byte);
243
} else {
244
/* 1 -> a match */
245
246
/* find bits of match length */
247
len_bits = 0;
248
for(i=0; i<7; i++){
249
match_step += 1;
250
bit = rc_bit(&rc, &rc.bm_match[rc_state][match_step]);
251
if(bit==0)
252
break;
253
len_bits += 1;
254
}
255
256
/* find match length */
257
if(len_bits==0){
258
match_len = 1;
259
}else{
260
len_state = ((len_bits-1)<<2)+((rc.out_ptr<<(len_bits-1))&0x03);
261
match_len = rc_number(&rc, &rc.bm_len[rc_state][len_state], len_bits);
262
if (match_len == 0xFF){
263
//end of stream
264
return rc.out_ptr;
265
}
266
}
267
268
/* find number of bits of match distance */
269
dist_state = 0;
270
limit = 8;
271
if(match_len>2){
272
dist_state += 7;
273
limit = 44;
274
}
275
dist_bits = rc_bittree(&rc, &rc.bm_dist_bits[len_bits][dist_state], limit);
276
dist_bits -= limit;
277
278
/* find match distance */
279
if(dist_bits>0){
280
match_dist = rc_number(&rc, &rc.bm_dist[dist_bits][0], dist_bits);
281
} else {
282
match_dist = 1;
283
}
284
285
/* copy match bytes */
286
if(match_dist>rc.out_ptr || match_dist<0){
287
printf("match_dist out of range! %08x\n", match_dist);
288
return -1;
289
}
290
match_src = rc.output+rc.out_ptr-match_dist;
291
for(i=0; i<match_len+1; i++){
292
rc_putbyte(&rc, *match_src++);
293
}
294
rc_state = 6+((rc.out_ptr+1)&1);
295
}
296
last_byte = rc.output[rc.out_ptr-1];
297
}
298
}
299
300