; Routine de d{compression ; version modifi{e du pucrunch ; pour pouvoir g{rer du streaming ; par packets de taille fixe ; OffseT - Mai 2007 BuffersSize Equ &100 BufferSize Equ streamscount ; ****** Unpack pucrunch data ****** ; Entry HL = Source packed data ; DE = Destination for unpacked data ; HL = InPtr ; D = bitstr ; E = X ; BC = temps InitStream ld a,buffersize*prebuffers ld (buffercount),a ld (ix+OutPtr),e ld (ix+OutPtr+1),d ld (ix+StartPtr),l ld (ix+StartPtr+1),h ; Read the file header & setup variables RestartStream ld bc,6 add hl,bc ld a,(hl) ld (ix+escPu),a inc hl inc hl inc hl ld a,(hl) ld (ix+EscBits),a ld a,8 sub (hl) ld (ix+Esc8Bits),a inc hl ld a,(hl) ld (ix+MaxGamma),a ld a,9 sub (hl) ld (ix+Max8Gamma),a inc hl ld a,(hl) ld (ix+Max1Gamma),a add a,a dec a ld (ix+Max2Gamma),a inc hl ld a,(hl) ld (ix+ExtraBits),a inc hl inc hl inc hl ld c,(hl) ; Get lenght of RLE table (max = 31) inc c ; (B=0) ld (ix+tablePu),l ld (ix+tablePu+1),h add hl,bc ; Go to the start of data ld d,&80 jp main newesc ld b,a ld a,(ix+escPu) ld (ix+regy),a ld a,(ix+EscBits) ld e,a ld a,b inc e call getchk ld (ix+escPu),a ld a,(ix+regy) ; Fall through and get the rest of the bits. noesc ld b,a ld a,(ix+Esc8Bits) ld e,a ld a,b inc e call getchk ; Write out the escaped/normal byte ld c,(ix+OutPtr) ld b,(ix+OutPtr+1) ld (bc),a inc c ld (ix+OutPtr),c ld a,(buffercount) dec a ld (buffercount),a jr nz,main ld (ix+returntype),0 ld (ix+saved),d ld (ix+savel),l ld (ix+saveh),h ret ; Fall through and check the escape bits again main ld a,(ix+EscBits) ld e,a xor a ld (ix+regy),a inc e call getchk ; X=2 -> X=0 ld b,a ld a,(ix+escPu) cp b ld a,b jr nz,noesc ; Not the escape code -> get the rest of the byte ; Fall through to packed code call getval ; X=0 -> X=0 ld (ix+lzpos),a ; xstore - save the length for a later time srl a ; cmp #1 ; LEN == 2 ? (A is never 0) jp nz,lz77 ; LEN != 2 -> LZ77 call get1bit ; X=0 -> X=0 srl a ; bit -> C, A = 0 jp nc,lz772 ; A=0 -> LZPOS+1 LZ77, len=2 ; e..e01 call get1bit ; X=0 -> X=0 srl a ; bit -> C, A = 0 jr nc,newesc ; e..e010 New Escape ; e..e011 Short/Long RLE ld a,(ix+regy) ; Y is 1 bigger than MSB loops inc a ld (ix+regy),a call getval ; Y is 1, get len, X=0 -> X=0 ld (ix+lzpos),a ; xstore - Save length LSB ld c,a ld a,(ix+Max1Gamma) ld b,a ld a,c cp b ; ** PARAMETER 63-64 -> C set, 64-64 -> C clear.. jr c,chrcode ; short RLE, get bytecode ; Otherwise it's long RLE longrle ld b,a ld a,(ix+Max8Gamma) ld e,a ; ** PARAMETER 111111xxxxxx ld a,b call getbits ; get 3/2/1 more bits to get a full byte, X=2 -> X=0 ld (ix+lzpos),a ; xstore - Save length LSB call getval ; length MSB, X=0 -> X=0 ld (ix+regy),a ; Y is 1 bigger than MSB loops chrcode call getval ; Byte Code, X=0 -> X=0 ld e,a ld a,(ix+tablepu) add a,e ld c,a ld a,(ix+tablepu+1) adc a,0 ld b,a ld a,e cp 32 ; 31-32 -> C set, 32-32 -> C clear.. ld a,(bc) jr c,less32 ; 1..31 ; Not ranks 1..31, -> 11111 # xxxxx (32..64), get byte.. ld a,e ; get back the value (5 valid bits) ld e,3 call getbits ; get 3 more bits to get a full byte, X=3 -> X=0 less32 ld (ix+savel),l ld (ix+saveh),h ld (ix+saved),d ld b,(ix+lzpos) ; xstore - get length LSB inc b ; adjust for cpx#$ff;bne -> bne ld c,(ix+regy) jr z,rlenodecc dec c RLENoDecC ld d,a ld l,(ix+OutPtr) ld h,(ix+OutPtr+1) RLEBufferManager ; D=fill byte, CB=size, HL=dest pointer xor a cp c jr nz,rlebufferoverflowbig ld a,(buffercount) cp b jr c,rlebufferoverflowsmall RLEBufferOK sub a,b RLEBufferOKLoop ld (hl),d inc l djnz rlebufferokloop ld (ix+OutPtr),l or a jr z,rlebufferokreturn RLEBufferOKGoMain ld (buffercount),a ld d,(ix+saved) ld l,(ix+savel) ld h,(ix+saveh) jp main RLEBufferOKReturn ld (ix+returntype),0 ret RLEBufferOverflowSmall ld c,b ld b,a RLEBufferOverflowSmallLoop ld (hl),d inc l djnz rlebufferoverflowsmallloop ld (ix+OutPtr),l ld b,a ld a,c ld c,b sub a,c ld (ix+data1),a ; remaining size ld (ix+data2),0 ld (ix+returntype),1 ret RLEBufferOverflowBig ld a,(buffercount) ld e,a ld a,b ld b,e sub a,b jr nc,rlebufferoverflowbigno16boverflow RLEBufferOverflowBig16bOverflow dec c RLEBufferOverflowBigNo16bOverflow ld (ix+data1),a ld (ix+data2),c ld b,e RLEBufferOverflowBigLoop ld (hl),d inc l djnz rlebufferoverflowbigloop ld (ix+OutPtr),l ld (ix+returntype),1 ret Exit ld l,(ix+StartPtr) ld h,(ix+StartPtr+1) jp restartstream lz77 call getval ; X=0 -> X=0 ld b,a ld a,(ix+Max2Gamma) cp b ; end of file? jr z,exit ; yes, exit ld a,(ix+ExtraBits) ; ** PARAMETER (more bits to get) ld e,a ld a,b dec a ; subtract 1 (1..126 -> 0..125) inc e call getchk ; clears Carry, X=0 -> X=0 lz772 ld e,8 ; offset MSB (lzlen+1) but always = 0 call getbits ; clears Carry, X=8 -> X=0 ; Note; Already eor;ed in the compressor.. ld b,(ix+lzpos) ; xstore - LZLEN (read before it's overwritten) inc b ; adjust for cpx#$ff;bne -> bne add a,(ix+OutPtr) ; -offset -1 + curpos (C is clear) ld (ix+lzpos),a ; Write decompressed bytes out to RAM ld (ix+saved),d ld (ix+savel),l ld (ix+saveh),h LZBufferManager ; A=src oft, B=lz size ld e,(ix+OutPtr) ; copy X+1 number of chars from LZPOS to OUTPOS ld d,(ix+OutPtr+1) ld l,a ld h,d ld a,(buffercount) cp b ; b > buffercount ? jr c,lzbufferoverflow LZBufferOK ld c,a sub a,b cp c jr z,lzbufferoverflow ; b=0 -> b=256 ld c,a LZBufferOKLoop ld a,(hl) ld (de),a inc l inc e djnz lzbufferokloop ld (ix+outptr),e ld a,c or a jr z,lzbufferokreturn LZBufferOKGoMain ld (buffercount),a ld d,(ix+saved) ld l,(ix+savel) ld h,(ix+saveh) jp main LZBufferOKReturn ld (ix+returntype),0 ret LZBufferOverflow ld c,a ld a,b ld b,c sub a,b ld (ix+data1),a LZBufferOverflowLoop ld a,(hl) ld (de),a inc l inc e djnz lzbufferoverflowloop ld (ix+outptr),e ld (ix+data2),l ld (ix+returntype),2 ret GetNextBytes ld a,buffersize ld (buffercount),a ld a,(ix+returntype) or a jr z,returntype0 cp 1 jr z,returntype1 cp 2 jr z,returntype2 ret ReturnType0 ; Simple return ld d,(ix+saved) ld l,(ix+savel) ld h,(ix+saveh) jp main ReturnType1 ; RLE copy management ld l,(ix+OutPtr) ld h,(ix+OutPtr+1) dec l ld d,(hl) inc l ld b,(ix+data1) ld c,(ix+data2) jp rlebuffermanager ReturnType2 ; LZ77 copy management ld b,(ix+data1) ld a,(ix+data2) jp lzbuffermanager ; getval; Gets a 'static huffman coded' value ; ** Scratches X, returns the value in A ** getval ld a,1 ; X must be 0 when called! ld e,a loop0 sla d jr nz,loop1 ld d,(hl) inc hl rl d ; Shift in C=1 (last bit marker) bitstr initial value = &80 == empty loop1 jr nc,getchk ; got 0-bit inc e ld b,a ; save a ld a,(ix+MaxGamma) cp e ld a,b ; restore a jr nz,loop0 jr getchk ; getbits; Gets X bits from the stream ; ** Scratches X, returns the value in A ** get1bit inc e getbits sla d jr nz,loop3 ld d,(hl) inc hl rl d ; Shift in C=1 (last bit marker) bitstr initial value = &80 == empty loop3 rla getchk dec e jr nz,getbits ret BufferCount db 0 ; Data Index Let CurrentPC=$ Org 0 Nocode escPu db 0 OutPtr dw 0 lzpos db 0 EscBits db 0 Esc8Bits db 0 MaxGamma db 0 Max1Gamma db 0 Max2Gamma db 0 Max8Gamma db 0 ExtraBits db 0 tablePu dw 0 regy db 0 StartPtr dw 0 SaveL db 0 SaveH db 0 SaveD db 0 Data1 db 0 Data2 db 0 ReturnType db 0 StreamsContextSize db 0 Org CurrentPC Code StreamsContextAdr ds streamscount*streamscontextsize {rer du streaming ; par packets de taille fixe ;