• Our software update is now concluded. You will need to reset your password to log in. In order to do this, you will have to click "Log in" in the top right corner and then "Forgot your password?".
  • Welcome to PokéCommunity! Register now and join one of the best fan communities on the 'net to talk Pokémon and more! We are not affiliated with The Pokémon Company or Nintendo.

Research: The Pokemon Ruby/Sapphire Dissassembly/Decompilation Project

182
Posts
7
Years
  • Age 34
  • Seen today
This is just awesome, but since I'm a little noobish in this type of things I'll ask anyways:

What does the disassembly mean for the normal rom-hacker?

When this is finished, engine upgrades, graphics, pokemon and etc will be easier to create since It's done from zero?
Meaning that you get the parts of the new code, put in the original one and compile and that's it?



I know this are just "bad" questions but I've never seen a thing like this before.

Keep this project going guys!
 
24
Posts
8
Years
  • Age 31
  • Seen Nov 3, 2018
This is just awesome, but since I'm a little noobish in this type of things I'll ask anyways:

What does the disassembly mean for the normal rom-hacker?

When this is finished, engine upgrades, graphics, pokemon and etc will be easier to create since It's done from zero?
Meaning that you get the parts of the new code, put in the original one and compile and that's it?



I know this are just "bad" questions but I've never seen a thing like this before.

Keep this project going guys!

Ok, time for a practical example.

Consider implementing instant text in Ruby/Sapphire. Emerald supports text speed 0, but R/S does not, so you cant just change speed to 0. If you only had the assembly, you would have to make quite the number of changes to support it. Specifically, InterpretText needs to be in a loop and conditionally break when it is the end of the string. This means you need to redirect a bunch of functions and handwrite the new assembly.

Now, lets look at what you need to do with a fully matching C file available.

Here is Ruby/Sapphire's normal InterpretText function in C:
Code:
static u8 InterpretText(struct Window *win)
{
    u8 c = win->text[win->textIndex++];

    switch (c)
    {
    case 0xFF:
        ClipRight(win);
        win->state = WIN_STATE_END;
        return 0;
    case 0xFD:
        win->state = WIN_STATE_PLACEHOLDER;
        return 2;
    case 0xFE:
        ClipRight(win);
        win->state = WIN_STATE_NEWLINE;
        return 2;
    case 0xFB:
        DrawInitialDownArrow(win);
        win->state = WIN_STATE_PARAGRAPH;
        return 2;
    case 0xFA:
        DrawInitialDownArrow(win);
        win->state = WIN_STATE_NEWLINE_WAIT;
        return 2;
    case 0xFC:
        return HandleExtCtrlCode(win);
    }

    sPrintGlyphFuncs[win->textMode](win, c);
    return 1;
}

Adding Instant text support is as simple as:
Code:
 static u8 InterpretText(struct Window *win)
 {
[COLOR="Red"]-    u8 c = win->text[win->textIndex++];[/COLOR]
[COLOR="SeaGreen"]+    u8 instantText = gSaveBlock2.speedchoiceConfig.instantText; // part of my speedchoice hack. ignore it for the example[/COLOR].
 
 
[COLOR="SeaGreen"]+    while(1)
+    {
+        u8 c = win->text[win->textIndex++];
+[/COLOR]
     switch (c)
     {
     case 0xFF:
         ClipRight(win);
         win->state = WIN_STATE_END;
         return 0;
     case 0xFD:
         win->state = WIN_STATE_PLACEHOLDER;
         return 2;
     case 0xFE:
         ClipRight(win);
         win->state = WIN_STATE_NEWLINE;
         return 2;
     case 0xFB:
         DrawInitialDownArrow(win);
         win->state = WIN_STATE_PARAGRAPH;
         return 2;
     case 0xFA:
         DrawInitialDownArrow(win);
         win->state = WIN_STATE_NEWLINE_WAIT;
         return 2;
     case 0xFC:
         return HandleExtCtrlCode(win);
[COLOR="Red"]-    }[/COLOR]
[COLOR="red"]-[/COLOR]
[COLOR="SeaGreen"]+        default:[/COLOR]
     sPrintGlyphFuncs[win->textMode](win, c);
[COLOR="SeaGreen"]+[/COLOR]
[COLOR="SeaGreen"]+        if(instantText == ON)[/COLOR]
[COLOR="SeaGreen"]+            break;[/COLOR]
[COLOR="SeaGreen"]+        else[/COLOR]
[COLOR="SeaGreen"]     return 1;[/COLOR]
[COLOR="SeaGreen"]+        }[/COLOR]
[COLOR="SeaGreen"]+    }[/COLOR]
 }

...and recompile the ROM to recalculate all the pointers.

Adding a new feature is as simple as that. There is virtually NO mangling with assembly anymore!

And that's whats really important about this project. When you have a decompiled C base that can recompile into a ROM with 0 issues (unlike C injection, which still requires you redirect stuff) this can rebuild without issues since it is the original ROM dissassembled.

Here's a video showing off the change, although its rather old:

https://youtu.be/5YG0uhWqvxI

The two side effects in the video (slight slowdown sometimes and player name printed incorrectly) were as a result of older code not working. The above C works and wouldnt have those issues.

You could also change part of scrcmd.c (waitbutton) to allow holdKeys rather than newKeys so you could also have a Hold to Mash feature with that instant text.
 
Last edited by a moderator:
182
Posts
7
Years
  • Age 34
  • Seen today
Spoiler:

This is awesome. Thank you for the example. I can't wait to see how this project goes.
 
1
Posts
6
Years
  • Age 24
  • Seen Sep 23, 2017
Hello, as I think ROM, once you replace the toolkit by the toolkit and put "make" jump an error
untitled.PNG
 
Last edited:
24
Posts
8
Years
  • Age 31
  • Seen Nov 3, 2018
Hello, as I think ROM, once you replace the toolkit by the toolkit and put "make" jump an error
untitled.PNG

I made a guide here.

Although, I should give an update regarding this project:

Ahem. The whole reason most of the pret team was decompiling ruby was so that access to emerald was much easier with a smaller but established codebase.

That means that: As of recent, a majority of pret members have started migrating to emerald, so focus is now formally shifting from pokeruby to pokeemerald. Once all of the baserom calls are gone from pokeemerald, I will probably make a new topic and update the guide.
 
Last edited:
853
Posts
3
Years
  • Age 33
  • Seen Nov 9, 2023
Questions

What is decompilation you ask?
Decompilation is the process of taking compiled assembly and running it backwards through the original compiler in order to get the original programming that was written by Game Freak. In this case, starting with generation 3 (up to 5), the Pokemon games were written in C and compiled into the console-specific assembly that you see on all ROMs.


Why use this over standard binary hacking methods? Well, for one, editing C is 1000x easier than assembly. You can implement things on a source level so much quicker than with standard script editor and map editor tools. Take Instant text for example, which in R/S text speed 0 does not produce an instant text effect, where as in Emerald it does. Implementing support in R/S via asm edits would probably require rewriting most of the text functions in the text.c area block of assembly, but via the C file, it's only a few lines of changes.

So is there no effective difference between decomp hacking and binary hacking, other than decomp being easier to read and change, otherwise you can do all the same things with asm?

And if its only the text and windows that can't decomp well, can I still decomp other gens fire red and up, and just edit other mechanics, without changing text and windows recompile with only the part I meant to change being changed and then make any other changes in binary.

And how do you acess decomp changes anyway, i know for binary i have to use callasm in my scripts?
 
Back
Top