home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Vectronix 2
/
VECTRONIX2.iso
/
FILES_03
/
JAG_DOX.ZIP
/
tutorial.txt
< prev
Wrap
Text File
|
1996-01-27
|
13KB
|
406 lines
# -------------------------------------------------------------------
# BLITTER TUTORIAL (c) Copyright 1996 Nat! & KKP
# -------------------------------------------------------------------
# These are some of the results/guesses that Klaus and Nat! found
# out about the Jaguar with a few helpful hints by other people,
# who'd prefer to remain anonymous.
#
# Since we are not under NDA or anything from Atari we feel free to
# give this to you for educational purposes only.
#
# Please note, that this is not official documentation from Atari
# or derived work thereof (both of us have never seen the Atari docs)
# and Atari isn't connected with this in any way.
#
# Please use this informationphile as a starting point for your own
# exploration and not as a reference. If you find anything innacurate,
# missing, needing more explanation etc. by all means please write
# to us:
# nat@zumdick.rhein-main.de
# or
# kkp@gamma.dou.dk
#
# If you could do us a small favor, don't use this information for
# those lame flamewars on r.g.v.a or the mailing list.
#
# HTML soon ?
# -------------------------------------------------------------------
# $Id: tutorial.txt,v 1.4 1996/01/27 15:22:58 nat Exp $
# -------------------------------------------------------------------
Blitter tutorial:
=-=-=-=-=-=-=-=-=
Here are a few examples, that should work. They haven't been tested (yet).
(note: not the best code, but hopefully understandable)
a) Clearing 256 bytes starting from $2000
--------------------------------------
.wait:
move.l B_CMD,d0 ;; wait for blitter to finish
ror.w #1,d0 ;; Check if blitter is idle
bcc.b .wait ;; bit was clear -> busy
move.l #$2000,A1_BASE ;; point to destination
move.l #$0,A1_PIXEL ;; start in front
move.l #PIXEL16|XADDPHR|PITCH1,A1_FLAGS ;; use 16bit pixels/phrasemode
move.l #0,B_PATD ;; our value to draw
move.w #1,d0 ;; we wanna draw 1 'line'
swap d0 ;; in upper word
move.w #256/2/4,d0 ;; and 256 bytes == 128 16-bit-pixels
move.l d0,B_COUNT ;; == 32 phrases
move.l #PATDSEL,B_CMD ;; use B_PATD to draw and GO
b) Setting 256 bytes starting at $2001 to 0xFF:
-------------------------------------------
move.l #$2000,A1_BASE ;; point to destination
move.l #$1,A1_PIXEL ;; start at offset 1
move.l #PIXEL8|XADDPIX|PITCH1,A1_FLAGS ;; use 8bit pixels pixelmode
move.l #$FF,B_PATD ;; our value to draw
move.w #1,d0 ;; we wanna draw 1 'line'
swap d0 ;; in upper word
move.w #256,d0 ;; and 256 bytes == 256 8-bit-pixels
move.l d0,B_COUNT
move.l #PATDSEL,B_CMD ;; use B_PATD to draw and GO
c) Copying 256 bytes from $2000 to $3000
------------------------------------
move.l #$3000,A1_BASE ;; point to destination
move.l #$0,A1_PIXEL ;; start in front
move.l #PIXEL16|XADDPHR|PITCH1,A1_FLAGS ;; use 16bit pixels/phrasemode
move.l #$2000,A2_BASE ;; point to source
move.l #$0,A2_PIXEL ;; start in front
move.l #PIXEL16|XADDPHR|PITCH1,A2_FLAGS ;; use 16bit pixels/phrasemode
move.w #1,d0 ;; we wanna draw 1 'line'
swap d0 ;; in upper word
move.w #256/2/4,d0 ;; and 256 bytes == 128 pixels
move.l d0,B_COUNT ;; == 32 phrases
move.l #LFU_REPLACE|SRCEN,B_CMD ;; straight copy
d) XORing 256 bytes from $2000 with $3000
------------------------------------
as c) but
move.l #LFU_XOR|DSTEN|SRCEN,B_CMD
instead of
move.l #LFU_REPLACE|SRCEN,B_CMD
e) Gouraudshading a horizontal 64 pixel line
on a 320x200 bitmap at $20000 starting at relative point 100,120
--------------------------------------------------------------
move.l #$20000,A1_BASE ;; point to destination
move.w #120,d0 ;; Y pos
swap d0 ;; in upper word
move.w #100,d0 ;; X pos in lower
move.l d0,A1_PIXEL ;; start in the middle
move.l #PIXEL16|XADDPIX|WID320|PITCH1,A1_FLAGS ;; note the WID320!!
move.w #$8000,B_PATD ;; starting color
move.l #$00038000,B_IINC ;; intensity increment (3.5)
move.w #1,d0 ;; we wanna draw 1 'line'
swap d0 ;; in upper word
move.w #64,d0 ;; and 64 pixels
move.l d0,B_COUNT
move.l #PATDSEL|GOURD,B_CMD
f) Blitting a 64x64 piece from a 128x128 pixmap (Pos: 10, 20)
unto a 320x200 pixmap with source shading (Pos: 100,120).
The source is at $30000 the destination at $20000.
--------------------------------------------------------------
move.l #$20000,A1_BASE ;; point to destination
move.l #PIXEL16|XADDPIX|WID320|PITCH1,A1_FLAGS ;; note the WID320!!
move.w #120,d0 ;; Y pos
swap d0 ;; in upper word
move.w #100,d0 ;; X pos in lower
move.l d0,A1_PIXEL ;; start in the middle
move.w #1,d0
swap d0
move.w #-64,d0
move.l d0,A1_STEP
move.l #$30000,A2_BASE
move.l #PIXEL16|XADDPIX|WID128|PITCH1,A2_FLAGS
move.w #12,d0 ;; Y pos
swap d0 ;; in upper word
move.w #10,d0 ;; X pos in lower
move.l d0,A2_PIXEL
move.w #1,d0
swap d0
move.w #-64,d0
move.l d0,A2_STEP
move.w #64,d0 ;; we wanna draw 64 lines
swap d0 ;; in upper word
move.w #64,d0 ;; and 64 pixels each
move.l d0,B_COUNT
move.l #$00040000,B_IINC ;; shade value for source
move.l #SRCEN|DSTEN|UPDA1|UPDA2|SRCSHADE,B_CMD
g) Blitting a 64x64 piece from a 128x128 pixmap (Pos: 10, 20)
unto a 320x200 pixmap with source shading (Pos: 100,120).
The pixmap will appear rotated about 45 degrees
The source is at $30000 the destination at $20000. (TESTED)
--------------------------------------------------------------
move.l #$20000,A1_BASE ;; point to destination
move.l #PIXEL16|XADDINC|WID320|PITCH1,A1_FLAGS ;; note the WID320!!
move.w #120,d0 ;; Y pos
swap d0 ;; in upper word
move.w #100,d0 ;; X pos in lower
move.l d0,A1_PIXEL ;; start in the middle
move.l #0,A1_INC ;; scaling in the X direction
move.w #$8000,d0 ;; and stepping diagonally
swap d0
move.w #$8000,d0
move.l d0,A1_FINC
move.w #-33,d0
swap d0
move.w #-32,d0
move.l d0,A1_STEP
move.w #$8000,d0
swap d0
move.w #$8000,d0
move.l d0,A1_FSTEP
move.l #$30000,A2_BASE
move.l #PIXEL16|XADDPIX|WID128|PITCH1,A2_FLAGS
move.w #12,d0 ;; Y pos
swap d0 ;; in upper word
move.w #10,d0 ;; X pos in lower
move.l d0,A2_PIXEL
move.w #1,d0
swap d0
move.w #-64,d0
move.l d0,A2_STEP
move.w #64,d0 ;; we wanna draw 64 lines
swap d0 ;; in upper word
move.w #64,d0 ;; and 64 pixels each
move.l d0,B_COUNT
move.l #$00040000,B_IINC ;; shade value for source
move.l #LFU_REPLACE|DSTEN|SRCEN|UPDA1|UPDA1F|UPDA2|SRCSHADE,B_CMD
Rotating with the blitter:
=-=-=-=-=-=-=-=-=-=-=-=-=
Scaling and rotation are really nice effects you can do with the
blitter. But you got to be careful that you don't leave holes
accidentally on the screen.
There are two ways to produce holes, one because of using a step
size (in either direction) that is larger than 1. This should be
obvious I guess.
The other not so obvious source of holes are quantization errors.
For example to rotate a bitmap around 30 degrees, you might do these
calculations:
a
A +--------+ B our source pixmap of size 64x64
| |
| | a a == 64
| |
D +--------+ C
A x
........+......... That's how it should look like
/ \ . rotated
/ \ . y
/ \.
D + + B
\ /
a \ / a
\ /
+ C
A x
+........... a magnified look at the upper corner
\m) 90 . we notice that:
\ .
\ .
\ . x = cos( m) * a
\ . y y = sin( m) * a
a \ .
\ .
\ . m = 30 deg
\ . x = 55.43 = $0037.6CF5
\. y = 32.00 = $0020.0000
+
B
hor increment = x / a = cos( m) = 0.87 = $0.DDB4 ($1.0000 * 0.87)
ver increment = y / a = sin( m) = 0.50 = $0.8000
Y X
--------+-----+-----+
A1_INC 0 0
A1_FINC $8000 $DDB4
We wanna draw in runs from A to B. Now after a line has been drawn. We
need to step back to the point we came from (A) (-55.43,-32) and then
move in a 60 degree (180 - 90 - 30) angle backwards (-)
and downwards (+), down the left slope (A -> D).
To get it perfect we calculate everything in integer fractional
representation (like the Blitter does):
Y X
64 * A1_INC.A1_FINC = $20.0000 $37.6D00
hor step = -x - cos( 60) = -$37.6D00 - $8000 = $FFC81300
ver step = -y + sin( 60) = -$20.0000 + $DDB4 = $FFE0DDB4
Y X
--------+-----+-----+
A1_STEP $FFE0 $FFC8
A1_FSTEP $DDB4 $1300
Now if you blit something on the screen you'll see holes (not
drawn pixels) in your pixmap, although the step size in both
directions is 1 (sin(x)^2 + cos(x)^2 = 1). The error is introduced
while the blitter is stepping in the 'integer.fractional' domain
and then plots a pixel in the 'integer' domain. What I mean with
'integer.fractional' domain are the contents of the A1_PIXEL, A1_FPIXEL
and the A1_FPIXEL and the A1_INC, A1_FINC registers.
The problem will be visible on adjacent lines only, because the
quantization of the pixels, which starts at a different fractional
offset, will be slightly but decisively different for the subsequent
runs.
Try the following program. Run it once with BLOCK set to 1 and look
at the resulting moiree pattern. Now set BLOCK to 0 and examine the
colored lines closely (drawn in sequence from top to bottom) and notice
how each line differs from the next.
BLOCK equ 1
.if BLOCK
HEIGHT equ 64
WIDTH equ 64
.else
HEIGHT equ 16
WIDTH equ 16
.endif
HINC equ $DDB4
VINC equ $8000
HSTEP equ -(HEIGHT*HINC)-VINC
VSTEP equ -(WIDTH*VINC)+HINC
blit:
.wait:
move.l B_CMD,d0
lsr.w #1,d0
bcc.b .wait
move.l #$20000,A1_BASE ;; point to destination
move.l #PIXEL16|XADDINC|WID256|PITCH1,A1_FLAGS ;; note the WID320
move.w #64,d0 ;; Y pos
swap d0 ;; in upper word
move.w #128,d0 ;; X pos in lower
move.l d0,A1_PIXEL ;; start in the middle
move.l #$0,A1_FPIXEL
move.l #$0,A1_INC
move.w #VINC,d0
swap d0
move.w #HINC,d0
move.l d0,A1_FINC
.if BLOCK
move.w #VSTEP>>16,d0
.else
move.w #(VSTEP>>16)+2,d0 ;; uncomment this, comment out next
.endif
swap d0
move.w #HSTEP>>16,d0
move.l d0,A1_STEP
move.w #VSTEP&$FFFF,d0
swap d0
move.w #HSTEP&$FFFF,d0
move.l d0,A1_FSTEP
move.w #HEIGHT,d0 ;; we wanna draw # lines
swap d0 ;; in upper word
move.w #WIDTH,d0 ;; and # pixels each
move.l d0,B_COUNT
.if BLOCK
move.l #PATDSEL|UPDA1|UPDA1F|LFU_REPLACE,B_CMD
.else
move.l #$01000000,B_IINC
move.l #$00C0,B_PATD
move.l #GOURD|TOPBEN|PATDSEL|UPDA1|UPDA1F|LFU_REPLACE,B_CMD
.endif
rts
How do you get rid of the holes ?
If you want to use the blitter for rotation, you probably should scale
down the bitmaps you want to rotate. Maybe using a 96x96 source
pixmap for a 'apparent' 64x64 target pixmap size will be sufficient.
You gotta experiment. It depends on the rotation angle!
( Well there's a software method I did once, which can do rotation without
holes. It goes basically like this:
Use the steepest slope for "STEP" use the other slope for your
line drawings (like Bresenham f.e.)
Use the most outside pixel as your starting pixel
Draw a line with the required slope.
Do an integer step horizontally (or vertically but not both) away
from your first starting pixel.
Skip as many pixels as needed until you want to start drawing.
Draw the line.
I can't quite see this being done with the blitter though :).
)