home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Elysian Archive
/
AmigaElysianArchive.iso
/
prog
/
source
/
dcassem.lha
/
No.19
< prev
next >
Wrap
Text File
|
1988-05-14
|
8KB
|
216 lines
CODE
NOLIST
INCLUDE "exec/types.i"
INCLUDE "graphics/rastport.i"
INCLUDE "custom.i"
INCLUDE "globals.i"
LIST
XREF _LVOOwnBlitter,_LVODisownBlitter
XDEF Draw,Line,Clear
;============================================================================
; Draw( rp,x2,y2 )
; a0 d0 d1
;
; Same as line but calls OwnBlitter before calling the line drawing routine.
;============================================================================
Draw move.l a6,-(sp)
movea.l GfxLib(a5),a6 need to own the blitter
movem.l d0/d1/a0,-(sp) save line arguments
jsr _LVOOwnBlitter(a6) get the blitter
movem.l (sp)+,d0/d1/a0 restore line args
bsr.s Line draw the line
jsr _LVODisownBlitter(a6) give blitter back to system
movea.l (sp)+,a6
rts
;============================================================================
; NAME
; Line ( rp,x2,y2 )
; a0 d0 d1
;
; Draws a line from the current position to x2,y2 in the given RastPort.
; Current color, linepat, mask and flags are observed from the rastport info.
; The blitter must be owned before calling this routine to draw lines.
;============================================================================
Line movem.l d2-d6/a2-a3,-(sp)
movea.l rp_BitMap(a0),a1 point to the bitmap struct
movea.l #_custom,a3 point to custom chips
move.w d0,d2 get start and end points
move.w d1,d3
movem.w rp_cp_x(a0),d0/d1 start positions
movem.w d2/d3,rp_cp_x(a0) save new start position
moveq.l #$0f,d4 compute ASH3-ASH0
and.w d0,d4 for preshifting bltadat
sub.w d0,d2 convert X2 to deltaX
sub.w d1,d3 convert Y2 to deltaY
mulu.w bm_BytesPerRow(a1),d1 offset to correct bitmap row
lsr.w #3,d0 convert X1 to a byte offset
add.w d0,d1 now d1=offset into bitplanes
; compute the correct octant code for this line ( SUD,SUL,AUL ) and get the
; absolute value of max(deltaX, deltaY) into D2 for use as the line length.
tst.w d2
bmi.s 40$ deltaX is negative
; when deltaX is positive, use the following octant generation decisions
tst.w d3 if deltaY is positive
bmi.s 20$
cmp.w d3,d2 ...then if deltaX > deltaY...
blt.s 10$
moveq.l #OCT4,d5 ...octant=4
bra.s GotOctant
10$ moveq.l #OCT0,d5 ...else octant=0...
exg d2,d3 ...and switch the delta values
bra.s GotOctant
20$ neg.w d3 else deltaY = -deltaY...
cmp.w d3,d2 ...if deltaX > deltaY...
blt.s 30$
moveq.l #OCT6,d5 ...octant=6
bra.s GotOctant
30$ moveq.l #OCT1,d5 ...else octant=1...
exg d2,d3 ...and switch the delta values
bra.s GotOctant
; but when deltaX is negative, use these octant generation decisions instead
40$ neg.w d2 deltaX = -deltaX
tst.w d3 if deltaY is positive...
bmi.s 60$
cmp.w d3,d2 ...then if deltaX > deltaY
blt.s 50$
moveq.l #OCT5,d5 ...octant=5
bra.s GotOctant
50$ moveq.l #OCT2,d5 ...else octant=2...
exg d2,d3 ...and switch the delta values
bra.s GotOctant
60$ neg.w d3 else deltaY = -deltaY
cmp.w d3,d2 if deltaX > deltaY...
blt.s 70$
moveq.l #OCT7,d5 ...octant=7
bra.s GotOctant
70$ moveq.l #OCT3,d5 ...else octant = 6...
exg d2,d3 ...and switch the delta values
; gets to here with the octant code in D5 and ABS(MAX(deltaX,deltaY)) in D2
GotOctant addq.w #1,d2 *** is this right ? ***
5$ add.w d3,d3 D3 = 2Y
move.w d3,d0 calculate initial error term
sub.w d2,d0 D0=2Y-X
bpl.s 10$ no need to set SIGN
ori.w #SIGN,d5 initial term is negative so...
; we start one line further up
; this is a bit tricky, we need the start code in the top 4 bits of d5 and d4
; but they are currently in the low 4 bits of d4. Instead of shifting them
; all the way up to position, we just rotate them around and or them in.
10$ ror.w #4,d4 move start code to top bits
or.w d4,d5 need shift in both halves...
; to shift line pattern too
ori.w #USEA!USEC!USED,d4 move in codes for DMA channels
; OK, let's start stuffing registers that won't change between successive blits
; so we can speed up the innner loop that draws a line in each bit plane. Make
; sure that the blitter is not busy from a previous line draw routine before
; we start storing to the registers.
move.w #BBUSY,d6
20$ and.w dmaconr(a3),d6 wait for the blitter to finish
bne.s 20$ still busy
move.w #SETBIT!BLTPRI,dmacon(a3) give blit high priority
move.w d3,bltbmod(a3) bltbmod=2Y
move.w d0,d3
sub.w d2,d3 compute 2Y-2X
move.w d3,bltamod(a3) bltamod=2Y-2X
move.w bm_BytesPerRow(a1),bltcmod(a3)
move.w bm_BytesPerRow(a1),bltdmod(a3)
moveq.l #-1,d3 first and last masks = $FFFF
move.l d3,bltafwm(a3) this stores to both
move.w rp_LinePtrn(a0),bltbdat(a3) set up line pattern
asl.w #6,d2 convert line length to bltsize
addq.w #2,d2 width=2 for all line drawing
move.w d5,bltcon1(a3) set up bltcon1
; stash things that need frequent reference during the plane drawing loop
move.b rp_FgPen(a0),d5 get pen color
and.b rp_Mask(a0),d5 and observe mask
clr.w d3
move.b bm_Depth(a1),d3 get a plane counter
lea.l bm_Planes(a1),a1 point to array of plane ptrs
bra.s LoopEntry
; this is the loop that draws lines in each of the required bitplanes.
; Registers are set up as follows:-
; D0 = 2Y-X
; D1 = Offset in bitplane to first word of the line
; D2 = BlitSize to start the blitter with
; D3 = plane counter
; D4 = bltcon0
; D5 = pencolor
; A1 = pointer to bitplane pointers
; A3 = pointer to custom chips
; Notice that during the loop, the blitter can be busy drawing the last line
; segment while the CPU is setting up for the next load of stores.
PlaneLoop movea.l (a1)+,a2 get next bitplane address
adda.w d1,a2 start address of line
move.b #$0a,d4 assume erasing (minterm = NAC)
lsr.w #1,d5 shift next bit into carry
bcc.s 5$ it's 0 so erase this bit
move.b #$ca,d4 NAC+AB we are drawing the line
5$ move.w #BBUSY,d6
10$ and.w dmaconr(a3),d6 wait for the blitter to finish
bne.s 10$ still busy
move.w #$8000,bltadat(a3) put in the line bit
move.l a2,bltcpth(a3) fill in line start address...
move.l a2,bltdpth(a3) ...of this line
move.w d0,bltaptl(a3) 2Y-X, needs reloading each use
move.w d4,bltcon0(a3) store the minterm and stuff
move.w d2,bltsize(a3) ZOOOOM! start the line draw
LoopEntry dbra d3,PlaneLoop and do the next plane
movem.l (sp)+,d2-d6/a2-a3 restore regs
rts all done
;============================================================================
; Clear( rp )
; a0
;
; Clears ALL bitmap memory in the given rastport. Must call OwnBlitter()
; before calling this routine (or nasty things will happen fer sure).
; This routine assumes all bitplanes are contiguous in memory!!!!!!!!!!!!
;============================================================================
Clear movea.l #_custom,a1 point to custom chips
movea.l rp_BitMap(a0),a0 get the bitmap ptr
moveq.l #0,d0
moveq.l #0,d1
move.w bm_Rows(a0),d0 calculate blitsize
move.b bm_Depth(a0),d1
mulu.w d1,d0 d0 = #lines to clear
lsl.l #6,d0 move to correct bits
move.w bm_BytesPerRow(a0),d1 get width in words
lsr.w #1,d1
or.w d1,d0 d0 = bltsize reg
move.w #BBUSY,d1
10$ and.w dmaconr(a1),d1 wait for blitter to finish
bne.s 10$ the last operation
move.w #SETBIT!BLTPRI,dmacon(a1) blitter nasty
clr.l bltamod(a1) bltamod & bltbmod = 0
clr.l bltcmod(a1) bltcmod & bltdmod = 0
clr.w bltcon1(a1) no shift or anything special
move.w #$01f0,bltcon0(a1) only using destination
move.l bm_Planes(a0),bltdpth(a1) where we are storing to
clr.w bltadat(a1) what we are storing (0's)
move.w d0,bltsize(a1) start the blit
rts done
END