English Amiga Board


Go Back   English Amiga Board > Coders > Coders. General

 
 
Thread Tools
Old 04 September 2019, 08:39   #1
Clydos
Registered User

 
Join Date: May 2018
Location: Dresden / Germany
Posts: 152
Copperlist explanation

Quote:
Originally Posted by roondar View Post
@Marle: since this is far off-topic, I'm not going to post about it here - but if you like, I could explain a bit about the basics of how Copperlists work sometime?
As this thread was split and is its own dedicated thread now, I think such an explaination would fit pefectly. I would also be interested in that.

Thanks in advance! :-)

Last edited by Clydos; 04 September 2019 at 09:12.
Clydos is offline  
Old 04 September 2019, 09:04   #2
malko
Ex nihilo nihil

malko's Avatar
 
Join Date: Oct 2017
Location: CH
Posts: 2,095
Quote:
Originally Posted by clydos View Post
as this thread was split and is its own dedicated thread now, i think such an explaination would fit pefectly. I would also interested in that.

Thanks in advance! :-)
+1
malko is offline  
Old 04 September 2019, 14:18   #3
roondar
Registered User

 
Join Date: Jul 2015
Location: The Netherlands
Posts: 1,288
Ok, here's a 'small' overview about the Copper. It's still a pretty big chunk of text though, so sit back and enjoy with a beverage of your choice

One note before I begin: to keep things somewhat less bulky, what I'm writing below is purely about Copperlists. The text does not deal with setting up the Amiga or screen itself, nor enabling/disabling DMA etc. It's just meant to cover how the Copper does it's colour changes and how this can be put into practice.

Should this be too in-depth or too long, the last post contains a "I don't care about theory, just give me an example already" Copperlist.

Edit: I do know this is a lot of text, but it's less complicated than the length of text makes it out to be. Check the example in the last post to see the actual copperlist is not all that complicated. The complication lies in understanding what's happening and me trying to explain it, not the actual code

@mods: to make it all a bit easier to digest, I've put this into three separate posts that deal with the different aspects I'm trying to explain. Hopefully this is ok.

Part 1: the basics
A copperlist is a program for the Copper. The Copper is a small co-processor that can change (almost) any Amiga custom chip set register at (almost) any time during the screen display.

The Copper only knows three instructions: WAIT, SKIP and MOVE. For the purposes of keeping things somewhat simpler, I'll only talk about WAIT and MOVE.

Let's talk about WAIT first. The WAIT command make the Copper (but not the rest of the system, which keeps running) wait until the given condition is true. This condition is usually a location on the screen. That is, you can give a 'screen coordinate' to wait for and then do stuff. Which brings us to MOVE. The MOVE command makes the Copper set an Amiga custom chip set register to a given value.

Combining WAIT and MOVE allows the Copper to wait for a position on the screen and then change something: colours, scroll offsets, bitplane pointers, etc. Because of how screen updates work on the Amiga, such changes only affect the screen from the given position onwards. For example: if your Copperlist waits for Y position 100 and then change the background colour, this will only affect the screen from Y position 100 downwards.

A few caveat do exist:

The first is that any change is permanent, unless changed again. So, if your Copperlist only changes the background colour at Y position 100, then it remains changed for ever. So, to keep the background colour different at Y positions smaller than 100, you need to set the colour to the desired value for the first part of the screen higher up. Usually, this too is done with the copper.

A second point is that the Amiga display chip requires you to reset the area of memory it points to every single frame. This can be done with both the CPU and the Copper, but most Amiga programs use the Copper to do this.

The third point is that the Copper was originally designed for an NTSC system, which means that PAL systems require an extra bit of Copper code to be able to change stuff in the bottom area of the screen (an extra WAIT is needed after the last Copper instruction in the 'NTSC part' of the screen)

Lastly, a Copperlist has a specific way in which it ends. Not ending the Copperlist properly can lead to all sorts of unexpected results.

Last edited by roondar; 04 September 2019 at 14:45.
roondar is offline  
Old 04 September 2019, 14:19   #4
roondar
Registered User

 
Join Date: Jul 2015
Location: The Netherlands
Posts: 1,288
Part 2: coding WAIT/MOVE instructions
Each Copper instruction takes the form of two 16 bit values (called words): one word gives the instruction, the second word gives the parameter for the instruction. To encode the instruction and value correctly, some knowledge of the Amiga chipset and binary/hexadecimal numbers is highly recommended.

