|
Author |
Message |
Jasmin68k
Member |
Hi! 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: 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, Jasmin68k
|
HM Kaiser
Member |
Hi !
Usually, the copperlist is defined as static data, in chip memory.
section copper, data_c copperlist: 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)
|
Jasmin68k
Member |
Hi! 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 copperloop: 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
Member |
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)
|
Jasmin68k
Member |
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
Member |
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.
|
Jasmin68k
Member |
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
Member |
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 :-)
|
Lonewolf10
Member |
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: COPPERLIST_SIZE=10000
* some code *
Section copperlist,bss_c clist ds.w COPPERLIST_SIZE
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. Regards, Lonewolf10
|
d0DgE
Member |
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.
|
Jasmin68k
Member |
Okay, thanks guys, so I guess it's counting words and loops ;) or maybe a big enough buffer in a bss section.
|
|
|