| |
Lord Crucifier
Registered: Feb 2004 Posts: 49 |
VIC trick hickup when wasting cycles vs. raster timing
Hey folks, I'm running across something my brain can't figure out. Here's a reduced test case in KickAssembler:
//------------------------------------------------------------
BasicUpstart2(start)
///////////////////////////////
*= $1000
start:
lda #$00
sta $3fff // Clear border garbage
sei
lda #$35
sta $01
lda #<irq
sta $fffe
lda #>irq
sta $ffff
lda #$01
sta $d019
sta $d01a
lda #$7f
sta $dc0d
lda #$00
sta $d012
cli
jmp *
///////////////////////////////
irq:
lda $d019
and #$01
sta $d019
bne cycle
jmp $ea81
cycle:
lda $d011
ora #$08
sta $d011
.var loop=true
// Simple loop, waiting until raster line $f9
// This works!
.if(loop) {
ldx #$f9
loop:
cpx $d012
bne loop
}
// Waste cycles until raster line $f9
// Doesn't work!
.if(!loop) {
.var x=0
.for (x=0;x<$f9;x++) {
// Waste 63 cycles
.var y=0
.for (y=0;y<30;y++) {
nop
}
bit $fe
}
}
// Verify we're on line $f9
lda $d012
sta $0400
inc $d020
// Open bottom border, turn off screen
lda $d011
and #%11100111
sta $d011
// Give $d020 jiggle some time to show
ldy #$10
dey
bne *-1
dec $d020
jmp $ea81
//------------------------------------------------------------
I want to reach raster line $f9, open the top/bottom borders and turn off the screen. Result: only sideborders are shown. Simple stuff. This works fine in a loop checking if $d012 has arrived at $f9.
But when I try to get to raster line $f9 by dumbly wasting cycles, it doesn't work: the screen is turned off, but the borders aren't opened.
The code above has both methods, change the .var loop=true to .var loop=false to waste cycles instead of waiting on $d012.
I check that I actually did arrive on $f9, and it is the case (when I read out $0400 where I dump the value of $d012, it's in both cases $f9). I also played with some more/less delays in case the timing depended on it, although opening top/bottom borders can require sloppy timing.
Anybody know why the delay version doesn't work? |
|
| |
Rastah Bar Account closed
Registered: Oct 2012 Posts: 336 |
Does it work for line $f8? My first guess is that with the cycle wasting method you just reached line $fa by the time you change $d011. |
| |
Lord Crucifier
Registered: Feb 2004 Posts: 49 |
Yeah, like I said, I played with more/less delay a lot. Even on two-cycle levels, even though this kind of strict timing isn't needed here. But the cycle wasting method will never work. |
| |
Bitbreaker
Registered: Oct 2002 Posts: 508 |
First of all, i find it courageous to jmp to $ea81 after done when kernal is disabled via $01 :-) Also no regs are saved. That however doesn't matter much in this case, as nothing serious happens in the main loop. Setting $d012 to $00 without touching the MSB in $d011 might also give you a irq at either line $00 or $100. That's the very few things i'd fix beforehand. Also an lda $dc0d will make sure no other IRQ is still pending when switching to raster-IRQ only. |
| |
Raistlin
Registered: Mar 2007 Posts: 680 |
You need to debug this in VICE. Enter the monitor, stop at the exact line of code where you’re doing the STa $D011 and look at the raster line there by using the “r” command (registers). This will tell you both the current HSYNC and VSYNC.
Note also that without stable rasters you’ll need to run it several times to make sure that jitter isn’t knocking you to the next line occasionally.
The STA $0400 isn’t accurate because you’re running several instructions after it that might knock you onto the next raster like. |
| |
Raistlin
Registered: Mar 2007 Posts: 680 |
Oh and yeah, what BB said. I didn’t check the IrQ setup logic you had, just assumed that was right ;-) |
| |
Raistlin
Registered: Mar 2007 Posts: 680 |
Oh Christ, wait, looking further, there’s much more wrong with this. You can’t just loop over 63 * 249 cycles... never going to work. That’s ignoring bad lines, sprites, etc. Any good reason why you want to waste all your cycles there.? I assume you plan to fill that with code that does something later on..? |
| |
Smasher
Registered: Feb 2003 Posts: 520 |
Quote: Oh Christ, wait, looking further, there’s much more wrong with this. You can’t just loop over 63 * 249 cycles... never going to work. That’s ignoring bad lines, sprites, etc. Any good reason why you want to waste all your cycles there.? I assume you plan to fill that with code that does something later on..?
if screen is set off 63*249 cycles *could* work. but after "irq:" I don't think rasterline $00 has 63 cycles, since you have some instructions there. try with (x=0;x<$f8;x++) + some NOPs (but only after you have fixed what Bitbreaker said). |
| |
Pantaloon
Registered: Aug 2003 Posts: 124 |
and why not use a raster interrupt instead of wasting those precious cycles. |
| |
Mixer
Registered: Apr 2008 Posts: 452 |
The screen must be on during the frame when you do the first $d011 narrowing. If screen is already off, it won't show the screen. Often this is the previous frame depends on how you time the code. |
| |
Smasher
Registered: Feb 2003 Posts: 520 |
I guess Lord Crucifier is trying to have a situation with screen off and sprites on, as explained in this thread: Screen with no Badlines (just guessing, maybe his goal is completely different).
but with that trick you can't have a full screen fx, because of the raster interrupt at $f9/$fa. so he's trying to reach that rasterline by nopping till there. good guess? :) if it works I'm interested in the solution too! |
| |
TWW
Registered: Jul 2009 Posts: 545 |
Right, first off, push your accumulator at least and secondly clear and latent IRQs from CIA. Thirdly switching off KERNAL is a bad idea if you plan to use KERNAL calls to handle the IRQ
Last, use a CIA timer (tricky) or Raster Compare (easy) to do this. |
| |
Rastah Bar Account closed
Registered: Oct 2012 Posts: 336 |
Quoting Lord CrucifierYeah, like I said, I played with more/less delay a lot. Even on two-cycle levels, even though this kind of strict timing isn't needed here. But the cycle wasting method will never work.
You can open the border also on line $fa, some my first guess was BS. Sorry about that. |
| |
Lord Crucifier
Registered: Feb 2004 Posts: 49 |
Haha, apologies to everyone who got their knickers in a knot from that code. It was just me being SUPERsüperSUBER lame, like joystick-up-my-ass lame, and thanks for all the suggestions for improvement.
Now, on to the problem at hand. The wasted cycles method didn't work because... the screen was already closed when I got to that point. All the 24/25 line toggling in the WORLD can't re-open them borders, right? Puh. It's so simple once you figured it out. Thanks ZeSmasher and Mixer for making that penny drop.
By the way, if you think THIS was lame, wait till you see what I'm bringing to X2018. Get ready to vomit your eyes out, eeeek! |
| |
chatGPZ
Registered: Dec 2001 Posts: 11386 |
for those who stumble about the thread looking for a solution - perhaps post the working snippet? (or... put it on codebase? :)) |
| |
Golara Account closed
Registered: Jan 2018 Posts: 212 |
I think the best way for you to achieve this effect is to do sometging like this in your irq handler
lda #8
sta $d011
;your main code here
lda #249
-:
cmp $d012
bne -
lda #0
sta $d011
this will work no matter how much code you have between these snipets. If it doesn't work then you've got so much code that it goes beyond 249th line. This is the second irq where you have the screen already off. The first irq that your program does should trigger at line 249 and set d011 to 0. Then change irq vector to the second irq handler posted above. |