I'm having trouble wrapping my head around how the .nes file and the emulator (or cartridge/NES) interact with each other. From what I understand, the layout for a .asm file goes as such:
.iNes header : 16Bytes
PRG-ROM : 16KB blocks
CHR-ROM : 8KB blocks
Why must the CHR-ROM data come after the PRG-ROM section and why couldn't you include it right after the iNes header instead? Couldn't I tell the assembler to start at address $0000 where the NES RAM is and then include the CHR data and switch to the PRG section at $C000? It seems strange to me how the end of the section is padded to $FFFA to write the NMI/Reset/IRQ addresses, and then the CHR data goes afterwards. Wouldn't that cause the NES CPU to overflow back to $0000?
I guess my question is, how do the addresses in a .asm/nes file relate to the NES CPU? From what I'm starting to believe is the .nes file doesn't sit on the CPU addresses at all, but instead sends bits and bytes from itself towards the CPU. So the CHR-ROM data isn't actually on the NES until the PRG-ROM section 'sends' it, but I'm not completely sure. In that case, why does it matter to set the addresses in the .nes file?
Orsi wrote:
From what I'm starting to believe is the .nes file doesn't sit on the CPU addresses at all
Bingo.
Quote:
but instead sends bits and bytes from itself towards the CPU.
The iNES file describes the content of two separate ROM chips on two separate buses. The PRG ROM is connected to the CPU; the CHR ROM is connected to the PPU. You have to consider each bus separately.
Some mappers support having everything in a single PRG ROM. The most common are UNROM (2), AOROM (7), and SNROM (1). In these cases, the cartridge has a RAM chip where the CHR ROM chip normally sits, and the program copies data from PRG ROM to CHR RAM through the PPU.
Excellent, thanks for the quick reply
. So what is the meaning of starting at $C000 instead of where the NES's PRG-ROM register begins at $8000?
I'm finding it a little confusing trying to piece together my understanding of everything from different sources, which always seem to assume or leave out little details that would make it sooo much easier.
The area mapped to the cartridge is actually $4018-$FFFF. Most cartridges map the PRG ROM chip into $8000-$FFFF. A 32 KiB ROM chip fills the entire area. A 16 KiB ROM chip ignores bit 14 of the address, which means that the ROM is
mirrored at $8000-$BFFF and $C000-$FFFF.
So it really doesn't matter whether you start at $8000 or $C000, so long as you don't spill over the 16KB space. Why do most examples start at #C000 instead of $8000 then?
Orsi wrote:
Why do most examples start at #C000 instead of $8000 then?
Some kinds of data used by the NES CPU, such as the vectors and sampled sound, have to be in $C000-$FFFF. It's easier to explain these if the code is considered to sit at $C000 and get mirrored down than if the code is considered to sit at $8000 and get mirrored up.
The reason that many .ORG their code at $C000 when using 16K PRG is that you can then .ORG $FFFA for the vectors and they'll be at the right place. If you told the assembler to start the code at $8000 the resulting file would be 32K.
For example this would produce 16K ($4000 bytes):
Code:
.ORG $C000
; some code here
.ORG $FFFA
; vectors here
This produces 32K ($10000-$8000 = $8000 bytes)
Code:
.ORG $8000
; some code here
.ORG $FFFA
; vectors here
Now you could do this but it's not obviously as pretty:
Code:
.ORG $8000
; some code here
.ORG $BFFA
; vectors here
This will work fine because 16K PRG is mirrored to $C000+ so even though you defined vectors at $BFFA they'll also appear at $FFFA.
I hope that didn't come out as too confusing.
No, no, they aren't too confusing. I mostly just need clarification as to why these are the cases, I don't like to assume anything is a certain way 'just because'.
Thanks for the replies guys.
Orsi wrote:
I'm finding it a little confusing trying to piece together my understanding of everything from different sources, which always seem to assume or leave out little details that would make it sooo much easier.
Quoted for emphasis. Good thing this forum exists. Though when I first came here, EVERYONE was REALLY over my head about EVERYTHING. At least now I've taken a computer architecture class, learned C and MIPS assembler and have a basic idea of how everything works. Now I just have to learn about all the little NES-specific peculiarities, like how it mirrors memory and how you need to write to certain addresses several times to make something happen etc, but I still find the many documents lacking in the way described in the quote above. I guess the whole point of the Wiki is to solve that problem, but it, too, is very far from complete.
Orsi wrote:
I'm finding it a little confusing trying to piece together my understanding of everything from different sources, which always seem to assume or leave out little details that would make it sooo much easier.
That's why lately, when I answer newbie questions, I've been summarizing some of the answers on the wiki, like
this.
And I very much appreciate it. Keep up the good work.
Quote:
That's why lately, when I answer newbie questions, I've been summarizing some of the answers on the wiki, like this.
I think the main issue is not being able to find what you are looking for unless you already know the technical name for it. For instance, the article above is hidden in the Cartridge Board section, under NROM, in a small paragraph. That's means you'd understand enough about all the different cartridges and are looking up specs for one particular ROM. Now, do you think that kind of person would not know this information already?
I wish I could think of a better place for it, but NROM is really the only place you see 16 KiB PRG ROM. By the time you've decided on a 16 KiB PRG ROM, you've decided on a mapper, and you can look up
mapper 0 to learn more about this mapper, which leads you to the NROM page.
Not necessarily NROM, it could be 16K PRG with WRAM if it's designed to run in an emulator.
Ninja Jajamaru Kun has 16k of PRG, but 16K of CHR as well.
And how do you go about having 16 or 32KB or PRG-ROM and 8KB of CHR-RAM? I've had more luck with mapper 2 than mapper 0 (my raycaster is a 16KB mapper 2 ROM).
tokumaru wrote:
And how do you go about having 16 or 32KB or PRG-ROM and 8KB of CHR-RAM?
Emus that don't recognize an NROM modded with a CHR RAM chip should recognize BNROM or AOROM depending on how you mirror.
I almost always use NROM + CHR-RAM when developing something, and never once that I remember had an emulator complain about it or mess things up. But I don't really use a wide range of emulators anymore.
tepples wrote:
I wish I could think of a better place for it, but NROM is really the only place you see 16 KiB PRG ROM. By the time you've decided on a 16 KiB PRG ROM, you've decided on a mapper, and you can look up
mapper 0 to learn more about this mapper, which leads you to the NROM page.
In the "
Programming Guide" section of the wiki, there's a section under tutorials called "
Programming Mappers". Right now it has articles for
programming UNROM and
programming UOROM. These articles are targetted at the software programmer, and they contain links back to the UNROM/UOROM hardware pages for reference. I think this NROM information would be right at home under this section in its own "Programming NROM" page.
Thanks for reminding me about that page.
These sections have to be more accessible. A lot of us don't even know all the sections that exist!
Once I get a good grasp of the structure of the system, I'll make a good summary of things I found difficult to find or understand and what areas should be elaborated on.
One area I just was enlightened on was the difference between the CPU addressing and the PPU addressing. I kept wondering why the heck we had to send an address to $2006 and then funnel it all through $2007 to write graphics, until I realized that the CPU has no access to the PPU's memory locations because it's completely separated from it! Correct me if I'm wrong, please.
Orsi wrote:
I kept wondering why the heck we had to send an address to $2006 and then funnel it all through $2007 to write graphics, until I realized that the CPU has no access to the PPU's memory locations because it's completely separated from it! Correct me if I'm wrong, please.
You're not wrong, that's exactly it. Those registers are used by the CPU as ports to access the PPU addressing space, which is not directly accessible. After receiving an address and a request for reading/writing data, the PPU is able to perform the operation in question because it has direct access to the video memory.