It is currently Thu Aug 17, 2017 8:12 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 65 posts ]  Go to page Previous  1, 2, 3, 4, 5  Next
Author Message
 Post subject: Re: How do I use Vblank?
PostPosted: Sun Mar 12, 2017 1:31 pm 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 18793
Location: NE Indiana, USA (NTSC)
The NMI vector is at $FFFA. From "NMI" on NESdev Wiki:
When the CPU checks for interrupts and find that the flip-flop is set, it pushes the processor status register and return address on the stack, reads the NMI handler's address from $FFFA-$FFFB, clears the flip-flop, and jumps to this address."

Thus the behavior of the CPU when servicing NMI is similar to the following pseudocode:
Code:
push pc>>8
push pc & #$FF
php
jmp ($FFFA)


Thank you for prompting me to check "CPU interrupts" on NESdev Wiki and discover it was missing information.


Top
 Profile  
 
 Post subject: Re: How do I use Vblank?
PostPosted: Sun Mar 12, 2017 2:09 pm 
Offline
User avatar

Joined: Fri May 08, 2015 7:17 pm
Posts: 1681
Location: DIGDUG
Ok, let's talk about what these are doing

.base $8000
RESET:

(code here)

NMI:
IRQ:
rti

;Vectors
.org $FFFA
.dw NMI
.dw RESET
.dw IRQ

######################

As the assembler goes line by line, converting ASM into machine code, it is also counting. BASE $8000, tells it to start counting at $8000. Why is it counting? So we can use Labels in our code.

The first thing the assembler sees after BASE $8000 is the label RESET. It assigns the value $8000 to the label RESET. Now, any time the assembler sees the word RESET, it replaces it (in the machine code) with the value $8000 (actually $00, $80, little endian style)

The advantage here, is, you should be able to move code around in your file, but the assembler should still be able to reassign a new value to RESET, if needed. Let's say that you wrote some code between the BASE $8000 and the label RESET. Now when it counts, it might be at $823c by the time it sees the RESET label... and would then replace all uses of that label with $823c.

The lines past .ORG FFFA, are addresses. DW = 2 bytes. The assembler will see the label for NMI, and replace that with the address of the NMI label. But, the important part, is the NMI label can be anywhere. You don't have to calculate its position and insert it at FFFA. The assembler will do that for you, if you put .DW NMI here.

_________________
nesdoug.com -- blog/tutorial on programming for the NES


Top
 Profile  
 
 Post subject: Re: How do I use Vblank?
PostPosted: Mon Mar 13, 2017 10:05 am 
Offline

Joined: Mon Jan 30, 2017 5:20 pm
Posts: 273
Location: Colorado USA
Would it be like in C# where you use the below code
Code:
int main()
{
NMI();
return 0;
}
static void NMI()
{
// put NMI code here
}

But instead of the NMI function you use BASE($8000)? And also, would I just use the command
Code:
bit $FFFA
to test the state of the NMI?


Top
 Profile  
 
 Post subject: Re: How do I use Vblank?
PostPosted: Mon Mar 13, 2017 11:10 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 18793
Location: NE Indiana, USA (NTSC)
$FFFA is a ROM location. Doing bit $FFFA will not read the state of the PPU.

The state of the NMI generator is at $2002, but there's a race condition associated with reading it. Normally you want to make $FFFA point at a routine that modifies a variable in RAM, then make your main program wait for that variable to change.

If you want an analogy to high-level languages, then $FFFA, $FFFC, and $FFFE contain hardcoded function pointers to listeners for NMI, reset, and IRQ events respectively, and the NMI and IRQ listeners run in a separate thread with priority over the main thread.
Code:
volatile unsigned char nmis = 0;
volatile unsigned char display_list_ready = 0;

int main() {
  RegisterNMIListener(NMI);
 
  // Omitted: init code
  while (!gameover) {
    PollControllers();
    GameLogic();
    PrepareDisplayList();
    display_list_ready = 1;
    vsync();
  }
}

static void vsync() {
  unsigned char oldnmis;
  while (oldnmis == nmis) { }
}

static void NMI() {
  nmis += 1;
  if (display_list_ready) {
    BlitOAM();
    BlitVRAM();
    display_list_ready = 0;
  }
}

In 6502 assembly language, you RegisterNMIListener() by putting a function pointer at $FFFA.


Top
 Profile  
 
 Post subject: Re: How do I use Vblank?
PostPosted: Mon Mar 13, 2017 12:01 pm 
Offline

Joined: Mon Jan 30, 2017 5:20 pm
Posts: 273
Location: Colorado USA
What is a function pointer, and second, what does BASE $8000 and labels have to do with testing a bit? can't you just use a bit command? I don't understand why having the reset label be in $8000 would help test the state of the NMI.


Top
 Profile  
 
 Post subject: Re: How do I use Vblank?
PostPosted: Mon Mar 13, 2017 12:24 pm 
Offline
User avatar

Joined: Fri May 08, 2015 7:17 pm
Posts: 1681
Location: DIGDUG
Base $8000 and Labels have nothing to do with testing a bit. They are instructions for the assembler to generate code with correct addresses.

