summaryrefslogtreecommitdiff
path: root/Source/DecodePic.S
blob: 67f4cd763efc63fe6c365c7d038f86e22db1c5b3 (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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
**
**	$Id: DecodePic.S,v 21.3 92/10/12 20:40:00 chris Exp $
**	$Revision: 21.3 $
**
**	$Filename: DecodePic.S $
**	$Author: chris $
**	$Date: 92/10/12 20:40:00 $
**
**	iff.library/IFFL_DecodePic
**
**	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_DecodePic
		SECTION	text,CODE

		INCLUDE	"IFFLib.i"

		XREF	ClearError,SetError,Decompress_BYTERUN1
		XREF	GetBMHDFunc,FindChunkFunc
		XDEF	DecodePicFunc


******* iff.library/IFFL_DecodePic ******************************************
*
*    NAME
*	IFFL_DecodePic -- decode the BODY of an ILBM file into a BitMap
*
*    SYNOPSIS
*	success = IFFL_DecodePic( iff, bitmap )
*	 D0                       A1   A0
*
*	BOOL IFFL_DecodePic( IFFL_HANDLE, struct BitMap * )
*
*    FUNCTION
*	Decodes and decompresses a picture into the user supplied BitMap.
*	If the picture is higher than your BitMap, it will be truncated.
*	If your BitMap is larger than the picture, the picture will be
*	drawn into the top left corner of your BitMap.
*	If the picture has less planes than the BitMap, the unused planes
*	are NOT touched by this routine, so you may wish to clear them
*	before calling IFFL_DecodePic(). If the picture has more planes
*	than your BitMap, the surplus planes of the picture are ignored.
*
*    INPUTS
*	iff    - IFF file handle, from IFFL_OpenIFF()
*	bitmap - Pointer to a properly initialized BitMap structure:
*		 bm_Planes[] must point to valid BitPlanes,
*		 bm_Depth contains the number of planes.
*		 bm_Width and bm_Height must be set according to the
*		 size of your bit planes.
*
*    RESULTS
*	Non-zero if successful, zero if error. Call IFFL_IFFError() to
*	know the reason of the failure
*
*    BUGS
*	If the picture is wider than your BitMap, one line of innocent
*	memory will be overwritten at the end of each bitplane. You can
*	avoid this by allocating a few bytes more for each plane.
*	Normally, you allocate your BitMap after inspecting the BMHD
*	chunk, so this should not be a problem.
*
*    NOTE
*	This routine needs at least 650 bytes of stack space
*
*    SEE ALSO
*
*****************************************************************************

	STRUCTURE DecodePicStackFrame,0
		STRUCT	WorkPlanes,24*4		; muß am Anfang sein
		STRUCT	LineBuffer,400		; max 3200 pixel bei stencil
	LABEL	LINKSIZE

DecodePicFunc:	movem.l	d2-d7/a2-a6,-(SP)
		lea	-LINKSIZE(SP),SP	; Lokalen Datenraum schaffen
		movea.l	a6,a5			; A5: IFFBase für SetError()
		movea.l	a0,a3			; A3: BitMap
		movea.l	a1,a4			; A4: IFFFile

	*** Testen ob ILBM-File

		cmpi.l	#'ILBM',8(a4)		; ist's überhaupt ein ILBM-File ?
		beq.b	1$			; ja --->
		moveq	#IFFL_ERROR_NOILBM,d0	; Fehlernummer
		bra	.Error
1$:
	*** BitMapHeader suchen und nach A2

		bsr	GetBMHDFunc		; BitMapHeader suchen
	;;	tst.l	d0
		bne.b	2$			; gefunden --->
		moveq	#IFFL_ERROR_NOBMHD,d0	; Fehlernummer
		bra	.Error
2$:		movea.l	d0,a2			; A2: BitMapHeader

	*** Testen ob Bild-Depth <= BitMap Depth

		move.b	bmh_nPlanes(a2),d2	; D2: Depth (Minimum)
		beq	.Okay			; Bild hat 0 planes --->
3$:
	*** Planes in Arbeitsbereich kopieren

		moveq.l	#23,d0			; Max. 24 Bitplanes
		lea	bm_Planes(a3),a0	; Source
		lea	WorkPlanes(SP),a1	; Destination
.CopyLoop:	move.l	(a0)+,(a1)+
		dbf	d0,.CopyLoop

	*** BODY-Chunk suchen und nach A0, BODY-Ende nach A4

		move.l	#'BODY',d0
		movea.l	a4,a1			; IFF-File
		bsr	FindChunkFunc
	;;	tst.l	d0
		bne.b	4$			; gefunden --->
		moveq	#IFFL_ERROR_NOBODY,d0	; Fehlernummer
		bra	.Error
4$:
		movea.l	d0,a0			; A0 :  Body-Adresse
		addq.l	#4,a0			; 'BODY' überspringen
		movea.l	(a0)+,a4		; Chunk-size
		adda.l	a0,a4			; A4 :  Body-Endadresse

	*** Compression testen und entsprechende Routine nach A6

		move.b	bmh_Compression(a2),d0
		bne.b	5$
		lea	CopyRow(PC),a6		; Not crunched
		bra.b	7$			; --->
5$:
		subq.b	#1,d0				; CmpByteRun1 ?
		bne.b	6$				; ja --->
		lea	Decompress_BYTERUN1(PC),a6	; DecompressBlock.S
		bra.b	7$				; --->
6$:
		moveq	#IFFL_ERROR_BADCOMPRESSION,d0
		bra.b	.Error
7$:
	*** Masking testen und wenn 'hasmask' (Stencil) D7.B:=$FF, sonst $00

		cmpi.b	#1,bmh_Masking(a2)	; 'mskHasMask' ?
		seq	d7			; wenn ja: D7 := $FF

	*** Modulos setzen etc.

.doit:		moveq.l	#0,d4			; D4 :  Source-Modulo
		move.w	bmh_Width(a2),d4
		add.w	#15,d4			; auf WORD aufrunden
		lsr.l	#3,d4
		bclr	#0,d4			; auf WORD aufrunden

		moveq.l	#0,d5
		move.w	bm_BytesPerRow(a3),d5	; D5 :  Destination-Modulo

		moveq.l	#0,d6
		move.w	bm_Rows(a3),d6		; D6 :  Max. Anzahl Zeilen
		cmp.w	bmh_Height(a2),d6	; BitMap zu groß ?
		ble.b	8$			; nein --->
		move.w	bmh_Height(a2),d6	; Sonst Höhe aus bmh nehmen
8$:
		bra.b	.CheckCond		; ---> für dbf

	*** Hauptschleife

.body1:		moveq	#0,d3			; Init plane-counter
		lea	WorkPlanes(SP),a2	; A2 : Arbeitskopie der Planes

.body2:		move.l	d4,d0			; Source bytes per row
		cmp.b	bm_Depth(a3),d3		; Is there a dest-plane ?
		bhs.b	.NoDest			; nope ---> skip it
		movea.l	(a2),a1			; Adrese der aktuellen Plane
		add.l	d5,(a2)+		; Plane auf nächste Linie
		bra.b	9$
.NoDest:	lea	LineBuffer(SP),a1	; Plane ins NIL kopieren
9$:		jsr	(a6)			; Linie copyren / decrunchen
		addq.b	#1,d3			; INC planecounter
		cmp.b	d2,d3
		blt.b	.body2			; ---> Nächste Plane

		tst.b	d7			; Maske zu überhüpfen ?
		beq.b	.NoMask			; nein --->
		move.l	d4,d0			; Source bytes per row
		lea	LineBuffer(SP),a1	; Maske zur Hölle schicken
		jsr	(a6)			; Linie copyren / decrunchen
.NoMask:
.CheckCond:	cmpa.l	a4,a0			; fertig ?
		dbhs	d6,.body1		; wenn nicht: nächste Linie

.Okay:		bsr	ClearError		; IFFError rücksetzen, D0 := 1
		bra.b	.Ende

.Error:		bsr	SetError		; IFFError setzen, clr.l d0

.Ende:		lea	LINKSIZE(SP),SP
		movem.l	(SP)+,d2-d7/a2-a6
		rts


*************** 1 Linie kopieren *****************************************

copyloop:	move.b	(a0)+,(a1)+
CopyRow:	dbf	d0,copyloop
		rts


		END