|
Author |
Message |
z5_
Member |
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 |
?? $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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
@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 |
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 |
Thanks! Im about to fire up my assemble right now, so Ill test it.
|
Cyf
Member |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
Thanks Blueberry for the nice explanations! Let's see if i can get some simple amiga stuff going in the next days :)
|
dalton
Member |
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 |
oh great, these are some cool tips! looking forward to try things out..
|
|
|