Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
589 diamond 1
; LZMA decoder for *.7z archives.
2
; Based on C decoder in LZMA SDK (c) Igor Pavlov.
3
; Portions by Diamond, 2006, 2007.
4
lzma_decoder:
5
virtual at 0
6
.outStream      rb      streamInfo.size
7
.inStream       dd      ?
8
 
9
; RangeDecoder data
10
.inLen          dd      ?
11
.inPtr          dd      ?
12
.code           dd      ?
13
.range          dd      ?
14
 
15
; parameters
16
.pb             db      ?       ; pos state bits (0 - 4)
17
.lp             db      ?       ; literal pos state bits (0 - 4)
18
.lc             db      ?       ; literal context bits (0 - 8)
19
.previousByte   db      ?
20
.posStateMask   dd      ?       ; (1 shl .pb)-1
21
.literalPosMask dd      ?       ; (1 shl .lp)-1
22
 
23
; constants
24
.kNumPosBitsMax	=	4
25
.kNumPosStatesMax =	(1 shl .kNumPosBitsMax)
26
 
27
.kLenNumLowBits         =       3
28
.kLenNumLowSymbols      =       (1 shl .kLenNumLowBits)
29
.kLenNumMidBits         =       3
30
.kLenNumMidSymbols      =       (1 shl .kLenNumMidBits)
31
.kLenNumHighBits        =       8
32
.kLenNumHighSymbols     =       (1 shl .kLenNumHighBits)
33
 
34
.LenChoice	=	0
35
.LenChoice2	=	1
36
.LenLow		=	2
37
.LenMid		=	(.LenLow + (.kNumPosStatesMax shl .kLenNumLowBits))
38
.LenHigh	=	(.LenMid + (.kNumPosStatesMax shl .kLenNumMidBits))
39
.kNumLenProbs	=	(.LenHigh + .kLenNumHighSymbols)
40
 
41
.kNumStates	=	12
42
.kNumLitStates	=	7
43
.kStartPosModelIndex =	4
44
.kEndPosModelIndex =	14
45
.kNumFullDistances =	(1 shl (.kEndPosModelIndex/2))
46
.kNumPosSlotBits =	6
47
.kNumLenToPosStates =	4
48
.kNumAlignBits	=	4
49
.kAlignTableSize =	(1 shl .kNumAlignBits)
50
.kMatchMinLen	=	2
51
 
52
.IsMatch	=	0
53
.IsRep		=	(.IsMatch + (.kNumStates shl .kNumPosBitsMax))
54
.IsRepG0	=	(.IsRep + .kNumStates)
55
.IsRepG1	=	(.IsRepG0 + .kNumStates)
56
.IsRepG2	=	(.IsRepG1 + .kNumStates)
57
.IsRep0Long	=	(.IsRepG2 + .kNumStates)
58
.PosSlot	=	(.IsRep0Long + (.kNumStates shl .kNumPosBitsMax))
59
.SpecPos	=	(.PosSlot + (.kNumLenToPosStates shl .kNumPosSlotBits))
60
.Align_		=	(.SpecPos + .kNumFullDistances - .kEndPosModelIndex)
61
.Lencoder	=	(.Align_ + .kAlignTableSize)
62
.RepLencoder	=	(.Lencoder + .kNumLenProbs)
63
.Literal	=	(.RepLencoder + .kNumLenProbs)
64
 
65
LZMA_BASE_SIZE	=	1846	; must be ==Literal
66
LZMA_LIT_SIZE	=	768
67
 
68
.kNumTopBits	=	24
69
.kTopValue	=	(1 shl .kNumTopBits)
70
 
71
.kNumBitModelTotalBits =	11
72
.kBitModelTotal	=	(1 shl .kNumBitModelTotalBits)
73
.kNumMoveBits	=	5
74
 
