A.D.A. Amiga Demoscene Archive

  Welcome guest! Please register a new account or log in




log in with SceneID


Demos Amiga Demoscene Archive Forum / Coding / Allocating memory for dynamically created copperlist


Author Message
#1 - Posted: 9 Mar 2012 23:49
Reply Quote

I am just getting into the basics of hardware asm coding on our beloved Amiga and got some code that uses the cpu to create a copperlist on startup (maybe modifies it at a later point).

What I am doing now is reserving some space like this:

ds.b 10000

This seems fairly unelegant and I am looking for a way to just reserve as much space as I really need at assembly time.

What I could do now is calculate by hand just how much space the routine which creates the copperlist needs at max and repeat this every time I change something.

There must be a better way which has eluded me so far. Would someone kindly point me in the right direction please?

Best regards,

HM Kaiser
#2 - Posted: 10 Mar 2012 10:46
Reply Quote
Hi !

Usually, the copperlist is defined as static data, in chip memory.

section copper, data_c
dc.w bplcon0,$6400
...various regs setup
BP1 dc.w $00E0,$0000,$00E2,$0000 ;bitplane 1 pointers

where you can update the pointer dynamically in your code with:
lea bitplan1,a0 ;pointer to bitplane data
move.l a0,d0
move.w d0,BP1+6
swap d0
move.w d0,BP1+2

or the same logic for color registers:
CLogo dc.w $0180,$0000,$0182,$0000,$0184,$0000 ;8 colors
dc.w $0186,$0000,$0188,$0000,$018A,$0000
dc.w $018C,$0000,$018E,$0000

where you can make a loop which starts with a pointer at clogo+2, then increase the pointer by 4 to update the next color register, and so on. (useful to update color palette from an iff, or copper color bars effect, for instance)
#3 - Posted: 10 Mar 2012 12:14
Reply Quote

Thank you for your reply. What you describe is what I had seen so far and what seemed pretty straightforward.

Then I stumbled upon a piece of code in some tutorial like this:

lea.l copperlist,a0

move.w #$fffe,d0
move.w #$0180,d1
move.w #$200f,d2
move.w #$0000,d3
move.w #$00e0,d4
move.w d2,(a0)+
move.w d0,(a0)+
move.w d1,(a0)+
move.w d3,(a0)+
add.w #$0100,d2
add.w #$0101,d3
dbf d4,copperloop

move.l #$01800000,(a0)+
move.l #$fffffffe,(a0)+

The only difference being the original code used an absolute address for copperlist, which I want to avoid, and then I am stuck with the aforementioned question: How to reserve the correct amount of memory for copperlist?

Or maybe it's just bad coding technique creating a copperlist like that?
HM Kaiser
#4 - Posted: 10 Mar 2012 13:39 - Edited
Reply Quote
It is not usual for a simple copperlist, and it uses two times more memory, because you have two times the copperlist in memory (once in the code to copy it, and then the copy itself). And this way, you need a code to copy data, which can be easily avoided.

In this particular example, I presume the coder used this method, to avoid redundant static data in sourcecode. (as many times as initialized in d4)

The copperlist is often quite static and simple; very often, the only hardware registers you need to update are bitplane pointers and color registers. So, it is more simple to declare the copperlist as static data, rather than write some code to copy it dynamically.

For instance, to setup a basic lores 2-colors display:

	section	copper,data_c

clist dc.w bplcon0,$1000 ;1 bitplane
dc.w bplcon1,$0000
dc.w ddfstrt,$0038
dc.w ddfstop,$00D0
dc.w diwstrt,$2C81
dc.w diwstop,$2CC1
dc.w bpl1mod,$0000
dc.w $0180,$0000
dc.w $0182,$0FFF
pth dc.w $00E0,0,$00E2,0 ;bitplane pointers
dc.w $FFFF,$FFFE ;end copperlist

