CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
hrydgard

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: hrydgard/ppsspp
Path: blob/master/Core/FileSystems/tlzrc.cpp
Views: 1401
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
memcpy(rc.output, rc.input+5, rc.code);
219
return rc.code;
220
}
221
222
rc_state = 0;
223
last_byte = 0;
224
225
226
while (1) {
227
round += 1;
228
match_step = 0;
229
230
bit = rc_bit(&rc, &rc.bm_match[rc_state][match_step]);
231
if (bit==0) {
232
/* 0 -> raw char */
233
if(rc_state>0)
234
rc_state -= 1;
235
236
byte = rc_bittree(&rc, &rc.bm_literal[((last_byte>>rc.lc)&0x07)][0], 0x100);
237
byte -= 0x100;
238
239
rc_putbyte(&rc, byte);
240
} else {
241
/* 1 -> a match */
242
243
/* find bits of match length */
244
len_bits = 0;
245
for(i=0; i<7; i++){
246
match_step += 1;
247
bit = rc_bit(&rc, &rc.bm_match[rc_state][match_step]);
248
if(bit==0)
249
break;
250
len_bits += 1;
251
}
252
253
/* find match length */
254
if(len_bits==0){
255
match_len = 1;
256
}else{
257
len_state = ((len_bits-1)<<2)+((rc.out_ptr<<(len_bits-1))&0x03);
258
match_len = rc_number(&rc, &rc.bm_len[rc_state][len_state], len_bits);
259
if (match_len == 0xFF){
260
//end of stream
261
return rc.out_ptr;
262
}
263
}
264
265
/* find number of bits of match distance */
266
dist_state = 0;
267
limit = 8;
268
if(match_len>2){
269
dist_state += 7;
270
limit = 44;
271
}
272
dist_bits = rc_bittree(&rc, &rc.bm_dist_bits[len_bits][dist_state], limit);
273
dist_bits -= limit;
274
275
/* find match distance */
276
if(dist_bits>0){
277
match_dist = rc_number(&rc, &rc.bm_dist[dist_bits][0], dist_bits);
278
} else {
279
match_dist = 1;
280
}
281
282
/* copy match bytes */
283
if(match_dist>rc.out_ptr || match_dist<0){
284
printf("match_dist out of range! %08x\n", match_dist);
285
return -1;
286
}
287
match_src = rc.output+rc.out_ptr-match_dist;
288
for(i=0; i<match_len+1; i++){
289
rc_putbyte(&rc, *match_src++);
290
}
291
rc_state = 6+((rc.out_ptr+1)&1);
292
}
293
last_byte = rc.output[rc.out_ptr-1];
294
}
295
}
296
297