Subversion Repositories Kolibri OS

Rev

Rev 893 | Go to most recent revision | Details | 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
135
	xor	edx, edx
136
	sub	edx, [ebp+.rep0]
137
	mov	dl, [edi + edx]
138
	call	.LzmaLiteralDecodeMatch
139
	jmp	@f
140
.literal:
141
	call	.LzmaLiteralDecode
142
@@:
143
	mov	[ebp+.previousByte], al
144
	stosb
145
	mov	al, bl
146
	cmp	bl, 4
147
	jb	@f
148
	mov	al, 3
149
	cmp	bl, 10
150
	jb	@f
151
	mov	al, 6
152
@@:	sub	bl, al
153
	jmp	.main_loop
154
.1:
155
	lea	eax, [ebp + .p + .IsRep*4 + ebx*4]
156
	call	.RangeDecoderBitDecode
157
	jnc	.10
158
	lea	eax, [ebp + .p + .IsRepG0*4 + ebx*4]
159
	call	.RangeDecoderBitDecode
160
	jc	.111
161
	mov	eax, ebx
162
	shl	eax, .kNumPosBitsMax
163
        add     eax, edx
164
	lea	eax, [ebp + .p + .IsRep0Long*4 + eax*4]
165
	call	.RangeDecoderBitDecode
166
	jc	.1101
167
	cmp	bl, 7
168
	setae	bl
169
	lea	ebx, [9 + ebx + ebx]
170
	xor	edx, edx
171
	sub	edx, [ebp+.rep0]
172
	mov	al, [edi + edx]
173
	stosb
174
	mov	[ebp+.previousByte], al
175
	jmp	.main_loop
176
.111:
177
	lea	eax, [ebp + .p + .IsRepG1*4 + ebx*4]
178
	call	.RangeDecoderBitDecode
179
	mov	eax, [ebp+.rep1]
180
	jnc	.l3
181
.l1:
182
	lea	eax, [ebp + .p + .IsRepG2*4 + ebx*4]
183
	call	.RangeDecoderBitDecode
184
	mov	eax, [ebp+.rep2]
185
	jnc	.l2
186
	xchg	[ebp+.rep3], eax
187
.l2:
188
	push	[ebp+.rep1]
189
	pop	[ebp+.rep2]
190
.l3:
191
	xchg	eax, [ebp+.rep0]
192
	mov	[ebp+.rep1], eax
193
.1101:
194
	lea	eax, [ebp + .p + .RepLencoder*4]
195
	call	.LzmaLenDecode
196
	cmp	bl, 7
197
	setc	bl
198
	adc	bl, bl
199
	xor	bl, 3
200
	add	bl, 8
201
	jmp	.repmovsb
202
.10:
203
	mov	eax, [ebp+.rep0]
204
	xchg	eax, [ebp+.rep1]
205
	xchg	eax, [ebp+.rep2]
206
	xchg	eax, [ebp+.rep3]
207
	cmp	bl, 7
208
	setc	bl
209
	adc	bl, bl
210
	xor	bl, 3
211
	add	bl, 7
212
	lea	eax, [ebp + .p + .Lencoder*4]
213
	call	.LzmaLenDecode
214
	mov	eax, .kNumLenToPosStates-1
215
	cmp	eax, ecx
216
	jb	@f
217
	mov	eax, ecx
218
@@:
219
	push	ecx
220
	mov	ecx, .kNumPosSlotBits
221
	shl	eax, cl
222
        lea     eax, [ebp + .p+.PosSlot*4 + eax*4]
223
	call	.RangeDecoderBitTreeDecode
224
	mov	[ebp+.rep0], ecx
225
	cmp	ecx, .kStartPosModelIndex
226
	jb	.l6
227
	push	ecx
228
	mov	eax, ecx
229
	and	eax, 1
230
	shr	ecx, 1
231
	or	eax, 2
232
	dec	ecx
233
	shl	eax, cl
234
	mov	[ebp+.rep0], eax
235
	pop	edx
236
	cmp	edx, .kEndPosModelIndex