EDIT : in your example, you can simply count the number of loops (initialized in d4) and multiply
that would give : (4 words * d4) +4 words
(the 4 words are in the loop, the additional 4 words at the end of the loop)
#5 - Posted: 10 Mar 2012 15:24
Reply Quote
Well, for my simplified example, counting the number of words is quite easy, but that has to be repeated every time the code changes, and might also get more complicated with more complex copperlists (in the actual example from the tutorial there was more like bpl pointers, ddfstrt/stop, diwstrt/stop etc.). Probably there is no other way though, if one insists on creating the copperlist that way.

It doesn't really take twice the amount of memory though, does it? The code to create the copperlist is not nearly as long as the resulting copperlist (in this example depending on the value of d4, of course). Or am I missing something?

So from what you say I take it that creating copperlists like that is less common practice, good to know.

I have worked with static copperlists and updating some bpl pointers etc. before, that's not an issue.

Thanks again for your advice!
HM Kaiser
#6 - Posted: 10 Mar 2012 17:45
Reply Quote
Yes,in this particular exemple,it does indeed not take twice the space,it even saves space, because of the loop. I just thought you would do this way for any copperlist :-)
Maybe you could initialize a counter which increases at each copperlist write,in a single loop, then move this counter in a data register before the final rts, so you could read its content in your assembler software? You could for instance do it by putting the copper copy code in a separate source and run only that portion of code. I don't really see another way.
#7 - Posted: 10 Mar 2012 17:53
Reply Quote
Well, ok, that should work. Maybe I can do that in the end, when a project is finished. At least easier, than counting words/loops by hand.

I am using ASMPro btw. If anyone can think of an automated solution that reserves just enough space at assembly time or somehow dynamically, I'd be happy to hear about it :)

And no, I am not doing this all the time for any copperlist, I just stumbled upon this particulay way of creating one in some tutorial and thought it might come in handy someday, especially for lots of repeating entries like the copper bars in my simple example, hence my question.
HM Kaiser
#8 - Posted: 10 Mar 2012 18:44 - Edited
Reply Quote
In fact I see no big problem to reserve more memory than you need. With ds.b and bss you can allocate space without having your object file growing, it does it at run time,but for a fixed value. For instance:

Section copperlist,bss_c
clist ds.w 10000

It's true that 10000 words is really a lot for a copperlist...you could try with less (at worst it will crash :-)

The bss section is also useful to allocate your bitplans.
For your specific issue, I think it's the better/simplier way, otherwise you'll have to count :-)
#9 - Posted: 12 Mar 2012 03:23 - Edited
Reply Quote
You could always define the size at the start of your program using a variable, so you don't have to hunt through your code to find the specific line/s that need changing. For example:


* some code *

Section copperlist,bss_c

Personally, for my first all ASM demo (available on Aminet here: http://aminet.net/demo/ecs/DD_AllSquare.lha ) I started off with static data which was modified dynamically for use in some of the later screens.

#10 - Posted: 12 Mar 2012 10:36
Reply Quote
I'm doing a bit of a mixture of a static and dynamic (i.e. membuffer) copperlist.
The essential copperdata like dma settings, planes, initial colours, diw start/stop etc. are written statically. After that I have a label "copprg: dcb.w COPPRG_SIZE" declared which is ultimately followed with dc.l -2. Constant COPPRG_SIZE is set at the top of the framework along with many initial constants like plane-size, screenwidth a.s.o.

In the case of a copper program < COPPRG_SIZE I have to of course put a move.l #-2,(ax) at the end of my current dynamic list to tell Copper to finish.

When it comes to determining COPPRG_SIZE I'm too stuck on counting words and multiplying with loop cycles and adding closing words for my biggest of the dynamic lists.
#11 - Posted: 12 Mar 2012 11:47
Reply Quote
Okay, thanks guys, so I guess it's counting words and loops ;) or maybe a big enough buffer in a bss section.


  Please register a new account or log in to comment





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