75
; variables
76
.continue       dd      ?
77
.ecx            dd      ?
78
.outEnd         dd      ?
79
.dictSize       dd      ?
80
.state          dd      ?
81
.rep0           dd      ?
82
.rep1           dd      ?
83
.rep2           dd      ?
84
.rep3           dd      ?
85
.p              rd      LZMA_BASE_SIZE
86
.basesize = $
87
;               rd      LZMA_LIT_SIZE shl (.lc+.lp)
88
end virtual
89
 
90
.fillBuf:
91
        mov     ebp, eax
92
        mov     ebx, [ebp+.state]
93
	jecxz	.nodata
94
        add     ecx, edi
95
        mov     [ebp+.outEnd], ecx
96
        mov     esi, [ebp+.inPtr]
97
        jmp     [ebp+.continue]
98
.nodata:
99
	popad
100
	ret
101
.start:
102
        mov     eax, [ebp+.inStream]
103
        call    fillBuf
104
        mov     esi, [eax+streamInfo.bufPtr]
105
        mov     eax, [eax+streamInfo.bufDataLen]
106
        sub     eax, 5
107
        jb      return.err
108
        mov     [ebp+.inLen], eax
109
        inc     esi
110
	lodsd
111
        bswap   eax
112
	mov	[ebp+.code], eax
113
	or	[ebp+.range], -1
114
.main_loop:
115
	cmp	edi, [ebp+.outEnd]
116
	jae	.main_loop_done
117
	mov	edx, edi
118
	and	edx, [ebp+.posStateMask]
119
	mov	eax, ebx
120
	shl	eax, .kNumPosBitsMax
121
        add     eax, edx
122
	lea	eax, [ebp + .p + .IsMatch*4 + eax*4]
123
	call	.RangeDecoderBitDecode
124
	jc	.1
125
	movzx	eax, [ebp+.previousByte]
126
	mov	ah, dl
127
	and	ah, byte [ebp+.literalPosMask]
128
        mov     cl, 8
129
        sub     cl, [ebp+.lc]
130
	shr	eax, cl
131
	imul	eax, LZMA_LIT_SIZE*4
132
	lea	eax, [ebp + eax + .p+.Literal*4]
133
	cmp	ebx, .kNumLitStates
134
	jb	.literal
893 diamond 135
	mov	edx, edi
589 diamond 136
	sub	edx, [ebp+.rep0]
1122 diamond 137
	jc	.before_buf
893 diamond 138
	cmp	edx, [ebp+streamInfo.bufPtr]
139
	jb	.before_buf
140
@@:
141
	mov	dl, [edx]
589 diamond 142
	call	.LzmaLiteralDecodeMatch
893 diamond 143
	jmp	.got_byte
144
.before_buf:
145
	add	edx, [ebp+streamInfo.bufSize]
146
	cmp	edx, [ebp+streamInfo.bufPtr]
147
	jb	return.err
148
	jmp	@b
589 diamond 149
.literal:
150
	call	.LzmaLiteralDecode
893 diamond 151
.got_byte:
589 diamond 152
	mov	[ebp+.previousByte], al
153
	stosb
154
	mov	al, bl
155
	cmp	bl, 4
156
	jb	@f
157
	mov	al, 3
158
	cmp	bl, 10
159
	jb	@f
160
	mov	al, 6
161
@@:	sub	bl, al
162
	jmp	.main_loop
163
.1:
164
	lea	eax, [ebp + .p + .IsRep*4 + ebx*4]
165
	call	.RangeDecoderBitDecode
166
	jnc	.10
167
	lea	eax, [ebp + .p + .IsRepG0*4 + ebx*4]
168
	call	.RangeDecoderBitDecode
169
	jc	.111
170
	mov	eax, ebx
171
	shl	eax, .kNumPosBitsMax
172
        add     eax, edx
173
	lea	eax, [ebp + .p + .IsRep0Long*4 + eax*4]
174
	call	.RangeDecoderBitDecode
175
	jc	.1101
176
	cmp	bl, 7
177
	setae	bl
