It is currently Thu Nov 23, 2017 11:56 am

All times are UTC - 7 hours





Post new topic Reply to topic  [ 7 posts ] 
Author Message
PostPosted: Sun Sep 03, 2017 9:53 am 
Offline
User avatar

Joined: Mon Dec 22, 2008 10:45 pm
Posts: 311
Location: Argentina
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.


Top
 Profile  
 
PostPosted: Sun Sep 03, 2017 11:06 am 
Offline

Joined: Sun Apr 13, 2008 11:12 am
Posts: 6449
Location: UK (temporarily)
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.


Top
 Profile  
 
PostPosted: Sun Sep 03, 2017 11:29 am 
Offline

Joined: Sun Feb 07, 2016 6:16 pm
Posts: 299
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)


Top
 Profile  
 
PostPosted: Sun Sep 03, 2017 11:47 am 
Offline

Joined: Sun Apr 13, 2008 11:12 am
Posts: 6449
Location: UK (temporarily)
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).

Quote:
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.


Top
 Profile  
 
PostPosted: Sun Sep 03, 2017 12:05 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10118
Location: Rio de Janeiro - Brazil
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.


Top
 Profile  
 
PostPosted: Sun Sep 03, 2017 2:36 pm 
Offline

Joined: Mon Nov 10, 2008 3:09 pm
Posts: 431
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)


Top
 Profile  
 
PostPosted: Mon Sep 04, 2017 8:20 am 
Offline
User avatar

Joined: Mon Dec 22, 2008 10:45 pm
Posts: 311
Location: Argentina
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.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 7 posts ] 

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 6 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group