Slide 1

Slide 1 text

The day I reverse engineered a Gameboy Advance game With @ythecombinator AND @macabeus REVISITED

Slide 2

Slide 2 text

WTF?! THE DAY I REVERSE ENGINEERED A GAMEBOY ADVANCE GAME

Slide 3

Slide 3 text

"""

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

soooo…

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

This is macabeus

Slide 8

Slide 8 text

This is MATHEUS

Slide 9

Slide 9 text

This is US PLAYING KLONOA

Slide 10

Slide 10 text

AND THIS IS US BORED

Slide 11

Slide 11 text

soooo…

Slide 12

Slide 12 text

WANTED MORE LEVELS TO PLAY WITH

Slide 13

Slide 13 text

WANTED DIFFERENT LEVELS

Slide 14

Slide 14 text

soooo…

Slide 15

Slide 15 text

soooo…

Slide 16

Slide 16 text

soooo…AND THIS IS KLONNOA

Slide 17

Slide 17 text

No content

Slide 18

Slide 18 text

No content

Slide 19

Slide 19 text

http://bit.ly/balccon-gba-code

Slide 20

Slide 20 text

Stretching the bridge THE DAY I REVERSE ENGINEERED A GAMEBOY ADVANCE GAME

Slide 21

Slide 21 text

https://www.nogba.com

Slide 22

Slide 22 text

https://www.hex-rays.com/products/ida

Slide 23

Slide 23 text

No content

Slide 24

Slide 24 text

No content

Slide 25

Slide 25 text

This is the tile ID. In this example, all tiles with the ID 9B are exactly the bridge part, which is the left corner. 9A is the ID of the continuous part of the bridge.

Slide 26

Slide 26 text

This tells us where the tile is stored in the memory. In this example, it is at 0600F1AD.

Slide 27

Slide 27 text

https://www.coranac.com/tonc/text/hardware.htm

Slide 28

Slide 28 text

https://www.coranac.com/tonc/text/hardware.htm The address found is expected 0600F1AD given that everything between 0600 and 0601 is part of the section known as VRAM.

Slide 29

Slide 29 text

Our bridge starts here!

Slide 30

Slide 30 text

And now we grow it bigger! WTF??!

Slide 31

Slide 31 text

Understanding the DMA THE DAY I REVERSE ENGINEERED A GAMEBOY ADVANCE GAME

Slide 32

Slide 32 text

VRAM pulls the tilemap
 containing exactly what the player has to see from somewhere else that has the entire thing.

Slide 33

Slide 33 text

https://www.coranac.com/tonc/text/regbg.htm

Slide 34

Slide 34 text

https://www.coranac.com/tonc/text/regbg.htm Direct Memory Access

Slide 35

Slide 35 text

https://www.coranac.com/tonc/text/regbg.htm It is a feature of computer systems that allows certain hardware subsystems to access main system memory (random- access memory), independent of the CPU

Slide 36

Slide 36 text

https://www.coranac.com/tonc/text/regbg.htm tldr; a faster copy and paste

Slide 37

Slide 37 text

DMA3: 03000900 0600E000 80000400 DMA3: 03001100 0600E800 80000400 DMA3: 03004DB0 0600F000 80000200 DMA3: 03004800 07000000 84000048

Slide 38

Slide 38 text

DMA3: 03000900 0600E000 80000400 DMA3: 03001100 0600E800 80000400 DMA3: 03004DB0 0600F000 80000200 DMA3: 03004800 07000000 84000048 The closest to the bytes of our bridge (0600F1AD).

Slide 39

Slide 39 text

DMA3: 03000900 0600E000 80000400 DMA3: 03001100 0600E800 80000400 DMA3: 03004DB0 0600F000 80000200 DMA3: 03004800 07000000 84000048 This address is the VRAM data source. It’s located in a region called Fast WRAM.

Slide 40

Slide 40 text

No content

Slide 41

Slide 41 text

Our bridge starts here!

Slide 42

Slide 42 text

Stretching it… …It works! And…

Slide 43

Slide 43 text

Stretching it… …It works! And… WTF??!

Slide 44

Slide 44 text

Our extra tiles disappear when out of the player vision range.

Slide 45

Slide 45 text

LET’S TALK ABOUT PHYSICS THE DAY I REVERSE ENGINEERED A GAMEBOY ADVANCE GAME

Slide 46

Slide 46 text

Object Attribute Memory

Slide 47

Slide 47 text

OAM

Slide 48

Slide 48 text

No content

Slide 49

Slide 49 text

This is the address in which Klonoa is stored on the memory

Slide 50

Slide 50 text

DMA3: 03000900 0600E000 80000400 DMA3: 03001100 0600E800 80000400 DMA3: 03004DB0 0600F000 80000200 DMA3: 03004800 07000000 8400003E

Slide 51

Slide 51 text

DMA3: 03000900 0600E000 80000400 DMA3: 03001100 0600E800 80000400 DMA3: 03004DB0 0600F000 80000200 DMA3: 03004800 07000000 8400003E We can see exactly the byte that writes on Klonoa’s object (03004800).

Slide 52

Slide 52 text

DMA3: 03000900 0600E000 80000400 DMA3: 03001100 0600E800 80000400 DMA3: 03004DB0 0600F000 80000200 DMA3: 03004800 07000000 8400003E We can see exactly the byte that writes on Klonoa’s OAM (03004800).

Slide 53

Slide 53 text

No content

Slide 54

Slide 54 text

No content

Slide 55

Slide 55 text

No content

Slide 56

Slide 56 text

1 2

Slide 57

Slide 57 text

No content

Slide 58

Slide 58 text

No content

Slide 59

Slide 59 text

No content

Slide 60

Slide 60 text

No content

Slide 61

Slide 61 text

No content

Slide 62

Slide 62 text

Here is where Y fixes Klonoa’s position Here is where which decides if should fix or not Klonoa’s position

Slide 63

Slide 63 text

No content

Slide 64

Slide 64 text

https://www.coranac.com/tonc/text/hardware.htm

Slide 65

Slide 65 text

https://www.coranac.com/tonc/text/hardware.htm

Slide 66

Slide 66 text

No content

Slide 67

Slide 67 text

Let’s find the tilemap on rom THE DAY I REVERSE ENGINEERED A GAMEBOY ADVANCE GAME

Slide 68

Slide 68 text

Cartridge Fast WRAM Display Slow WRAM VRAM > > > > The data flow

Slide 69

Slide 69 text

Cartridge Fast WRAM Display VRAM Slow WRAM > > > > Our research flow

Slide 70

Slide 70 text

swi 11h what?

Slide 71

Slide 71 text

Swi

Slide 72

Slide 72 text

SoftWare Interrupt

Slide 73

Slide 73 text

SoftWare Interrupt = Bios calls

Slide 74

Slide 74 text

BIOS is a firmware that is intended to initialise the physical components of the system In GBA, its BIOS exposes many functions often used in games, including data compression and decompression Each function has an associated numeric code, which must be used as a parameter in the SWI statement

Slide 75

Slide 75 text

Input: How division works on ARM Assembly swi 0x06 R0
 numerator R1
 denominator R0
 numerator / denominator R1
 numerator % denominator R3
 abs(numerator / denominator) Output:

Slide 76

Slide 76 text

No content

Slide 77

Slide 77 text

Huffman + lz77 = deflate

Slide 78

Slide 78 text

No content

Slide 79

Slide 79 text

No content

Slide 80

Slide 80 text

No content

Slide 81

Slide 81 text

No content

Slide 82

Slide 82 text

6E 6E 6E B0 B1 BD 77 AB B3 AB B3 7C 6E 6E 6E 6E 6E 6E 6E 6E 7C 6E 6E 6E 6E 7C 6E 6E

Slide 83

Slide 83 text

6E 6E 6E B0 B1 BD 77 AB B3 AB B3 7C 6E 6E 6E 6E 6E 6E 6E 6E 7C 6E 6E 6E 6E 7C 6E 6E 6E 6E 6E B0 B1 BD 77 AB B3 AB B3 7C 6E 6E 6E 6E 6E 6E 6E 6E 7C 6E 6E 6E 6E 7C 6E 6E

Slide 84

Slide 84 text

6E 6E 6E B0 B1 BD 77 AB B3 AB B3 7C 6E 6E 6E 6E 6E 6E 6E 6E 7C 6E 6E 6E 6E 7C 6E 6E 6E 6E 6E B0 B1 BD 77 AB B3 AB B3 7C 6E 6E 6E 6E 6E 6E 6E 6E 7C 6E 6E 6E 6E 7C 6E 6E =

Slide 85

Slide 85 text

Let’s paint the tilemap THE DAY I REVERSE ENGINEERED A GAMEBOY ADVANCE GAME

Slide 86

Slide 86 text

0x1A 0x1B 0x1C 0x1D 0x1E 0x1F

Slide 87

Slide 87 text

0x1A 0x1B 0x1C 0x1D 0x1E 0x1F 0x1A 0x1B 0x1C 0x1D 0x1E 0x1F 0x1A 0x1B 0x1C 0x1D 0x1E 0x1F 0x1A 0x1B 0x1C 0x1D 0x1E 0x1F

Slide 88

Slide 88 text

H · W = 25023
 H,W ∈ ℕ

Slide 89

Slide 89 text

x x x x a x x x x x x x x b x x x x I’m on tile a

Slide 90

Slide 90 text

x x x x a x x x x x x x x b x x x x I’m on tile a x x x x a x x x x x x x x b x x x x From the tile a to b there are 9 bytes (= 9 tiles), so the length of the tilemap is exactly 9

Slide 91

Slide 91 text

No content

Slide 92

Slide 92 text

Breakpoint here

Slide 93

Slide 93 text

…is located here This byte…

Slide 94

Slide 94 text

No content

Slide 95

Slide 95 text

As I change this byte…

Slide 96

Slide 96 text

…it reflects right here

Slide 97

Slide 97 text

No content

Slide 98

Slide 98 text

Changing these bytes…

Slide 99

Slide 99 text

…we drop Klonoa one level below

Slide 100

Slide 100 text

No content

Slide 101

Slide 101 text

Changing these bytes… …we found the B tile!

Slide 102

Slide 102 text

020085DB The length of the level is 420! - 02008437 = 1A4 (420)

Slide 103

Slide 103 text

https://github.com/oliver-moran/jimp

Slide 104

Slide 104 text

const Jimp = require('jimp') const { drop } = require('ramda') const fs = require('fs') const data = drop(3, fs.readFileSync('dump/level-2/tilemap'))

Slide 105

Slide 105 text

const getPixelColor = hexTile "# { if (hexTile === 0) { return 0x00000000 } return 0xFFFFFFFF }

Slide 106

Slide 106 text

new Jimp(300, 600, (err, image) "# { let x = 0 let y = 0 for (let i = 0; i < data.length; i += 1) { const value = data[i] x += 1 if (x === 300) { y += 1 x = 0 } let color = getPixelColor(value) image.setPixelColor(color, x, y) } image.write('image.png') })

Slide 107

Slide 107 text

No content

Slide 108

Slide 108 text

No content

Slide 109

Slide 109 text

No content

Slide 110

Slide 110 text

No content

Slide 111

Slide 111 text

No content

Slide 112

Slide 112 text

Let’s find and paint the objects THE DAY I REVERSE ENGINEERED A GAMEBOY ADVANCE GAME

Slide 113

Slide 113 text

No content

Slide 114

Slide 114 text

No content

Slide 115

Slide 115 text

DMA3: 03000900 0600E000 80000400 DMA3: 03001100 0600E800 80000400 DMA3: 03004DB0 0600F000 80000200 DMA3: 03004800 07000000 8400003E Update the OAM

Slide 116

Slide 116 text

DMA3: 03000900 0600E000 80000400 DMA3: 03001100 0600E800 80000400 DMA3: 03004DB0 0600F000 80000200 DMA3: 03004800 07000000 8400003E Update the OAM

Slide 117

Slide 117 text

DMA3: 03000900 0600E000 80000400 DMA3: 03001100 0600E800 80000400 DMA3: 03004DB0 0600F000 80000200 DMA3: 03004800 07000000 8400003E Update the OAM 0300480A:0300480B ✘

Slide 118

Slide 118 text

C

Slide 119

Slide 119 text

No content

Slide 120

Slide 120 text

No content

Slide 121

Slide 121 text

No content

Slide 122

Slide 122 text

Global OAM

Slide 123

Slide 123 text

> > > > 08051440 08003CD4 0800B602 0800B634 0804505C

Slide 124

Slide 124 text

No content

Slide 125

Slide 125 text

ROM OAM

Slide 126

Slide 126 text

No content

Slide 127

Slide 127 text

No content

Slide 128

Slide 128 text

Global OAM OAM > ROM OAM >

Slide 129

Slide 129 text

No content

Slide 130

Slide 130 text

ROM OAM of the first level 08367700 083686B0 08369380 ROM OAM of the third level ROM OAM of the second level Hole Hole . . .

Slide 131

Slide 131 text

const [ xFirstPosition, yFirstPosition, xSecondPosition, ySecondPosition, xThirdPosition, yThirdPosition, xFourthPosition, yFourthPosition, xFifthPosition, yFifthPosition, kind, ] = qunpack.unpack('v2 x4 v2 x4 v2 x4 v2 x4 v2 x5 c', bytes);

Slide 132

Slide 132 text

const [ xFirstPosition, yFirstPosition, xSecondPosition, ySecondPosition, xThirdPosition, yThirdPosition, xFourthPosition, yFourthPosition, xFifthPosition, yFifthPosition, kind, ] = qunpack.unpack('v2 x4 v2 x4 v2 x4 v2 x4 v2 x5 c', bytes); ✘

Slide 133

Slide 133 text

const { xStage1, yStage1, xStage2, yStage2, xStage3, yStage3, xStage4, yStage4, xStage5, yStage5, kind, } = binary.parse(memory) .word16lu('xStage1').word16lu('yStage1') .skip(4) .word16lu('xStage2').word16lu('yStage2') .skip(4) .word16lu('xStage3').word16lu('yStage3') .skip(4) .word16lu('xStage4').word16lu('yStage4') .skip(4) .word16lu('xStage5').word16lu('yStage5') .skip(5) .word8lu('kind') .vars

Slide 134

Slide 134 text

No content

Slide 135

Slide 135 text

let’s see the project THE DAY I REVERSE ENGINEERED A GAMEBOY ADVANCE GAME

Slide 136

Slide 136 text

Coding THE DAY I REVERSE ENGINEERED A GAMEBOY ADVANCE GAME

Slide 137

Slide 137 text

soooo…

Slide 138

Slide 138 text

Stack

Slide 139

Slide 139 text

React.js

Slide 140

Slide 140 text

Webpack

Slide 141

Slide 141 text

Ramda.js

Slide 142

Slide 142 text

architecture

Slide 143

Slide 143 text

✂ Brush Scissors

Slide 144

Slide 144 text

klo-gba.js/scissors/src/visions/

Slide 145

Slide 145 text

export default { rom: { tilemap: [0x1B27FC, 0x1B36F3], oam: [0xE2B90, 0xE2F59], portals: [0xD48C8, 0xD48EF], }, tilemap: { totalStages: 3, height: 60, width: 420, scheme: [ { name: 'grass', ids: [0x7D, 0x80, 0x81, 0x82, 0x8E, 0x8F, 0x90], },

Slide 146

Slide 146 text

export default { rom: { tilemap: [0x1B27FC, 0x1B36F3], oam: [0xE2B90, 0xE2F59], portals: [0xD48C8, 0xD48EF], }, tilemap: { totalStages: 3, height: 60, width: 420, scheme: [ { name: 'grass', ids: [0x7D, 0x80, 0x81, 0x82, 0x8E, 0x8F, 0x90], },

Slide 147

Slide 147 text

export default { rom: { tilemap: [0x1B27FC, 0x1B36F3], oam: [0xE2B90, 0xE2F59], portals: [0xD48C8, 0xD48EF], }, tilemap: { totalStages: 3, height: 60, width: 420, scheme: [ { name: 'grass', ids: [0x7D, 0x80, 0x81, 0x82, 0x8E, 0x8F, 0x90], },

Slide 148

Slide 148 text

{ name: 'rock', ids: [0x54, 0x53, 0x55, 0x56, 0x57, 0x58, 0x59, }, { name: 'darkRock', ids: [0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, }, { name: 'wood', ids: [0x52, 0x94, 0x98, 0x99, 0x9A, 0x9B, 0x9D, }, { name: 'bridgeRope', ids: [0x04, 0x05, 0x0B, 0x0C, 0x11, 0x13, 0x14,

Slide 149

Slide 149 text

{ name: 'spike', ids: [0x3D], }, ], },

Slide 150

Slide 150 text

Web assembly

Slide 151

Slide 151 text

Tilemap compressed Old C code to uncompress it Decompressed Tilemap > >

Slide 152

Slide 152 text

Tilemap compressed Old C code to uncompress it Decompressed Tilemap > > Can’t run C code on browser!

Slide 153

Slide 153 text

Tilemap compressed Old C code to uncompress it Decompressed Tilemap > >

Slide 154

Slide 154 text

Tilemap compressed Old C code to uncompress it Decompressed Tilemap > > >Emscripten >WebAssembly

Slide 155

Slide 155 text

huffman.c lzss.c > > Emscripten huffman.js lzss.js huffman.wasm lzss.wasm +

Slide 156

Slide 156 text

class HuffmanDecodeError extends Error { constructor (e) { super(`Error when tried to use huffman decoder: ${e}`) this.name = 'HuffmanDecodeError' } } huffmanModule.onRuntimeInitialized = () "# {} const huffmanDecode = (buffer) "# { FS.writeFile('file', buffer)

Slide 157

Slide 157 text

class HuffmanDecodeError extends Error { constructor (e) { super(`Error when tried to use huffman decoder: ${e}`) this.name = 'HuffmanDecodeError' } } huffmanModule.onRuntimeInitialized = () "# {} const huffmanDecode = (buffer) "# { FS.writeFile('file', buffer)

Slide 158

Slide 158 text

const huffmanDecode = (buffer) "# { FS.writeFile('file', buffer) huffmanModule._HUF_Decode() try { return huffmanModule.FS.readFile('file', { encoding: 'binary' }) } catch (e) { throw new HuffmanDecodeError(e) } }

Slide 159

Slide 159 text

function docker_run_emscripten { local filename="$1" echo "Compiling $filename$$." docker run \ --rm -it \ -v $(pwd)/scissors/src/wasm:/src \ trzeci/emscripten \ emcc -s WASM=1 -s ALLOW_MEMORY_GROWTH=1 -s MODULARIZE=1 -s EXTRA_EXPORTED_RUNTIME_METHODS=[\"FS\"] -s EXPORT_NAME=\"$filename\" -o ./$filename.js $filename.c } docker_run_emscripten huffman docker_run_emscripten lzss

Slide 160

Slide 160 text

function docker_run_emscripten { local filename="$1" echo "Compiling $filename$$." docker run \ --rm -it \ -v $(pwd)/scissors/src/wasm:/src \ trzeci/emscripten \ emcc -s WASM=1 -s ALLOW_MEMORY_GROWTH=1 -s MODULARIZE=1 -s EXTRA_EXPORTED_RUNTIME_METHODS=[\"FS\"] -s EXPORT_NAME=\"$filename\" -o ./$filename.js $filename.c } docker_run_emscripten huffman docker_run_emscripten lzss

Slide 161

Slide 161 text

const extractFullTilemap = (romBuffer, [addressStart, addressEnd]) "# romBuffer.slice(addressStart, addressEnd) |> huffmanDecode |> lzssDecode

Slide 162

Slide 162 text

Tilemap

Slide 163

Slide 163 text

No content

Slide 164

Slide 164 text

✔ Display tiles and OAM ✔ Allow the user to edit it

Slide 165

Slide 165 text

https://github.com/konvajs/konva

Slide 166

Slide 166 text

No content

Slide 167

Slide 167 text

1st load: ˜3 seconds! 2nd load: ˜13 seconds!

Slide 168

Slide 168 text

After some React.js performance work…

Slide 169

Slide 169 text

1st load

Slide 170

Slide 170 text

1st load ˜1.8 seconds!

Slide 171

Slide 171 text

1st load 2nd load

Slide 172

Slide 172 text

1st load 2nd load ˜3.6 seconds!

Slide 173

Slide 173 text

After switching from Canvas to WebGL…

Slide 174

Slide 174 text

1st load

Slide 175

Slide 175 text

1st load ˜1.6 seconds!

Slide 176

Slide 176 text

1st load ˜1.6 seconds! 2nd load

Slide 177

Slide 177 text

1st load ˜1.6 seconds! 2nd load ˜2.8 seconds!

Slide 178

Slide 178 text

After doing more optimizations on WebGL…

Slide 179

Slide 179 text

1st load

Slide 180

Slide 180 text

1st load ˜625 ms!

Slide 181

Slide 181 text

1st load 2nd load ˜625 ms!

Slide 182

Slide 182 text

1st load 2nd load ˜536 ms! ˜625 ms!

Slide 183

Slide 183 text

1st load: ˜3 seconds! 2nd load: ˜13 seconds! Perf recap: No one is gonna play with this

Slide 184

Slide 184 text

1st load: ˜3 1.8 seconds! 2nd load: ˜13 3.6 seconds! Perf recap: Removing wasted renders and other React optimisation stuff.

Slide 185

Slide 185 text

1st load: ˜3 1.8 1.6 seconds! 2nd load: ˜13 3.6 2.8 seconds! Perf recap: Canvas → WebGL

Slide 186

Slide 186 text

1st load: ˜3 1.8 1.6 0.625 seconds! 2nd load: ˜13 3.6 2.8 0.536 seconds! Perf recap: React → WebGL

Slide 187

Slide 187 text

Saving the new tilemap

Slide 188

Slide 188 text

Each level is stored continually in the memory First Level Second Level Third Level

Slide 189

Slide 189 text

First Level Second Level Third Level > Changes in the first level

Slide 190

Slide 190 text

First Level Second Level Third Level > Customised First Level > Changes in the first level

Slide 191

Slide 191 text

Second Level Third Level First Level Second Level Third Level > Customised First Level > Changes in the first level

Slide 192

Slide 192 text

Second Level Third Level First Level Second Level Third Level > Customised First Level > Changes in the first level

Slide 193

Slide 193 text

No content

Slide 194

Slide 194 text

ARM Thumb Faster to execute Instructions demands less memory Can perform instructions more complex

Slide 195

Slide 195 text

The switch between ARM and Thumb must be done by bx instruction. And this instruction only can read a register

Slide 196

Slide 196 text

Instructions to load a level . . . . . . . . . Very big hole space at the end of cartridge First Level__ Second Level__ Third Level__ 081B27FC 081B3E5C 081B50AC Instructions to load a level

Slide 197

Slide 197 text

First Level__ Second Level__ Third Level__ . . . . . . . . . 081B27FC 081B3E5C 081B50AC Instructions to load a level Customised First Level__ Customised level loader Constant addresses map table Hole Customised Second Level__ Hole Customised Third Level__ Hole Hole 08367700 083686B0 08369380

Slide 198

Slide 198 text

Instructions to load a level 08367620 FC 27 1B 08 08367624 00 77 36 08 08367628 5C 3E 1B 08 0836762C B0 86 36 08 08367620 AC 50 1B 08 08367634 80 93 36 08 First Level__ Second Level__ Third Level__ . . . . . . . . . 081B27FC 081B3E5C 081B50AC Customised First Level__ Customised level loader Constant addresses map table Hole Customised Second Level__ Hole Customised Third Level__ Hole Hole 08367700 083686B0 08369380

Slide 199

Slide 199 text

Instructions to load a level 08367620 FC 27 1B 08 08367624 00 77 36 08 08367628 5C 3E 1B 08 0836762C B0 86 36 08 08367620 AC 50 1B 08 08367634 80 93 36 08 First Level__ Second Level__ Third Level__ . . . . . . . . . 081B27FC 081B3E5C 081B50AC Customised First Level__ Customised level loader Constant addresses map table Hole Customised Second Level__ Hole Customised Third Level__ Hole Hole 08367700 083686B0 08369380

Slide 200

Slide 200 text

Instructions to load a level 08367620 FC 27 1B 08 08367624 00 77 36 08 08367628 5C 3E 1B 08 0836762C B0 86 36 08 08367620 AC 50 1B 08 08367634 80 93 36 08 First Level__ Second Level__ Third Level__ . . . . . . . . . 081B27FC 081B3E5C 081B50AC Customised First Level__ Customised level loader Constant addresses map table Hole Customised Second Level__ Hole Customised Third Level__ Hole Hole 08367700 083686B0 08369380

Slide 201

Slide 201 text

Instructions to load a level 08367620 FC 27 1B 08 08367624 00 77 36 08 08367628 5C 3E 1B 08 0836762C B0 86 36 08 08367620 AC 50 1B 08 08367634 80 93 36 08 First Level__ Second Level__ Third Level__ . . . . . . . . . 081B27FC 081B3E5C 081B50AC Customised First Level__ Customised level loader Constant addresses map table Hole Customised Second Level__ Hole Customised Third Level__ Hole Hole 08367700 083686B0 08369380

Slide 202

Slide 202 text

Instructions to load a level (patched) First Level__ Second Level__ Third Level__ . . . . . . . . . 081B27FC 081B3E5C 081B50AC Customised First Level__ Customised level loader Constant addresses map table Hole Customised Second Level__ Hole Customised Third Level__ Hole Hole 08367700 083686B0 08369380 Original loader Patched loader 08043B0A mov r4,r0 08043B0C bl 08367610h 08043B10 bl 0805143Ch 08043B0A mov r4,r0 08043B0C add r0,r5,4 08043B0E mov r1,r4 08043B10 bl 0805143Ch

Slide 203

Slide 203 text

Instructions to load a level (patched) First Level__ Second Level__ Third Level__ . . . . . . . . . 081B27FC 081B3E5C 081B50AC Customised First Level__ Customised level loader Constant addresses map table Hole Customised Second Level__ Hole Customised Third Level__ Hole Hole 08367700 083686B0 08369380 R0 is the pointer to where is the tilemap that will load Original loader Patched loader 08043B0A mov r4,r0 08043B0C bl 08367610h 08043B10 bl 0805143Ch 08043B0A mov r4,r0 08043B0C add r0,r5,4 08043B0E mov r1,r4 08043B10 bl 0805143Ch

Slide 204

Slide 204 text

Instructions to load a level (patched) First Level__ Second Level__ Third Level__ . . . . . . . . . 081B27FC 081B3E5C 081B50AC Customised First Level__ Customised level loader Constant addresses map table Hole Customised Second Level__ Hole Customised Third Level__ Hole Hole 08367700 083686B0 08369380 Original loader Patched loader 08043B0A mov r4,r0 08043B0C bl 08367610h 08043B10 bl 0805143Ch 08043B0A mov r4,r0 08043B0C add r0,r5,4 08043B0E mov r1,r4 08043B10 bl 0805143Ch

Slide 205

Slide 205 text

Instructions to load a level (patched) First Level__ Second Level__ Third Level__ . . . . . . . . . 081B27FC 081B3E5C 081B50AC Customised First Level__ Customised level loader Constant addresses map table Hole Customised Second Level__ Hole Customised Third Level__ Hole Hole 08367700 083686B0 08369380 08367610 mov r0,r15 08367612 add r0,3Ch 08367614 bx r0

Slide 206

Slide 206 text

Instructions to load a level (patched) First Level__ Second Level__ Third Level__ . . . . . . . . . 081B27FC 081B3E5C 081B50AC Customised First Level__ Customised level loader Constant addresses map table Hole Customised Second Level__ Hole Customised Third Level__ Hole Hole 08367700 083686B0 08369380 08367650 add r0,r4,4h 08367654 ldr r4,[r15,#-3Ch] 08367658 cmp r0,r4 0836765C ldreq r0,[r15,#-40h] 08367654 ldr r4,[r15,#-40h] 08367658 cmp r0,r4 0836765C ldreq r0,[r15,#-44h] 08367654 ldr r4,[r15,#-44h] 08367658 cmp r0,r4 0836765C ldreq r0,[r15,#-48h] 08367660 mov r4,r1 08367664 bx r14

Slide 207

Slide 207 text

Instructions to load a level (patched) First Level__ Second Level__ Third Level__ . . . . . . . . . 081B27FC 081B3E5C 081B50AC Customised First Level__ Customised level loader Constant addresses map table Hole Customised Second Level__ Hole Customised Third Level__ Hole Hole 08367700 083686B0 08369380 08367650 add r0,r4,4h 08367654 ldr r4,[r15,#-3Ch] 08367658 cmp r0,r4 0836765C ldreq r0,[r15,#-40h] 08367654 ldr r4,[r15,#-40h] 08367658 cmp r0,r4 0836765C ldreq r0,[r15,#-44h] 08367654 ldr r4,[r15,#-44h] 08367658 cmp r0,r4 0836765C ldreq r0,[r15,#-48h] 08367660 mov r4,r1 08367664 bx r14

Slide 208

Slide 208 text

Instructions to load a level (patched) First Level__ Second Level__ Third Level__ . . . . . . . . . 081B27FC 081B3E5C 081B50AC Customised First Level__ Customised level loader Constant addresses map table Hole Customised Second Level__ Hole Customised Third Level__ Hole Hole 08367700 083686B0 08369380 08367650 add r0,r4,4h 08367654 ldr r4,[r15,#-3Ch] 08367658 cmp r0,r4 0836765C ldreq r0,[r15,#-40h] 08367654 ldr r4,[r15,#-40h] 08367658 cmp r0,r4 0836765C ldreq r0,[r15,#-44h] 08367654 ldr r4,[r15,#-44h] 08367658 cmp r0,r4 0836765C ldreq r0,[r15,#-48h] 08367660 mov r4,r1 08367664 bx r14

Slide 209

Slide 209 text

Instructions to load a level (patched) First Level__ Second Level__ Third Level__ . . . . . . . . . 081B27FC 081B3E5C 081B50AC Customised First Level__ Customised level loader Constant addresses map table Hole Customised Second Level__ Hole Customised Third Level__ Hole Hole 08367700 083686B0 08369380 08367650 add r0,r4,4h 08367654 ldr r4,[r15,#-3Ch] 08367658 cmp r0,r4 0836765C ldreq r0,[r15,#-40h] 08367654 ldr r4,[r15,#-40h] 08367658 cmp r0,r4 0836765C ldreq r0,[r15,#-44h] 08367654 ldr r4,[r15,#-44h] 08367658 cmp r0,r4 0836765C ldreq r0,[r15,#-48h] 08367660 mov r4,r1 08367664 bx r14

Slide 210

Slide 210 text

Instructions to load a level (patched) First Level__ Second Level__ Third Level__ . . . . . . . . . 081B27FC 081B3E5C 081B50AC Customised First Level__ Customised level loader Constant addresses map table Hole Customised Second Level__ Hole Customised Third Level__ Hole Hole 08367700 083686B0 08369380 08367650 add r0,r4,4h 08367654 ldr r4,[r15,#-3Ch] 08367658 cmp r0,r4 0836765C ldreq r0,[r15,#-40h] 08367654 ldr r4,[r15,#-40h] 08367658 cmp r0,r4 0836765C ldreq r0,[r15,#-44h] 08367654 ldr r4,[r15,#-44h] 08367658 cmp r0,r4 0836765C ldreq r0,[r15,#-48h] 08367660 mov r4,r1 08367664 bx r14

Slide 211

Slide 211 text

1. Redirect to the patched code 2. Check if the R0 is on the table 3. If yes, load the associated value 4. Return to the original loader

Slide 212

Slide 212 text

No content

Slide 213

Slide 213 text

No content

Slide 214

Slide 214 text

No content

Slide 215

Slide 215 text

No content

Slide 216

Slide 216 text

Result THE DAY I REVERSE ENGINEERED A GAMEBOY ADVANCE GAME

Slide 217

Slide 217 text

No content

Slide 218

Slide 218 text

No content

Slide 219

Slide 219 text

No content

Slide 220

Slide 220 text

No content

Slide 221

Slide 221 text

No content

Slide 222

Slide 222 text

THE Future THE DAY I REVERSE ENGINEERED A GAMEBOY ADVANCE GAME

Slide 223

Slide 223 text

No content

Slide 224

Slide 224 text

No content

Slide 225

Slide 225 text

WE ARE... THE DAY I REVERSE ENGINEERED A GAMEBOY ADVANCE GAME

Slide 226

Slide 226 text

MACABEUS macabeus ____ www.macalogs.com.br _ _ Software Engineer, full-stack @CASAFARI Always creating crazy projects

Slide 227

Slide 227 text

MATHEUS ALBUQUERQUE YTHECOMBINATOR www.ythecombinator.space [email protected] Software Engineer, Front- End @STRV addicted to emojis, memes and beer

Slide 228

Slide 228 text

Benjamin Stauffer kcowolf TRANSLATOR

Slide 229

Slide 229 text

Raul peres behance.net/Kniksis illustrator

Slide 230

Slide 230 text

This talk THE DAY I REVERSE ENGINEERED A GAMEBOY ADVANCE GAME

Slide 231

Slide 231 text

http://bit.ly/balccon-gba-keynote

Slide 232

Slide 232 text

http://bit.ly/balccon-gba-code

Slide 233

Slide 233 text

http://bit.ly/balccon-gba-posts

Slide 234

Slide 234 text

No content

Slide 235

Slide 235 text

We got stickers!

Slide 236

Slide 236 text

Hvala THANKS @ythecombinator AND @macabeus