Gameboy and Gameboy Color special modes and features
This page describes various special modes and features of the Gameboy and Gameboy Color SoC intended for the boot ROM, debug features, or hardware features that ended being unused in the final hardware. Some of these features were discovered through data found in Nintendo leaks, whereas others were found out through experimentation. This knowledge has been described in various places, including semiprivate spaces like the GB Dev Discord server. This is an attempt to document everything that's known about these features publicly.
This document is still a work in progress and may contain errors.
Contents
- 1 DMG test mode pins
- 2 GBC test mode pins
- 3 Palette selection window - PSW (GBC)
- 4 Non-maskable interrupt (NMI) (GBC)
- 5 PGB mode (GBC)
- 6 Miscellaneous test mode IO registers
- 7 Miscellaneous boot ROM IO registers
- 8 Entering GBC mode manually on GBA (GBA)
- 9 Clock glitching to access the boot ROM context (DMG/GBC)
- 10 Credits
DMG test mode pins
The DMG SoC has two test pins, T1 (pin 77) and T2 (pin 76) which are normally both grounded on the circuit board. By looking at DMG-CPU-Inside, we can predict the functionality of the test pins. The above schematic from sheet 7_SYS_DECODE shows 3 valid modes:
- Both pins low: Normal operating mode. The SoC is also held in this state when reset is asserted.
- T1 is high
- T2 is high
- T1 and T2 are both high. This state is invalid. The test decoding stage suggests that putting the test line in this state will fail to signal either the normal operating mode, or either of the test states, rather than a combination of the two test states. Maybe this can be useful for something though?
GBC test mode pins
The GBC SoC has three test pins, TEST0 (pin 49), TEST1 (pin 50), TEST2 (pin 51).
Palette selection window - PSW (GBC)
The palette selection menu is a cancelled product feature in that would allow the user to change the palette of a monochrome game after the game had started. This was instead implemented in the final hardware as a one time palette selection before the game starts that can be accessed by pressing buttons during the boot animation. The PSW was previously known from Nintendo's '447 patent covering the GBC, where it's mentioned as step S10 and S11 and the flowchart in fig 14. While this was known information, it was not known whether hardware implementing it existed before the leaks happened.
From a technical point of view, the PSW consists of the following hardware features. These features are not normally visible to the running program, but require you to get access to the boot ROM context or test mode. See other sections for possible routes if you want to experiment with these features.
The palette selection window (PSW)
The PSW is a second display window similar to the regular window. It's repurposing VRAM bank 1, which is inaccessible to monochrome games, for storing tile and map data for the second window. The function of the PSW is demonstrated in mattcurrie's apparently.gb. (Xwitter post, ROM download)
Button mask for remapping the boot ROM and triggering a non-maskable interrupt (NMI)
The PSM register holds a button mask. The idea is that when all buttons specified in the button mask are pressed, the boot ROM is remapped, and an NMI is triggered, which would allow the boot ROM to display the menu, as well as have access to the GBC palette registers which are otherwise locked away from monochrome games.
Associated IO registers
Note that while these can be written and read back without special requirements they only haven effect when in the boot ROM context/test mode.
Address | Name | Description |
---|---|---|
$FF71 | PSW | Palette Select Window control. Controls functionality related to the palette select window.
|
$FF72 | PSWX | Palette select window X/Y position. 8 bit numbers that works similarly to the well known WX and WY registers. Note that PSWX has a lower memory address than PSWY, unlike WY and WX. |
$FF73 | PSWY | |
$FF74 | PSM | PSW activation button mask. Same format as $FF61: buttons are in the upper nibble and D pad in the lower nibble. |
PSW VRAM format
Map data comes from 1:$9800 and has format %pppttttt where the top 3 bits are palette index and the lower 5 bits are the tile number, 0-$1F.
Tile data is from 1:$9000.
The feature was intended to be used with monochrome games, which only use bank 0 of VRAM, so it makes sense that all PSW data is stored in bank 1.
Non-maskable interrupt (NMI) (GBC)
NMIs on the GBC are not normally accessible, but can be accessed through one of two ways. A non-maskable interrupt can be triggered either by the button combination in the PSM register, assuming you're able to set it up right, or by pulling the NMI line low. The NMI line is permanently shorted to +3.3V on a standard GBC circuit board, but the board design has an option link that you can cut. It's then recommended to replace the option link with a suitable pullup resistor to avoid spurious triggering of NMIs. You're now ready to connect a switch or other mechanism to short the NMI pin to ground to trigger an NMI.
A NMI on the GBC has the interrupt vector $0080. To exit NMI mode, you need to execute a reti instruction. Executing an ei instruction is not enough, and will not re-enable "user mode" interrupts, or allow another NMI to be executed, until NMI mode is exited with a reti instruction.
One additional NMI interrupt request can be buffered if there's an additional pulse while the interrupt vector is still executing.
If the NMI was triggered by the PSM button combination, the boot ROM might be remapped. It will be unmapped again when executing when executing a reti opcode. However, this circuit is somewhat separate from the CPU logic, and it is strictly speaking not executing a reti that does it, but executing an instruction with opcode D9. This means that the prefixed instruction set 3,c will unmap the boot ROM after a NMI as well.
Opcode Instruction Notes D9 reti ; The instruction has opcode D9 and will unmap the boot ROM and re-enable NMI. 3E D9 ld a,$D9 ; D9 is the instruction argument and not considered an opcode, so it doesn't unmap the boot ROM or re-enable NMI. CB D9 set 3,C ; Both CB and D9 are considered opcodes in the decoding process, so this will unmap the boot ROM but not re-enable NMI.
PGB mode (GBC)
PGB mode is a mode described in leaked Nintendo documents as a way to control the LCD externally from the cartridge. According to documentation, it can be activated by writing to bits 3 and 2 of $FF4C (KEY0).
Address | Name | Description |
---|---|---|
$FF4C | KEY0 | CPU mode register.
Bits 3 and 2:
Bit 0:
|
$FF4C is written by the following code in the boot ROM:
ld a, [HeaderCGBCompat] ; $0143 of the ROM header. bit 7, a jr z, .dmgMode ldh [rKEY0], a jr .done .dmgMode ld a, KEY0_DMG ldh [rKEY0], a ld a, OPRI_COORD ldh [rOPRI], a
If bit 7 of the header value is set, the whole byte is written to $FF4C. This might be either be based on an assumption that $80 and $C0 are the only valid values for a GBC game, so bits 3 and 2 should always be 0. Or, it might be a deliberate way of allowing these bits to be set to values corresponding to one of the PGB modes for potential future hardware by puttting a value with those bits set in the header.
Activating and using PGB mode
PGB1 mode
PGB1 mode stops the CPU completely, and it never wakes up
Set $0143 in the ROM header to $88 to let the boot ROM activate PGB1 mode. Then execute a stop instruction to stop the CPU.
This turns most of the cartridge bus pins into digital passthrough signals for the LCD signals.
This data has been produced by Sono, by pulling each of the cart bus signals high/low and measuring what changed on the LCD bus. However, no hardware for actually displaying useful data on the GBC LCD has been produced as of writing.
Pinout
Pin# | Normal use | LCD signal in PGB mode |
---|---|---|
1 | Vcc | Vcc |
2 | /PHI | ??? |
3 | /WR | SPL |
4 | /RD | DCK |
5 | /CS | Unused (see note) |
6 | A0 | LDR0 |
7 | A1 | LDR1 |
8 | A2 | LDR2 |
9 | A3 | LDR3 |
10 | A4 | LDR4 |
11 | A5 | LDR5 |
12 | A6 | LDG0 |
13 | A7 | LDG1 |
14 | A8 | LDG2 |
15 | A9 | LDG3 |
16 | A10 | LDG4 |
17 | A11 | LDG5 |
18 | A12 | LDB0 |
19 | A13 | LDB1 |
20 | A14 | LDB2 |
21 | A15 | Unused (see note) |
22 | D0 | LDB3 |
23 | D1 | LDB4 |
24 | D2 | LDB5 |
25 | D3 | REVC |
26 | D4 | CLS |
27 | D5 | SPS |
28 | D6 | PS |
29 | D7 | LP |
30 | /RST | /RESET |
31 | VIN | VIN |
32 | GND | GND |
Note: A15 (which is typically used as a /CS signal for the ROM and MBC) as well as /CS (used as part of SRAM chip select decoding) are not connected to any LCD signals. This is likely intentional so that a ROM, MBC and SRAM can live on the same bus without being selected, by pulling A15 and /CS high. A cartridge using PGB mode needs to supply its own pullup resistors for those pins.
PGB2 mode
It's still unknown how PGB2 mode works in terms of allowing the CPU to run, considering the address/data buses are used solely for LCD signal passthrough. (Possibilities: Can the CPU receive an interrupt? Do you need to copy code to RAM before activating PGB2 mode somehow?)
It's also unknown how or even if joypad input is communicated to the cartridge in any PGB mode.
nocash notes
FF4C - DMG1 - CGB Mode / DMG Mode (R/W only until FF50h is written) Internally used by CGB-BIOS. Set to 04h in DMG-mode. Set to Cart[0143h] in CGB-mode (for CGB carts, that is usually 80h or C0h) (so the three read/write-able bits are usually zero in CGB mode). Settings like Cart[0143h]=88h, would allow to enter a special mode, but, in that case, the BIOS boots up with a locked blank palette, so that mode is of no good use. Bit 0 - Unknown (0=Normal, 1=No effect?) Bit 1 - Not used Bit 2 - Disable All CGB Functions (0=CGB, 1=DMG) Bit 3 - Disable Some CGB Functions (0=Normal, 1=Extended DMG Mode) Bit 4-7 - Not used Bit3 disables HDMA, BGPD, OBPD, and KEY1. Bit2 does the same, and additionally disables RP(IR), VBK(VRAM), SVBK(WRAM), and FF6Ch. If both bits are set, Bit3 has priority over Bit2. FF4Ch is write-able (and read-able) only until FF50h is written to for the 1st time. ...one or more of the bits probably affect FF02h serial-speed... ?
$FF75 (kgsws notes)
Reading (bits): 0 = PHI input reading 1 = A15 input reading 2 = !CS input reading 3 = unknown, read as 1 4 - 7 = possibly written state? not tested Writing (bits): 0 = PHI output value 1 = A15 output value 2 = !CS output value 3 = unknown 4 = enable PHI output 5 = enable A15 output 6 = enable !CS output 7 = unknown
Note: Outputs are open-drain. Pull-ups are required.
Miscellaneous test mode IO registers
TODO: Check which of these are available in the boot ROM context and which require test pins.
$FF26 - NR52
NR52 is the register normally used turning the APU on or off, and reading the status of playing sound channels. The following is a note by Sono that the unused bits might have a special function. (Possibly based on DMG-CPU-inside tracing, and possibly only available when test pins are set.)
.5 (write only?) - manual sweep clock overide level .4 (write only?) - APU test mode enable (TODO: how?)
$FF60 (TEST_PAD) and special functions of $FF00 (P1)
Sono notes:
(write only?) - test mode port .1 - TODO: something with serial port and buttons .0 - TODO: something with button input overriding
nocash notes:
FF60 - JOYC - Joypad Mode (W) (enabled while ROMDIS=HIGH only) Exists on all gameboy types. Register is write-only (even when it is enabled, reading always returns FFh). Bit 0 - Joypad Mode (0=Normal/Read-only, 1=Read/Write) Bit 1-7 - Not used On older gameboys (those with 2x4bit joypad pinout), the lower 4bit of FF00h become read/write-able. On color gameboy and up (those with 8bit joypad pinout), register FF61h becomes R/W (if it is enabled by ROMDIS). Although FF60h is write-able only while ROMDIS=HIGH, the setting keeps working even after releasing ROMDIS.
Looking at DMG-CPU-Inside, we can predict how the FF60 register will behave on DMG. The register is writable if T1 or T2 asserted. This register is write-only and can't be read back. (On DMG, based on DMG-CPU-Inside. TODO: Check if this is true, and whether it's also true on GBC.)
Bit | Description |
---|---|
0 | IO mode.
Ie, both the output and input part of the joypad port are reverse from normal. (TODO: Check if this is true in reality.)
|
1 | Div speed. This is predicted by the ULUR mux in the 1_CLOCKS_RESET sheet of DMG-CPU-Inside. TODO: Verify if 0 is really the normal mode. It seems like 1 should select the standard mode, but on the other hand FF60 seems to default to 0 on reset.
|
2-7 | Unused. |
$FF61 (PAD)
Sono notes:
$FF61 - PAD - raw keypad value and override (1=override, how?) .7 - Start .6 - Select .5 - B .4 - A .3 - Down .2 - Up .1 - Left .0 - Right
nocash notes:
FF61 - JOY8 - 8bit-Joypad (R, or R/W) (enabled while ROMDIS=HIGH only) 0 - Right (0=Low/Pressed, 1=High/Released/Disabled) 1 - Left ("") 2 - Up ("") 3 - Down ("") 4 - Button A ("") 5 - Button B ("") 6 - Select ("") 7 - Start ("") The register is normally disabled. When enabled via ROMDIS, it can be either read-only (input), or read/write (output), depending on FF60h setting.
$FF63 (???)
Sono notes:
$FF63 - TEST_PPU - PPU "malfunction" port .7 - unknown .6 - unknown other bits are unknown, but most of them force/disconnect/freeze PPU stuff
Sono notes 2:
weird observations for $FF63:
- bit0 disables sprite VRAM access or something? sprites turn invisible
- bit1 disables Color RAM access perhaps? everything turns white
- bit2 and bit3 seem to work together, various BG-related things stop functioning
- with bit4 enabled, bit2 and bit3 fill the entire screen with BG color index $FF63[3:2] (in my case white, light gray, dark gray, black)
- bit5 ceases VBlank from function?
- idk what bit6 does
- bit7 unlocks a TON of new never-before-seen registers
- GDMA src/dest addr become readable.
- [$FF64] = $00
- [$FF65] = $A0 (160)
- [$FF66] = $A7 (167)
- [$FF6F] = $00
- setting bit4 when writing to $FF64 makes $FF65 turn from $A0 to $00
- the rest don't seem to respond to writting
nocash notes:
FF63 - ? - Undocumented Ext.Configuration (enabled while ROMDIS=HIGH only) This register is normally deactivated (value FFh, read-only). 0 - Unknown (0=Normal, 1=No effect?) 1 - Unknown (0=Normal, 1=Disable Video?) 2 - Unknown (0=Normal, 1=Disable Video?) 3 - Unknown (0=Normal, 1=Disable Video?) 4 - Unknown (0=Normal, 1=Disable Video?) 5 - Unknown (0=Normal, 1=Crash?) 6 - Unknown (0=Normal, 1=No effect?) 7 - Unknown (0=Normal, 1=No effect?) When ROMDIS is high, reading returns 00h, and writing non-zero values seems to crash the program (or disable video) in most cases.
$FF76/$FF77 (PCM12/PCM34) GBC
The current amplitude level of each audio channel. Read only and always available, without needing special modes.
- PCM12 lower nibble: channel 1 amplitude level.
- PCM12 upper nibble: channel 2 amplitude level.
- PCM34 lower nibble: channel 3 amplitude level.
- PCM34 upper nibble: channel 4 amplitude level.
Miscellaneous boot ROM IO registers
$FF50 (BANK) DMG/GBC
Writing a value with bit 0 set locks out the boot ROM and (on GBC) various configuration registers. The value is latching: once bit 0 has been set, it cannot be cleared without a reset. The exception to this when a PSW NMI is triggered.
$FF6C (OPRI) GBC
Controls priority of overlapping objects. Set by the GBC boot ROM based on the GBC compatibility flag in the ROM header. This bit can still be modified in GBC mode, but doesn't have an effect on object priority after the boot ROM has been locked. (TODO: verify that this is true.)
- Bit 7-1: Unused.
- Bit 0: 0: Priority is based on the position in the OAM table. (GBC default.) 1: Priority is based on the X position. (Emulate DMG mode.)
Entering GBC mode manually on GBA (GBA)
Gameboy Advance can run GBA as well as GBC games. The way it does this is with an electrical microswitch at the bottom of the cartridge port which is only pressed by GB(C) cartridges, due to their shape. When a GBA boots, the GBA (ARM) BIOS checks whether this switch is pressed, and then requests a mode switch to GBC mode. with some trickery, this can also be done "manually", which opens up a couple of cool possibilities. This is demonstrated in AntonioND's gba-switch-to-gbc project.
The BIOS performs the following procedure:
- Configure the audio sample rate/bit rate to the default of 9bit / 32.768kHz using the 4000088h (SOUNDBIAS) register. (TODO: Do more research on this. Does this actually affect GBC mode, and is there a detectable difference if this mode is changed when entering GBC mode manually?)
- Check bit 15 of the register 4000204h (WAITCNT). If it's 0, continue the normal boot procedure. It it's 1 continue below.
- Draw a border in VRAM.
- Set bit 3 of 4000000h (DISPCNT) to 1, which requests a mode switch.
- Write 0 to 4000301h (HALTCNT) which permanently halts the ARM CPU and boots the GBC subsystem.
To enter GBC mode manually from GBA software, one caveat is that writes to bit 3 of DISPCNT only take effect if the program counter is in the GBA BIOS area. One popular method around this is to use swi 0x0B (CpuSet) to copy one word to DISPCNT. Since the write is then done by the BIOS, it takes effect as intended.
Resource allocation between the GBA and GBC subsystems
Some resources are shared between the subsystems. However, the way that they are shared varies. Some resources are handed over when the mode switch takes place. Other resources are switched on the fly as soon as the microswitch in the cartridge port is engaged or disengaged. This leads to some caveats when dealing with manually entering GBC mode, because some resources could be unavailable or rug pulled when inserting or removing a GBC cartridge.
GBA resource | GBC resource | Allocated by | Notes/caveats |
---|---|---|---|
Joypad | Cartridge switch | When the switch is pressed, GBA software can't read the state of the buttons. When the switch is depressed, GBC software can't read the state of the buttons. On the GBC side, this show up as all bits reading 0, or put differently, all buttons being pressed at once. | |
Cartridge bus | Cartridge switch | When the switch is pressed, GBA software can't access the external cartridge bus. When the switch is depressed, GBC software can't read the state of the buttons. On the GBC side, this show up as any byte reading 0. This can be used to run GBC code on a GBC without a GBC cartridge. See below. | |
EWRAM | WRAM | Cartridge switch | The same memory that works as GBA external work RAM (EWRAM) is reused as work RAM (WRAM) in the GBC subsystem. This is directly controlled by the cartridge switch. If you want your code to wait x seconds before performing the actual switch to allow the user time to insert a GBC cartridge, this waiting code should be placed IWRAM, or else it will crash when EWRAM is rug pulled. Likewise, GBC WRAM reads 0 when no GBC cartridge is inserted. GBC software that should run without a GBC cartridge inserted should avoid using WRAM, sticking to only VRAM and HRAM. Exception: The GB micro has WRAM mapped in GBC mode. This is weird because it doesn't even support running GBC cartridges. |
IWRAM | VRAM | DISPCNT | The same memory that works as GBA internal work RAM (IWRAM) is reused as video RAM (VRAM) in the GBC subsystem. (TODO: Confirm whether it's disconnected from the GBA side immediately when writing DISPCNT or when performing the halt.) |
The boot "ROM skip bit" and running SM83 code on the GBA without a GBA cartridge
Setting bit 3 of the undocumented GBA IO register 4000800h and then entering GBC mode manually will skip the boot ROM. (It is believed that bit 1-3 of this register correspond to the three test pins of the GBC CPU.) This makes the GBC CPU start executing at address 0 and thus skip the boot ROM. However if doing this with no GB(C) cartridge inserted, because the ROM area all reads 0, the CPU will nop slide into the next memory area, which is VRAM. By placing specially crafted GBC code in IWRAM, which is used as GBC VRAM, it's possible to run GBC code on the GBA without the help of a GBC cartridge. However, it's not possible to read the state of the joypad buttons and GBC WRAM (work RAM) is unless you insert a cartridge (or at least an object that engages the microswitch like the back half of a cartriudge shell) so this mode is less useful for many things. A practical use case of this method is Lorenzooone's gba-dump-gb.
RAM mapping between GBA and GBC
Sono notes:
; WRAM mapping: ; for each EWRAM word ; AA BB ; AA BB CC DD (on Micro) ; AA - WRAM ; BB - (unused) ; CC - (unused) ; DD - (unused) ; addr = offset * wordsize ; VRAM mapping: ; for each IWRAM word ; AA BB CC DD ; AA - bank0 $8000 ; BB - bank0 $9000 ; CC - bank1 $8000 ; DD - bank1 $9000 ; addr = ((offset << 2) & 0x3FFF) | (offset >> 12)
addr being GBA-side, offset being CGB-side
Clock glitching to access the boot ROM context (DMG/GBC)
In 2014, BennVenn discovered that you can glitch the program counter (PC) by stopping the CPU clock, by briefly shorting one of the clock crystal pins to ground. This effectively makes the CPU jump to some random location, with the boot ROM still mapped. Then at that point the boot ROM can be dumped, and IO registers normally only available to the boot ROM can be accessed for research purposes or fun.
The procedure works like this:
- Make a program where the payload is at the end of the ROM space. Fill up the rest of the ROM with null bytes, which will act as the nop opcode.
- Make sure the logo and header checksum are invalid. This can be done using rgbfix -f LH rom.gb. This is strictly speaking optional, but recommended because it will make the boot ROM lock up in an endless loop, giving you more than just a couple of seconds to successfully perform the glitch before the boot sequence ends.
- Short one of the clock crystal pins to ground to (hopefully) jump to your payload. Note that the oscillator circuit will always have two load capacitors nearby which are convenient for this operation if using tweezers to do the shorting, so you don't have to touch the actual crystal's pins which are less convenient to access. Or on a DMG you could for example hold one side of a wire against the link port and scrape the other side against the clock oscillator pin. Yet another option if you're going to do this often is to connect two short wires going to a switch, so you can trigger the glitch more easily. Note that the wires should not be too long to avoid loading the down the oscillator with too much capacitance. This is practically necessary for GBC since the clock circuit is obscured by the cartridge and the clock signal is not broken out to test pads on the back of the board.
The clock circuit on a DMG
The clock circuit on a GBC
Tips, tricks and caveats
- One of the oscillator pins is an input and one is an output driving the crystal. I've had more luck with shorting the "input" side, and this should also theoretically be safer for the chip, although I've never observed any permanent damage from using either pin. (TODO: Document which is which for various GB models, and document how to figure this out using an oscilloscope.)
- Some revisions of GBC are more difficult to glitch, maybe due to changes in the silicon layout to clean up the clock signal. CPU CGB D is known to be hard to glitch. (TODO: Document in more detail which revisions are easier and harder to glitch.)
- There may be difference in success rate based on decisions in the ROM. For example, maybe you should only trash the logo or only the header checksum because one endless loop happens to have a higher success rate for where it ends up jumping when glitched. (TODO: Research if this is the case and document it.)
Glitching a monochrome GB clone
If you're attempting to dump the boot ROM from a Gameboy clone, there's a possibility that it's using an inductor based oscillator instead of a quartz crystal. Whereas the quartz crystal would either look like a metal can, or a rectangular ceramic block, the inductor would look like a slightly fatter resistor. See this example from a Fortune SY-3000B clone. In this case, the "short to ground" method doesn't really work. Instead you need to replace the inductor with a suitable quartz crystal. However, be aware that the inductor can be brittle, and it's easy to break it if you try to remove it.
The crystal could be one from a DMG, and this could be left in permanently to make the clone run at the correct speed as a bonus. But anything in the range 2-5 MHz should work for the purposes of glitching. You also need to add a 1-5 Mohm resistor in parallel to make it start oscillating. The board in this case already has load capacitors, the two brown orange ones. See the GBC schematic for a typical circuit. After a quartz crystal is in place, the clone can be glitched much like a DMG.
For a noninvasive way to detect whether a GB clone has a boot ROM that has not yet been dumped, please see the whichboot.gb project.
Glitching a monochrome GB Boy Colour clone
The GB Boy Colour has a higher frequency oscillator (3x the CPU frequency maybe?) which is used for the image upscaling, as well as divided down for the SoC. I've had some success in glitching this as well, by the same short to ground method, but on the higher frequency crystal. Image of the setup:
Credits
Various people have contributed to the research of these features. This list is likely far from complete. In no particular order:
- Dwedit - early research about the GBA's GBC mode.
- AntonioND - research about the GBA's GBC mode and the gba-switch-to-gbc project.
- mattcurrie - research about the boot ROM context and PSW, and making the apparently.gb demo.
- Sono - Figuring out the PGB mode mapping between the cart bus and LCD, and various other research.
- nocash - Various research.
- BennVenn - Discovering that you can corrupt the program counter (PC) by briefly shorting one of the clock crystal pins to ground, allowing code to access the boot ROM context.
- Furrtek - Maintainer of the DMG-CPU-Inside which allows predictions about various test mode behaviors.
- Org - Maintainer of Emu-Russia's dmgcpu project, which has a similar goal to DMG-CPU-Inside.
- gekkio - Attempting to fully reverse engineer and document the Gameboy. Tons of research on obscure Gameboy hardware features. Maintaining GBHWDB, a database of console variations.
- shinyquagsire23 - Discovered the GBC test mode bits on GBA.
- nitro2k01 - Various research, maintaining this document.
- casualpokeplayer - Various research.
- Lorenzooone - Made the gba-dump-gb project as a practical demonstration of using the GBA's GBC mode with boot ROM skip.
- kgsws - Figuring out the function of $ff75.