A move looks like this:
Code:
 
	word one: <register>, word two: <value>
Examples:
Setting colour 0 to black would be encoded as $0180,$0000
Setting colour 8 to bright red would be encoded as $0188,$0F00
Setting colour 21 to a pastel yellow would be encoded as $01AA,$0FF9
(Amiga colour registers run from $180-$1BE)

A wait looks like this:
Code:
	word one: <position> OR 1, word two: <comparison bits>
Where position is a specially encoded X&Y coordinate.
Normally, the comparison bits are either set to $FFFE (wait for vertical and horizontal position) or $FF00 (wait for vertical position only)*.

The full explanation for this is more complicated than the move one, so I'll first give some examples and then add the explanation below for those interested.

Examples:
Code:
$2C39,$FFFE: the first non-border pixel of the top line of a standard 320x256 screen
$4001,$FF00: the first pixel of line 20 of a standard 320x256 screen
$58E3,$FFFE: position in the border for line 45 of a standard 320x256 screen
Changing X&Y of the examples:
Y = first two digits, X = second two digits
Y moves in steps of 1, each representing one line
X moves in steps of 2, each two representing four pixels
The very last digit in the first word is always odd, but X position always refers to an even coordinate

*) Waiting on just vertical value works for colour changes, but can cause a visible 'step' if the colour changed is the background colour. To avoid this, the wait has to be timed so that it changes colour zero in the 'horizontal blank'. Generally, this can be achieved by waiting until the end of the line prior to the line where the background colour needs to change and then change the colour. This corresponds to a wait of $<y_pos>E3,$FFFE.

--- in depth explanation follows below ---


Encoding the X&Y position:
The Y position is equal to the screen's Y position, plus the number of lines in the vertical border. For a standard Amiga screen (PAL & NTSC), the number to add is 44. For overscan or underscan screens, this number can be different.

If the resulting Y position is larger than 255, subtract 256 from the result. Convert the result to hexadecimal. This forms the first two digits of the WAIT instruction.

The X position is more complicated.

First off, the Copper's horizontal resolution is 1/4th of a low resolution screen. But the value to use in the WAIT command is given as if the resolution is half the standard screen (that is, the value is double of what you expect for a 1/4 resolution). Secondly, the Copper's horizontal resolution operates in the range of $4 to $e4 (229), rather than in the range of $0-$ff (255). This means that a wait for the first position before $4 must actually wait for position $e4 on the previous line.

The horizontal position always refers to an even pixel. Thirdly, the visible part of the screen does not start at position $4, but normally at position $38 (56). The rest is the horizontal border.

Take the desired X value as determined by using the above information to get the second two digits. A copper WAIT must have the least significant bit set to 1, so OR/ADD a 1 to the result. For example, a wait for Y location $50 and X location $40 that waits for both the horizontal and vertical value would look like this: $5041,$FFFE.

PAL area
A PAL Amiga can access more lines than an NTSC one can. This causes a problem, because the Copper only recognises up to 256 lines and a PAL display can have up to 286 of them. To make the Copper work as expected, a special WAIT instruction has to be added before any Copper waits in the 'PAL area' will work.

Copper PAL area wait: $FFDF,$FFFE

Simply add this after the last copper instruction before the linenumber reaches 256.

Ending the Copperlist
Ending the Copperlist is done with a special WAIT instruction: $FFFF,$FFFE

A word on timing
Copper instructions take some time to execute. It's a small amount, but it's not instant. During this time the display update keeps running. As a result, you can think of Copper instructions as taking a certain number of 'horizontal pixels' each. How many 'pixels' an instruction takes is dependent on the screen mode chosen:
  • In the horizontal and vertical border/blanking area each Copper Move takes up 8 pixels and each Copper Wait takes up 12. The same is true for any Copper Move or Wait used with a screen mode that uses 4 bitplanes or less (16 colours). For non-overscan screens, a general guideline is that 15 to 16 registers can be changed during the horizontal blanking interval.
  • During the visible part of a 5 bitplane display, a Copper move takes up 12 pixels and a Copper wait takes up 16.
  • During the visible part of a 6 bitplane display, a Copper move takes up 16 pixels and a Copper wait takes up 24.

