I've been using a single interrupt to extend VBlank. Once the stuff that needs doing is done, I poll the V-counter until it hits the scanline I want, and then poll the H-counter until it passes the dot I want. The idea is to turn on the screen in between when the last blank scanline finishes and when the first non-blank scanline starts.
I know I could simply toggle the IRQ and use it twice, and I suspect it would be faster as well as more accurate, but I encountered something very odd with this method that I think might be relevant.
In higan accuracy, the above dot target (215) is just far enough along that in the context of the rest of the code, the screen always gets turned on during HBlank, and no artifacts are seen. I can move it as far forward as 221 before it starts cutting into the next scanline.
On my real SNES, however, while 214 is not quite far enough along to eliminate pixel flutter at the end of the last blank line (and even this happens more than in higan), it is barely far enough along that the screen sometimes isn't turned on until several pixels into the first active line. Which means I can't use this method at all; it apparently has negative wiggle room.
(It worked fine before, but I'm in the middle of adding a lot of functionality, and apparently it disturbs the loop start timing enough to render this technique non-viable. Unless there's a bug I'm missing...)
I'm using all eight HDMA channels, but the screen is de-blanked between scanlines 4 and 5, and none of the HDMA channels have anything to do between line 0 and line 39 or so.
Is this a known issue with higan? I do seem to recall the mode change taking effect at a slightly different horizontal position vs. a real SNES...
Code:
; wait for the right moment to turn the screen back on:
rep #$20 ; 16-bit accumulator
lda #$2100 ; set direct page to PPU regs
tcd
blankline:
sep #$20 ; 8-bit accumulator
lda $37 ; latch H/V counter
lda $3D ; read V-position low byte
xba ; flip bytes in accumulator
lda $3D ; read V-position high byte
and #$01 ; discard upper 7 bits
xba ; flip accumulator bytes again
rep #$20 ; 16-bit accumulator
cmp #$0004 ; check for last blank scanline
bne blankline ; repeat if not there yet
blankdot:
sep #$20 ; 8-bit accumulator
lda $37 ; latch H/V counter
lda $3C ; read H-position low byte
xba
lda $3C ; read H-position high byte
and #$01 ; discard upper 7 bits
xba
rep #$20 ; 16-bit accumulator
sbc #$00D7 ; check if past end of last blank scanline (minus overhead to finish loop and turn screen on)
bmi blankdot ; repeat if not there yet
sep #$20 ; 8-bit accumulator
lda $0010.w ; turn the screen back on (brightness stored in RAM)
sta $2100
rep #$20 ; 16-bit accumulator
lda #$2100 ; set direct page to PPU regs
tcd
blankline:
sep #$20 ; 8-bit accumulator
lda $37 ; latch H/V counter
lda $3D ; read V-position low byte
xba ; flip bytes in accumulator
lda $3D ; read V-position high byte
and #$01 ; discard upper 7 bits
xba ; flip accumulator bytes again
rep #$20 ; 16-bit accumulator
cmp #$0004 ; check for last blank scanline
bne blankline ; repeat if not there yet
blankdot:
sep #$20 ; 8-bit accumulator
lda $37 ; latch H/V counter
lda $3C ; read H-position low byte
xba
lda $3C ; read H-position high byte
and #$01 ; discard upper 7 bits
xba
rep #$20 ; 16-bit accumulator
sbc #$00D7 ; check if past end of last blank scanline (minus overhead to finish loop and turn screen on)
bmi blankdot ; repeat if not there yet
sep #$20 ; 8-bit accumulator
lda $0010.w ; turn the screen back on (brightness stored in RAM)
sta $2100
I know I could simply toggle the IRQ and use it twice, and I suspect it would be faster as well as more accurate, but I encountered something very odd with this method that I think might be relevant.
In higan accuracy, the above dot target (215) is just far enough along that in the context of the rest of the code, the screen always gets turned on during HBlank, and no artifacts are seen. I can move it as far forward as 221 before it starts cutting into the next scanline.
On my real SNES, however, while 214 is not quite far enough along to eliminate pixel flutter at the end of the last blank line (and even this happens more than in higan), it is barely far enough along that the screen sometimes isn't turned on until several pixels into the first active line. Which means I can't use this method at all; it apparently has negative wiggle room.
(It worked fine before, but I'm in the middle of adding a lot of functionality, and apparently it disturbs the loop start timing enough to render this technique non-viable. Unless there's a bug I'm missing...)
I'm using all eight HDMA channels, but the screen is de-blanked between scanlines 4 and 5, and none of the HDMA channels have anything to do between line 0 and line 39 or so.
Is this a known issue with higan? I do seem to recall the mode change taking effect at a slightly different horizontal position vs. a real SNES...