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
214
|
**
** $Id: DecodePic.S,v 21.2 92/05/18 02:16:02 chris Exp $
** $Revision: 21.2 $
**
** $Filename: DecodePic.S $
** $Author: chris $
** $Release: 19.1 $
** $Date: 92/05/18 02:16:02 $
**
** 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
|