summaryrefslogtreecommitdiff
path: root/Source/CompressBlock.S
blob: 36bed53e70a15a2df3527683ad983d526758c83a (plain)
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