237
	jae	.l5
238
	sub	eax, edx
239
        lea     eax, [ebp + .p + (.SpecPos - 1)*4 + eax*4]
240
	call	.RangeDecoderReverseBitTreeDecode
241
	add	[ebp+.rep0], ecx
242
	jmp	.l6
243
.l5:
244
	sub	ecx, .kNumAlignBits
245
	call	.RangeDecoderDecodeDirectBits
246
	mov	ecx, .kNumAlignBits
247
	shl	eax, cl
248
	add	[ebp+.rep0], eax
249
	lea	eax, [ebp+.p+.Align_*4]
250
	call	.RangeDecoderReverseBitTreeDecode
251
	add	[ebp+.rep0], ecx
252
.l6:
253
	pop	ecx
254
	inc	[ebp+.rep0]
255
	jz	.main_loop_done
256
.repmovsb:
257
	add	ecx, .kMatchMinLen
258
.repmovsbz:
259
	push	esi
260
.repmovsbr:
261
        mov     eax, [ebp+.rep0]
262
        cmp     eax, [ebp+.dictSize]
263
        jae     return.err
264
	mov	esi, edi
265
	sub	esi, eax
266
        mov     eax, [ebp+streamInfo.bufPtr]
267
        sub     eax, esi
268
        ja      .repmovsb0
269
	mov	eax, [ebp+.outEnd]
270
        sub     eax, edi
271
        push    ecx
272
        cmp     ecx, eax
273
        jb      @f
274
        mov     ecx, eax
275
@@:
276
        sub     [esp], ecx
277
	rep	movsb
278
        pop     ecx
279
        jz      .repmovsb1
280
        pop     [ebp+.inPtr]
281
	mov	[ebp+.state], ebx
282
        mov     [ebp+.ecx], ecx
283
        mov     [ebp+.continue], .restart_repmovsb
284
        popad
285
        ret
286
.repmovsb0:
287
	mov	edx, [ebp+.dictSize]
288
	cmp	edx, [ebp+streamInfo.bufSize]
289
	jnz	return.err
290
        add     esi, edx
291
        push    ecx
292
        cmp     ecx, eax
293
        jb      @f
294
        mov     ecx, eax
295
@@:
296
	mov	eax, [ebp+.outEnd]
297
	sub	eax, edi
298
	cmp	ecx, eax
299
	jb	@f
300
	mov	ecx, eax
301
@@:
302
        sub     [esp], ecx
303
        rep     movsb
304
        pop     ecx
305
        jnz     .repmovsbr
306
.repmovsb1:
307
        pop     esi
308
        mov     al, [edi-1]
309
        mov     [ebp+.previousByte], al
310
        jmp     .main_loop
311
.main_loop_done:
312
	mov	[ebp+.state], ebx
313
        mov     [ebp+.continue], .main_loop
314
        mov     [ebp+.inPtr], esi
315
        popad
316
	ret
317
.restart_repmovsb:
318
        mov     ecx, [ebp+.ecx]
319
        jmp     .repmovsbz
320
 
321
.RangeDecoderBitDecode:
322
; in: eax->prob
323
; out: CF=bit; destroys eax
324
	push	edx
325
	mov	edx, [ebp+.range]
326
	shr	edx, .kNumBitModelTotalBits
327
	imul	edx, [eax]
328
	cmp	[ebp+.code], edx
329
	jae	.ae
330
	mov	[ebp+.range], edx
331
	mov	edx, .kBitModelTotal
332
	sub	edx, [eax]
333
	shr	edx, .kNumMoveBits
334
	add	[eax], edx
335
	clc
336
.n:
337
	lahf
338
	cmp	[ebp+.range], .kTopValue
339
	jae	@f
340
	shl	[ebp+.range], 8
341
	shl	[ebp+.code], 8
342
        sub     [ebp+.inLen], 1
343
        js      .refill1
344
.refilled1:
345
	lodsb
346
	mov	byte [ebp+.code], al
347
@@:
348
	sahf
349
	pop	edx
