OAM DMA hijacking

From Glitch City Wiki
Jump to navigation Jump to search
Arbitrary code execution in the Pokémon series

0x1500 control code arbitrary code execution (Crystal) | Cart-swap arbitrary code execution | Generation I custom map script pointer | Generation I invalid meta-map scripts | Generation I item ("8F", "ws m", "-g m", "5かい", "てへ" etc.) | Generation I move ("-", "TM42") | Generation I Trainer escape glitch text boxes | Generation II bad clone | Generation II Burned Tower Silver | Japanese Crystal Pokémon Communication Center SRAM glitches | Coin Case glitch | Generation II glitch Pokédex sortings | Pikachu off-screen glitch ACE | OAM DMA hijacking | Pikachu glitch emote | Generation III glitch Pokémon summary | Generation III glitch move animation) | Remote code execution | TM/HMs outside of the TM/HM pocket | ZZAZZ glitch Trainer FC

List of arbitrary code execution programs

(view, talk, edit)
More research is needed for this article.
Gen III 00FC-0114.png
Reason given: A technical explanation of what OAM DMA is and how it works would be great.

OAM DMA hijacking (Object Attribute Memory Direct Memory Access hijacking) is a means of changing the OAM DMA routine at FF80-FF89 (though the actual end can be extended e.g. FF89 could use two bytes for a relative jump, in which case FF8A is occupied) in Game Boy games by glitching or hacking. In this case, this article will describe how to do it with glitches in the Pokémon games.

This glitch works by hijacking the OAM DMA routine associated with sprites.[elaboration needed]

An easy means to perform OAM DMA hijacking in both Pokémon Red and Blue and Pokémon Gold and Silver is to write to the HRAM region FF80, however care must be taken as this region will be executed every frame. For this reason it is safe to place a ret (0xC9) opcode at the beginning of this region, write the code after it and replace the ret with a nop (0x00) byte afterwards. This exploit was documented by Crystal_.

YouTube video by Crystal_

It can be used for both arbitrary code execution and adding custom OAM sprite entries.

Normal behaviour

During gameplay, FF80 is typically always executed and in Pokémon Red and Blue, Pokémon Yellow the OAM DMA I/O register (represented by FF46 on the memory map) is altered by the following routine:

ld a,c3
ld (ff46),a
ld a,28
dec a
jr nz,ff86

When C3 is written to FF46, it means that the OAM sprites will be mirrored at C3XX in RAM. The OAM sprites are stored at the sprite attribute table in FE00-FE9F. For more information, see this section in the Pan Docs.

Setup (additional arbitrary code execution)

Using another arbitrary code execution method (such an item configuration to run applicable GBZ80), write to the regions. Note the following:

Before doing anything, make sure to write C9 (ret) to FF80 first; unless the code writes to the region all at once as the game could freeze.

  • Option 1 - Simplest but breaks OAM sprites - The player can write bytes from FF81 onward, such as a simple RAM modification code (15 EA 59 D0 C9), before adding 3E back to FF80. Another option for longer codes is to make FF80 read jp (source address). The ld a,C3 ld (ff00+46),a if overwritten like this will break OAM sprites (i.e. the sprites like Red on the screen, although from now on the code will run every frame regardless of where the player is in game; something that other arbitrary code execution methods cannot normally do (though hypothetically something may be possible without it by manipulating the stack).
  • Option 2 - Keeps OAM sprites - A more elaborate code may be written to keep OAM sprite functionality. Note the ld a,C3 ld (ff00+46),a works with a delay to keep the program counter in HRAM until FF89's ret (jumping there if the z flag is unset, from the code ld a,28 dec a jr nz,ff86). If the program counter remains in HRAM for the wrong amount of time, the game will freeze after leaving it (for example, if the 28 was changed to a lower value). Hence, any new delay should address this before leaving HRAM, yet if properly accounted for it is possible to run code outside of HRAM in addition to OAM sprites still working.
  • Option 3 - Keeps OAM sprites, but at the cost of potentially freezing the game if the HRAM addresses the player chose to change are overwritten again); Another option is to overwrite other HRAM address that don't often change beginning from a relative jump at FF89 (such as to the money coins amount at FF9F) to run additional code (and with a potential series of other relative jumps across HRAM) which can be ended with a ret, without having to ever leave HRAM as part of the routines the player writes.

OAM DMA hijacking is useful as a form of 'real-time' arbitrary code execution, allowing the player to perform exploits such as walk through walls in Generation II or writing a 0x50 sub-tile permanently to the beginning of the screen data for Generation I.

Setup (OAM sprite manipulation)

By simply changing the value at FF81 (normally the C3 in ld a,C3); the player can change the source of OAM sprites from C300 to XX00.

This method can also be used for a creative purpose; for the player to add their own sprites to the screen; for example changing it to D300 will touch the start of the inventory items; D31C (the last Pokédex seen flag controls the y-coordinate of the eighth entry, D31D (the number of items) controls the x-coordinate of the entry, D31E (the first item) controls the sprite, D31F (the first item quantity) controls the attribute of that sprite). More control however starts at item 2 (D320) (or the ninth entry) and onward; two item pairs consisting of the item and its quantity will control one OAM entry (four bytes), so by adding specific items the player can display their own sprites on the screen. Note memory addresses are -1 in Yellow, so the same D31C is the number of items and so on.

In this case, it may be possible to animate them with additional code to change the items. Animations of the OAM entries are normally done by other routines (such as the overworld loop which is meant to change C3XX), but the player could for instance use map script arbitrary code execution to run their own sprite animation routine.

Taking over the joypad

At FF86, write "jr FFF9".
At FFF9, write "dec a"
At FFFA, write "jr nz, FFF9"
At FFFC, write "jp [RAM]"

At the desired RAM address (e.g. D34A), write:

ld a,(FFD3) ; a=random "D-sum" byte 1 number.
ld (FFF8),a ; put a into FFF8, which controls what buttons are being pressed.
ret ; Don't execute any code after D350.

This example is a simulation of RNG Plays Pokémon, but the routine at D34A can be adjusted for different inputs into FFF8.

This technique was documented by luckytyphlosion, and a method of setting it up from scratch using TheZZAZZGlitch's coordinates memory editing method by ChickasaurusGL.

YouTube video by ChickasaurusGL

See also

This article or section is a stub. You can help Glitch City Wiki wiki by expanding it. RB 234 fs crop.png