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

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

Re: How do I use Vblank?

Post by DementedPurple »

Sorry, I thought the BASE statement was something like a .db statement that wouldn't work on the actual hardware. If I were to write the binary file to an actual EPROM, would the NMI code appear in that section?
User avatar
dustmop
Posts: 136
Joined: Wed Oct 16, 2013 7:55 am

Re: How do I use Vblank?

Post by dustmop »

.db reserves space in memory (RAM or ROM, depending on usage and the assembler), and it works just fine on hardware.

Generally speaking, anything in a compiled .nes file that runs in emulator will work the same on hardware when burned on an EPROM. There are tons of exceptions (buggy emulators, startup state, improper mapper usage, lua scripting), but generally speaking the features are the same, especially when talking about how assemblers work.

NMI code will appear in the NES hardware's address space the same way it will in an emulator, regardless of whether you use .BANK for linker relocation, or .SEGMENT directives, or whatever.
Last edited by dustmop on Thu Mar 16, 2017 11:08 am, edited 1 time in total.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: How do I use Vblank?

Post by tokumaru »

The .nes file you run on emulators contains the exact same binary data you burn on EPROMs to run on real hardware, you don't need 2 separate builds when coding the program. To burn EPROMs you just need to take the .nes file and use a tool or an hex editor to split it into header, PRG-ROM and CHR-ROM, and then burn the PRG and CHR to different chips.
DementedPurple
Posts: 318
Joined: Mon Jan 30, 2017 5:20 pm
Location: Colorado USA

Re: How do I use Vblank?

Post by DementedPurple »

Then how would the actual NES know where to go when the NMI is true?
User avatar
dustmop
Posts: 136
Joined: Wed Oct 16, 2013 7:55 am

Re: How do I use Vblank?

Post by dustmop »

Tepples mentioned this earlier. The address at $FFFA contains the NMI "vector", which is just an address that points to the NMI function. So for example, if your NMI function gets compiled such that it is in the ROM at $8123, then the value at $FFFA is $23, and the value at $FFFB is $81 (little-endian order swaps the bytes of the address). You maybe were confused and thought that the vectors were "metadata", like the 16 byte header at the start of the ROM, but they're not. They exist in the binary even when on hardware.
DementedPurple
Posts: 318
Joined: Mon Jan 30, 2017 5:20 pm
Location: Colorado USA

Re: How do I use Vblank?

Post by DementedPurple »

If the NMI vector is at $FFFA, would that mean I'm limited to only 4 bytes of NMI code?
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: How do I use Vblank?

Post by tepples »

The vector $FFFA can point anywhere in ROM or RAM.

The vast majority of Super Mario Bros., for instance, is its NMI handler. That's because it's structured roughly like the following pseudocode:

Code: Select all

main() {
  setup_hardware();
  init_globals();
  enable_nmi();
  for (;;) { }
}

__interrupt__ void nmi() {
  PUSH_ALL;
  if (vram_data_ready) {
    copy_data_to_vram();
    vram_data_ready = 0;
  }
  read_controllers();
  game_logic();
  prepare_data_for_vram();
  vram_data_ready = 1;
  POP_ALL;
}
User avatar
dougeff
Posts: 3079
Joined: Fri May 08, 2015 7:17 pm

Re: How do I use Vblank?

Post by dougeff »

Nothing at fffa but an address.

When the processor gets an Interrupt signal, it will jump somewhere. Fffa tells it where to jump.
nesdoug.com -- blog/tutorial on programming for the NES
User avatar
mikejmoffitt
Posts: 1353
Joined: Sun May 27, 2012 8:43 pm

Re: How do I use Vblank?

Post by mikejmoffitt »

DementedPurple wrote:If the NMI vector is at $FFFA, would that mean I'm limited to only 4 bytes of NMI code?
Think of it as a function pointer.
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: How do I use Vblank?

Post by tepples »

DementedPurple wrote:What is a function pointer
Pokun
Posts: 2681
Joined: Tue May 28, 2013 5:49 am
Location: Hokkaido, Japan

Re: How do I use Vblank?

Post by Pokun »

DementedPurple wrote:If the NMI vector is at $FFFA, would that mean I'm limited to only 4 bytes of NMI code?
No the interrupt vectors just points to your interrupt handlers. They don't contain any code, just addresses (addresses are 2 byte each). The interrupt handlers contains the code.

The templates you are using looks something like this:

Code: Select all

;iNES header here

.org $8000

RESET:
;init code here
main:
  ;main loop code here
  jmp main

NMI:
;nmi code here
  rti

IRQ:
;irq code here
  rti

;Interrupt vectors:
  .org $FFFA
  .dw NMI
  .dw RESET
  .dw IRQ
You use labels like "RESET" so you don't have to hard-code the addresses for your interrupt handlers. Of course when the ROM is assembled the vectors will contain constant addresses, but that is the assemblers job to solve. Instructions like .org and .base is for the assembler to know where in the output file everything should be placed. The reason we start at $8000 (or $C000 if ROM is small) is because $8000 is where the ROM area starts in the address space. If we would use .org $0000 as start address, the interrupt vectors (if we don't change their start addresses) would be in the wrong place and the assembled ROM would become too big. It makes more sense to start counting from a number that matches the start address in the ROM area in the address space.

The order of the three interrupt handlers (RESET, NMI and IRQ) doesn't matter, they can be anywhere in the ROM (or RAM as Tepples said). Just make sure that NMI and IRQ handlers ends with an RTI instruction, and the RESET handler ends with an endless loop.

The order of the interrupt vectors DO matter however.
Last edited by Pokun on Fri Mar 17, 2017 5:53 pm, edited 1 time in total.
User avatar
mikejmoffitt
Posts: 1353
Joined: Sun May 27, 2012 8:43 pm

Re: How do I use Vblank?

Post by mikejmoffitt »

Think of it as the NES doing something similar to

Code: Select all

JSR $FFFA
every time there is an NMI. That's not literally what's going on, but the point is that $FFFA stores the address of your NMI routine, and the 6502 reads that memory to find where to jump. We say that $FFFA points to a location in memory.
DementedPurple
Posts: 318
Joined: Mon Jan 30, 2017 5:20 pm
Location: Colorado USA

Re: How do I use Vblank?

Post by DementedPurple »

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? And also, does the NROM template have that built in? Also, could I just do BASE $FFFA before the header?
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: How do I use Vblank?

Post by tokumaru »

DementedPurple wrote:would it still go to the NMI?
Yes, as long as NMI generation is enabled in the PPU (bit 7 of register $2000), which you normally do at the end of the initialization code.
And also, does the NROM template have that built in?
All mappers behave the same way in regard to NMIs.
Also, could I just do BASE $FFFA before the header?
Again, what's with this BASE stuff, man? No more BASE, forget about BASE. Specially before the header, that makes no sense whatsoever. Just out of curiosity, what would you be trying to accomplish with a BASE before the header anyway?
DementedPurple
Posts: 318
Joined: Mon Jan 30, 2017 5:20 pm
Location: Colorado USA

Re: How do I use Vblank?

Post by DementedPurple »

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?
Post Reply