A.D.A. Amiga Demoscene Archive

        Welcome guest!

  

  

  

log in with SceneID

  

Demos Amiga Demoscene Archive Forum / Coding / 100x100 (pattern 2x2) copperchunky 8192 colour mode created using real resolution of 200x201

 

Author Message
Fachen
Member
#1 - Posted: 17 Apr 2015 13:23 - Edited
Reply Quote
Here is the explanation of 70x100 (pattern 2x2) copperchunky 8192 colour mode created using real resolution of 144x200

0. First words

They were created tens of nonstandard graphics modes for Commodore C64. Its time to create something for Amiga too.

--------------------------------------------------------------------------------
1. Theory behind this mode

To explain this mode first I suggest to examine how the memory subsystem works on amiga 500.
http://amigadev.elowar.com/read/ADCD_2.1/Hardware_Manual_guide/node012B.html
Important quotes from there:

"During a horizontal scan line (about 63 microseconds), there are 227.5 "color clocks", or memory access cycles. A memory cycle is approximately
280 ns in duration. The total of 227.5 cycles per horizontal line includes both display time and non-display time. Of this total time, 226
cycles are available to be allocated to the various devices that need memory access."

The time-slot allocation per horizontal line is:

4 cycles for memory refresh
3 cycles for disk DMA (in our case we turn it off)
4 cycles for audio DMA (2 bytes per channel) (we need to have this enabled in demo)
16 cycles for sprite DMA (2 words per channel) (in our case we turn it off)
80 cycles for bitplane DMA (even- or odd-numbered slots according to the display size used)

We are setting resolution of 144x200 with 2 bitplanes which requie from us only 18 cycles.
To display our mode we will use 36 copper instructions, which requie 72 memory cycles,.so 226-4-4-18-72=128 cycles left.

It is pretty much important because MC68000 DOES NOT HAVE cache and without memory access it does nothing.
Ok, but someone may say that with 2 bitplanes we have only 4 colours (except black mask), where we would find another 15, to have total 19? Well, Using sprites.

----------------------------------------------------------------------------------
2. How it will look?

Our displayed pixel will have this pattern.

A0A0C0C0... where A is first logical pixel colour and C is third logical pixel colour
0B0B0D0D... where B is second logical pixel colour and D is forth logical pixel colour

Why this? There is a dithering pattern in middle of interleaved pixels which will visually double the 4096colours (perceptually it will look like 8192 colours)

Of course it can be also

AA00CC00...
00BB00DD...

its just what you prefer.

-------------------------------------------------------------------------------
3. How it can be done?

The one important thing you must understand is that 18 colour registers need to be filled before we will display first pixel of copperchunky mode.
Thats why the copperlist must first fill those 18 collors, before starting repeating the basic 3 colour palette.
To avoid unnecessary copperwork we need to display the sprites only once on the specific position on the screen (no duplication) and thats make first problemm

Why this number (18)?
18 x 4/8 = 9 [displaying 18 (real 4px wide) Logical pixels we can precache another 9 colour]
9/2=4.5 [displaying another 9 (real 4px wide) Logical pixels we can precache another 4.5 colour]
4.5/2=2.25 [displaying another 4.5 (real 4px wide) Logical pixels we can precache another 2.25 colour]
2.25/2=1.125 [displaying another 2.25 (real 4px wide) Logical pixels we can precache another 1.25 colour]
1.25/2=0.625 [displaying another 1.25 (real 4px wide) Logical pixels we can precache another 0 colour - THE END]

Total 18+9+4.5+2,25+1.25=35 copper instructions and 35x4px=140px hence 144x200 real resolution.

