Subversion Repositories Kolibri OS

Rev

Rev 9029 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2288 clevermous 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
9715 Doczom 3
;; Copyright (C) KolibriOS team 2004-2022. All rights reserved. ;;
2288 clevermous 4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7
 
8
$Revision: 9715 $
9
 
10
 
9027 Boppan 11
; @brief Unpack LZMA-compressed data. C-style declaration of the function.
12
;
9029 Boppan 13
; ```void __stdcall unpack(void *packed_data, void *unpacked_data);```
9027 Boppan 14
;
15
; @param packed_data Data to unpack
16
; @param unpacked_data Buffer to hold unpacked data
17
; @returns Nothing
2288 clevermous 18
unpack:
19
        pushad
20
        mov     esi, [esp+32+4]
21
        mov     edi, [esp+32+8]
22
        mov     eax, [esi+8]
23
        and     al, 0xC0
24
        cmp     al, 0xC0
25
        jz      .failed
26
        mov     eax, [esi+8]
27
        push    eax
28
        add     esi, 12
29
        and     al, not 0xC0
30
        dec     al
31
        jz      .lzma
32
.failed:
33
        pop     eax
34
        popad
35
        ret     8
36
.lzma:
37
        call    .lzma_unpack
38
.common:
39
        pop     eax
40
        test    al, 0x80
41
        jnz     .ctr1
42
        test    al, 0x40
43
        jz      .ok
44
        lodsd
45
        mov     ecx, eax
46
        jecxz   .ok
47
        mov     dl, [esi]
48
        mov     esi, [esp+32+8]
49
.c1:
50
        lodsb
51
        sub     al, 0E8h
52
        cmp     al, 1
53
        ja      .c1
54
        cmp     byte [esi], dl
55
        jnz     .c1
56
        lodsd
57
; "bswap eax" is not supported on i386
58
        shr     ax, 8
59
        ror     eax, 16
60
        xchg    al, ah
61
        sub     eax, esi
62
        add     eax, [esp+32+8]
63
        mov     [esi-4], eax
64
        loop    .c1
65
.ok:
66
        popad
67
        ret     8
68
.ctr1:
69
        lodsd
70
        mov     ecx, eax
71
        jecxz   .ok
72
        mov     dl, [esi]
73
        mov     esi, [esp+32+8]
74
.c2:
75
        lodsb
76
@@:
77
        cmp     al, 0xF
78
        jnz     .f
79
        lodsb
80
        cmp     al, 80h
81
        jb      @b
82
        cmp     al, 90h
83
        jb      @f
84
.f:
85
        sub     al, 0E8h
86
        cmp     al, 1
87
        ja      .c2
88
@@:
89
        cmp     byte [esi], dl
90
        jnz     .c2
91
        lodsd
92
        shr     ax, 8
93
        ror     eax, 16
94
        xchg    al, ah
95
        sub     eax, esi
96
        add     eax, [esp+32+8]
97
        mov     [esi-4], eax
98
        loop    .c2
99
        jmp     .ok
100
 
101
.lzma_unpack:
102
 
103
.pb     =       2       ; pos state bits
104
.lp     =       0       ; literal pos state bits
105
.lc     =       3       ; literal context bits
106
.posStateMask   =       ((1 shl .pb)-1)
107
.literalPosMask =       ((1 shl .lp)-1)
108
 
109
.kNumPosBitsMax =       4
110
.kNumPosStatesMax =     (1 shl .kNumPosBitsMax)
111
 
112
.kLenNumLowBits         =       3
113
.kLenNumLowSymbols      =       (1 shl .kLenNumLowBits)
114
.kLenNumMidBits         =       3
115
.kLenNumMidSymbols      =       (1 shl .kLenNumMidBits)
116
.kLenNumHighBits        =       8
117
.kLenNumHighSymbols     =       (1 shl .kLenNumHighBits)
118
 
119
.LenChoice      =       0
120
.LenChoice2     =       1
121
.LenLow         =       2
122
.LenMid         =       (.LenLow + (.kNumPosStatesMax shl .kLenNumLowBits))
123
.LenHigh        =       (.LenMid + (.kNumPosStatesMax shl .kLenNumMidBits))
124
.kNumLenProbs   =       (.LenHigh + .kLenNumHighSymbols)
125
 
126
.kNumStates     =       12
127
.kNumLitStates  =       7
128
.kStartPosModelIndex =  4
129
.kEndPosModelIndex =    14
130
.kNumFullDistances =    (1 shl (.kEndPosModelIndex/2))
131
.kNumPosSlotBits =      6
132
.kNumLenToPosStates =   4
133
.kNumAlignBits  =       4
134
.kAlignTableSize =      (1 shl .kNumAlignBits)
135
.kMatchMinLen   =       2
136
 
