How does the Gameboy's memory bank switching work?Game Boy Sound System Unused Memory LocationsWhat is this...
Authorship dispute on a paper that came out of a final report of a course?
What is the intuition for higher homotopy groups not vanishing?
How electronics on board of JWST can survive the low operating temperature while it's difficult to survive lunar night?
Why do we need an estimator to be consistent?
Inscriptio Labyrinthica
Company looks for long-term employees, but I know I won't be interested in staying long
Is this guy trying to scam me?
Why aren't there any women super Grandmasters (GMs)?
I want light controlled by one switch, not two
Should I work for free if client's requirement changed
Align the contents of a numerical matrix when you have minus signs
Does unblocking power bar outlets through short extension cords increase fire risk?
Why are flying carpets banned while flying brooms are not?
Found old paper shares of Motorola Inc that has since been broken up
Is it possible to have a career in SciComp without contributing to arms research?
Are there foods that astronauts are explicitly never allowed to eat?
Brute-force the switchboard
Should I have shared a document with a former employee?
Did Hitler say this quote about education?
"Je suis petite, moi?", purpose of the "moi"?
Help understanding separation of variables technique
What makes MOVEQ quicker than a normal MOVE in 68000 assembly?
Are there any satellites in geosynchronous but not geostationary orbits?
Can a creature sustain itself by eating its own severed body parts?
How does the Gameboy's memory bank switching work?
Game Boy Sound System Unused Memory LocationsWhat is this unused memory range in the Game Boy's memory map?How did the IBM PC handle multiple physical devices serving memory at the same physical address?Core Memory StabilityPhysically emulate Gameboy cartridge using Raspberry Pi?How does memory addressing/mapping work in 8-bit systems?How did the ZX80 store both a useful program and screen memory?Does fast page mode apply to ROM?How much time does a Mac SE/30 with 128 MB of memory take for its power-on memory test?Details of video memory access arbitration in Space Invaders
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ margin-bottom:0;
}
I'm writing a Game Boy emulator, but I don't completely understand how its memory mapping works. Here is what I (think) I know (and don't know).
The CPU can address up to 0x10000
memory locations with the 16-bit address bus. The memory is mapped as follows:
$0000-$3fff
: a 16KB ROM bank. Initially, reading from this accesses the bootloader, but afterwards ot accesses a fixed bank in the cartridge.
$4000-$7fff
: accesses ROM from cartridge, but can access more memory by switching banks (what does this mean?)
$8000-$9fff
: VRAM, the PPU reads from this to draw the screen
$a000-$bfff
: external ram found in the cartridge, this is the switchable bank?
$c000-$cfff
: actual work RAM stored in the Gameboy (not in the cartridge)
$d000-$dfff
: also the switchable bank that is accessed when reading from $4000-$7fff?
$e000-$fdff
: echo of $c000-$dfff
, accesses the same memory
$fe00-$fe9f
: sprite attribute table, used to hold sprites
$ff00-$ff7f
: IO registers
$ff80-$fffe
: also accessible ram that is supposedly fast to access?
$ffff
: Interrupt Enable Register flag, used to allow or disable interrupts to the CPU.
memory game-boy
add a comment |
I'm writing a Game Boy emulator, but I don't completely understand how its memory mapping works. Here is what I (think) I know (and don't know).
The CPU can address up to 0x10000
memory locations with the 16-bit address bus. The memory is mapped as follows:
$0000-$3fff
: a 16KB ROM bank. Initially, reading from this accesses the bootloader, but afterwards ot accesses a fixed bank in the cartridge.
$4000-$7fff
: accesses ROM from cartridge, but can access more memory by switching banks (what does this mean?)
$8000-$9fff
: VRAM, the PPU reads from this to draw the screen
$a000-$bfff
: external ram found in the cartridge, this is the switchable bank?
$c000-$cfff
: actual work RAM stored in the Gameboy (not in the cartridge)
$d000-$dfff
: also the switchable bank that is accessed when reading from $4000-$7fff?
$e000-$fdff
: echo of $c000-$dfff
, accesses the same memory
$fe00-$fe9f
: sprite attribute table, used to hold sprites
$ff00-$ff7f
: IO registers
$ff80-$fffe
: also accessible ram that is supposedly fast to access?
$ffff
: Interrupt Enable Register flag, used to allow or disable interrupts to the CPU.
memory game-boy
1
Bank switching means that there's more ROM in the cartridge than will fit into the space available for it, so only part of the ROM shows up in that space. You can switch which a part of the ROM, or bank, appears there in order to access the entire ROM.
– Ross Ridge
8 hours ago
So what are the memory locations d000-dfff and a000-bfff?
– David Tran
8 hours ago
I assume the later is what you said it is, RAM located on the cartridge. Presumably this is battery-backed RAM so that it can be used to save game state. I don''t know what the former is but it can't be the same thing as what's located at $4000-$7FFF because it's much smaller.
– Ross Ridge
7 hours ago
add a comment |
I'm writing a Game Boy emulator, but I don't completely understand how its memory mapping works. Here is what I (think) I know (and don't know).
The CPU can address up to 0x10000
memory locations with the 16-bit address bus. The memory is mapped as follows:
$0000-$3fff
: a 16KB ROM bank. Initially, reading from this accesses the bootloader, but afterwards ot accesses a fixed bank in the cartridge.
$4000-$7fff
: accesses ROM from cartridge, but can access more memory by switching banks (what does this mean?)
$8000-$9fff
: VRAM, the PPU reads from this to draw the screen
$a000-$bfff
: external ram found in the cartridge, this is the switchable bank?
$c000-$cfff
: actual work RAM stored in the Gameboy (not in the cartridge)
$d000-$dfff
: also the switchable bank that is accessed when reading from $4000-$7fff?
$e000-$fdff
: echo of $c000-$dfff
, accesses the same memory
$fe00-$fe9f
: sprite attribute table, used to hold sprites
$ff00-$ff7f
: IO registers
$ff80-$fffe
: also accessible ram that is supposedly fast to access?
$ffff
: Interrupt Enable Register flag, used to allow or disable interrupts to the CPU.
memory game-boy
I'm writing a Game Boy emulator, but I don't completely understand how its memory mapping works. Here is what I (think) I know (and don't know).
The CPU can address up to 0x10000
memory locations with the 16-bit address bus. The memory is mapped as follows:
$0000-$3fff
: a 16KB ROM bank. Initially, reading from this accesses the bootloader, but afterwards ot accesses a fixed bank in the cartridge.
$4000-$7fff
: accesses ROM from cartridge, but can access more memory by switching banks (what does this mean?)
$8000-$9fff
: VRAM, the PPU reads from this to draw the screen
$a000-$bfff
: external ram found in the cartridge, this is the switchable bank?
$c000-$cfff
: actual work RAM stored in the Gameboy (not in the cartridge)
$d000-$dfff
: also the switchable bank that is accessed when reading from $4000-$7fff?
$e000-$fdff
: echo of $c000-$dfff
, accesses the same memory
$fe00-$fe9f
: sprite attribute table, used to hold sprites
$ff00-$ff7f
: IO registers
$ff80-$fffe
: also accessible ram that is supposedly fast to access?
$ffff
: Interrupt Enable Register flag, used to allow or disable interrupts to the CPU.
memory game-boy
memory game-boy
asked 8 hours ago
David TranDavid Tran
3953 silver badges9 bronze badges
3953 silver badges9 bronze badges
1
Bank switching means that there's more ROM in the cartridge than will fit into the space available for it, so only part of the ROM shows up in that space. You can switch which a part of the ROM, or bank, appears there in order to access the entire ROM.
– Ross Ridge
8 hours ago
So what are the memory locations d000-dfff and a000-bfff?
– David Tran
8 hours ago
I assume the later is what you said it is, RAM located on the cartridge. Presumably this is battery-backed RAM so that it can be used to save game state. I don''t know what the former is but it can't be the same thing as what's located at $4000-$7FFF because it's much smaller.
– Ross Ridge
7 hours ago
add a comment |
1
Bank switching means that there's more ROM in the cartridge than will fit into the space available for it, so only part of the ROM shows up in that space. You can switch which a part of the ROM, or bank, appears there in order to access the entire ROM.
– Ross Ridge
8 hours ago
So what are the memory locations d000-dfff and a000-bfff?
– David Tran
8 hours ago
I assume the later is what you said it is, RAM located on the cartridge. Presumably this is battery-backed RAM so that it can be used to save game state. I don''t know what the former is but it can't be the same thing as what's located at $4000-$7FFF because it's much smaller.
– Ross Ridge
7 hours ago
1
1
Bank switching means that there's more ROM in the cartridge than will fit into the space available for it, so only part of the ROM shows up in that space. You can switch which a part of the ROM, or bank, appears there in order to access the entire ROM.
– Ross Ridge
8 hours ago
Bank switching means that there's more ROM in the cartridge than will fit into the space available for it, so only part of the ROM shows up in that space. You can switch which a part of the ROM, or bank, appears there in order to access the entire ROM.
– Ross Ridge
8 hours ago
So what are the memory locations d000-dfff and a000-bfff?
– David Tran
8 hours ago
So what are the memory locations d000-dfff and a000-bfff?
– David Tran
8 hours ago
I assume the later is what you said it is, RAM located on the cartridge. Presumably this is battery-backed RAM so that it can be used to save game state. I don''t know what the former is but it can't be the same thing as what's located at $4000-$7FFF because it's much smaller.
– Ross Ridge
7 hours ago
I assume the later is what you said it is, RAM located on the cartridge. Presumably this is battery-backed RAM so that it can be used to save game state. I don''t know what the former is but it can't be the same thing as what's located at $4000-$7FFF because it's much smaller.
– Ross Ridge
7 hours ago
add a comment |
2 Answers
2
active
oldest
votes
ROM and RAM bank switching is controlled by a memory bank controller present on the cartridge.
By writing values to areas of read-only memory, a game or program is able to specify which ROM banks to access when read operations are performed.
The simplest cartridges simply contained ROM and had only had 32 KBytes of space.
It is mapped directly to $0000-$7FFF
.
There was no MBC on these types of cartridges because the entire game would be able to fit on the cartridge.
This types of cartridge could also contain up to 8KB of RAM, mapped to $A000-$BFFF
, though it would require an MBC-like circuit to work.
An example of a game that didn't use a MBC was Tetris, whose ROM is only 19KB.
Larger games required larger amounts of storage, which as you pointed out, the Gameboy was not natively able to address.
Types of Memory Bank Controllers
There were 3 (and a half) types of MBCs that cartridges used.
They each possessed different amounts of ROM and RAM.
Each ROM bank was 16KB in size
- MBC1: max 2MByte ROM (125 banks) and/or up to 32KByte RAM
- MBC2: max 256KByte ROM (16 banks) and 512x4 bits RAM
- MBC3: max 2MByte ROM (128 banks) and/or 32KByte RAM (4 banks) and Timer
- HuC1: Similar to MBC1 with an Infrared Controller
One thing to note is that MBC1 and MBC3 both support 2MB, but have a different number of banks.
I will explain that once I explain the memory map and bank switching.
Before describing how the bank switching takes place, I'm going to explain how the MBC1 itself operates.
MBC1 Memory Map
This was the first MBC chip for the Gameboy.
It behaves much the same as the other, with a few exceptions.
A cartridge with an MBC1 uses to following memory ranges:
$0000-$3FFF
: ROM Bank $00
(Read Only)
This always contains the first 16KB of the cartridge, the first memory bank.
It is unable to be switched or modified.
$4000-$7FFF
: Additional ROM Banks (Read Only)
This area of memory will contain whatever memory bank is currently selected.
$A000-$BFFF
: Ram Bank, if present (Read/Write)
This is where RAM banks will be placed in memory.
They are able to be both written to and read from, allowing the game to store data.
If the cartridge contains a battery, like in Pokemon cartridges, the data written is able to be preserved across shutdowns.
This type of MBC had 3 different RAM options:
- 2KB: $A000-A7FF
- 8KB: $A000-BFFF
- 32KB: $A000-BFFF
(four switchable 8KB banks)
$0000-$1FFF
: RAM Enable (Write Only)
Before a game is able to use the RAM, it must be specifically enabled.
This is done by writing a value with the lower 4 bits being $0A
somewhere in this address space.
To disable RAM, any number except $0A
can be written.
It does not matter where it is written, just as long as it within the address range.
You will notice that this address range is part of the first ROM bank, which is read only.
Because it is ROM, there is obviously no way to actually write data to those memory locations.
Instead, the write call is "intercepted" and interpreted differently by the MBC.
This method of writing to ROM is also used for the remaining memory areas I'll explain now.
$2000-$3FFF
: ROM Bank Number (Write Only)
Writing a value to this address range will select the lower 5 bits of the bank number.
There are a few special cases though.
If the value $00
is written, it will converted to bank $01
.
This is not an issue because bank $00
is always present at $0000-$3FFF
.
The issue lies in writing the values $20
, $40
, and $60
.
When these values are written, instead of addressing the correct ROM banks they will address banks $21``$41
and $61
respectively.
I couldn't find an explanation of why this takes place, but I assume it has something to do with how the lower 5 bits are used when choosing the bank.
Each of these numbers have all zeros as the lower 5 bits (0x0XX
00000
).
This issue is not present in MBC2 and MBC3.
$6000-$7FFF
: ROM/RAM Mode Select (Write Only)
Writing either $00
or $01
to this area will select which mode the MBC is in.
On an MBC1, there are two modes: 16Mb ROM/8KB RAM and 4Mb ROM/32KB RAM.
The game is able to switch between the modes on the fly, allowing a game to access extended ROM banks during normal operation and switch to RAM mode temporarily when data needs to be read.
Valid values are $00
for ROM mode and $01
for RAM mode.
$4000-$5FFF
: RAM Bank Number or Upper Bits of ROM Bank Number (Write Only)
Writing to this area of memory will effect the ROM or RAM modes, depending on what is written in $6000-$7FFF
.
Only the first two bits of the value matter.
If in ROM mode (no RAM bank switching), it will specify the upper two bits of the ROM bank number.
In this mode, only RAM bank $00
may be used.
If in RAM mode, it will specify which RAM bank to load into $A000-$BFFF
.
In this mode, only ROM banks $00-$1f
may be used.
The MBC1 is only able to switch between 125 different ROM banks, instead of the expected 128.
The ROM banks are addressed using a 6 bit number created from writing to $2000-$3FFF
and $4000-$5FFF
.
The reason is because of the number conversion when writing $20
, $40
, and $60
to $2000-$3FFF
.
This results in it being able to address 128-3 or 125 banks for a actual total of 1.95MB, not 2MB.
This issue is not present in MBC2 and MBC3.
MBC2 has a maximum of 16 banks, so the issue is never encountered.
The MBC3 chip correctly addresses $20
, $40
, and $60
and does not perform the conversion.
Examples
That was a lot of numbers and memory ranges, so now I'll give a few examples of bank switching and the process a game would take.
When the Gameboy is first turned on, the cartridge header is read and gives information on the ROM and RAM sizes present on the cartridge.
Byte $0147
specifies the type of MBC and what hardware is present on the cart.
Byte $0148
specifies the size of the ROM, from which the number of banks can be derived.
These examples assume the cart has a MBC1 type chip.
Switching to a ROM Bank < $20
Switching to banks $01-$1F
is very simple.
We only need to write our intended bank to $2000-$3FFF
.
Here we are switching to bank $05
:
ld $2000, $05
; Now able to read data from bank $05
Switching to a ROM Bank > $1F
To switch to a ROM bank greater than $1F
, there is some extra legwork to be done.
First, we need to switch to the ROM banking mode.
Then we write the lower 5 bits to $2000-$3FFF
and the upper 2 bits to $4000-$5FFF
.
For this example, I will be loading bank $46
.
This value is 0x0100 0x0110
in binary.
ld $6000, $00 ; Set ROM mode
ld $2000, $06 ; Set lower 5 bits, could also use $46
ld $4000, $02 ; Set upper 2 bits
; Now able to read data from bank $46
Reading a Value from RAM Bank $00
When reading a value from RAM Bank $00
, there is no need to change the banking mode.
This example assumes that there is RAM present on the cart.
Before reading and writing the RAM, we need to enable the RAM.
It is prudent to disable RAM after it is accessed in case the Gameboy is suddenly turned off.
If it it isn't turned off, an unexpected shutdown could leave the RAM in an inconsistent state.
Once we are done moving data in and out of RAM, we should disable once again.
ld $0000, $0A ; Enable RAM
; Perform operations on RAM data
ld $0000, $00 ; Disable RAM
Reading a Value from RAM Bank $02
To read a value from a RAM bank other than $00
, we need to switch to RAM mode.
Once this is done, we can select the RAM bank, enable RAM, and begin moving data.
Note we are able to select the RAM bank before enabling RAM.
ld $6000, $01 ; Switch to RAM mode
ld $4000, $02 ; Select our RAM bank
ld $0000, $0A ; Enable RAM
; Perform operations on RAM data
ld $0000, $00 ; Disable RAM
Reference / Further Reading
Pan Docs
GB Dev Wiki: Memory Bank Controllers
Gameboy CPU Manual
New contributor
add a comment |
Address Decoding
Any computer system (including video game consoles) with more than one
memory device needs hardware (usually) external to the CPU to
determine which device to access for any particular address. This
process is called address decoding. In the simplest case this
could be a single device that looks at the address and makes the
decision this way:
- Address <
$c000
: access the RAM chip by setting the chip select
signal for the RAM chip "on" and the chip select signal for the ROM
chip "off." - Address >=
$e000
: access the ROM chip by setting the chip select
signal for the RAM chip "off" and the chip select signal for the ROM
chip "on."
This can also cause the mirroring that you sometimes see. Say that the
RAM chip is only 4 KiB, and thus uses only 12-bit addresses, with the
CPU's address bus lines A0-A11 connected to the RAM chip's address
pins. In the case above accessing $0003
will access address 3 on the
RAM chip, but also so will accessing $1003
or $2003
, because in
all cases:
- The address is less than
$c000
, so the address decoding logic
enables the RAM chip and disables all other devices. - The lower 12 bits of the address, are
$003
(sometimes expressed
as$x003
, where thex
is the four "don't care" bits the RAM
chip doesn't see), accessing the third location on the RAM chip. - The higher address bits A12-A15 are
$0
,$1
or$2
(sometimes
expressed as$0xxx
,$1xxx
or$2xxx
), but these address bits
are not connected to the RAM chip and are thus ignored by it.
Bank Switching
Bank switching extends this by changing which device is accessed
in a programmable way. Say you have a latch (basically, a one-bit
memory location) accessed at $c000
. (This would usually be on a
separate device, also enabled/accessed via appropriate address
decoding.) You might configure the hardware so that when this latch
contains a 0
any access to $e000
-$ffff
will access ROM chip #0,
but when a 1
is in this latch any access to $e000
-$ffff
will
instead access ROM chip #1.
Using this technique you can access more than 0x10000
memory
locations even though you have only 0x10000
addresses available by
having multiple devices at the same memory address and choosing them
based on further information such as the bit stored in the latch
example above. The system would start out at boot with a 0
in that
latch, but at any time the program could write a 1
to $c000
,
access the alternate memory, and when done, write a 0
to $c000
so
that further access would read the first memory again. (The program
would usually not be running from those $e000
-$ffff
memory
locations during this process. But with careful design of what's in
each memory bank, it could also be stored in both ROMs and switch
itself as it's running.)
Read vs. Write Decoding
There's one more bit of complexity that can be added to address
decoding: different decoding for reads and writes. In the example
above I had $c000
dedicated to the latch switching the ROM banks at
$e000
-$ffff
. However, since ROM is read-only and thus never
written, I can make the ROM-addresses dual-purpose by making writes
access a different device from reads. So I could, for example, make my
ROM two banks of 16 KiB, both accessed by reading $c000
-$ffff
, and
still use $c000
to switch as well. That address would thus be
accessing three separate devices:
- On write to
$c000
, with the current value of the latch0
or1
,
the data are always written to the latch. - On read from
$c000
with the current value of the latch =0
the
data are read from ROM chip #0. - On read from
$c000
with the current value of the latch =1
the
data are read from ROM chip #1.
Additional Hardware
Though every non-trivial video game system will have some address
decoding hardware built-in, it's common to add extra address decoding
hardware on the cartridge if the game is bigger than will fit into the
cartridge's address space. If the built-in address decoding always
accesses the cartridge for addresses $4000
-$7fff
, that could be
just a single 16 KiB ROM chip on the cartridge, or the cartridge could
have additional address decoding to select one of multiple ROM chips
based on other information, such as a latch also added to the
cartridge.
Cartridges may also have extra non-ROM hardware, such as RAM,
battery-backed RAM, timers, clocks, other sensors, and so on. The
address decoding on the cartridge also needs to manage how all these
devices are accessed, usually by assigning them specific memory
locations as well.
Game Boy Cartridge Memory Bank Controllers
On the Game Boy the additional address decoding logic on a cartridge
is called a Memory Bank Controller (MBC). There are several
different standard versions of this available, and you can find out
which one is used and the configuration of the cartridge by checking
certain memory locations in the cartridge header:
0x147
: Cartridge type.
$00
means it's a ROM-only cartridge, having no extra address
decoding. Addresses$0000
-$7ffff
each access one ROM location.
$01
is an MBC1 controller, allowing bank switching for a maximum
of 2 MiB of ROM, as described below.
$02
is MBC1+RAM, adding access to RAM on the cartridge (maximum
32 KiB) as described below.
$03
is MBC1+RAM+battery, with battery-backed RAM so that it's
preserved when the cartridge is removed. You need to remember to
disable the RAM when you're not using it so that it's not
corrupted when the cartridge is removed.
$04
is MBC2, which is similar to MBC1 but allows access to more
ROM and RAM. I don't describe this here; see the GB Dev Wiki for
details.- Higher values are yet more memory bank controller systems and
arrangements; again, see the GB Dev Wiki for details.
0x148
: ROM size.
$00
means one 32 KiB bank of ROM; this is the only valid value
for a cartridge type of$00
.
$01
means 64 KiB of ROM. The first 16 KiB is bank 0 and is
always accessed at$0000
-$3fff
. The additional three 16 KiB
banks are accessed at$4000
-$7fff
via bank switching. To
select the current bank using this range you write the ROM bank
number$01
,$02
or$03
to any address in the$2000
-$3fff
range. (This is ROM address space when read, but control latches
when written.)
0x149
: RAM size.
$00
means no RAM.
$01
and$02
are 2 KiB and 8 KiB of RAM respectively. The RAM
is accessed at addresses$a000
-$bfff
, after enabling it by
writing$0a
any address in the range$0000
-$1fff
. (This is
ROM address space when read, but control latches when written.)
$03
means 32 KiB of RAM in four 8 KiB banks. This still accessed
only in the 8 KiB range$a000
-$bfff
, but now you must bank
switch this to choose which of the four 8 KiB banks is read and
written when accessing that range.
$04
,$05
mean 128 KiB and 32 KiB respectively, bank switched
(in 16 and 8 banks, respectively) as for 32 KiB above.
The above information is far from complete; it's just intended to give
the general idea of how this works. The Memory Bank Controller
and Cartridge Header pages on the Game Boy Development
Wiki (where this information came from) contain much more
extensive information about the devices and address decoding for the
Game Boy and its various cartridges. If you have specific questions
about how to access certain things in the Game Boy, it would probably
be best to ask them as separate questions here.
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "648"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
noCode: true, onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fretrocomputing.stackexchange.com%2fquestions%2f11732%2fhow-does-the-gameboys-memory-bank-switching-work%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
ROM and RAM bank switching is controlled by a memory bank controller present on the cartridge.
By writing values to areas of read-only memory, a game or program is able to specify which ROM banks to access when read operations are performed.
The simplest cartridges simply contained ROM and had only had 32 KBytes of space.
It is mapped directly to $0000-$7FFF
.
There was no MBC on these types of cartridges because the entire game would be able to fit on the cartridge.
This types of cartridge could also contain up to 8KB of RAM, mapped to $A000-$BFFF
, though it would require an MBC-like circuit to work.
An example of a game that didn't use a MBC was Tetris, whose ROM is only 19KB.
Larger games required larger amounts of storage, which as you pointed out, the Gameboy was not natively able to address.
Types of Memory Bank Controllers
There were 3 (and a half) types of MBCs that cartridges used.
They each possessed different amounts of ROM and RAM.
Each ROM bank was 16KB in size
- MBC1: max 2MByte ROM (125 banks) and/or up to 32KByte RAM
- MBC2: max 256KByte ROM (16 banks) and 512x4 bits RAM
- MBC3: max 2MByte ROM (128 banks) and/or 32KByte RAM (4 banks) and Timer
- HuC1: Similar to MBC1 with an Infrared Controller
One thing to note is that MBC1 and MBC3 both support 2MB, but have a different number of banks.
I will explain that once I explain the memory map and bank switching.
Before describing how the bank switching takes place, I'm going to explain how the MBC1 itself operates.
MBC1 Memory Map
This was the first MBC chip for the Gameboy.
It behaves much the same as the other, with a few exceptions.
A cartridge with an MBC1 uses to following memory ranges:
$0000-$3FFF
: ROM Bank $00
(Read Only)
This always contains the first 16KB of the cartridge, the first memory bank.
It is unable to be switched or modified.
$4000-$7FFF
: Additional ROM Banks (Read Only)
This area of memory will contain whatever memory bank is currently selected.
$A000-$BFFF
: Ram Bank, if present (Read/Write)
This is where RAM banks will be placed in memory.
They are able to be both written to and read from, allowing the game to store data.
If the cartridge contains a battery, like in Pokemon cartridges, the data written is able to be preserved across shutdowns.
This type of MBC had 3 different RAM options:
- 2KB: $A000-A7FF
- 8KB: $A000-BFFF
- 32KB: $A000-BFFF
(four switchable 8KB banks)
$0000-$1FFF
: RAM Enable (Write Only)
Before a game is able to use the RAM, it must be specifically enabled.
This is done by writing a value with the lower 4 bits being $0A
somewhere in this address space.
To disable RAM, any number except $0A
can be written.
It does not matter where it is written, just as long as it within the address range.
You will notice that this address range is part of the first ROM bank, which is read only.
Because it is ROM, there is obviously no way to actually write data to those memory locations.
Instead, the write call is "intercepted" and interpreted differently by the MBC.
This method of writing to ROM is also used for the remaining memory areas I'll explain now.
$2000-$3FFF
: ROM Bank Number (Write Only)
Writing a value to this address range will select the lower 5 bits of the bank number.
There are a few special cases though.
If the value $00
is written, it will converted to bank $01
.
This is not an issue because bank $00
is always present at $0000-$3FFF
.
The issue lies in writing the values $20
, $40
, and $60
.
When these values are written, instead of addressing the correct ROM banks they will address banks $21``$41
and $61
respectively.
I couldn't find an explanation of why this takes place, but I assume it has something to do with how the lower 5 bits are used when choosing the bank.
Each of these numbers have all zeros as the lower 5 bits (0x0XX
00000
).
This issue is not present in MBC2 and MBC3.
$6000-$7FFF
: ROM/RAM Mode Select (Write Only)
Writing either $00
or $01
to this area will select which mode the MBC is in.
On an MBC1, there are two modes: 16Mb ROM/8KB RAM and 4Mb ROM/32KB RAM.
The game is able to switch between the modes on the fly, allowing a game to access extended ROM banks during normal operation and switch to RAM mode temporarily when data needs to be read.
Valid values are $00
for ROM mode and $01
for RAM mode.
$4000-$5FFF
: RAM Bank Number or Upper Bits of ROM Bank Number (Write Only)
Writing to this area of memory will effect the ROM or RAM modes, depending on what is written in $6000-$7FFF
.
Only the first two bits of the value matter.
If in ROM mode (no RAM bank switching), it will specify the upper two bits of the ROM bank number.
In this mode, only RAM bank $00
may be used.
If in RAM mode, it will specify which RAM bank to load into $A000-$BFFF
.
In this mode, only ROM banks $00-$1f
may be used.
The MBC1 is only able to switch between 125 different ROM banks, instead of the expected 128.
The ROM banks are addressed using a 6 bit number created from writing to $2000-$3FFF
and $4000-$5FFF
.
The reason is because of the number conversion when writing $20
, $40
, and $60
to $2000-$3FFF
.
This results in it being able to address 128-3 or 125 banks for a actual total of 1.95MB, not 2MB.
This issue is not present in MBC2 and MBC3.
MBC2 has a maximum of 16 banks, so the issue is never encountered.
The MBC3 chip correctly addresses $20
, $40
, and $60
and does not perform the conversion.
Examples
That was a lot of numbers and memory ranges, so now I'll give a few examples of bank switching and the process a game would take.
When the Gameboy is first turned on, the cartridge header is read and gives information on the ROM and RAM sizes present on the cartridge.
Byte $0147
specifies the type of MBC and what hardware is present on the cart.
Byte $0148
specifies the size of the ROM, from which the number of banks can be derived.
These examples assume the cart has a MBC1 type chip.
Switching to a ROM Bank < $20
Switching to banks $01-$1F
is very simple.
We only need to write our intended bank to $2000-$3FFF
.
Here we are switching to bank $05
:
ld $2000, $05
; Now able to read data from bank $05
Switching to a ROM Bank > $1F
To switch to a ROM bank greater than $1F
, there is some extra legwork to be done.
First, we need to switch to the ROM banking mode.
Then we write the lower 5 bits to $2000-$3FFF
and the upper 2 bits to $4000-$5FFF
.
For this example, I will be loading bank $46
.
This value is 0x0100 0x0110
in binary.
ld $6000, $00 ; Set ROM mode
ld $2000, $06 ; Set lower 5 bits, could also use $46
ld $4000, $02 ; Set upper 2 bits
; Now able to read data from bank $46
Reading a Value from RAM Bank $00
When reading a value from RAM Bank $00
, there is no need to change the banking mode.
This example assumes that there is RAM present on the cart.
Before reading and writing the RAM, we need to enable the RAM.
It is prudent to disable RAM after it is accessed in case the Gameboy is suddenly turned off.
If it it isn't turned off, an unexpected shutdown could leave the RAM in an inconsistent state.
Once we are done moving data in and out of RAM, we should disable once again.
ld $0000, $0A ; Enable RAM
; Perform operations on RAM data
ld $0000, $00 ; Disable RAM
Reading a Value from RAM Bank $02
To read a value from a RAM bank other than $00
, we need to switch to RAM mode.
Once this is done, we can select the RAM bank, enable RAM, and begin moving data.
Note we are able to select the RAM bank before enabling RAM.
ld $6000, $01 ; Switch to RAM mode
ld $4000, $02 ; Select our RAM bank
ld $0000, $0A ; Enable RAM
; Perform operations on RAM data
ld $0000, $00 ; Disable RAM
Reference / Further Reading
Pan Docs
GB Dev Wiki: Memory Bank Controllers
Gameboy CPU Manual
New contributor
add a comment |
ROM and RAM bank switching is controlled by a memory bank controller present on the cartridge.
By writing values to areas of read-only memory, a game or program is able to specify which ROM banks to access when read operations are performed.
The simplest cartridges simply contained ROM and had only had 32 KBytes of space.
It is mapped directly to $0000-$7FFF
.
There was no MBC on these types of cartridges because the entire game would be able to fit on the cartridge.
This types of cartridge could also contain up to 8KB of RAM, mapped to $A000-$BFFF
, though it would require an MBC-like circuit to work.
An example of a game that didn't use a MBC was Tetris, whose ROM is only 19KB.
Larger games required larger amounts of storage, which as you pointed out, the Gameboy was not natively able to address.
Types of Memory Bank Controllers
There were 3 (and a half) types of MBCs that cartridges used.
They each possessed different amounts of ROM and RAM.
Each ROM bank was 16KB in size
- MBC1: max 2MByte ROM (125 banks) and/or up to 32KByte RAM
- MBC2: max 256KByte ROM (16 banks) and 512x4 bits RAM
- MBC3: max 2MByte ROM (128 banks) and/or 32KByte RAM (4 banks) and Timer
- HuC1: Similar to MBC1 with an Infrared Controller
One thing to note is that MBC1 and MBC3 both support 2MB, but have a different number of banks.
I will explain that once I explain the memory map and bank switching.
Before describing how the bank switching takes place, I'm going to explain how the MBC1 itself operates.
MBC1 Memory Map
This was the first MBC chip for the Gameboy.
It behaves much the same as the other, with a few exceptions.
A cartridge with an MBC1 uses to following memory ranges:
$0000-$3FFF
: ROM Bank $00
(Read Only)
This always contains the first 16KB of the cartridge, the first memory bank.
It is unable to be switched or modified.
$4000-$7FFF
: Additional ROM Banks (Read Only)
This area of memory will contain whatever memory bank is currently selected.
$A000-$BFFF
: Ram Bank, if present (Read/Write)
This is where RAM banks will be placed in memory.
They are able to be both written to and read from, allowing the game to store data.
If the cartridge contains a battery, like in Pokemon cartridges, the data written is able to be preserved across shutdowns.
This type of MBC had 3 different RAM options:
- 2KB: $A000-A7FF
- 8KB: $A000-BFFF
- 32KB: $A000-BFFF
(four switchable 8KB banks)
$0000-$1FFF
: RAM Enable (Write Only)
Before a game is able to use the RAM, it must be specifically enabled.
This is done by writing a value with the lower 4 bits being $0A
somewhere in this address space.
To disable RAM, any number except $0A
can be written.
It does not matter where it is written, just as long as it within the address range.
You will notice that this address range is part of the first ROM bank, which is read only.
Because it is ROM, there is obviously no way to actually write data to those memory locations.
Instead, the write call is "intercepted" and interpreted differently by the MBC.
This method of writing to ROM is also used for the remaining memory areas I'll explain now.
$2000-$3FFF
: ROM Bank Number (Write Only)
Writing a value to this address range will select the lower 5 bits of the bank number.
There are a few special cases though.
If the value $00
is written, it will converted to bank $01
.
This is not an issue because bank $00
is always present at $0000-$3FFF
.
The issue lies in writing the values $20
, $40
, and $60
.
When these values are written, instead of addressing the correct ROM banks they will address banks $21``$41
and $61
respectively.
I couldn't find an explanation of why this takes place, but I assume it has something to do with how the lower 5 bits are used when choosing the bank.
Each of these numbers have all zeros as the lower 5 bits (0x0XX
00000
).
This issue is not present in MBC2 and MBC3.
$6000-$7FFF
: ROM/RAM Mode Select (Write Only)
Writing either $00
or $01
to this area will select which mode the MBC is in.
On an MBC1, there are two modes: 16Mb ROM/8KB RAM and 4Mb ROM/32KB RAM.
The game is able to switch between the modes on the fly, allowing a game to access extended ROM banks during normal operation and switch to RAM mode temporarily when data needs to be read.
Valid values are $00
for ROM mode and $01
for RAM mode.
$4000-$5FFF
: RAM Bank Number or Upper Bits of ROM Bank Number (Write Only)
Writing to this area of memory will effect the ROM or RAM modes, depending on what is written in $6000-$7FFF
.
Only the first two bits of the value matter.
If in ROM mode (no RAM bank switching), it will specify the upper two bits of the ROM bank number.
In this mode, only RAM bank $00
may be used.
If in RAM mode, it will specify which RAM bank to load into $A000-$BFFF
.
In this mode, only ROM banks $00-$1f
may be used.
The MBC1 is only able to switch between 125 different ROM banks, instead of the expected 128.
The ROM banks are addressed using a 6 bit number created from writing to $2000-$3FFF
and $4000-$5FFF
.
The reason is because of the number conversion when writing $20
, $40
, and $60
to $2000-$3FFF
.
This results in it being able to address 128-3 or 125 banks for a actual total of 1.95MB, not 2MB.
This issue is not present in MBC2 and MBC3.
MBC2 has a maximum of 16 banks, so the issue is never encountered.
The MBC3 chip correctly addresses $20
, $40
, and $60
and does not perform the conversion.
Examples
That was a lot of numbers and memory ranges, so now I'll give a few examples of bank switching and the process a game would take.
When the Gameboy is first turned on, the cartridge header is read and gives information on the ROM and RAM sizes present on the cartridge.
Byte $0147
specifies the type of MBC and what hardware is present on the cart.
Byte $0148
specifies the size of the ROM, from which the number of banks can be derived.
These examples assume the cart has a MBC1 type chip.
Switching to a ROM Bank < $20
Switching to banks $01-$1F
is very simple.
We only need to write our intended bank to $2000-$3FFF
.
Here we are switching to bank $05
:
ld $2000, $05
; Now able to read data from bank $05
Switching to a ROM Bank > $1F
To switch to a ROM bank greater than $1F
, there is some extra legwork to be done.
First, we need to switch to the ROM banking mode.
Then we write the lower 5 bits to $2000-$3FFF
and the upper 2 bits to $4000-$5FFF
.
For this example, I will be loading bank $46
.
This value is 0x0100 0x0110
in binary.
ld $6000, $00 ; Set ROM mode
ld $2000, $06 ; Set lower 5 bits, could also use $46
ld $4000, $02 ; Set upper 2 bits
; Now able to read data from bank $46
Reading a Value from RAM Bank $00
When reading a value from RAM Bank $00
, there is no need to change the banking mode.
This example assumes that there is RAM present on the cart.
Before reading and writing the RAM, we need to enable the RAM.
It is prudent to disable RAM after it is accessed in case the Gameboy is suddenly turned off.
If it it isn't turned off, an unexpected shutdown could leave the RAM in an inconsistent state.
Once we are done moving data in and out of RAM, we should disable once again.
ld $0000, $0A ; Enable RAM
; Perform operations on RAM data
ld $0000, $00 ; Disable RAM
Reading a Value from RAM Bank $02
To read a value from a RAM bank other than $00
, we need to switch to RAM mode.
Once this is done, we can select the RAM bank, enable RAM, and begin moving data.
Note we are able to select the RAM bank before enabling RAM.
ld $6000, $01 ; Switch to RAM mode
ld $4000, $02 ; Select our RAM bank
ld $0000, $0A ; Enable RAM
; Perform operations on RAM data
ld $0000, $00 ; Disable RAM
Reference / Further Reading
Pan Docs
GB Dev Wiki: Memory Bank Controllers
Gameboy CPU Manual
New contributor
add a comment |
ROM and RAM bank switching is controlled by a memory bank controller present on the cartridge.
By writing values to areas of read-only memory, a game or program is able to specify which ROM banks to access when read operations are performed.
The simplest cartridges simply contained ROM and had only had 32 KBytes of space.
It is mapped directly to $0000-$7FFF
.
There was no MBC on these types of cartridges because the entire game would be able to fit on the cartridge.
This types of cartridge could also contain up to 8KB of RAM, mapped to $A000-$BFFF
, though it would require an MBC-like circuit to work.
An example of a game that didn't use a MBC was Tetris, whose ROM is only 19KB.
Larger games required larger amounts of storage, which as you pointed out, the Gameboy was not natively able to address.
Types of Memory Bank Controllers
There were 3 (and a half) types of MBCs that cartridges used.
They each possessed different amounts of ROM and RAM.
Each ROM bank was 16KB in size
- MBC1: max 2MByte ROM (125 banks) and/or up to 32KByte RAM
- MBC2: max 256KByte ROM (16 banks) and 512x4 bits RAM
- MBC3: max 2MByte ROM (128 banks) and/or 32KByte RAM (4 banks) and Timer
- HuC1: Similar to MBC1 with an Infrared Controller
One thing to note is that MBC1 and MBC3 both support 2MB, but have a different number of banks.
I will explain that once I explain the memory map and bank switching.
Before describing how the bank switching takes place, I'm going to explain how the MBC1 itself operates.
MBC1 Memory Map
This was the first MBC chip for the Gameboy.
It behaves much the same as the other, with a few exceptions.
A cartridge with an MBC1 uses to following memory ranges:
$0000-$3FFF
: ROM Bank $00
(Read Only)
This always contains the first 16KB of the cartridge, the first memory bank.
It is unable to be switched or modified.
$4000-$7FFF
: Additional ROM Banks (Read Only)
This area of memory will contain whatever memory bank is currently selected.
$A000-$BFFF
: Ram Bank, if present (Read/Write)
This is where RAM banks will be placed in memory.
They are able to be both written to and read from, allowing the game to store data.
If the cartridge contains a battery, like in Pokemon cartridges, the data written is able to be preserved across shutdowns.
This type of MBC had 3 different RAM options:
- 2KB: $A000-A7FF
- 8KB: $A000-BFFF
- 32KB: $A000-BFFF
(four switchable 8KB banks)
$0000-$1FFF
: RAM Enable (Write Only)
Before a game is able to use the RAM, it must be specifically enabled.
This is done by writing a value with the lower 4 bits being $0A
somewhere in this address space.
To disable RAM, any number except $0A
can be written.
It does not matter where it is written, just as long as it within the address range.
You will notice that this address range is part of the first ROM bank, which is read only.
Because it is ROM, there is obviously no way to actually write data to those memory locations.
Instead, the write call is "intercepted" and interpreted differently by the MBC.
This method of writing to ROM is also used for the remaining memory areas I'll explain now.
$2000-$3FFF
: ROM Bank Number (Write Only)
Writing a value to this address range will select the lower 5 bits of the bank number.
There are a few special cases though.
If the value $00
is written, it will converted to bank $01
.
This is not an issue because bank $00
is always present at $0000-$3FFF
.
The issue lies in writing the values $20
, $40
, and $60
.
When these values are written, instead of addressing the correct ROM banks they will address banks $21``$41
and $61
respectively.
I couldn't find an explanation of why this takes place, but I assume it has something to do with how the lower 5 bits are used when choosing the bank.
Each of these numbers have all zeros as the lower 5 bits (0x0XX
00000
).
This issue is not present in MBC2 and MBC3.
$6000-$7FFF
: ROM/RAM Mode Select (Write Only)
Writing either $00
or $01
to this area will select which mode the MBC is in.
On an MBC1, there are two modes: 16Mb ROM/8KB RAM and 4Mb ROM/32KB RAM.
The game is able to switch between the modes on the fly, allowing a game to access extended ROM banks during normal operation and switch to RAM mode temporarily when data needs to be read.
Valid values are $00
for ROM mode and $01
for RAM mode.
$4000-$5FFF
: RAM Bank Number or Upper Bits of ROM Bank Number (Write Only)
Writing to this area of memory will effect the ROM or RAM modes, depending on what is written in $6000-$7FFF
.
Only the first two bits of the value matter.
If in ROM mode (no RAM bank switching), it will specify the upper two bits of the ROM bank number.
In this mode, only RAM bank $00
may be used.
If in RAM mode, it will specify which RAM bank to load into $A000-$BFFF
.
In this mode, only ROM banks $00-$1f
may be used.
The MBC1 is only able to switch between 125 different ROM banks, instead of the expected 128.
The ROM banks are addressed using a 6 bit number created from writing to $2000-$3FFF
and $4000-$5FFF
.
The reason is because of the number conversion when writing $20
, $40
, and $60
to $2000-$3FFF
.
This results in it being able to address 128-3 or 125 banks for a actual total of 1.95MB, not 2MB.
This issue is not present in MBC2 and MBC3.
MBC2 has a maximum of 16 banks, so the issue is never encountered.
The MBC3 chip correctly addresses $20
, $40
, and $60
and does not perform the conversion.
Examples
That was a lot of numbers and memory ranges, so now I'll give a few examples of bank switching and the process a game would take.
When the Gameboy is first turned on, the cartridge header is read and gives information on the ROM and RAM sizes present on the cartridge.
Byte $0147
specifies the type of MBC and what hardware is present on the cart.
Byte $0148
specifies the size of the ROM, from which the number of banks can be derived.
These examples assume the cart has a MBC1 type chip.
Switching to a ROM Bank < $20
Switching to banks $01-$1F
is very simple.
We only need to write our intended bank to $2000-$3FFF
.
Here we are switching to bank $05
:
ld $2000, $05
; Now able to read data from bank $05
Switching to a ROM Bank > $1F
To switch to a ROM bank greater than $1F
, there is some extra legwork to be done.
First, we need to switch to the ROM banking mode.
Then we write the lower 5 bits to $2000-$3FFF
and the upper 2 bits to $4000-$5FFF
.
For this example, I will be loading bank $46
.
This value is 0x0100 0x0110
in binary.
ld $6000, $00 ; Set ROM mode
ld $2000, $06 ; Set lower 5 bits, could also use $46
ld $4000, $02 ; Set upper 2 bits
; Now able to read data from bank $46
Reading a Value from RAM Bank $00
When reading a value from RAM Bank $00
, there is no need to change the banking mode.
This example assumes that there is RAM present on the cart.
Before reading and writing the RAM, we need to enable the RAM.
It is prudent to disable RAM after it is accessed in case the Gameboy is suddenly turned off.
If it it isn't turned off, an unexpected shutdown could leave the RAM in an inconsistent state.
Once we are done moving data in and out of RAM, we should disable once again.
ld $0000, $0A ; Enable RAM
; Perform operations on RAM data
ld $0000, $00 ; Disable RAM
Reading a Value from RAM Bank $02
To read a value from a RAM bank other than $00
, we need to switch to RAM mode.
Once this is done, we can select the RAM bank, enable RAM, and begin moving data.
Note we are able to select the RAM bank before enabling RAM.
ld $6000, $01 ; Switch to RAM mode
ld $4000, $02 ; Select our RAM bank
ld $0000, $0A ; Enable RAM
; Perform operations on RAM data
ld $0000, $00 ; Disable RAM
Reference / Further Reading
Pan Docs
GB Dev Wiki: Memory Bank Controllers
Gameboy CPU Manual
New contributor
ROM and RAM bank switching is controlled by a memory bank controller present on the cartridge.
By writing values to areas of read-only memory, a game or program is able to specify which ROM banks to access when read operations are performed.
The simplest cartridges simply contained ROM and had only had 32 KBytes of space.
It is mapped directly to $0000-$7FFF
.
There was no MBC on these types of cartridges because the entire game would be able to fit on the cartridge.
This types of cartridge could also contain up to 8KB of RAM, mapped to $A000-$BFFF
, though it would require an MBC-like circuit to work.
An example of a game that didn't use a MBC was Tetris, whose ROM is only 19KB.
Larger games required larger amounts of storage, which as you pointed out, the Gameboy was not natively able to address.
Types of Memory Bank Controllers
There were 3 (and a half) types of MBCs that cartridges used.
They each possessed different amounts of ROM and RAM.
Each ROM bank was 16KB in size
- MBC1: max 2MByte ROM (125 banks) and/or up to 32KByte RAM
- MBC2: max 256KByte ROM (16 banks) and 512x4 bits RAM
- MBC3: max 2MByte ROM (128 banks) and/or 32KByte RAM (4 banks) and Timer
- HuC1: Similar to MBC1 with an Infrared Controller
One thing to note is that MBC1 and MBC3 both support 2MB, but have a different number of banks.
I will explain that once I explain the memory map and bank switching.
Before describing how the bank switching takes place, I'm going to explain how the MBC1 itself operates.
MBC1 Memory Map
This was the first MBC chip for the Gameboy.
It behaves much the same as the other, with a few exceptions.
A cartridge with an MBC1 uses to following memory ranges:
$0000-$3FFF
: ROM Bank $00
(Read Only)
This always contains the first 16KB of the cartridge, the first memory bank.
It is unable to be switched or modified.
$4000-$7FFF
: Additional ROM Banks (Read Only)
This area of memory will contain whatever memory bank is currently selected.
$A000-$BFFF
: Ram Bank, if present (Read/Write)
This is where RAM banks will be placed in memory.
They are able to be both written to and read from, allowing the game to store data.
If the cartridge contains a battery, like in Pokemon cartridges, the data written is able to be preserved across shutdowns.
This type of MBC had 3 different RAM options:
- 2KB: $A000-A7FF
- 8KB: $A000-BFFF
- 32KB: $A000-BFFF
(four switchable 8KB banks)
$0000-$1FFF
: RAM Enable (Write Only)
Before a game is able to use the RAM, it must be specifically enabled.
This is done by writing a value with the lower 4 bits being $0A
somewhere in this address space.
To disable RAM, any number except $0A
can be written.
It does not matter where it is written, just as long as it within the address range.
You will notice that this address range is part of the first ROM bank, which is read only.
Because it is ROM, there is obviously no way to actually write data to those memory locations.
Instead, the write call is "intercepted" and interpreted differently by the MBC.
This method of writing to ROM is also used for the remaining memory areas I'll explain now.
$2000-$3FFF
: ROM Bank Number (Write Only)
Writing a value to this address range will select the lower 5 bits of the bank number.
There are a few special cases though.
If the value $00
is written, it will converted to bank $01
.
This is not an issue because bank $00
is always present at $0000-$3FFF
.
The issue lies in writing the values $20
, $40
, and $60
.
When these values are written, instead of addressing the correct ROM banks they will address banks $21``$41
and $61
respectively.
I couldn't find an explanation of why this takes place, but I assume it has something to do with how the lower 5 bits are used when choosing the bank.
Each of these numbers have all zeros as the lower 5 bits (0x0XX
00000
).
This issue is not present in MBC2 and MBC3.
$6000-$7FFF
: ROM/RAM Mode Select (Write Only)
Writing either $00
or $01
to this area will select which mode the MBC is in.
On an MBC1, there are two modes: 16Mb ROM/8KB RAM and 4Mb ROM/32KB RAM.
The game is able to switch between the modes on the fly, allowing a game to access extended ROM banks during normal operation and switch to RAM mode temporarily when data needs to be read.
Valid values are $00
for ROM mode and $01
for RAM mode.
$4000-$5FFF
: RAM Bank Number or Upper Bits of ROM Bank Number (Write Only)
Writing to this area of memory will effect the ROM or RAM modes, depending on what is written in $6000-$7FFF
.
Only the first two bits of the value matter.
If in ROM mode (no RAM bank switching), it will specify the upper two bits of the ROM bank number.
In this mode, only RAM bank $00
may be used.
If in RAM mode, it will specify which RAM bank to load into $A000-$BFFF
.
In this mode, only ROM banks $00-$1f
may be used.
The MBC1 is only able to switch between 125 different ROM banks, instead of the expected 128.
The ROM banks are addressed using a 6 bit number created from writing to $2000-$3FFF
and $4000-$5FFF
.
The reason is because of the number conversion when writing $20
, $40
, and $60
to $2000-$3FFF
.
This results in it being able to address 128-3 or 125 banks for a actual total of 1.95MB, not 2MB.
This issue is not present in MBC2 and MBC3.
MBC2 has a maximum of 16 banks, so the issue is never encountered.
The MBC3 chip correctly addresses $20
, $40
, and $60
and does not perform the conversion.
Examples
That was a lot of numbers and memory ranges, so now I'll give a few examples of bank switching and the process a game would take.
When the Gameboy is first turned on, the cartridge header is read and gives information on the ROM and RAM sizes present on the cartridge.
Byte $0147
specifies the type of MBC and what hardware is present on the cart.
Byte $0148
specifies the size of the ROM, from which the number of banks can be derived.
These examples assume the cart has a MBC1 type chip.
Switching to a ROM Bank < $20
Switching to banks $01-$1F
is very simple.
We only need to write our intended bank to $2000-$3FFF
.
Here we are switching to bank $05
:
ld $2000, $05
; Now able to read data from bank $05
Switching to a ROM Bank > $1F
To switch to a ROM bank greater than $1F
, there is some extra legwork to be done.
First, we need to switch to the ROM banking mode.
Then we write the lower 5 bits to $2000-$3FFF
and the upper 2 bits to $4000-$5FFF
.
For this example, I will be loading bank $46
.
This value is 0x0100 0x0110
in binary.
ld $6000, $00 ; Set ROM mode
ld $2000, $06 ; Set lower 5 bits, could also use $46
ld $4000, $02 ; Set upper 2 bits
; Now able to read data from bank $46
Reading a Value from RAM Bank $00
When reading a value from RAM Bank $00
, there is no need to change the banking mode.
This example assumes that there is RAM present on the cart.
Before reading and writing the RAM, we need to enable the RAM.
It is prudent to disable RAM after it is accessed in case the Gameboy is suddenly turned off.
If it it isn't turned off, an unexpected shutdown could leave the RAM in an inconsistent state.
Once we are done moving data in and out of RAM, we should disable once again.
ld $0000, $0A ; Enable RAM
; Perform operations on RAM data
ld $0000, $00 ; Disable RAM
Reading a Value from RAM Bank $02
To read a value from a RAM bank other than $00
, we need to switch to RAM mode.
Once this is done, we can select the RAM bank, enable RAM, and begin moving data.
Note we are able to select the RAM bank before enabling RAM.
ld $6000, $01 ; Switch to RAM mode
ld $4000, $02 ; Select our RAM bank
ld $0000, $0A ; Enable RAM
; Perform operations on RAM data
ld $0000, $00 ; Disable RAM
Reference / Further Reading
Pan Docs
GB Dev Wiki: Memory Bank Controllers
Gameboy CPU Manual
New contributor
New contributor
answered 1 hour ago
b13rgb13rg
211 bronze badge
211 bronze badge
New contributor
New contributor
add a comment |
add a comment |
Address Decoding
Any computer system (including video game consoles) with more than one
memory device needs hardware (usually) external to the CPU to
determine which device to access for any particular address. This
process is called address decoding. In the simplest case this
could be a single device that looks at the address and makes the
decision this way:
- Address <
$c000
: access the RAM chip by setting the chip select
signal for the RAM chip "on" and the chip select signal for the ROM
chip "off." - Address >=
$e000
: access the ROM chip by setting the chip select
signal for the RAM chip "off" and the chip select signal for the ROM
chip "on."
This can also cause the mirroring that you sometimes see. Say that the
RAM chip is only 4 KiB, and thus uses only 12-bit addresses, with the
CPU's address bus lines A0-A11 connected to the RAM chip's address
pins. In the case above accessing $0003
will access address 3 on the
RAM chip, but also so will accessing $1003
or $2003
, because in
all cases:
- The address is less than
$c000
, so the address decoding logic
enables the RAM chip and disables all other devices. - The lower 12 bits of the address, are
$003
(sometimes expressed
as$x003
, where thex
is the four "don't care" bits the RAM
chip doesn't see), accessing the third location on the RAM chip. - The higher address bits A12-A15 are
$0
,$1
or$2
(sometimes
expressed as$0xxx
,$1xxx
or$2xxx
), but these address bits
are not connected to the RAM chip and are thus ignored by it.
Bank Switching
Bank switching extends this by changing which device is accessed
in a programmable way. Say you have a latch (basically, a one-bit
memory location) accessed at $c000
. (This would usually be on a
separate device, also enabled/accessed via appropriate address
decoding.) You might configure the hardware so that when this latch
contains a 0
any access to $e000
-$ffff
will access ROM chip #0,
but when a 1
is in this latch any access to $e000
-$ffff
will
instead access ROM chip #1.
Using this technique you can access more than 0x10000
memory
locations even though you have only 0x10000
addresses available by
having multiple devices at the same memory address and choosing them
based on further information such as the bit stored in the latch
example above. The system would start out at boot with a 0
in that
latch, but at any time the program could write a 1
to $c000
,
access the alternate memory, and when done, write a 0
to $c000
so
that further access would read the first memory again. (The program
would usually not be running from those $e000
-$ffff
memory
locations during this process. But with careful design of what's in
each memory bank, it could also be stored in both ROMs and switch
itself as it's running.)
Read vs. Write Decoding
There's one more bit of complexity that can be added to address
decoding: different decoding for reads and writes. In the example
above I had $c000
dedicated to the latch switching the ROM banks at
$e000
-$ffff
. However, since ROM is read-only and thus never
written, I can make the ROM-addresses dual-purpose by making writes
access a different device from reads. So I could, for example, make my
ROM two banks of 16 KiB, both accessed by reading $c000
-$ffff
, and
still use $c000
to switch as well. That address would thus be
accessing three separate devices:
- On write to
$c000
, with the current value of the latch0
or1
,
the data are always written to the latch. - On read from
$c000
with the current value of the latch =0
the
data are read from ROM chip #0. - On read from
$c000
with the current value of the latch =1
the
data are read from ROM chip #1.
Additional Hardware
Though every non-trivial video game system will have some address
decoding hardware built-in, it's common to add extra address decoding
hardware on the cartridge if the game is bigger than will fit into the
cartridge's address space. If the built-in address decoding always
accesses the cartridge for addresses $4000
-$7fff
, that could be
just a single 16 KiB ROM chip on the cartridge, or the cartridge could
have additional address decoding to select one of multiple ROM chips
based on other information, such as a latch also added to the
cartridge.
Cartridges may also have extra non-ROM hardware, such as RAM,
battery-backed RAM, timers, clocks, other sensors, and so on. The
address decoding on the cartridge also needs to manage how all these
devices are accessed, usually by assigning them specific memory
locations as well.
Game Boy Cartridge Memory Bank Controllers
On the Game Boy the additional address decoding logic on a cartridge
is called a Memory Bank Controller (MBC). There are several
different standard versions of this available, and you can find out
which one is used and the configuration of the cartridge by checking
certain memory locations in the cartridge header:
0x147
: Cartridge type.
$00
means it's a ROM-only cartridge, having no extra address
decoding. Addresses$0000
-$7ffff
each access one ROM location.
$01
is an MBC1 controller, allowing bank switching for a maximum
of 2 MiB of ROM, as described below.
$02
is MBC1+RAM, adding access to RAM on the cartridge (maximum
32 KiB) as described below.
$03
is MBC1+RAM+battery, with battery-backed RAM so that it's
preserved when the cartridge is removed. You need to remember to
disable the RAM when you're not using it so that it's not
corrupted when the cartridge is removed.
$04
is MBC2, which is similar to MBC1 but allows access to more
ROM and RAM. I don't describe this here; see the GB Dev Wiki for
details.- Higher values are yet more memory bank controller systems and
arrangements; again, see the GB Dev Wiki for details.
0x148
: ROM size.
$00
means one 32 KiB bank of ROM; this is the only valid value
for a cartridge type of$00
.
$01
means 64 KiB of ROM. The first 16 KiB is bank 0 and is
always accessed at$0000
-$3fff
. The additional three 16 KiB
banks are accessed at$4000
-$7fff
via bank switching. To
select the current bank using this range you write the ROM bank
number$01
,$02
or$03
to any address in the$2000
-$3fff
range. (This is ROM address space when read, but control latches
when written.)
0x149
: RAM size.
$00
means no RAM.
$01
and$02
are 2 KiB and 8 KiB of RAM respectively. The RAM
is accessed at addresses$a000
-$bfff
, after enabling it by
writing$0a
any address in the range$0000
-$1fff
. (This is
ROM address space when read, but control latches when written.)
$03
means 32 KiB of RAM in four 8 KiB banks. This still accessed
only in the 8 KiB range$a000
-$bfff
, but now you must bank
switch this to choose which of the four 8 KiB banks is read and
written when accessing that range.
$04
,$05
mean 128 KiB and 32 KiB respectively, bank switched
(in 16 and 8 banks, respectively) as for 32 KiB above.
The above information is far from complete; it's just intended to give
the general idea of how this works. The Memory Bank Controller
and Cartridge Header pages on the Game Boy Development
Wiki (where this information came from) contain much more
extensive information about the devices and address decoding for the
Game Boy and its various cartridges. If you have specific questions
about how to access certain things in the Game Boy, it would probably
be best to ask them as separate questions here.
add a comment |
Address Decoding
Any computer system (including video game consoles) with more than one
memory device needs hardware (usually) external to the CPU to
determine which device to access for any particular address. This
process is called address decoding. In the simplest case this
could be a single device that looks at the address and makes the
decision this way:
- Address <
$c000
: access the RAM chip by setting the chip select
signal for the RAM chip "on" and the chip select signal for the ROM
chip "off." - Address >=
$e000
: access the ROM chip by setting the chip select
signal for the RAM chip "off" and the chip select signal for the ROM
chip "on."
This can also cause the mirroring that you sometimes see. Say that the
RAM chip is only 4 KiB, and thus uses only 12-bit addresses, with the
CPU's address bus lines A0-A11 connected to the RAM chip's address
pins. In the case above accessing $0003
will access address 3 on the
RAM chip, but also so will accessing $1003
or $2003
, because in
all cases:
- The address is less than
$c000
, so the address decoding logic
enables the RAM chip and disables all other devices. - The lower 12 bits of the address, are
$003
(sometimes expressed
as$x003
, where thex
is the four "don't care" bits the RAM
chip doesn't see), accessing the third location on the RAM chip. - The higher address bits A12-A15 are
$0
,$1
or$2
(sometimes
expressed as$0xxx
,$1xxx
or$2xxx
), but these address bits
are not connected to the RAM chip and are thus ignored by it.
Bank Switching
Bank switching extends this by changing which device is accessed
in a programmable way. Say you have a latch (basically, a one-bit
memory location) accessed at $c000
. (This would usually be on a
separate device, also enabled/accessed via appropriate address
decoding.) You might configure the hardware so that when this latch
contains a 0
any access to $e000
-$ffff
will access ROM chip #0,
but when a 1
is in this latch any access to $e000
-$ffff
will
instead access ROM chip #1.
Using this technique you can access more than 0x10000
memory
locations even though you have only 0x10000
addresses available by
having multiple devices at the same memory address and choosing them
based on further information such as the bit stored in the latch
example above. The system would start out at boot with a 0
in that
latch, but at any time the program could write a 1
to $c000
,
access the alternate memory, and when done, write a 0
to $c000
so
that further access would read the first memory again. (The program
would usually not be running from those $e000
-$ffff
memory
locations during this process. But with careful design of what's in
each memory bank, it could also be stored in both ROMs and switch
itself as it's running.)
Read vs. Write Decoding
There's one more bit of complexity that can be added to address
decoding: different decoding for reads and writes. In the example
above I had $c000
dedicated to the latch switching the ROM banks at
$e000
-$ffff
. However, since ROM is read-only and thus never
written, I can make the ROM-addresses dual-purpose by making writes
access a different device from reads. So I could, for example, make my
ROM two banks of 16 KiB, both accessed by reading $c000
-$ffff
, and
still use $c000
to switch as well. That address would thus be
accessing three separate devices:
- On write to
$c000
, with the current value of the latch0
or1
,
the data are always written to the latch. - On read from
$c000
with the current value of the latch =0
the
data are read from ROM chip #0. - On read from
$c000
with the current value of the latch =1
the
data are read from ROM chip #1.
Additional Hardware
Though every non-trivial video game system will have some address
decoding hardware built-in, it's common to add extra address decoding
hardware on the cartridge if the game is bigger than will fit into the
cartridge's address space. If the built-in address decoding always
accesses the cartridge for addresses $4000
-$7fff
, that could be
just a single 16 KiB ROM chip on the cartridge, or the cartridge could
have additional address decoding to select one of multiple ROM chips
based on other information, such as a latch also added to the
cartridge.
Cartridges may also have extra non-ROM hardware, such as RAM,
battery-backed RAM, timers, clocks, other sensors, and so on. The
address decoding on the cartridge also needs to manage how all these
devices are accessed, usually by assigning them specific memory
locations as well.
Game Boy Cartridge Memory Bank Controllers
On the Game Boy the additional address decoding logic on a cartridge
is called a Memory Bank Controller (MBC). There are several
different standard versions of this available, and you can find out
which one is used and the configuration of the cartridge by checking
certain memory locations in the cartridge header:
0x147
: Cartridge type.
$00
means it's a ROM-only cartridge, having no extra address
decoding. Addresses$0000
-$7ffff
each access one ROM location.
$01
is an MBC1 controller, allowing bank switching for a maximum
of 2 MiB of ROM, as described below.
$02
is MBC1+RAM, adding access to RAM on the cartridge (maximum
32 KiB) as described below.
$03
is MBC1+RAM+battery, with battery-backed RAM so that it's
preserved when the cartridge is removed. You need to remember to
disable the RAM when you're not using it so that it's not
corrupted when the cartridge is removed.
$04
is MBC2, which is similar to MBC1 but allows access to more
ROM and RAM. I don't describe this here; see the GB Dev Wiki for
details.- Higher values are yet more memory bank controller systems and
arrangements; again, see the GB Dev Wiki for details.
0x148
: ROM size.
$00
means one 32 KiB bank of ROM; this is the only valid value
for a cartridge type of$00
.
$01
means 64 KiB of ROM. The first 16 KiB is bank 0 and is
always accessed at$0000
-$3fff
. The additional three 16 KiB
banks are accessed at$4000
-$7fff
via bank switching. To
select the current bank using this range you write the ROM bank
number$01
,$02
or$03
to any address in the$2000
-$3fff
range. (This is ROM address space when read, but control latches
when written.)
0x149
: RAM size.
$00
means no RAM.
$01
and$02
are 2 KiB and 8 KiB of RAM respectively. The RAM
is accessed at addresses$a000
-$bfff
, after enabling it by
writing$0a
any address in the range$0000
-$1fff
. (This is
ROM address space when read, but control latches when written.)
$03
means 32 KiB of RAM in four 8 KiB banks. This still accessed
only in the 8 KiB range$a000
-$bfff
, but now you must bank
switch this to choose which of the four 8 KiB banks is read and
written when accessing that range.
$04
,$05
mean 128 KiB and 32 KiB respectively, bank switched
(in 16 and 8 banks, respectively) as for 32 KiB above.
The above information is far from complete; it's just intended to give
the general idea of how this works. The Memory Bank Controller
and Cartridge Header pages on the Game Boy Development
Wiki (where this information came from) contain much more
extensive information about the devices and address decoding for the
Game Boy and its various cartridges. If you have specific questions
about how to access certain things in the Game Boy, it would probably
be best to ask them as separate questions here.
add a comment |
Address Decoding
Any computer system (including video game consoles) with more than one
memory device needs hardware (usually) external to the CPU to
determine which device to access for any particular address. This
process is called address decoding. In the simplest case this
could be a single device that looks at the address and makes the
decision this way:
- Address <
$c000
: access the RAM chip by setting the chip select
signal for the RAM chip "on" and the chip select signal for the ROM
chip "off." - Address >=
$e000
: access the ROM chip by setting the chip select
signal for the RAM chip "off" and the chip select signal for the ROM
chip "on."
This can also cause the mirroring that you sometimes see. Say that the
RAM chip is only 4 KiB, and thus uses only 12-bit addresses, with the
CPU's address bus lines A0-A11 connected to the RAM chip's address
pins. In the case above accessing $0003
will access address 3 on the
RAM chip, but also so will accessing $1003
or $2003
, because in
all cases:
- The address is less than
$c000
, so the address decoding logic
enables the RAM chip and disables all other devices. - The lower 12 bits of the address, are
$003
(sometimes expressed
as$x003
, where thex
is the four "don't care" bits the RAM
chip doesn't see), accessing the third location on the RAM chip. - The higher address bits A12-A15 are
$0
,$1
or$2
(sometimes
expressed as$0xxx
,$1xxx
or$2xxx
), but these address bits
are not connected to the RAM chip and are thus ignored by it.
Bank Switching
Bank switching extends this by changing which device is accessed
in a programmable way. Say you have a latch (basically, a one-bit
memory location) accessed at $c000
. (This would usually be on a
separate device, also enabled/accessed via appropriate address
decoding.) You might configure the hardware so that when this latch
contains a 0
any access to $e000
-$ffff
will access ROM chip #0,
but when a 1
is in this latch any access to $e000
-$ffff
will
instead access ROM chip #1.
Using this technique you can access more than 0x10000
memory
locations even though you have only 0x10000
addresses available by
having multiple devices at the same memory address and choosing them
based on further information such as the bit stored in the latch
example above. The system would start out at boot with a 0
in that
latch, but at any time the program could write a 1
to $c000
,
access the alternate memory, and when done, write a 0
to $c000
so
that further access would read the first memory again. (The program
would usually not be running from those $e000
-$ffff
memory
locations during this process. But with careful design of what's in
each memory bank, it could also be stored in both ROMs and switch
itself as it's running.)
Read vs. Write Decoding
There's one more bit of complexity that can be added to address
decoding: different decoding for reads and writes. In the example
above I had $c000
dedicated to the latch switching the ROM banks at
$e000
-$ffff
. However, since ROM is read-only and thus never
written, I can make the ROM-addresses dual-purpose by making writes
access a different device from reads. So I could, for example, make my
ROM two banks of 16 KiB, both accessed by reading $c000
-$ffff
, and
still use $c000
to switch as well. That address would thus be
accessing three separate devices:
- On write to
$c000
, with the current value of the latch0
or1
,
the data are always written to the latch. - On read from
$c000
with the current value of the latch =0
the
data are read from ROM chip #0. - On read from
$c000
with the current value of the latch =1
the
data are read from ROM chip #1.
Additional Hardware
Though every non-trivial video game system will have some address
decoding hardware built-in, it's common to add extra address decoding
hardware on the cartridge if the game is bigger than will fit into the
cartridge's address space. If the built-in address decoding always
accesses the cartridge for addresses $4000
-$7fff
, that could be
just a single 16 KiB ROM chip on the cartridge, or the cartridge could
have additional address decoding to select one of multiple ROM chips
based on other information, such as a latch also added to the
cartridge.
Cartridges may also have extra non-ROM hardware, such as RAM,
battery-backed RAM, timers, clocks, other sensors, and so on. The
address decoding on the cartridge also needs to manage how all these
devices are accessed, usually by assigning them specific memory
locations as well.
Game Boy Cartridge Memory Bank Controllers
On the Game Boy the additional address decoding logic on a cartridge
is called a Memory Bank Controller (MBC). There are several
different standard versions of this available, and you can find out
which one is used and the configuration of the cartridge by checking
certain memory locations in the cartridge header:
0x147
: Cartridge type.
$00
means it's a ROM-only cartridge, having no extra address
decoding. Addresses$0000
-$7ffff
each access one ROM location.
$01
is an MBC1 controller, allowing bank switching for a maximum
of 2 MiB of ROM, as described below.
$02
is MBC1+RAM, adding access to RAM on the cartridge (maximum
32 KiB) as described below.
$03
is MBC1+RAM+battery, with battery-backed RAM so that it's
preserved when the cartridge is removed. You need to remember to
disable the RAM when you're not using it so that it's not
corrupted when the cartridge is removed.
$04
is MBC2, which is similar to MBC1 but allows access to more
ROM and RAM. I don't describe this here; see the GB Dev Wiki for
details.- Higher values are yet more memory bank controller systems and
arrangements; again, see the GB Dev Wiki for details.
0x148
: ROM size.
$00
means one 32 KiB bank of ROM; this is the only valid value
for a cartridge type of$00
.
$01
means 64 KiB of ROM. The first 16 KiB is bank 0 and is
always accessed at$0000
-$3fff
. The additional three 16 KiB
banks are accessed at$4000
-$7fff
via bank switching. To
select the current bank using this range you write the ROM bank
number$01
,$02
or$03
to any address in the$2000
-$3fff
range. (This is ROM address space when read, but control latches
when written.)
0x149
: RAM size.
$00
means no RAM.
$01
and$02
are 2 KiB and 8 KiB of RAM respectively. The RAM
is accessed at addresses$a000
-$bfff
, after enabling it by
writing$0a
any address in the range$0000
-$1fff
. (This is
ROM address space when read, but control latches when written.)
$03
means 32 KiB of RAM in four 8 KiB banks. This still accessed
only in the 8 KiB range$a000
-$bfff
, but now you must bank
switch this to choose which of the four 8 KiB banks is read and
written when accessing that range.
$04
,$05
mean 128 KiB and 32 KiB respectively, bank switched
(in 16 and 8 banks, respectively) as for 32 KiB above.
The above information is far from complete; it's just intended to give
the general idea of how this works. The Memory Bank Controller
and Cartridge Header pages on the Game Boy Development
Wiki (where this information came from) contain much more
extensive information about the devices and address decoding for the
Game Boy and its various cartridges. If you have specific questions
about how to access certain things in the Game Boy, it would probably
be best to ask them as separate questions here.
Address Decoding
Any computer system (including video game consoles) with more than one
memory device needs hardware (usually) external to the CPU to
determine which device to access for any particular address. This
process is called address decoding. In the simplest case this
could be a single device that looks at the address and makes the
decision this way:
- Address <
$c000
: access the RAM chip by setting the chip select
signal for the RAM chip "on" and the chip select signal for the ROM
chip "off." - Address >=
$e000
: access the ROM chip by setting the chip select
signal for the RAM chip "off" and the chip select signal for the ROM
chip "on."
This can also cause the mirroring that you sometimes see. Say that the
RAM chip is only 4 KiB, and thus uses only 12-bit addresses, with the
CPU's address bus lines A0-A11 connected to the RAM chip's address
pins. In the case above accessing $0003
will access address 3 on the
RAM chip, but also so will accessing $1003
or $2003
, because in
all cases:
- The address is less than
$c000
, so the address decoding logic
enables the RAM chip and disables all other devices. - The lower 12 bits of the address, are
$003
(sometimes expressed
as$x003
, where thex
is the four "don't care" bits the RAM
chip doesn't see), accessing the third location on the RAM chip. - The higher address bits A12-A15 are
$0
,$1
or$2
(sometimes
expressed as$0xxx
,$1xxx
or$2xxx
), but these address bits
are not connected to the RAM chip and are thus ignored by it.
Bank Switching
Bank switching extends this by changing which device is accessed
in a programmable way. Say you have a latch (basically, a one-bit
memory location) accessed at $c000
. (This would usually be on a
separate device, also enabled/accessed via appropriate address
decoding.) You might configure the hardware so that when this latch
contains a 0
any access to $e000
-$ffff
will access ROM chip #0,
but when a 1
is in this latch any access to $e000
-$ffff
will
instead access ROM chip #1.
Using this technique you can access more than 0x10000
memory
locations even though you have only 0x10000
addresses available by
having multiple devices at the same memory address and choosing them
based on further information such as the bit stored in the latch
example above. The system would start out at boot with a 0
in that
latch, but at any time the program could write a 1
to $c000
,
access the alternate memory, and when done, write a 0
to $c000
so
that further access would read the first memory again. (The program
would usually not be running from those $e000
-$ffff
memory
locations during this process. But with careful design of what's in
each memory bank, it could also be stored in both ROMs and switch
itself as it's running.)
Read vs. Write Decoding
There's one more bit of complexity that can be added to address
decoding: different decoding for reads and writes. In the example
above I had $c000
dedicated to the latch switching the ROM banks at
$e000
-$ffff
. However, since ROM is read-only and thus never
written, I can make the ROM-addresses dual-purpose by making writes
access a different device from reads. So I could, for example, make my
ROM two banks of 16 KiB, both accessed by reading $c000
-$ffff
, and
still use $c000
to switch as well. That address would thus be
accessing three separate devices:
- On write to
$c000
, with the current value of the latch0
or1
,
the data are always written to the latch. - On read from
$c000
with the current value of the latch =0
the
data are read from ROM chip #0. - On read from
$c000
with the current value of the latch =1
the
data are read from ROM chip #1.
Additional Hardware
Though every non-trivial video game system will have some address
decoding hardware built-in, it's common to add extra address decoding
hardware on the cartridge if the game is bigger than will fit into the
cartridge's address space. If the built-in address decoding always
accesses the cartridge for addresses $4000
-$7fff
, that could be
just a single 16 KiB ROM chip on the cartridge, or the cartridge could
have additional address decoding to select one of multiple ROM chips
based on other information, such as a latch also added to the
cartridge.
Cartridges may also have extra non-ROM hardware, such as RAM,
battery-backed RAM, timers, clocks, other sensors, and so on. The
address decoding on the cartridge also needs to manage how all these
devices are accessed, usually by assigning them specific memory
locations as well.
Game Boy Cartridge Memory Bank Controllers
On the Game Boy the additional address decoding logic on a cartridge
is called a Memory Bank Controller (MBC). There are several
different standard versions of this available, and you can find out
which one is used and the configuration of the cartridge by checking
certain memory locations in the cartridge header:
0x147
: Cartridge type.
$00
means it's a ROM-only cartridge, having no extra address
decoding. Addresses$0000
-$7ffff
each access one ROM location.
$01
is an MBC1 controller, allowing bank switching for a maximum
of 2 MiB of ROM, as described below.
$02
is MBC1+RAM, adding access to RAM on the cartridge (maximum
32 KiB) as described below.
$03
is MBC1+RAM+battery, with battery-backed RAM so that it's
preserved when the cartridge is removed. You need to remember to
disable the RAM when you're not using it so that it's not
corrupted when the cartridge is removed.
$04
is MBC2, which is similar to MBC1 but allows access to more
ROM and RAM. I don't describe this here; see the GB Dev Wiki for
details.- Higher values are yet more memory bank controller systems and
arrangements; again, see the GB Dev Wiki for details.
0x148
: ROM size.
$00
means one 32 KiB bank of ROM; this is the only valid value
for a cartridge type of$00
.
$01
means 64 KiB of ROM. The first 16 KiB is bank 0 and is
always accessed at$0000
-$3fff
. The additional three 16 KiB
banks are accessed at$4000
-$7fff
via bank switching. To
select the current bank using this range you write the ROM bank
number$01
,$02
or$03
to any address in the$2000
-$3fff
range. (This is ROM address space when read, but control latches
when written.)
0x149
: RAM size.
$00
means no RAM.
$01
and$02
are 2 KiB and 8 KiB of RAM respectively. The RAM
is accessed at addresses$a000
-$bfff
, after enabling it by
writing$0a
any address in the range$0000
-$1fff
. (This is
ROM address space when read, but control latches when written.)
$03
means 32 KiB of RAM in four 8 KiB banks. This still accessed
only in the 8 KiB range$a000
-$bfff
, but now you must bank
switch this to choose which of the four 8 KiB banks is read and
written when accessing that range.
$04
,$05
mean 128 KiB and 32 KiB respectively, bank switched
(in 16 and 8 banks, respectively) as for 32 KiB above.
The above information is far from complete; it's just intended to give
the general idea of how this works. The Memory Bank Controller
and Cartridge Header pages on the Game Boy Development
Wiki (where this information came from) contain much more
extensive information about the devices and address decoding for the
Game Boy and its various cartridges. If you have specific questions
about how to access certain things in the Game Boy, it would probably
be best to ask them as separate questions here.
edited 4 hours ago
answered 5 hours ago
Curt J. SampsonCurt J. Sampson
7541 silver badge12 bronze badges
7541 silver badge12 bronze badges
add a comment |
add a comment |
Thanks for contributing an answer to Retrocomputing Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fretrocomputing.stackexchange.com%2fquestions%2f11732%2fhow-does-the-gameboys-memory-bank-switching-work%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
Bank switching means that there's more ROM in the cartridge than will fit into the space available for it, so only part of the ROM shows up in that space. You can switch which a part of the ROM, or bank, appears there in order to access the entire ROM.
– Ross Ridge
8 hours ago
So what are the memory locations d000-dfff and a000-bfff?
– David Tran
8 hours ago
I assume the later is what you said it is, RAM located on the cartridge. Presumably this is battery-backed RAM so that it can be used to save game state. I don''t know what the former is but it can't be the same thing as what's located at $4000-$7FFF because it's much smaller.
– Ross Ridge
7 hours ago