Skip to content

Commit 04e7161

Browse files
Repository cleanup & README.md. (#5)
1 parent cd6fcb3 commit 04e7161

24 files changed

Lines changed: 341 additions & 269 deletions

CMakeLists.txt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@ add_subdirectory(${XENONANALYSE_ROOT})
2424
add_subdirectory(${XENONRECOMP_ROOT})
2525
add_subdirectory(${XENONUTILS_ROOT})
2626

27-
# Only build sample and tests if this is the top level project
27+
# Only tests if this is the top level project
2828
if (${CMAKE_CURRENT_SOURCE_DIR} STREQUAL ${CMAKE_SOURCE_DIR})
29-
add_subdirectory(XenonSample)
3029
add_subdirectory(XenonTests)
3130
endif()

LICENSE.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# MIT License
2+
3+
Copyright (c) 2025 hedge-dev and contributors
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
- The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 258 additions & 0 deletions
Large diffs are not rendered by default.

XenonAnalyse/main.cpp

Lines changed: 20 additions & 161 deletions
Original file line numberDiff line numberDiff line change
@@ -172,32 +172,25 @@ void* SearchMask(const void* source, const uint32_t* compare, size_t compareCoun
172172
return nullptr;
173173
}
174174

175-
int main()
175+
static std::string out;
176+
177+
template<class... Args>
178+
static void println(fmt::format_string<Args...> fmt, Args&&... args)
176179
{
177-
const auto file = LoadFile("private/default.xex");
178-
auto image = Image::ParseImage(file.data(), file.size());
180+
fmt::vformat_to(std::back_inserter(out), fmt.get(), fmt::make_format_args(args...));
181+
out += '\n';
182+
};
179183

180-
std::string out;
181-
auto println = [&]<class... Args>(fmt::format_string<Args...> fmt, Args&&... args)
184+
int main(int argc, char** argv)
185+
{
186+
if (argc < 3)
182187
{
183-
fmt::vformat_to(std::back_inserter(out), fmt.get(), fmt::make_format_args(args...));
184-
out += '\n';
185-
};
186-
//for (const auto& section : image.sections)
187-
//{
188-
// image.symbols.emplace(section.name, section.base, section.size, Symbol_Section);
189-
//}
190-
191-
// MakeMask((uint32_t*)image.Find(0x82C40D84), 6);
192-
193-
//auto data = "\x4D\x99\x00\x20";
194-
//auto data2 = ByteSwap((2129));
195-
//ppc_insn insn;
196-
//ppc_insn insn2;
197-
//ppc::Disassemble(data, 0, insn);
198-
//ppc::Disassemble(&data2, 0, insn2);
199-
//auto op = PPC_OP(insn.instruction);
200-
//auto xop = PPC_XOP(insn.instruction);
188+
printf("Usage: XenonAnalyse [input XEX file path] [output jump table TOML file path]");
189+
return EXIT_SUCCESS;
190+
}
191+
192+
const auto file = LoadFile(argv[1]);
193+
auto image = Image::ParseImage(file.data(), file.size());
201194

202195
auto printTable = [&](const SwitchTable& table)
203196
{
@@ -217,27 +210,7 @@ int main()
217210

218211
std::vector<SwitchTable> switches{};
219212

220-
auto insertTable = [&](size_t base, size_t defaultLabel, size_t r, size_t nLabels, uint32_t type)
221-
{
222-
auto& sw = switches.emplace_back();
223-
sw.base = base;
224-
sw.defaultLabel = defaultLabel;
225-
sw.r = r;
226-
sw.labels.resize(nLabels);
227-
sw.type = type;
228-
};
229-
230-
println("# Generated by PowerAnalyse");
231-
insertTable(0x830ADAD8, 0x830ADB28, 11, 0x1B, SWITCH_COMPUTED);
232-
insertTable(0x830AE1B0, 0x830AE21C, 11, 0x1B, SWITCH_BYTEOFFSET);
233-
insertTable(0x82CFE120, 0x82CFDE68, 11, 0x10, SWITCH_SHORTOFFSET);
234-
235-
println("# ---- MANUAL JUMPTABLE ----");
236-
for (auto& table : switches)
237-
{
238-
ReadTable(image, table);
239-
printTable(table);
240-
}
213+
println("# Generated by XenonAnalyse");
241214

242215
auto scanPattern = [&](uint32_t* pattern, size_t count, size_t type)
243216
{
@@ -332,122 +305,8 @@ int main()
332305
scanPattern(offsetSwitch, std::size(offsetSwitch), SWITCH_BYTEOFFSET);
333306
scanPattern(wordOffsetSwitch, std::size(wordOffsetSwitch), SWITCH_SHORTOFFSET);
334307

335-
FILE* f = fopen("out/switches.toml", "w");
336-
fwrite(out.data(), 1, out.size(), f);
337-
fclose(f);
338-
339-
uint32_t cxxFrameHandler = ByteSwap(0x831B1C90);
340-
uint32_t cSpecificFrameHandler = ByteSwap(0x8324B3BC);
341-
image.symbols.emplace("__CxxFrameHandler", 0x831B1C90, 0x38, Symbol_Function);
342-
image.symbols.emplace("__C_specific_handler", 0x8324B3BC, 0x38, Symbol_Function);
343-
image.symbols.emplace("memcpy", 0x831B0ED0, 0x488, Symbol_Function);
344-
image.symbols.emplace("memset", 0x831B0BA0, 0xA0, Symbol_Function);
345-
image.symbols.emplace("blkmov", 0x831B1358, 0xA8, Symbol_Function);
346-
347-
image.symbols.emplace(fmt::format("sub_{:X}", 0x82EF5D78), 0x82EF5D78, 0x3F8, Symbol_Function);
348-
349-
// auto fnd = Function::Analyze(image.Find(0x82C40D58), image.size, 0x82C40D58);
350-
351-
std::vector<Function> functions;
352-
auto& pdata = *image.Find(".pdata");
353-
size_t count = pdata.size / sizeof(IMAGE_CE_RUNTIME_FUNCTION);
354-
auto* pf = (IMAGE_CE_RUNTIME_FUNCTION*)pdata.data;
355-
for (size_t i = 0; i < count; i++)
356-
{
357-
auto fn = pf[i];
358-
fn.BeginAddress = ByteSwap(fn.BeginAddress);
359-
fn.Data = ByteSwap(fn.Data);
360-
361-
auto& f = functions.emplace_back();
362-
f.base = fn.BeginAddress;
363-
f.size = fn.FunctionLength * 4;
364-
365-
if (f.base == 0x82BD7420)
366-
{
367-
__builtin_debugtrap();
368-
}
369-
370-
image.symbols.emplace(fmt::format("sub_{:X}", f.base), f.base, f.size, Symbol_Function);
371-
}
372-
373-
auto sym = image.symbols.find(0x82BD7420);
374-
375-
std::vector<Function> missingFunctions;
376-
for (const auto& section : image.sections)
377-
{
378-
if (!(section.flags & SectionFlags_Code))
379-
{
380-
continue;
381-
}
382-
size_t base = section.base;
383-
uint8_t* data = section.data;
384-
uint8_t* dataEnd = section.data + section.size;
385-
const Symbol* prevSymbol = nullptr;
386-
while (data < dataEnd)
387-
{
388-
if (*(uint32_t*)data == 0)
389-
{
390-
data += 4;
391-
base += 4;
392-
continue;
393-
}
394-
395-
if (*(uint32_t*)data == cxxFrameHandler || *(uint32_t*)data == cSpecificFrameHandler)
396-
{
397-
data += 8;
398-
base += 8;
399-
continue;
400-
}
401-
402-
auto fnSymbol = image.symbols.find(base);
403-
if (fnSymbol != image.symbols.end() && fnSymbol->type == Symbol_Function)
404-
{
405-
assert(fnSymbol->address == base);
406-
407-
prevSymbol = &*fnSymbol;
408-
base += fnSymbol->size;
409-
data += fnSymbol->size;
410-
}
411-
else
412-
{
413-
auto& missingFn = missingFunctions.emplace_back(Function::Analyze(data, dataEnd - data, base));
414-
base += missingFn.size;
415-
data += missingFn.size;
416-
417-
fmt::println("sub_{:X}", missingFn.base);
418-
}
419-
}
420-
}
421-
422-
//ppc_insn insn;
423-
//uint8_t c[4] = { 0x10, 0x00, 0x59, 0xC3 };
424-
//ppc::Disassemble(c, 0x831D6C64, insn);
425-
//fmt::println("{:20}{}", insn.opcode->name, insn.op_str);
426-
427-
428-
const auto entrySymbol = image.symbols.find(image.entry_point);
429-
assert(entrySymbol != image.symbols.end());
430-
431-
const auto entrySize = entrySymbol->size;
432-
image.symbols.erase(entrySymbol);
433-
434-
image.symbols.emplace("_start", image.entry_point, entrySize, Symbol_Function);
435-
436-
fmt::println("FUNCTIONS");
437-
for (const auto& fn : functions)
438-
{
439-
fmt::println("\tsub_{:X}", fn.base);
440-
}
441-
fmt::println("");
442-
443-
444-
fmt::println("SECTIONS");
445-
for (const auto& section : image.sections)
446-
{
447-
printf("Section %.8s\n", section.name.c_str());
448-
printf("\t%X-%X\n", section.base, section.base + section.size);
449-
}
308+
std::ofstream f(argv[2]);
309+
f.write(out.data(), out.size());
450310

451-
fmt::println("");
452-
return 0;
311+
return EXIT_SUCCESS;
453312
}

XenonRecomp/main.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,14 @@
33

44
int main(int argc, char* argv[])
55
{
6+
#ifndef XENON_RECOMP_CONFIG_FILE_PATH
7+
if (argc < 3)
8+
{
9+
printf("Usage: XenonRecomp [input TOML file path] [PPC context header file path]");
10+
return EXIT_SUCCESS;
11+
}
12+
#endif
13+
614
const char* path =
715
#ifdef XENON_RECOMP_CONFIG_FILE_PATH
816
XENON_RECOMP_CONFIG_FILE_PATH
@@ -40,5 +48,5 @@ int main(int argc, char* argv[])
4048
TestRecompiler::RecompileTests(path, argv[2]);
4149
}
4250

43-
return 0;
51+
return EXIT_SUCCESS;
4452
}

XenonRecomp/recompiler.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2578,7 +2578,11 @@ void Recompiler::SaveCurrentOutData(const std::string_view& name)
25782578
bool shouldWrite = true;
25792579

25802580
// Check if an identical file already exists first to not trigger recompilation
2581-
std::string filePath = fmt::format("{}/{}/{}", config.directoryPath, config.outDirectoryPath, name.empty() ? cppName : name);
2581+
std::string directoryPath = config.directoryPath;
2582+
if (!directoryPath.empty())
2583+
directoryPath += "/";
2584+
2585+
std::string filePath = fmt::format("{}{}/{}", directoryPath, config.outDirectoryPath, name.empty() ? cppName : name);
25822586
FILE* f = fopen(filePath.c_str(), "rb");
25832587
if (f)
25842588
{

XenonRecomp/test_recompiler.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ void TestRecompiler::RecompileTests(const char* srcDirectoryPath, const char* ds
5151

5252
recompiler.println("#define PPC_CONFIG_H_INCLUDED");
5353
recompiler.println("#include <ppc_context.h>\n");
54-
recompiler.println("#define __debugbreak()\n");
54+
recompiler.println("#define __builtin_debugtrap()\n");
5555

5656
for (auto& fn : recompiler.functions)
5757
{
@@ -102,8 +102,12 @@ void TestRecompiler::RecompileTests(const char* srcDirectoryPath, const char* ds
102102

103103
fmt::println(file, "#define PPC_CONFIG_H_INCLUDED");
104104
fmt::println(file, "#include <ppc_context.h>");
105+
fmt::println(file, "#ifdef _WIN32");
105106
fmt::println(file, "#include <Windows.h>");
106-
fmt::println(file, "#include <print>\n");
107+
fmt::println(file, "#else");
108+
fmt::println(file, "#include <sys/mman.h>");
109+
fmt::println(file, "#endif");
110+
fmt::println(file, "#include <fmt/core.h>\n");
107111
fmt::println(file, "#define PPC_CHECK_VALUE_U(f, lhs, rhs) if (lhs != rhs) fmt::println(#f \" \" #lhs \" EXPECTED \" #rhs \" ACTUAL {{:X}}\", lhs)\n");
108112
fmt::println(file, "#define PPC_CHECK_VALUE_F(f, lhs, rhs) if (lhs != rhs) fmt::println(#f \" \" #lhs \" EXPECTED \" #rhs \" ACTUAL {{}}\", lhs)\n");
109113

@@ -274,7 +278,11 @@ void TestRecompiler::RecompileTests(const char* srcDirectoryPath, const char* ds
274278
}
275279

276280
fmt::println(file, "int main() {{");
277-
fmt::println(file, "\tuint8_t* base = reinterpret_cast<uint8_t*>(VirtualAlloc(nullptr, 0x100000000, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE));");
281+
fmt::println(file, "#ifdef _WIN32");
282+
fmt::println(file, "\tuint8_t* base = reinterpret_cast<uint8_t*>(VirtualAlloc(nullptr, 0x100000000ull, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE));");
283+
fmt::println(file, "#else");
284+
fmt::println(file, "\tuint8_t* base = reinterpret_cast<uint8_t*>(mmap(NULL, 0x100000000ull, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0));");
285+
fmt::println(file, "#endif");
278286
fwrite(main.data(), 1, main.size(), file);
279287
fmt::println(file, "\treturn 0;");
280288
fmt::println(file, "}}");

XenonSample/.gitignore

Lines changed: 0 additions & 1 deletion
This file was deleted.

XenonSample/CMakeLists.txt

Lines changed: 0 additions & 14 deletions
This file was deleted.

XenonSample/main.cpp

Whitespace-only changes.

0 commit comments

Comments
 (0)