home *** CD-ROM | disk | FTP | other *** search
-
- /*
- **
- ** $VER: dispatch.c 1.9 (22.5.97)
- ** anim.datatype 1.9
- **
- ** Dispatch routine for a DataTypes class
- **
- ** Written 1996/97 by Roland 'Gizzy' Mainz
- ** Original example source from David N. Junod
- **
- */
-
- /* main includes */
- #include "classbase.h"
-
- /* ansi includes */
- #include <limits.h>
-
-
- /* IFF errors to DOS errors */
- const
- LONG ifferr2doserr[] =
- {
- 0L, /* End of file (not an error). */
- 0L, /* End of context (not an error). */
- DTERROR_INVALID_DATA, /* No lexical scope. */
- ERROR_NO_FREE_STORE, /* Insufficient memory. */
- ERROR_SEEK_ERROR, /* Stream read error. */
- ERROR_SEEK_ERROR, /* Stream write error. */
- ERROR_SEEK_ERROR, /* Stream seek error. */
- DTERROR_INVALID_DATA, /* File is corrupt. */
- DTERROR_INVALID_DATA, /* IFF syntax error. */
- ERROR_OBJECT_WRONG_TYPE, /* Not an IFF file. */
- ERROR_REQUIRED_ARG_MISSING, /* Required call-back hook missing. */
- 0xDEADDEADUL /* Return to client. You should never see this */
- };
-
- /* anim.datatype class instance data */
- struct AnimInstData
- {
- /* Misc */
- struct SignalSemaphore aid_SigSem; /* Instance data lock */
- UWORD aid_Pad0;
- APTR aid_Pool;
- struct BitMapHeader *aid_BMH;
- struct BitMap *aid_KeyBitMap; /* Key BitMap */
- struct MinList aid_FrameList; /* List of frames */
- STRPTR aid_ProjectName; /* Shortcut to DTA_Name */
- BPTR aid_VerboseOutput; /* Verbose output */
-
- /* Prefs */
- ULONG aid_ModeID;
- BOOL aid_NoCMAPs; /* Don't create colormaps */
- BOOL aid_LoadAll; /* Load all frames of the animation */
- BOOL aid_NoRemap; /* Set ADTA_Remap to FALSE if possible */
- UWORD aid_FPS; /* fps of stream (maybe modified by prefs) */
-
- /* Sample stuff */
- BYTE *aid_Sample;
- ULONG aid_SampleLength;
- ULONG aid_Period;
- ULONG aid_Volume;
-
- /* Disk-loading section */
- BPTR aid_FH;
- LONG aid_CurrFilePos;
- };
-
-
- /* node which holds information about a single animation frame */
- struct FrameNode
- {
- struct MinNode fn_Node;
-
- /* Misc */
- WORD fn_UseCount;
- UWORD fn_Pad0;
-
- /* Timing section */
- ULONG fn_TimeStamp;
- ULONG fn_Frame;
-
- /* Animation info */
- struct AnimHeader fn_AH;
-
- /* Bitmap/ColorMap section */
- struct BitMap *fn_BitMap;
- struct ColorMap *fn_CMap;
-
- /* BitMap loading section */
- LONG fn_BMOffset; /* File offset (0 is begin of file) */
- ULONG fn_BMSize; /* Chunk size */
-
- /* Sample section */
- BYTE *fn_Sample;
- ULONG fn_SampleLength;
- ULONG fn_Period;
- };
-
- /*****************************************************************************/
-
- struct AnimContext
- {
- APTR ac_Pool; /* memory pool for this context */
- UBYTE *ac_WorkBuffer;
- ULONG ac_WorkBufferSize;
- struct BitMap *ac_BitMap[ 2 ]; /* two buffers... */
- WORD ac_WhichBitMap; /* which buffer: 0 or 1 */
- };
-
- /*****************************************************************************/
-
- /* local prototypes */
- static STRPTR GetPrefsVar( struct ClassBase *, STRPTR );
- static BOOL matchstr( struct ClassBase *, STRPTR, STRPTR );
- static void ReadENVPrefs( struct ClassBase *, struct AnimInstData * );
- static LONG LoadFrames( struct ClassBase *, Object * );
- static struct FrameNode *AllocFrameNode( struct ClassBase *, APTR );
- static struct FrameNode *FindFrameNode( struct MinList *, ULONG );
- static void FreeFrameNodeResources( struct ClassBase *, struct MinList * );
- static void CopyBitMap( struct ClassBase *, struct BitMap *, struct BitMap * );
- static void ClearBitMap( struct BitMap * );
- static void XORBitMaps( struct BitMap *, struct BitMap * );
- static struct BitMap *AllocBitMapPooled( struct ClassBase *, ULONG, ULONG, ULONG, APTR );
- static BOOL CMAP2Object( struct ClassBase *, Object *, UBYTE *, ULONG );
- static struct ColorMap *CMAP2ColorMap( struct ClassBase *, struct AnimInstData *, UBYTE *, ULONG );
- static struct ColorMap *CopyColorMap( struct ClassBase *, struct ColorMap * );
- static APTR AllocVecPooled( struct ClassBase *, APTR, ULONG );
- static void FreeVecPooled( struct ClassBase *, APTR, APTR );
- static LONG DrawDLTA( struct ClassBase *, struct AnimInstData *, struct BitMap *, struct BitMap *, struct AnimHeader *, UBYTE *, ULONG );
- static void DumpAnimHeader( struct ClassBase *, struct AnimInstData *, ULONG, struct AnimHeader * );
- static struct FrameNode *GetPrevFrameNode( struct FrameNode *, ULONG );
- static void OpenLogfile( struct ClassBase *, struct AnimInstData * );
- static void mysprintf( struct ClassBase *, STRPTR, STRPTR, ... );
- static void verbose_printf( struct ClassBase *, struct AnimInstData *, STRPTR, ... );
- static void error_printf( struct ClassBase *, struct AnimInstData *, STRPTR, ... );
- static void AttachSample( struct ClassBase *, struct AnimInstData * );
-
- static ULONG SaveIFFAnim( struct ClassBase *, struct IClass *, Object *, struct dtWrite * );
- static struct IFFHandle *CreateDOSIFFHandle( struct ClassBase *, BPTR );
- static LONG StartIFFAnim3( struct ClassBase *, struct AnimInstData *, struct IFFHandle *iff, struct AnimContext *, struct BitMapHeader *, ULONG, ULONG *, ULONG, ULONG, ULONG, struct BitMap * );
- static void EndIFFAnim3( struct ClassBase *, struct AnimInstData *, struct IFFHandle * );
- static LONG WriteIFFAnim3( struct ClassBase *, struct IFFHandle *, struct AnimContext *, ULONG, ULONG, struct BitMapHeader *, ULONG *, ULONG, struct BitMap * );
- static LONG PutAnim3Delta( struct ClassBase *, struct IFFHandle *, struct AnimContext *, struct BitMap *, struct BitMap * );
- static LONG PutILBMCMAP( struct ClassBase *, struct IFFHandle *, ULONG *, ULONG );
- static LONG PutILBMBody( struct ClassBase *, struct IFFHandle *, struct BitMap *, struct BitMapHeader * );
- static struct AnimContext *CreateAnimContext( struct ClassBase *, ULONG, ULONG, ULONG );
- static struct BitMap *PrevFrame( struct ClassBase *, struct AnimContext * );
- static void SwapFrames( struct ClassBase *, struct AnimContext * );
- static struct BitMap *CurrFrame( struct ClassBase *, struct AnimContext * );
- static void DeleteAnimContext( struct ClassBase *, struct AnimContext * );
-
-
- /*****************************************************************************/
-
- /* Create "anim.datatype" BOOPSI class */
- struct IClass *initClass( struct ClassBase *cb )
- {
- struct IClass *cl;
-
- /* Create our class... */
- if( cl = MakeClass( ANIMDTCLASS, ANIMATIONDTCLASS, NULL, (ULONG)sizeof( struct AnimInstData ), 0UL ) )
- {
- cl -> cl_Dispatcher . h_Entry = (HOOKFUNC)Dispatch;
- cl -> cl_UserData = (ULONG)cb;
-
- AddClass( cl );
- }
-
- return( cl );
- }
-
- /*****************************************************************************/
-
- struct MyStackSwapStruct
- {
- struct StackSwapStruct stk;
- struct IClass *cl;
- Object *o;
- Msg msg;
- };
-
- /*****************************************************************************/
-
- DISPATCHERFLAGS
- ULONG Dispatch( REGA0 struct IClass *cl, REGA2 Object *o, REGA1 Msg msg )
- {
- struct ClassBase *cb = (struct ClassBase *)(cl -> cl_UserData);
- ULONG retval;
- struct MyStackSwapStruct mystk;
- UBYTE *lower,
- *upper,
- *sp;
-
- #define DTSTACKSIZE (16384UL)
- while( !(lower = (UBYTE *)AllocMem( DTSTACKSIZE, MEMF_PUBLIC )) );
-
- sp = upper = lower + DTSTACKSIZE;
-
- mystk . stk . stk_Lower = lower;
- mystk . stk . stk_Upper = (ULONG)upper;
- mystk . stk . stk_Pointer = sp;
- mystk . cl = cl;
- mystk . o = o;
- mystk . msg = msg;
-
- retval = SwapMe( (&mystk) );
-
- FreeMem( lower, DTSTACKSIZE );
-
- return( retval );
- }
-
-
- DISPATCHERFLAGS
- ULONG SwapMe( REGA0 struct MyStackSwapStruct *mystk )
- {
- register ULONG retval;
-
- #define cb ((struct ClassBase *)(mystk -> cl -> cl_UserData))
-
- StackSwap( (&(mystk -> stk)) );
-
- retval = MyDispatch( mystk );
-
- StackSwap( (&(mystk -> stk)) );
-
- #undef cb
-
- return( retval );
- }
-
-
- /* class dispatcher */
- DISPATCHERFLAGS
- ULONG MyDispatch( REGA0 struct MyStackSwapStruct *mystk )
- {
- struct IClass *cl = mystk -> cl;
- Object *o = mystk -> o;
- Msg msg = mystk -> msg;
- struct ClassBase *cb = (struct ClassBase *)(cl -> cl_UserData);
- struct AnimInstData *aid;
- ULONG retval = 0UL;
-
- switch( msg -> MethodID )
- {
- /****** anim.datatype/OM_NEW *************************************************
- *
- * NAME
- * OM_NEW -- Create a anim.datatype object.
- *
- * FUNCTION
- * The OM_NEW method is used to create an instance of the anim.datatype
- * class. This method is passed to the superclass first. After this,
- * anim.datatype parses the prefs file and makes a scan through
- * the data to get index information. Frame bitmaps are loaded if the
- * input stream isn't seekable (e.g. IFF handle/clipboard),
- * colormaps and the first frame are loaded immediately.
- * If a sample was set in the prefs, it will be loaded and attached
- * to the animation.
- *
- * Subclasses of anim.datatype are not supported. Any attempt to
- * create a subclass object of anim.datatype will be rejected by this
- * method.
- *
- * ATTRIBUTES
- * The following attributes can be specified at creation time.
- *
- * DTA_SourceType (ULONG) -- Determinates the type of DTA_Handle
- * attribute. DTST_FILE, DTST_CLIPBOARD and DTST_RAM are supported.
- * If any other type was set in a given DTA_SourceType,
- * OM_NEW will be rejected.
- * A sourcetype of DTST_CLIPBOARD forces the LOADALL prefs
- * switch (can't seek on clipboard).
- * Defaults to DTST_FILE.
- *
- * DTA_Handle -- For both DTST_FILE and DTST_CLIPBOARD, a
- * (struct IFFHandle *) is expected. This handle will be
- * created by datatypesclass depeding on the DTF_#? flag, which
- * is DTF_IFF here. DTST_FILE, datatypesclass creates
- * a IFF handle from the given DTA_Name and DTA_Handle (a
- * BPTR returned by Lock), if DTST_CLIPBOARD, datatypesclass
- * passes the given (IFF) handle through.
- * A DTST_RAM (create empty object) source type requires a NULL
- * handle.
- *
- * RESULT
- * If the object was created a pointer to the object is returned,
- * otherwise NULL is returned.
- *
- ******************************************************************************
- *
- */
- case OM_NEW:
- {
- struct TagItem *ti;
-
- /* We only support DTST_FILE, DTST_CLIPBOARD or DTST_RAM as source type */
- if( ti = FindTagItem( DTA_SourceType, (((struct opSet *)msg) -> ops_AttrList) ) )
- {
- if( ((ti -> ti_Data) != DTST_FILE) &&
- ((ti -> ti_Data) != DTST_CLIPBOARD) &&
- ((ti -> ti_Data) != DTST_RAM) )
- {
- SetIoErr( ERROR_OBJECT_WRONG_TYPE );
-
- break;
- }
- }
-
- if( retval = DoSuperMethodA( cl, o, msg ) )
- {
- LONG error;
-
- /* Load frames... */
- if( error = LoadFrames( cb, (Object *)retval ) )
- {
- /* Something went fatally wrong, dispose object */
- CoerceMethod( cl, (Object *)retval, OM_DISPOSE );
- retval = 0UL;
- }
-
- SetIoErr( error );
- }
- }
- break;
-
- /****** anim.datatype/OM_DISPOSE *********************************************
- *
- * NAME
- * OM_DISPOSE -- Delete a anim.datatype object.
- *
- * FUNCTION
- * The OM_DISPOSE method is used to delete an instance of the
- * anim.datatype class. This method is passed to the superclass when
- * it has completed.
- * This method frees all frame nodes and their contents (bitmaps,
- * colormaps, samples etc.)
- *
- * RESULT
- * The object is deleted. 0UL is returned.
- *
- ******************************************************************************
- *
- */
- case OM_DISPOSE:
- {
- /* Get a pointer to our object data */
- aid = (struct AnimInstData *)INST_DATA( cl, o );
-
- /* Free colormaps etc. */
- FreeFrameNodeResources( cb, (&(aid -> aid_FrameList)) );
-
- /* Free our key bitmap */
- FreeBitMap( (aid -> aid_KeyBitMap) );
-
- /* Delete the frame pool */
- DeletePool( (aid -> aid_Pool) );
-
- /* Close input file */
- if( aid -> aid_FH )
- {
- Close( (aid -> aid_FH) );
- }
-
- /* Close verbose output file */
- if( aid -> aid_VerboseOutput )
- {
- Close( (aid -> aid_VerboseOutput) );
- }
-
- /* Dispose object */
- DoSuperMethodA( cl, o, msg );
- }
- break;
-
- case OM_UPDATE:
- {
- if( DoMethod( o, ICM_CHECKLOOP ) )
- {
- break;
- }
- }
- case OM_SET:
- {
- /* Pass the attributes to the animation class and force a refresh if we need it */
- if( retval = DoSuperMethodA( cl, o, msg ) )
- {
- /* Top instance ? */
- if( OCLASS( o ) == cl )
- {
- struct RastPort *rp;
-
- /* Get a pointer to the rastport */
- if( rp = ObtainGIRPort( (((struct opSet *)msg) -> ops_GInfo) ) )
- {
- struct gpRender gpr;
-
- /* Force a redraw */
- gpr . MethodID = GM_RENDER;
- gpr . gpr_GInfo = ((struct opSet *)msg) -> ops_GInfo;
- gpr . gpr_RPort = rp;
- gpr . gpr_Redraw = GREDRAW_UPDATE;
-
- DoMethodA( o, (Msg)(&gpr) );
-
- /* Release the temporary rastport */
- ReleaseGIRPort( rp );
-
- retval = 0UL;
- }
- }
- }
- }
- break;
-
- /****** anim.datatype/GM_LAYOUT *****************************************
- *
- * NAME
- * GM_LAYOUT -- Layout animation object
- * DTM_PROCLAYOUT -- Layout animation object on appliaction's
- * process
- *
- * FUNCTION
- * This method is passed to the superclass first.
- * Then it collects information from superclass, set up
- * struct DTSpecialInfo and send an OM_NOTIFY containing the following
- * attributes:
- * DTA_VisibleVert, (DTA_Domain -> Height)
- * DTA_TotalVert, (same as ADTA_Height)
- * DTA_NominalVert, (same as ADTA_Height)
- * DTA_VertUnit, 1UL,
- * DTA_VisibleHoriz, (DTA_Domain -> Width),
- * DTA_TotalHoriz, (same as ADTA_Width),
- * DTA_NominalHoriz, (same as ADTA_Width),
- * DTA_HorizUnit, 1UL,
- * GA_ID, (GadgetID),
- * DTA_Title, (same as DTA_ObjName, if missing, DTA_Name is
- * used),
- * DTA_Busy, FALSE,
- * DTA_Sync, TRUE
- *
- * RESULT
- * The value from the superclass is returned.
- *
- *******************************************************************************
- *
- */
- case GM_LAYOUT:
- case DTM_PROCLAYOUT:
- {
- /* Attributes obtained from super-class */
- struct IBox *domain;
- STRPTR name,
- objname;
-
- ULONG animwidth,
- animheight;
-
- /* Let the super-class partake */
- retval = DoSuperMethodA( cl, o, msg );
-
- /* Get all the attributes that we are going to need for a successful layout */
- if( GetDTAttrs( o,
- DTA_Domain, (&domain),
- DTA_Name, (&name),
- DTA_ObjName, (&objname),
- ADTA_Width, (&animwidth),
- ADTA_Height, (&animheight),
- TAG_DONE ) == 5UL )
- {
- struct DTSpecialInfo *si = (struct DTSpecialInfo *)(G( o ) -> SpecialInfo);
- STRPTR title;
- struct TagItem NotifyTags[ 13 ];
- struct opUpdate opu;
-
- /* Lock the global object data so that nobody else can manipulate it
- * (when modifying DTSpecialInfo and building the notify attributes)
- */
- ObtainSemaphore( (&(si -> si_Lock)) );
-
- /* Compute the lines and columns type information */
- si -> si_VertUnit = 1L;
- si -> si_VisVert = (LONG)(domain -> Height);
- si -> si_TotVert = (LONG)animheight;
-
- si -> si_HorizUnit = 1L;
- si -> si_VisHoriz = (LONG)(domain -> Width);
- si -> si_TotHoriz = (LONG)animwidth;
-
- /* Where should I get DTA_Title (from DTA_ObjName or DTA_Name) ? */
- title = ((objname)?(objname):(name));
-
- /* Build notify attrs */
- NotifyTags[ 0 ] . ti_Tag = DTA_VisibleVert;
- NotifyTags[ 0 ] . ti_Data = (si -> si_VisVert);
- NotifyTags[ 1 ] . ti_Tag = DTA_TotalVert;
- NotifyTags[ 1 ] . ti_Data = (si -> si_TotVert);
- NotifyTags[ 2 ] . ti_Tag = DTA_NominalVert;
- NotifyTags[ 2 ] . ti_Data = animheight;
- NotifyTags[ 3 ] . ti_Tag = DTA_VertUnit;
- NotifyTags[ 3 ] . ti_Data = (si -> si_VertUnit);
- NotifyTags[ 4 ] . ti_Tag = DTA_VisibleHoriz;
- NotifyTags[ 4 ] . ti_Data = (si -> si_VisHoriz);
- NotifyTags[ 5 ] . ti_Tag = DTA_TotalHoriz;
- NotifyTags[ 5 ] . ti_Data = (si -> si_TotHoriz);
- NotifyTags[ 6 ] . ti_Tag = DTA_NominalHoriz;
- NotifyTags[ 6 ] . ti_Data = animwidth;
- NotifyTags[ 7 ] . ti_Tag = DTA_HorizUnit;
- NotifyTags[ 7 ] . ti_Data = (ULONG)(si -> si_HorizUnit);
- NotifyTags[ 8 ] . ti_Tag = GA_ID;
- NotifyTags[ 8 ] . ti_Data = (ULONG)(G( o ) -> GadgetID);
- NotifyTags[ 9 ] . ti_Tag = DTA_Title;
- NotifyTags[ 9 ] . ti_Data = (ULONG)title;
- NotifyTags[ 10 ] . ti_Tag = DTA_Busy;
- NotifyTags[ 10 ] . ti_Data = (ULONG)FALSE;
- NotifyTags[ 11 ] . ti_Tag = DTA_Sync;
- NotifyTags[ 11 ] . ti_Data = (ULONG)TRUE;
- NotifyTags[ 12 ] . ti_Tag = TAG_DONE;
- NotifyTags[ 12 ] . ti_Data = 0UL;
-
- /* Release the global data lock */
- ReleaseSemaphore( (&(si -> si_Lock)) );
-
- /* Tell the world of our newest attributes */
- opu . MethodID = OM_NOTIFY;
- opu . opu_AttrList = NotifyTags;
- opu . opu_GInfo = ((struct gpLayout *)msg) -> gpl_GInfo;
- opu . opu_Flags = 0UL;
-
- DoMethodA( o, (Msg)(&opu) );
- }
- }
- break;
-
- /****** anim.datatype/DTM_FRAMEBOX ***************************************
- *
- * NAME
- * DTM_FRAMEBOX -- Set up object for a specified environment
- *
- * FUNCTION
- * The DTM_FRAMEBOX method is used to set up for a specified
- * environment. This method is passed to the superclass after
- * anim.datatype instance finished it's work.
- *
- * Only if FRAMEF_SPECIFY is set in (dtf -> dtf_FrameFlags), the
- * anim.datatype instance will modify the ADTA_Remap to FALSE if
- * the NOREMAP switch in the prefs file was set and the animation
- * depth matches the given (frameinfo -> fri_Screen -> BitMap . Depth)
- * depth.
- *
- * RESULT
- * The value from the superclass is returned.
- *
- * SEE ALSO
- * 3.1_Examples2:DataTypes/Src/ClipView/clipview.c
- *
- ******************************************************************************
- *
- */
- case DTM_FRAMEBOX:
- {
- struct dtFrameBox *dtf;
-
- aid = (struct AnimInstData *)INST_DATA( cl, o );
- dtf = (struct dtFrameBox *)msg;
-
- /* Make do with the dimensions of FrameBox provided ? */
- if( (dtf -> dtf_FrameFlags) & FRAMEF_SPECIFY )
- {
- /* NOREMAP switch set ? */
- if( aid -> aid_NoRemap )
- {
- ULONG depth;
-
- /* Get animation depth */
- if( GetDTAttrs( o, ADTA_Depth, (&depth), TAG_DONE ) == 1UL )
- {
- /* Match ? */
- if( depth == (dtf -> dtf_ContentsInfo -> fri_Dimensions . Depth) )
- {
- SetAttrs( o, ADTA_Remap, FALSE, TAG_DONE );
- }
- }
- }
- }
-
- retval = DoSuperMethodA( cl, o, msg );
- }
- break;
-
- /****** anim.datatype/DTM_WRITE **********************************************
- *
- * NAME
- * DTM_WRITE -- Save data
- *
- * FUNCTION
- * This method saves the object's contents to disk.
- *
- * If dtw_Mode is DTWM_IFF, the method is passed unchanged to the
- * superclass, animation.datatype, which writes a single IFF ILBM
- * picture.
- *
- * If dtw_mode is DTWM_RAW, the object saved an IFF ANIM stream to
- * the filehandle given, starting with the current frame until
- * the end is reached.
- * The sequence saved can be controlled by the ADTA_Frame, ADTA_Frames
- * and ADTA_FrameIncrement attributes (see TAGS section below).
- *
- * TAGS
- * When writing the local ("raw") format, IFF ANIM, the following
- * attributes are recognized:
- *
- * ADTA_Frame (ULONG) - start frame, saving starts here.
- * Defaults to the current frame displayed.
- *
- * ADTA_Frames (ULONG) - the number of frames to be saved,
- * Defaults to (max_num_of_frames - curr_frame).
- *
- * ADTA_FrameIncrement (ULONG) - frame increment when saving.
- * Defaults to 1, which means: "jump to next frame".
- *
- * NOTE
- * - Any sound attached to the animation will NOT be saved.
- *
- * - A CTRL-D signal to the writing process aborts the save.
- *
- * RESULT
- * Returns 0 for failure (IoErr() returns result2), non-zero
- * for success.
- *
- ******************************************************************************
- *
- */
- case DTM_WRITE:
- {
- struct dtWrite *dtw;
-
- dtw = (struct dtWrite *)msg;
-
- /* Local data format not supported yet... */
- if( (dtw -> dtw_Mode) == DTWM_RAW )
- {
- retval = SaveIFFAnim( cb, cl, o, dtw );
- }
- else
- {
- /* Pass msg to superclass (which writes a single frame as an IFF ILBM picture)... */
- retval = DoSuperMethodA( cl, o, msg );
- }
- }
- break;
-
-
- /****** anim.datatype/ADTM_LOADFRAME *****************************************
- *
- * NAME
- * ADTM_LOADFRAME -- Load frame
- *
- * FUNCTION
- * The ADTM_LOADFRAME method is used to obtain the bitmap and timing
- * data of the animation.
- * The given timestamp will be used to find a matching timestamp
- * in the internal FrameNode list. If it was found, the corresponding
- * timing, bitmap and colormap data are stored into the struct
- * adtFrame. If the bitmap wasn't loaded, this method attempts to
- * load it from disk.
- *
- * RESULT
- * Returns always non-zero,
- * the bitmap ptr if a bitmap was found,
- * 1UL otherwise.
- *
- ******************************************************************************
- *
- */
- case ADTM_LOADFRAME:
- {
- struct FrameNode *fn;
- struct adtFrame *alf;
-
- aid = (struct AnimInstData *)INST_DATA( cl, o );
- alf = (struct adtFrame *)msg;
-
- ObtainSemaphore( (&(aid -> aid_SigSem)) );
-
- /* Find frame by timestamp */
- if( fn = FindFrameNode( (&(aid -> aid_FrameList)), (alf -> alf_TimeStamp) ) )
- {
- /* Load bitmaps only if we don't cache the whole anim and
- * if we have a filehandle to load from (an empty object created using DTST_RAM)...
- */
- if( (aid -> aid_LoadAll) == FALSE && (aid -> aid_FH) )
- {
- /* If no bitmap is loaded, load it... */
- if( (fn -> fn_BitMap) == NULL )
- {
- if( fn -> fn_BitMap = AllocBitMapPooled( cb, (ULONG)(aid -> aid_BMH -> bmh_Width), (ULONG)(aid -> aid_BMH -> bmh_Height), (ULONG)(aid -> aid_BMH -> bmh_Depth), (aid -> aid_Pool) ) )
- {
- struct FrameNode *worknode = fn;
- ULONG rollback = 0UL;
-
- #ifdef DEBUG_ALF
- verbose_printf( cb, aid, "frame %lu ", (fn -> fn_TimeStamp) );
- #endif /* DEBUG_ALF */
-
- do
- {
- worknode = GetPrevFrameNode( worknode, (ULONG)(worknode -> fn_AH . ah_Interleave) );
-
- rollback++;
-
- #ifdef DEBUG_ALF
- verbose_printf( cb, aid, "r %lu ", (worknode -> fn_TimeStamp) );
- #endif /* DEBUG_ALF */
- } while( ((worknode -> fn_BitMap) == NULL) && ((worknode -> fn_TimeStamp) != 0UL) );
-
- #ifdef DEBUG_ALF
- verbose_printf( cb, aid, "rollback %lu ", rollback );
- #endif /* DEBUG_ALF */
-
- if( ((worknode -> fn_BitMap) == NULL) && ((worknode -> fn_TimeStamp) == 0UL) )
- {
- verbose_printf( cb, aid, "first frame without bitmap ... !\n" );
- ClearBitMap( (fn -> fn_BitMap) );
- }
-
- #ifdef DEBUG_ALF
- verbose_printf( cb, aid, "l " );
- #endif /* DEBUG_ALF */
-
- do
- {
- ULONG current = rollback;
-
- worknode = fn;
-
- while( current-- )
- {
- worknode = GetPrevFrameNode( worknode, (ULONG)(worknode -> fn_AH . ah_Interleave) );
- }
-
- #ifdef DEBUG_ALF
- verbose_printf( cb, aid, "%lu:%lu ", rollback, (worknode -> fn_TimeStamp) );
- #endif /* DEBUG_ALF */
-
- if( (worknode -> fn_BitMap) && (worknode != fn) )
- {
- #ifdef DEBUG_ALF
- verbose_printf( cb, aid, "CP " );
- #endif /* DEBUG_ALF */
-
- CopyBitMap( cb, (fn -> fn_BitMap), (worknode -> fn_BitMap) );
- }
- else
- {
- #ifdef DEBUG_ALF
- verbose_printf( cb, aid, "LO " );
- #endif /* DEBUG_ALF */
-
- if( Seek( (aid -> aid_FH), (((worknode -> fn_BMOffset) + 8UL) - (aid -> aid_CurrFilePos)), OFFSET_CURRENT ) != (-1L) )
- {
- UBYTE *buff;
-
- if( buff = (UBYTE *)AllocVec( ((worknode -> fn_BMSize) + 16UL), MEMF_PUBLIC ) )
- {
- if( Read( (aid -> aid_FH), buff, (worknode -> fn_BMSize) ) == (worknode -> fn_BMSize) )
- {
- LONG error;
-
- if( error = DrawDLTA( cb, aid, (fn -> fn_BitMap), (fn -> fn_BitMap), (&(worknode -> fn_AH)), buff, (worknode -> fn_BMSize) ) )
- {
- error_printf( cb, aid, "dlta unpacking error %lu\n", error );
- }
-
- /* Bump file pos */
- aid -> aid_CurrFilePos = ((worknode -> fn_BMOffset) + 8UL) + (worknode -> fn_BMSize);
- }
- else
- {
- error_printf( cb, aid, "ADTM_LOADFRAME: read error %ld\n", IoErr() );
-
- /* Error, rewind stream */
- Seek( (aid -> aid_FH), 0L, OFFSET_BEGINNING );
- aid -> aid_CurrFilePos = 0L;
- }
-
- FreeVec( buff );
- }
- }
- else
- {
- error_printf( cb, aid, "ADTM_LOADFRAME: seek error %ld\n", IoErr() );
- }
- }
- } while( rollback-- );
-
- #ifdef DEBUG_ALF
- verbose_printf( cb, aid, ".\n" );
- #endif /* DEBUG_ALF */
- }
- else
- {
- error_printf( cb, aid, "ADTM_LOADFRAME: can't alloc load bitmap\n" );
- }
- }
- }
-
- /* Store frame/context information */
- alf -> alf_Frame = fn -> fn_Frame;
- alf -> alf_UserData = (APTR)fn; /* Links back to this FrameNode (used by ADTM_UNLOADFRAME) */
-
- /* Store bitmap information */
- alf -> alf_BitMap = fn -> fn_BitMap;
- alf -> alf_CMap = fn -> fn_CMap;
-
- /* Is there a sample to play ? */
- if( fn -> fn_Sample )
- {
- /* Store sound information */
- alf -> alf_Sample = fn -> fn_Sample;
- alf -> alf_SampleLength = fn -> fn_SampleLength;
- alf -> alf_Period = fn -> fn_Period;
- }
- else
- {
- /* No sound */
- alf -> alf_Sample = NULL;
- alf -> alf_SampleLength = 0UL;
- alf -> alf_Period = 0UL;
- }
-
- /* Frame "in use" */
- fn -> fn_UseCount++;
-
- /* Return bitmap ptr of possible, 1UL otherwise */
- retval = (alf -> alf_BitMap)?((ULONG)(alf -> alf_BitMap)):(1UL);
- }
- else
- {
- /* no matching frame found */
- retval = 1UL;
- }
-
- ReleaseSemaphore( (&(aid -> aid_SigSem)) );
- }
- break;
-
- /****** anim.datatype/ADTM_UNLOADFRAME ***************************************
- *
- * NAME
- * ADTM_UNLOADFRAME -- Load frame contents
- *
- * FUNCTION
- * The ADTM_UNLOADFRAME method is used to release the contents of a
- * animation frame.
- *
- * This method frees the bitmap data found in adtFrame.
- *
- * RESULT
- * Returns always 0UL.
- *
- ******************************************************************************
- *
- */
- case ADTM_UNLOADFRAME:
- {
- struct FrameNode *fn;
- struct adtFrame *alf;
-
- aid = (struct AnimInstData *)INST_DATA( cl, o );
- alf = (struct adtFrame *)msg;
-
- /* Free bitmaps only if we don't cache the whole anim */
- if( (aid -> aid_LoadAll) == FALSE )
- {
- ObtainSemaphore( (&(aid -> aid_SigSem)) );
-
- if( fn = (struct FrameNode *)(alf -> alf_UserData) )
- {
- if( (fn -> fn_UseCount) > 0 )
- {
- fn -> fn_UseCount--;
-
- /* Free an existing bitmap if it isn't in use and if it is NOT the first bitmap */
- if( ((fn -> fn_UseCount) == 0) && (fn -> fn_BitMap) && (fn != (struct FrameNode *)(aid -> aid_FrameList . mlh_Head)) )
- {
- FreeVecPooled( cb, (aid -> aid_Pool), (fn -> fn_BitMap) );
- fn -> fn_BitMap = NULL;
- }
- }
- }
-
- ReleaseSemaphore( (&(aid -> aid_SigSem)) );
- }
- }
- break;
-
- /* Let the superclass handle everything else */
- default:
- {
- retval = DoSuperMethodA( cl, o, msg );
- }
- break;
- }
-
- return( retval );
- }
-
-
- /****** anim.datatype/preferences ********************************************
- *
- * NAME
- * preferences
- *
- * DESCRIPTION
- * The "ENV:Classes/DataTypes/anim.prefs" file contains global
- * settings for the datatype.
- * The preferences file is an ASCII file containing one line where the
- * preferences can be set.
- * It can be superset by a local variable with the same name.
- *
- * Each line can contain settings, special settings for some projects
- * can be set using the MATCHPROJECT option.
- * Lines beginning with a '#' or ';' chars are treated as comments.
- * Lines are limitted to 256 chars.
- *
- * TEMPLATE
- * MATCHPROJECT/K,MODEID/K/N,NOCMAPS/S,NOREMAP/S,FPS/K/N,SAMPLE/K,
- * VOLUME/K/N,LOADALL/S,VERBOSE/S
- *
- * MATCHPROJECT -- The settings in this line belongs only to this
- * project(s), e.g. if the case-insensitive pattern does not match,
- * this line is ignored.
- * The maximum length of the pattern is 128 chars.
- * Defaults to #?, which matches any project.
- *
- * MODEID -- Select screen mode id of datatype (will be stored in
- * ADTA_ModeID). Note that the DOS ReadArgs function used for parsing
- * fetches a SIGNED long. The bit 31 will be represented by minus
- * '-'. (example: "MODEID=266240" sets the mode to the A2024 screen
- * mode id)
- * Defaults to 0, which means: Use the screen mode from CAMG chunk,
- * if missing use the best screenmode available for the given width,
- * height and depth.
- *
- * NOCMAPS -- Don't load/use colormaps per frame. Only the initial
- * colormap will be used.
- * The current version of animation.datatype (V40.7 (28.09.93)) does
- * not implement per frame colormaps, it's output may look trashed.
- * Custom players like "DBufDTAnim" does support
- * "per frame colormaps",
- * animation.datatype V41 will implement "per frame colormaps".
- *
- * FPS -- Frames Per Second
- * Defaults to FPS set by DPAN chunk. If the DPAN chunk is missing
- * a fixed 5 fps rate is used.
- * A value of 0 here means: Use default FPS.
- *
- * SAMPLE -- Attach the given sample to the animation. The sample will
- * be loaded using datatypes (GID_SOUND).
- * Only one sample can be attached to one animationstream, any
- * following attempt to attach a sample will be ignored.
- *
- * VOLUME -- Volume of the sound when playing.
- * Defaults to 64, which is the maximum. A value greater than 64 will
- * be set to 64.
- *
- * LOADALL -- Load all frames into memory. If the source input is a
- * clipboard, this option is always set.
- *
- * VERBOSE -- Print information about the animation. Currently
- * the frame numbers and the used compression are printed, after all
- * number of scanned/loaded frames, set FPS rate, dimensions (width/
- * height/depth), sample information etc.
- *
- * NOTE
- * An invalid prefs file line will be ignored and forces the VERBOSE
- * output.
- *
- * BUGS
- * - Low memory may cause that the prefs file won't be parsed.
- *
- * - Lines are limitted to 256 chars
- *
- * - An invalid prefs file line will be ignored.
- *
- * - The sample path length is limitted to 200 chars. A larger
- * value may crash the machine if an error occurs.
- *
- ******************************************************************************
- *
- */
-
-
- static
- STRPTR GetPrefsVar( struct ClassBase *cb, STRPTR name )
- {
- STRPTR buff;
- const ULONG buffsize = 16UL;
-
- if( buff = (STRPTR)AllocVec( (buffsize + 2UL), (MEMF_PUBLIC | MEMF_CLEAR) ) )
- {
- if( GetVar( name, buff, buffsize, GVF_BINARY_VAR ) != (-1L) )
- {
- ULONG varsize = IoErr();
-
- varsize += 2UL;
-
- if( varsize > buffsize )
- {
- FreeVec( buff );
-
- if( buff = (STRPTR)AllocVec( (varsize + 2UL), (MEMF_PUBLIC | MEMF_CLEAR) ) )
- {
- if( GetVar( name, buff, varsize, GVF_BINARY_VAR ) != (-1L) )
- {
- return( buff );
- }
- }
- }
- else
- {
- return( buff );
- }
- }
-
- FreeVec( buff );
- }
-
- return( NULL );
- }
-
-
- static
- BOOL matchstr( struct ClassBase *cb, STRPTR pat, STRPTR s )
- {
- TEXT buff[ 512 ];
-
- if( pat && s )
- {
- if( ParsePatternNoCase( pat, buff, (sizeof( buff ) - 1) ) != (-1L) )
- {
- if( MatchPatternNoCase( buff, s ) )
- {
- return( TRUE );
- }
- }
- }
-
- return( FALSE );
- }
-
-
- static
- void ReadENVPrefs( struct ClassBase *cb, struct AnimInstData *aid )
- {
- struct RDArgs envvarrda =
- {
- NULL,
- 256L,
- 0L,
- 0L,
- NULL,
- 0L,
- NULL,
- RDAF_NOPROMPT
- };
-
- struct
- {
- STRPTR matchproject;
- long *modeid;
- long *nocmaps;
- long *noremap;
- long *fps;
- STRPTR sample;
- long *volume;
- long *loadall;
- long *verbose;
- } animargs;
-
- TEXT varbuff[ 258 ];
- STRPTR var;
-
- if( var = GetPrefsVar( cb, "Classes/DataTypes/anim.prefs" ) )
- {
- STRPTR prefsline = var,
- nextprefsline;
- ULONG linecount = 1UL;
-
- /* Be sure that "var" contains at least one break-char */
- strcat( var, "\n" );
-
- while( nextprefsline = strpbrk( prefsline, "\n" ) )
- {
- stccpy( varbuff, prefsline, MIN( (sizeof( varbuff ) - 2UL), (((ULONG)(nextprefsline - prefsline)) + 1UL) ) );
-
- /* be sure that this line isn't a comment line or an empty line */
- if( (varbuff[ 0 ] != '#') && (varbuff[ 0 ] != ';') && (varbuff[ 0 ] != '\n') && (strlen( varbuff ) > 2UL) )
- {
- /* Prepare ReadArgs processing */
- strcat( varbuff, "\n" ); /* Add NEWLINE-char */
- envvarrda . RDA_Source . CS_Buffer = varbuff; /* Buffer */
- envvarrda . RDA_Source . CS_Length = strlen( varbuff ) + 1UL; /* Set up input buffer length */
- envvarrda . RDA_Source . CS_CurChr = 0L;
- envvarrda . RDA_Buffer = NULL;
- envvarrda . RDA_BufSiz = 0L;
- memset( (void *)(&animargs), 0, sizeof( animargs ) ); /* Clear result array */
-
- if( ReadArgs( "MATCHPROJECT/K,"
- "MODEID/K/N,"
- "NOCMAPS/S,"
- "NOREMAP/S,"
- "FPS/K/N,"
- "SAMPLE/K,"
- "VOLUME/K/N,"
- "LOADALL/S,"
- "VERBOSE/S", (LONG *)(&animargs), (&envvarrda) ) )
- {
- BOOL noignore = TRUE;
-
- if( (animargs . matchproject) && (aid -> aid_ProjectName) )
- {
- noignore = matchstr( cb, (animargs . matchproject), (aid -> aid_ProjectName) );
- }
-
- if( noignore )
- {
- if( animargs . verbose )
- {
- OpenLogfile( cb, aid );
- }
-
- if( animargs . modeid )
- {
- aid -> aid_ModeID = *(animargs . modeid);
- }
-
- if( animargs . nocmaps )
- {
- aid -> aid_NoCMAPs = TRUE;
- }
-
- if( animargs . noremap )
- {
- aid -> aid_NoRemap = TRUE;
- }
-
- if( animargs . fps )
- {
- aid -> aid_FPS = *(animargs . fps);
- }
-
- if( animargs . loadall )
- {
- aid -> aid_LoadAll = TRUE;
- }
-
- if( (animargs . sample) && ((aid -> aid_Sample) == NULL) )
- {
- Object *so;
- LONG ioerr = 0L;
-
- verbose_printf( cb, aid, "loading sample \"%s\"...\n", (animargs . sample) );
-
- if( so = NewDTObject( (animargs . sample), DTA_GroupID, GID_SOUND, TAG_DONE ) )
- {
- BYTE *sample;
- ULONG length;
- ULONG period;
-
- /* Get sample data from object */
- if( GetDTAttrs( so, SDTA_Sample, (&sample),
- SDTA_SampleLength, (&length),
- SDTA_Period, (&period),
- TAG_DONE ) == 3UL )
- {
- if( aid -> aid_Sample = (STRPTR)AllocPooled( (aid -> aid_Pool), (length + 1UL) ) )
- {
- /* Copy sample and context */
- CopyMem( (APTR)sample, (APTR)(aid -> aid_Sample), length );
- aid -> aid_SampleLength = length;
- aid -> aid_Period = period;
- }
- else
- {
- /* Can't alloc sample */
- ioerr = ERROR_NO_FREE_STORE;
- }
- }
- else
- {
- /* Object does not support the requested attributes */
- ioerr = ERROR_OBJECT_WRONG_TYPE;
- }
-
- DisposeDTObject( so );
- }
- else
- {
- /* NewDTObjectA failed, cannot load sample... */
- ioerr = IoErr();
- }
-
- if( (aid -> aid_Sample) == NULL )
- {
- TEXT errbuff[ 256 ];
-
- if( ioerr >= DTERROR_UNKNOWN_DATATYPE )
- {
- mysprintf( cb, errbuff, GetDTString( ioerr ), (animargs . sample) );
- }
- else
- {
- Fault( ioerr, (animargs . sample), errbuff, sizeof( errbuff ) );
- }
-
- error_printf( cb, aid, "can't load sample: \"%s\" line %lu\n", errbuff, linecount );
- }
- }
-
- if( animargs . volume )
- {
- aid -> aid_Volume = *(animargs . volume);
-
- if( (aid -> aid_Volume) > 64UL )
- {
- aid -> aid_Volume = 64UL;
- }
- }
- }
- else
- {
- verbose_printf( cb, aid, "prefs line %lu ignored\n", linecount );
- }
-
- FreeArgs( (&envvarrda) );
- }
- else
- {
- LONG ioerr = IoErr();
- TEXT errbuff[ 256 ];
-
- Fault( ioerr, "Classes/DataTypes/anim.prefs", errbuff, (LONG)sizeof( errbuff ) );
-
- error_printf( cb, aid, "preferences \"%s\" line %lu\n", errbuff, linecount );
- }
- }
-
- prefsline = ++nextprefsline;
- linecount++;
- }
-
- FreeVec( var );
- }
- }
-
-
- static
- LONG LoadFrames( struct ClassBase *cb, Object *o )
- {
- struct AnimInstData *aid = (struct AnimInstData *)INST_DATA( (cb -> cb_Lib . cl_Class), o );
- LONG error = 0L;
-
- InitSemaphore( (&(aid -> aid_SigSem)) );
- NewList( (struct List *)(&(aid -> aid_FrameList)) );
-
- /* Create a memory pool for frame nodes */
- if( aid -> aid_Pool = CreatePool( MEMF_PUBLIC, 16384UL, 16384UL ) )
- {
- APTR fh; /* handle (IFF stream handle) */
- ULONG sourcetype; /* type of stream (either DTST_FILE or DTST_CLIPBOARD */
- ULONG pos = 0UL; /* current file pos in IFF stream */
- struct BitMapHeader *bmh; /* obj's bitmapheader */
- ULONG modeid = 0UL; /* anim view mode */
- ULONG animwidth = 0UL, /* anim width */
- animheight = 0UL, /* anim height */
- animdepth = 0UL; /* anim depth */
- ULONG timestamp = 0UL; /* timestamp */
-
- /* Prefs defaults */
- aid -> aid_Volume = 64UL;
-
- /* Read prefs */
- ReadENVPrefs( cb, aid );
-
- /* Get file handle, handle type and BitMapHeader */
- if( GetDTAttrs( o, DTA_SourceType, (&sourcetype),
- DTA_Handle, (&fh),
- DTA_Name, (&(aid -> aid_ProjectName)),
- PDTA_BitMapHeader, (&bmh),
- TAG_DONE ) == 4UL )
- {
- struct IFFHandle *iff = NULL;
-
- aid -> aid_BMH = bmh; /* Store BitMapHeader */
-
- switch( sourcetype )
- {
- case DTST_CLIPBOARD:
- {
- aid -> aid_LoadAll = TRUE;
-
- iff = (struct IFFHandle *)fh;
- }
- break;
-
- case DTST_FILE:
- {
- BPTR iff_file_fh;
-
- iff = (struct IFFHandle *)fh;
-
- /* Attempt to open file from given stream (allows usage of virtual fs when using datatypes.library V45) */
- iff_file_fh = (BPTR)(iff -> iff_Stream); /* see iffparse.library/InitIFFasDOS autodoc */
-
- if( iff_file_fh )
- {
- BPTR lock;
-
- if( lock = DupLockFromFH( iff_file_fh ) )
- {
- /* Set up a filehandle for disk-based loading (random loading) */
- if( !(aid -> aid_FH = (LONG)OpenFromLock( lock )) )
- {
- /* failure */
- UnLock( lock );
- }
- }
- }
-
- /* OpenFromLock failed ? - Then open by name :-( */
- if( (aid -> aid_FH) == NULL )
- {
- /* Set up a filehandle for disk-based loading (random loading) */
- if( !(aid -> aid_FH = (LONG)Open( (aid -> aid_ProjectName), MODE_OLDFILE )) )
- {
- /* Can't open file */
- error = IoErr();
- }
- }
- }
- break;
-
- case DTST_RAM:
- {
- /* do nothing */
- }
- break;
-
- default:
- {
- /* unsupported source type */
- error = ERROR_NOT_IMPLEMENTED;
- }
- break;
- }
-
- /* Any error ? */
- if( error == 0L )
- {
- if( iff )
- {
- struct StoredProperty *bmhdprop = NULL, /* ILBM BMHD (struct BitMapHeader) */
- *camgprop = NULL, /* ILBM CAMG (amiga view mode id) */
- *dpanprop = NULL, /* DPaint DPAN chunk */
- *annoprop = NULL, /* Generic IFF ANNO (annotation) chunk */
- *authprop = NULL, /* Generic IFF AUTH (author) chunk */
- *copyrightprop = NULL, /* Generic IFF (C) (copyright) chunk */
- *fverprop = NULL, /* Generic IFF FVER (version) chunk */
- *nameprop = NULL; /* Generic IFF NAME (name) chunk */
-
- #define NUM_PROPCHUNKS (8L)
- const
- LONG propchunks[ (NUM_PROPCHUNKS * 2) ] =
- {
- ID_ILBM, ID_BMHD,
- ID_ILBM, ID_CAMG,
- ID_ILBM, ID_DPAN,
- ID_ILBM, ID_ANNO,
- ID_ILBM, ID_AUTH,
- ID_ILBM, ID_Copyright,
- ID_ILBM, ID_FVER,
- ID_ILBM, ID_NAME
- };
-
- if( !(error = PropChunks( iff, (LONG *)propchunks, NUM_PROPCHUNKS )) )
- {
- #define NUM_STOPCHUNKS (4L)
- const
- LONG stopchunks[ (NUM_STOPCHUNKS * 2) ] =
- {
- ID_ILBM, ID_ANHD,
- ID_ILBM, ID_CMAP,
- ID_ILBM, ID_BODY,
- ID_ILBM, ID_DLTA
- };
-
- if( !(error = StopChunks( iff, (LONG *)stopchunks, NUM_STOPCHUNKS )) )
- {
- struct FrameNode *fn = NULL;
- ULONG numcmaps = 0UL; /* number of created cmaps */
-
- /* Scan IFF stream until an error or an EOF occurs */
- for( ;; )
- {
- struct ContextNode *cn;
-
- if( error = ParseIFF( iff, IFFPARSE_SCAN ) )
- {
- /* EOF (End Of File) is no error here... */
- if( error == IFFERR_EOF )
- {
- error = 0L;
- }
-
- break;
- }
-
- /* Get file position */
- if( cn = CurrentChunk( iff ) )
- {
- pos = 0UL;
-
- while( cn = ParentChunk( cn ) )
- {
- pos += cn -> cn_Scan;
- }
- }
-
- /* bmhd header loaded ? */
- if( bmhdprop == NULL )
- {
- if( bmhdprop = FindProp( iff, ID_ILBM, ID_BMHD ) )
- {
- *bmh = *((struct BitMapHeader *)(bmhdprop -> sp_Data));
-
- animwidth = bmh -> bmh_Width;
- animheight = bmh -> bmh_Height;
- animdepth = bmh -> bmh_Depth;
- }
- }
-
- /* camg loaded ? */
- if( camgprop == NULL )
- {
- if( camgprop = FindProp( iff, ID_ILBM, ID_CAMG ) )
- {
- modeid = *(ULONG *)(camgprop -> sp_Data);
- }
- }
-
- /* dpan loaded ? */
- if( dpanprop == NULL )
- {
- if( dpanprop = FindProp( iff, ID_ILBM, ID_DPAN ) )
- {
- if( (aid -> aid_FPS) == 0UL )
- {
- struct DPAnimChunk *dpan = (struct DPAnimChunk *)(dpanprop -> sp_Data);
-
- aid -> aid_FPS = dpan -> dpan_FPS;
-
- verbose_printf( cb, aid, "DPAN found, FPS set to %lu\n", (aid -> aid_FPS) );
- }
- }
- }
-
- if( annoprop == NULL )
- {
- /* IFF ANNO found ? */
- if( annoprop = FindProp( iff, ID_ILBM, ID_ANNO ) )
- {
- STRPTR buff;
-
- /* Allocate a temp buffer so that stccpy can add a '\0'-terminator */
- if( buff = (STRPTR)AllocVec( ((annoprop -> sp_Size) + 2UL), MEMF_ANY ) )
- {
- stccpy( buff, (annoprop -> sp_Data), (int)(annoprop -> sp_Size) );
-
- verbose_printf( cb, aid, "ANNO annotation: \"%s\"\n", buff );
-
- SetDTAttrs( o, NULL, NULL, DTA_ObjAnnotation, buff, TAG_DONE );
-
- FreeVec( buff );
- }
- else
- {
- /* no temp. buffer */
- error = ERROR_NO_FREE_STORE;
- }
- }
- }
-
- if( authprop == NULL )
- {
- /* IFF AUTH found ? */
- if( authprop = FindProp( iff, ID_ILBM, ID_AUTH ) )
- {
- STRPTR buff;
-
- /* Allocate a temp buffer so that stccpy can add a '\0'-terminator */
- if( buff = (STRPTR)AllocVec( ((authprop -> sp_Size) + 2UL), MEMF_ANY ) )
- {
- stccpy( buff, (authprop -> sp_Data), (int)(authprop -> sp_Size) );
-
- verbose_printf( cb, aid, "AUTH author: \"%s\"\n", buff );
-
- SetDTAttrs( o, NULL, NULL, DTA_ObjAuthor, buff, TAG_DONE );
-
- FreeVec( buff );
- }
- else
- {
- /* no temp. buffer */
- error = ERROR_NO_FREE_STORE;
- }
- }
- }
-
- if( copyrightprop == NULL )
- {
- /* IFF (C) found ? */
- if( copyrightprop = FindProp( iff, ID_ILBM, ID_Copyright ) )
- {
- STRPTR buff;
-
- /* Allocate a temp buffer so that stccpy can add a '\0'-terminator */
- if( buff = (STRPTR)AllocVec( ((copyrightprop -> sp_Size) + 2UL), MEMF_ANY ) )
- {
- stccpy( buff, (copyrightprop -> sp_Data), (int)(copyrightprop -> sp_Size) );
-
- verbose_printf( cb, aid, "(C) copyright: \"%s\"\n", buff );
-
- SetDTAttrs( o, NULL, NULL, DTA_ObjCopyright, buff, TAG_DONE );
-
- FreeVec( buff );
- }
- else
- {
- /* no temp. buffer */
- error = ERROR_NO_FREE_STORE;
- }
- }
- }
-
- if( fverprop == NULL )
- {
- /* IFF FVER found ? */
- if( fverprop = FindProp( iff, ID_ILBM, ID_FVER ) )
- {
- STRPTR buff;
-
- /* Allocate a temp buffer so that stccpy can add a '\0'-terminator */
- if( buff = (STRPTR)AllocVec( ((fverprop -> sp_Size) + 2UL), MEMF_ANY ) )
- {
- stccpy( buff, (fverprop -> sp_Data), (int)(fverprop -> sp_Size) );
-
- verbose_printf( cb, aid, "FVER version: \"%s\"\n", buff );
-
- SetDTAttrs( o, NULL, NULL, DTA_ObjVersion, buff, TAG_DONE );
-
- FreeVec( buff );
- }
- else
- {
- /* no temp. buffer */
- error = ERROR_NO_FREE_STORE;
- }
- }
- }
-
- if( nameprop == NULL )
- {
- /* IFF NAME found ? */
- if( nameprop = FindProp( iff, ID_ILBM, ID_NAME ) )
- {
- STRPTR buff;
-
- /* Allocate a temp buffer so that stccpy can add a '\0'-terminator */
- if( buff = (STRPTR)AllocVec( ((nameprop -> sp_Size) + 2UL), MEMF_ANY ) )
- {
- stccpy( buff, (nameprop -> sp_Data), (int)(nameprop -> sp_Size) );
-
- verbose_printf( cb, aid, "NAME name: \"%s\"\n", buff );
-
- SetDTAttrs( o, NULL, NULL, DTA_ObjName, buff, TAG_DONE );
-
- FreeVec( buff );
- }
- else
- {
- /* no temp. buffer */
- error = ERROR_NO_FREE_STORE;
- }
- }
- }
-
- if( cn = CurrentChunk( iff ) )
- {
- switch( (cn -> cn_Type) )
- {
- case ID_ILBM:
- {
- switch( (cn -> cn_ID) )
- {
- case ID_ANHD:
- {
- /* Create an prepare a new frame node */
- if( fn = AllocFrameNode( cb, (aid -> aid_Pool) ) )
- {
- AddTail( (struct List *)(&(aid -> aid_FrameList)), (struct Node *)(&(fn -> fn_Node)) );
-
- fn -> fn_TimeStamp = timestamp++;
- fn -> fn_Frame = fn -> fn_TimeStamp;
-
- /* Read struct AnimHeader */
- error = ReadChunkBytes( iff, (&(fn -> fn_AH)), (LONG)sizeof( struct AnimHeader ) );
- if( error == (LONG)sizeof( struct AnimHeader ) ) error = 0L;
-
- DumpAnimHeader( cb, aid, (fn -> fn_TimeStamp), (&(fn -> fn_AH)) );
- }
- else
- {
- /* can't alloc frame node */
- error = ERROR_NO_FREE_STORE;
- }
- }
- break;
-
- case ID_CMAP:
- {
- if( fn == NULL )
- {
- /* First frame in animation ?
- * (the first frame in an animation may not have an AnimHeader,
- * therefore we're creating an empty FrameNode,
- * (ah_Operation == acmpILBM), e.g. 0)
- */
- if( timestamp == 0UL )
- {
- /* Create an prepare a new frame node */
- if( fn = AllocFrameNode( cb, (aid -> aid_Pool) ) )
- {
- AddTail( (struct List *)(&(aid -> aid_FrameList)), (struct Node *)(&(fn -> fn_Node)) );
-
- fn -> fn_TimeStamp = timestamp++;
- fn -> fn_Frame = fn -> fn_TimeStamp;
-
- DumpAnimHeader( cb, aid, (fn -> fn_TimeStamp), (&(fn -> fn_AH)) );
- }
- else
- {
- /* can't alloc frame node */
- error = ERROR_NO_FREE_STORE;
- }
- }
- }
-
- if( fn )
- {
- UBYTE *buff;
-
- /* Allocate buffer */
- if( buff = (UBYTE *)AllocVecPooled( cb, (aid -> aid_Pool), ((cn -> cn_Size) + 16UL) ) )
- {
- /* Load CMAP data */
- error = ReadChunkBytes( iff, buff, (cn -> cn_Size) );
-
- /* All read ? */
- if( error == (cn -> cn_Size) )
- {
- error = 0L; /* Success ! */
-
- if( timestamp == 1UL )
- {
- if( !CMAP2Object( cb, o, buff, (cn -> cn_Size) ) )
- {
- /* can't alloc object's color table */
- error = ERROR_NO_FREE_STORE;
- }
- }
- else
- {
- verbose_printf( cb, aid, "CMAP found, changing colormap\n" );
- }
-
- /* Any failure ? */
- if( error == 0L )
- {
- if( aid -> aid_NoCMAPs )
- {
- error = 0L; /* Success ! */
- }
- else
- {
- if( fn -> fn_CMap = CMAP2ColorMap( cb, aid, buff, (cn -> cn_Size) ) )
- {
- error = 0L; /* Success ! */
- numcmaps++;
- }
- else
- {
- /* no colormap */
- error = ERROR_NO_FREE_STORE;
- }
- }
- }
- }
-
- FreeVecPooled( cb, (aid -> aid_Pool), buff );
- }
- else
- {
- /* no load buff */
- error = ERROR_NO_FREE_STORE;
- }
- }
- }
- break;
-
- case ID_BODY:
- {
- if( fn == NULL )
- {
- /* First frame in animation ?
- * (the first frame in an animation may not have an AnimHeader,
- * therefore we're creating an empty FrameNode,
- * (ah_Operation == acmpILBM), e.g. 0)
- */
- if( timestamp == 0UL )
- {
- /* Create an prepare a new frame node */
- if( fn = AllocFrameNode( cb, (aid -> aid_Pool) ) )
- {
- AddTail( (struct List *)(&(aid -> aid_FrameList)), (struct Node *)(&(fn -> fn_Node)) );
-
- fn -> fn_TimeStamp = timestamp++;
- fn -> fn_Frame = fn -> fn_TimeStamp;
-
- DumpAnimHeader( cb, aid, (fn -> fn_TimeStamp), (&(fn -> fn_AH)) );
- }
- else
- {
- /* can't alloc frame node */
- error = ERROR_NO_FREE_STORE;
- }
- }
- }
- }
- case ID_DLTA:
- {
- if( fn )
- {
- /* Store position of DLTA (pos points to the DLTA ID) */
- fn -> fn_BMOffset = pos;
- fn -> fn_BMSize = cn -> cn_Size;
-
- if( (fn -> fn_BitMap) == NULL )
- {
- /* Preload frames only if requested or if this is the key frame (first frame of anim) */
- if( (aid -> aid_LoadAll) || ((fn -> fn_TimeStamp) == 0UL) )
- {
- if( animwidth && animheight && animdepth )
- {
- if( fn -> fn_BitMap = AllocBitMapPooled( cb, animwidth, animheight, animdepth, (aid -> aid_Pool) ) )
- {
- UBYTE *buff;
-
- /* Allocate buffer */
- if( buff = (UBYTE *)AllocVecPooled( cb, (aid -> aid_Pool), ((cn -> cn_Size) + 16UL) ) )
- {
- struct FrameNode *prevfn;
-
- /* Get previous frame */
- prevfn = GetPrevFrameNode( fn, (ULONG)(fn -> fn_AH . ah_Interleave) );
-
- /* Load delta data */
- error = ReadChunkBytes( iff, buff, (cn -> cn_Size) );
-
- /* All bytes read ? */
- if( error == (cn -> cn_Size) )
- {
- error = DrawDLTA( cb, aid, (prevfn -> fn_BitMap), (fn -> fn_BitMap), (&(fn -> fn_AH)), buff, (cn -> cn_Size) );
-
- if( error )
- {
- error_printf( cb, aid, "scan/load: dlta unpacking error %lu\n", error );
- }
- }
-
- FreeVecPooled( cb, (aid -> aid_Pool), buff );
- }
- else
- {
- /* no load buff */
- error = ERROR_NO_FREE_STORE;
- }
- }
- else
- {
- /* no bitmap */
- error = ERROR_NO_FREE_STORE;
- }
- }
- else
- {
- /* no dimensions for bitmap (possibly a missing bmhd) */
- error = DTERROR_NOT_ENOUGH_DATA;
- }
- }
- }
- else
- {
- verbose_printf( cb, aid, "scan/load: bitmap already loaded\n" );
- }
- }
- else
- {
- verbose_printf( cb, aid, "scan: no fn while scanning DLTA\n" );
- }
- }
- break;
- }
- }
- break;
- }
- }
-
- /* on error: leave for-loop */
- if( error )
- {
- break;
- }
- }
-
- /* Any frames ? */
- if( timestamp && (error == 0L) && numcmaps )
- {
- if( numcmaps == 1UL )
- {
- /* We only have a global colormap and no colormap changes,
- * delete first colormap (a colormap in the first frames indicates following colormap
- * changes)
- */
- struct FrameNode *firstnode = (struct FrameNode *)(aid -> aid_FrameList . mlh_Head);
-
- if( firstnode -> fn_CMap )
- {
- FreeColorMap( (firstnode -> fn_CMap) );
- firstnode -> fn_CMap = NULL;
- }
- }
- else
- {
- /* All frames must have a colormap, therefore we replicate the colormap
- * from the previous colormap if one is missing
- */
- struct FrameNode *worknode,
- *nextnode;
- struct ColorMap *currcm = NULL;
-
- worknode = (struct FrameNode *)(aid -> aid_FrameList . mlh_Head);
-
- while( nextnode = (struct FrameNode *)(worknode -> fn_Node . mln_Succ) )
- {
- if( worknode -> fn_CMap )
- {
- /* Current node contains colormap, this are the colors for the following frames... */
- currcm = worknode -> fn_CMap;
- }
- else
- {
- if( currcm )
- {
- /* Copy colormap from previous one... */
- if( !(worknode -> fn_CMap = CopyColorMap( cb, currcm )) )
- {
- /* Can't copy/alloc colormap */
- error = ERROR_NO_FREE_STORE;
- }
- }
- else
- {
- verbose_printf( cb, aid, "scan/load: no colormap, can't copy it\n" );
- }
- }
-
- worknode = nextnode;
- }
- }
- }
- }
- }
-
- /* Check for required information */
- if( error == 0L )
- {
- /* bmh information available ? */
- if( bmhdprop == NULL )
- {
- verbose_printf( cb, aid, "scan: no bmhd found\n" );
-
- /* BMHD missing */
- error = DTERROR_INVALID_DATA;
- }
- else
- {
- /* Any frames loaded ? */
- if( timestamp == 0UL )
- {
- /* not enougth frames (at least one required) */
- error = DTERROR_NOT_ENOUGH_DATA;
- }
- }
- }
-
- /* Any error ? */
- if( error == 0L )
- {
- /* Alloc bitmap as key bitmap */
- if( aid -> aid_KeyBitMap = AllocBitMap( animwidth, animheight, animdepth, BMF_CLEAR, NULL ) )
- {
- struct FrameNode *firstfn = (struct FrameNode *)(aid -> aid_FrameList . mlh_Head); /* short cut to the first FrameNode */
-
- if( (firstfn -> fn_BitMap) == NULL )
- {
- if( !(firstfn -> fn_BitMap = AllocBitMapPooled( cb, (ULONG)(aid -> aid_BMH -> bmh_Width), (ULONG)(aid -> aid_BMH -> bmh_Height), (ULONG)(aid -> aid_BMH -> bmh_Depth), (aid -> aid_Pool) )) )
- {
- /* can't alloc first bitmap */
- error = ERROR_NO_FREE_STORE;
- }
- }
-
- if( error == 0L )
- {
- /* Copy first frame into key bitmap */
- CopyBitMap( cb, (aid -> aid_KeyBitMap), (firstfn -> fn_BitMap) );
-
- if( aid -> aid_ModeID )
- {
- modeid = aid -> aid_ModeID;
- }
- else
- {
- /* No mode id ? */
- if( modeid == 0UL )
- {
- /* Get best modeid for this dimensions */
- modeid = BestModeID( BIDTAG_NominalWidth, animwidth,
- BIDTAG_NominalHeight, animheight,
- BIDTAG_Depth, animdepth,
- BIDTAG_DIPFMustNotHave, (DIPF_IS_DUALPF | DIPF_IS_PF2PRI),
- TAG_DONE );
- }
- }
-
- if( (aid -> aid_FPS) == 0UL )
- {
- aid -> aid_FPS = 5UL;
- }
-
- AttachSample( cb, aid );
-
- verbose_printf( cb, aid, "width %lu height %lu depth %lu frames %lu fps %lu\n",
- animwidth,
- animheight,
- animdepth,
- timestamp,
- (aid -> aid_FPS) );
-
- /* Set misc attributes */
- SetDTAttrs( o, NULL, NULL,
- ADTA_ModeID, modeid,
- ADTA_Width, animwidth,
- ADTA_Height, animheight,
- ADTA_Depth, animdepth,
- ADTA_Frames, timestamp,
- ADTA_FramesPerSecond, (aid -> aid_FPS),
- ADTA_KeyFrame, (aid -> aid_KeyBitMap),
- ADTA_Sample, (firstfn -> fn_Sample),
- ADTA_SampleLength, (firstfn -> fn_SampleLength),
- ADTA_Period, (firstfn -> fn_Period),
- ADTA_Volume, (aid -> aid_Volume),
- ADTA_Cycles, 1UL,
- DTA_NominalHoriz, animwidth,
- DTA_NominalVert, animheight,
- TAG_DONE );
- }
- }
- else
- {
- /* can't alloc key bitmap */
- error = ERROR_NO_FREE_STORE;
- }
- }
- }
- else
- {
- /* No iff handle ? - Be sure we got a DTST_RAM sourcetype */
- if( sourcetype != DTST_RAM )
- {
- /* No handle ! */
- error = ERROR_REQUIRED_ARG_MISSING;
- }
- }
- }
- }
- else
- {
- /* can't get required attributes from superclass */
- error = ERROR_OBJECT_WRONG_TYPE;
- }
- }
- else
- {
- /* no memory pool */
- error = ERROR_NO_FREE_STORE;
- }
-
- /* Error codes below 0 are related to the IFFParse.library functions */
- if( error < 0L )
- {
- verbose_printf( cb, aid, "iff error %ld\n", (long)error );
-
- /* convert IFFParse error to DOS error */
- error = ifferr2doserr[ (-error - 1) ];
- }
-
- return( error );
- }
-
-
- static
- struct FrameNode *AllocFrameNode( struct ClassBase *cb, APTR pool )
- {
- struct FrameNode *fn;
-
- if( fn = (struct FrameNode *)AllocPooled( pool, (ULONG)sizeof( struct FrameNode ) ) )
- {
- memset( fn, 0, sizeof( struct FrameNode ) );
- }
-
- return( fn );
- }
-
-
- static
- struct FrameNode *FindFrameNode( struct MinList *fnl, ULONG timestamp )
- {
- if( fnl )
- {
- struct FrameNode *worknode,
- *nextnode;
-
- worknode = (struct FrameNode *)(fnl -> mlh_Head);
-
- while( nextnode = (struct FrameNode *)(worknode -> fn_Node . mln_Succ) )
- {
- if( (worknode -> fn_TimeStamp) == timestamp )
- {
- return( worknode );
- }
-
- worknode = nextnode;
- }
- }
-
- return( NULL );
- }
-
-
- static
- void FreeFrameNodeResources( struct ClassBase *cb, struct MinList *fnl )
- {
- if( fnl )
- {
- struct FrameNode *worknode,
- *nextnode;
-
- worknode = (struct FrameNode *)(fnl -> mlh_Head);
-
- while( nextnode = (struct FrameNode *)(worknode -> fn_Node . mln_Succ) )
- {
- if( worknode -> fn_CMap )
- {
- FreeColorMap( (worknode -> fn_CMap) );
- worknode -> fn_CMap = NULL;
- }
-
- worknode = nextnode;
- }
- }
- }
-
-
- static
- void CopyBitMap( struct ClassBase *cb, struct BitMap *dest, struct BitMap *src )
- {
- if( dest && src )
- {
- ULONG planesize = (ULONG)(dest -> BytesPerRow) * (ULONG)(dest -> Rows);
- UWORD i;
-
- for( i = 0U ; i < (dest -> Depth) ; i++ )
- {
- CopyMem( (src -> Planes[ i ]), (dest -> Planes[ i ]), planesize );
- }
- }
- }
-
-
- static
- void ClearBitMap( struct BitMap *bm )
- {
- if( bm )
- {
- ULONG planesize = (ULONG)(bm -> BytesPerRow) * (ULONG)(bm -> Rows);
- UWORD i;
-
- for( i = 0U ; i < (bm -> Depth) ; i++ )
- {
- memset( (bm -> Planes[ i ]), 0, (size_t)planesize );
- }
- }
- }
-
-
- /* XOR Bitmaps op1 ^= op2 */
- static
- void XORBitMaps( struct BitMap *op1, struct BitMap *op2 )
- {
- if( op1 && op2 )
- {
- ULONG planesize = (ULONG)(op1 -> BytesPerRow) * (ULONG)(op1 -> Rows);
- UWORD i,
- j;
- WORD *op1p, /* op1 planes */
- *op2p; /* op2 planes */
-
- planesize /= sizeof( WORD ); /* op1p and op2p are WORDs, not BYTES... */
-
- for( i = 0U ; i < (op1 -> Depth) ; i++ )
- {
- for( j = 0U, op1p = (WORD *)(op1 -> Planes[ i ]), op2p = (WORD *)(op2 -> Planes[ i ]) ;
- j < planesize ;
- j++, op1p++, op2p++ )
- {
- *op1p ^= *op2p;
- }
- }
- }
- }
-
-
- /* This function assumes (0UL < depth) && (depth <= 8UL) */
- static
- struct BitMap *AllocBitMapPooled( struct ClassBase *cb, ULONG width, ULONG height, ULONG depth, APTR pool )
- {
- struct BitMap *bm;
- ULONG planesize,
- size;
-
- planesize = (ULONG)RASSIZE( width, height );
- size = ((ULONG)sizeof( struct BitMap )) + (planesize * depth) + width;
-
- if( bm = (struct BitMap *)AllocVecPooled( cb, pool, size ) )
- {
- UWORD pl;
- PLANEPTR plane;
-
- InitBitMap( bm, depth, width, height );
-
- plane = (PLANEPTR)(bm + 1); /* First plane follows struct BitMap */
-
- /* Set up plane data */
- pl = 0U;
-
- /* Set up plane ptrs */
- while( pl < depth )
- {
- bm -> Planes[ pl ] = plane;
-
- plane = (PLANEPTR)(((UBYTE *)plane) + planesize);
- pl++;
- }
-
- /* Clear the remaining plane ptrs */
- while( pl < 8U )
- {
- bm -> Planes[ pl ] = NULL;
-
- pl++;
- }
- }
-
- return( bm );
- }
-
-
- static
- BOOL CMAP2Object( struct ClassBase *cb, Object *o, UBYTE *rgb, ULONG rgbsize )
- {
- struct ColorRegister *acm;
- ULONG *acregs;
- ULONG nc;
-
- /* file has this many colors (e.g. each color has one byte per R,B,G-gun) */
- nc = rgbsize / 3UL;
-
- SetDTAttrs( o, NULL, NULL, ADTA_NumColors, nc, TAG_DONE );
-
- /* Get color context */
- if( GetDTAttrs( o,
- ADTA_ColorRegisters, (&acm),
- ADTA_CRegs, (&acregs),
- ADTA_NumColors, (&nc),
- TAG_DONE ) == 3UL )
- {
- /* All valid ? */
- if( acm && acregs && nc )
- {
- ULONG i;
-
- for( i = 0UL ; i < nc ; i++, acm++ )
- {
- acm -> red = *rgb++;
- acm -> green = *rgb++;
- acm -> blue = *rgb++;
-
- /* Replicate the color information.
- * This surrounds an OS bug which uses the low-oreder bytes of the 32-bit colors
- * instead of the high order ones
- */
- acregs[ ((i * 3) + 0) ] = ((ULONG)(acm -> red)) * 0x01010101UL;
- acregs[ ((i * 3) + 1) ] = ((ULONG)(acm -> green)) * 0x01010101UL;
- acregs[ ((i * 3) + 2) ] = ((ULONG)(acm -> blue)) * 0x01010101UL;
- }
-
- return( TRUE );
- }
- }
-
- return( FALSE );
- }
-
-
- static
- struct ColorMap *CMAP2ColorMap( struct ClassBase *cb, struct AnimInstData *aid, UBYTE *rgb, ULONG rgbsize )
- {
- struct ColorMap *cm;
- ULONG a_nc = (1UL << (ULONG)(aid -> aid_BMH -> bmh_Depth)); /* Number of colors in animation */
- ULONG rgb_nc = rgbsize / 3UL; /* Number of colors in CMAP */
-
- /* Get a colormap which hold all colors */
- if( cm = GetColorMap( (long)MAX( a_nc, rgb_nc ) ) )
- {
- ULONG i,
- r, g, b;
-
- for( i = 0UL ; i < rgb_nc ; i++ )
- {
- r = *rgb++;
- g = *rgb++;
- b = *rgb++;
-
- /* Replicate color information (see CMAP2Object for details) and store them into colormap */
- SetRGB32CM( cm, i, (r * 0x01010101UL), (g * 0x01010101UL), (b * 0x01010101UL) );
- }
-
- /* BUG: the remaining entries should be filled with colors from the last colormap */
- for( ; i < a_nc ; i++ )
- {
- SetRGB32CM( cm, i, 0UL, 0UL, 0UL ); /* fill remaining entries with black */
- }
- }
-
- return( cm );
- }
-
-
- static
- struct ColorMap *CopyColorMap( struct ClassBase *cb, struct ColorMap *src )
- {
- struct ColorMap *dest = NULL;
-
- if( src )
- {
- ULONG *ctable;
-
- if( ctable = (ULONG *)AllocVec( ((ULONG)(src -> Count) * sizeof( ULONG ) * 3UL), MEMF_PUBLIC ) )
- {
- if( dest = GetColorMap( (long)(src -> Count) ) )
- {
- ULONG i;
-
- GetRGB32( src, 0UL, (ULONG)(src -> Count), ctable );
-
- for( i = 0UL ; i < (src -> Count) ; i++ )
- {
- SetRGB32CM( dest, i, ctable[ ((i * 3) + 0) ], ctable[ ((i * 3) + 1) ], ctable[ ((i * 3) + 2) ] );
- }
- }
-
- FreeVec( ctable );
- }
- }
-
- return( dest );
- }
-
-
-
- /*****************************************************************************/
-
-
- static
- APTR AllocVecPooled( struct ClassBase *cb, APTR pool, ULONG memsize )
- {
- ULONG *memory = NULL;
-
- if( pool && memsize )
- {
- memsize += (ULONG)sizeof( ULONG );
-
- if( memory = (ULONG *)AllocPooled( pool, memsize ) )
- {
- (*memory) = memsize;
-
- memory++;
- }
- }
-
- return( (APTR)memory );
- }
-
-
- static
- void FreeVecPooled( struct ClassBase *cb, APTR pool, APTR mem )
- {
- if( pool && mem )
- {
- ULONG *memory;
-
- memory = (ULONG *)mem;
-
- memory--;
-
- FreePooled( pool, memory, (*memory) );
- }
- }
-
-
- static
- LONG DrawDLTA( struct ClassBase *cb, struct AnimInstData *aid, struct BitMap *prevbm, struct BitMap *bm, struct AnimHeader *ah, UBYTE *dlta, ULONG dltasize )
- {
- LONG error = 0L;
-
- if( bm && ah && dlta && dltasize )
- {
- struct BitMap *unpackbm = bm,
- *tempbm = NULL;
- struct BitMapHeader *bmh = aid -> aid_BMH;
-
- /* Handle acmpILBM and acmpAnimJ explicitly */
- switch( ah -> ah_Operation )
- {
- case acmpILBM: /* 0 */
- /* unpack ILBM BODY */
- return( LoadILBMBody( cb, unpackbm, bmh, dlta, dltasize ) );
- break;
-
- case acmpXORILBM: /* 1 */
- {
- error_printf( cb, aid, "\adlta: acmpXORILBM disabled, call author immediately\n" );
- return( ERROR_NOT_IMPLEMENTED );
- }
- break;
-
- case acmpAnimJ: /* 'J' */
- /* unpack ANIM-J */
- return( unpackanimjdelta( cb, dlta, dltasize, prevbm, bm ) );
- break;
- }
-
- /* Handle XOR */
- if( ((ah -> ah_Flags) & ahfXOR) && prevbm )
- {
- if( prevbm == bm )
- {
- if( !(tempbm = AllocBitMapPooled( cb, (ULONG)(aid -> aid_BMH -> bmh_Width), (ULONG)(aid -> aid_BMH -> bmh_Height), (ULONG)(aid -> aid_BMH -> bmh_Depth), (aid -> aid_Pool) )) )
- {
- return( ERROR_NO_FREE_STORE );
- }
-
- unpackbm = prevbm = tempbm;
- }
-
- ClearBitMap( unpackbm );
- }
- else
- {
- if( prevbm )
- {
- if( prevbm != bm )
- {
- CopyBitMap( cb, bm, prevbm );
- }
- }
- else
- {
- ClearBitMap( bm );
- }
- }
-
- /* dispatch compression type */
- switch( ah -> ah_Operation )
- {
- /* acmpILBM, acmpXORILBM and acmpAnimJ have been processed above */
-
- case acmpLongDelta: /* 2 */
- {
- error = unpacklongdelta( unpackbm, dlta, dltasize );
- }
- break;
-
- case acmpShortDelta: /* 3 */
- {
- error = unpackshortdelta( unpackbm, dlta, dltasize );
- }
- break;
-
- case acmpDelta: /* 4 */
- {
- #ifdef COMMENTED_OUT
- if( (ah -> ah_Flags) & ahfLongData )
- {
- error = unpackanim4longdelta( unpackbm, dlta, dltasize, (ah -> ah_Flags) );
- }
- else
- {
- error = unpackanim4worddelta( unpackbm, dlta, dltasize, (ah -> ah_Flags) );
- }
- #else
- error_printf( cb, aid, "\adlta: acmpDelta disabled, call author immediately\n" );
- error = ERROR_NOT_IMPLEMENTED;
- #endif /* COMMENTED_OUT */
- }
- break;
-
- case acmpByteDelta: /* 5 */
- case acmpStereoByteDelta: /* 6 */
- {
- error = unpackbytedelta( unpackbm, dlta, dltasize );
- }
- break;
-
- case acmpAnim7: /* 7 */
- {
- if( (ah -> ah_Flags) & ahfLongData )
- {
- error = unpackanim7longdelta( unpackbm, dlta, dltasize );
- }
- else
- {
- error = unpackanim7worddelta( unpackbm, dlta, dltasize );
- }
- }
- break;
-
- case acmpAnim8: /* 8 */
- {
- if( (ah -> ah_Flags) & ahfLongData )
- {
- error = unpackanim8longdelta( unpackbm, dlta, dltasize );
- }
- else
- {
- error = unpackanim8worddelta( unpackbm, dlta, dltasize );
- }
- }
- break;
-
- default: /* 'l' */
- {
- error_printf( cb, aid, "\adlta: anim compression %ld not implemented yet\n", (long)(ah -> ah_Operation) );
- error = ERROR_NOT_IMPLEMENTED;
- }
- break;
- }
-
- /* Handle XOR (see above) */
- if( ((ah -> ah_Flags) & ahfXOR) && prevbm )
- {
- XORBitMaps( bm, prevbm );
- }
-
- if( tempbm )
- {
- FreeVecPooled( cb, (aid -> aid_Pool), tempbm );
- }
- }
-
- return( error );
- }
-
-
- static
- void DumpAnimHeader( struct ClassBase *cb, struct AnimInstData *aid, ULONG ti, struct AnimHeader *anhd )
- {
- if( anhd )
- {
- verbose_printf( cb, aid, "%4lu: ", ti );
-
- switch( anhd -> ah_Operation )
- {
- case acmpILBM: verbose_printf( cb, aid, "ah_Operation acmpILBM" ); break;
- case acmpXORILBM: verbose_printf( cb, aid, "ah_Operation acmpXORILBM" ); break;
- case acmpLongDelta: verbose_printf( cb, aid, "ah_Operation acmpLongDelta" ); break;
- case acmpShortDelta: verbose_printf( cb, aid, "ah_Operation acmpShortDelta" ); break;
- case acmpDelta: verbose_printf( cb, aid, "ah_Operation acmpDelta" ); break;
- case acmpByteDelta: verbose_printf( cb, aid, "ah_Operation acmpByteDelta" ); break;
- case acmpStereoByteDelta: verbose_printf( cb, aid, "ah_Operation acmpStereoByteDelta" ); break;
- case acmpAnim7: verbose_printf( cb, aid, "ah_Operation acmpAnim7" ); break;
- case acmpAnim8: verbose_printf( cb, aid, "ah_Operation acmpAnim8" ); break;
- case acmpAnimJ: verbose_printf( cb, aid, "ah_Operation acmpAnimJ" ); break;
- default: verbose_printf( cb, aid, "ah_Operation <acmp unknown>" ); break;
- }
-
- verbose_printf( cb, aid, " ah_AbsTime %3lu ah_RelTime %3lu ah_Interleave %3lu", (anhd -> ah_AbsTime), (anhd -> ah_RelTime), (ULONG)(anhd -> ah_Interleave) );
-
- if( (anhd -> ah_Flags) & ahfLongData ) verbose_printf( cb, aid, " ahfLongData" );
- if( (anhd -> ah_Flags) & ahfXOR ) verbose_printf( cb, aid, " ahfXOR" );
- if( (anhd -> ah_Flags) & ahfOneInfoList ) verbose_printf( cb, aid, " ahfOneInfoList" );
- if( (anhd -> ah_Flags) & ahfRLC ) verbose_printf( cb, aid, " ahfRLC" );
- if( (anhd -> ah_Flags) & ahfVertical ) verbose_printf( cb, aid, " ahfVertical" );
- if( (anhd -> ah_Flags) & ahfLongInfoOffsets ) verbose_printf( cb, aid, " ahfLongInfoOffsets" );
-
- verbose_printf( cb, aid, "\n" );
- }
- }
-
-
- static
- struct FrameNode *GetPrevFrameNode( struct FrameNode *currfn, ULONG interleave )
- {
- struct FrameNode *worknode,
- *prevnode;
-
- /* An interleave of 0 means two frames back */
- if( interleave == 0UL )
- {
- interleave = 2UL;
- }
-
- /* Get previous frame */
- worknode = currfn;
-
- while( prevnode = (struct FrameNode *)(worknode -> fn_Node . mln_Pred) )
- {
- if( (interleave-- == 0U) || ((prevnode -> fn_Node . mln_Pred) == NULL) )
- {
- break;
- }
-
- worknode = prevnode;
- }
-
- return( worknode );
- }
-
-
- static
- void OpenLogfile( struct ClassBase *cb, struct AnimInstData *aid )
- {
- if( (aid -> aid_VerboseOutput) == NULL )
- {
- STRPTR confile;
-
- if( confile = (STRPTR)AllocVec( (((aid -> aid_ProjectName)?(strlen( (aid -> aid_ProjectName) )):(0UL)) + 100UL), MEMF_PUBLIC ) )
- {
- mysprintf( cb, confile, "CON:////Anim DataType %s/auto/wait/close/inactive",
- ((aid -> aid_ProjectName)?(FilePart( (aid -> aid_ProjectName) )):(NULL)) );
-
- aid -> aid_VerboseOutput = Open( confile, MODE_READWRITE );
-
- FreeVec( confile );
- }
- }
- }
-
-
- static
- void mysprintf( struct ClassBase *cb, STRPTR buffer, STRPTR fmt, ... )
- {
- APTR args;
-
- args = (APTR)((&fmt) + 1);
-
- RawDoFmt( fmt, args, (void (*))"\x16\xc0\x4e\x75", buffer );
- }
-
-
- static
- void error_printf( struct ClassBase *cb, struct AnimInstData *aid, STRPTR format, ... )
- {
- OpenLogfile( cb, aid );
-
- if( aid -> aid_VerboseOutput )
- {
- VFPrintf( (aid -> aid_VerboseOutput), format, (APTR)((&format) + 1) );
- }
- }
-
-
- static
- void verbose_printf( struct ClassBase *cb, struct AnimInstData *aid, STRPTR format, ... )
- {
- if( aid -> aid_VerboseOutput )
- {
- VFPrintf( (aid -> aid_VerboseOutput), format, (APTR)((&format) + 1) );
- }
- }
-
-
- static
- void AttachSample( struct ClassBase *cb, struct AnimInstData *aid )
- {
- if( aid -> aid_Sample )
- {
- struct FrameNode *worknode,
- *nextnode;
-
- ULONG period = aid -> aid_Period;
- ULONG samplesperframe = (((SysBase -> ex_EClockFrequency) * 10UL) / (period * (aid -> aid_FPS) * 2UL));
- BYTE *sample = aid -> aid_Sample;
-
- verbose_printf( cb, aid, "Attching samples (sysclock %lu period %lu fps %lu length %lu samplesperframe %lu)...\n",
- (SysBase -> ex_EClockFrequency), period, (aid -> aid_FPS), (aid -> aid_SampleLength), samplesperframe );
-
- worknode = (struct FrameNode *)(aid -> aid_FrameList . mlh_Head);
-
- while( nextnode = (struct FrameNode *)(worknode -> fn_Node . mln_Succ) )
- {
- worknode -> fn_Sample = sample;
- worknode -> fn_SampleLength = samplesperframe;
- worknode -> fn_Period = period;
-
- sample += samplesperframe;
-
- /* End of sample reached ? */
- if( (ULONG)(sample - (aid -> aid_Sample)) > (aid -> aid_SampleLength) )
- {
- break;
- }
-
- worknode = nextnode;
- }
- }
- }
-
-
- static
- ULONG SaveIFFAnim( struct ClassBase *cb, struct IClass *cl, Object *o, struct dtWrite *dtw )
- {
- ULONG retval = 0UL;
- LONG error = 0L;
-
- /* A NULL file handle is a nop (GMultiView uses this to test if a datatype supports RAW writing) */
- if( dtw -> dtw_FileHandle )
- {
- struct AnimInstData *aid = (struct AnimInstData *)INST_DATA( cl, o );
-
- struct BitMapHeader *bmh;
- ULONG modeid;
- ULONG *cregs;
- ULONG numcolors;
- ULONG startframe = 0UL,
- numframes = 0UL,
- framestep = 1UL;
- ULONG fps = 0UL;
- struct BitMap *keyframe;
- ULONG animwidth,
- animheight,
- animdepth;
-
- if( GetDTAttrs( o, PDTA_BitMapHeader, (&bmh),
- ADTA_ModeID, (&modeid),
- ADTA_CRegs, (&cregs),
- ADTA_NumColors, (&numcolors),
- ADTA_Width, (&animwidth),
- ADTA_Height, (&animheight),
- ADTA_Depth, (&animdepth),
- ADTA_Frame, (&startframe),
- ADTA_Frames, (&numframes),
- ADTA_FramesPerSecond, (&fps),
- ADTA_KeyFrame, (&keyframe),
- TAG_DONE ) == 11UL )
- {
- struct TagItem *tstate,
- *ti;
- struct AnimContext *ac;
- struct IFFHandle *iff;
- struct BitMapHeader xbmh = *bmh;
-
- xbmh . bmh_Compression = cmpNone; /* Currently we only write an uncompressed key frame */
-
- numframes -= startframe;
-
- tstate = dtw -> dtw_AttrList;
-
- while( ti = NextTagItem( (&tstate) ) )
- {
- switch( ti -> ti_Tag )
- {
- case ADTA_Frame: startframe = ti -> ti_Data; break;
- case ADTA_Frames: numframes = ti -> ti_Data; break;
- case ADTA_FrameIncrement: framestep = ti -> ti_Data; break;
- }
- }
-
- if( framestep == 0UL ) framestep = 1UL;
-
- verbose_printf( cb, aid, "saving iff anim %lu %lu %lu\n", startframe, numframes, framestep );
-
- if( numframes )
- {
- if( ac = CreateAnimContext( cb, animwidth, animheight, animdepth ) )
- {
- if( iff = CreateDOSIFFHandle( cb, (dtw -> dtw_FileHandle) ) )
- {
- if( !(error = StartIFFAnim3( cb, aid, iff, ac, (&xbmh), modeid, cregs, numcolors, numframes, fps, keyframe )) )
- {
- struct adtFrame alf;
- ULONG timestamp,
- *cmap_cregs = NULL;
-
- /* Start scan through animation */
- for( timestamp = startframe ; numframes > 0UL ; timestamp += framestep, numframes-- )
- {
- /* On error break */
- if( error )
- {
- break;
- }
-
- /* Check for CTRL_D signal... */
- if( SetSignal( 0UL, 0UL ) & SIGBREAKF_CTRL_D )
- {
- error = ERROR_BREAK;
-
- break;
- }
-
- /* reset method msg */
- memset( (void *)(&alf), 0, sizeof( struct adtFrame ) );
-
- /* load frame */
- alf . MethodID = ADTM_LOADFRAME;
- alf . alf_TimeStamp = timestamp;
- alf . alf_Frame = timestamp;
-
- if( DoMethodA( o, (Msg)(&alf) ) == 0UL )
- {
- error = IoErr();
- break;
- }
-
- /* print frame contents */
- verbose_printf( cb, aid, "frame: timestamp %lu frame %lu duration %lu bitmap %lx cmap %lx sample %lx len %lu period %lu\n",
- timestamp,
- (alf . alf_Frame),
- (alf . alf_Duration),
- (alf . alf_BitMap),
- (alf . alf_CMap),
- (alf . alf_Sample),
- (alf . alf_SampleLength),
- (alf . alf_Period) );
-
- if( alf . alf_CMap )
- {
- if( cmap_cregs = (ULONG *)AllocVec( (((sizeof( ULONG ) * 3UL) + 1UL) * numcolors), MEMF_PUBLIC ) )
- {
- GetRGB32( (alf . alf_CMap), 0UL, (numcolors - 1UL), cmap_cregs );
- }
- else
- {
- error_printf( cb, aid, "can't alloc dynamic palette buffer\n" );
- error = ERROR_NO_FREE_STORE;
- }
- }
-
- if( alf . alf_BitMap )
- {
- if( error = WriteIFFAnim3( cb, iff, ac, ((timestamp * 60UL) / fps), (60UL / fps), (&xbmh), cmap_cregs, numcolors, (alf . alf_BitMap) ) )
- {
- error_printf( cb, aid, "error while writing IFF ANIM-3, aborted\n" );
- }
- }
-
- if( cmap_cregs )
- {
- FreeVec( cmap_cregs );
- cmap_cregs = NULL;
- }
-
- alf . MethodID = ADTM_UNLOADFRAME;
- DoMethodA( o, (Msg)(&alf) );
- }
-
- EndIFFAnim3( cb, aid, iff );
-
- if( error == 0L )
- {
- retval = 1UL; /* success ! */
- }
- }
-
- FreeIFF( iff );
- }
- else
- {
- error = IoErr();
- }
-
- DeleteAnimContext( cb, ac );
- }
- else
- {
- /* Can't alloc animcontext */
- error = ERROR_NO_FREE_STORE;
- }
- }
- }
- else
- {
- error_printf( cb, aid, "not enougth attributes\n" );
- }
- }
-
- /* Error codes below 0 are related to the IFFParse.library functions */
- if( error < 0L )
- {
- /* convert IFFParse error to DOS error */
- error = ifferr2doserr[ (-error - 1) ];
- }
-
- SetIoErr( error );
-
- return( retval );
- }
-
-
- static
- struct IFFHandle *CreateDOSIFFHandle( struct ClassBase *cb, BPTR fh )
- {
- struct IFFHandle *iff;
-
- if( iff = AllocIFF() )
- {
- iff -> iff_Stream = (ULONG)fh;
-
- InitIFFasDOS( iff );
- }
-
- return( iff );
- }
-
-
- static
- LONG StartIFFAnim3( struct ClassBase *cb, struct AnimInstData *aid, struct IFFHandle *iff, struct AnimContext *ac, struct BitMapHeader *bmh, ULONG modeid, ULONG *cregs, ULONG numcolors, ULONG numframes, ULONG fps, struct BitMap *bm )
- {
- LONG error;
-
- if( !(error = OpenIFF( iff, IFFF_WRITE )) )
- {
- for( ;; ) /* not a loop, used as a jump table */
- {
- if( error = PushChunk( iff, ID_ANIM, ID_FORM, IFFSIZE_UNKNOWN ) )
- break;
-
- /* write initial FORM ILBM */
- {
- if( error = PushChunk( iff, ID_ILBM, ID_FORM, IFFSIZE_UNKNOWN ) )
- break;
-
- /* write ILBM BMHD (BitMapHeader) */
- {
- if( error = PushChunk( iff, 0UL, ID_BMHD, IFFSIZE_UNKNOWN ) )
- break;
-
- if( WriteChunkBytes( iff, (APTR)bmh, sizeof( struct BitMapHeader ) ) != sizeof( struct BitMapHeader ) )
- {
- error = IFFERR_WRITE;
- break;
- }
-
- if( error = PopChunk( iff ) )
- break;
- }
-
- /* write ILBM CMAP (global color map) */
- if( error = PutILBMCMAP( cb, iff, cregs, numcolors ) )
- break;
-
- /* write ILBM DPAN chunk */
- {
- struct DPAnimChunk dpan;
-
- dpan . dpan_Version = 0U; /* ??? */
- dpan . dpan_nframes = numframes;
- dpan . dpan_FPS = fps;
-
- if( error = PushChunk( iff, 0UL, ID_DPAN, IFFSIZE_UNKNOWN ) )
- break;
-
- if( WriteChunkBytes( iff, (APTR)(&dpan), sizeof( struct DPAnimChunk ) ) != sizeof( struct DPAnimChunk ) )
- {
- error = IFFERR_WRITE;
- break;
- }
-
- if( error = PopChunk( iff ) )
- break;
- }
-
- /* write ILBM CAMG (amiga view mode) */
- {
- if( error = PushChunk( iff, 0UL, ID_CAMG, IFFSIZE_UNKNOWN ) )
- break;
-
- if( WriteChunkBytes( iff, (APTR)(&modeid), sizeof( ULONG ) ) != sizeof( ULONG ) )
- {
- error = IFFERR_WRITE;
- break;
- }
-
- if( error = PopChunk( iff ) )
- break;
- }
-
- /* Write ILBM BODY (if there is one...) */
- if( bm )
- {
- if( error = PutILBMBody( cb, iff, bm, bmh ) )
- break;
-
- /* Copy current bitmap into both buffers */
- CopyBitMap( cb, CurrFrame( cb, ac ), bm );
- SwapFrames( cb, ac );
- CopyBitMap( cb, CurrFrame( cb, ac ), bm );
- }
-
- if( error = PopChunk( iff ) )
- break;
- }
-
- break; /* end of jump table */
- }
-
- /* All headers written successfully ? */
- if( error == 0L )
- {
- /* Success ! */
- return( 0L );
- }
-
- CloseIFF( iff );
- }
-
- return( error );
- }
-
-
- static
- void EndIFFAnim3( struct ClassBase *cb, struct AnimInstData *aid, struct IFFHandle *iff )
- {
- if( iff )
- {
- LONG error;
-
- if( error = PopChunk( iff ) )
- {
- error_printf( cb, aid, "error while popping IFF ANIM-3 FORM %ld\n", error );
- }
-
- CloseIFF( iff );
-
- verbose_printf( cb, aid, "IFF ANIM-3 sucessfully created\n" );
- }
- }
-
-
- static
- LONG WriteIFFAnim3( struct ClassBase *cb, struct IFFHandle *iff, struct AnimContext *ac, ULONG abstime, ULONG reltime, struct BitMapHeader *bmh, ULONG *cregs, ULONG numcolors, struct BitMap *bm )
- {
- LONG error;
-
- for( ;; ) /* not a loop, used as a jump-table */
- {
- /* write FORM ILBM */
- {
- if( error = PushChunk( iff, ID_ILBM, ID_FORM, IFFSIZE_UNKNOWN ) )
- break;
-
- /* write ILBM ANHD (AnimHeader) */
- {
- struct AnimHeader animheader = { 0 };
-
- animheader . ah_Operation = acmpShortDelta;
- animheader . ah_AbsTime = abstime;
- animheader . ah_RelTime = reltime;
- animheader . ah_Interleave = 2U;
-
- if( error = PushChunk( iff, 0UL, ID_ANHD, IFFSIZE_UNKNOWN ) )
- break;
-
- if( WriteChunkBytes( iff, (APTR)(&animheader), sizeof( struct AnimHeader ) ) != sizeof( struct AnimHeader ) )
- {
- error = IFFERR_WRITE;
- break;
- }
-
- if( error = PopChunk( iff ) )
- break;
- }
-
- /* Palette change ? */
- if( cregs && numcolors )
- {
- if( error = PutILBMCMAP( cb, iff, cregs, numcolors ) )
- break;
- }
-
- /* Write ANIM-3 delta */
- if( error = PutAnim3Delta( cb, iff, ac, CurrFrame( cb, ac ), bm ) )
- break;
-
- /* Copy current bitmap into buffer, then swap to next frame */
- CopyBitMap( cb, CurrFrame( cb, ac ), bm );
- SwapFrames( cb, ac );
-
- if( error = PopChunk( iff ) )
- break;
- }
-
- break; /* end of jump-table */
- }
-
- return( error );
- }
-
-
- static
- LONG PutAnim3Delta( struct ClassBase *cb, struct IFFHandle *iff, struct AnimContext *ac, struct BitMap *prevbm, struct BitMap *bm )
- {
- LONG error;
- ULONG len;
-
- ULONG *ptrs = (ULONG *)(ac -> ac_WorkBuffer);
- WORD *data = (WORD *)(ptrs + 8UL); /* data space starts after the 8 byte pointers... */
- UBYTE plane;
- ULONG planesize = ((bm -> BytesPerRow) * (bm -> Rows)) / sizeof( WORD ); /* size of plane,
- * in compression units (WORD).
- */
-
- memset( (ac -> ac_WorkBuffer), 0, (size_t)(ac -> ac_WorkBufferSize) );
-
- for( plane = 0U ; plane < (bm -> Depth) ; plane++ )
- {
- WORD distance = 0,
- i;
- WORD *planedata = (WORD *)(bm -> Planes[ plane ]),
- *prevplanedata = (WORD *)(prevbm -> Planes[ plane ]);
-
- ptrs[ plane ] = (ULONG)((UBYTE *)data - (UBYTE *)(ac -> ac_WorkBuffer));
-
- for( i = 0 ; i < planesize ; i++ )
- {
- if( (planedata[ i ] != prevplanedata[ i ]) || (distance > 30000) )
- {
- if( planedata[ (i + 1) ] != prevplanedata[ (i + 1) ] )
- {
- WORD *len;
-
- *data++ = -distance - 1;
- len = data++;
-
- *len = 0;
-
- while( (planedata[ i ] != prevplanedata[ i ]) && (i < planesize) && (*len < 30000))
- {
- *data++ = planedata[ i ];
- i++;
- (*len)++;
- }
-
- i--;
- }
- else
- {
- *data++ = distance;
- *data++ = planedata[ i ];
- }
-
- distance = 1;
- }
- else
- {
- distance++;
- }
- }
-
- /* No changes ? */
- if( ptrs[ plane ] == (ULONG)((UBYTE *)data - (UBYTE *)(ac -> ac_WorkBuffer)) )
- {
- ptrs[ plane ] = 0UL;
- }
- else
- {
- *data++ = (WORD)0xFFFF; /* terminator */
- }
- }
-
- if( error = PushChunk( iff, 0UL, ID_DLTA, IFFSIZE_UNKNOWN ) )
- return( error );
-
- len = (ULONG)((UBYTE *)data - (UBYTE *)(ac -> ac_WorkBuffer));
-
- if( WriteChunkBytes( iff, (APTR)(ac -> ac_WorkBuffer), len ) != len )
- {
- return( IFFERR_WRITE );
- }
-
- error = PopChunk( iff );
-
- return( error );
- }
-
-
- /*****************************************************************************/
-
- /* write ILBM CMAP */
- static
- LONG PutILBMCMAP( struct ClassBase *cb, struct IFFHandle *iff, ULONG *cregs, ULONG numcolors )
- {
- long error;
- ULONG i;
- struct ColorRegister cm;
-
- if( error = PushChunk( iff, 0UL, ID_CMAP, IFFSIZE_UNKNOWN ) )
- return( error );
-
- for( i = 0UL ; i < numcolors ; i++ )
- {
- /* reduce colors from 32 bits to cmap's 8 bit-per-gun */
- cm . red = (UBYTE)(cregs[ ((i * 3) + 0) ] >> 24UL);
- cm . green = (UBYTE)(cregs[ ((i * 3) + 1) ] >> 24UL);
- cm . blue = (UBYTE)(cregs[ ((i * 3) + 2) ] >> 24UL);
-
- /* Write R, B, G bytes */
- if( WriteChunkBytes( iff, (APTR)(&cm), 3UL ) != 3UL )
- {
- return( IFFERR_WRITE );
- }
- }
-
- return( PopChunk( iff ) );
- }
-
-
- /*****************************************************************************/
-
- /* from IFF example code ("iffp/ilbm.h") */
- #define RowBytes( w ) ((((w) + 15) >> 4) << 1)
- #define RowBits( w ) ((((w) + 15) >> 4) << 4)
-
-
- static
- LONG PutILBMBody( struct ClassBase *cb, struct IFFHandle *iff, struct BitMap *bitmap, struct BitMapHeader *bmh )
- {
- LONG error;
- LONG rowBytes = bitmap -> BytesPerRow; /* for source modulo only */
- LONG FileRowBytes = RowBytes( (bmh -> bmh_Width) ); /* width to write in bytes */
- ULONG planeCnt = bmh -> bmh_Depth; /* number of bit planes including mask */
- ULONG iPlane,
- iRow;
- BYTE *planes[ 24 ]; /* array of ptrs to planes & mask */
-
- /* Copy the ptrs to bit & mask planes into local array "planes" */
- for( iPlane = 0 ; iPlane < planeCnt; iPlane++ )
- planes[ iPlane ] = (BYTE *)(bitmap -> Planes[ iPlane ]);
-
- /* Write out a BODY chunk header */
- if( error = PushChunk( iff, 0L, ID_BODY, IFFSIZE_UNKNOWN ) )
- return( error );
-
- /* Write out the BODY contents */
- for( iRow = bmh -> bmh_Height ; iRow > 0 ; iRow-- )
- {
- for( iPlane = 0 ; iPlane < planeCnt ; iPlane++ )
- {
- /* Write next row.*/
- if( WriteChunkBytes( iff, planes[ iPlane ], FileRowBytes ) != FileRowBytes )
- return( IFFERR_WRITE );
-
- planes[ iPlane ] += rowBytes; /* Possibly skipping unused bytes */
- }
- }
-
- /* Finish the chunk */
- error = PopChunk( iff );
-
- return( error );
- }
-
-
- static
- struct AnimContext *CreateAnimContext( struct ClassBase *cb, ULONG width, ULONG height, ULONG depth )
- {
- APTR pool;
-
- if( pool = CreatePool( (MEMF_PUBLIC | MEMF_CLEAR), 1024UL, 1024UL ) )
- {
- struct AnimContext *ac;
-
- if( ac = (struct AnimContext *)AllocVecPooled( cb, pool, sizeof( struct AnimContext ) ) )
- {
- /* Alloc two bitmaps, used for interleaving */
- ac -> ac_BitMap[ 0 ] = AllocBitMapPooled( cb, width, height, depth, pool );
- ac -> ac_BitMap[ 1 ] = AllocBitMapPooled( cb, width, height, depth, pool );
-
- /* Alloc work buffer large enougth to hold fancy things... */
-
- ac -> ac_WorkBufferSize = (width * height * depth * 2UL) + 1024UL;
- ac -> ac_WorkBuffer = (UBYTE *)AllocVecPooled( cb, pool, (ac -> ac_WorkBufferSize) );
-
- if( (ac -> ac_BitMap[ 0 ]) && (ac -> ac_BitMap[ 1 ]) && (ac -> ac_WorkBuffer) )
- {
- return( ac );
- }
- }
-
- /* Something goes wrong here, get rid of the resources allocated */
- DeletePool( pool );
- }
-
- return( NULL );
- }
-
-
- static
- struct BitMap *PrevFrame( struct ClassBase *cb, struct AnimContext *ac )
- {
- if( ac )
- {
- return( (ac -> ac_BitMap[ ((ac -> ac_WhichBitMap) ^ 1) ]) );
- }
-
- return( NULL );
- }
-
-
- static
- void SwapFrames( struct ClassBase *cb, struct AnimContext *ac )
- {
- if( ac )
- {
- ac -> ac_WhichBitMap ^= 1; /* Toggle buffer */
- }
- }
-
-
- static
- struct BitMap *CurrFrame( struct ClassBase *cb, struct AnimContext *ac )
- {
- if( ac )
- {
- return( (ac -> ac_BitMap[ (ac -> ac_WhichBitMap) ]) );
- }
-
- return( NULL );
- }
-
-
- static
- void DeleteAnimContext( struct ClassBase *cb, struct AnimContext *ac )
- {
- if( ac )
- {
- DeletePool( (ac -> ac_Pool) );
- }
- }
-
-
-
-