178
	lea	ebx, [9 + ebx + ebx]
893 diamond 179
	mov	edx, edi
589 diamond 180
	sub	edx, [ebp+.rep0]
1122 diamond 181
	jc	@f
893 diamond 182
	cmp	edx, [ebp+streamInfo.bufPtr]
1122 diamond 183
	jae	.copy_byte
184
@@:
893 diamond 185
	add	edx, [ebp+streamInfo.bufSize]
186
	cmp	edx, [ebp+streamInfo.bufPtr]
187
	jb	return.err
1122 diamond 188
.copy_byte:
893 diamond 189
	mov	al, [edx]
589 diamond 190
	stosb
191
	mov	[ebp+.previousByte], al
192
	jmp	.main_loop
193
.111:
194
	lea	eax, [ebp + .p + .IsRepG1*4 + ebx*4]
195
	call	.RangeDecoderBitDecode
196
	mov	eax, [ebp+.rep1]
197
	jnc	.l3
198
.l1:
199
	lea	eax, [ebp + .p + .IsRepG2*4 + ebx*4]
200
	call	.RangeDecoderBitDecode
201
	mov	eax, [ebp+.rep2]
202
	jnc	.l2
203
	xchg	[ebp+.rep3], eax
204
.l2:
205
	push	[ebp+.rep1]
206
	pop	[ebp+.rep2]
207
.l3:
208
	xchg	eax, [ebp+.rep0]
209
	mov	[ebp+.rep1], eax
210
.1101:
211
	lea	eax, [ebp + .p + .RepLencoder*4]
212
	call	.LzmaLenDecode
213
	cmp	bl, 7
214
	setc	bl
215
	adc	bl, bl
216
	xor	bl, 3
217
	add	bl, 8
218
	jmp	.repmovsb
219
.10:
220
	mov	eax, [ebp+.rep0]
221
	xchg	eax, [ebp+.rep1]
222
	xchg	eax, [ebp+.rep2]
223
	xchg	eax, [ebp+.rep3]
224
	cmp	bl, 7
225
	setc	bl
226
	adc	bl, bl
227
	xor	bl, 3
228
	add	bl, 7
229
	lea	eax, [ebp + .p + .Lencoder*4]
230
	call	.LzmaLenDecode
231
	mov	eax, .kNumLenToPosStates-1
232
	cmp	eax, ecx
233
	jb	@f
234
	mov	eax, ecx
235
@@:
236
	push	ecx
237
	mov	ecx, .kNumPosSlotBits
238
	shl	eax, cl
239
        lea     eax, [ebp + .p+.PosSlot*4 + eax*4]
240
	call	.RangeDecoderBitTreeDecode
241
	mov	[ebp+.rep0], ecx
242
	cmp	ecx, .kStartPosModelIndex
243
	jb	.l6
244
	push	ecx
245
	mov	eax, ecx
246
	and	eax, 1
247
	shr	ecx, 1
248
	or	eax, 2
249
	dec	ecx
250
	shl	eax, cl
251
	mov	[ebp+.rep0], eax
252
	pop	edx
253
	cmp	edx, .kEndPosModelIndex
254
	jae	.l5
255
	sub	eax, edx
256
        lea     eax, [ebp + .p + (.SpecPos - 1)*4 + eax*4]
257
	call	.RangeDecoderReverseBitTreeDecode
258
	add	[ebp+.rep0], ecx
259
	jmp	.l6
260
.l5:
261
	sub	ecx, .kNumAlignBits
262
	call	.RangeDecoderDecodeDirectBits
263
	mov	ecx, .kNumAlignBits
264
	shl	eax, cl
265
	add	[ebp+.rep0], eax
266
	lea	eax, [ebp+.p+.Align_*4]
267
	call	.RangeDecoderReverseBitTreeDecode
268
	add	[ebp+.rep0], ecx
269
.l6:
270
	pop	ecx
271
	inc	[ebp+.rep0]