137
.IsMatch        =       0
138
.IsRep          =       (.IsMatch + (.kNumStates shl .kNumPosBitsMax))
139
.IsRepG0        =       (.IsRep + .kNumStates)
140
.IsRepG1        =       (.IsRepG0 + .kNumStates)
141
.IsRepG2        =       (.IsRepG1 + .kNumStates)
142
.IsRep0Long     =       (.IsRepG2 + .kNumStates)
143
.PosSlot        =       (.IsRep0Long + (.kNumStates shl .kNumPosBitsMax))
144
.SpecPos        =       (.PosSlot + (.kNumLenToPosStates shl .kNumPosSlotBits))
145
.Align_         =       (.SpecPos + .kNumFullDistances - .kEndPosModelIndex)
146
.Lencoder       =       (.Align_ + .kAlignTableSize)
147
.RepLencoder    =       (.Lencoder + .kNumLenProbs)
148
.Literal        =       (.RepLencoder + .kNumLenProbs)
149
 
150
.LZMA_BASE_SIZE =       1846    ; must be ==Literal
151
.LZMA_LIT_SIZE  =       768
152
 
153
.kNumTopBits    =       24
154
.kTopValue      =       (1 shl .kNumTopBits)
155
 
156
.kNumBitModelTotalBits =        11
157
.kBitModelTotal =       (1 shl .kNumBitModelTotalBits)
158
.kNumMoveBits   =       5
159
 
160
        push    edi
161
; int state=0;
162
        xor     ebx, ebx
163
        mov     [.previousByte], bl
164
; unsigned rep0=1,rep1=1,rep2=1,rep3=1;
165
        mov     eax, 1
166
        mov     edi, .rep0
167
        stosd
168
        stosd
169
        stosd
170
        stosd
171
; int len=0;
172
; result=0;
173
        mov     ecx, .Literal + (.LZMA_LIT_SIZE shl (.lc+.lp))
174
        mov     eax, .kBitModelTotal/2
175
        mov     edi, [.p]
176
        rep stosd
177
; RangeDecoderInit
178
; rd->ExtraBytes = 0
179
; rd->Buffer = stream
180
; rd->BufferLim = stream+bufferSize
181
; rd->Range = 0xFFFFFFFF
182
        pop     edi
183
        mov     ebp, [esi-8]    ; dest_length
184
        add     ebp, edi        ; ebp = destination limit
185
        lodsd
186
; rd->code_ = eax
187
        mov     [.code_], eax
188
        or      [.range], -1
189
.main_loop:
190
        cmp     edi, ebp
191
        jae     .main_loop_done
192
        mov     edx, edi
193
        and     edx, .posStateMask
194
        mov     eax, ebx
195
        shl     eax, .kNumPosBitsMax+2
196
        lea     eax, [.IsMatch*4 + eax + edx*4]
197
        add     eax, [.p]
198
        call    .RangeDecoderBitDecode
199
        jc      .1
200
        movzx   eax, [.previousByte]
201
if .literalPosMask
202
        mov     ah, dl
203
        and     ah, .literalPosMask
204
end if
205
        shr     eax, 8-.lc
206
        imul    eax, .LZMA_LIT_SIZE*4
207
        add     eax, .Literal*4
208
        add     eax, [.p]
209
        cmp     ebx, .kNumLitStates
210
        jb      .literal
211
        xor     edx, edx
212
        sub     edx, [.rep0]
213
        mov     dl, [edi + edx]
214
        call    .LzmaLiteralDecodeMatch
215
        jmp     @f
216
.literal:
217
        call    .LzmaLiteralDecode
218
@@:
219
        mov     [.previousByte], al
220
        stosb
221
        mov     al, bl
222
        cmp     bl, 4
223
        jb      @f
224
        mov     al, 3
225
        cmp     bl, 10
226
        jb      @f
227
        mov     al, 6
228
@@:
229
        sub     bl, al
230
        jmp     .main_loop
231
.1:
232
        lea     eax, [.IsRep*4 + ebx*4]
233
        add     eax, [.p]
234
        call    .RangeDecoderBitDecode
235
        jnc     .10
236
        lea     eax, [.IsRepG0*4 + ebx*4]
237
        add     eax, [.p]
238
        call    .RangeDecoderBitDecode
239
        jc      .111
240
        mov     eax, ebx
241
        shl     eax, .kNumPosBitsMax+2
242
        lea     eax, [.IsRep0Long*4 + eax + edx*4]
243
        add     eax, [.p]
244
        call    .RangeDecoderBitDecode
245
        jc      .1101
246
        cmp     bl, 7
247
        setae   bl
248
        lea     ebx, [9 + ebx + ebx]
249
        xor     edx, edx
250
        sub     edx, [.rep0]
251
        mov     al, [edi + edx]
