Article View: comp.sys.amiga.tech
Article #7577Re: Animate vs Manual Blitter
From: Mike Farren
Date: Wed, 19 Dec 1990 09:47
Date: Wed, 19 Dec 1990 09:47
335 lines
16986 bytes
16986 bytes
pashdown@javelin.es.com (Pete Ashdown) writes:
>farren@well.sf.ca.us (Mike Farren) writes:
>>I whipped up a quick blitter routine in assembly
>Hey Mike, how about a post of that routine?
Sure thing. Here you are:
; This routine draws an object directly to the bitplanes.
;
; The shape data is organized as one large block, for ease of loading via
; a standard "fread" statement. In this case, there are 73 shapes possible,
; and the shape number and location onscreen are passed to the drawshape
; routines.
; There are five arrays, plus the actual shape data. The first two arrays
; are held in the area pointed to by the "shape" pointer, and are
; a series of pointers to the shape and mask data, respectively. The
; next three are held in the area pointed to by the "shapeinfo" pointer,
; and are the width of the shape (in pixels), the height of the
; shape (in lines), and the modulo of the shape (the number of bytes per
; line - with this data being constrained to either two or three bytes).
;
; The shape data is simply the bit patterns of the shape, plane by plane.
; The mask data is used to "cookie-cut" the shape onto the screen, and
; is the bit pattern of the shape, with a set bit whenever the same
; bit in the final shape is not transparent. The first longword in
; the shape data is a length word, indicating the total length of the
; data area - this is for simplicity in loading.
; The basic coordinates are held in a Mac-like "rect" array, which holds
; four words: the leftmost x coordinate, the topmost y coordinate, the
; rightmost x coordinate, and the bottommost y coordinate. This arrangement
; makes it easy to compute collisons between rectangles.
LEFT EQU 0
TOP EQU 2
; The offsets into the big array are precomputed for ease of access
SHOFF EQU 0 ;The offset of the shape data pointers
MOFF EQU 292 ;The offset of the mask data pointers
HEIGHT EQU 584 ;The offset of the height values
WIDTH EQU 146 ;The offset of the width values
MODULO EQU 292 ;The offset of the modulo values
include 'types.i'
include 'custom.i'
include 'blit.i'
include 'dmabits.i'
CSECT data,1
; these are the externals. Mostly self-explanatory, except for "bp",
; which is an array of pointers to the individual bitplanes which make
; up the playfield. In this example, four planes are hardwired in.
XREF _Screen ; The screen structure (playfield)
XREF _custom ; To point to blitter
XREF _shapes ; The shape and mask data
XREF _bp ; a pointer to the bitplane pointers
XREF _shapeinfo ; The shape height, width, and modulo
; these are defined here for debugging purposes only.
XDEF fbltcon0
XDEF fbltcon1
XDEF fbltafwm
XDEF fbltalwm
XDEF fbltcpth
XDEF fbltcptl
XDEF fbltbpth
XDEF fbltbptl
XDEF fbltapth
XDEF fbltaptl
XDEF fbltdpth
XDEF fbltdptl
XDEF fbltsize
XDEF fbltcmod
XDEF fbltbmod
XDEF fbltamod
XDEF fbltdmod
; these are the blitter shadow registers. For some reason, direct writes
; to the blitter register did not work correctly, while indirect writes
; did not. I haven't the slightest idea why - but this works, at the
; cost of one additional set of accesses.
fbltcon0: DC.W 0
fbltcon1: DC.W 0
fbltafwm: DC.W 0
fbltalwm: DC.W 0
fbltcpth: DC.W 0
fbltcptl: DC.W 0
fbltbpth: DC.W 0
fbltbptl: DC.W 0
fbltapth: DC.W 0
fbltaptl: DC.W 0
fbltdpth: DC.W 0
fbltdptl: DC.W 0
fbltsize: DC.W 0
fbltcmod: DC.W 0
fbltbmod: DC.W 0
fbltamod: DC.W 0
fbltdmod: DC.W 0
CSECT text
; drawshape(number, where)
; short number;
; struct Rect *where;
;
; (using Lattice register parameter passing, number is passed in d0,
; the pointer to where in a0.)
;
; eraseshape(number, where)
; parameters as above.
XDEF _drawshape
XDEF _eraseshape
; outside routines used, using Lattice's bindings instead of "OVF" styles.
XREF _OwnBlitter
XREF _DisownBlitter
XREF _WaitBlit
_drawshape:
movem.l d2-d7/a2-a6,-(a7)
lea _custom,a5 ;point to the custom address
;Calculate the bitplane offset for this X,Y value - place into D2, with
;D3 the number of pixels offset from the word boundary
move (a0)+,d2 ;get the Y value
ext.l d2 ;make it a long
asl.l #3,d2 ;d2 = Y*8
move.l d2,d1 ;save it for now
asl.l #2,d2 ;d2 = Y*32
add.l d1,d2 ;d2 = Y*40
move (a0),d3 ;d3 = X
ext.l d3 ;make it long
move.l d3,d1 ;temp save x in d0
andi.l #15,d3 ;d3 = bit shift
ror.w #4,d3 ;move to high order nibble
asr.l #3,d1 ;d0 = words of x
andi #$fffffffe,d1 ;convert to word address
add.l d1,d2 ;d2 = y*40+x
;Extract addresses and dimensions from shapeinfo. Figure address ends up
;in A2, mask address in A3. Height in d4, modulo in d5. Setup some of
;the blitter shadow registers as appropriate.
ext.l d0 ;make the number a fake long
movea.l _shapeinfo,a0 ;point to the shape information
adda.l #4,a0 ;a0 points to shape data offset
movea.l a0,a4 ;save it here, too...
adda.l #HEIGHT,a4 ;a4 points to height data offset
asl.l #1,d0 ;times two (for WORD)
adda.l d0,a4 ;calculate height offset
asl.l #1,d0 ;calculate the offset for data
adda.l d0,a0 ;a0 points to figure data offset
movea.l _shapes,a2 ;get the shape data pointer
movea.l a2,a3 ;into both registers
adda.l (a0),a2 ;a2 now points to figure data
adda.l MOFF(a0),a3 ;a3 now points to mask data
move.w (a4),d4 ;d4 now has the height
move.w MODULO(a4),d6 ;and d6 the modulo
;Setup the blitter shadow registers. Most of these will not change
;from plane to plane, so can be set up now.
move.l a3,fbltbpth ;address of mask data in "B"
move.w #0,fbltamod ;no modulo for figure
move.w #0,fbltbmod ;or mask
move.l #-1,fbltafwm ;setup masks
move.l #$0fe20000,d0 ;save bltcons temporarily
or.l d3,d0 ;or in the "b" shift value
swap d3 ;swap words in shift
or.l d3,d0 ;"or" in the "a" shift value
move.l d0,fbltcon0 ;setup controller
move.w d4,d5 ;calculate the modulo for figure
cmpi.w #3,d6 ;if modulo == 3, setup differs
bne.s notthree ;
asl.w #1,d4 ;height * 4 words
asl.w #2,d5 ;d5 = height * 4
add.w d4,d5 ;d4 = height * 6
asl.w #5,d4 ;d4 = vertical size
or.w #3,d4 ;horizontal size = 3
move.w d4,fbltsize
move.w #34,fbltcmod ;34 byte modulo for this one
move.w #34,fbltdmod ;and this, too.
bra.s domod ;finish it off
notthree:
asl.w #6,d4 ;size = height * 64
asl.w #2,d5 ;size of this bit plane mod.
or.w #2,d4 ;or in the width
move.w d4,fbltsize ;and save it
move.w #36,fbltcmod ;36 byte modulo for screen
move.w #36,fbltdmod ;in both registers
domod:
;Setup the pointer to the bitplanes in a4, and the bitplane counter in
;d7.
ext.l d5 ;make sure d5 is long
lea _bp,a4 ;get pointer to first plane
moveq #4,d7 ;do four planes
PlaneLoop: movea.l (a4)+,a0 ;a0 = bitplane to do
adda.l d2,a0 ;add in offset to first word
move.l a2,fbltapth ;address of data in "A"
move.l a0,fbltcpth ;address of screen in "C"
move.l a0,fbltdpth ;and in "D"
jsr DoRealBlit
adda.l d5,a2 ;point to next line of shape
subq.w #1,d7 ;
bne PlaneLoop ;and the planes
movem.l (a7)+,d2-d7/a2-a6 ;restore registers
rts ;and return
_eraseshape:
movem.l d2-d7/a2-a6,-(a7)
lea _custom,a5 ;point to the custom address
;Calculate the bitplane offset for this X,Y value - place into D2, with
;D3 the number of pixels offset from the word boundary
move (a0)+,d2 ;get the Y value
ext.l d2 ;make it a word
asl.l #3,d2 ;d2 = Y*8
move.l d2,d1 ;save it for now
asl.l #2,d2 ;d2 = Y*32
add.l d1,d2 ;d2 = Y*40
move (a0),d3 ;d3 = X
ext.l d3 ;make it a word
move.l d3,d1 ;temp save x in d0
andi.l #15,d3 ;d3 = bit shift
ror.w #4,d3 ;move to high order nibble
asr.l #3,d1 ;d0 = words of x
andi #$fffffffe,d1 ;convert to word address
add.l d1,d2 ;d2 = y*40+x
;Extract addresses and dimensions from shapeinfo. Mask address ends up
;in A2, height in d4, modulo in d5. Setup some of the blitter shadow
;registers as appropriate.
ext.l d0 ;extend the pointer to a long
movea.l _shapeinfo,a0 ;point to the shape information
adda.l #4,a0 ;a0 points to shape data offset
movea.l a0,a4 ;save it here, too...
adda.l #HEIGHT,a4 ;a4 points to height data offset
asl.l #1,d0 ;times two (for WORD)
adda.l d0,a4 ;calculate height offset
asl.l #1,d0 ;calculate the offset for data
adda.l d0,a0 ;a0 points to figure data offset
movea.l _shapes,a3 ;get the shape data pointer
adda.l MOFF(a0),a3 ;a3 now points to mask data
move.w (a4),d4 ;d4 now has the height
move.w MODULO(a4),d6 ;and d6 the modulo
;Setup the blitter shadow registers. Most of these will not change
;from plane to plane, so can be set up now.
move.l a3,fbltapth ;address of mask data in "A"
move.w #0,fbltamod ;no modulo for figure
move.l #-1,fbltafwm ;setup masks
move.l #$0b0a0000,d0 ;save bltcons temporarily
swap d3 ;swap words in shift
or.l d3,d0 ;"or" in the "a" shift value
move.l d0,fbltcon0 ;setup controller
cmpi #3,d6 ;if modulo == 3, setup differs
bne.s notthreea ;
asl.w #1,d4 ;height * 4 words
asl.w #2,d5 ;d5 = height * 4
add.w d4,d5 ;d4 = height * 6
asl.w #5,d4 ;d4 = vertical size
or.w #3,d4 ;horizontal size = 3
move.w d4,fbltsize
move.w #34,fbltcmod ;34 byte modulo for this one
move.w #34,fbltdmod ;and this, too.
bra.s domoda ;finish it off
notthreea:
asl.w #6,d4 ;size = height * 64
or.w #2,d4 ;or in the width
move.w d4,fbltsize ;and save it
move.w #36,fbltcmod ;36 byte modulo for screen
move.w #36,fbltdmod ;in both registers
domoda:
;Setup the pointer to the bitplanes in a4, and the bitplane counter in
;d7.
ext.l d5 ;make sure d5 is long
lea _bp,a4 ;get pointer to first plane
moveq #4,d7 ;do four planes
PlaneLoopa: movea.l (a4)+,a0 ;a0 = bitplane to do
adda.l d2,a0 ;add in offset to first word
move.l a0,fbltcpth ;address of screen in "C"
move.l a0,fbltdpth ;and in "D"
jsr DoRealBlit
subq.w #1,d7 ;
bne PlaneLoopa ;and the planes
movem.l (a7)+,d2-d7/a2-a6 ;restore registers
rts ;and return
DoRealBlit:
jsr _OwnBlitter
jsr _WaitBlit
move #$8400,dmacon(a5) ;nasty blitter
move fbltcon0,bltcon0(a5)
move fbltcon1,bltcon1(a5)
move fbltafwm,bltafwm(a5)
move fbltalwm,bltalwm(a5)
move.l fbltcpth,bltcpt(a5)
move.l fbltbpth,bltbpt(a5)
move.l fbltapth,bltapt(a5)
move.l fbltdpth,bltdpt(a5)
move fbltcmod,bltcmod(a5)
move fbltbmod,bltbmod(a5)
move fbltamod,bltamod(a5)
move fbltdmod,bltdmod(a5)
move fbltsize,bltsize(a5)
w1: btst #DMAB_BLTDONE-8,dmaconr(a5) ;check it
bne.s w1 ;loop 'til done
jsr _DisownBlitter
rts
end
--
Mike Farren farren@well.sf.ca.us
Technical Details
Message-ID:
<22246@well.sf.ca.us>Path:
arc1-ca.pugleaf.net!utzoo!attcan!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!sdd.hp.com!usc!apple!well!farrenReferences:
<BZLRT1w163w@ersys.uucp> <22111@well.sf.ca.us> <1990Dec12.140157.1352@javelin.es.com>Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!attcan!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!sdd.hp.com!usc!apple!well!farren From: farren@well.sf.ca.us (Mike Farren) Newsgroups: comp.sys.amiga.tech Subject: Re: Animate vs Manual Blitter Message-ID: <22246@well.sf.ca.us> Date: 19 Dec 90 09:47:08 GMT References: <BZLRT1w163w@ersys.uucp> <22111@well.sf.ca.us> <1990Dec12.140157.1352@javelin.es.com> Lines: 335