Advices on implementing mixed switchable and fixed PRG banks

Discuss emulation of the Nintendo Entertainment System and Famicom.

Moderator: Moderators

Post Reply
User avatar
Petruza
Posts: 307
Joined: Mon Dec 22, 2008 10:45 pm
Location: Argentina

Advices on implementing mixed switchable and fixed PRG banks

Post by Petruza »

Hi, my emulator is currently only supporting mapper 0, so the PRG-ROM is just a 32 kB chunk that gets loaded at ROM load and that's it.
So mappers that switch entire 32 kB PRG banks are trivial, but for mapper 2-UNROM, for example, that uses one switchable 16 kB bank and another one fixed, I've thought of these options:

1) Just switch the switchable bank, using a pointer to the selected bank, in which case I have to modify my CPU code because if the PC crosses the bank boundary, I'll have to point to a different chunk in memory, cause they won't be next to each other.
2) I could instead of switching pointers just copy over the whole switchable bank on each bank switch so both banks are always next to each other in memory and PC movement is transparent. It looks unefficient, but moving 16 kB in a modern computer should be near cost zero.
3) I also could create whole 32 kB chunks in memory, one for each switchable 16 kB bank, all with copies of the fixed 16 kB bank so I could just switch between them transparently.

Any ideas? a better solution?
My emulator is made in C.
lidnariq
Posts: 11432
Joined: Sun Apr 13, 2008 11:12 am

Re: Advices on implementing mixed switchable and fixed PRG b

Post by lidnariq »

FCEUX uses an array of function pointers and calls the correct one for each memory access.

Using memcpy will produce subtle bugs later on, e.g. when you get to MMC5.
Sour
Posts: 891
Joined: Sun Feb 07, 2016 6:16 pm

Re: Advices on implementing mixed switchable and fixed PRG b

Post by Sour »

Imo, the simplest option (in the long run), is #1 - an array of pointers (e.g what lidnariq suggested)
When you consider the mappers with bank-switchable PRG RAM at $6000-$7FFF, it becomes hard to ensure your copy and the original stay in sync - it's simpler to just keep a single copy of the data.
Also, keep in mind that PRG ROM can be technically mapped outside the $8000-$FFFF range (although I forget if any mapper actually does this) and that banks can be smaller than 16kb (I believe 8kb is the smallest I have seen for PRG ROM, but smaller banks exist when it comes to PRG RAM)
lidnariq
Posts: 11432
Joined: Sun Apr 13, 2008 11:12 am

Re: Advices on implementing mixed switchable and fixed PRG b

Post by lidnariq »

Sour wrote:Also, keep in mind that PRG ROM can be technically mapped outside the $8000-$FFFF range (although I forget if any mapper actually does this)
FME-7 can bank ROM instead of RAM to $6000. JY Company's mapper collection can too. A bunch of the pirate FDS ports have unbankable ROM fixed there (m40, m50).
and that banks can be smaller than 16kb (I believe 8kb is the smallest I have seen for PRG ROM, but smaller banks exist when it comes to PRG RAM)
There's something weird going on with this board where banking granularity is 4K but that's split into a 3K and a 1K nonadjacent region. Of course, it's another pirate FDS port.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Advices on implementing mixed switchable and fixed PRG b

Post by tokumaru »

Petruza wrote:2) I could instead of switching pointers just copy over the whole switchable bank on each bank switch so both banks are always next to each other in memory and PC movement is transparent. It looks unefficient, but moving 16 kB in a modern computer should be near cost zero.
I won't pretend to know how fast modern computers are at moving data, but don't fail to consider that games might switch banks dozens of times in a single frame, so you may end up with slight performance variations depending on the game/mapper.
AWJ
Posts: 433
Joined: Mon Nov 10, 2008 3:09 pm

Re: Advices on implementing mixed switchable and fixed PRG b

Post by AWJ »

Petruza wrote:Hi, my emulator is currently only supporting mapper 0, so the PRG-ROM is just a 32 kB chunk that gets loaded at ROM load and that's it.
So mappers that switch entire 32 kB PRG banks are trivial, but for mapper 2-UNROM, for example, that uses one switchable 16 kB bank and another one fixed, I've thought of these options:

1) Just switch the switchable bank, using a pointer to the selected bank, in which case I have to modify my CPU code because if the PC crosses the bank boundary, I'll have to point to a different chunk in memory, cause they won't be next to each other.
2) I could instead of switching pointers just copy over the whole switchable bank on each bank switch so both banks are always next to each other in memory and PC movement is transparent. It looks unefficient, but moving 16 kB in a modern computer should be near cost zero.
3) I also could create whole 32 kB chunks in memory, one for each switchable 16 kB bank, all with copies of the fixed 16 kB bank so I could just switch between them transparently.

Any ideas? a better solution?
My emulator is made in C.
It sounds like you've got assumptions about the NES memory layout hardcoded into your CPU implementation. This isn't a good idea and will only further break down as you attempt to emulate more sophisticated mappers (ones with multiple bank slots like MMC3, ones with registers below address $8000 like many third-party mappers, ones which can map RAM above address $8000 and/or map ROM below it like Sunsoft mappers and MMC5) You need to implement an abstract memory system; take a look at FCEU for an example (it's C++ but the actual emulation components were originally written in C and AFAIK are still entirely C-like code that doesn't make use of classes or polymorphism or other C++ features)
User avatar
Petruza
Posts: 307
Joined: Mon Dec 22, 2008 10:45 pm
Location: Argentina

Re: Advices on implementing mixed switchable and fixed PRG b

Post by Petruza »

lidnariq wrote:FCEUX uses an array of function pointers and calls the correct one for each memory access.
Using memcpy will produce subtle bugs later on, e.g. when you get to MMC5.
Sour wrote:Imo, the simplest option (in the long run), is #1 - an array of pointers (e.g what lidnariq suggested) [...]
Oh right! my emulator actually does have the function table for memory I/O, I haven't touched the code for almost a year now and had forgotten about that.
So I guess that's the most elegant solution and more well suited for future mappers too. Thanks!
tokumaru wrote:I won't pretend to know how fast modern computers are at moving data, but don't fail to consider that games might switch banks dozens of times in a single frame, so you may end up with slight performance variations depending on the game/mapper.
Yeah, you're right.
AWJ wrote:It sounds like you've got assumptions about the NES memory layout hardcoded into your CPU implementation. This isn't a good idea and will only further break down as you attempt to emulate more sophisticated mappers (ones with multiple bank slots like MMC3, ones with registers below address $8000 like many third-party mappers, ones which can map RAM above address $8000 and/or map ROM below it like Sunsoft mappers and MMC5) You need to implement an abstract memory system; take a look at FCEU for an example (it's C++ but the actual emulation components were originally written in C and AFAIK are still entirely C-like code that doesn't make use of classes or polymorphism or other C++ features)
You're right, but I failed to mention that my immediate next step is to implement mappers 2,3,7 & 11, which I considered a good compromise between amount of games supported and ease of implementation. Then I'll have to implement more important things before moving to implement MMCs and other mappers. (The whole APU is missing, lightgun support, state save, save RAM, etc.)
So a sub-optimal hacked solution that works with these 4 mappers would be ok for now, I can then improve it when moving to other mappers but that will happen in a distant future.
Never the less, I think the function table solution will be the best choice to cope with future mappers as well.
I will take another look at FCEU though.
Post Reply