How do I use Vblank?

Are you new to 6502, NES, or even programming in general? Post any of your questions here. Remember - the only dumb question is the question that remains unasked.

Moderator: Moderators

User avatar
mikejmoffitt
Posts: 1348
Joined: Sun May 27, 2012 8:43 pm

Re: How do I use Vblank?

Post by mikejmoffitt » Fri Mar 17, 2017 3:59 pm

DementedPurple wrote:I don't know, I think that a BASE command is like a header, I honestly have no idea. How would the NES know where $FFFA is?
The 6502 processor, as well as the derivative 2A03 processor in the NES, is hard-coded to look to $FFFA, $FFFC, and $FFFE for the three vectors. When it boots up (reset state), it immediately does a JMP ($FFFC) effectively, and that's how your program begins. Whatever you put in $FFFC tells it where to start execution.

I don't know what BASE is - it may be related to the assembler you're using, or whatever - but there's nothing linking it to 6502 programming intrinsically.
Last edited by mikejmoffitt on Fri Mar 17, 2017 6:39 pm, edited 1 time in total.

User avatar
tokumaru
Posts: 11469
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: How do I use Vblank?

Post by tokumaru » Fri Mar 17, 2017 5:06 pm

OK, let's look at what happens in my simple NROM example:

First we have the variables. To set their address we use ENUM, which is an ASM6 command that temporarily sets the program counter without generating any output for anything inside the ENUM block. This is great for variables because they live in RAM, and an .NES file only contains ROM, so the goal is to define the addresses of all variables, without storing anything anywhere.

Then comes the header. The header must be written to the output file, but since it's never mapped to any address space (it's only used to give the emulator or Flash cart information about what to do with the rest of the file), we don't even need to set an address, just output the header bytes.

Then the PRG-ROM starts. To let the assembler know where in the CPU space the code that follows will be mapped to (so it can calculate addresses for labels and stuff), we use BASE, another ASM6 command. BASE simply sets the program counter to whatever value we want. Since we know that PRG-ROM on the NES starts at $8000 (or $C000 if you only have 16KB of it), we use BASE $8000.

Then comes all of the code, and normally we don't need to do any address manipulation in this part. We just write the code and let the assembler update the program counter accordingly.

Now we need to write the interrupt vectors to the output file. Those must be at $FFFA, always, because that's where the CPU will look for them. So now we use ORG $FFFA (ORG is more universal, and works mostly the same in any assembler). Why ORG and not BASE? Because ORG pads the ROM with zeroes (or another value of our choice) up until the specified address. We need that because we don't know how big our code is, so we need this padding to make the ROM size correct. BASE doesn't pad anything, so if you had only 6KB of code and used BASE, your PRG-ROM would end up being 6KB large, instead of the expected 16 or 32KB.

For NROM we don't really need to use BASE... that command is only necessary when we have to roll back the program counter, which normally only happens when we use bankswitching. I only used BASE in the NROM example for consistency with the other templates, that have multiple banks. For NROM ORG would have worked fine, because ORG behaves exactly like BASE if the program counter hasn't been set yet.

Pokun
Posts: 1274
Joined: Tue May 28, 2013 5:49 am
Location: Hokkaido, Japan

Re: How do I use Vblank?

Post by Pokun » Fri Mar 17, 2017 6:26 pm

DementedPurple wrote:So it goes to the NMI code automatically, no matter what the CPU is doing. So if I where to have a loop like the one down below:

Code: Select all

example:
jmp example
would it still go to the NMI?
Sounds like maybe you are not fully familiar with interrupts yet? When an interrupt happens, the program counter is interrupted in the code, no matter where it currently is, and then it jumps to the interrupt handler (the NMI handler in this case). It will then run the code from the start of the interrupt handler until it runs into an RTI instruction. When it does, it will jump back to wherever it was before the interrupt happened.
does the NROM template have that built in?
As long as the interrupt vectors are in the correct place the CPU will be able to find the address for the three interrupt handlers, so yes it does have this built in. The three vectors are a minimal requirement for a 6502 program to work at all I think, it's not NES-specific.

tepples
Posts: 21755
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: How do I use Vblank?

Post by tepples » Fri Mar 17, 2017 6:36 pm

DementedPurple wrote:So it goes to the NMI code automatically, no matter what the CPU is doing. So if I where to have a loop like the one down below:

Code: Select all

