Page 1 of 1

6502 Program counter initialization?

Posted: Fri Nov 09, 2007 10:45 am
by johnnie
Hello! I have just started work on a NES emulator, and am working on the first part, the 6502 CPU. On reset or powerup, does the 6502 program counter initialize to the first PRG-bank (0x8000)? If not, where should it get its starting value from? I have looked in several documents, but cannot find any info on the initialization of the PC-register.

Thanks!

Posted: Fri Nov 09, 2007 11:25 am
by kyuusaku
Like all CPUs it's initialized to the reset vector.

Posted: Fri Nov 09, 2007 12:29 pm
by blargg
PC = byte at $FFFD * 256 + byte at $FFFC

Some other processors have a fixed reset vector stored internally, for example 0.

Posted: Fri Nov 09, 2007 1:37 pm
by johnnie
OK, thanks. But there's something (probably fundamental) which I do not understand. Since PRG-ROM is loaded into 0x8000, what would be wrong with initializing PC to 0x8000? I guess this question belongs in the newbie forum, but I'll just post it here to prevent fragmenting the issue across the board.

Posted: Fri Nov 09, 2007 1:45 pm
by never-obsolete
johnnie wrote:OK, thanks. But there's something (probably fundamental) which I do not understand. Since PRG-ROM is loaded into 0x8000, what would be wrong with initializing PC to 0x8000?
because that may be data or non-start up code. with mappers you'd (most of the time) want the RESET vector to point to a "hardwired" bank, make the proper register writes, then jump somewhere else.

Posted: Fri Nov 09, 2007 1:51 pm
by johnnie
never-obsolete wrote:
johnnie wrote:OK, thanks. But there's something (probably fundamental) which I do not understand. Since PRG-ROM is loaded into 0x8000, what would be wrong with initializing PC to 0x8000?
because that may be data or non-start up code. with mappers you'd (most of the time) want the RESET vector to point to a "hardwired" bank, make the proper register writes, then jump somewhere else.
Guess I was kind of stupid in assuming all programs actually *start* at 0x8000. I guess availability of the reset vector is also the reason why games with only one PRG bank must have it loaded into both upper and lower PRG :)

Posted: Fri Nov 09, 2007 2:49 pm
by kyuusaku
ROM isn't "loaded" anywhere, it's enabled when $8000-FFFF is active. Any ROM smaller than 32KiB will be mirrored since A14 isn't being used to select data. In other words the ROM doesn't know the difference between $8000 and $C000.

Posted: Fri Nov 09, 2007 10:36 pm
by blargg
Since PRG-ROM is loaded into 0x8000, what would be wrong with initializing PC to 0x8000?
Nothing. English could be written right to left, bottom to top of page, but since it's not, you can't reasonably read it that way.

The indirect reset vector also isn't necessary. Some other processors jump to fixed addresses that are spaced several bytes apart, which gives enough room for a JMP $xxxx. If the routine is short, it doesn't need the JMP. Given that the 6502 is so optimized, they probably found a way to do the indirect vector with only a few extra transistors, and it gives you slightly faster IRQ handling since you don't need an extra JMP.

Posted: Sat Nov 10, 2007 1:24 am
by johnnie
kyuusaku wrote:ROM isn't "loaded" anywhere, it's enabled when $8000-FFFF is active. Any ROM smaller than 32KiB will be mirrored since A14 isn't being used to select data. In other words the ROM doesn't know the difference between $8000 and $C000.
Allright, but for the purpose of my emulator, which loads the PRG-banks into a virtual memory map of the 6502 (which is basically just a chunk of 0x10000 size with pointers to key locations like SRAM, APU, PRG etc.), I call it 'loading' ;)

Posted: Sat Nov 10, 2007 5:57 am
by tepples
So you have a design based on copying a chunk whenever the emulated program performs a bank switch operation through the mapper. How will your design hold up when programs start switching banks once every few scanlines?

Posted: Sat Nov 10, 2007 6:49 am
by johnnie
tepples wrote:So you have a design based on copying a chunk whenever the emulated program performs a bank switch operation through the mapper. How will your design hold up when programs start switching banks once every few scanlines?
Good point. I basically just wanted to just mimic the memory map of the 6502. I guess it's a better idea to just store the PRG banks as two pointers to the ROM data.

Posted: Sat Nov 10, 2007 8:31 am
by Disch
I'd opt for 16 pointers rather than 2 (one for each 4K of addressing space).

This will make things easier when you add PRG swapping and mapper support.

Posted: Sat Nov 10, 2007 4:39 pm
by johnnie
Disch wrote:I'd opt for 16 pointers rather than 2 (one for each 4K of addressing space).

This will make things easier when you add PRG swapping and mapper support.
Erhm, I thought PRG-ROM was only 32k? Or are you divindg the entire CPU memory map into 4k-blocks?

Posted: Sat Nov 10, 2007 5:22 pm
by Disch
johnnie wrote:Or are you divindg the entire CPU memory map into 4k-blocks?
Bingo

Having 16 pointers for PRG is a little bit of a waste since the low pointers won't be used -- but it avoids come extra math later

Code: Select all

return prg[ address >> 12 ][ address & 0x0FFF ];

instead of

return prg[ (address >> 12) - 8 ][ address & 0x0FFF ];
plus some mappers can put PRG-ROM at the $6000-7FFF range (mapper 069 comes to mind)... and theoretically it's possible for it to be at $4xxx and $5xxx as well.