1

I follow the free software implementation of OpenRCT2 from the beggining (when it was in other repository).

And the first commits are a bunch of C files, these files has a lot of asm blocks of code inline of C, and there were a lot of C functions with automatic names.

I don't know the tool. I was trying with Ghidra and Cutter but it is not a "correct" C that it can not is compiled it.

A example of code from first commits of OpenRCT2:

// rct2: 0x00683499
void rct2_init_directories()
{
    strcpy(RCT2_ADDRESS(RCT2_ADDRESS_APP_PATH, char), "C:\\Program Files (x86)\\Infogrames\\RollerCoaster Tycoon 2");
strcpy(RCT2_ADDRESS(RCT2_ADDRESS_APP_PATH_SLASH, char), RCT2_ADDRESS(RCT2_ADDRESS_APP_PATH, char));
strcat(RCT2_ADDRESS(RCT2_ADDRESS_APP_PATH_SLASH, char), "\\");

strcpy(RCT2_ADDRESS(RCT2_ADDRESS_SAVED_GAMES_PATH, char), RCT2_ADDRESS(RCT2_ADDRESS_APP_PATH, char));
strcat(RCT2_ADDRESS(RCT2_ADDRESS_SAVED_GAMES_PATH, char), "\\Saved Games\\");

strcpy(RCT2_ADDRESS(RCT2_ADDRESS_SCENARIOS_PATH, char), RCT2_ADDRESS(RCT2_ADDRESS_APP_PATH, char));
strcat(RCT2_ADDRESS(RCT2_ADDRESS_SCENARIOS_PATH, char), "\\Scenarios\\*.SC6");

strcpy(RCT2_ADDRESS(RCT2_ADDRESS_LANDSCAPES_PATH, char), RCT2_ADDRESS(RCT2_ADDRESS_APP_PATH, char));
strcat(RCT2_ADDRESS(RCT2_ADDRESS_LANDSCAPES_PATH, char), "\\Landscapes\\*.SC6");

strcpy(RCT2_ADDRESS(RCT2_ADDRESS_OBJECT_DATA_PATH, char), RCT2_ADDRESS(RCT2_ADDRESS_APP_PATH, char));
strcat(RCT2_ADDRESS(RCT2_ADDRESS_OBJECT_DATA_PATH, char), "\\ObjData\\*.DAT");

strcpy(RCT2_ADDRESS(RCT2_ADDRESS_TRACKS_PATH, char), RCT2_ADDRESS(RCT2_ADDRESS_APP_PATH, char));
strcat(RCT2_ADDRESS(RCT2_ADDRESS_TRACKS_PATH, char), "\\Tracks\\*.TD?");

strcpy(RCT2_ADDRESS(RCT2_ADDRESS_SAVED_GAMES_PATH_2, char), RCT2_ADDRESS(RCT2_ADDRESS_SAVED_GAMES_PATH, char));

}

// rct2: 0x00674B42 void rct2_startup_checks() { // check if game is already running

RCT2_CALLPROC(0x00674C0B);

}

void rct2_update() { __asm { mov eax, 009DE564h mov[eax], esp }

if (!setjmp(_end_update_jump))
    rct2_update_2();

}

void rct2_update_2() { int tick, tick2;

tick = timeGetTime();

RCT2_GLOBAL(0x009DE588, sint16) = tick2 = tick - RCT2_GLOBAL(0x009DE580, sint32);
if (RCT2_GLOBAL(0x009DE588, sint16) > 500)
    RCT2_GLOBAL(0x009DE588, sint16) = 500;

RCT2_GLOBAL(0x009DE580, sint32) = tick;
if (RCT2_GLOBAL(0x009DEA6E, uint8) == 0)
    RCT2_GLOBAL(0x009DE584, sint32) += tick2;

if (RCT2_GLOBAL(0x009DEA6E, uint8) == 0)
    RCT2_GLOBAL(0x009DE584, sint32) += tick2;

if (RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8) != 0)
    RCT2_GLOBAL(0x009DE588, sint16) = 31;

// TODO: screenshot countdown process

// Screens
if (RCT2_GLOBAL(RCT2_ADDRESS_RUN_INTRO_TICK_PART, uint8) != 0)
    intro_update();
else if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 1)
    title_update();
else
    game_update();

}

tres.14159
  • 111
  • 2
  • I know that there are a lot of work to "translate" the automatic lines to human readable code. But I don't know the first step (get a bunch of C files). – tres.14159 Jan 18 '22 at 10:47

2 Answers2

1

Reko maintainer here. You could give Reko a try (https://github.com/uxmal/reko). Like the other decompilers you've tried, it won't generate immediately compileable code, for a vast number of reasons.

However, open source projects usually appreciate constructive user feedback. You could try running Reko (or any other decompiler) on your binary, and then looking at places where you think Reko could do better. Then you could file specific issues (here's a good example: https://github.com/uxmal/reko/issues/1129). This is more likely to result in improvements than the non-specific "I ran and the output is not what I want it to be."

John Källén
  • 1,070
  • 9
  • 17
1

Many years ago, I wrote a lengthy answer explaining why it is generally impossible for decompilers to produce C code that compiles for arbitrary input binaries. There is a lot of manual work in your future.

Rolf Rolles
  • 9,198
  • 1
  • 23
  • 33