252
        stosb
253
        mov     [.previousByte], al
254
        jmp     .main_loop
255
.111:
256
        lea     eax, [.IsRepG1*4 + ebx*4]
257
        add     eax, [.p]
258
        call    .RangeDecoderBitDecode
259
        mov     eax, [.rep1]
260
        jnc     .l3
261
.l1:
262
        lea     eax, [.IsRepG2*4 + ebx*4]
263
        add     eax, [.p]
264
        call    .RangeDecoderBitDecode
265
        mov     eax, [.rep2]
266
        jnc     .l2
267
        xchg    [.rep3], eax
268
.l2:
269
        push    [.rep1]
270
        pop     [.rep2]
271
.l3:
272
        xchg    eax, [.rep0]
273
        mov     [.rep1], eax
274
.1101:
275
        mov     eax, .RepLencoder*4
276
        add     eax, [.p]
277
        call    .LzmaLenDecode
278
        cmp     bl, 7
279
        setc    bl
280
        adc     bl, bl
281
        xor     bl, 3
282
        add     bl, 8
283
        jmp     .repmovsb
284
.10:
285
        mov     eax, [.rep0]
286
        xchg    eax, [.rep1]
287
        xchg    eax, [.rep2]
288
        xchg    eax, [.rep3]
289
        cmp     bl, 7
290
        setc    bl
291
        adc     bl, bl
292
        xor     bl, 3
293
        add     bl, 7
294
        mov     eax, .Lencoder*4
295
        add     eax, [.p]
296
        call    .LzmaLenDecode
297
        mov     eax, .kNumLenToPosStates-1
298
        cmp     eax, ecx
299
        jb      @f
300
        mov     eax, ecx
301
@@:
302
        push    ecx
303
        mov     ecx, .kNumPosSlotBits
304
        shl     eax, cl
305
        shl     eax, 2
306
        add     eax, .PosSlot*4
307
        add     eax, [.p]
308
        call    .RangeDecoderBitTreeDecode
309
        mov     [.rep0], ecx
310
        cmp     ecx, .kStartPosModelIndex
311
        jb      .l6
312
        push    ecx
313
        mov     eax, ecx
314
        and     eax, 1
315
        shr     ecx, 1
316
        or      eax, 2
317
        dec     ecx
318
        shl     eax, cl
319
        mov     [.rep0], eax
320
        pop     edx
321
        cmp     edx, .kEndPosModelIndex
322
        jae     .l5
323
        sub     eax, edx
324
        shl     eax, 2
325
        add     eax, (.SpecPos - 1)*4
326
        add     eax, [.p]
327
        call    .RangeDecoderReverseBitTreeDecode
328
        add     [.rep0], ecx
329
        jmp     .l6
330
.l5:
331
        sub     ecx, .kNumAlignBits
332
        call    .RangeDecoderDecodeDirectBits
333
        mov     ecx, .kNumAlignBits
334
        shl     eax, cl
335
        add     [.rep0], eax
336
        mov     eax, .Align_*4
337
        add     eax, [.p]
338
        call    .RangeDecoderReverseBitTreeDecode
339
        add     [.rep0], ecx
340
.l6:
341
        pop     ecx
342
        inc     [.rep0]
343
        jz      .main_loop_done
344
.repmovsb:
345
        add     ecx, .kMatchMinLen
346
        push    esi
347
        mov     esi, edi
348
        sub     esi, [.rep0]
349
        rep movsb
350
        pop     esi
351
        mov     al, [edi-1]
352
        mov     [.previousByte], al
353
        jmp     .main_loop
354
.main_loop_done:
355
        ret
356
 
357
.RangeDecoderBitDecode:
358
; in: eax->prob
359
; out: CF=bit; destroys eax
360
        push    edx
361
        mov     edx, [.range]
362
        shr     edx, .kNumBitModelTotalBits
363
        imul    edx, [eax]
364
        cmp     [.code_], edx
365
        jae     .ae
366
        mov     [.range], edx
367
        mov     edx, .kBitModelTotal
368
        sub     edx, [eax]
369
        shr     edx, .kNumMoveBits
370
        add     [eax], edx
371
        clc
372
.n:
373
        lahf
374
        cmp     [.range], .kTopValue
375
        jae     @f
376
        shl     [.range], 8
377
        shl     [.code_], 8
378
        lodsb
379
        mov     byte [.code_], al
380
@@:
381
        sahf
382
        pop     edx
383
        ret
384
.ae:
385
        sub     [.range], edx
386
        sub     [.code_], edx
387
        mov     edx, [eax]
388
        shr     edx, .kNumMoveBits
389
        sub     [eax], edx
390
        stc
391
        jmp     .n
392
 