The memory map of the NES has the program ROM located between $8000 and $ffff. That's why we (have the assembler) start counting bytes from $8000.

The last 6 bytes of the program ROM are special addresses, the starting address of NMI, the starting address of RESET, and the starting address of an IRQ (and BRK).

Writing the code like I did, will ensure that when the ROM is assembled, the last 6 bytes will contain the correct location of these functions.

These addresses POINT to a function. They are function POINTERS.

_________________
nesdoug.com -- blog/tutorial on programming for the NES


Top
 Profile  
 
 Post subject: Re: How do I use Vblank?
PostPosted: Mon Mar 13, 2017 12:55 pm 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 18793
Location: NE Indiana, USA (NTSC)
DementedPurple wrote:
What is a function pointer

"Function pointer" is the term used in C and C++ for something akin to what C# calls a "delegate".


Top
 Profile  
 
 Post subject: Re: How do I use Vblank?
PostPosted: Mon Mar 13, 2017 4:01 pm 
Offline
User avatar

Joined: Fri May 08, 2015 7:17 pm
Posts: 1681
Location: DIGDUG
Just to be clear, I was talking about RESET vectors as an example of how to set up a functional ROM, with a functioning NMI.

From tepples example earlier...

    1. Make an NMI handler, which is a special kind of subroutine that ends with RTI instead of RTS.

    2. Set the vector at $FFFA to point to the NMI handler. Exactly how this is done depends on the assembler you're using.

    3. Set bit 7 of PPUCTRL ($2000) to 1. If bit 7 of PPUCTRL is 1, the CPU will call the NMI handler at the start of every vblank.

I was explaining part 2. Set the NMI vector to point to the NMI handler. I guess I was also explaining part 1...the NMI handler itself is everything between the label NMI: and the RTI.

To USE the NMI, you do part 3, and the PPU will generate an NMI Interrupt at the start of every v-blank, and your code will AUTOMATICALLY jump to the NMI code at this time (which happens 60 times a second).

EDIT, the NMI code should terminate in RTI. At which point it will return to your regular code.

_________________
nesdoug.com -- blog/tutorial on programming for the NES


Top
 Profile  
 
 Post subject: Re: How do I use Vblank?
PostPosted: Wed Mar 15, 2017 12:42 pm 
Offline

Joined: Mon Jan 30, 2017 5:20 pm
Posts: 273
Location: Colorado USA
Okay, so would do the BASE $5000 but instead of $5000 use $FFFA?


Top
 Profile  
 
 Post subject: Re: How do I use Vblank?
PostPosted: Wed Mar 15, 2017 1:23 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 9880
Location: Rio de Janeiro - Brazil
BASE changes the PC instantaneously, while ORG fills the ROM with the fill value up to the specified address. For this reason, BASE has to be used carefully, or you might end up with an invalid ROM. Normally you'll use BASE to switch to a different addressing space (from bank to bank, from PRG to CHR, etc.), but when advancing within the same space you probably want to use ORG.


Top
 Profile  
 
 Post subject: Re: How do I use Vblank?
PostPosted: Wed Mar 15, 2017 1:33 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 9880
Location: Rio de Janeiro - Brazil
Don't mix up assembler commands and the actual program. Things like BASE and ORG are used only by the assembler, to know where to put the code in the ROM and what addresses to use for labels, variables and such. The program running in the CPU doesn't care or know about any of that, it just needs everything to be in the correct places.


Top
 Profile  
 
 Post subject: Re: How do I use Vblank?
PostPosted: Thu Mar 16, 2017 6:47 am 
Offline

Joined: Mon Jan 30, 2017 5:20 pm
Posts: 273
Location: Colorado USA
So what would I do if I wanted to put my game on an actual NES cartridge?


Top
 Profile  
 
 Post subject: Re: How do I use Vblank?
PostPosted: Thu Mar 16, 2017 6:53 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 18793
Location: NE Indiana, USA (NTSC)
If you mean put it on an NES cartridge for testing, the PowerPak and EverDrive N8 are the most common choices for this. These adapters take digital camera memory (CompactFlash or Secure Digital respectively) and plug into an NES Control Deck.

If you mean put it on an NES cartridge for distribution to the public, you have a few options: DIY kits from RetroStage, preassembled user-flashable carts from Infinite NES Lives, or having RetroUSB or Infinite NES Lives manufacture and sell the things for you.


Top
 Profile  
 
 Post subject: Re: How do I use Vblank?
PostPosted: Thu Mar 16, 2017 6:57 am 
Offline

Joined: Mon Jan 30, 2017 5:20 pm
Posts: 273
Location: Colorado USA
Would I be able to use the BASE command on an EPROM cartridge? What equivalent would I have?


Top
 Profile  
 
 Post subject: Re: How do I use Vblank?
PostPosted: Thu Mar 16, 2017 7:27 am 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 9880
Location: Rio de Janeiro - Brazil
What is this thing about BASE? BASE is something you use to structure the ROM correctly. If you already have a working ROM, you don't need anymore BASE statements. If you put anymore of those you'll probably break the ROM's structure. Why are you insisting on that? What exactly are you trying to accomplish with it?


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 65 posts ]  Go to page Previous  1, 2, 3, 4, 5  Next

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 8 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group