Subversion Repositories Kolibri OS

Rev

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

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