1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
|
*****************************************************************************
** **
** PPDecrunch - Eine Datei PowerPacker-decrunchen auf sich selber **
** **
** Parameter : A0.L : Adresse **
** D0.L : Länge der gecrunchten Daten **
** **
** Resultat : nix **
** **
*****************************************************************************
IDNT PPDecrunch
SECTION text,CODE
INCLUDE "MyExec.i"
XDEF PPDecrunch
PPDecrunch: movem.l d0-d7/a0-a5,-(SP)
lea Efficiency(PC),a5 ; A5: Pointer to efficiency
move.l a0,-(SP) ; Buffer für später
lea PP_SAVEMARGIN(a0),a3 ; A3: Destination
move.l a3,-(SP) ; Quelle für später
move.l (a0)+,-(SP) ; Decrunchte Grösse für später
move.l (a0)+,(a5) ; Efficiency eintragen
lea -8(a0,d0.l),a0 ; A0: Source-Ende
move.l a6,-(SP)
bsr.b Decrunch
movea.l (SP)+,a6
move.l (SP)+,d0 ; Decrunchte Grösse
movea.l (SP)+,a0 ; Quelle
movea.l (SP)+,a1 ; Ziel
jsr meb_CopyMem(a6) ; runterschieben
movem.l (SP)+,d0-d7/a0-a5
rts
Efficiency: dc.l 0
****************************************************************************
* *
* PowerPacker Decrunch assembler subroutine V2.0 (reentrant !) *
* DESTROYS ALL REGISTERS! *
* *
* call as: *
* pp_DecrunchBuffer (endcrun, buffer, &efficiency, coloraddr); *
* with: *
* A0 endcrun : UBYTE * just after last byte of crunched file *
* A3 buffer : UBYTE * to memory block to decrunch in *
* A5 &efficiency: ptr to Longword defining efficiency of crunched file *
* *
* NOTE: *
* Decrunch a few bytes higher (safety margin) than the crunched file *
* to decrunch in the same memory space. (8 bytes suffice) *
* *
****************************************************************************
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.b NoEmptyBits
bsr.b 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.b ReadBit ; check if crunch or normal
bcs.b CrunchedBytes
NormalBytes:
moveq #0,d2
Read2BitsRow:
moveq #1,d0
bsr.b ReadD1
add.w d1,d2
cmp.w d6,d1
beq.b Read2BitsRow
ReadNormalByte:
moveq #7,d0
bsr.b ReadD1
move.b d1,-(a3)
dbf d2,ReadNormalByte
cmp.l a3,a2
bcs.b CrunchedBytes
rts
ReadBit:
lsr.l #1,d5 ; this will set X if d5 becomes zero
beq.b 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 set X if d5 becomes zero
beq.b 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.b RotX
CrunchedBytes:
moveq #1,d0
bsr.b 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.b ReadOffset
bsr.b ReadBit ; read offset bit (long/short)
bcs.b LongBlockOffset
moveq #7,d0
LongBlockOffset:
bsr.b ReadD1sub
move.w d1,d3 ; d3 = offset
Read3BitsRow:
moveq #2,d0
bsr.b ReadD1
add.w d1,d2 ; d2 = length-1
cmp.w d7,d1 ; cmp with #7
beq.b Read3BitsRow
bra.b DecrunchBlock
ReadOffset:
bsr.b 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:
cmp.l a3,a2
bcs LoopCheckCrunch
rts
END
|