Last edited by roondar; 05 September 2019 at 09:56. Reason: Corrected some small errors
roondar is offline  
Old 04 September 2019, 14:20   #5
roondar
Registered User

 
Join Date: Jul 2015
Location: The Netherlands
Posts: 1,288
Part 3: an example Copperlist
Let's look at all this in the form of an example. In this example, I skip the part where the Copper sets up the bitplane pointers and other display setting. I can give an example that does this as well, but I think it's more useful to show the basics first.

Note: in order to use the Copperlist below, the rest of the program running has to set up the display and reset the bitplane pointers every frame. If this is not done, the colour changes will still show up but the display will be garbled. It's also neccesary to put the Copperlist somewhere in memory and point the Copper location register to this place in memory.

Simple copperlist (as code)
Code:
; Screen setup omitted
; No waiting at the start means the Copper starts high up in the vertical border
$0180,$0000	; Change background colour to black
$0182,$0000	; Change colour 1 to black
$0184,$0000	; Change colour 2 to black
$0186,$0000	; Change colour 3 to black
$2BE3,$FFFE	; Wait for border location of top line of screen
$0180,$0F00	; Change background colour to red
$3BE3,$FFFE	; Wait for border location of line 16 of screen
$0180,$00F0	; Change background colour to green
$4BE3,$FFFE	; Wait for border location of line 32 of screen
$0180,$000F	; Change background colour to blue
$BB61,$FFFE	; Wait for Y position $BB, X position $60 = line 144, x=160
$0180,$0555	; Change background colour to gray
$EB00,$FF00	; Wait for any location of line 191 of screen
$0180,$0FFF	; Change background colour to white
$0182,$0400	; Change colour 1 to dark red
$0184,$0040	; Change colour 2 to dark green
$0186,$0004	; Change colour 3 to dark blue
$FFDF,$FFFE	; Wait for start of PAL area (visible part of screen Y=212)
$0180,$0000	; Change background colour to black
$FFFF,$FFFE	; End of Copper list
For reference, the above Copper list looks as follows if we decode the instructions:
Code:
; Screen setup omitted
; No waiting at the start means the Copper starts high up in the vertical border
MOVE $0000 to register $180	; Change background colour to black
MOVE $0000 to register $182	; Change colour 1 to black
MOVE $0000 to register $184	; Change colour 2 to black
MOVE $0000 to register $186	; Change colour 3 to black
WAIT on position Y=$2B, X=$E3	; Wait for border location of top line of screen
MOVE $0F00 to register $180	; Change background colour to red
WAIT on position Y=$3B, X=$E3	; Wait for border location of line 16 of screen
MOVE $00F0 to register $180	; Change background colour to green
WAIT on position Y=$4B, X=$E3	; Wait for border location of line 32 of screen
MOVE $000F to register $180	; Change background colour to blue
WAIT on position Y=$BB, X=$61	; Wait for Y=$BB, X=$60 => screen y=144, x=160
MOVE $0555 to register $180	; Change background colour to gray
WAIT on position Y=$EB		; Wait for any location of line 191 of screen
MOVE $0FFF to register $180	; Change background colour to white
MOVE $0400 to register $182	; Change colour 1 to dark red
MOVE $0040 to register $184	; Change colour 2 to dark green
MOVE $0004 to register $186	; Change colour 3 to dark blue
WAIT on position Y=$FF, X=$DF	; Wait for start of PAL area (screen Y=212)
MOVE $0000 to register $180	; Change background colour to black
WAIT on position Y=$FF, X=$FF	; End of Copper list
Hopefully, the example shows that the practical application of all that wall of theory text is not as complicated as it might seem. It all boils down to: WAIT on a position, MOVE the colours you want

Last edited by roondar; 05 September 2019 at 09:57. Reason: Fixed a small error
roondar is offline  
Old 04 September 2019, 15:08   #6
Shatterhand
Warhasneverbeensomuchfun

Shatterhand's Avatar
 