272
	jz	.main_loop_done
273
.repmovsb:
274
	add	ecx, .kMatchMinLen
275
.repmovsbz:
276
	push	esi
277
.repmovsbr:
278
        mov     eax, [ebp+.rep0]
279
        cmp     eax, [ebp+.dictSize]
920 diamond 280
        ja      return.err
589 diamond 281
	mov	esi, edi
282
	sub	esi, eax
1122 diamond 283
	jc	.repmovsb0a
589 diamond 284
        mov     eax, [ebp+streamInfo.bufPtr]
285
        sub     eax, esi
286
        ja      .repmovsb0
287
	mov	eax, [ebp+.outEnd]
288
        sub     eax, edi
920 diamond 289
        jz      .done1
589 diamond 290
        push    ecx
291
        cmp     ecx, eax
292
        jb      @f
293
        mov     ecx, eax
294
@@:
295
        sub     [esp], ecx
296
	rep	movsb
297
        pop     ecx
298
        jz      .repmovsb1
920 diamond 299
.done1:
589 diamond 300
        pop     [ebp+.inPtr]
301
	mov	[ebp+.state], ebx
302
        mov     [ebp+.ecx], ecx
303
        mov     [ebp+.continue], .restart_repmovsb
304
        popad
305
        ret
1122 diamond 306
.repmovsb0a:
307
        mov     eax, [ebp+streamInfo.bufPtr]
308
        sub     eax, esi
589 diamond 309
.repmovsb0:
310
	mov	edx, [ebp+.dictSize]
920 diamond 311
;	cmp	edx, [ebp+streamInfo.bufSize]
312
;	jnz	return.err
589 diamond 313
        add     esi, edx
314
        push    ecx
315
        cmp     ecx, eax
316
        jb      @f
317
        mov     ecx, eax
318
@@:
319
	mov	eax, [ebp+.outEnd]
320
	sub	eax, edi
920 diamond 321
	jz      .done2
589 diamond 322
	cmp	ecx, eax
323
	jb	@f
324
	mov	ecx, eax
325
@@:
326
        sub     [esp], ecx
327
        rep     movsb
328
        pop     ecx
329
        jnz     .repmovsbr
330
.repmovsb1:
331
        pop     esi
332
        mov     al, [edi-1]
333
        mov     [ebp+.previousByte], al
334
        jmp     .main_loop
920 diamond 335
.done2:
336
	pop	ecx
337
	jmp	.done1
589 diamond 338
.main_loop_done:
339
	mov	[ebp+.state], ebx
340
        mov     [ebp+.continue], .main_loop
341
        mov     [ebp+.inPtr], esi
342
        popad
343
	ret
344
.restart_repmovsb:
345
        mov     ecx, [ebp+.ecx]
346
        jmp     .repmovsbz
347
 
348
.RangeDecoderBitDecode:
349
; in: eax->prob
350
; out: CF=bit; destroys eax
351
	push	edx
352
	mov	edx, [ebp+.range]
353
	shr	edx, .kNumBitModelTotalBits
354
	imul	edx, [eax]
355
	cmp	[ebp+.code], edx
356
	jae	.ae
357
	mov	[ebp+.range], edx
358
	mov	edx, .kBitModelTotal
359
	sub	edx, [eax]
360
	shr	edx, .kNumMoveBits
361
	add	[eax], edx
362
	clc
363
.n:
364
	lahf
365
	cmp	[ebp+.range], .kTopValue
366
	jae	@f
367
	shl	[ebp+.range], 8
368
	shl	[ebp+.code], 8
369
        sub     [ebp+.inLen], 1
370
        js      .refill1
371
.refilled1:
372
	lodsb
373
	mov	byte [ebp+.code], al
374
@@:
375
	sahf
376
	pop	edx
377
	ret
378
.ae:
379
	sub	[ebp+.range], edx
380
	sub	[ebp+.code], edx
381
	mov	edx, [eax]
382
	shr	edx, .kNumMoveBits
