A.D.A. Amiga Demoscene Archive

  Welcome guest! Please register a new account or log in

  

  

  

Demos Amiga Demoscene Archive Forum / Coding / coding tutorial: the copper

 

Author Message
z5_
Member
#1 - Posted: 20 Nov 2004 11:04
Reply Quote
Please post all info about the copper in here :)
z5_
Member
#2 - Posted: 20 Nov 2004 11:44 - Edited by Admin
Reply Quote
Ok, i'm going to start with all that i have learned about the copper (which isn't much).

As far as i understand, the copper is used to move big parts of data to the custom chipset registers (graphics, sound, ...). You could do this without the copper, but it would be very slow (is that correct?). The copper has 3 instructions: wait, move and skip.

For example, suppose that you want to change the background color (=color 0, the color value is at $180) on screen. You've got to tell to the system what the new value of our background color will be. So you've got to move the new color value into $180.

You set up a copperlist (must always be in chip-mem) like this:

(data_c means that it will be loaded in chipmem?)

section copper,data_c
;--------------------------------------------------------------------- --------
;!! The copper list !!
;--------------------------------------------------------------------- --------
copper:
dc.w $0180,$ffff
dc.w $ffff,$fffe

Now, in your program, you can push a new color value into that copperlist like this (is this example correct??):
lea copper+2,a1
move.w $0ff0,(a1)

So the copperlist will look like this:
copper:
dc.w $0180,$0ff0 (we justed pushed $0ff0 in here instead of the original $ffff)
dc.w $ffff,$fffe

The last line (dc.w $ffff,$fffe) tells the copper where our copper list ends. We do this by asking the copper to wait for a position on screen that never can be reached ($ff horizontally is impossible) so the copper knows that this is the end of our list.


But this does not mean that the background will have changed color yet. For that, we need to do two things: tell the system where our copper list is in memory:

move.l #copper,$dff080

And tell the system that it should use that list instead of the previous one by writing a 0 to the strobe register:

move.w #0,$dff088

In this example, the color will be changed before the beam starts to build up the screen (does the copper move this data to the custom chipregisters only once, or every "scan' time?).

To go a bit further, one can also let the copper wait for a certain position on screen, then execute the copperlist, wait for another position on screen, change again.

Let's say we want the top half of our screen black, the bottom part white. We can let the copper wait for the beam to reach the middle of the screen, then push a new value into the background color. From then on, the screen will be white until the bottom. That is, i assume, how the rainbow colored backgrounds where made. Wait for a position on screen, change the background color, wait for another position on screen, change the background,...
Cyf
Member
#3 - Posted: 20 Nov 2004 13:02 - Edited
Reply Quote
?? $ff00 ??

$ff0 or $0ff0= RGB . only

move #$ff0,(a1)

Colorxx/bit:
15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
xx xx xx xx R3 R2 R1 R0 G3 G2 G1 G0 B3 B2 B1 B0

"does the copper move this data to the custom chipregisters only once, or every "scan' time?" :

the copper refresh registers each VBL
dalton
Member
#4 - Posted: 20 Nov 2004 20:36
Reply Quote
first I'd like to say that there's a chapter on the copper in Hardware Reference Manual which holds all the vital information. he who hasn't read it should =)

the copper is used to move big parts of data to the custom chipset registers (graphics, sound, ...)

that's not really it... the copper is used to set the custom registers, that is a form of data-moving I suppose, but not in the way you're thinking of. setting a bitplane pointer is not moving the picture into screen-memory, it's just telling the amiga where the to read from.

basically the copper is a simple command-interpreter, it has three commands...normally only move and wait is used...and that's why i can't remeber the third =)
by setting up the copper in different ways combining waits and moves you can make copper-bars, zoomers, highcolour-displays and much more.

there are some other interresting things that can be done with the copper aswell, such as blitter-queueing...i think dr.doom wrote some stuff about this in eurocharts, maybe someone has it in .txt format?
Cyf
Member
#5 - Posted: 20 Nov 2004 21:29 - Edited
Reply Quote
the copper is used to move big parts of data to the custom chipset registers (graphics, sound, ...).

Nop...it's the Blitter :)

the base of the copper is to set/write register values, and check/test some registers : set the screen (size, position, depth, resolution), sprites, colors, rasters...
but it can mofifying register value at any position of the rasterline, set multiple screenzone with different resolutions,colors...
the copper is a coprocesseur, because it use a special program with 3 instructions : copperlist