Join Date: Jun 2001
Location: Rio de Janeiro / Brazil
Age: 36
Posts: 3,341
Ohh Roondar, thank you! It wasn't that much text to be quite honest, and a very interesting reading for those who, like me, never dabbled on 68K ASM. This actually made me want to know more about the Amiga registers... because I know I can, with the copper, change the horizontal offset of the bitmap shown or draw sprites, and that's something I find extremely interesting.
Shatterhand is offline  
Old 04 September 2019, 15:22   #7
roondar
Registered User

 
Join Date: Jul 2015
Location: The Netherlands
Posts: 1,288
You're welcome!

There's tons more I could add, including a lot about registers etc. But for now I'll wait and see what people want to know and how much of it fits this thread

That said, I can point you towards a very complete source of hardware information - complete with a list of all registers: the complete online version of the Hardware Reference Manual. It can be found at http://amigadev.elowar.com/read/ADCD.../node0000.html

This book/site is where I starting learning pretty much all I know about the Amiga chipset
roondar is offline  
Old 05 September 2019, 09:46   #8
Clydos
Registered User

 
Join Date: May 2018
Location: Dresden / Germany
Posts: 152
Wow, thanks a lot, roondar, that is massive! I need time to read (and understand :-)) that, but looks very promising!
Clydos is offline  
Old 05 September 2019, 09:58   #9
roondar
Registered User

 
Join Date: Jul 2015
Location: The Netherlands
Posts: 1,288
No problem, happy to help

Know that I did make a small error in the Copperlist (one of the WAIT commands was not correct) which I have corrected just now.
roondar is offline  
Old 05 September 2019, 10:27   #10
Steril707
Tigerskunk!

Steril707's Avatar
 
Join Date: Sep 2016
Location: Amiga Island
Posts: 972
Quote:
Originally Posted by Shatterhand View Post
Ohh Roondar, thank you! It wasn't that much text to be quite honest, and a very interesting reading for those who, like me, never dabbled on 68K ASM. This actually made me want to know more about the Amiga registers... because I know I can, with the copper, change the horizontal offset of the bitmap shown or draw sprites, and that's something I find extremely interesting.
Just go for ASM, it's not that hard if you understood a couple of simple concepts.
In the end, it's just almost like some kind of very abstract looking BASIC coding.

Also, we are more than happy to help you here if you don't understand something..
Steril707 is offline  
Old 05 September 2019, 12:00   #11
Clydos
Registered User

 
Join Date: May 2018
Location: Dresden / Germany
Posts: 152
Ok, I had a good read! Some things there I knew a bit was made more clear now. And I learned new stuff - awesome! Thanks a lot, that was really helpful!

So, one question: As for the colours. I cannot write $00FF0000 instead of $0F00, right? Because $0F00 is 16 bit and $00FF0000 is 256!?
Clydos is offline  
Old 05 September 2019, 12:09   #12
Steril707
Tigerskunk!

Steril707's Avatar
 
Join Date: Sep 2016
Location: Amiga Island
Posts: 972
Quote:
Originally Posted by Clydos View Post
Ok, I had a good read! Some things there I knew a bit was made more clear now. And I learned new stuff - awesome! Thanks a lot, that was really helpful!

So, one question: As for the colours. I cannot write $00FF0000 instead of $0F00, right? Because $0F00 is 16 bit and $00FF0000 is 256!?
Exactly..

The OCS Amiga has only 12 bits colour depth. That first nibble is always zero as well.
Steril707 is offline  
Old 05 September 2019, 12:23   #13
Clydos
Registered User

 
Join Date: May 2018
Location: Dresden / Germany
Posts: 152
Quote:
Originally Posted by Steril707 View Post
Exactly..

The OCS Amiga has only 12 bits colour depth. That first nibble is always zero as well.
Alright, thanks. But if I would address AGA, I could use $00FF0000? Or "just" $FF0000?

Regarding the first nibble: I thought this has sth to do with transparency (as I am coming from the web dev corner). No?
Clydos is offline  
Old 05 September 2019, 12:36   #14
roondar
Registered User

 
Join Date: Jul 2015
Location: The Netherlands
Posts: 1,288
Quote:
Originally Posted by Clydos View Post
Ok, I had a good read! Some things there I knew a bit was made more clear now. And I learned new stuff - awesome! Thanks a lot, that was really helpful!

So, one question: As for the colours. I cannot write $00FF0000 instead of $0F00, right? Because $0F00 is 16 bit and $00FF0000 is 256!?
You're welcome!
If you have more questions, I'm more than happy to help

