Okay, this might be a little vague a question, but about how long should it take me to fill a nametable with the screen turned off?
I have no idea what I should be aiming for as far as speed goes... Is one frame fast? Two? Three? Four?
I understand that it would depend on the compression used, and how many layers of metatiles you have, but if any one could give me some relative numbers that would be pretty handy...
It takes about half the screen time to update one nametable using a not-unrolled loop. This is for a simple memcpy style update.
In my scroller demo, it took about 5 frames to update an entire nametable when I used the same code called when scrolling rows onto the screen. Your mileage may vary.
Yeah, just copying bytes to VRAM can be done in less than a frame, so what really dictates the time it will take is where the data that goes to VRAM is being copied from. If it's stored uncompressed in the ROM the whole thing will be very fast, otherwise, all levels of compression must be taken into consideration.
Drawing the initial screen of my game takes 17 frames (1 column of metatiles per frame), but that's because the game engine is already running and the title card is being displayed (meaning rendering is not disabled) in the alternate name table.
If you don't mind elaborating, why is this time important to you?
Okay, thanks a lot!
tokumaru wrote:
If you don't mind elaborating, why is this time important to you?
Sometimes I write code rather backwards. For example, I had a flag for turning off and on the screen. In the NMI, it would check to see if the flag was set, and then alter the screen accordingly. Turns out it's faster and simpler to just to sta $2001 regardless.
If I was taking an extraordinary amount of time to load a whole nametable it would tell me that I not only had a problem with that specific code, but most likely the code to load an individual column or row as well.
It just kinda tells me if I'm on the right track or not.
Thanks again.
For turning ON the screen, it's much better to have a flag to make NMI turn it on. Otherwise you turn on the screen during the middle of draw time, and the whole picture is shifted downwards for one frame.
I don't actually use the flag approach though, I just completely change which NMI handler is used based on whether the screen is on or off. For example, use a limited NMI handler that calls the music engine if the screen is off, and never attempts to do any drawing. Then when you finish drawing, switch back to the normal NMI handler which turns on the screen.
This means that the first instruction of NMI is a jmp (xxxx) instruction. Make sure you disable NMIs while you are updating that address, so you don't end up with a half-updated 16-bit pointer.
This also means that for different types of scenes, you can use a different NMI handler. For example, one that installs interrupts for later, or one that waits for a sprite 0 hit, or whatever.
Opps. I don't write $2001 immediately, I update a variable that writes $2001 every NMI.
The multiple NMI approach seems pretty awesome, so I might just switch! It would be handy to have different NMIs for different states, like the title sequence, or even odd in-game areas. Thanks for the heads up!
Disabling NMI while switching the pointer could mean a visual glitch if NMI was doing important things, though. Simplest to wait in a loop until NMI has just run, then switch the pointer. If the delay is a problem, then work out a scheme that allows an atomic switch. Something like this:
Code:
.org $100
nmi_vec:
.word real_nmi
.word 0
nmi:
jmp (nmi_vec) ; must also be in RAM
Then when you want to switch:
Code:
; Calculate index of inactive address
lda nmi+1
eor #2
tax
; Put new address into inactive vector
lda #<new_nmi
sta nmi_vec,x
lda #>new_nmi
sta nmi_vec+1,x
; Atomically switch to new address
stx nmi+1
This avoids upsetting NMI timing when switching, or missing an NMI. Switching takes constant time as well.