Hi, as I'm just starting to program a NES emulator I may be awfully wrong, but this idea just came to my mind.
Did anyone use a pointer to char instead of an integer to represent the program counter and maybe the index registers X and Y ?
This way you could do:
Code:
opcode = *pc
instead of:
Code:
opcode = prg_rom[pc]
I'm not sure if this method is faster, anyway. Should it be?
Petruza wrote:
Did anyone use a pointer to char instead of an integer to represent the program counter
How do you make sure that the program counter doesn't go outside the ROM?
I guess the same way you do with an int, doing pointer arithmetic.
Code:
if( pc >= rom_base_address + rom_size ) error();
You can screw it up also if you do: opcode[pc] without checking that pc isn't outside the rom boundaries.
PocketNES used a pointer for the program counter, and relative branches are also implemented by manipulating the pointer directly. While this method is clearly faster, it has obvious problems/implementation details:
* Adjacent rom banks in the rom map must be contiguous. "The Magic of Scheherazade" relies on ROM banks which are continuous in the memory map, but not contiguous in the file. If you use a pointer to emulate the Program Counter, you'll get a crash whenever the enemy uses magic against you.
* You need to encode the PC to a 16-bit pointer whenever pushing it to the stack when performing a call or interrupt.
You need to calculate the address within the ROM when you jump, or return from a subroutine/interrupt.
* You can often get away with using offsets of the pointer for relative jumps, but sometimes you get page-crossing small jumps to the next page, which will fail if the pages are contiguous in the memory map, but not contiguous in the file.
* If a game executes code at the end of RAM and expects it to wrap around to the zeropage, that will fail (I don't think any game does this though).
* If a game executes code at the end of SRAM and expects it to wrap around to the beginning of the next ROM page, that will fail.
In the PocketNES method, whenever you perform an absolute jump, or subroutine return, it looks up the base address of the bank it's jumping to, adds the 16-bit PC value, then saves that somewhere so it re-obtain a different 16-bit PC value when it needs to push the PC onto the stack.
PocketNES keeps a set of 8 pointers to each 8K of memory so it can quickly look up what the base address should be. The pointers have their base address subtracted as well, so a pointer to ROM 8000 also has -8000 added to the pointer value, so you then add PC to that and get the real address.