On the topic of colour registers:
  • Amiga colour registers do not have any form of alpha transparency
  • AGA colours are set in a roundabout way, you can't directly write a 32 bit value

Edit: I'd highly recommend starting with OCS first, regardless of your final plans. Most things are the same and the differences there are can be tricky to grasp unless you already know how OCS does it.
roondar is offline  
Old 05 September 2019, 12:38   #15
Steril707
Tigerskunk!

Steril707's Avatar
 
Join Date: Sep 2016
Location: Amiga Island
Posts: 972
Quote:
Originally Posted by Clydos View Post
Alright, thanks. But if I would address AGA, I could
use $00FF0000? Or "just" $FF0000?
Don't know, I never dabbled in the dark arts of AGA.

Quote:
Originally Posted by Clydos View Post
Regarding the first nibble: I thought this has sth to do with transparency (as I am coming from the web dev corner). No?
No, there is no "alpha" value in those early graphics chips.
If you write an OCS colour value, the first nibble doesn't count. I don't know if it must be set to zero though, or what happens if you don't, since I never tried that out. I guess it just doesn't get read.

so #$0fff is white, and #$0000 is black, #$0f00 is red, etc...

if you want to set your screen to a black background, you'd put..

dc.w $0180,$0000

in your copperlist. The $0180 here is short form for $dff180, which is the register responsible for colour 0, the background colour.. The copper understands writing this short form.

And what Roondar said. Get aquainted with OCS first.
AGA is really a lot more confusing, imo...
Steril707 is offline  
Old 05 September 2019, 12:45   #16
roondar
Registered User

 
Join Date: Jul 2015
Location: The Netherlands
Posts: 1,288
Yup, AGA is a lot less elegant to code for and has all sorts of alignment restrictions and stuff like colour banking and having to set colours in two writes to worry about. OCS is much nicer to program for, IMHO.
roondar is offline  
Old 05 September 2019, 12:48   #17
Steril707
Tigerskunk!

Steril707's Avatar
 
Join Date: Sep 2016
Location: Amiga Island
Posts: 972
OCS is a lot more thought out and coherent, imo.

AGA feels to me like they needed to stick a new part on top of an existing cars engine to make it faster.
Steril707 is offline  
Old 05 September 2019, 12:58   #18
Clydos
Registered User

 
Join Date: May 2018
Location: Dresden / Germany
Posts: 152
Thanks for all the great responses, @Steril707 and @roondar!

I am asking for AGA for a specific reason, but I can't reveal that yet (but really nothing to get excited about!). Just @invent currently knows. :-) But good to know that AGA is harder to do.
Clydos is offline  
Old 05 September 2019, 12:58   #19
DamienD
Global Moderator

DamienD's Avatar
 
Join Date: Aug 2005
Location: London / Sydney
Age: 42
Posts: 15,107
Guys, can we please not turn this into a coding thread?

In fact I might move all coding stuff into another thread under the Coders. General section

Edit: done, all posts here moved from the Graphics tools and techniques for creating Retro games thread.

Last edited by DamienD; 05 September 2019 at 13:05.
DamienD is online now  
Old 05 September 2019, 13:05   #20
roondar
Registered User

 
Join Date: Jul 2015
Location: The Netherlands
Posts: 1,288
It seems to me the problem here is that 'graphic techniques' and 'coding' are very close on retro platforms like the Amiga
I guess we had indeed moved from 'copper reloading exists' into 'coding talk'.
roondar is offline  
 


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools

Similar Threads
Thread Thread Starter Forum Replies Last Post
UHRES? Mistery/curiosity - any explanation? pandy71 Coders. Asm / Hardware 50 03 October 2019 20:22
A little explanation on GOTEK+HxC would be great.. appiah4 support.Hardware 19 22 December 2016 13:12
whdload decent explanation ? marcolau project.WHDLoad 5 01 December 2009 16:43
Error explanation?? ORSM T support.Hardware 7 01 June 2007 07:36
code explanation BippyM Coders. General 19 01 May 2007 14:12

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +2. The time now is 15:54.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2019, vBulletin Solutions Inc.
Page generated in 0.09097 seconds with 13 queries