** ** $Id: DecodePic.S,v 1.1 92/05/12 22:26:36 chris Exp $ ** $Revision: 1.1 $ ** ** $Filename: DecodePic.S $ ** $Author: chris $ ** $Release: 19.1 $ ** $Date: 92/05/12 22:26:36 $ ** ** 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,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 larger than your BitMap's planes, 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 * * 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.s 1$ ; ja ---> moveq #IFFL_ERROR_NOILBM,d0 ; Fehlernummer bra .Error 1$: *** BitMapHeader suchen und nach A2 bsr GetBMHDFunc ; BitMapHeader suchen ;; tst.l d0 bne.s 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.s 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.s 5$ lea CopyRow(PC),a6 ; Not crunched bra.s 7$ ; ---> 5$: cmpi.b #1,d0 ; CmpByteRun1 ? bne.s 6$ ; ja ---> lea DecrunchRow(PC),a6 ; CmpByteRun1 bra.s 7$ ; ---> 6$: moveq #IFFL_ERROR_BADCOMPRESSION,d0 bra.s .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.s 8$ ; nein ---> move.w bmh_Height(a2),d6 ; Sonst Höhe aus bmh nehmen 8$: bra.s .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.s .NoDest ; nope ---> skip it movea.l (a2),a1 ; Adrese der aktuellen Plane add.l d5,(a2)+ ; Plane auf nächste Linie bra.s 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.s .body2 ; ---> Nächste Plane tst.b d7 ; Maske zu überhüpfen ? beq.s .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.s .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 *************** 1 Linie decrunchen *************************************** DecrunchRow: move.l d2,-(SP) 1$: moveq.l #0,d1 move.b (a0)+,d1 ; D1 : nächstes Kommando-Byte bmi.s 2$ ; crunched ---> .CopyLoop: move.b (a0)+,(a1)+ ; D1+1 Bytes normal kopieren subq.w #1,d0 ; DEC ColumnCounter dble d1,.CopyLoop bra.s 3$ ; ---> 2$: neg.b d1 bmi.s 3$ ; ~$80 (== $80) ist 'NOP' move.b (a0)+,d2 ; Zu repetierender Wert .RepLoop: move.b d2,(a1)+ subq.w #1,d0 ; DEC ColumnCounter dble d1,.RepLoop 3$: tst.w d0 ; Linie fertig ? bgt.s 1$ ; noch nicht ---> Loop move.l (SP)+,d2 rts END