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
|
**
** $Id: CompressBlock.S,v 2.1 92/05/13 01:48:05 chris Exp $
** $Revision: 2.1 $
**
** $Filename: CompressBlock.S $
** $Author: chris $
** $Release: $
** $Date: 92/05/13 01:48:05 $
**
** 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 ClearError
XDEF CompressBlockFunc
******* 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:
* $$$
*
* RESULTS
* Length of compressed data or 0 if an error occurred.
*
* SEE ALSO
* IFFL_DecompressBlock()
*
*****************************************************************************
CompressBlockFunc:
tst.l d1 ; Modus == 0 ?
beq.b Mode_Copy
subq.l #1,d1 ; Modus == 1 ?
beq.b Mode_CmpByteRun1
moveq.l #0,d0
rts
*****************************************************************************
** Kopiermodus
Mode_Copy: movem.l d0/a6,-(SP)
movea.l iffb_SysBase(a6),a6
JSRLIB CopyMem
movem.l (SP)+,d0/a6
rts
*****************************************************************************
** CmpByteRun1 komprimieren
Mode_CmpByteRun1:
movem.l d2-d3/a2-a3,-(SP)
lea (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 Linie erreicht ?
bge.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 ?
blt.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
|