| |
Copyfault
Registered: Dec 2001 Posts: 475 |
Stable Raster via Timer
Maybe some of you advanced coders can help me with the following oddity. I'll keep out the basic routine for stabilizing rasters with the timer method, as it is presumably known to everyone!
If we ignore Illegal Ops for the moment, the max. number of cycles occuring in the main prog is 7 (when executing an indexed RMW). When it comes to the different values the variance can take, there should also be 7 (0 to 6 cycles). I wrote some (working!) routines, but I always end up having 8 different variance values. Of course one can live with it, but I wonder where this 8th state comes from!
If necessary, I'll deliver more details. I'd be really happy to understand this behaviour!
Yours, Copyfault |
|
... 65 posts hidden. Click here to view all posts.... |
| |
Cybernator
Registered: Jun 2002 Posts: 154 |
Let's suppose you want to do a 4x4 mode. An IRQ is generated every 8th rasterline. To achieve this with raster-IRQ, you'd need to add 8 to $d012 every time an IRQ occurs. If you use timer, you can set it to generate IRQ every 8*63 cycles, and you don't have to do anything, as the counter will start from beginning after it generates an IRQ (assuming it's in continuous mode :))
|
| |
chatGPZ
Registered: Dec 2001 Posts: 11360 |
@ninja: hehe i used the 2 timer thingy too in the mongobong thingy :) (infact its using 2 timers and raster-irq aswell). two timers seem to be much more useful than just one to me actually. |
| |
Ninja
Registered: Jan 2002 Posts: 411 |
@Cybernator: Heh, I never used 4x4 :) Nevertheless, have you ever tried this? I remember rasterline $000 being one cycle off, or does this count just for the Raster-IRQ in line $000? |
| |
Cybernator
Registered: Jun 2002 Posts: 154 |
I've only used dithered 4x4, 'coz the normal one don't look sexy enough. :) But they are technically the same. I start the timer right before the paper area, and I stop it after 25 interrupts. So the timer is resync-ed each frame.
I just wrote another routine, which starts the timer once, and I use raster IRQ. It works as well, so rasterline $000 also has 63 cycles. But the IRQ is generated at cycle 2, unlike the other rasterlines where it's generated at cycle 1 (counting cycles from 1-63). I still haven't tested this on the real thing. I'll do it right away, but first I need to add visual control. Anyway, the chances that it will work are 99.9% :)
Btw, I noticed that when I start the timer, it takes a few cycles (3?) until it starts the countdown. Is there any detailed info about the CIA? (A doc that explains the inner details, like the VIC-article does for the VIC-II)
|
| |
Oswald
Registered: Apr 2002 Posts: 5086 |
btw.. :) I havent coded a stable raster using CIA timers myself but I have a source... Now... I would like to put sprites over the routine. Is this possible ? And how should I change the routine to get it work ? I've checked what happens if I do this, but even one sprite messes up the routine way too badly... Maybe the solution is to make the interrupt happen as many cycles earlier as much the sprites eat up ? But in this case I need 2 timers... hmm anyone?:) |
| |
Ninja
Registered: Jan 2002 Posts: 411 |
@Cybernator: Stupid me, of course rasterline $000 has 63 cycles, otherwise my routine with raster-irq and one timer wouldn't work as well. It is just that the IRQ is triggered one cycle later. I should really start thinking before using the keyboard :) |
| |
Cybernator
Registered: Jun 2002 Posts: 154 |
The idea is to make the timer have values from 0-7 at the moment when you access it! How do we do that? First I recommend that you write the sync routine. Supposing we are using the one I mentioned above, we have:
(Assume the value is in $dc04)
lda #7
sec
sbc $dc04
The access to $dc04 occurs at the last (4th) cycle of SBC. Now the important thing is to find out where's this cycle in the rasterline. An IRQ condition is given in cycle 1 (with exception to the first rasterline). The processor first needs to finish the current instruction. The smallest nr. of cycles an instruction takes is 2 (eg. NOP). If the IRQ occurs in the first cycle of NOP, there will be 2 cycles delay. If it occurs in the second cycle, there will be 3 cycles delay! So the minimum delay is 2 cycles to finish the current instruction. Then the CPU needs 7 cycles to store the PC and flags to stack and jump to the IRQ routine. So cycle 1 + 2 + 7 = 10. The first possible cycle in which the first instruction of the IRQ will execute is 10.
If there're sprites active, the first possible cycle will happen somewhere later. Let's assume there're 8 sprites active: sprites 0,1,2 are processed at the right border, so they are irrelevant. But the rest of them are. :) I recommend the diagram shown in 'Pal Timing'. You'll see that the CPU is halted until cycle 11. So 10 + 11 = 21 (what a math-dude I am, eh? ;-P)
The first instr. (lda #7) will take cycles 21 and 22. Sec will take 23 and 24. Sbc takes 25, 26, 27 and 28. (or a few cycles later, do to jitter).
Oops! At cycle 28, the timer should have value 7! It's up to you to achieve this. As I mentioned, I noticed delay between the activation of the timer, and the actual countdown.
CCS may be helpful here, unless you really hate MUs. :)
@Ninja: Thinking is better when you have company. :) |
| |
Copyfault
Registered: Dec 2001 Posts: 475 |
@Cybernator: Hmmm, I always thought that the max. delay that occurs with a NOP is 1?!? I mean, if the IRQ occurs in the first cycle of the NOP (let's call it c_1), there is one cycle delay and the IRQ starts at c_1 + 2. If it occurs in the second cycle, there is no delay and the IRQ also starts at c_1 + 2 (it can't start earlier as the instruction has to be finished!). So your calculations should be altered by -1 I assume...
I also observed that the timers do not start immediatly after the start instruction(e.g. STA $DC0E). A closer look at the inner workings of the CIA would really be nice...
Another observation: the timers never give value 0 - at least not in continous mode (that's what I've tried so far;))! Instead they give the max.value!So a stabilization routine like
LDA #$07
SEC
SBC $DC04
<appropriate branch>
should not work correctly! |
| |
Cybernator
Registered: Jun 2002 Posts: 154 |
If the IRQ occurs in the _last_ cycle of any instruction, the CPU will also execute the next one! So if we have two NOPs in succession, there will be 3 cycles delay if the IRQ occured in the second cycle of the NOP!
As for the routine, it will work if there's 7 cycle variance. But with the 8 cycle variance you have shown, it won't. So yes, make it:
lda #8
sec
sbc $dc04
But the first possible cycle in which $dc04 is accessed, should be when $dc04 = 8. |
| |
Copyfault
Registered: Dec 2001 Posts: 475 |
Ok, I see! This does not even contradict the max.of 7 different variance values, as you get some delay between 2 and 8 cycles(= 7 different states). But how does an IRQ behave when triggered during a fulfilled branch condition? When does the processor check the condition? Possibly a branch is internally always 2 cycles long, and if the condition is fulfilled, there will be an extracycle which ofcourse cannot be interrupted, too! This way you have a maximal delay of 9 cycles (e.g. LDA #$00 : BEQ *+2 : INC adr,X). But I guess I'm wrong with this assumption - how could I correctly test it? |
Previous - 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 - Next |