move: write value into a chip register ($dffxxx)
wait : wait a raster position
skip : skip the next instuction when raster reach the position set

wait(x1,y1) = # line * $100 + $f
move #0,$180
wait(x2,y2)

ex:
dc.w $180,0 ; color00 register to black
dc.w $300f,$fffe ; wait line $30 (Horizontal) (by default vertical pos=$F)
dc.w $180,$fff ; white
dc.w $310f,$fffe ; wait line $31
dc.w $180,0

for a perfect white raster

the end of the coplist is a special wait instruction with impossible position (horizontal pos>$e4). by default to $ffff,$fffe

but the copper is much more great! look coplist from Shadow of the beast, Jim Power...and demos FX
Cyf
Member
#6 - Posted: 20 Nov 2004 21:41 - Edited
Reply Quote
to set a standard good screen : registers :
DIWSTRT $8E : up left corner = $yyxx
position where start the raster (set for visible pos. yy~$28)
std = $2881

DIWSTOP $90 : bottom right corner
end of screen : $(yy+H)(xx+W) = $28D1

H vertical pos = Number of lines = $28+296 = $128 (keep 28)
W horiz. pos = number of cycles
1 cycle = 4 pix (8 in hires)
320 pix = 80 visible cycles = + $50 for end of screen

other registers :
DDFSTRT : horizontal pos of the start of Bitplan
DDFSTOP : horizontal pos of the end of Bitplan

DDFSTRT=lores (VSTART/2-8.5) or hires (VSTART/2-4.5)
DDFSTOP=lores DDFSTRT+(8*(words by line-1)) or hires (DDFSTRT+(4*(words by line -2))

by default for a 320 pix or 640 pix screen : $38 / $D0
if change, multiple x4 : > or < standard width of screen

if $30/$D8 (-8 +8) = 352 pix
with these values, it's simple to do Overscan (Atari ST Graal !)

-------
Resolution : BPLCON0 $100

bit 15 Hires ($4000)
bit 14-12 depth (nb bitplans) = depth*$1000
bit 11 Ham mode ($800)
bit 10 Dualplayfield mode ($400)
bit 9 colors ($200)
bit 8 genlock
bit 7-4 unused
bit 3 lightpen
bit 2 lace (4)
bit 1 extern synchro
bit 0 unused

ex: 32 col. low res non-interlace = 5 plans

value = 5*$1000+$200 (activate color mode otherwise no display) = $5200

if you want more...but all is in Hardware Reference Manual
z5_
Member
#7 - Posted: 20 Nov 2004 23:10
Reply Quote
Indeed, the Amiga Hardware Reference manual is a MUST read. Really well explained. You can find parts of it on Amigarealm. However, having some additional explanations, examples, dicussion,... is always nice :)

@cyf:
Isn't it so that some bits have changed in BPLCON0 since AGA. I do remember reading something about an extra bit (bit 7?) for defining the number of bitplanes, making it a 4 bit combination (because of the extra colors on AGA i presume...)
Cyf
Member
#8 - Posted: 21 Nov 2004 00:10 - Edited
Reply Quote
yes, with aga chipset all unused bits of bplcon0 are defined :
7 : UHres = ultra hires 1024*1024 (set also bit 9 in Dmacon)
6 : superhires 1280 35ns
5 : BplHwrm - screen black and white, no copcolors
4 : 8 planes (bits 12-14 must be 0)
0 : EcsEna - enable bplcon3 register (ECS-AGA)

and many other new registers

for aga compatibility, insert following lines in coplist :
dc.w $106,$c00 ; Bplcon3 : aga sprites, palette and dualplayfield reset
dc.w $1fc,0 ; Fmode : aga sprites and burst reset

and set $108,$10a,$8e,$90 or you will get the Workbench values

