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
152
153
154
155
156
157
158
159
160
|
**
** $Id: CompressBlock.S,v 21.3 92/05/18 02:20:39 chris Exp $
** $Revision: 21.3 $
**
** $Filename: CompressBlock.S $
** $Author: chris $
** $Date: 92/05/18 02:20:39 $
**
** iff.library/IFFL_CompressBlock
**
** COPYRIGHT (C) 1987-1992 BY CHRISTIAN A. WEBER, BRUGGERWEG 2,
** CH-8037 ZUERICH, SWITZERLAND. ALL RIGHTS RESERVED. NO PART
** OF THIS SOFTWARE MAY BE COPIED, REPRODUCED, OR TRANSMITTED
** IN ANY FORM OR BY ANY MEANS, WITHOUT THE PRIOR WRITTEN PER-
** MISSION OF THE AUTHOR. USE AT YOUR OWN RISK.
**
IDNT IFFL_CompressBlock
SECTION text,CODE
INCLUDE "IffLib.i"
XREF SetError
XDEF CompressBlockFunc
XDEF Compress_NONE,Compress_BYTERUN1 ;,Compress_FIBDELTA
******* iff.library/IFFL_CompressBlock **************************************
*
* NAME
* IFFL_CompressBlock -- Compress a memory block
*
* SYNOPSIS
* result = IFFL_CompressBlock( source, destination, size, mode )
* A0 A1 D0 D1
*
* ULONG IFFL_CompressBlock( APTR, APTR, ULONG, ULONG )
*
* FUNCTION
* Compress the memory block using the appropriate compression mode.
* If the compressed data would become longer than the uncompressed,
* an error is returned.
*
* INPUTS
* source - Pointer to data to compress
* destination - Target address for compression
* size - Number of data bytes to compress
* mode - Compression mode. Currently, the following modes
* are supported:
*
* IFFL_COMPR_NONE - Vanilla copy
* IFFL_COMPR_BYTERUN1 - CmpByteRun1 (ILBM BODY data)
* IFFL_COMPR_FIBDELTA - Fibonacci Delta (8SVX BODY data)
*
* RESULTS
* Length of compressed data or 0 if an error occurred.
* IFFL_IFFError() returns IFFL_ERROR_BADCOMPRESSION if you ask for
* an unsupported compression mode.
*
* BUGS
* In IFFL_COMPR_BYTERUN1, if the compressed data would become longer,
* the buffer will be overwritten, and no error is returned. So be
* sure to supply a destination buffer which is big enough!
*
* SEE ALSO
* IFFL_DecompressBlock()
*
*****************************************************************************
CompressBlockFunc:
subq.l #1,d1
beq.b Compress_BYTERUN1 ; Modus == 1
bmi.b Compress_NONE ; Modus == 0
*** Unbekannter Modus --> Error setzen
movem.l a5-a6,-(SP)
movea.l a6,a5 ; A5 : IFFBase für SetError()
moveq.l #IFFL_ERROR_BADCOMPRESSION,d0
bsr SetError ; Setzt auch D0 auf 0
movem.l (SP)+,a5-a6
rts
*****************************************************************************
** Kopiermodus (für CompressBlock() UND DecompressBlock() benutzt)
Compress_NONE: movem.l d0/a6,-(SP)
movea.l iffb_SysBase(a6),a6
JSRLIB CopyMem
movem.l (SP)+,d0/a6
rts
*****************************************************************************
** CmpByteRun1 komprimieren
Compress_BYTERUN1:
movem.l d2-d3/a2-a3,-(SP)
lea 0(a0,d0.l),a2 ; A2 : Source-Endadresse
moveq #0,d3 ; Byte-Zähler
crunchloop: bsr.b CountEq ; wieviele gleiche Bytes folgen ?
cmp.w #3,d0 ; genug gleiche Bytes zum runnen ?
blt.b countdump ; nee, lohnt sich nicht -> Dumpen
addq.l #2,d3 ; Markierbyte & Anzahl
move.b (a0),d1 ; Wert
adda.w d0,a0 ; Source anpassen
subq.w #1,d0 ; muss .w sein und nicht .b !!!!!!!
neg.b d0 ; negieren (= "Run"-Code)
move.b d0,(a1)+ ; und eintragen
move.b d1,(a1)+ ; Wert eintragen
bra.b crunchcont ; weitermachen
countdump: movea.l a0,a3 ; Source-Pointer retten
moveq #0,d2 ; D2 : Länge des Dump-Blocks
1$: addq.b #1,d2
bmi.b 2$ ; höchstens 127 Bytes pro Block
addq.l #1,a0
cmpa.l a2,a0 ; Ende der Daten erreicht ?
bhs.b 3$ ; ja -> abbrechen
bsr.b CountEq
cmp.w #3,d0 ; Ende des Dump-Blocks ?
blt.b 1$ ; noch nicht
bra.b 3$ ; Ende
2$: moveq #127,d2
3$: movea.l a3,a0 ; Source-Pointer restaurieren
add.l d2,d3 ; zur Gesamtanzahl dazuzählen
addq.l #1,d3 ; Markierbyte nicht vergessen
subq.w #1,d2 ; aus 1..128 mach 0..127
move.b d2,(a1)+ ; Markierbyte eintragen
4$: move.b (a0)+,(a1)+ ; Datenbytes eintragen
dbf d2,4$
crunchcont: cmpa.l a2,a0 ; Ende der Linie erreicht ?
blo.b crunchloop ; noch nicht!
move.l d3,d0 ; Return: Anzahl Destination-Bytes
movem.l (SP)+,d2-d3/a2-a3
rts
*** Anzahl gleicher Zeichen ab (a0) zählen und nach D0
CountEq: move.l a0,-(SP)
moveq #1,d0 ; D0 : Anzahl gleiche Bytes
1$: move.b (a0)+,d1 ; erstes Byte
2$: cmp.b (a0)+,d1 ; Byte gleich wie letztes Byte ?
bne.b 3$ ; nein -> abbrechen
cmp.w #128,d0
bge.b 3$ ; höchstens 128 gleiche
addq.w #1,d0 ; Anzahl erhöhen
cmpa.l a2,a0 ; Ende des Buffers erreicht ?
blo.b 2$ ; noch nicht -> weiterzählen
3$: move.l (SP)+,a0
rts
END
|