** ** $Id: MovieDecode.a,v 1.1 93/05/24 14:33:22 chris Exp $ ** $Revision: 1.1 $ ** ** $Filename: MovieDecode/MovieDecode.a $ ** $Author: chris $ ** $Release: $ ** $Date: 93/05/24 14:33:22 $ ** ** Frame decoder for Sculpt/Animate MOVIE Format ** ** Author: Christian A. Weber, Bruggerweg 2, CH-8037 Zürich, Switzerland ** E-mail: chris@mighty.adsp.sub.org -or- weber@amiga.physik.unizh.ch ** ** COPYRIGHT © 1990-1993 BY CHRISTIAN A. WEBER. 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 PERMISSION ** OF THE AUTHOR. NO WARRANTY. USE AT YOUR OWN RISK. ** ** Note: I use the Devpac Assembler, but it should work with other ** Assemblers too. The code is pure and reentrant. V37 or newer ** is required. ** OPT O+,OW- ; Devpac: Optimize without warnings IDNT JDecode SECTION text,CODE INCLUDE "exec/types.i" INCLUDE "exec/memory.i" INCLUDE "exec/macros.i" INCLUDE "graphics/gfx.i" XDEF _InitJDecoder,_FreeJDecoder,_ModifyJFrame * Memory used for the automatically generated player code MEMSIZE EQU 32000 * Structure of an entry of "MoveTable" STRUCTURE TabEntry,0 APTR dec_Template ; Pointer to template WORD dec_TempSize ; Size of template LABEL dec_SIZEOF * For my ego :-) dc.b "J-Type ANIM Decoder V2.0 by Christian A. Weber",10,0 ******* MovieDecode/InitJDecoder ******************************************** * * NAME * InitJDecoder -- Initialize the player code for a given animation * * SYNOPSIS * handle = InitJDecoder(animtype) * D0 D0 * * APTR InitJDecoder(ULONG animtype); * * FUNCTION * Initializes the movie player for a given animation type. This is * typically called once after loading the animation. After playing, * FreeJDecoder() should be called (with the handle this function * returns) to free any resources allocated by this function. * * INPUTS * animtype - Bits 0 to 7: Number of bitplanes (1..6) * Bit 16: mode 0 = "Move" (loop), 1 = "EOR" (ping-pong) * * RESULT * Non-zero if everything was OK, NULL if no memory or bad animtype. * * BUGS * * SEE ALSO * FreeJDecoder() * ***************************************************************************** _InitJDecoder: movem.l d2-d7/a2-a6,-(SP) move.l d0,d7 ; D7: type & depth *** Allocate memory for the player code move.l #MEMSIZE,d0 moveq.l #MEMF_ANY,d1 movea.l (4).W,a6 JSRLIB AllocVec tst.l d0 ; Memory OK ? beq initerror ; no ---> movea.l d0,a2 ; A2: Player code buffer *** Copy header of the player code into the allocated buffer movea.l a2,a3 ; Destination lea Code(PC),a0 ; Source moveq.l #(CodeEnd-Code)/2-1,d0 ; Size (words) - 1 1$: move.w (a0)+,(a3)+ dbf d0,1$ *** Create jump table for the different anim operands mktab: movea.l a3,a4 moveq #3,d0 ; 4 types: Byte/Word/Long/Quad moveq #Error-CodeEnd-2,d2 ; D2 : BRA to Error-Offset 1$: moveq #32,d1 ; 33 entries per table move.l #$4EFB1002,(a4)+ ; JMP 02(PC,D1.W) subq.w #4,d2 ; correct offset (negative) 2$: move.w #$6000,(a4)+ ; BRA.W move.w d2,(a4)+ subq.w #4,d2 ; correct offset (negative) dbf d1,2$ dbf d0,1$ *** Create decoding routines for the different anim operands mkroutines: lea MoveTable(PC),a1 bclr #16,d7 ; EOR (reversible) mode ? beq.b 1$ ; no ---> lea EORTable(PC),a1 1$: addq.l #2,a3 ; BRA offsets of the jump table moveq #3,d0 ; 4 types: Byte/Word/Long/Quad .Loop1: moveq #0,d1 ; 10 routines: 1-8,16,32 lines addq.l #4+4,a3 ; Skip JMP and first BRA .Loop2: move.w d1,d2 ; Number of repetitions-1 cmpi.w #8,d1 bne.b 2$ moveq #16-1,d2 lea 7*4(a3),a3 ; Skip vectors for 9 to 15 2$: cmpi.w #9,d1 bne.b 3$ moveq #32-1,d2 lea 15*4(a3),a3 ; Skip vectors for 17 to 31 3$: move.w d2,d3 addq.w #1,d3 ; D3: number of repetitions movea.l a4,a5 ; A5: Start of actual routine move.w #$3018,(a4)+ ; MOVE.W (A0)+,D0 .Loop3: movea.l dec_Template(a1),a0 ; Template move.w dec_TempSize(a1),d4 ; Size of template in WORDs mulu.w d7,d4 ; * number of bitplanes bra.b .Dbf4 ; For dbf .Loop4: move.w (a0)+,(a4)+ ; Copy the template .Dbf4: dbf d4,.Loop4 tst.w d2 ; Is this the last one ? beq.b .NoAdd ; yes ---> don't generate ADD ins move.w #$D047,(a4)+ ; ADD.W D7,D0 .NoAdd: dbf d2,.Loop3 *** If we're in BYTE mode with an odd number of planes we have *** to insert an ADDQ.L #1,A0 instruction to word-align the *** delta data. cmpi.b #3,d0 ; BYTE mode ? bne.b 6$ ; no ---> no ADD required btst #0,d7 ; Even number of bitplanes ? beq.b 6$ ; yes ---> no ADD required btst #0,d3 ; Even number of repetitions ? beq.b 6$ ; yes ---> no ADD required move.w #$5288,(a4)+ ; ADDQ.L #1,A0 6$: *** Insert the start of this routine into the BRA.W table move.l a4,d4 ; Jump Destination: before the DBF sub.l a3,d4 ; minus table offset move.w d4,(a3) ; gives offset of BRA addq.w #4,a3 ; Pointer to next BRA move.w #$51CE,(a4)+ ; DBF D6, move.l a5,d4 ; Branch destination: Start of routine sub.l a4,d4 ; minus actual address move.w d4,(a4)+ ; gives offset move.w #$6000,(a4)+ ; BRA.W move.l a2,d4 ; Branch destination: MainLoop sub.l a4,d4 ; minus actual address move.w d4,(a4)+ ; gives offset addq.w #1,d1 ; increment number of repetitions cmpi.w #10,d1 blt.b .Loop2 addq.l #dec_SIZEOF,a1 ; Next template dbf d0,.Loop1 *** Since we created some code, we have to clear the I-cache JSRLIB CacheClearU ; A6 is still holding ExecBase move.l a2,d0 ; Result: handle initerror: movem.l (SP)+,d2-d7/a2-a6 rts ******* MovieDecode/FreeJDecoder ******************************************** * * NAME * FreeJDecoder -- Free the player code for an animation * * SYNOPSIS * FreeJDecoder(handle) * D0 A0 * * VOID FreeJDecoder(APTR handle); * * FUNCTION * Frees all resources which were allocated by InitJDecoder(). * This is typically called once after playing an animation. * * INPUTS * hande - result from InitJDecoder() ONLY! * * RESULT * none * * BUGS * * SEE ALSO * InitJDecoder() * ***************************************************************************** _FreeJDecoder: move.l a6,-(SP) *** Free the memory we allocated in InitJDecoder() movea.l a0,a1 movea.l (4).W,a6 JSRLIB FreeVec movea.l (SP)+,a6 rts ******* MovieDecode/ModifyJFrame ******************************************** * * NAME * ModifyJFrame -- Apply delta data on an animation frame * * SYNOPSIS * success = ModifyJFrame( deltas, bitmap, handle ) * D0 A0 A1 A2 * * BOOL ModifyJFrame( APTR, struct BitMap *, APTR ); * * FUNCTION * Generates a new animation frame by changing the frame before the * currently displayed frame (for double-buffering, as usual). * * INPUTS * deltas - pointer to the actual DLTA chunk data * bitmap - BitMap to render into * handle - player handle, from InitJDecoder() * * RESULT * Non-zero if everything was OK, FALSE if an error occurred. * * BUGS * * SEE ALSO * InitJDecoder(), FreeJDecoder() * ***************************************************************************** _ModifyJFrame: movem.l d2-d7/a2-a6,-(SP) move.w bm_BytesPerRow(a1),d7 ; d7 : BytesPerRow move.l a2,-(SP) ; Push address of player code movem.l bm_Planes(a1),a1-a6 ; A1-A6: plane pointers moveq.l #0,d0 ; Clear bitplane index pointer rts ; ---> Do the code *** The following code fragment will be copied to the beginning *** of the player code. It will be followed by the decoder *** routines for the particular mode and bitplane depth. Code: MainLoop: move.w (a0)+,d0 ; Number of bytes per entry addq.l #2,a0 ; Skip type: 0=Move, 1=EOR move.w (a0)+,d1 ; Number of rows of this width cmpi.w #32,d1 ; More than 32 ? bhi.b End ; yes ---> we can't handle this lsl.w #2,d1 ; Adjust for table index subq.w #1,d0 ; CODE 1: 1 Byte ? beq.b DoBytes ; yep ---> subq.w #1,d0 ; CODE 2: >1 Byte ? bne.b End ; no ---> finished move.w (a0)+,d0 ; Number of bytes per entry move.w (a0)+,d6 ; Number of n-rows entries subq.w #4,d0 beq DoBytes+68*4+2 ; 4 Bytes ---> bcc DoBytes+102*4+2 ; 6 Bytes ---> (bcc == bhs) bra DoBytes+34*4+2 ; 2 Bytes ---> Error: moveq #0,d0 ; Result: Error bra.b Exit End: moveq #1,d0 ; Result: Success Exit: movem.l (SP)+,d2-d7/a2-a6 rts DoBytes: move.w (a0)+,d6 ; Number of n-rows-entries CodeEnd: *** Here are the templates for the various operations. *** No code is generated for unused bitplanes. MoveByteTemplate: move.b (a0)+,0(a1,d0.L) move.b (a0)+,0(a2,d0.L) move.b (a0)+,0(a3,d0.L) move.b (a0)+,0(a4,d0.L) move.b (a0)+,0(a5,d0.L) move.b (a0)+,0(a6,d0.L) MoveByteTemplateEnd: MoveWordTemplate: move.w (a0)+,0(a1,d0.L) move.w (a0)+,0(a2,d0.L) move.w (a0)+,0(a3,d0.L) move.w (a0)+,0(a4,d0.L) move.w (a0)+,0(a5,d0.L) move.w (a0)+,0(a6,d0.L) MoveWordTemplateEnd: MoveLongTemplate: move.l (a0)+,0(a1,d0.L) move.l (a0)+,0(a2,d0.L) move.l (a0)+,0(a3,d0.L) move.l (a0)+,0(a4,d0.L) move.l (a0)+,0(a5,d0.L) move.l (a0)+,0(a6,d0.L) MoveLongTemplateEnd: MoveQuadTemplate: move.l (a0)+,0(a1,d0.L) move.w (a0)+,4(a1,d0.L) move.l (a0)+,0(a2,d0.L) move.w (a0)+,4(a2,d0.L) move.l (a0)+,0(a3,d0.L) move.w (a0)+,4(a3,d0.L) move.l (a0)+,0(a4,d0.L) move.w (a0)+,4(a4,d0.L) move.l (a0)+,0(a5,d0.L) move.w (a0)+,4(a5,d0.L) move.l (a0)+,0(a6,d0.L) move.w (a0)+,4(a6,d0.L) MoveQuadTemplateEnd: EORByteTemplate: move.b (a0)+,d1 eor.b d1,0(a1,d0.L) move.b (a0)+,d1 eor.b d1,0(a2,d0.L) move.b (a0)+,d1 eor.b d1,0(a3,d0.L) move.b (a0)+,d1 eor.b d1,0(a4,d0.L) move.b (a0)+,d1 eor.b d1,0(a5,d0.L) move.b (a0)+,d1 eor.b d1,0(a6,d0.L) EORByteTemplateEnd: EORWordTemplate: move.w (a0)+,d1 eor.w d1,0(a1,d0.L) move.w (a0)+,d1 eor.w d1,0(a2,d0.L) move.w (a0)+,d1 eor.w d1,0(a3,d0.L) move.w (a0)+,d1 eor.w d1,0(a4,d0.L) move.w (a0)+,d1 eor.w d1,0(a5,d0.L) move.w (a0)+,d1 eor.w d1,0(a6,d0.L) EORWordTemplateEnd: EORLongTemplate: move.l (a0)+,d1 eor.l d1,0(a1,d0.L) move.l (a0)+,d1 eor.l d1,0(a2,d0.L) move.l (a0)+,d1 eor.l d1,0(a3,d0.L) move.l (a0)+,d1 eor.l d1,0(a4,d0.L) move.l (a0)+,d1 eor.l d1,0(a5,d0.L) move.l (a0)+,d1 eor.l d1,0(a6,d0.L) EORLongTemplateEnd: EORQuadTemplate: move.l (a0)+,d1 eor.l d1,0(a1,d0.L) move.w (a0)+,d1 eor.w d1,4(a1,d0.L) move.l (a0)+,d1 eor.l d1,0(a2,d0.L) move.w (a0)+,d1 eor.w d1,4(a2,d0.L) move.l (a0)+,d1 eor.l d1,0(a3,d0.L) move.w (a0)+,d1 eor.w d1,4(a3,d0.L) move.l (a0)+,d1 eor.l d1,0(a4,d0.L) move.w (a0)+,d1 eor.w d1,4(a4,d0.L) move.l (a0)+,d1 eor.l d1,0(a5,d0.L) move.w (a0)+,d1 eor.w d1,4(a5,d0.L) move.l (a0)+,d1 eor.l d1,0(a6,d0.L) move.w (a0)+,d1 eor.w d1,4(a6,d0.L) EORQuadTemplateEnd: MoveTable: dc.l MoveByteTemplate dc.w (MoveByteTemplateEnd-MoveByteTemplate)/2/6 dc.l MoveWordTemplate dc.w (MoveWordTemplateEnd-MoveWordTemplate)/2/6 dc.l MoveLongTemplate dc.w (MoveLongTemplateEnd-MoveLongTemplate)/2/6 dc.l MoveQuadTemplate dc.w (MoveQuadTemplateEnd-MoveQuadTemplate)/2/6 dc.l $43485721 EORTable: dc.l EORByteTemplate dc.w (EORByteTemplateEnd-EORByteTemplate)/2/6 dc.l EORWordTemplate dc.w (EORWordTemplateEnd-EORWordTemplate)/2/6 dc.l EORLongTemplate dc.w (EORLongTemplateEnd-EORLongTemplate)/2/6 dc.l EORQuadTemplate dc.w (EORQuadTemplateEnd-EORQuadTemplate)/2/6 *** That's all folks! END