oodle-kraken-ruby 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: c1e6d630f19de2c2de3888643967ddbd39ef42d7187b7f9f60e4d871e4811648
4
+ data.tar.gz: 6e675ea78dcdfe739fa78c47e36ba61ab9aae9b7033ce20ae8483bad68cadfea
5
+ SHA512:
6
+ metadata.gz: 7ee8347d55b228dc8b86aa1e75c3c9a5123e54ec14b9c7363400635449119019f2db795b9e0f4b8f7e9cd8b49804a9c8e0d8e81441dfb6af26a3c1635880dc8a
7
+ data.tar.gz: 3876de0ddc9a0babcb20710eace1d86f3f9bf75a699d0b52c79f5b554ee893ec9b1d8fd075b4b03bfbbbf3d51a4fa3f0bbfaafd4ece59ee5621072c15ce132c5
data/LICENSE ADDED
@@ -0,0 +1,14 @@
1
+ Copyright (C) 2022, Kerilk
2
+
3
+ This program is free software: you can redistribute it and/or modify
4
+ it under the terms of the GNU General Public License as published by
5
+ the Free Software Foundation, either version 3 of the License, or
6
+ (at your option) any later version.
7
+
8
+ This program is distributed in the hope that it will be useful,
9
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ GNU General Public License for more details.
12
+
13
+ You should have received a copy of the GNU General Public License
14
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
@@ -0,0 +1,11 @@
1
+ require 'mkmf'
2
+
3
+ dir_config("oodle_kraken_c")
4
+
5
+ $srcs = ["oodle_kraken_c.c", "ooz/bitknit.cpp", "ooz/lzna.cpp", "ooz/kraken.cpp"]
6
+
7
+ $INCFLAGS << " -I$(srcdir)/ooz"
8
+
9
+ $VPATH << "$(srcdir)/ooz"
10
+
11
+ create_makefile("oodle_kraken_c")
@@ -0,0 +1,38 @@
1
+ #include <ruby.h>
2
+ #include "kraken.h"
3
+ #include <stdlib.h>
4
+
5
+ VALUE mOodleKraken;
6
+
7
+ #define SAFE_SPACE 64
8
+
9
+ static VALUE decompress_p(VALUE self, VALUE in_str, VALUE decompressed_size) {
10
+ (void)self;
11
+ VALUE out_str = Qnil;
12
+ Check_Type(in_str, T_STRING);
13
+ size_t out_sz = NUM2ULL(decompressed_size);
14
+ size_t in_sz = RSTRING_LEN(in_str);
15
+ const uint8_t *in_ptr = RSTRING_PTR(in_str);
16
+
17
+ uint8_t *out_ptr = malloc((long)out_sz + SAFE_SPACE);
18
+ if (!out_ptr)
19
+ rb_raise(rb_eRuntimeError, "Decompression Error");
20
+ ssize_t out_bytes = Kraken_Decompress(in_ptr, in_sz, out_ptr, out_sz);
21
+ if (out_bytes < 0 || (size_t)out_bytes != out_sz)
22
+ rb_raise(rb_eRuntimeError, "Decompression Error");
23
+ out_str = rb_str_buf_new((long)out_sz);
24
+ rb_str_cat(out_str, out_ptr, out_sz);
25
+ return out_str;
26
+ }
27
+
28
+ void Init_oodle_kraken_c() {
29
+ mOodleKraken = rb_define_module("OodleKraken");
30
+ /**
31
+ * @overload decompress(str, decompressed_size)
32
+ * decompress an Oodle compressed string
33
+ * @param str [String] the string to decompress
34
+ * @param decompressed_size [Integer] the size of the decompressed data
35
+ * @return [String] the decompressed string
36
+ */
37
+ rb_define_module_function(mOodleKraken, "decompress", decompress_p, 2);
38
+ }
@@ -0,0 +1,15 @@
1
+ Copyright (C) 2016, Powzix
2
+ Copyright (C) 2019, rarten
3
+
4
+ This program is free software: you can redistribute it and/or modify
5
+ it under the terms of the GNU General Public License as published by
6
+ the Free Software Foundation, either version 3 of the License, or
7
+ (at your option) any later version.
8
+
9
+ This program is distributed in the hope that it will be useful,
10
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ GNU General Public License for more details.
13
+
14
+ You should have received a copy of the GNU General Public License
15
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
@@ -0,0 +1,23 @@
1
+ # ooz
2
+ Open source Kraken / Mermaid / Selkie / Leviathan / LZNA / Bitknit decompressor
3
+
4
+ Also supports using oo2core_7_win32.dll / oo2core_7_win64.dll which can be acquired from the free game Warframe on steam.
5
+
6
+ ```
7
+ ooz v7.0
8
+
9
+ Usage: ooz [options] input [output]
10
+ -c --stdout write to stdout
11
+ -d --decompress decompress (default)
12
+ -z --compress compress (requires oo2core_7_win64.dll)
13
+ -b just benchmark, don't overwrite anything
14
+ -f force overwrite existing file
15
+ --dll decompress with the dll
16
+ --verify decompress and verify that it matches output
17
+ --verify=<folder> verify with files in this folder
18
+ -<1-9> --level=<-4..10> compression level
19
+ -m<k> [k|m|s|l|h] compressor selection
20
+ --kraken --mermaid --selkie --leviathan --hydra compressor selection
21
+
22
+ (Warning! not fuzz safe, so please trust the input)
23
+ ```
@@ -0,0 +1,429 @@
1
+ /*
2
+ Copyright (C) 2016, Powzix
3
+ Copyright (C) 2019, rarten
4
+
5
+ This program is free software: you can redistribute it and/or modify
6
+ it under the terms of the GNU General Public License as published by
7
+ the Free Software Foundation, either version 3 of the License, or
8
+ (at your option) any later version.
9
+
10
+ This program is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU General Public License for more details.
14
+
15
+ You should have received a copy of the GNU General Public License
16
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+ */
18
+
19
+ #include "stdafx.h"
20
+
21
+ struct BitknitLiteral {
22
+ uint16 lookup[512 + 4];
23
+ uint16 a[300 + 1];
24
+ uint16 freq[300];
25
+ uint32 adapt_interval;
26
+ };
27
+
28
+ struct BitknitDistanceLsb {
29
+ uint16 lookup[64 + 4];
30
+ uint16 a[40 + 1];
31
+ uint16 freq[40];
32
+ uint32 adapt_interval;
33
+ };
34
+
35
+ struct BitknitDistanceBits {
36
+ uint16 lookup[64 + 4];
37
+ uint16 a[21 + 1];
38
+ uint16 freq[21];
39
+ uint32 adapt_interval;
40
+ };
41
+
42
+
43
+ struct BitknitState {
44
+ uint32 recent_dist[8];
45
+ uint32 last_match_dist;
46
+ uint32 recent_dist_mask;
47
+ uint32 bits, bits2;
48
+
49
+ BitknitLiteral literals[4];
50
+ BitknitDistanceLsb distance_lsb[4];
51
+ BitknitDistanceBits distance_bits;
52
+ };
53
+
54
+ void BitknitLiteral_Init(BitknitLiteral *model) {
55
+ size_t i;
56
+ uint16 *p, *p_end;
57
+
58
+ for (i = 0; i < 264; i++)
59
+ model->a[i] = (0x8000 - 300 + 264) * i / 264;
60
+ for (; i <= 300; i++)
61
+ model->a[i] = (0x8000 - 300) + i;
62
+
63
+ model->adapt_interval = 1024;
64
+ for (i = 0; i < 300; i++)
65
+ model->freq[i] = 1;
66
+
67
+ for (i = 0, p = model->lookup; i < 300; i++) {
68
+ p_end = &model->lookup[(model->a[i + 1] - 1) >> 6];
69
+ do {
70
+ p[0] = p[1] = p[2] = p[3] = i;
71
+ p += 4;
72
+ } while (p <= p_end);
73
+ p = p_end + 1;
74
+ }
75
+ }
76
+
77
+ void BitknitDistanceLsb_Init(BitknitDistanceLsb *model) {
78
+ size_t i;
79
+ uint16 *p, *p_end;
80
+
81
+ for (i = 0; i <= 40; i++)
82
+ model->a[i] = 0x8000 * i / 40;
83
+
84
+ model->adapt_interval = 1024;
85
+ for (i = 0; i < 40; i++)
86
+ model->freq[i] = 1;
87
+
88
+ for (i = 0, p = model->lookup; i < 40; i++) {
89
+ p_end = &model->lookup[(model->a[i + 1] - 1) >> 9];
90
+ do {
91
+ p[0] = p[1] = p[2] = p[3] = i;
92
+ p += 4;
93
+ } while (p <= p_end);
94
+ p = p_end + 1;
95
+ }
96
+ }
97
+
98
+ void BitknitDistanceBits_Init(BitknitDistanceBits *model) {
99
+ size_t i;
100
+ uint16 *p, *p_end;
101
+
102
+ for (i = 0; i <= 21; i++)
103
+ model->a[i] = 0x8000 * i / 21;
104
+
105
+ model->adapt_interval = 1024;
106
+ for (i = 0; i < 21; i++)
107
+ model->freq[i] = 1;
108
+
109
+ for (i = 0, p = model->lookup; i < 21; i++) {
110
+ p_end = &model->lookup[(model->a[i + 1] - 1) >> 9];
111
+ do {
112
+ p[0] = p[1] = p[2] = p[3] = i;
113
+ p += 4;
114
+ } while (p <= p_end);
115
+ p = p_end + 1;
116
+ }
117
+ }
118
+
119
+ void BitknitState_Init(BitknitState *bk) {
120
+ size_t i;
121
+
122
+ bk->last_match_dist = 1;
123
+ for (i = 0; i < 8; i++)
124
+ bk->recent_dist[i] = 1;
125
+
126
+ bk->recent_dist_mask =
127
+ (7 << (7 * 3)) | (6 << (6 * 3)) |
128
+ (5 << (5 * 3)) | (4 << (4 * 3)) |
129
+ (3 << (3 * 3)) | (2 << (2 * 3)) |
130
+ (1 << (1 * 3)) | (0 << (0 * 3));
131
+
132
+ for (i = 0; i < 4; i++)
133
+ BitknitLiteral_Init(&bk->literals[i]);
134
+
135
+ for (i = 0; i < 4; i++)
136
+ BitknitDistanceLsb_Init(&bk->distance_lsb[i]);
137
+
138
+ BitknitDistanceBits_Init(&bk->distance_bits);
139
+
140
+ }
141
+
142
+ void BitknitLiteral_Adaptive(BitknitLiteral *model, uint32 sym) {
143
+ size_t i;
144
+ uint32 sum;
145
+ uint16 *p, *p_end;
146
+
147
+ model->adapt_interval = 1024;
148
+ model->freq[sym] += 725;
149
+
150
+ sum = 0;
151
+ for (i = 0; i < 300; i++) {
152
+ sum += model->freq[i];
153
+ model->freq[i] = 1;
154
+ model->a[i + 1] = model->a[i + 1] + ((sum - model->a[i + 1]) >> 1);
155
+ }
156
+
157
+ for (i = 0, p = model->lookup; i < 300; i++) {
158
+ p_end = &model->lookup[(model->a[i + 1] - 1) >> 6];
159
+ do {
160
+ p[0] = p[1] = p[2] = p[3] = i;
161
+ p += 4;
162
+ } while (p <= p_end);
163
+ p = p_end + 1;
164
+ }
165
+ }
166
+
167
+ uint32 BitknitLiteral_Lookup(BitknitLiteral *model, uint32 *bits) {
168
+ uint32 masked = *bits & 0x7FFF;
169
+ size_t sym = model->lookup[masked >> 6];
170
+ sym += masked > model->a[sym + 1];
171
+ while (masked >= model->a[sym + 1])
172
+ sym += 1;
173
+ *bits = masked + (*bits >> 15) * (model->a[sym + 1] - model->a[sym]) - model->a[sym];
174
+ model->freq[sym] += 31;
175
+ if (--model->adapt_interval == 0)
176
+ BitknitLiteral_Adaptive(model, sym);
177
+ return sym;
178
+ }
179
+
180
+ void BitknitDistanceLsb_Adaptive(BitknitDistanceLsb *model, uint32 sym) {
181
+ size_t i;
182
+ uint32 sum;
183
+ uint16 *p, *p_end;
184
+
185
+ model->adapt_interval = 1024;
186
+ model->freq[sym] += 985;
187
+
188
+ sum = 0;
189
+ for (i = 0; i < 40; i++) {
190
+ sum += model->freq[i];
191
+ model->freq[i] = 1;
192
+ model->a[i + 1] = model->a[i + 1] + ((sum - model->a[i + 1]) >> 1);
193
+ }
194
+
195
+ for (i = 0, p = model->lookup; i < 40; i++) {
196
+ p_end = &model->lookup[(model->a[i + 1] - 1) >> 9];
197
+ do {
198
+ p[0] = p[1] = p[2] = p[3] = i;
199
+ p += 4;
200
+ } while (p <= p_end);
201
+ p = p_end + 1;
202
+ }
203
+ }
204
+
205
+ uint32 BitknitDistanceLsb_Lookup(BitknitDistanceLsb *model, uint32 *bits) {
206
+ uint32 masked = *bits & 0x7FFF;
207
+ size_t sym = model->lookup[masked >> 9];
208
+ sym += masked > model->a[sym + 1];
209
+ while (masked >= model->a[sym + 1])
210
+ sym += 1;
211
+ *bits = masked + (*bits >> 15) * (model->a[sym + 1] - model->a[sym]) - model->a[sym];
212
+ model->freq[sym] += 31;
213
+ if (--model->adapt_interval == 0)
214
+ BitknitDistanceLsb_Adaptive(model, sym);
215
+ return sym;
216
+ }
217
+
218
+
219
+ void BitknitDistanceBits_Adaptive(BitknitDistanceBits *model, uint32 sym) {
220
+ size_t i;
221
+ uint32 sum;
222
+ uint16 *p, *p_end;
223
+
224
+ model->adapt_interval = 1024;
225
+ model->freq[sym] += 1004;
226
+
227
+ sum = 0;
228
+ for (i = 0; i < 21; i++) {
229
+ sum += model->freq[i];
230
+ model->freq[i] = 1;
231
+ model->a[i + 1] = model->a[i + 1] + ((sum - model->a[i + 1]) >> 1);
232
+ }
233
+
234
+ for (i = 0, p = model->lookup; i < 21; i++) {
235
+ p_end = &model->lookup[(model->a[i + 1] - 1) >> 9];
236
+ do {
237
+ p[0] = p[1] = p[2] = p[3] = i;
238
+ p += 4;
239
+ } while (p <= p_end);
240
+ p = p_end + 1;
241
+ }
242
+ }
243
+
244
+ uint32 BitknitDistanceBits_Lookup(BitknitDistanceBits *model, uint32 *bits) {
245
+ uint32 masked = *bits & 0x7FFF;
246
+ size_t sym = model->lookup[masked >> 9];
247
+ sym += masked > model->a[sym + 1];
248
+ while (masked >= model->a[sym + 1])
249
+ sym += 1;
250
+ *bits = masked + (*bits >> 15) * (model->a[sym + 1] - model->a[sym]) - model->a[sym];
251
+ model->freq[sym] += 31;
252
+ if (--model->adapt_interval == 0)
253
+ BitknitDistanceBits_Adaptive(model, sym);
254
+ return sym;
255
+ }
256
+
257
+
258
+ #define RENORMALIZE() { if (bits < 0x10000) bits = (bits << 16) | *(uint16*)src, src += 2; bitst = bits; bits = bits2; bits2 = bitst; }
259
+
260
+
261
+ static void BitknitCopyLongDist(byte *dst, size_t dist, size_t length) {
262
+ const byte *src = dst - dist;
263
+ ((uint64*)dst)[0] = ((uint64*)src)[0];
264
+ ((uint64*)dst)[1] = ((uint64*)src)[1];
265
+ if (length > 16) {
266
+ do {
267
+ ((uint64*)dst)[2] = ((uint64*)src)[2];
268
+ dst += 8;
269
+ src += 8;
270
+ length -= 8;
271
+ } while (length > 16);
272
+ }
273
+ }
274
+
275
+ static void BitknitCopyShortDist(byte *dst, size_t dist, size_t length) {
276
+ const byte *src = dst - dist;
277
+ if (dist >= 4) {
278
+ ((uint32*)dst)[0] = ((uint32*)src)[0];
279
+ ((uint32*)dst)[1] = ((uint32*)src)[1];
280
+ ((uint32*)dst)[2] = ((uint32*)src)[2];
281
+ if (length > 12) {
282
+ ((uint32*)dst)[3] = ((uint32*)src)[3];
283
+ if (length > 16) {
284
+ do {
285
+ ((uint32*)dst)[4] = ((uint32*)src)[4];
286
+ length -= 4;
287
+ dst += 4;
288
+ src += 4;
289
+ } while (length > 16);
290
+ }
291
+ }
292
+ } else if (dist == 1) {
293
+ memset(dst, *src, length);
294
+ } else {
295
+ ((byte*)dst)[0] = ((byte*)src)[0];
296
+ ((byte*)dst)[1] = ((byte*)src)[1];
297
+ ((byte*)dst)[2] = ((byte*)src)[2];
298
+ ((byte*)dst)[3] = ((byte*)src)[3];
299
+ ((byte*)dst)[4] = ((byte*)src)[4];
300
+ ((byte*)dst)[5] = ((byte*)src)[5];
301
+ ((byte*)dst)[6] = ((byte*)src)[6];
302
+ ((byte*)dst)[7] = ((byte*)src)[7];
303
+ ((byte*)dst)[8] = ((byte*)src)[8];
304
+ while (length > 9) {
305
+ ((byte*)dst)[9] = ((byte*)src)[9];
306
+ dst += 1;
307
+ src += 1;
308
+ length -= 1;
309
+ }
310
+ }
311
+ }
312
+
313
+
314
+ size_t Bitknit_Decode(const byte *src, const byte *src_end, byte *dst, byte *dst_end, byte *dst_start, BitknitState *bk) {
315
+ const byte *src_in = src;
316
+ BitknitLiteral *litmodel[4];
317
+ BitknitDistanceLsb *distancelsb[4];
318
+ size_t i;
319
+ intptr_t last_match_negative;
320
+ uint32 bits, bits2, bitst;
321
+ uint32 v, a, n;
322
+ uint32 copy_length;
323
+ uint32 recent_dist_mask;
324
+ uint32 match_dist;
325
+
326
+ for (i = 0; i < 4; i++)
327
+ litmodel[i] = &bk->literals[(i - (intptr_t)dst_start) & 3];
328
+
329
+ for (i = 0; i < 4; i++)
330
+ distancelsb[i] = &bk->distance_lsb[(i - (intptr_t)dst_start) & 3];
331
+
332
+
333
+ recent_dist_mask = bk->recent_dist_mask;
334
+ bits = 0x10000;
335
+ bits2 = 0x10000;
336
+ last_match_negative = -(intptr_t)bk->last_match_dist;
337
+
338
+ v = *(uint32*)src, src += 4;
339
+ if (v < 0x10000)
340
+ return 0;
341
+
342
+ a = v >> 4;
343
+ n = v & 0xF;
344
+ if (a < 0x10000)
345
+ a = (a << 16) | *(uint16*)src, src += 2;
346
+ bits = a >> n;
347
+ if (bits < 0x10000)
348
+ bits = (bits << 16) | *(uint16*)src, src += 2;
349
+ a = (a << 16) | *(uint16*)src, src += 2;
350
+
351
+ bits2 = (1 << (n + 16)) | (a & ((1 << (n + 16)) - 1));
352
+
353
+ if (dst == dst_start) {
354
+ *dst++ = bits;
355
+ bits >>= 8;
356
+ RENORMALIZE();
357
+ }
358
+
359
+ while (dst + 4 < dst_end) {
360
+ uint32 sym = BitknitLiteral_Lookup(litmodel[(intptr_t)dst & 3], &bits);
361
+ RENORMALIZE();
362
+
363
+ if (sym < 256) {
364
+ *dst = sym + dst[last_match_negative];
365
+ dst++;
366
+
367
+ if (dst + 4 >= dst_end)
368
+ break;
369
+
370
+ sym = BitknitLiteral_Lookup(litmodel[(intptr_t)dst & 3], &bits);
371
+ RENORMALIZE();
372
+
373
+ if (sym < 256) {
374
+ *dst = sym + dst[last_match_negative];
375
+ dst++;
376
+ continue;
377
+ }
378
+ }
379
+
380
+ if (sym >= 288) {
381
+ uint32 nb = sym - 287;
382
+ sym = (bits & ((1 << nb) - 1)) + (1 << nb) + 286;
383
+ bits >>= nb;
384
+ RENORMALIZE();
385
+ }
386
+
387
+ copy_length = sym - 254;
388
+
389
+ sym = BitknitDistanceLsb_Lookup(distancelsb[(intptr_t)dst & 3], &bits);
390
+ RENORMALIZE();
391
+
392
+ if (sym >= 8) {
393
+ uint32 nb = BitknitDistanceBits_Lookup(&bk->distance_bits, &bits);
394
+ RENORMALIZE();
395
+
396
+ match_dist = bits & ((1 << (nb & 0xF)) - 1);
397
+ bits >>= (nb & 0xF);
398
+ RENORMALIZE();
399
+ if (nb >= 0x10)
400
+ match_dist = (match_dist << 16) | *(uint16*)src, src += 2;
401
+ match_dist = (32 << nb) + (match_dist << 5) + sym - 39;
402
+
403
+ bk->recent_dist[(recent_dist_mask >> 21) & 7] = bk->recent_dist[(recent_dist_mask >> 18) & 7];
404
+ bk->recent_dist[(recent_dist_mask >> 18) & 7] = match_dist;
405
+
406
+ } else {
407
+ size_t idx = (recent_dist_mask >> (3 * sym)) & 7;
408
+ uint32 mask = ~7 << (3 * sym);
409
+ match_dist = bk->recent_dist[idx];
410
+ recent_dist_mask = (recent_dist_mask & mask) | ((idx + 8 * recent_dist_mask) & ~mask);
411
+ }
412
+
413
+ if (match_dist >= 8) {
414
+ BitknitCopyLongDist(dst, match_dist, copy_length);
415
+ } else {
416
+ BitknitCopyShortDist(dst, match_dist, copy_length);
417
+ }
418
+
419
+ dst += copy_length;
420
+
421
+ last_match_negative = -(intptr_t)match_dist;
422
+ }
423
+ *(uint32*)dst = (uint16)bits | bits2 << 16;
424
+
425
+ bk->last_match_dist = -last_match_negative;
426
+ bk->recent_dist_mask = recent_dist_mask;
427
+ return src - src_in;
428
+ }
429
+