383
	sub	[eax], edx
384
	stc
385
	jmp	.n
386
 
387
.refill1:
388
        push    eax
389
        call    .refill
390
        pop     eax
391
        jmp     .refilled1
392
 
393
.refill:
394
        mov     eax, [ebp+.inStream]
395
        cmp     dword [eax+streamInfo.fullSize+4], 0
396
        jnz     @f
397
        cmp     dword [eax+streamInfo.fullSize], 0
398
        jz      return.err
399
@@:
400
        call    fillBuf
401
        mov     esi, [eax+streamInfo.bufPtr]
402
        mov     eax, [eax+streamInfo.bufDataLen]
403
        dec     eax
404
        js      return.err
405
        mov     [ebp+.inLen], eax
406
        ret
407
 
408
.refill2:
409
        call    .refill
410
        jmp     .refilled2
411
 
412
.RangeDecoderDecodeDirectBits:
413
; in: ecx=numTotalBits
414
; out: eax=result; destroys edx
415
	xor	eax, eax
416
.l:
417
	shr	[ebp+.range], 1
418
	shl	eax, 1
419
	mov	edx, [ebp+.code]
420
	sub	edx, [ebp+.range]
421
	jb	@f
422
	mov	[ebp+.code], edx
423
	or	eax, 1
424
@@:
425
	cmp	[ebp+.range], .kTopValue
426
	jae	@f
427
	shl	[ebp+.range], 8
428
	shl	[ebp+.code], 8
429
	push	eax
430
        dec     [ebp+.inLen]
431
        js      .refill2
432
.refilled2:
433
	lodsb
434
	mov	byte [ebp+.code], al
435
	pop	eax
436
@@:
437
	loop	.l
438
	ret
439
 
440
.LzmaLiteralDecode:
441
; in: eax->probs
442
; out: al=byte; destroys edx
443
	push	ecx
444
	mov	ecx, 1
445
@@:
446
	push	eax
447
	lea	eax, [eax+ecx*4]
448
	call	.RangeDecoderBitDecode
449
	pop	eax
450
	adc	cl, cl
451
	jnc	@b
452
.LzmaLiteralDecode.ret:
453
	mov	al, cl
454
	pop	ecx
455
	ret
456
.LzmaLiteralDecodeMatch:
457
; in: eax->probs, dl=matchByte
458
; out: al=byte; destroys edx
459
	push	ecx
460
	mov	ecx, 1
461
.LzmaLiteralDecodeMatch.1:
462
	add	dl, dl
463
	setc	ch
464
	push	eax
465
	lea	eax, [eax+ecx*4+0x100*4]
466
	call	.RangeDecoderBitDecode
467
	pop	eax
468
	adc	cl, cl
469
	jc	.LzmaLiteralDecode.ret
470
	xor	ch, cl
471
	test	ch, 1
472
	mov	ch, 0
473
	jnz	@b
474
	jmp	.LzmaLiteralDecodeMatch.1
475
 
476
.LzmaLenDecode:
477
; in: eax->prob, edx=posState
478
; out: ecx=len
479
	push	eax
480
	add	eax, .LenChoice*4
481
	call	.RangeDecoderBitDecode
482
	pop	eax
483
	jnc	.0
484
	push	eax
485
	add	eax, .LenChoice2*4
486
	call	.RangeDecoderBitDecode
487
	pop	eax
488
	jc	@f
489
	mov	ecx, .kLenNumMidBits
490
	shl	edx, cl
491
	lea	eax, [eax + .LenMid*4 + edx*4]
492
	call	.RangeDecoderBitTreeDecode
493
	add	ecx, .kLenNumLowSymbols
494
	ret
495
@@:
496
	add	eax, .LenHigh*4
497
	mov	ecx, .kLenNumHighBits
498
	call	.RangeDecoderBitTreeDecode
499
	add	ecx, .kLenNumLowSymbols + .kLenNumMidSymbols