We will reserve colour 3 as black mask and by changing its RGB=000 to 111 or 222 we will make the whole screen a little brigther if its requied.
Colour registers number 0-2 together with sprite`s 16-31 will be used for coppermagic.

---------------------------------------------------------------------------------
4. Using sprites for precaching colours.

We will use all sprites 3 colour patterns.
=======================
Sprite 0 and 1 need to be attached (but set at different position) and theirs registers filled with pattern

ccccbbbbaaaa0000 where A is 17th colour register and B is 18th colour register and C is 19th colour register

Pixel Number 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
----------------------------------------------------------------------
SPR0DATA 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 $F0F0 ; Low Sprite Word
SPR0DATB 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 $FF00 ; High Sprite Word

llllhhhhdddd0000 where D is 20th colour register and H is 24th colour register and L is 28th colour register (if we set ATTACH bit and set different positions)

SPR1DATA 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 $F0F0 ; Low Sprite Word
SPR1DATB 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 $FF00 ; High Sprite Word

-----
Sprite 2 and 3 have registers filled with pattern

ggggffffeeee0000 where E is 21th colour register and F is 22th colour register and G is 23th colour register

Pixel Number 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
----------------------------------------------------------------------
SPR2DATA 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 $F0F0 ; Low Sprite Word
SPR2DATB 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 $FF00 ; High Sprite Word

SPR3DATA 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 $F0F0 ; Low Sprite Word
SPR3DATB 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 $FF00 ; High Sprite Word

-----
Sprite 4 and 5 have registers filled with pattern

kkkkjjjjiiii0000 where I is 25th colour register and J is 26th colour register and K is 27th colour register

Pixel Number 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
----------------------------------------------------------------------
SPR4DATA 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 $F0F0 ; Low Sprite Word
SPR4DATB 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 $FF00 ; High Sprite Word

SPR5DATA 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 $F0F0 ; Low Sprite Word
SPR5DATB 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 $FF00 ; High Sprite Word

-----
Sprites 6 and 7 have registers filled with pattern

oooonnnnmmmm0000 where M is 29th colour register and N is 30th colour register and 0 is 31th colour register

Pixel Number 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
----------------------------------------------------------------------
SPR6DATA 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 $F0F0 ; Low Sprite Word
SPR6DATB 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 $FF00 ; High Sprite Word

SPR7DATA 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 $F0F0 ; Low Sprite Word
SPR7DATB 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 $FF00 ; High Sprite Word

=========================
Our sprite has to have constant pattern and be in specific horizontal position, because of that we do not need sprite DMA enabled and we can just fill its registers with the requied pattern once per frame.
If you want you can read more about sprites here http://amigadev.elowar.com/read/ADCD_2.1/Hardware_Manual_guide/node00D0.html#line38

--------------------------------------------------------------------------------
5. Memory requiement.

Our copper list will be using around 148Bytes for every disply line, but it will work as frame buffer (in memory it will take around 28kB). Each instruction uses 16bit and following colour value also uses 16 bits, so our drawing routine would be quite simple in drawing the right (x,y) logical pixel.
We must have 2 such copperlist in memory (one for drawing and one for display, switching between them during vertical blanking) for double buffering (2x28kB=56kB ).
Together with 7kB display data we need around 63kB.

--------------------------------------------------------------------------------
6. CPU cost.

As this is based on copper no cpu is needed, but in display area Copper will steal YHalf of memory slots from CPU (exactly (148/8)x2=37 slots every line)
Overally using this mode CPU looses 7400 memory cycles.
If you think its a lot know this that typical 4x2 mode used in such demos like SUPERPRODUCTION or MULTICOLOR is stealing from CPU 80 slots every line(16000 total)!!!!

--------------------------------------------------------------------------------
7. Copperlist.

;here we preset certain registers
DC.W DMACON,$20 ;Disabling Sprite DMA
DC.W SPR1CTL,$0080 ;set ATTACH bit to create 16colour sprite
DC.W BPLCON2,$0000 ;set playfield priority over sprite to properly mask it
DC.W COLOR03,$0000 ;Move black into register $186 (COLOR03) our mask

DC.W SPR6POS,$00 ;Move Sprite6 at position X=0
DC.W SPR4POS,$00 ;Move Sprite4 at position X=12
DC.W SPR2POS,$00 ;Move Sprite2 at position X=24
DC.W SPR0POS,$00 ;Move Sprite0 at position X=36
DC.W SPR1POS,$00 ;Move Sprite1 at position X=56
DC.W SPR7POS,$00 ;Move Sprite7 at position X=72
DC.W SPR5POS,$00 ;Move Sprite5 at position X=84
DC.W SPR3POS,$00 ;Move Sprite3 at position X=108

DC.W SPR0DATA,$F0F0 ; here we load sprite registers with desired pattern
DC.W SPR0DATB,$FF00
DC.W SPR1DATA,$F0F0
DC.W SPR1DATB,$FF00
DC.W SPR2DATA,$F0F0
DC.W SPR2DATB,$FF00
DC.W SPR3DATA,$F0F0
DC.W SPR3DATB,$FF00
DC.W SPR4DATA,$F0F0
DC.W SPR4DATB,$FF00
DC.W SPR5DATA,$F0F0
DC.W SPR5DATB,$FF00
DC.W SPR6DATA,$F0F0
DC.W SPR6DATB,$FF00
DC.W SPR7DATA,$F0F0
DC.W SPR7DATB,$FF00

;here starts our frame buffer
;This is where our first logical line consist of 2 real lines starts
DC.W COLOR31,$000F ;Move blue into register $234 (COLOR31) - Sprite6
DC.W COLOR30,$00F0 ;Move green into register $232 (COLOR30) - Sprite6
DC.W COLOR29,$0F00 ;Move red into register $230 (COLOR29) - Sprite6
DC.W COLOR27,$000F ;Move blue into register $226 (COLOR27) - Sprite4
DC.W COLOR26,$00F0 ;Move green into register $224 (COLOR26) - Sprite4
DC.W COLOR25,$0F00 ;Move red into register $222 (COLOR25) - Sprite4
DC.W COLOR23,$000F ;Move blue into register $218 (COLOR23) - Sprite2
DC.W COLOR22,$00F0 ;Move green into register $216 (COLOR22) - Sprite2
DC.W COLOR21,$0F00 ;Move red into register $214 (COLOR21) - Sprite2
DC.W COLOR19,$000F ;Move blue into register $210 (COLOR19) - Sprite0
DC.W COLOR18,$00F0 ;Move green into register $208 (COLOR18) - Sprite0
DC.W COLOR17,$0F00 ;Move red into register $206 (COLOR17) - Sprite0
DC.W COLOR02,$000F ;Move blue into register $184 (COLOR02)
DC.W COLOR01,$0F00 ;Move red into register $182 (COLOR01)
DC.W COLOR28,$000F ;Move blue into register $228 (COLOR28) - Sprite1 thnx to ATTACH bit
DC.W COLOR24,$00F0 ;Move green into register $220 (COLOR24) - Sprite1 thnx to ATTACH bit
DC.W COLOR20,$0F00 ;Move red into register $212 (COLOR20) - Sprite1 thnx to ATTACH bit
DC.W COLOR00,$00F0 ;Move green into register $180 (COLOR00)
;This is where precaching ends and at the same time first pixel should be displayed
DC.W COLOR31,$000F ;Move blue into register $234 (COLOR31) - Sprite7
DC.W COLOR30,$00F0 ;Move green into register $232 (COLOR30) - Sprite7
DC.W COLOR29,$0F00 ;Move red into register $230 (COLOR29) - Sprite7
DC.W COLOR27,$000F ;Move blue into register $226 (COLOR27) - Sprite5
DC.W COLOR26,$00F0 ;Move green into register $224 (COLOR26) - Sprite5
DC.W COLOR25,$0F00 ;Move red into register $222 (COLOR25) - Sprite5
DC.W COLOR02,$000F ;Move blue into register $184 (COLOR02)
DC.W COLOR01,$0F00 ;Move red into register $182 (COLOR01)
DC.W COLOR00,$00F0 ;Move green into register $180 (COLOR00)
DC.W COLOR23,$000F ;Move blue into register $218 (COLOR23) - Sprite3
DC.W COLOR22,$00F0 ;Move green into register $216 (COLOR22) - Sprite3
DC.W COLOR21,$0F00 ;Move red into register $214 (COLOR21) - Sprite3
DC.W COLOR02,$000F ;Move blue into register $184 (COLOR02)
DC.W COLOR01,$0F00 ;Move red into register $182 (COLOR01)
DC.W COLOR00,$00F0 ;Move green into register $180 (COLOR00)
DC.W COLOR02,$000F ;Move blue into register $184 (COLOR02)
DC.W COLOR01,$0F00 ;Move red into register $182 (COLOR01)
;This is where total 35 copperpixels were displayed
DC.W COLOR00,$0000 ;Move black into register $180 (COLOR00) - restore black border
;Wait till specific position of another real line

DC.W COLOR31,$000F ;Move blue into register $234 (COLOR31) - Sprite6
DC.W COLOR30,$00F0 ;Move green into register $232 (COLOR30) - Sprite6
DC.W COLOR29,$0F00 ;Move red into register $230 (COLOR29) - Sprite6
DC.W COLOR27,$000F ;Move blue into register $226 (COLOR27) - Sprite4
DC.W COLOR26,$00F0 ;Move green into register $224 (COLOR26) - Sprite4
DC.W COLOR25,$0F00 ;Move red into register $222 (COLOR25) - Sprite4
DC.W COLOR23,$000F ;Move blue into register $218 (COLOR23) - Sprite2
DC.W COLOR22,$00F0 ;Move green into register $216 (COLOR22) - Sprite2
DC.W COLOR21,$0F00 ;Move red into register $214 (COLOR21) - Sprite2
DC.W COLOR19,$000F ;Move blue into register $210 (COLOR19) - Sprite0
DC.W COLOR18,$00F0 ;Move green into register $208 (COLOR18) - Sprite0
DC.W COLOR17,$0F00 ;Move red into register $206 (COLOR17) - Sprite0
DC.W COLOR02,$000F ;Move blue into register $184 (COLOR02)
DC.W COLOR01,$0F00 ;Move red into register $182 (COLOR01)
DC.W COLOR28,$000F ;Move blue into register $228 (COLOR28) - Sprite1 thnx to ATTACH bit
DC.W COLOR24,$00F0 ;Move green into register $220 (COLOR24) - Sprite1 thnx to ATTACH bit
DC.W COLOR20,$0F00 ;Move red into register $212 (COLOR20) - Sprite1 thnx to ATTACH bit
DC.W COLOR00,$00F0 ;Move green into register $180 (COLOR00)
;This is where precaching ends and at the same time first pixel should be displayed
DC.W COLOR31,$000F ;Move blue into register $234 (COLOR31) - Sprite7
DC.W COLOR30,$00F0 ;Move green into register $232 (COLOR30) - Sprite7
DC.W COLOR29,$0F00 ;Move red into register $230 (COLOR29) - Sprite7
DC.W COLOR27,$000F ;Move blue into register $226 (COLOR27) - Sprite5
DC.W COLOR26,$00F0 ;Move green into register $224 (COLOR26) - Sprite5
DC.W COLOR25,$0F00 ;Move red into register $222 (COLOR25) - Sprite5
DC.W COLOR02,$000F ;Move blue into register $184 (COLOR02)
DC.W COLOR01,$0F00 ;Move red into register $182 (COLOR01)
DC.W COLOR00,$00F0 ;Move green into register $180 (COLOR00)
DC.W COLOR23,$000F ;Move blue into register $218 (COLOR23) - Sprite3
DC.W COLOR22,$00F0 ;Move green into register $216 (COLOR22) - Sprite3
DC.W COLOR21,$0F00 ;Move red into register $214 (COLOR21) - Sprite3
DC.W COLOR02,$000F ;Move blue into register $184 (COLOR02)
DC.W COLOR01,$0F00 ;Move red into register $182 (COLOR01)
DC.W COLOR00,$00F0 ;Move green into register $180 (COLOR00)
DC.W COLOR02,$000F ;Move blue into register $184 (COLOR02)
DC.W COLOR01,$0F00 ;Move red into register $182 (COLOR01)
;This is where total 35 copperpixels were displayed
DC.W COLOR00,$0000 ;Move black into register $180 (COLOR00) - restore black border
;Wait till specific position of another real line
;This is where our first logical line consist of 2 real lines ends
;Now we have to repeat this pattern 99 more times creating one big copper list.

--------------------------------------------------------------------------------
8. How to find the specific pixel in Copperlist

Designing this mode i wanted to have a very clear and easy to operate chunky frame buffer.
Each copper instruction consist of 16bit instruction and following 16bit value where hides color data.
If we want to change specific chunkypixel color we just needs to change 16 bit (WORD) color data, without changing tyhe instruction.(single memory operation on MC68k)

First we need to locate the exact address in memory where the veryh first color data in copperlist [in our case DC.W COLOR31,$000F;Move blue into register$234(COLOR31) - Sprite7] resides. Lets call it BEGIN (address) and from this address we will start calculating addresses of other pixels color data.
First we start from ODD pixels

(x,y) ODD logical pixel is hidden in BEGIN + XWords + (y*148Words)

Examples:
First logical pixel in first line (0,0) value is hidden in BEGIN+(0+0 Words) address.
Third logical pixel in first line (2,0) value is hidden in (BEGIN+(2+0 Words) address.
Fifths logical pixel in second line (4,1) value is hidden in BEGIN+(4+(1*228) Words) address.

For even pixels this changes a bit.

(x,y) EVEN logical pixel is hidden in BEGIN + 74Words + xWords + (y*148Words)

Examples:
Second logical pixel in first line (1,0) value is hidden in BEGIN+(74+1+0 Words) address.
Forth logical pixel in first line (3,0) value is hidden in BEGIN+(74+3+0 Words) address.
Sixths logical pixel in fifths line (5,4) value is hidden in BEGIN+(74+5+(3*148) Words) address.

Generally i think it would be preffered if our drawing routine would draw first odd then even pixels

--------------------------------------------------------------------------------
9. End words.

The vertical resolution can be higher however it will limit available memory slots for CPU making it work slower. As for the horizontal resolution it can also be wider, but each expansion have noreason witout adding more bitplanes and will also costs CPU memory cycles, because Copper will steal it.
Copper has higher priority over Blitter so you probably can use it freely.


the source files including special prepared IFF you can download here:
http://www98.zippyshare.com/v/vR4S0EZp/file.html
Lonewolf10
Member
#2 - Posted: 17 Apr 2015 18:04
Reply Quote

That's all very interesting.

Do you have any example source files so that we can go straight to using/playing with it?
britelite
Member
#3 - Posted: 18 Apr 2015 09:10
Reply Quote
Yes, some proof that it actually works would be nice. Otherwise it's just a waste of time.
Fachen
Member
#4 - Posted: 22 Apr 2015 19:47 - Edited
Reply Quote
Lonewolf10: Sorry for the delay. I was shocked how many time i have lost with drawing the proper pattern of IFF ILBM 4 bitplanes. I have drawn the correct pattern, then it turns out the program writes 256 colour IFF and during the conversion all colours changed. I have tried many programms and finally GrafX2 did the job correctly without fucking up the colours. I have prepared and uploaded the IFFs and copperlists above

Enjoy
Lonewolf10
Member
#5 - Posted: 23 Apr 2015 23:04
Reply Quote

Thanks for the files.

I should have time to have a play over the weekend ;)

Fachen
Member
#6 - Posted: 24 Apr 2015 00:11 - Edited
Reply Quote
You are welcome, everything for the glory of Amiga 500 ;-)

 

  Please log in to comment

  

  

  

 

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