# Decompiling

Code starts out in `asm/`. When decompiled to C, it goes into `src/`. The goal is to decompile all the code.

Some of the code in `asm/` is handwritten assembly. It can't and shouldn't be decompiled. It's already commented, so there's no further work to do on these files.
* `asm/crt0.s`
* `asm/libagbsyscall.s`
* `asm/libgcnmultiboot.s`
* `asm/m4a_1.s`
* `asm/m4a_3.s`

The rest of the `.s` files in `asm/` are fair game.

The basic decompilation process is:
* Choose a file in `asm/`, i.e. `asm/x.s`. Create a C file called `src/x.c`.
* Translate the first function in `asm/x.s` to C in `src/x.c`.
* `make`, and tweak the function until it matches.
* Clean up the code and comment.
* Repeat for each function until `asm/x.s` is empty.


# For example, let's decompile `asm/cable_car.s`.


## 1. Create `src/cable_car.c`

```c
#include "global.h"
```

`global.h` contains typedefs for GBA programming and more.
It must be the first include in the file. Other includes will assume you have included it.


## 2. Include it in the rom

Include `src/cable_car.c` in the rom by adding `src/cable_car.o` to `ld_script.txt`:
```diff
         asm/battle_message.o(.text);
         asm/choose_party.o(.text);
+        src/cable_car.o(.text);
         asm/cable_car.o(.text);
         asm/roulette_util.o(.text);
```
Do not remove `asm/cable_car.o(.text)`. We want both `src/cable_car.c` and `asm/cable_car.s` in the rom.


## 3. Translate the function to C

Take the first function in `asm/cable_car.s`. Either comment it out or remove it, whichever is easier.

```asm
	thumb_func_start sub_81231EC
sub_81231EC: @ 81231EC
	push {r4,lr}
	lsls r0, 24
	lsrs r4, r0, 24
	ldr r0, _08123210 @ =gPaletteFade
	ldrb r1, [r0, 0x7]
	movs r0, 0x80
	ands r0, r1
	cmp r0, 0
	bne _0812320A
	ldr r0, _08123214 @ =sub_8123244
	bl SetMainCallback2
	adds r0, r4, 0
	bl DestroyTask
_0812320A:
	pop {r4}
	pop {r0}
	bx r0
	.align 2, 0
_08123210: .4byte gPaletteFade
_08123214: .4byte sub_8123244
	thumb_func_end sub_81231EC
```
---

Then, start translating the code to `src/cable_car.c`, bit by bit:

```asm
	lsls r0, 24
	lsrs r4, r0, 24
```
```c
void sub_81231EC(u8 r4) {
```
---
```asm
	ldr r0, _08123210 @ =gPaletteFade
	ldrb r1, [r0, 0x7]
	movs r0, 0x80
	ands r0, r1
```
```c
	r0 = (u8 *)(&gPaletteFade + 7) & 0x80;
```
---

---
```asm
	cmp r0, 0
	bne _0812320A
```
```c
	if (!r0) {
```
---
```asm
	ldr r0, _08123214 @ =sub_8123244
	bl SetMainCallback2
```
```c
		SetMainCallback2(&sub_8123244);
```
---
```asm
	adds r0, r4, 0
	bl DestroyTask
```
```c
		DestroyTask(r4);
```
---
```asm
_0812320A:
```
```c
	}
```
---
```asm
	pop {r4}
	pop {r0}
	bx r0
```
```c
	return;
```
The type signature of the function depends on the return type.
* `bx r0`: `void`
* `bx r1`: `*`
* `bx lr`: `void`, `*`

You will need to look at the caller and the function prologue to determine the exact type if not void.

Since it used `bx r0`, it's `void` for sure.

---

Putting it all together, we get:
```c
void sub_81231EC(u8 r4) {
	r0 = (u8 *)(&gPaletteFade + 7) & 0x80;
	if (!r0) {
		SetMainCallback2(&sub_8123244);
		DestroyTask(r4);
	}
	return;
}
```


## 4. Simplify and document

This line doesn't look quite right.

```c
	r0 = (u8 *)(&gPaletteFade + 7) & 0x80;
```

What is `gPaletteFade`? You can find out where stuff is with `git grep`:

