summaryrefslogtreecommitdiff
path: root/ByteMap.S
diff options
context:
space:
mode:
Diffstat (limited to 'ByteMap.S')
-rw-r--r--ByteMap.S591
1 files changed, 591 insertions, 0 deletions
diff --git a/ByteMap.S b/ByteMap.S
new file mode 100644
index 0000000..d2a0c04
--- /dev/null
+++ b/ByteMap.S
@@ -0,0 +1,591 @@
+**
+** 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