393
.RangeDecoderDecodeDirectBits:
394
; in: ecx=numTotalBits
395
; out: eax=result; destroys edx
396
        xor     eax, eax
397
.l:
398
        shr     [.range], 1
399
        shl     eax, 1
400
        mov     edx, [.code_]
401
        sub     edx, [.range]
402
        jb      @f
403
        mov     [.code_], edx
404
        or      eax, 1
405
@@:
406
        cmp     [.range], .kTopValue
407
        jae     @f
408
        shl     [.range], 8
409
        shl     [.code_], 8
410
        push    eax
411
        lodsb
412
        mov     byte [.code_], al
413
        pop     eax
414
@@:
415
        loop    .l
416
        ret
417
 
418
.LzmaLiteralDecode:
419
; in: eax->probs
420
; out: al=byte; destroys edx
421
        push    ecx
422
        mov     ecx, 1
423
@@:
424
        push    eax
425
        lea     eax, [eax+ecx*4]
426
        call    .RangeDecoderBitDecode
427
        pop     eax
428
        adc     cl, cl
429
        jnc     @b
430
.LzmaLiteralDecode.ret:
431
        mov     al, cl
432
        pop     ecx
433
        ret
434
.LzmaLiteralDecodeMatch:
435
; in: eax->probs, dl=matchByte
436
; out: al=byte; destroys edx
437
        push    ecx
438
        mov     ecx, 1
439
.LzmaLiteralDecodeMatch.1:
440
        add     dl, dl
441
        setc    ch
442
        push    eax
443
        lea     eax, [eax+ecx*4+0x100*4]
444
        call    .RangeDecoderBitDecode
445
        pop     eax
446
        adc     cl, cl
447
        jc      .LzmaLiteralDecode.ret
448
        xor     ch, cl
449
        test    ch, 1
450
        mov     ch, 0
451
        jnz     @b
452
        jmp     .LzmaLiteralDecodeMatch.1
453
 
454
.LzmaLenDecode:
455
; in: eax->prob, edx=posState
456
; out: ecx=len
457
        push    eax
458
        add     eax, .LenChoice*4
459
        call    .RangeDecoderBitDecode
460
        pop     eax
461
        jnc     .0
462
        push    eax
463
        add     eax, .LenChoice2*4
464
        call    .RangeDecoderBitDecode
465
        pop     eax
466
        jc      @f
467
        mov     ecx, .kLenNumMidBits
468
        shl     edx, cl
469
        lea     eax, [eax + .LenMid*4 + edx*4]
470
        call    .RangeDecoderBitTreeDecode
471
        add     ecx, .kLenNumLowSymbols
472
        ret
473
@@:
474
        add     eax, .LenHigh*4
475
        mov     ecx, .kLenNumHighBits
476
        call    .RangeDecoderBitTreeDecode
477
        add     ecx, .kLenNumLowSymbols + .kLenNumMidSymbols
478
        ret
479
.0:
480
        mov     ecx, .kLenNumLowBits
481
        shl     edx, cl
482
        lea     eax, [eax + .LenLow*4 + edx*4]
483
.RangeDecoderBitTreeDecode:
484
; in: eax->probs,ecx=numLevels
485
; out: ecx=length; destroys edx
486
        push    ebx
487
        mov     edx, 1
488
        mov     ebx, edx
489
@@:
490
        push    eax
491
        lea     eax, [eax+edx*4]
492
        call    .RangeDecoderBitDecode
493
        pop     eax
494
        adc     dl, dl
495
        add     bl, bl
496
        loop    @b
497
        sub     dl, bl
498
        pop     ebx
499
        mov     ecx, edx
500
        ret
501
.RangeDecoderReverseBitTreeDecode:
502
; in: eax->probs,ecx=numLevels
503
; out: ecx=length; destroys edx
504
        push    ebx ecx
505
        mov     edx, 1
506
        xor     ebx, ebx
507
@@:
508
        push    eax
509
        lea     eax, [eax+edx*4]
510
        call    .RangeDecoderBitDecode
511
        lahf
512
        adc     edx, edx
513
        sahf
514
        rcr     ebx, 1
515
        pop     eax
516
        loop    @b
517
        pop     ecx
518
        rol     ebx, cl
519
        mov     ecx, ebx
520
        pop     ebx
521
        ret
522
 
523
uglobal
524
align 4
525
;unpack.p       rd      unpack.LZMA_BASE_SIZE + (unpack.LZMA_LIT_SIZE shl (unpack.lc+unpack.lp))
526
unpack.p        dd      ?
527
unpack.code_    dd      ?
528
unpack.range    dd      ?
529
unpack.rep0     dd      ?
530
unpack.rep1     dd      ?
531
unpack.rep2     dd      ?
532
unpack.rep3     dd      ?
533
unpack.previousByte db  ?
534
endg