🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.sys.amiga.tech
Article #7577

Re: Animate vs Manual Blitter

#7577
From: Mike Farren
Date: Wed, 19 Dec 1990 09:47
335 lines
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!farren
References: <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