Two things: first, it looks like your "turn the screen back on" part actually turns it off. You have to write $0 (or something less than $8) to the high nibble, and something nonzero to the low nibble because that's what controls the screen brightness - if you want full brightness, as is probable, you should write $0F to $2100 to turn the screen on.Espozo wrote:LDA #$80
STA $2100 ; Turn the screen back on
STZ $420C
LDA #$00
STA $4310 ; CPU -> PPU, auto increment, write 1 reg, $2100
LDA #$00
STA $4311
LDY #ForceBlankTable
STY $4312 ; source offset
LDA #$00
STA $4314 ; bank address = $7E (work RAM)
LDA #$02
STA $420C ;start HDMA transfer
Later...
ForceBlankTable:
.DB $60,$80 ; Turns off the screen after line $60
.DB 0
Second, why are you taking your HDMA table values out of WRAM? Is the table actually in WRAM?
Also, the first part of your code is in the NMI routine, right?
Generally you'd use an IRQ. HDMA isn't so useful for this in most cases, because it's not synchronized with the main code. You'd need to be writing raster-aligned cycle-timed code to fit ordinary processing or general-purpose DMA in between two specific scanlines, and that's a very advanced programming technique; I can't help you with such a thing...Regarding updating everything while the screen is off, how do you arrange everything? Would you put the part that gets updated in force blank between where you turn the screen off and where you turn the screen on?
But with an IRQ, you have a whole separate chunk of code that's guaranteed to run at a certain position on the screen, so you can turn off the display, do whatever needs to be done, and then turn it back on.
You can even have the IRQ fire at different times to do different things; the IRQ code itself can change the settings for when it's supposed to fire ($4200 and $4207-420A), and change a variable in RAM or something each time, so it can check that variable at the start and branch to the appropriate task. This can be useful even in a basic case like the Mario Kart split screen, if you can't guarantee that your IRQ code will take exactly the right amount of time - rather than cycle counting with NOPs or polling the H/V counters, just repurpose the IRQ to turn the screen back on (and then un-hijack it again so it works properly during the next frame, obviously).
That's only for the same scanline. I assume Mario Kart re-enables rendering soon enough after the end of the last blank scanline that the next scanline works fine.Also, about graphics being messed up after force blanking mid screen, How is Super Mario Kart able to transfer sprite Data using force blank then? I don't see any abnormalities with the graphics.
I suppose if this was causing trouble, you could re-enable the screen early at zero brightness (write $00 to $2100), and then bump it to full brightness ($0F) at the point where you actually wanted it turned on. Now that I think about it, sprites are scanned and cached during the scanline above the one where they're displayed, and I doubt that happens during forced blank, so this may be what SMK is actually doing...
...maybe I should back off and let an actual expert handle this...
No. If all parts of a sprite are off screen, it doesn't count towards the 32-sprite limit, and if a tile is off screen it doesn't count towards the 34-tile limit.Lastly, are pixels from a sprite that are off screen count toward the limit?
...except when the sprite is at $0100 exactly, in which case all of its tiles count towards the tile limit. Basically, never put a sprite at X=256, especially a big one; no good can come of it.