Best way to implement CHR/PRG Bank switching?

Discuss emulation of the Nintendo Entertainment System and Famicom.

Moderator: Moderators

Post Reply
beannaich
Posts: 207
Joined: Wed Mar 31, 2010 12:40 pm

Best way to implement CHR/PRG Bank switching?

Post by beannaich »

Hello all!

I've been working on my emulator, and am about to start adding memory mappers. So I've been trying to think of the best way to create a somewhat generic set of methods to accomplish CHR/PRG bank switching. Admittedly, I am something of a novice when it comes to bank switching, so go easy on me! :P

Something like the following will be used in my mapper base class:

Code: Select all

public:
  virtual void SwitchChr() = 0;
  virtual void SwitchPrg() = 0;
Now, the parts I'm unsure of are the following:
1. What parameters will be needed for those methods. (I know I need to specify what size bank I am attempting to switch, but other than that..)
2. If I should have some sort of method that will allow you to modify the values passed to the mapper by the currently running game. (I don't want to do this in the calls to the Switch methods, and have ugly looking code!)

It would be ideal in my opinion to have some sort of pointer array, to keep track of which bank is holding which page of PRG/CHR rom:

Code: Select all

BYTE* prgBank[8];
BYTE* chrBank[8];
But I am unsure, so I'm asking; What do you guys think is the best way to implement what I want?

If I have been unclear, let me know and I will try to correct that!
User avatar
tokumaru
Posts: 12574
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Post by tokumaru »

I believe most people break up the memory into chunks of the smallest bank sizes known to be used by mappers (that would be 4KB for PRG and 1KB for CHR). Then if larger banks than that are used, you just have to adjust multiple pointers (i.e. if the mapper uses 16KB PRG chunks you have to modify 4 pointers to point to 4 contiguous 4KB segments).

I believe your switch methods need 3 parameters: the memory that will become visible (which part of the entire chip), where it will be visible in the NES addressing space (so that you know which pointers to change) and the bank size (so that you know how many pointers to change). All parameters depend on the mapper being used and the values written to its registers.
beannaich
Posts: 207
Joined: Wed Mar 31, 2010 12:40 pm

Post by beannaich »

tokumaru wrote:I believe most people break up the memory into chunks of the smallest bank sizes known to be used by mappers (that would be 4KB for PRG and 1KB for CHR). Then if larger banks than that are used, you just have to adjust multiple pointers (i.e. if the mapper uses 16KB PRG chunks you have to modify 4 pointers to point to 4 contiguous 4KB segments).

I believe your switch methods need 3 parameters: the memory that will become visible (which part of the entire chip), where it will be visible in the NES addressing space (so that you know which pointers to change) and the bank size (so that you know how many pointers to change). All parameters depend on the mapper being used and the values written to its registers.
That's the biggest part I want to address here. I've looked around at some other emulators, to see how they handle this. Some have method calls like this:

Code: Select all

Switch16kPrg((data & ((PRGPages << 2) - 1), 0);
The above code is an eyesore to me, and there has to be a better way.. So that I only have to do something like the following

Code: Select all

Switch16kPrg(data, 0);
Maybe with an internal way of modifying the values passed in, that can be set for each mapper, etc. Do you see what I mean?
Post Reply