good doc about Aga chipset is "Programming AGA hardware" by Randy/Comax (I'm searching where is my disk with this doc)

Edit: the link for randy's doc : http://aminet.back2roots.org/pub/aminet/docs/misc/RandyAGA.lha
Overflow
Member
#9 - Posted: 21 Nov 2004 00:46
Reply Quote
Im trying to make a copperinit that creates vertical copperbars, meaning that they change color horizontally. I can make one line fine by changing like this

initcop
lea.l copper,a3
move.l #9,d3
move.l #$8241fffe,d2
move.l #$01800000,d5

docop: move.l d2,(a3)+
move.l d5,(a3)+

add.l #$00020000,d2

dbra d3,docop
rts

But...then i want to do jump down to the next line by same horizontal position and do it all over again....

initcop
clr.l d4
lea.l copper,a3
move.l #9,d3
move.l #9,d4
move.l #$8241fffe,d2
move.l #$01800000,d5

docop: move.l d2,(a3)+
move.l d5,(a3)+

add.l #$00020000,d2

dbra d3,docop

add.l #$01000000,d2
dbra d4,docop
clr.l d4
rts

That add.l #$01000000,d2 changes the line but I need to get rid of what
add.l #$00020000,d2 has done or ill not get the colors lined up in the correct horizontal position... :P

I could TYPE it..but there must be a simpler manner to loop it all...
Cyf
Member
#10 - Posted: 21 Nov 2004 11:24 - Edited
Reply Quote
real vertical copperbars "onepixel" aren't copperbars :) but blitter objects (bob)

you can obtain a "vertical copper" by changing color, yes.
also like this :
dc.w $180,$00c,$180,$00d,$180,$00e,$180,$00f
dc.w $180,$00f,$180,$00e,$180,$00d,$180,$00c

start wait at the middle of the screen or try with bitplan #1 color

instruction Move need 2 cycles. DMA bitplan display 2 pixels lowres by cycle : the color is modified each 4 pix. and copper can execute 56 MOVE/line

it's possible to do "roller" copper effect
Cyf
Member
#11 - Posted: 21 Nov 2004 14:28 - Edited
Reply Quote
roller effect :
60 colors (black->red (15) red->black (15) black->blue (15) blue->black (15)) x13 because of 56 move/line = 13 lines

makeroll:
lea roller,a0 ; copperlist buffer pointer

moveq #12,d0 ; repeat 13 time (13 lines)

.loop:
moveq #0,d1 ; current color = 0 (black)

moveq #14,d2 ; first black to red (0->$f00)
.roll1:
move.w #$180,(a0)+ ; MOVE $180 (Color00)
move.w d1,(a0)+ ; MOVE current color
addi.w #$100,d1 ; fade to red - inc Red composant (Rgb)
dbra d2,.roll1 ; x15 (0->$f00)
move.w #$180,(a0)+ ; +1 line red
move.w d1,(a0)+

moveq #14,d2 ; red to black ($f00->0)
.roll2:
move.w #$180,(a0)+
subi.w #$100,d1 ; fade to black - decr Red
move.w d1,(a0)+
dbra d2,.roll2 ; x15 ($f00->0)

moveq #14,d2 ; black to blue (0->$00f)
.roll3:
move.w #$180,(a0)+ ;
addq.w #1,d1 ; incr Blue composant (rgB)
move.w d1,(a0)+
dbra d2,.roll3

moveq #13,d2 ; blue to black ($00f->$001)
.roll4:
move.w #$180,(a0)+
subq.w #1,d1 ; decr Blue
move.w d1,(a0)+
dbra d2,.roll4

dbra d0,.loop ; 60 colors x13
rts

coplist:
dc.w $8e,$2c81,$90,$2cc1,$92,$38,$94,$d0 ; standard screen
dc.w $100,0
dc.w $180,0
dc.w $2c3f,$fffe
roller:
ds.w 60*13*2 ; 60 cols 13 time in 1 roll, 2 words (size in bytes)
dc.w $180,0 ; color black
dc.l -2 ; end of copperlist
z5_
Member
#12 - Posted: 21 Nov 2004 15:52
Reply Quote
@cyf:

If possible, try to explain the code a bit (adding comments in the code would be nice). It may be obvious for experienced users, but for newbies, it is daunting... ;) Every comment can help beginners speed up the learning-process/time.
Cyf
Member
#13 - Posted: 21 Nov 2004 17:55
Reply Quote
That add.l #$01000000,d2 changes the line but I need to get rid of what
add.l #$00020000,d2 has done or ill not get the colors lined up in the correct horizontal position... :P


d2=$8241fffe
add $20000,d2 *10 : d2=$8255fffe. the same line
(add $20000 *10)*10 : d2=$8309fffe. only 1 line
Overflow
Member
#14 - Posted: 21 Nov 2004 18:10
Reply Quote
Thanks! Im about to fire up my assemble right now, so Ill test it.
Cyf
Member
#15 - Posted: 21 Nov 2004 19:18
Reply Quote
you can move the Roller like by a simple shifting :

