21 July 2017, 14:42 | #1 |
Registered User
Join Date: May 2017
Location: Belgium
Age: 50
Posts: 334
|
Using the Copper
I'm playing around with the copper, and I came about this example: https://github.com/weiju/amiga_hardw...-002/startup.c I've attached the source and exe.
I've expanded this code somewhat in order to make the copper list dynamic, ie I want to write a new copper list each frame. So I need a frame loop, and here's what I have: Code:
BOOL cont = TRUE; volatile UBYTE *ciaa_pra = (volatile UBYTE *) 0xbfe001; UWORD currCOL = COL1; int currFrame = 0; int maxFames = 50; while(cont) // frame loop { WaitTOF(); currFrame += 1; if(currFrame > maxFames) { currFrame = 0; if(currCOL == COL1) currCOL = COL2; else currCOL = COL1; coplist[7] = currCOL; } if((*ciaa_pra & PRA_FIR0_BIT) == 0) cont = FALSE; // quit when lmb pressed } Also, I'm on a PAL system, so I'm assuming my code runs (exactly) 50 times a second. I've included the color change to occur every 50 frames, but I feel it actually changes quicker than that (so like in 0.8 seconds instead of 1). I've tested in emulation and on real hardware; the behaviour/timing is the same. Can anybody verify this? I'll need to get this basic timing stuff sorted out, if I ever want to do some seriously swinging copper animations, right.. |
21 July 2017, 15:08 | #2 | ||
Registered User
Join Date: Jul 2015
Location: The Netherlands
Posts: 3,423
|
Quote:
As for adding the Blitter, I feel that could still be done in this framework, though you probably want to add some form of double buffering to it in that case to avoid screen tearing/missing bobs. Quote:
If your loop takes less than a scanline (this is possible, though more so on faster processors) it could on occasion hit the WaitTOF so quickly it would still be on the correct scanline and return immediately (depending on how WaitTOF is implemented this can be the case). Which would mean some frames might not actually be waited for at all. Edit: I've checked the documentation (http://amigadev.elowar.com/read/ADCD.../node033B.html) and it seems really unlikely that WaitTOF will trigger more than once per frame. However, it may still be a cause for timing issues - the copperlist will change the colour at a set time, but the interrupt handlers could take a variable amount of time. This could mean that some of the copper writes are added in too late for the copper to execute them, so they execute a frame late. Last edited by roondar; 21 July 2017 at 15:14. |
||
21 July 2017, 15:33 | #3 | |
Registered User
Join Date: May 2017
Location: Belgium
Age: 50
Posts: 334
|
Quote:
|
|
21 July 2017, 15:40 | #4 |
Registered User
Join Date: Dec 2010
Location: Athens/Greece
Age: 53
Posts: 719
|
Have a look here https://github.com/voitureblanche/projet-secret
|
21 July 2017, 16:07 | #5 | |
Registered User
Join Date: May 2017
Location: Belgium
Age: 50
Posts: 334
|
Quote:
Code:
if (faster_machine) WaitTOF(); There's also (before the frame loop) this interesting bit: Code:
if (!faster_machine) OFF_VBLANK; |
|
21 July 2017, 17:25 | #6 |
Registered User
Join Date: Dec 2010
Location: Athens/Greece
Age: 53
Posts: 719
|
It was more like "do you have more fancy stuff in mind than this?" sort of thing.
|
21 July 2017, 17:48 | #7 |
Registered User
Join Date: May 2017
Location: Belgium
Age: 50
Posts: 334
|
|
21 July 2017, 21:40 | #8 |
Registered User
Join Date: May 2017
Location: Belgium
Age: 50
Posts: 334
|
Ok, here's an update, see attachment. We have a moving copper bar (vertically, along a sine) with a customisable color gradient -- woohoo!
You will notice that I'm including .c files in my main file. I should probably separate that into libs later on, but for now it should do, I thought. Strange thing is though, it seems to work for colorUtil.c (line 18), but not for sineUtil.c, which gives a 'decalaration expected' error. So even if including .c files isn't ideal in the long run, shouldn't it just work in this case? You'll also notice a lot of unused functionality in colorUtil.c, btw. Just ignore this for now; I'm just testing stuff out. It's my intention to have a variable height for the bar, so that I can make it look '3D', as if spinning around on a circle. The colors themselves will also be animated, at some point, I hope. If you have any suggestions or remarks about this code, please speak up. I can only learn so much in a day on my own, you know.. |
21 July 2017, 22:04 | #9 |
Registered User
Join Date: Dec 2010
Location: Athens/Greece
Age: 53
Posts: 719
|
You don't include .c
You include .h What you put in .h? The prototypes of the functions you have inside the .c So, create sineUtil.h and colorUtil.h Put there the prototypes of the functions you need, include them even in their corresponding .c (i.e. in sineUtil.c include sineUtli.h, and in colorUtil.c include colorUtil.h) Then include them (the *.h only) in sinecopper.c (which is your "main") (btw, why is the source code of SampleSineWORD in sinecopper.c? Remove it) I'll do one example of .h ------ start of sineutil.h #ifndef SINEUTIL_H #define SINEUTIL_H #include <exec/types.h> void SampleSineWORD(WORD * dst, float offset, float amplitude, UWORD nrSamples); #endif ------- end of sineutil.h what's the define SINEUTIL_H? https://en.wikipedia.org/wiki/Include_guard |
21 July 2017, 22:16 | #10 |
Registered User
Join Date: May 2017
Location: Belgium
Age: 50
Posts: 334
|
Thanks for clarifying this, alkis, I guess I was a little confused as I assumed this would require extra compilation and linking steps, but I'll probably just need to put the .c files in my make (compile + link). Hang on, I'll give that a go.
As I said, including the .c didn't work, so.. |
21 July 2017, 22:54 | #11 |
Registered User
Join Date: May 2017
Location: Belgium
Age: 50
Posts: 334
|
I've reorganised my code (including a local include/colorUtil.h and src/colorUtil.c), adjusted my makefile to include the extra .c file and to also look for header files in this local directory. It doesn't seem to want to compile though, throwing a 'no declarator and no identifier in prototype' error on the first function definition in colorUtil.c. I'm still doing something wrong, aren't I..
|
22 July 2017, 00:59 | #12 |
Registered User
Join Date: Dec 2010
Location: Athens/Greece
Age: 53
Posts: 719
|
In colorUtil.c you are not including colorUtil.h
Replace #include <math.h> with #include "colorUtil.h" (the <> is for system includes, "" are used for local includes...just a convention) |
22 July 2017, 01:11 | #13 |
Registered User
Join Date: May 2017
Location: Belgium
Age: 50
Posts: 334
|
Ah crap, I can't believe I missed that.. Thanks again for your help, now it works!
|
23 July 2017, 00:30 | #14 |
Registered User
Join Date: May 2017
Location: Belgium
Age: 50
Posts: 334
|
Something is not right with my code. ATM, it is supposed to display a pure red bar of 13 lines height, moving from top to bottom and back, following a (precalculated) sine wave. You will notice, however, that it becomes smaller (< 13 lines) when it's moving up, and taller (> 13 lines) when moving down. What?! This is not intended, so something is wrong.
The most obvious thing to consider is that my code to update the copper list is too slow, so the copper reads it (possibly multiple times) while I'm still writing it. But when you think about it, that should give the opposite effect, ie the bar getting smaller when moving down and bigger when moving up. As far as I can see, the only thing that could cause this is my code being too fast (or running too often), so it modifies the list while the copper is still processing it -- and that would probably mean that something's wrong with my frame loop. As an example, consider the bar moving down. The copper starts reading the current list (starting with the upper bar lines), but I replace the second have of that list with the new copper list (which ends lower down), so the bar would be bigger -- which is what we see. If the copper were faster than me, it would read the beginning of the new list (beginning lower down) and the ending of the old list (stopping higher up) -- so the bar would become smaller, which is not what we see. Thank you roondar, who has already suggested that my code may be too fast to be good, but how do I solve this? Maybe I could do some easy timing experiments or something? Count to a million here or there? Code (cleaned up) & exe attached. Note: if you hold the right mouse button, it stops refreshing the copper list, and the bar becomes/stays 13 lines high. This illustrates the problem quite clearly -- and even more so when you lower the animation frame length. At first I thought it was something psycho-visual, you know, but I don't think so.. Just for good measure, here's the frame loop: Code:
BOOL cont = TRUE; volatile UBYTE *ciaa_pra = (volatile UBYTE *) 0xbfe001; volatile UWORD *someLocation = (volatile UWORD *) 0xdff016; while(cont) // frame loop { WaitTOF(); // ON_VBLANK; // don't animate/refresh copper if rmb down if((*someLocation & RMB_BIT) != 0) { iAnim += 1; if(iAnim >= nrAnimFrames) iAnim = 0; centerY = sineTable[iAnim]; calcCopListLinesY(linesY, centerY); refreshCopList(linesY, colors); } if((*ciaa_pra & PRA_FIR0_BIT) == 0) cont = FALSE; } |
23 July 2017, 19:09 | #15 |
Registered User
Join Date: May 2017
Location: Belgium
Age: 50
Posts: 334
|
Ok, I'm not 100% sure how, but I got it working as expected, see attached. The major ingredient seems to be the allocation of an extra buffer copper list. You calculate your next copper list in this buffer, and then, at just the right time, point the copper to this buffer. This requires double the amount of chip memory, of course, but I guess I can live with that for now. Here's the new frame loop:
Code:
while(cont) // frame loop { // don't animate/refresh copper if rmb down if((*someLocation & RMB_BIT) != 0) { iAnim += 1; if(iAnim >= nrAnimFrames) iAnim = 0; centerY = sineTable[iAnim]; calcCopListLinesY(linesY, centerY); if(currCopList == copList1) currCopList = copList2; else currCopList = copList1; refreshCopList(currCopList, linesY, colors); } // ?? don't swap the following 2 lines ?? how does WaitTOF() work, again ?? custom.cop1lc = (ULONG) currCopList; WaitTOF(); if((*ciaa_pra & PRA_FIR0_BIT) == 0) cont = FALSE; // quit when lmb pressed } Anyway, I'm very happy to have it behave correctly, so I can move on to those spectacular effects I have in mind! If anybody could shed some more light on this frame loop thing, though, I'd be even happier! |
23 July 2017, 23:57 | #16 | |
Registered User
Join Date: Jul 2015
Location: The Netherlands
Posts: 3,423
|
Quote:
What I meant was that when the system is running, you can't quite predict at what time during the frame your Copper update would run because the WaitEOF adds your task to the vertical blank interrupt service. Which may or may not be interupted by other interrupts or may or may not have a lot of tasks in it for that particular frame. You can probably circumvent that problem (if it is actually a problem) by increasing the priority of your task a bit. Though it did later occur to me that 0.8 seconds for 50 frames is almost exactly what you'd get if you where running a 60Hz display. Anyway, it seems you got that bit working now so have fun making Copper effects |
|
24 July 2017, 14:24 | #17 | |
Registered User
Join Date: May 2017
Location: Belgium
Age: 50
Posts: 334
|
Quote:
As for the priority: it's my demo, for crying out loud, so it should always have the highest priority imaginable! On a side note: I've noticed that when you press RMB to pause the animation, when the program exits, a popup menu is open on the shell I started it from, so this shell also processed this event. I'd say this is actually good news, but not really desired in this case. So I should probably open my own screen or something? Off I go, happy as a child.. |
|
25 July 2017, 13:00 | #18 | |
ex. demoscener "Bigmama"
Join Date: Jun 2012
Location: Fyn / Denmark
Posts: 1,630
|
Quote:
|
|
25 July 2017, 22:33 | #19 | ||
Registered User
Join Date: Jul 2015
Location: The Netherlands
Posts: 3,423
|
Quote:
My personal view these days is that you either use the OS (to do timing, IO, input, etc) or you don't use the OS at all. Manually disabling interrupts can have detrimental effects on system stability, especially so the system has a 3rd party harddisk controller or any form of network card. That said, it is possible to selectively switch the OS on and off. However, if you wish the OS to stay on... You can change the priority instead and only use OS supported functions to dabble with interrupts (meaning no Forbid()/Permit() and no manual interrupt vectors except through Exec) Quote:
Usually a priority of 5 or 10 is plenty. Anyway, even when using a high priority Wait() functions of any type will return to the OS at least temporarily. However, since your task priority is high, your task will get a slot ahead of pretty much everything else. Last edited by roondar; 25 July 2017 at 22:44. Reason: Grammar update ;) |
||
25 July 2017, 22:39 | #20 |
Registered User
Join Date: May 2017
Location: Belgium
Age: 50
Posts: 334
|
Here's another update. It has the '3D' effect, a customisable gradient (and ellipsoid path) for the bar, a fov for the camera and so on.
It still has some hard coded screen/view/whatever parameters, though, like lineTop/Bottom and such. I should probably get that from the system/screen/.. I'd also like it to go beyond line 255, someday, btw.. I'm not complaining, though, everything's still working as expected, for now.. |
Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
Thread Tools | |
Similar Threads | ||||
Thread | Thread Starter | Forum | Replies | Last Post |
Combining copper scrolling with copper background | phx | Coders. Asm / Hardware | 16 | 13 February 2021 12:41 |
Best way to mix blitting with copper and copper effects | roondar | Coders. Asm / Hardware | 3 | 12 September 2016 13:12 |
copper ? | turrican3 | Coders. Asm / Hardware | 10 | 27 January 2016 09:10 |
Blitter using the copper... | h0ffman | Coders. Asm / Hardware | 9 | 23 February 2012 08:25 |
Understanding the Copper | BippyM | Coders. Tutorials | 38 | 04 September 2010 12:18 |
|
|