I must do lots of calculations during VBlank.
And I must write VRAM during VBlank.
It course abnomal of PPU scanline refresh & destroy my screen view.
Who can tell me how to solve this problem.
Why do you absolutelly must do the calculations in VBlank? In most cases you can perform the calculations during the frame and store the results in a buffer. Then, in VBlank, you only copy the bytes directly from the buffer to the PPU.
I can't see a case where it's absolutelly necessary to do calculations in VBlank time. In the game I'm working now, for example, when the screen scrolls and I have to draw a new part (row and/or column) of the level, I don't read the data directly from the level map, because it is heavily encoded and there would be no time to decode it all in time for drawing. So I decode the stuff I want to draw during the frame and a routine copies everything to the PPU in VBlank time.
Maybe you could be more specific on the reason you MUST do the calculations inside VBlank.
when i learn nes 6502, i see all routines for show frame are inside NMI. i think it's unique way in order to get running code to infinite or one condition.
example: I am confused..
is it correct??
Code:
wait for vblank.
NMI:
showing sprites and another stuff (calculations)
infinite:
jmp infinite
yeah, just i can making stuff because nmi is executed..
if i dont have my code inside a nmi when vblanks occurs, it's running in infinite label, but i get nothing here..
any tips??? do you understan my confusion tokumaru?
then im going to wait until bit 7 is 0 (vblank time ends), then i am making calculations here and it's the frame drawing time???
ps: i played with fcultra x and see nametables of smb3, finally i understand for what smb3 use horizontal mirroring, it's because smb3 must having ground level and sky level in differents nametables ;o)
Well, lord_Chile, programs on the NES can be structured in many ways.
The NMI is a routine that runs everytime VBlanks starts, if you have them enabled. Some games have all their code inside the NMI routine. These will write what is needed to the PPU first, and them do the calculations for the next frame, and then finish the NMI with an RTI instruction. I would not recommend doing this in more complex programs, where an NMI could possibly fire while the previous one hasn't finished yet, and that may not be good.
Programs can have only the drawing (PPU writing) routines inside the NMI, and have the main code elsewhere. In this case, the main code wouldn't be "forever: jmp forever". In this case you would do all calculations, move the player and enemies, decode maps, etc., and when finished, set a flag indicating that the frame is ready to be copied to the PPU, and enter a loop that will repeat while this flag is set. When the NMI fires, you check for this flag, if it is set (frame ready for drawing) you can copy the whole stuff to the PPU, and then you clear the flag and return from the NMI (with RTI). Since the flag was cleared, the main code would get out of the loop and start calculating the next frame.
Programs could even not use the NMI at all. They can just calculate the whole frame, wait for VBlank the "traditional way" (wait: bit $2002 bpl wait) and then copy all the data to the PPU. This is cleaner and easier to understand, in my opinion.
The NMI can be really useful when the program is very complex and you have to write data to the PPU in consecutive blocks as they bocome ready, and the main program doesn't ever stop. I was gonna do this with my raycaster, where the program is always calculating new columns of walls and the NMI routine would draw them as they became ready.
lord_Chile, the code you posted is a bit incomplete, and I don't know exactly what you're trying to do there. I can see you are not returning from the interrupt, with the RTI instruction, but I don't know if that is your problem.
i dont have problem now, your explanation era justo mi respuesta.. gracias.
lord_Chile wrote:
then im going to wait until bit 7 is 0 (vblank time ends), then i am making calculations here and it's the frame drawing time???
I don't think you can do that. I think the VBlank flag is cleared as soon as you read it. So, if you read $2002 and the VBlank flag is set, all subsequent reads will return the flag cleared, even if you're still in VBlank, until the NEXT VBlank starts, when the flag will be set again. But you don't usually have a reason to wait for the end of VBlank. There is no problem in calculating the stuff for the next frame while VBlank is still occuring. The other way around is forbiden, you can't write to the PPU outside of VBlank.
Quote:
ps: i played with fcultra x and see nametables of smb3, finally i understand for what smb3 use horizontal mirroring, it's because smb3 must having ground level and sky level in differents nametables ;o)
There is a lot to learn a lot by watching the behavior of the name tables in commercial games.
it's the point:
if you calculations are very much, you dont have time to calculating stuff for next frame in vblank time!! then my question is: you say that you are calculating stuff when frame is drawed.. and in what time it is??? after vblank?? before vblank?? and how can i to know when frames are being drawed??
"After Vblank" is the same as "Before Vblank" if you are thinking about the next frame
You run your game logic while the screen is drawing, after vblank. Then you draw during vblank.
Hum... let's try this...
lord_Chile wrote:
if you calculations are very much, you dont have time to calculating stuff for next frame in vblank time!!
No one should do during VBlank calculations that could be performed outside of it. All results of calculations should be buffered, and then directly written during VBlank.
Quote:
then my question is: you say that you are calculating stuff when frame is drawed.. and in what time it is??? after vblank?? before vblank?? and how can i to know when frames are being drawed??
You don't have to know exactly when it is. It is the time after you drew the graphics of the last frame to the PPU and before you write the graphics for the next.
Don't worry too much about it. If you just repeat this:
calculate - wait vblank - draw, you'll be safe, as long as the drawing routines don't go past VBlank time. In case the calculation part takes too long, you may just loose a VBlank. You'll loose a frame and it will feel as a slow down to the player, but if it doesn't happen much it's not such a big deal.
To safely detect VBlank though, you should first verify that you are NOT in VBlank, and then wait for it. If you don't do it like this and your calculation/game logic step takes a little more time than a frame (calculations ended after VBlank has already started), you will find yourself inside an incomplete VBlank, meaning the time left may not be enough to do all your drawing. You'll have to ignore this Vblank and wait for the next, so you can use all avaliable time.
The same goes for the flag an NMI technique. If the NMI is triggered and the "ready to draw" flag is not set, you'll just have miss that frame. The calculations were not finished by the time VBlank started, so you can't draw anything yet. Just exit the NMI and leave it for the next time.
i know wait to vblank in asm 6502..
but which is the code in order to know that you are NOT in vblank???
One note, though: you should NOT poll $2002 to wait for VBLANK within your game logic, as you'll have a 14% chance of entirely missing the frame due to a timing glitch - if you read $2002 just as VBLANK starts (either on the exact cycle or on the previous cycle), you will read it as being clear but it will actually be set; it will then be cleared, and you will effectively miss the frame. You should use NMI in your game code, even if it does nothing more than set a variable, since it always triggers (when enabled).
totally confused, but i understand something, i will try..
Q is right. Many homebrewn programs. (the only programs I know of that do NOT use the NMI) suffer from this bug. Don't repeat that mistake.
The only reason where polling $2002 to get vblank status would be needed is if you want to execute vblank without having a valid interrupt vector at $FFFA. i.e., to execute code after you pull the cart out with the power still on.
The only program I know of that does this is Chris Covells Theremin program for the NES. (and it doesn't do any vblank updates) But a small EPROM cart with a NES2serial cable could make a neat "poor man's copyNES" device by doing this.
EDIT: Then again, having no cart in the NES anymore leaves you with little reason to draw anything to vblank at all. I must've somehow confused this idea with the one of "hijacking" unmodified carts with battery RAM using a (modified) Game Genie.
quietust give me a different thinking about vblanks because many and many people says me wait to vblank using bit 7 of $2002.
This discussion is very interesting, tokumaru, memblers what do you say about it??
Quietust wrote:
One note, though: you should NOT poll $2002 to wait for VBLANK within your game logic, as you'll have a 14% chance of entirely missing the frame due to a timing glitch
It would indeed be really bad loosing these random frames here and there. I'm sorry for saying that was an option. You heard it people? Avoid it. =)
Quote:
if you read $2002 just as VBLANK starts (either on the exact cycle or on the previous cycle), you will read it as being clear but it will actually be set; it will then be cleared, and you will effectively miss the frame.
I wouldn't know that exactly, as I don't know what operations are performed on each cycle of the instructions. If the flag didn't get cleared this method would work. Why the hell did Nintendo think it was a good idea to clear the flag on read? The other flags ("sprite 0 hit" and "more than 8 sprites in one scanline") don't get cleared, right?
Quote:
You should use NMI in your game code, even if it does nothing more than set a variable, since it always triggers (when enabled).
You mean you could have your main code pool that variable instead of $2002? But if the game logic takes too long and you're not yet pooling the variable when it gets set, you'll get an incomplete VBlank. Maybe we could still check for "not in VBlank" by reading $2002, but wait for VBlank by pooling the variable. If the read from $2002 returns the flag set, the frame was missed. Yeah, it could work like this...
I was gonna say pretty much the same as what tokumaru said, just do all your calculations during the frame and buffer them so during vblank you can unload the buffer quickly.
I don't put much in my NMI routine besides the needed stuff. I'd also normally do the controller reading and music playing there (after all the PPU stuff is done), because I want that going all the time even if the main loop slows down.
And definitely don't use $2002 polling for vblank waiting, like everyone said, that doesn't work the same on an emulator.
Polling $2002 doesn't offer much advantage.
NMI is definitely more usefull.
If your main code overflows and cannot follow the frames, you'll be happy to still have the music programm and some automatic frame buffering done in NMI routine, so that only a part of the gameplay effectively slows down.
Also, it allow you to place the usual code (stuff like writing sprite DMA) in an un-rolled style.
That means that you only time your NMI to do sprite DMA if its flag is set, but polling $2002 will require you to do sprite DMA manually each time you poll would end.
Eventually, I think there was one commerial game to use $2002 poll, but it wasn't an action game, and it used frame IRQ for the sound, so missing frame would be totally unimportant. This game is the game Enix released between Door Door and Dragon Quest, and his name was so complicated that I don't remember it.
Oh, everyone has posted while I was making my post... anoying.
Quote:
Why the hell did Nintendo think it was a good idea to clear the flag on read?
Imagine this :
Code:
- bit $2002
bpl -
- bit $2002
bpl -
You wanted to poll 2 frames, but it the flag doesn't get cleared, it waits only one frame... AS IT DOES WITH NESTICLE !
I'd personally not like doing controller reading in NMI, because detecting buttons is very anoying to code, and if you additionally have to admit that the button value could in theory change at any time (it a NMI occurs during your calculation parts check the joypad buttons), it sure make things harder. But some peolpe would prefer the other way arround, so it is up to each progammer to do as his/her wishes.
lord_Chile wrote:
quietust give me a different thinking about vblanks because many and many people says me wait to vblank using bit 7 of $2002.
I guess it is still usefull for the first few tasks, where timing isn't critical. Missing a frame inside the main game would sure suck, but what would be the real difference when you're waiting for the PPU to warm up, and you wait 3 frames instead of 2? None. When you're about to turn the screen on for the first time, what's the problem in missing one single frame? No problem.
I'm still not really sure what the best way would be. Since a game has many different areas such as title screen, options screen, different kinds of in-game sections (depending on the game), the NMI would need to check where you are at the moment (some variable can say that) and jump to the appropriate code. But that decision has to be quick or you'll loose precious VBlank time.
Maybe the first thing inside the NMI should be an indirect jump, so that you could redirect it to any routine you wish just by writing it's address to the proper place. Then you could use only NMI's and stop pooling $2002 for good. But I guess it would be necessary to turn NMI's off when changing the address, to avoid the unfortunate, but unlikely case where the jump would happen between the writes of the 2 bytes that make up the address.
That's very easy to overpass.
Have your NMI vertor pointing to RAM (yeah), and write $4c (jump opcode) followed by your real vector adress. It only delays 3 cycles, and the fact to have an NMI occuring in RAM is so cool !!
However, be carefull, when writing the adress to the RAM area, you'll anyway be unable to totally prevent writing the first byte, then the second byte. If an NMI *would* occur during theese two writes, your code will most likly frezee (at least mess up). So, be sure to disable NMI in hardware (write $00 to $2000) or in software (replace $4c per $60 (RTI) then turn it back to $4c when the vector is ready).
Bregalad wrote:
Imagine this :
Code:
- bit $2002
bpl -
- bit $2002
bpl -
You wanted to poll 2 frames, but it the flag doesn't get cleared, it waits only one frame... AS IT DOES WITH NESTICLE !
Yeah, I know this wouldn't work... but if Nintendo had designed tha hardware differently, programmers would have programmed differently than that (waiting for the flag to be clearead and then waiting for it to be set, twice) if they wanted to wait 2 frames. Nintendo certainly didn't choose to clear the flag so you could detect VBlank with less instructions, since their decision pretty much invalidated the use of the flag for the serious stuff, where speed is needed.
Bregalad wrote:
or in software (replace $4c per $60 (RTI) then turn it back to $4c when the vector is ready).
That's a very good idea! Write $60, then the address, and then $4c again. Pretty smart.
There is no chance an NMI would fire before you have the chance to turn them off in the beginning of the program, right? Or else the NES would try to run random crap from RAM... but I guess this is not the case.
Well... at reset, you'll like writing pretty much imediatly $00 to $2000, instantly disabling NMIs.
If, for an obscure reason, an NMI would happen at reset, that could be disastrous in the very particular case of having the processor execute random code writing to SRAM, and possibly erasing/corrupting the game's saves. Else than that, it doesn't matter if it frezee at start up, since NES cartridges often doesn't work the first try, the player will just press the reset button again without caring if his cartridge isn't working because of the hardware or the software.
However, I doubt having an NMI between reset and the first write to $2000 is thinkable. Again, I think this will be very very very unlucky.
About $2002 polling, you're definitely right. But I don't think it is very usefull to ask why Nintendo did that. It sure is a good question, but any answer won't change facts.
Memblers wrote:
I was gonna say pretty much the same as what tokumaru said, just do all your calculations during the frame and buffer them so during vblank you can unload the buffer quickly.
Yeah, but then I said one could just wait for VBlank by polling (sorry, I was writing "pooling" before) $2002... shame on me! =)
I usually use NMI's, but considered polling $2002 a valid option. I'll just keep in mind it's not.
Bregalad wrote:
Quote:
Why the hell did Nintendo think it was a good idea to clear the flag on read?
Imagine this :
Code:
- bit $2002
bpl -
- bit $2002
bpl -
You wanted to poll 2 frames, but it the flag doesn't get cleared, it waits only one frame... AS IT DOES WITH NESTICLE !
Then you do what a lot of "Nesticle game" programmers did, as tokumaru points out:
Code:
- bit $2002
bpl -
- bit $2002
bmi -
- bit $2002
bpl -
But if you want the Nesticle-like behavior, such as if you plan to steal a few scanlines off the top of the NTSC overscan to do nametable or OAM updates, you can still coax that out of a real NES if you can ensure that sprite 0 will always be hit. Here, you'd use a bit/bvs loop.
Quote:
Have your NMI vertor pointing to RAM (yeah), and write $4c (jump opcode) followed by your real vector adress. It only delays 3 cycles, and the fact to have an NMI occuring in RAM is so cool !!
The Apple II "monitor" BIOS used exactly this technique.
Quote:
However, I doubt having an NMI between reset and the first write to $2000 is thinkable. Again, I think this will be very very very unlucky.
Even with the best reset code, you are likely to get an NMI before the STX completes on about one out of 3700 resets:
Code:
reset:
sei
ldx #0
stx $2000
stx $2001
cld
dex
txs
tepples wrote:
Even with the best reset code, you are likely to get an NMI before the STX completes on about one out of 3700 resets.
Eh? Did you measure this? If so, bravo for sitting through hundreds of thousands of resets to get this to such an accurate value. I've found that the NMI is disabled at power-up, but perhaps you're saying it can occur at the beginning even so?
blargg wrote:
tepples wrote:
Even with the best reset code, you are likely to get an NMI before the STX completes on about one out of 3700 resets.
Eh? Did you measure this?
No, I calculated it as 29780 cycles per frame divided by 8 cycles before the sta completes.
Quote:
I've found that the NMI is disabled at power-up
What about at soft reset?
After a soft reset, the vector from the previous reset would most probably be decent in the good area of RAM.
And it while changing the adress, you write $60 to the vector's destination as I said above, it will perform RTS, not RTI, which is $40. I just said something wrong.
This method can be fairly dangerous if NMI *could* be triggered between the reset and the first write to $2000 with bit 7 clear, at least on the first startup where most RAM contain only $ff.
But if it would contain data that *may* do something with $6000-$7fff, it *may* alter game saves and that would be really bad.
tepples wrote:
What about at soft reset?
NMI is disabled after soft reset. Code enables NMI then loops. Reset vector waits half a second and NMI doesn't occur within that time.
blargg wrote:
NMI is disabled after soft reset.
Is this true of Famicom, frontloading NES, and toploading NES? I seem to remember that they behave differently on reset, such that only the CPU gets reset on the Famicom, not the PPU.