```sh
git grep "gPaletteFade" include/
```
```grep
include/palette.h:extern struct PaletteFadeControl gPaletteFade;
```

So it's a struct called `PaletteFadeControl`. Let's look in `palette.h`:

```c
struct PaletteFadeControl
{
    u32 multipurpose1;
    u8 delayCounter:6;
    u16 y:5; // blend coefficient
    u16 targetY:5; // target blend coefficient
    u16 blendColor:15;
    u16 active:1;
    u16 multipurpose2:6;
    u16 yDec:1; // whether blend coefficient is decreasing
    u16 bufferTransferDisabled:1;
    u16 mode:2;
    u16 shouldResetBlendRegisters:1;
    u16 hardwareFadeFinishing:1;
    u16 softwareFadeFinishingCounter:5;
    u16 softwareFadeFinishing:1;
    u16 objPaletteToggle:1;
    u8 deltaY:4; // rate of change of blend coefficient
};
```
---

What's the 7th byte in this struct?
```c
    u32 multipurpose1; // 0-3
    u8 delayCounter:6; // 4
    u16 y:5;           // 5
    u16 targetY:5;     // 5-6
    u16 blendColor:15; // 7
    u16 active:1;      // 7
```

Byte 7 has both `.blendColor` and `.active`.

---

Okay, what's 0x80 mean? It's `0b10000000`, which is the highest bit in a byte.

`.active` comes after, which means it's higher, but it's also only one bit, so it's a safe bet.

```c
	r0 = gPaletteFade.active;
```

Much better.

---

```c
void sub_81231EC(u8 r4) {
	r0 = gPaletteFade.active;
	if (!r0) {
		SetMainCallback2(&sub_8123244);
		DestroyTask(r4);
	}
	return;
}
```

Now the temp variable `r0` is a little pointless. We can simplify this to:

```c
void sub_81231EC(u8 taskId) {
	if (!gPaletteFade.active) {
		SetMainCallback2(&sub_8123244);
		DestroyTask(taskId);
	}
}
```

Looks done, right?
This function is pretty simple, so it doesn't need any comments right now.

But what about `sub_8123244`? It's still not obvious what that function does. We can find out by decompiling it later.


## 5. Build

```sh
make
```
```gcc
src/cable_car.c: In function `sub_81231EC':
src/cable_car.c:4: `gPaletteFade' undeclared (first use in this function)
src/cable_car.c:4: (Each undeclared identifier is reported only once for each function it appears in.)
src/cable_car.c:5: warning: implicit declaration of function `SetMainCallback2'
src/cable_car.c:5: `sub_8123244' undeclared (first use in this function)
src/cable_car.c:6: warning: implicit declaration of function `DestroyTask'
```

We got some errors. We need to tell the compiler what `gPaletteFade`, `SetMainCallback2`, `sub_8123244`, and `DestroyTask` are.

We know `gPaletteFade` is from `palette.h`. We can do the same with the others. Declare them above the function:
```c
#include "palette.h"
#include "main.h"
#include "task.h"
```
The odd one out is `sub_8123244`, which is in `asm/cable_car.s`! What then?
```c
void sub_8123244();
```
Normally, we would do `extern void sub_8123244();`, but it won't be `extern` when we're done this file.

---

Now our file looks like this:
```c
#include "global.h"
#include "palette.h"
#include "main.h"
#include "task.h"

void sub_8123244();

void sub_81231EC(u8 taskId) {
	if (!gPaletteFade.active) {
		SetMainCallback2(&sub_8123244);
		DestroyTask(taskId);
	}
}
```

---

Build again, and we get:
```sh
make
```
```sha1sum
pokeruby.gba: OK
```

This means the function matches. Congratulations!

---

If it doesn't match, you will get:
```sha1sum
pokeruby.gba: FAILED
sha1sum: WARNING: 1 computed checksum did NOT match
```

---

If you forgot to remove the function from `asm/cable_car.s`, you will get this error:
```gcc
asm/cable_car.o: In function `sub_81231EC':
(.text+0x0): multiple definition of `sub_81231EC'
src/cable_car.o:(.text+0x0): first defined here
```


## 6. Repeat until `asm/cable_car.s` is empty

Once you're done, you can delete `asm/cable_car.s`, and remove it from `ld_script.txt`.