example:
jmp example
would it still go to the NMI?
Yes. Super Mario Bros. does exactly this. It sets up the hardware and game state and falls into an infinite JMP loop, and then the entire game runs inside of the NMI handler.
DementedPurple wrote:And also, does the NROM template have that built in? Also, could I just do BASE $FFFA before the header?
As far as I can tell, BASE isn't very useful unless you're trying to copy code to RAM, such as for self-modification or to keep code available no matter which 32K bank is switched in.
mikejmoffitt wrote:When it boots up (reset state), it immediately does a JMP $FFFC effectively, and that's how your program begins. Whatever you put in $FFFC tells it where to start execution.
I thought it was JMP ($FFFC), which reads the program counter from $FFFC instead of actually looking for an opcode at $FFFC.

User avatar
mikejmoffitt
Posts: 1348
Joined: Sun May 27, 2012 8:43 pm

Re: How do I use Vblank?

Post by mikejmoffitt » Fri Mar 17, 2017 6:39 pm

tepples wrote:
mikejmoffitt wrote:When it boots up (reset state), it immediately does a JMP $FFFC effectively, and that's how your program begins. Whatever you put in $FFFC tells it where to start execution.
I thought it was JMP ($FFFC), which reads the program counter from $FFFC instead of actually looking for an opcode at $FFFC.

As far as I can tell, BASE isn't very useful unless you're trying to copy code to RAM, such as for self-modification or to keep code available no matter which 32K bank is switched in.
You are right. That is what I meant, I'll fix it.

User avatar
tokumaru
Posts: 11469
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: How do I use Vblank?

Post by tokumaru » Fri Mar 17, 2017 6:44 pm

tepples wrote:As far as I can tell, BASE isn't very useful unless you're trying to copy code to RAM
Or if you have more than one PRG-ROM bank, in which case you have to move the PC from the end of the bank back to the beginning ($C000 back to $8000 in the case of UNROM, for example). Another option for multiple banks in ASM6 I'm aware of is to assemble each bank separately, but that can get really hard if the banks reference each other a lot.

tepples
Posts: 21755
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: How do I use Vblank?

Post by tepples » Fri Mar 17, 2017 6:47 pm

Good point, if you're just using it like .bank in NESASM or .segment in ca65.

Pokun
Posts: 1274
Joined: Tue May 28, 2013 5:49 am
Location: Hokkaido, Japan

Re: How do I use Vblank?

Post by Pokun » Sat Mar 18, 2017 1:38 am

tokumaru wrote:Another option for multiple banks in ASM6 I'm aware of is to assemble each bank separately, but that can get really hard if the banks reference each other a lot.
That is what I do for the FDS mapper, I couldn't figure out another way that would work.

User avatar
tokumaru
Posts: 11469
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: How do I use Vblank?

Post by tokumaru » Sat Mar 18, 2017 8:37 am

I'm sure BASE would've worked.

Pokun
Posts: 1274
Joined: Tue May 28, 2013 5:49 am
Location: Hokkaido, Japan

Re: How do I use Vblank?

Post by Pokun » Sun Mar 19, 2017 5:02 pm

I tried with base, but I think I probably didn't understand how it worked back then. I might try it again.

DementedPurple
Posts: 318
Joined: Mon Jan 30, 2017 5:20 pm
Location: Colorado USA

Re: How do I use Vblank?

Post by DementedPurple » Tue Mar 21, 2017 11:48 am

Also, is there a way to know when the NMI is not true?

tepples
Posts: 21755
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: How do I use Vblank?

Post by tepples » Tue Mar 21, 2017 11:52 am

It depends on what exactly you mean by "know[ing] when the NMI is not true". What would "know[ing] when the NMI is not true" tell you? Are you trying to wait for the end of vertical blanking?

DementedPurple
Posts: 318
Joined: Mon Jan 30, 2017 5:20 pm
Location: Colorado USA

Re: How do I use Vblank?

Post by DementedPurple » Tue Mar 21, 2017 11:57 am

tepples wrote:It depends on what exactly you mean by "know[ing] when the NMI is not true". What would "know[ing] when the NMI is not true" tell you? Are you trying to wait for the end of vertical blanking?
Yes.

User avatar
tokumaru
Posts: 11469
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: How do I use Vblank?

Post by tokumaru » Tue Mar 21, 2017 12:22 pm

The only reliable way to know when vblank ends is to wait for the sprite overflow or sprite 0 hit flags to be cleared (which happens near the end of vblank), but you have to make sure they were set in the previous frame to begin with. May I ask why you'd need this information? Most people just optimize their vblank handling code so it never extrapolates the allowed time.

DementedPurple
Posts: 318
Joined: Mon Jan 30, 2017 5:20 pm
Location: Colorado USA

Re: How do I use Vblank?

Post by DementedPurple » Tue Mar 21, 2017 12:49 pm

I'm afraid that my Vblank my be too short, and it'll finish early and go to the part where it will read the controllers and then you will be still pressing the right arrow and the x-position will be increasing too fast.

Post Reply