Copy Link
Add to Bookmark
Report
PowerPacker Decrunch assembler subroutine V2.0 for Atari
****************************************************************************
* *
* PowerPacker Decrunch assembler subroutine V2.0 (reentrant !) *
* *
* call as: *
* pp_DecrunchBuffer (endcrun, buffer, &efficiency, coloraddr); *
* with: *
* endcrun : UBYTE * just after last byte of crunched file *
* buffer : UBYTE * to memory block to decrunch in *
* &efficiency: ptr to Longword defining efficiency of crunched file *
* coloraddr : address of color register or an address of a dummy *
* *
* NOTE: *
* Decrunch a few bytes higher (safety margin) than the crunched file *
* to decrunch in the same memory space. (8 bytes suffice) *
* *
****************************************************************************
SECTION text,CODE
XDEF _pp_DecrunchBuffer
XDEF _pp_CalcCheckSum
XDEF _pp_CalcPasskey
XDEF _pp_Decrypt
_pp_DecrunchBuffer:
movem.l d1-d7/a0-a6,-(a7)
move.l 56+4(a7),a0
move.l 56+8(a7),a3
move.l 56+12(a7),a5
move.l 56+16(a7),a6
bsr.s Decrunch
movem.l (a7)+,d1-d7/a0-a6
rts
; a3 -> file, a0 -> longword after crunched, a5 -> ptr to eff., a6 -> decr.col
; destroys a0-a6 and d0-d7
Decrunch:
moveq #3,d6
moveq #7,d7
moveq #1,d5
move.l a3,a2 ; remember start of file
move.l -(a0),d1 ; get file length and empty bits
tst.b d1
beq.s NoEmptyBits
bsr.s ReadBit ; this will always get the next long (D5 = 1)
subq.b #1,d1
lsr.l d1,d5 ; get rid of empty bits
NoEmptyBits:
lsr.l #8,d1
add.l d1,a3 ; a3 = endfile
LoopCheckCrunch:
bsr.s ReadBit ; check if crunch or normal
bcs.s CrunchedBytes
NormalBytes:
moveq #0,d2
Read2BitsRow:
moveq #1,d0
bsr.s ReadD1
add.w d1,d2
cmp.w d6,d1
beq.s Read2BitsRow
ReadNormalByte:
moveq #7,d0
bsr.s ReadD1
move.b d1,-(a3)
dbf d2,ReadNormalByte
cmp.l a3,a2
bcs.s CrunchedBytes
rts
ReadBit:
lsr.l #1,d5 ; this will also set X if d5 becomes zero
beq.s GetNextLong
rts
GetNextLong:
move.l -(a0),d5
roxr.l #1,d5 ; X-bit set by lsr above
rts
ReadD1sub:
subq.w #1,d0
ReadD1:
moveq #0,d1
ReadBits:
lsr.l #1,d5 ; this will also set X if d5 becomes zero
beq.s GetNext
RotX:
roxl.l #1,d1
dbf d0,ReadBits
rts
GetNext:
move.l -(a0),d5
roxr.l #1,d5 ; X-bit set by lsr above
bra.s RotX
CrunchedBytes:
moveq #1,d0
bsr.s ReadD1 ; read code
moveq #0,d0
move.b 0(a5,d1.w),d0 ; get number of bits of offset
move.w d1,d2 ; d2 = code = length-2
cmp.w d6,d2 ; if d2 = 3 check offset bit and read length
bne.s ReadOffset
bsr.s ReadBit ; read offset bit (long/short)
bcs.s LongBlockOffset
moveq #7,d0
LongBlockOffset:
bsr.s ReadD1sub
move.w d1,d3 ; d3 = offset
Read3BitsRow:
moveq #2,d0
bsr.s ReadD1
add.w d1,d2 ; d2 = length-1
cmp.w d7,d1 ; cmp with #7
beq.s Read3BitsRow
bra.s DecrunchBlock
ReadOffset:
bsr.s ReadD1sub ; read offset
move.w d1,d3 ; d3 = offset
DecrunchBlock:
addq.w #1,d2
DecrunchBlockLoop:
move.b 0(a3,d3.w),-(a3)
dbf d2,DecrunchBlockLoop
EndOfLoop:
move.w a3,(a6)
cmp.l a3,a2
bcs LoopCheckCrunch
rts
****************************************************************************
* pp_CalcCheckSum (char *);
_pp_CalcCheckSum:
move.l 4(a7),a0
moveq #0,d0
moveq #0,d1
sumloop:
move.b (a0)+,d1
beq.s exitasm
ror.w d1,d0
add.w d1,d0
bra.s sumloop
* pp_CalcPasskey (char *);
_pp_CalcPasskey:
move.l 4(a7),a0
moveq #0,d0
moveq #0,d1
keyloop:
move.b (a0)+,d1
beq.s exitasm
rol.l #1,d0
add.l d1,d0
swap d0
bra.s keyloop
exitasm:
rts
* pp_Decrypt (UBYTE *, ULONG, ULONG);
_pp_Decrypt:
move.l 4(a7),a0
move.l 8(a7),d1
move.l 12(a7),d0
move.l d2,-(a7)
addq.l #3,d1
lsr.l #2,d1
encryptloop:
move.l (a0),d2
eor.l d0,d2
move.l d2,(a0)+
subq.l #1,d1
bne.s encryptloop
move.l (a7)+,d2
rts
END