No mapper, one 16k PRG block = $C000 origin?

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

Post Reply
User avatar
GradualGames
Posts: 1107
Joined: Sun Nov 09, 2008 9:18 pm
Location: Pennsylvania, USA
Contact:

No mapper, one 16k PRG block = $C000 origin?

Post by GradualGames » Wed Apr 15, 2009 6:38 pm

In Michael Martin's NES 101 tutorial, we find the following comment:

"; Actual program code. We only have one PRG-ROM chip here, so the
; origin is $C000."

I've been basing most of my experiments on his demo, so I've left the .org $c000 in there so far. Now that I want to learn about how to use memory mappers, I'm re-reading a lot of information on the NES memory map.

From what I understand, everything at $8000 is mirrored at $c000 (with no mapper). Thus, I would expect to be able to .org my code at either location without modifying anything else---however this doesn't seem to be the case in practice, only $c000 works. Why is this?

User avatar
Disch
Posts: 1849
Joined: Wed Nov 10, 2004 6:47 pm

Post by Disch » Wed Apr 15, 2009 7:50 pm

.org at $8000 should work. However remember that the vector table needs to be put at $FFFA. If you have the following code:

Code: Select all

.org $8000

 ;; your program here

.pad $FFFA

 ;; your vector table here
This probably requires you have 2 16K PRG banks, Because if you only have one, the code might get cut-off after $C000 (and thus the vector table will be omitted from your final binary -- causing it to fail to start).

If you want to try it out with just 1 16K bank, you can "trick" the assembler by putting the vector table at $BFFA (since that will be mirrored at $FFFA by the emulator/cartridge).

User avatar
GradualGames
Posts: 1107
Joined: Sun Nov 09, 2008 9:18 pm
Location: Pennsylvania, USA
Contact:

Post by GradualGames » Sat Apr 18, 2009 6:40 am

Thanks Disch! That makes perfect sense. I guess it hadn't occurred to me that .pad $FFFA goes beyond the 16k that would start at $8000. Now I think I understand why some mappers can "fix" a 16k prg block at either $8000 or $C000---this is so you can basically have 32k for game code, correct? So if you have code at $8000, it should just keep on executing right past the block boundary, since when the CPU accesses anything in the second PRG block, the mapper will "override" the mirroring that normally occurs?

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

Post by tokumaru » Sat Apr 18, 2009 8:52 am

PRG-ROM mirroring is not that common, because very few games have only 16KB. Anyway, the CPU is not aware of any mirroring, it will try to execute whatever the PC points to in the 64KB it sees, be it RAM, ROM, registers, whatever. AFAIK, it will even wrap around from $FFFF to $0000 if you let it.

Mappers that "fix" a bank of memory to the end of the addressing space do it so that the programmer can have a place to safely store all the bankswitching logic and the interrupt vectors. In programs that use 32KB bankswitching, the reset code and the vectors must be replicated across all the banks, because you never know which one will be mapped in when execution starts. All bankswitching routines and tables will most likely need to be replicated too.

Post Reply