no memory mapper knowledge---how do they work for PRG?
Moderator: Moderators
- GradualGames
- Posts: 1106
- Joined: Sun Nov 09, 2008 9:18 pm
- Location: Pennsylvania, USA
- Contact:
no memory mapper knowledge---how do they work for PRG?
So I've been wondering how NES game engines use memory mappers for code. I can easily imagine using them for graphics, swapping out patterns and so forth when needed, but say a game engine takes more than one PRG block. How does a game manage jumping between various locations in the code between PRG banks? Is it just when a certain address is written to, that the write is pre-empted and the bank is switched in from PRG-ROM? Or does the engine have to manually perform this switch?
If the program writes to the PRG bank register, and the program counter is within the switched bank, instruction fetches continue immediately from the new bank. There are three ways for "trampolines", or pieces of code that handle subroutine calls between banks, to work around this:
- Put some of the trampoline code in RAM (common on multicarts and, for some reason, Chinese-developed games). I've written a demo of this method.
- Put identical trampoline code in all PRG banks (common on A*ROM and B*ROM, which use 32 KiB bankswitching).
- Put the trampoline code in a fixed PRG bank (common on U*ROM or S*ROM or T*ROM).
I don't think many "game engines" would take that much code really. The majority of your PRG usage will be for data anyway and not code I imagine. Many games could keep their main code in the fixed upper 16K many mappers have and use the lower 16K for swapping data in at the needed times, including sound engine update routines.
- GradualGames
- Posts: 1106
- Joined: Sun Nov 09, 2008 9:18 pm
- Location: Pennsylvania, USA
- Contact:
I've learned a bit since my OP... I have a simple MMC1 experiment working for example. This has led me to speculate more about how I will be using mappers as I develop a game engine.
Is bankswitching virtually instantaneous? That is to say, could your update routine actually swap in a 16k PRG block for each large chunk of your game engine, and call individual routines within those? For example (pseudo):
Update (a routine in the fixed PRG block):
-swap in massive 16k music engine
-jump to appropriate update routine in the music engine
-swap in massive 16k AI engine
-jump to appropriate update routine in the AI engine
-swap in massive 16k map decoding engine
-jump to appropriate update routine in the map decoding engine
While this example may be extreme, I would assume this sort of thing would be plausible since bankswitching, from what I understand, simply "points" certain address lines at different locations in a ROM, no data is actually being copied.
Is bankswitching virtually instantaneous? That is to say, could your update routine actually swap in a 16k PRG block for each large chunk of your game engine, and call individual routines within those? For example (pseudo):
Update (a routine in the fixed PRG block):
-swap in massive 16k music engine
-jump to appropriate update routine in the music engine
-swap in massive 16k AI engine
-jump to appropriate update routine in the AI engine
-swap in massive 16k map decoding engine
-jump to appropriate update routine in the map decoding engine
While this example may be extreme, I would assume this sort of thing would be plausible since bankswitching, from what I understand, simply "points" certain address lines at different locations in a ROM, no data is actually being copied.
You are 100% right. There is no real overhead caused by bankswitching other than the time the necessary instructions take. For the MMC1 there is a bit of a waste because of all the shifting and multiple writes, but it should still be reasonable to switch banks some 10 times or more in a frame.ZomCoder wrote:While this example may be extreme, I would assume this sort of thing would be plausible since bankswitching, from what I understand, simply "points" certain address lines at different locations in a ROM, no data is actually being copied.