** ** $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