Espozo wrote:
93143 wrote:
That line is what forced blank looks like. You wouldn't have time to rearrange much of OAM during HBlank even if you did turn off rendering during it; a full OAM update takes more than three scanlines of pure DMA. And Mario Kart might have other things to do between the two screens besides the OAM update. So it blanks the display for several scanlines to get it all done.
Doesn't that mean you could actually force blank 1/4 of OAM on one line and there wouldn't be any graphical side effects, Or would the line still be messed up? Or will it still be messed up because it can't "pre fetch" or whatever? It might be worth it to have 4 lines of messed up sprites if it means you could push twice the amount of sprites on screen. (it would probably look better if there were four spread out lines)
I don't think you're getting this. Force blank isn't something you do to OAM. It means
turning the screen off. The fact that you can access OAM while the screen is off is a side effect. And since OAM is 544 bytes and DMA is only 1324 bits per scanline, you'd need to turn the screen off completely for more than three scanlines to update all of OAM in one shot. Those scanlines would be black, not because of the OAM refresh but because you turned off the screen.
While the screen is off, the PPU isn't keeping track of what it would otherwise be doing. This means that if you turn the screen on partway through the active display portion of a frame, it takes a while for the PPU to figure out what's going on. In the case of BG layers, it's a few tiles. In the case of sprites, it's a whole line. So the line
under the black area would (we think) have no sprites, or glitched sprites. (Unless you set the screen to zero brightness for the duration of that line, in which case it too would be black.)
So in your example, you'd get one black scanline (during which you can do a partial OAM update), probably followed by one line with sprites absent or not working properly, and then the picture would work normally for subsequent scanlines.
Quote:
93143 wrote:
I'm pretty sure BG layers work fine a few tiles after force blank is turned off, so as long as you disable force blank early enough after HBlank starts, the next scanline's BG layers should work normally. At least, I've done it with a single 8bpp layer in mode 3. It's only sprites that need extensive preprocessing.
Do you mind showing me what you wrote?
I'm not completely sure how to set it up.
I don't really mind, but be aware that there may be a vulnerability in it, so you shouldn't slavishly copy what I've done... I was using force blank to extend VBlank, and using the IRQ as a substitute for NMI (since you can't change when NMI triggers). Here's the relevant part of my code:
Code:
.ENUM $10
disp db ; screen brightness; can be given to $2100 to turn the screen on
end_vblank db ; IRQ toggle flag
.ENDE
Code:
ldx #$00B0 ; dot number for interrupt
stx $4207 ; set H-timer
ldx #$00DC ; scanline number for interrupt
stx $4209 ; set V-timer
stz end_vblank ; initialize IRQ switch
Code:
lda #$31 ; enable IRQ and controller autopoll
sta $4200
Code:
Interrupt:
phb
pha
phx
phy
phd
php
rep #$30 ; all 16-bit
lda #$0000.w ; reset direct page
tcd
sep #$20 ; mem/A = 8 bit
lda #$00 ; ...but A should already be zero...
pha
plb ; reset data bank
lda end_vblank
beq begin_vblank
ldx #$00B0 ; dot number for interrupt
stx $4207 ; set H-timer
ldx #$00DC ; scanline number for interrupt
stx $4209 ; set V-timer
stz end_vblank ; toggle IRQ
lda disp ; turn the screen back on (brightness stored in RAM)
sta $2100
jmp end_interrupt
begin_vblank:
lda #$80 ; turn the screen off
sta $2100
ldx #$0090 ; dot number for interrupt
stx $4207 ; set H-timer
ldx #$0004 ; scanline number for interrupt
stx $4209 ; set V-timer
inc end_vblank ; toggle IRQ
; VBLANK CODE GOES HERE
end_interrupt:
lda $4211 ; clear interrupt flag
plp
pld
ply
plx
pla
plb
rti
PLEASE NOTE that there is a sporadic timing-sensitive bug hiding somewhere in the program I took this from, and removing the
lda #$00 from the direct page and data bank reset code near the top of the IRQ triggers the bug. (Actually, I can replace the
lda #$00 with two
nops and it will still work, which is very odd as with the
lda #$00 there I can delete both
lda #$0000.w and
tcd and it will
still work...) I am not a guru; use my code with caution.
Better yet, don't use my code at all. Look at it, figure out what it does, and then write your own.
Oh, and if any of the experts on here can tell what might be going wrong (the bug doesn't affect the IRQ; it results in a subroutine the IRQ is interrupting occasionally getting a calculation wrong), please speak up...
Quote:
Oh yeah, If we ever did pull off this stunt, how would you set it up?
I haven't really worked it out yet. The details probably depend on how well it works, if it does (which is looking increasingly unlikely, unless you're willing to accept graphical artifacts). But you sound like you might be on the right track.
As for me, I can't spend a whole lot of time on this right now, because I have a ton of work to do and I'm behind schedule...