Jump to content

OAM DMA hijacking: Difference between revisions

no edit summary
No edit summary
No edit summary
Line 3:
{{clr}}
 
'''OAM DMA hijacking''' is a formmeans of [[arbitrarychanging codethe OAM DMA routine at execution]]FF80-FF89 in Game Boy games by glitching or hacking. In this case, whichthis allowsarticle forwill thedescribe playerhow to executedo codeit everywith frameglitches in the Pokémon games.
 
This glitch works by hijacking the "OAM DMA" processroutine associated with sprites. {{elaborate}}
 
An easy means to perform OAM DMA hijacking in both {{RB}} and {{GS}} 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_.
Line 11:
{{YouTube|1w2iQdAHPh4|Crystal_}}
 
It can be used for both arbitrary code execution and adding custom OAM sprite entries.
A basic way to do it is to replace FF80 with a jp instruction (C3 yy xx) to another routine stored in RAM. However, this will prevent the OAM sprites from updating.
 
==Setup (additional arbitrary code execution)==
Another exploit for Red and Blue can involve making the following modifications to the HRAM, as documented by luckytyphlosion:
Using another [[arbitrary code execution]] method (such an item configuration to run applicable GBZ80), write to the regions. Note the following:
 
1. Before doing anything, make sure to write C9 (ret) to FF80 first; unless the code writes to the region all at once (and without an interrupt back to FF80).
2. (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 do.
2. (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 (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.
2. (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 the money coins amount at FF9F) to run additional code which can be ended with a ret, without having to ever leave HRAM as part of the routines the player writes.
 
AnotherHere exploitis an example for Red and Blue canwhich involvekeeps makingoverworld thesprites followingbut modificationsdisables tomoving the HRAMcharacter, as documented by luckytyphlosion:
 
At FF86, write "jr FFF9".
Line 20 ⟶ 28:
At FFFC, write "jp [region]"
 
Do note that this will disable moving the character.
 
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.
 
 
This glitch works by hijacking the "OAM DMA" process associated with sprites. {{elaborate}}
 
An easy means to perform OAM DMA hijacking in both {{RB}} and {{GS}} 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|1w2iQdAHPh4|Crystal_}}
 
==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. In particular, this is useful for [[Party scrolling memory corruption#HRAM manipulation|party scrolling memory corruption]]; a glitch where scrolling beyond slot 6 in the party menu will attempt to animate those sprites and corrupt the memory. OAM sprite manipulation increases the range of corruptible memory addresses that would otherwise be possible.
 
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 (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.
 
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.
 
{{stub}}
Cookies help us deliver our services. By using our services, you agree to our use of cookies.