initstabilise lda $d012 ldx #10 ; 2 - dex ; (10 * 5) + 4 bpl - ; 54 nop ; 2 eor $d012 - $ff,x; 5 = 63 bne initstabilise; 7 = 70 [...]; timer setup
[...] But back to your INC-based solution: why does it take 9 frames at most?[...]
waitline: inc $d012 bne waitline ...
waitline: lda $d012 bne waitline ...
sync: lax $dc04 sbx #51 sta ZP ;RMW instruction cpx $dc04 bne sync:
I guess it can be easily fixed by blanking the screen in the init code. This is often required anyway when setting up the graphics, so this is not really a constraint.[...]
I can shave off one byte: sync: lax $dc04 sbx #51 sta ZP ;RMW instruction cpx $dc04 bne sync: The loop is 16 cycles and since 461 = 29*16 - 3, this also should always lock. It needs at most 20 consecutive badlines, so the very worst case is that the lower border is reached after 19 badlines and you have to start again at the first badline. So locking is guaranteed in less than 1.4 frames.
Quoting Rastah BarI guess it can be easily fixed by blanking the screen in the init code. This is often required anyway when setting up the graphics, so this is not really a constraint.[...]Forgot to stress this detail, but I had this in mind: you even do not have to set it before the start of the stabilization loop (the first check of $d012 might be a "bad case" anyway), so it suffices to blank screen/kill irqs/etc in the init code blob.
This one looks quite clever, though I did not deep-check "all the math" behind it. One thing (besides the badline-timing) that might also cause a cycle-mismatch at the cpx $dc04-instruction is the behaviour of the timers: afair, it never reaches the $00-value, but gets initialized with the max-value (so $dc04 outputs the same value in two consequetive cycles, but never $00). And as a sidenote: a STA ZP is just a write-instruction, no Read-Modify-Write (the RMW-comment in your code examples confused me a little;)). But the idea you posted with one write-cycle is correct and should work...