04 September 2019, 08:39 | #1 | |
aka (Cpt)JohnArcher
Join Date: May 2018
Location: Dresden / Germany
Posts: 193
|
Copperlist explanation
Quote:
Thanks in advance! :-) Last edited by Clydos; 04 September 2019 at 09:12. |
|
04 September 2019, 09:04 | #2 |
Ex nihilo nihil
Join Date: Oct 2017
Location: CH
Posts: 4,856
|
|
04 September 2019, 14:18 | #3 |
Registered User
Join Date: Jul 2015
Location: The Netherlands
Posts: 3,407
|
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. |
04 September 2019, 14:19 | #4 |
Registered User
Join Date: Jul 2015
Location: The Netherlands
Posts: 3,407
|
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> 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> 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 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:
Last edited by roondar; 05 September 2019 at 09:56. Reason: Corrected some small errors |
04 September 2019, 14:20 | #5 |
Registered User
Join Date: Jul 2015
Location: The Netherlands
Posts: 3,407
|
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 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 Last edited by roondar; 05 September 2019 at 09:57. Reason: Fixed a small error |
04 September 2019, 15:08 | #6 |
Warhasneverbeensomuchfun
Join Date: Jun 2001
Location: Rio de Janeiro / Brazil
Age: 41
Posts: 3,450
|
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.
|
04 September 2019, 15:22 | #7 |
Registered User
Join Date: Jul 2015
Location: The Netherlands
Posts: 3,407
|
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 |
05 September 2019, 09:46 | #8 |
aka (Cpt)JohnArcher
Join Date: May 2018
Location: Dresden / Germany
Posts: 193
|
Wow, thanks a lot, roondar, that is massive! I need time to read (and understand :-)) that, but looks very promising!
|
05 September 2019, 09:58 | #9 |
Registered User
Join Date: Jul 2015
Location: The Netherlands
Posts: 3,407
|
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. |
05 September 2019, 10:27 | #10 | |
Inviyya Dude!
Join Date: Sep 2016
Location: Amiga Island
Posts: 2,770
|
Quote:
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.. |
|
05 September 2019, 12:00 | #11 |
aka (Cpt)JohnArcher
Join Date: May 2018
Location: Dresden / Germany
Posts: 193
|
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!? |
05 September 2019, 12:09 | #12 | |
Inviyya Dude!
Join Date: Sep 2016
Location: Amiga Island
Posts: 2,770
|
Quote:
The OCS Amiga has only 12 bits colour depth. That first nibble is always zero as well. |
|
05 September 2019, 12:23 | #13 | |
aka (Cpt)JohnArcher
Join Date: May 2018
Location: Dresden / Germany
Posts: 193
|
Quote:
Regarding the first nibble: I thought this has sth to do with transparency (as I am coming from the web dev corner). No? |
|
05 September 2019, 12:36 | #14 | |
Registered User
Join Date: Jul 2015
Location: The Netherlands
Posts: 3,407
|
Quote:
If you have more questions, I'm more than happy to help On the topic of colour registers:
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. |
|
05 September 2019, 12:38 | #15 | ||
Inviyya Dude!
Join Date: Sep 2016
Location: Amiga Island
Posts: 2,770
|
Quote:
Quote:
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... |
||
05 September 2019, 12:45 | #16 |
Registered User
Join Date: Jul 2015
Location: The Netherlands
Posts: 3,407
|
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.
|
05 September 2019, 12:48 | #17 |
Inviyya Dude!
Join Date: Sep 2016
Location: Amiga Island
Posts: 2,770
|
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. |
05 September 2019, 12:58 | #18 |
aka (Cpt)JohnArcher
Join Date: May 2018
Location: Dresden / Germany
Posts: 193
|
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. |
05 September 2019, 12:58 | #19 |
Banned
Join Date: Aug 2005
Location: London / Sydney
Age: 47
Posts: 20,420
|
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. |
05 September 2019, 13:05 | #20 |
Registered User
Join Date: Jul 2015
Location: The Netherlands
Posts: 3,407
|
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'. |
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 | 52 | 05 December 2020 15:38 |
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 |
|
|