350
	ret
351
.ae:
352
	sub	[ebp+.range], edx
353
	sub	[ebp+.code], edx
354
	mov	edx, [eax]
355
	shr	edx, .kNumMoveBits
356
	sub	[eax], edx
357
	stc
358
	jmp	.n
359
 
360
.refill1:
361
        push    eax
362
        call    .refill
363
        pop     eax
364
        jmp     .refilled1
365
 
366
.refill:
367
        mov     eax, [ebp+.inStream]
368
        cmp     dword [eax+streamInfo.fullSize+4], 0
369
        jnz     @f
370
        cmp     dword [eax+streamInfo.fullSize], 0
371
        jz      return.err
372
@@:
373
        call    fillBuf
374
        mov     esi, [eax+streamInfo.bufPtr]
375
        mov     eax, [eax+streamInfo.bufDataLen]
376
        dec     eax
377
        js      return.err
378
        mov     [ebp+.inLen], eax
379
        ret
380
 
381
.refill2:
382
        call    .refill
383
        jmp     .refilled2
384
 
385
.RangeDecoderDecodeDirectBits:
386
; in: ecx=numTotalBits
387
; out: eax=result; destroys edx
388
	xor	eax, eax
389
.l:
390
	shr	[ebp+.range], 1
391
	shl	eax, 1
392
	mov	edx, [ebp+.code]
393
	sub	edx, [ebp+.range]
394
	jb	@f
395
	mov	[ebp+.code], edx
396
	or	eax, 1
397
@@:
398
	cmp	[ebp+.range], .kTopValue
399
	jae	@f
400
	shl	[ebp+.range], 8
401
	shl	[ebp+.code], 8
402
	push	eax
403
        dec     [ebp+.inLen]
404
        js      .refill2
405
.refilled2:
406
	lodsb
407
	mov	byte [ebp+.code], al
408
	pop	eax
409
@@:
410
	loop	.l
411
	ret
412
 
413
.LzmaLiteralDecode:
414
; in: eax->probs
415
; out: al=byte; destroys edx
416
	push	ecx
417
	mov	ecx, 1
418
@@:
419
	push	eax
420
	lea	eax, [eax+ecx*4]
421
	call	.RangeDecoderBitDecode
422
	pop	eax
423
	adc	cl, cl
424
	jnc	@b
425
.LzmaLiteralDecode.ret:
426
	mov	al, cl
427
	pop	ecx
428
	ret
429
.LzmaLiteralDecodeMatch:
430
; in: eax->probs, dl=matchByte
431
; out: al=byte; destroys edx
432
	push	ecx
433
	mov	ecx, 1
434
.LzmaLiteralDecodeMatch.1:
435
	add	dl, dl
436
	setc	ch
437
	push	eax
438
	lea	eax, [eax+ecx*4+0x100*4]
439
	call	.RangeDecoderBitDecode
440
	pop	eax
441
	adc	cl, cl
442
	jc	.LzmaLiteralDecode.ret
443
	xor	ch, cl
444
	test	ch, 1
445
	mov	ch, 0
446
	jnz	@b
447
	jmp	.LzmaLiteralDecodeMatch.1
448
 
449
.LzmaLenDecode:
450
; in: eax->prob, edx=posState
451
; out: ecx=len
452
	push	eax
453
	add	eax, .LenChoice*4
454
	call	.RangeDecoderBitDecode
455
	pop	eax
456
	jnc	.0
457
	push	eax
458
	add	eax, .LenChoice2*4
459
	call	.RangeDecoderBitDecode
460
	pop	eax
461
	jc	@f
462
	mov	ecx, .kLenNumMidBits
463
	shl	edx, cl
464
	lea	eax, [eax + .LenMid*4 + edx*4]
465
	call	.RangeDecoderBitTreeDecode
466
	add	ecx, .kLenNumLowSymbols
467
	ret
468
@@:
469
	add	eax, .LenHigh*4
470
	mov	ecx, .kLenNumHighBits
471
	call	.RangeDecoderBitTreeDecode