forward:
1. dc.w $180,0
2. dc.w $180,$100 <- a1
3. dc.w $180,$200 <- a0. d0=$200

save 3 (d0)
copy 2 to 3
copy 1 to 2
copy d0 (3) to 1

moveroll_forward:
lea roller+(60*13*2)*2,a0 ; pointer at the end of the roller
lea -4(a0),a1 ; source= one color back
move.w -2(a0),d0 ; save last color
move.w #60*13-2,d1

.loop
move.l -(a1),-(a0) ; copy end->start
dbra d1,.loop

move.w d0,2(a0) ; put old last color at start
rts


moveroll_back:
lea roller,a0
lea 4(a0),a1
move.w 2(a0),d0
move.w #60*13-2,d1
.loop
move.l (a1)+,(a0)+
dbra d1,.loop

move.w d0,-2(a1)
rts
Cyf
Member
#16 - Posted: 23 Nov 2004 00:50 - Edited
Reply Quote
another example of "vertical copperbars" (used in Z-Out intro game) :

; init
makerast:
lea raster,a0 ; coplist buffer
move.l #$400ffffe,d1 ; wait
moveq #9,d6 ; 10 lines
.loop
move.l d1,(a0)+ ; put Wait
bsr makedeg ; put 31 Move Color00
addi.l #$01000000,d1 ; next line
dbf d6,.loop
rts

makedeg:
lea bluecol(pc),a1
moveq.l #30,d7 ; 31 colors
.loop
move.w #$180,(a0)+
move.w (a1)+,(a0)+
dbf d7,.loop
rts

; in vbl - vertical move right<->left
moverast:
subq.w #1,cpt ; delay before switching right to left/left to right
bne.s .right
neg.w shift ; shift to left
move.w #40,cpt
.right
move.w shift(pc),d0
add.w d0,vpos ; vertical pos +- shift
move.w vpos(pc),d0
lsr.w #3,d0 ; /8
andi.w #$fffe,d0
addi.b #$43,d0 ; vertical start pos.

lea raster,a0
lea 1(a0),a0 ; pointer to vertical wait position hhVV fffe
moveq #9,d7 ; 10 lines
.loop
move.b d0,(a0)
lea 128(a0),a0 ; next line (32*4)
dbf d7,.loop
rts

vpos dc.w 0
shift dc.w 16
cpt dc.w 30
bluecol:
dc.w 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1 ,0


coplist:
dc.w $8e,$2c81,$90,$2cc1,$92,$38,$94,$d0
dc.w $106,$c00,$1fc,0
dc.w $100,$0200
dc.w $180,$00
raster:
ds.w 64*10 ; wait,move color00
dc.w $180,0
dc.l -2

this effect can be used for a menu with rasterline moved with mouse (another lesson ?)
Cyf
Member
#17 - Posted: 23 Nov 2004 23:51 - Edited
Reply Quote
with the same way, another little effect : copper line "progressbar" style

; init
makeline:
lea line,a0 ; coplist buffer
move.w #49,d7 ; 50 Move color00
.loop2
move.l #$1800000,(a0)+ ; color black
dbf d7,.loop2
rts

; vbl routine
fill:
cmpi.w #49,cpt ; position counter : 50 colors to fill
bge.s .skip
move.w cpt(pc),d0
lsl.w #2,d0 ; x4 (2 words 180,000)
lea line+2,a0 ; color value pointer
adda.w d0,a0 ; from left / suba.w d0,a0 : from right
move.w #$fff,(a0) ; put color
addq.w #1,cpt ; next color
.skip:
rts
cpt dc.w 0

coplist:
dc.w $180,0,$3221,$fffe
line: ds.l 50
dc.w $180,0
dc.l -2
noname
Member
#18 - Posted: 28 Feb 2010 20:11
Reply Quote
I have a small problem with a copper list and I forgot about its solution over the years. I want to wait for certain lines, which is easy enough as long as you stay below line 255 ($ff).

E.g. dc.w $460f,$fffe ;will wait for line 70 (hex $46)

