oodle-kraken-ruby 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+