Skip to content
Dennis Stanistan edited this page Mar 8, 2025 · 2 revisions

This page gives an overview of the tools in XenonRecomp.

XenonAnalyse

XenonAnalyse analyzes an Xbox360 executable (.xex files), scans for jump tables within the executable and generates a .toml file that contains found jump table addresses.

Command:

XenonAnalyze.exe [input .xex file] [output jump_tables.toml file]

The patterns in XenonAnalyze are defined like this:

uint32_t absoluteSwitch[] = {
    PPC_INST_LIS,
    PPC_INST_ADDI,
    PPC_INST_RLWINM,
    PPC_INST_LWZX,
    PPC_INST_MTCTR,
    PPC_INST_BCTR,
};

uint32_t computedSwitch[] = {
    PPC_INST_LIS,
    PPC_INST_ADDI,
    PPC_INST_LBZX,
    PPC_INST_RLWINM,
    PPC_INST_LIS,
    PPC_INST_ADDI,
    PPC_INST_ADD,
    PPC_INST_MTCTR,
};

uint32_t offsetSwitch[] = {
    PPC_INST_LIS,
    PPC_INST_ADDI,
    PPC_INST_LBZX,
    PPC_INST_LIS,
    PPC_INST_ADDI,
    PPC_INST_ADD,
    PPC_INST_MTCTR,
};

Some games have different patterns for jump tables, the patterns shown here are from Sonic: Unleashed so you may have to change the patterns and adjust the ReadTable function to account for the changes in the array if you get empty jump tables or jump tables with incorrect offsets in the generated .toml file.

XenonUtils

XenonUtils contains code that other tools use and the ppc_context.h file that is used with XenonRecomp to generate source code for a given x360 executable.

XenonRecomp

XenonRecomp takes an input config .toml file and a PPC context header file (ppc_context.h) and generates C++ code from the code in the x360 executable.

Command:

XenonRecomp.exe [input config .toml file] [input ppc_context.h file]

Here is an example of a config .toml file that has the bare minimum to get XenonRecomp running.

[main]
file_path = "Default_unpacked.xex" # Input xex file
out_directory_path = "ppc" # Directory output for generated code
switch_table_file_path = "jump_tables.toml" # The jump table we got from XenonAnalyze

# rest/save addresses, you will have to provide the correct addresses from your game here
restgprlr_14_address = 0x82bafea0
savegprlr_14_address = 0x82bafe50
restfpr_14_address = 0x82bb0b3c
savefpr_14_address = 0x82bb0af0
restvmx_14_address = 0x82bb1d58
savevmx_14_address = 0x82bb1ac0
savevmx_64_address = 0x82bb1b54
restvmx_64_address = 0x82bb1dec

Depending on your game, you may need to provide an array of function boundaries (defined as functions) and an array of invalid insturctions (defined as invalid_instructions) in your config .toml file. Here is an example of these from Sonic: Unleashed

# These functions do not exist in .pdata and do
# not analyze properly due to having jump tables
functions = [
    { address = 0x824E7EF0, size = 0x98 },
    { address = 0x824E7F28, size = 0x60 },
    { address = 0x82C980E8, size = 0x110 },
    { address = 0x82CF7080, size = 0x80 },
    { address = 0x82D9AC08, size = 0x78 },
    { address = 0x82E86770, size = 0x98 },
    { address = 0x82E97E50, size = 0x84 },
    { address = 0x82EE2D08, size = 0x154 },
    { address = 0x82EF5C38, size = 0x64 },
    { address = 0x82EF5D78, size = 0x3F8 },
    { address = 0x82F08730, size = 0x2B0 },
    { address = 0x82F098C0, size = 0x19C },
    { address = 0x82F13980, size = 0xF4 },
    { address = 0x82F1D668, size = 0x1E8 },
    { address = 0x82F22908, size = 0x20C },
    { address = 0x82F25FD8, size = 0x240 },
    { address = 0x82F852A0, size = 0xCC },
    { address = 0x830DADA0, size = 0x150 },
    { address = 0x831487D0, size = 0xD4 },
    { address = 0x831530C8, size = 0x258 },
    { address = 0x831539E0, size = 0xD0 },
    { address = 0x83168940, size = 0x100 },
    { address = 0x83168A48, size = 0x11C },
    { address = 0x83168B70, size = 0x128 },
    { address = 0x83168F18, size = 0x254 },
    { address = 0x8316C678, size = 0x78 },
    { address = 0x8317CD30, size = 0x50 },
    { address = 0x83180700, size = 0x74 },
    { address = 0x8319ED58, size = 0x98 },
    { address = 0x82455E70, size = 0x84 },
    { address = 0x82456DC8, size = 0xD4 },
    { address = 0x826ABB70, size = 0x70 },
    { address = 0x82893088, size = 0x45C },
    { address = 0x82C49540, size = 0x114 },
    { address = 0x82DE35D8, size = 0x68 },
    { address = 0x82DE3640, size = 0x64 },
    { address = 0x82DE36A8, size = 0x5C },
    { address = 0x82DE3708, size = 0x198 },
    { address = 0x82DE38A0, size = 0x16C },
    { address = 0x830B7DD0, size = 0x74 },
    { address = 0x831B0BA0, size = 0xA0 },
    { address = 0x8305D168, size = 0x278 }
]

invalid_instructions = [
    { data = 0x00000000, size = 4 }, # Padding
    { data = 0x831B1C90, size = 8 }, # C++ Frame Handler
    { data = 0x8324B3BC, size = 8 }, # C Specific Frame Handler
    { data = 0x831C8B50, size = 8 },
    { data = 0x00485645, size = 44 } # End of .text
]
Clone this wiki locally