Compare commits

...

5 commits

Author SHA1 Message Date
Isaac Marovitz
e33541ea3a
Merge c122571951 into ddd128bcca 2025-08-05 17:01:13 -03:00
Skyth (Asilkan)
ddd128bcca
Update outdated info in README. (#159) 2025-08-04 16:56:26 +03:00
Isaac Marovitz
c122571951
Whitespace
Signed-off-by: Isaac Marovitz <isaacryu@icloud.com>
2025-03-13 11:01:32 -04:00
Isaac Marovitz
6783869c8a
This langauge sucks
Signed-off-by: Isaac Marovitz <isaacryu@icloud.com>
2025-03-13 10:42:15 -04:00
Isaac Marovitz
9c6c3dbaa6
Search for and print out register save/load locations
Signed-off-by: Isaac Marovitz <isaacryu@icloud.com>
2025-03-13 10:17:10 -04:00
2 changed files with 61 additions and 6 deletions

View file

@ -1,6 +1,6 @@
# XenonRecomp
XenonRecomp is a tool that converts Xbox 360 executables into C++ code, which can then be recompiled for any platform. Currently, it only supports x86 platforms due to the use of x86 intrinsics.
XenonRecomp is a tool that converts Xbox 360 executables into C++ code, which can then be recompiled for any platform.
This project was heavily inspired by [N64: Recompiled](https://github.com/N64Recomp/N64Recomp), a similar tool for N64 executables.
@ -20,7 +20,7 @@ Vector registers' endianness handling is more complicated. Instead of swapping i
The FPU expects denormalized numbers to remain unmodified, while VMX instructions always flush them. This is managed by storing the current floating-point state in the CPU state struct and enabling or disabling denormal flushing as necessary before executing each instruction.
Most VMX instructions are implemented using x86 intrinsics. Luckily, the number of AVX intrinsics used is relatively low, so adding support for other architectures using libraries like [SIMD Everywhere](https://github.com/simd-everywhere/simde) might be possible.
Most VMX instructions are implemented using x86 intrinsics. Support for ARM64 is implemented using [SIMD Everywhere](https://github.com/simd-everywhere/simde).
### MMIO

View file

@ -1,11 +1,11 @@
#include "fmt/xchar.h"
#include "function.h"
#include <algorithm>
#include <cassert>
#include <iterator>
#include <file.h>
#include <disasm.h>
#include <file.h>
#include <image.h>
#include <xbox.h>
#include <fmt/core.h>
#include "function.h"
#define SWITCH_ABSOLUTE 0
#define SWITCH_COMPUTED 1
@ -21,6 +21,59 @@ struct SwitchTable
uint32_t type{};
};
static const uint8_t RESTGPRLR_14[] = { 0xe9, 0xc1, 0xff, 0x68 };
static const uint8_t SAVEGPRLR_14[] = { 0xf9, 0xc1, 0xff, 0x68 };
static const uint8_t RESTFPR_14[] = { 0xc9, 0xcc, 0xff, 0x70 };
static const uint8_t SAVEFPR_14[] = { 0xd9, 0xcc, 0xff, 0x70 };
static const uint8_t RESTVMX_14[] = { 0x39, 0x60, 0xfe, 0xe0, 0x7d, 0xcb, 0x60, 0xce };
static const uint8_t SAVEVMX_14[] = { 0x39, 0x60, 0xfe, 0xe0, 0x7d, 0xcb, 0x61, 0xce };
static const uint8_t RESTVMX_64[] = { 0x39, 0x60, 0xfc, 0x00, 0x10, 0x0b, 0x60, 0xcb };
static const uint8_t SAVEVMX_64[] = { 0x39, 0x60, 0xfc, 0x00, 0x10, 0x0b, 0x61, 0xcb };
uint32_t BytePatternSearch(uint8_t* data, const uint32_t dataSize, const uint32_t baseAddress, const uint8_t pattern[], const size_t patternSize)
{
auto result = std::search(data, data + dataSize, pattern, pattern + patternSize);
if (result != data + dataSize) {
return baseAddress + std::distance(data, result);
}
return UINT32_MAX;
}
void RegisterFunctionsSearch(Image& image)
{
uint32_t baseAddress = UINT32_MAX;
for (const auto& section : image.sections) {
if (section.name == ".text") {
baseAddress = section.base;
if (baseAddress == UINT32_MAX) {
fmt::println("Could not find \".text\" section.");
return;
}
uint32_t restgprlr_14 = BytePatternSearch(section.data, section.size, baseAddress, RESTGPRLR_14, sizeof(RESTGPRLR_14));
uint32_t savegprlr_14 = BytePatternSearch(section.data, section.size, baseAddress, SAVEGPRLR_14, sizeof(SAVEGPRLR_14));
uint32_t restfpr_14 = BytePatternSearch(section.data, section.size, baseAddress, RESTFPR_14, sizeof(RESTFPR_14));
uint32_t savefpr_14 = BytePatternSearch(section.data, section.size, baseAddress, SAVEFPR_14, sizeof(SAVEFPR_14));
uint32_t restvmx_14 = BytePatternSearch(section.data, section.size, baseAddress, RESTVMX_14, sizeof(RESTVMX_14));
uint32_t savevmx_14 = BytePatternSearch(section.data, section.size, baseAddress, SAVEVMX_14, sizeof(SAVEVMX_14));
uint32_t restvmx_64 = BytePatternSearch(section.data, section.size, baseAddress, RESTVMX_64, sizeof(RESTVMX_64));
uint32_t savevmx_64 = BytePatternSearch(section.data, section.size, baseAddress, SAVEVMX_64, sizeof(SAVEVMX_64));
fmt::println("restgprlr_14_address = 0x{:X}", restgprlr_14);
fmt::println("savegprlr_14_address = 0x{:X}", savegprlr_14);
fmt::println("restfpr_14_address = 0x{:X}", restfpr_14);
fmt::println("savefpr_14_address = 0x{:X}", savefpr_14);
fmt::println("restvmx_14_address = 0x{:X}", restvmx_14);
fmt::println("savevmx_14_address = 0x{:X}", savevmx_14);
fmt::println("restvmx_64_address = 0x{:X}", restvmx_64);
fmt::println("savevmx_64_address = 0x{:X}", savevmx_64);
}
}
}
void ReadTable(Image& image, SwitchTable& table)
{
uint32_t pOffset;
@ -192,6 +245,8 @@ int main(int argc, char** argv)
const auto file = LoadFile(argv[1]);
auto image = Image::ParseImage(file.data(), file.size());
RegisterFunctionsSearch(image);
auto printTable = [&](const SwitchTable& table)
{
println("[[switch]]");