But how can I wait for a line > 255?
noname
Member
#19 - Posted: 1 Mar 2010 07:45
Reply Quote
Memo to myself:
; dc.w $ffdf,$fffe ; wait for end of line 255
; dc.w $0c0f,$fffe ; now we can wait some more and reach the lower part of the screen
d0DgE
Member
#20 - Posted: 1 Mar 2010 22:09
Reply Quote
Thanks for the memo. Never came around this info, yet \o/
OTOH, most of my stuff is "letterboxed" and ends at $f00f :D
dalton
Member
#21 - Posted: 2 Mar 2010 06:52
Reply Quote
I found that in some applications, like when you want to use the copper list as a table for writing values, that little extra wait becomes rather annoying. It would be enough to use a mul (or shift) to find the appropriate position for writing in the list, but with the extra wait, compare/jump/add is also needed.

I believe it's common practice to wait for the beginning of a line in copper lists, but why not wait for the end of the previous line instead? If you do that, the extra compare is not needed, you sort of get it for free.
ZEROblue
Member
#22 - Posted: 2 Mar 2010 11:34
Reply Quote
Good to keep in mind, I wouldn't have thought of that myself.

Will work great if you're changing values on consecutive lines across the $100 break, but if it's the background color you're changing and haven't got the ECS border blank feature then you will have to insert the extra wait since you're not physically on the next line until HPOS 7 I think, and the color split in the border would be visible on some monitors.
endo
Member
#23 - Posted: 12 Mar 2010 00:19
Reply Quote
yes, you should always wait for the x pos. 7, $4007. if you wait for just y pos and ignore the x pos, like $4001, then color change just before line current line ($3f) ends.
Crumb
Member
#24 - Posted: 26 Apr 2010 16:26
Reply Quote
Thinking about table effects and copper I came across this idea: if copper could modify display start address enough fast it would be possible to make a "tablemask" using a copperlist. As a result copper would apply our mask directly to the bitmap in the screen. I guess it won't be possible due to one or both of these:
a) Amiga won't be fast enough to switch display start address in a way it looks ok
b) Copper won't be fast enough to modify all required registers so the horizontal resolution will be too low.

If b) was true would it be possible to use the cpu to modify the display start address fast enough? That way we would have to use the cpu to write to the registers but perhaps it would be less work than applying the mask, I only have a little experience with chunky effects so this is probably a silly idea but I wanted to ask to Amiga gurus :-)
jar
Member
#25 - Posted: 19 Mar 2013 09:31
Reply Quote
I have a short beginner's question:
Instead of using the copper, is it also viable to set up the display values in a VBlank interrupt routine? I.e. moving the correct values into DIWSTRT, etc. by hand.
What would be the downsides? Would the display be stable enough?
Blueberry
Member
#26 - Posted: 19 Mar 2013 09:58
Reply Quote
Yes, that is perfectly viable. I do it in most of my productions. And the display is perfectly stable if you do it as the first thing in your vblank interrupt. In fact, writing the bitplane pointers this way is a reliable way of avoiding the occasional flickering seen in many Amiga demos. Hmm, let me repeat that:

NEVER WRITE DYNAMIC BITPLANE POINTERS INTO THE COPPERLIST UNLESS YOU ARE ABSOLUTELY SURE THAT THE COPPER IS NOT READING THEM AT THE SAME TIME!

Thank you. :)

Anyway, the only downside I can think of (as long as you don't need any specific copper functionality, such as waiting), is that the CPU spends some time on writing the registers. For instance, writing a full 256-color 24-bit palette on 060 takes about 6 scanlines. You can save some time by remembering what you wrote last time and only writing the registers whose values have changed (except for bitplane and sprite pointers, which must be refreshed every vblank).

Writing everything using the CPU can also have a size benefit, as you can store your "copperlist" in a more compact/compressible format which is easily read by the CPU. And you don't have to set up (and restore) the copper. It can make a noticeable difference in a 4k or bootblock.
jar
Member
#27 - Posted: 19 Mar 2013 10:32
Reply Quote
Thanks Blueberry for the nice explanations! Let's see if i can get some simple amiga stuff going in the next days :)
dalton
Member
#28 - Posted: 19 Mar 2013 11:48
Reply Quote
Also remember that the only values you need to set in your interrupt routine are the bitplane pointers and the sprite pointers. The other values (like the palette, DIWSTRT etc) do not change from frame to frame so just set them once and that's it (i.e. not like many tutorials and documents tell you to write these every frame with the copper).
jar
Member
#29 - Posted: 19 Mar 2013 14:52
Reply Quote
oh great, these are some cool tips! looking forward to try things out..

 

  Please register a new account or log in to comment

  

  

  

 

A.D.A. Amiga Demoscene Archive, Version 3.0