500
	ret
501
.0:
502
	mov	ecx, .kLenNumLowBits
503
	shl	edx, cl
504
	lea	eax, [eax + .LenLow*4 + edx*4]
505
.RangeDecoderBitTreeDecode:
506
; in: eax->probs,ecx=numLevels
507
; out: ecx=length; destroys edx
508
	push	ebx
509
	mov	edx, 1
510
	mov	ebx, edx
511
@@:
512
	push	eax
513
	lea	eax, [eax+edx*4]
514
	call	.RangeDecoderBitDecode
515
	pop	eax
516
	adc	dl, dl
517
	add	bl, bl
518
	loop	@b
519
	sub	dl, bl
520
	pop	ebx
521
	mov	ecx, edx
522
	ret
523
.RangeDecoderReverseBitTreeDecode:
524
; in: eax->probs,ecx=numLevels
525
; out: ecx=length; destroys edx
526
	push	ebx ecx
527
	mov	edx, 1
528
	xor	ebx, ebx
529
@@:
530
	push	eax
531
	lea	eax, [eax+edx*4]
532
	call	.RangeDecoderBitDecode
533
	lahf
534
	adc	edx, edx
535
	sahf
536
	rcr	ebx, 1
537
	pop	eax
538
	loop	@b
539
	pop	ecx
540
	rol	ebx, cl
541
	mov	ecx, ebx
542
	pop	ebx
543
	ret
544
 
545
; LZMA parameters:
546
;       db      lc + 9 * (lp + 5 * pb)
547
;       dd      dictionarySize
548
 
549
lzma_get_buf_size:
550
        cmp     dword [esi-4], 5
551
        jb      return.err
552
        push    ecx
553
        lodsb
554
        aam     9
555
        mov     cl, al
556
        mov     al, ah
557
        aam     5
558
        add     cl, al
559
        mov     eax, LZMA_LIT_SIZE
560
        shl     eax, cl
561
        lea     eax, [lzma_decoder.basesize+eax*4]
562
        pop     ecx
563
        mov     edx, [esi]
564
        ret
565
 
566
lzma_init_decoder:
567
        lodsb
568
        aam     9
569
        mov     [ebp+lzma_decoder.lc], al
570
        mov     al, ah
571
        aam     5
572
        mov     [ebp+lzma_decoder.lp], al
573
        mov     [ebp+lzma_decoder.pb], ah
574
        cmp     ah, lzma_decoder.kNumPosBitsMax
575
        ja      return.err
576
        mov     cl, ah
577
        lodsd
578
        mov     [ebp+lzma_decoder.dictSize], eax
579
        push    1
580
        pop     eax
581
        shl     eax, cl
582
        dec     eax
583
        mov     [ebp+lzma_decoder.posStateMask], eax
584
        mov     cl, [ebp+lzma_decoder.lp]
585
        push    1
586
        pop     eax
587
        shl     eax, cl
588
        dec     eax
589
        mov     [ebp+lzma_decoder.literalPosMask], eax
590
        mov     [ebp+streamInfo.fillBuf], lzma_decoder.fillBuf
591
        mov     [ebp+lzma_decoder.continue], lzma_decoder.start
592
        xor     eax, eax
593
        mov     [ebp+lzma_decoder.previousByte], al
594
        mov     [ebp+lzma_decoder.state], eax
595
        inc     eax
596
        lea     edi, [ebp+lzma_decoder.rep0]
597
        stosd
598
        stosd
599
        stosd
600
        mov     eax, LZMA_LIT_SIZE
601
        mov     cl, [ebp+lzma_decoder.lc]
602
        add     cl, [ebp+lzma_decoder.lp]
603
        shl     eax, cl
604
        lea     ecx, [eax+lzma_decoder.Literal]
605
	mov	eax, lzma_decoder.kBitModelTotal/2
606
	lea	edi, [ebp+lzma_decoder.p]
607
	rep	stosd
608
        ret