** ** Bobi - The Ultimate Amiga Bob Manipulator ** ** ByteMap.S - ByteMaps konvertieren, spiegeln, rotieren, zoomen usw. ** ** COPYRIGHT (C) 1989-1993 BY CHRISTIAN A. WEBER, 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 ** PERMISSION OF THE AUTHOR. NO WARRANTY. USE AT YOUR OWN RISK. ** IDNT ByteMap SECTION text,CODE INCLUDE "exec/types.i" INCLUDE "graphics/gfx.i" XDEF @BitMapToByteMap,@BobToByteMap,@ByteMapToBitMap XDEF @AutoResizeByteMap XDEF @FlipXByteMap,@FlipYByteMap XDEF @RotateByteMap,@ZoomByteMap ***************************************************************************** STRUCTURE MyBob,0 STRUCT mb_Planes,8*4 ; Alle Planes sind aneinander!! APTR mb_Mask ; Zeiger auf Masken-Plane WORD mb_BytesPerRow ; Aufgerundetes ((Width+15)/8)&~1 WORD mb_Width WORD mb_Height WORD mb_Depth WORD mb_Flags ; Siehe BOBF_ Definitionen WORD mb_PlaneSize ; BytesPerRow*Height WORD mb_X0 ; Nullpunkt X-Koordinate WORD mb_Y0 ; Nullpunkt Y-Koordinate WORD mb_CollX0 ; X0 des Kollisions-Bereiches WORD mb_CollY0 ; Y0 des Kollisions-Bereiches WORD mb_CollX1 ; X1 des Kollisions-Bereiches WORD mb_CollY1 ; Y1 des Kollisions-Bereiches BYTE mb_PlanePick ; Für welche Planes existieren Daten BYTE mb_PlaneOnOff ; wie bei Image Struktur STRUCT mb_SourceLabel,64 LABEL mb_SIZEOF ***************************************************************************** STRUCTURE ByteMap,0 WORD bym_Width ; Breite der ByteMap in Pixel WORD bym_Height ; Höhe der ByteMap in Pixel LONG bym_PlaneSize ; Grösse für Alloc/FreeMem der Plane APTR bym_Plane ; Zeiger auf die aktuelle Datenplane LABEL bym_SIZEOF *************************************************************************** ** ** ** BitMapToByteMap - BitMap in ByteMap umwandeln (1Byte=1Pixel) ** ** ** *************************************************************************** ** ** ** Parameter : A0.L : Zeiger auf struct BitMap (Source) ** ** A1.L : Zeiger auf struct ByteMap (Destination) ** ** ** ** Resultat : nix ** ** ** *************************************************************************** @BitMapToByteMap: movem.l d0-d7/a0-a6,-(SP) movem.l bm_Planes(a0),a2-a6 ; IMMER 5 Planes bra.b ToByteMap ; ---> *************************************************************************** ** ** ** BobToByteMap - struct MyBob in ByteMap umwandeln (1Byte=1Pixel) ** ** ** *************************************************************************** ** ** ** Parameter : A0.L : Zeiger auf struct MyBob (Source) ** ** A1.L : Zeiger auf struct ByteMap (Destination) ** ** ** ** Resultat : nix ** ** ** *************************************************************************** @BobToByteMap: movem.l d0-d7/a0-a6,-(SP) movem.l mb_Planes(a0),a2-a6 ; IMMER 5 Planes ;; bra.b ToByteMap ; ---> ToByteMap: bsr ValidatePlanePointers ; Falls weniger als 5 Planes move.w bym_Height(a1),-(SP) move.w bym_Width(a1),-(SP) movea.l bym_Plane(a1),a1 ; Destination-Plane movea.w #16,a0 ; 16 Bits pro Word 1$: move.w (SP),d7 ; Breite in Pixel 2$: move.w (a2)+,d2 move.w (a3)+,d3 move.w (a4)+,d4 move.w (a5)+,d5 move.w (a6)+,d6 moveq #15,d1 cmp.w a0,d7 ; Noch mehr als 16 Bit ? bge.b 3$ ; ja ---> move.w d7,d1 bra.b 4$ ; für dbf 3$: ;; moveq #0,d0 addx.w d6,d6 ; roxl.w #1,d6 addx.w d0,d0 addx.w d5,d5 addx.w d0,d0 addx.w d4,d4 addx.w d0,d0 addx.w d3,d3 addx.w d0,d0 addx.w d2,d2 addx.w d0,d0 move.b d0,(a1)+ 4$: dbf d1,3$ sub.w a0,d7 ; D7 -= 16 bgt.b 2$ subq.w #1,2(SP) ; DEC Rows bgt.b 1$ addq.l #4,SP ; Lokalen Datenraum freigeben movem.l (SP)+,d0-d7/a0-a6 rts *************************************************************************** ** ** ** ByteMapToBitMap - ByteMap in BitMap umwandeln (1Byte=1Pixel) ** ** ** *************************************************************************** ** ** ** Parameter : A0.L : Zeiger auf struct ByteMap (Source) ** ** A1.L : Zeiger auf struct BitMap (Destination) ** ** ** ** Resultat : nix ** ** ** *************************************************************************** @ByteMapToBitMap: movem.l d0-d7/a0-a6,-(SP) move.w bym_Height(a0),-(SP) move.w bym_Width(a0),-(SP) movea.l bym_Plane(a0),a0 ; Source-ByteMap-Plane movem.l bm_Planes(a1),a2-a6 ; IMMER 5 Destination-Planes bsr ValidatePlanePointers ; Falls weniger als 5 Planes movea.w #16,a1 ; 16 Bits pro Word 1$: move.w (SP),d7 ; Breite in Pixel 2$: moveq #15,d1 3$: move.b (a0)+,d0 ; Color-Wert roxr.w #1,d0 roxl.w #1,d2 roxr.w #1,d0 roxl.w #1,d3 roxr.w #1,d0 roxl.w #1,d4 roxr.w #1,d0 roxl.w #1,d5 roxr.w #1,d0 roxl.w #1,d6 dbf d1,3$ move.w d2,(a2)+ move.w d3,(a3)+ move.w d4,(a4)+ move.w d5,(a5)+ move.w d6,(a6)+ sub.w a1,d7 ; D7 -= 16 bgt.b 2$ neg.w d7 ; D7 := #zuvielgenommene Pixel suba.w d7,a0 ; Correct Source add.w d7,d7 ; Index in WORD-Tabelle move.w MaskTab(PC,d7.w),d0 and.w d0,-2(a2) ; Rest-Pixel löschen and.w d0,-2(a3) and.w d0,-2(a4) and.w d0,-2(a5) and.w d0,-2(a6) subq.w #1,2(SP) ; DEC Rows bgt.b 1$ addq.l #4,SP ; Lokalen Datenraum freigeben movem.l (SP)+,d0-d7/a0-a6 rts MaskTab: dc.w %1111111111111111 dc.w %1111111111111110 dc.w %1111111111111100 dc.w %1111111111111000 dc.w %1111111111110000 dc.w %1111111111100000 dc.w %1111111111000000 dc.w %1111111110000000 dc.w %1111111100000000 dc.w %1111111000000000 dc.w %1111110000000000 dc.w %1111100000000000 dc.w %1111000000000000 dc.w %1110000000000000 dc.w %1100000000000000 dc.w %1000000000000000 *************************************************************************** ** ** ** AutoResizeByteMap - ByteMap auf kleinstmögliche Grösse reduzieren ** ** ** *************************************************************************** ** ** ** Parameter : A0.L : Zeiger auf struct ByteMap ** ** ** ** Resultat : D0.L : 0 falls ByteMap leer, 1 sonst ** ** ** *************************************************************************** @AutoResizeByteMap: movem.l d1-d6/a0-a3,-(SP) moveq #0,d0 ; D0 : X0 moveq #0,d1 ; D1 : Y0 move.w bym_Width(a0),d2 ; D2 : Breite in Pixel move.w bym_Height(a0),d3 ; D3 : Höhe in Pixel move.w d2,d4 ; D4 : Originalbreite const. movea.l bym_Plane(a0),a1 ; A1 : Plane *** Neues Y0 finden FindY0: movea.l a1,a2 ; Plane 1$: move.w d2,d5 ; Breite bra.b 3$ ; für dbf 2$: tst.b (a2)+ ; Pixel == 0 ? bne.b 4$ ; nein ---> Y0 gefunden 3$: dbf d5,2$ addq.w #1,d1 ; INC Y0 subq.w #1,d3 ; DEC Höhe bgt.b 1$ ; Noch grösse als 0 ---> Loop bra ByteMapEmpty 4$: *** Neues Y1 finden FindY1: movea.l a1,a2 ; Plane move.w d2,d5 ; Breite mulu.w bym_Height(a0),d5 ; mal Original-Höhe adda.l d5,a2 ; Plane-Ende 1$: move.w d2,d5 ; Breite bra.b 3$ ; für dbf 2$: tst.b -(a2) ; Pixel == 0 ? bne.b 4$ ; nein ---> Y1 gefunden 3$: dbf d5,2$ subq.w #1,d3 ; DEC Höhe bgt.b 1$ ; > 0 ---> Loop bra ByteMapEmpty 4$: *** Neues X0 finden FindX0: movea.l a1,a2 ; Plane move.w d1,d5 ; Y0 mulu.w d4,d5 ; * Original-Width adda.l d5,a2 move.w d4,d5 ; Original-Breite 1$: movea.l a2,a3 ; Plane move.w d3,d6 ; Höhe bra.b 3$ 2$: tst.b (a3) ; Pixel == 0 ? bne.b 4$ ; nein ---> X0 gefunden adda.w d5,a3 ; Plane += Width 3$: dbf d6,2$ addq.l #1,a2 ; INC Plane addq.w #1,d0 ; INC X0 subq.w #1,d2 ; DEC Width bgt.b 1$ ; > 0 ---> Loop bra ByteMapEmpty 4$: *** Neues X1 finden FindX1: movea.l a1,a2 ; Plane move.w d1,d5 ; Y0 addq.w #1,d5 ; Ganz rechts + 1 mulu.w d4,d5 ; * Original-Width adda.l d5,a2 move.w d4,d5 ; Original-Breite 1$: subq.l #1,a2 ; DEC Plane movea.l a2,a3 ; Plane move.w d3,d6 ; Höhe bra.b 3$ 2$: tst.b (a3) ; Pixel == 0 ? bne.b 4$ ; nein ---> X0 gefunden adda.w d5,a3 ; Plane += Width 3$: dbf d6,2$ subq.w #1,d2 ; DEC Width bgt.b 1$ ; > 0 ---> Loop bra ByteMapEmpty 4$: *** Neue Parameter in ByteMap eintragen subq.w #1,d2 ; Nur so stimmt's weiss auch nicht wieso move.w d2,bym_Width(a0) move.w d3,bym_Height(a0) *** ByteMap an neues Format anpassen ResizeBM: movea.l a1,a2 ; Destination adda.w d0,a1 ; A1 += X0 mulu.w d4,d1 ; Y0 *= Old Width adda.l d1,a1 ; A1 += Y0 move.w d4,d0 ; Original-Width sub.w d2,d0 ; D0 := Width-Modulo move.w d3,d6 ; Height bra.b 4$ ; Für dbf 1$: move.w d2,d5 ; Neue Breite bra.b 3$ ; Für dbf 2$: move.b (a1)+,(a2)+ ; Tada! 3$: dbf d5,2$ adda.w d0,a1 ; A1 += Width-Modulo 4$: dbf d6,1$ ; DEC Höhe, Loop moveq.l #1,d0 ; 'Not empty' bra.b AutoResizeEnd ; ---> ByteMapEmpty: moveq.l #0,d0 ; 'Empty' AutoResizeEnd: movem.l (SP)+,d1-d6/a0-a3 rts *************************************************************************** ** ** ** FlipXByteMap - ByteMap in X-Richtung spiegeln ** ** ** *************************************************************************** ** ** ** Parameter : A0.L : Zeiger auf struct ByteMap ** ** ** ** Resultat : nix ** ** ** *************************************************************************** @FlipXByteMap: movem.l d0-d3/a0-a2,-(SP) move.w bym_Width(a0),d0 ; Breite in Pixel move.w bym_Height(a0),d1 ; Höhe in Pixel movea.l bym_Plane(a0),a0 ; Plane bra.b 4$ ; für dbf 1$: move.w d0,d2 asr.w #1,d2 ; X/2 movea.l a0,a1 ; links lea 0(a1,d0.w),a2 ; rechts bra.b 3$ ; für dbf 2$: move.b (a1),d3 ; Pixel swappen move.b -(a2),(a1)+ move.b d3,(a2) 3$: dbf d2,2$ adda.w d0,a0 ; Nächste Linie 4$: dbf d1,1$ movem.l (SP)+,d0-d3/a0-a2 rts *************************************************************************** ** ** ** FlipYByteMap - ByteMap in Y-Richtung spiegeln ** ** ** *************************************************************************** ** ** ** Parameter : A0.L : Zeiger auf struct ByteMap ** ** ** ** Resultat : nix ** ** ** *************************************************************************** @FlipYByteMap: movem.l d0-d3/a0-a1,-(SP) move.w bym_Width(a0),d0 ; Breite in Pixel move.w bym_Height(a0),d1 ; Höhe in Pixel movea.l bym_Plane(a0),a0 ; Plane move.w d1,d2 subq.w #1,d2 mulu.w d0,d2 movea.l a0,a1 adda.l d2,a1 ; A1: Letzte Linie lsr.w #1,d1 ; D1: Höhe/2 bra.b 4$ ; für dbf 1$: move.w d0,d2 ; Breite bra.b 3$ ; für dbf 2$: move.b (a0),d3 move.b (a1),(a0)+ move.b d3,(a1)+ 3$: dbf d2,2$ suba.w d0,a1 suba.w d0,a1 4$: dbf d1,1$ movem.l (SP)+,d0-d3/a0-a1 rts *************************************************************************** ** ** ** RotateByteMap - ByteMap um einen bestimmten Punkt/Winkel rotieren ** ** ** ** ** *************************************************************************** ** ** ** Parameter : A0.L : Zeiger auf struct ByteMap (Source) ** ** A1.L : Zeiger auf struct ByteMap (Destination) ** ** D0.L : Rotationsmittelpunkt X ** ** D1.L : Rotationsmittelpunkt Y ** ** D2.L : Sinus des Rotationswinkels <<10 ** ** D3.L : Cosinus des Rotationswinkels <<10 ** ** ** ** Resultat : nix ** ** ** *************************************************************************** * x2 = (x1-xm)*cos - (y1-ym)*sin +xm * y2 = (x1-xm)*sin + (y1-ym)*cos +ym @RotateByteMap: movem.l d0-d7/a0-a4,-(SP) movem.l 13*4+4(SP),d2-d3 move.w bym_Width(a0),d4 ; D4 : Breite in Pixel move.w bym_Height(a0),d5 ; D5 : Höhe in Pixel movea.l bym_Plane(a0),a0 ; A0 : Source-Plane movea.l bym_Plane(a1),a1 ; A1 : Destination-Plane suba.l a3,a3 ; A3 : Y-Zähler 1$: suba.l a2,a2 ; A2 : X-Zähler 2$: move.w a2,d6 ; X sub.w d0,d6 ; -Xm muls.w d3,d6 ; *cos move.w a3,d7 ; Y sub.w d1,d7 ; -Ym muls.w d2,d7 ; *sin sub.l d7,d6 asr.l #5,d6 ; Fixkomma to int asr.l #5,d6 add.l d0,d6 ; +Xm bpl.b 4$ 3$: clr.b (a1)+ bra.b 5$ 4$: cmp.w d4,d6 bge.b 3$ move.l d6,a4 ; X2 move.w a2,d6 ; X sub.w d0,d6 ; -Xm muls.w d2,d6 ; *sin move.w a3,d7 ; Y sub.w d1,d7 ; -Ym muls.w d3,d7 ; *cos add.l d7,d6 asr.l #5,d6 ; Fixkomma to int asr.l #5,d6 add.w d1,d6 ; +Ym gibt Y2 bmi.b 3$ cmp.w d5,d6 bge.b 3$ muls.w d4,d6 ; * Breite add.l a4,d6 ; + X2 gibt Offset move.b 0(a0,d6.l),(a1)+ ; Tada! 5$: addq.w #1,a2 ; INC X cmp.w d4,a2 ; == width ? blt.b 2$ ; nope ---> addq.w #1,a3 ; INC Y cmp.w d5,a3 ; == height ? blt.b 1$ ; nope ---> movem.l (SP)+,d0-d7/a0-a4 rts *************************************************************************** ** ** ** ZoomByteMap - ByteMap um einen bestimmten Faktor zoomen ** ** ** ** ** *************************************************************************** ** ** ** Parameter : A0.L : Zeiger auf struct ByteMap (Source) ** ** A1.L : Zeiger auf struct ByteMap (Destination) ** ** D0.L : Zoomfaktor in Prozent ** ** ** ** Resultat : nix ** ** ** *************************************************************************** * x2 = (x1-xm)*f + xm * y2 = (y1-ym)*f + ym @ZoomByteMap: movem.l d0-d7/a0-a2,-(SP) tst.l d0 beq .ZoomEnd move.w bym_Width(a1),d4 ; D4 : Breite in Pixel move.w bym_Height(a1),d5 ; D5 : Höhe in Pixel movea.l bym_Plane(a0),a0 ; A0 : Source-Plane movea.l bym_Plane(a1),a1 ; A1 : Destination-Plane move.w d4,d6 lsr.w #1,d6 ; D6 : Mittelpunkt X move.w d5,d7 lsr.w #1,d7 ; D7 : Mittelpunkt Y moveq #0,d2 ; D2 : Y-Zähler .YLoop: moveq #0,d3 ; D3 : X-Zähler .XLoop: move.w d3,d1 ; X1 sub.w d6,d1 ; -xm muls.w #100,d1 divs.w d0,d1 ; * f add.w d6,d1 ; +xm bmi.b .Next ; X < 0 ---> unsichtbar cmp.w d4,d1 bge.b .Next ; X > xmax ---> unsichtbar movea.w d1,a2 ; macht auch ext.l move.w d2,d1 ; Y1 sub.w d7,d1 ; -ym muls.w #100,d1 divs.w d0,d1 ; * f add.w d7,d1 ; +ym bmi.b .Next ; Y < 0 ---> unsichtbar cmp.w d5,d1 bge.b .Next ; Y > xmax ---> unsichtbar mulu.w d4,d1 ; mal Breite add.l a2,d1 ; +X move.b 0(a0,d1.l),(a1) ; Tada! .Next: addq.l #1,a1 ; INC destination addq.w #1,d3 ; INC X cmp.w d4,d3 ; X == Width ? blt.b .XLoop ; noch nicht ---> Loop addq.w #1,d2 ; INC Y cmp.w d5,d2 ; Y == Height ? blt.b .YLoop ; noch nicht ---> Loop .ZoomEnd: movem.l (SP)+,d0-d7/a0-a2 rts *************************************************************************** ** ** ** ValidatePlanePointers - Letzten gültigen Plane-Pointer in alle ** ** ungültigen Plane-Pointers kopieren ** ** ** *************************************************************************** ** ** ** Parameter : A2-A6: Zeiger auf Bitplanes oder NULL wenn ungültig ** ** ** ** Resultat : A2-A6: Zeiger auf BitPlanes, nirgends mehr NULL ** ** ** *************************************************************************** ValidatePlanePointers: move.l a3,d0 ; Plane 1 gültig ? bne.b 1$ ; ja ---> movea.l a2,a3 ; Sonst Plane 0 übernehmen 1$: move.l a4,d0 ; Plane 2 gültig ? bne.b 2$ ; ja ---> movea.l a3,a4 ; Sonst Plane 0 übernehmen 2$: move.l a5,d0 ; Plane 3 gültig ? bne.b 3$ ; ja ---> movea.l a4,a5 ; Sonst Plane 0 übernehmen 3$: move.l a6,d0 ; Plane 4 gültig ? bne.b 4$ ; ja ---> movea.l a5,a6 ; Sonst Plane 0 übernehmen 4$: rts END