472
	add	ecx, .kLenNumLowSymbols + .kLenNumMidSymbols
473
	ret
474
.0:
475
	mov	ecx, .kLenNumLowBits
476
	shl	edx, cl
477
	lea	eax, [eax + .LenLow*4 + edx*4]
478
.RangeDecoderBitTreeDecode:
479
; in: eax->probs,ecx=numLevels
480
; out: ecx=length; destroys edx
481
	push	ebx
482
	mov	edx, 1
483
	mov	ebx, edx
484
@@:
485
	push	eax
486
	lea	eax, [eax+edx*4]
487
	call	.RangeDecoderBitDecode
488
	pop	eax
489
	adc	dl, dl
490
	add	bl, bl
491
	loop	@b
492
	sub	dl, bl
493
	pop	ebx
494
	mov	ecx, edx
495
	ret
496
.RangeDecoderReverseBitTreeDecode:
497
; in: eax->probs,ecx=numLevels
498
; out: ecx=length; destroys edx
499
	push	ebx ecx
500
	mov	edx, 1
501
	xor	ebx, ebx
502
@@:
503
	push	eax
504
	lea	eax, [eax+edx*4]
505
	call	.RangeDecoderBitDecode
506
	lahf
507
	adc	edx, edx
508
	sahf
509
	rcr	ebx, 1
510
	pop	eax
511
	loop	@b
512
	pop	ecx
513
	rol	ebx, cl
514
	mov	ecx, ebx
515
	pop	ebx
516
	ret
517
 
518
; LZMA parameters:
519
;       db      lc + 9 * (lp + 5 * pb)
520
;       dd      dictionarySize
521
 
522
lzma_get_buf_size:
523
        cmp     dword [esi-4], 5
524
        jb      return.err
525
        push    ecx
526
        lodsb
527
        aam     9
528
        mov     cl, al
529
        mov     al, ah
530
        aam     5
531
        add     cl, al
532
        mov     eax, LZMA_LIT_SIZE
533
        shl     eax, cl
534
        lea     eax, [lzma_decoder.basesize+eax*4]
535
        pop     ecx
536
        mov     edx, [esi]
537
        ret
538
 
539
lzma_init_decoder:
540
        lodsb
541
        aam     9
542
        mov     [ebp+lzma_decoder.lc], al
543
        mov     al, ah
544
        aam     5
545
        mov     [ebp+lzma_decoder.lp], al
546
        mov     [ebp+lzma_decoder.pb], ah
547
        cmp     ah, lzma_decoder.kNumPosBitsMax
548
        ja      return.err
549
        mov     cl, ah
550
        lodsd
551
        mov     [ebp+lzma_decoder.dictSize], eax
552
        push    1
553
        pop     eax
554
        shl     eax, cl
555
        dec     eax
556
        mov     [ebp+lzma_decoder.posStateMask], eax
557
        mov     cl, [ebp+lzma_decoder.lp]
558
        push    1
559
        pop     eax
560
        shl     eax, cl
561
        dec     eax
562
        mov     [ebp+lzma_decoder.literalPosMask], eax
563
        mov     [ebp+streamInfo.fillBuf], lzma_decoder.fillBuf
564
        mov     [ebp+lzma_decoder.continue], lzma_decoder.start
565
        xor     eax, eax
566
        mov     [ebp+lzma_decoder.previousByte], al
567
        mov     [ebp+lzma_decoder.state], eax
568
        inc     eax
569
        lea     edi, [ebp+lzma_decoder.rep0]
570
        stosd
571
        stosd
572
        stosd
573
        mov     eax, LZMA_LIT_SIZE
574
        mov     cl, [ebp+lzma_decoder.lc]
575
        add     cl, [ebp+lzma_decoder.lp]
576
        shl     eax, cl
577
        lea     ecx, [eax+lzma_decoder.Literal]
578
	mov	eax, lzma_decoder.kBitModelTotal/2
579
	lea	edi, [ebp+lzma_decoder.p]
580
	rep	stosd
581
        ret