Skip to content

Commit

Permalink
ExeReader: Support 64 Bit executables
Browse files Browse the repository at this point in the history
Maniac Patch is now detected when the new exe is used.
  • Loading branch information
Ghabry committed Dec 21, 2024
1 parent 2bf6dae commit fa12034
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 9 deletions.
28 changes: 20 additions & 8 deletions src/exe_reader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,31 @@ namespace {
EXEReader::EXEReader(Filesystem_Stream::InputStream core) : corefile(std::move(core)) {
// The Incredibly Dumb PE parser (tm)
// Extracts data from the resource section for engine detection and can read ExFont.
uint32_t ofs = GetU32(0x3C);
uint32_t ofs = GetU32(0x3C); // PE header offset
uint16_t machine = GetU16(ofs + 4);
if (machine != 0x14c) {
if (machine != 0x14c && machine != 0x8664) {
// FIXME: Newer versions of Maniac Patch can be 64 Bit
Output::Debug("EXEReader: Machine type is not i386 ({:#x})", machine);
file_info.is_i386 = false;
Output::Debug("EXEReader: Machine type is not i386 or amd64 ({:#x})", machine);
file_info.machine_type = MachineType::Unknown;
return;
}

if (machine == 0x14c) {
file_info.machine_type = MachineType::i386;
} else {
file_info.machine_type = MachineType::amd64;
}

// The largest known exe has 11 segments, guard against bogus section data here
uint16_t sections = std::min<uint16_t>(GetU16(ofs + 6), 11);
uint32_t sectionsOfs = ofs + 0x18 + GetU16(ofs + 0x14);
resource_rva = GetU32(ofs + 0x88);
uint32_t optional_header = ofs + 0x18;
uint32_t oh_magic = GetU16(optional_header);

bool format_pe32 = (oh_magic == 0x10b); // 0x20b is PE32+ (64 bit)

uint32_t sectionsOfs = optional_header + GetU16(ofs + 0x14); // skip opt header
uint32_t data_directory_ofs = (format_pe32 ? 0x60 : 0x70);
resource_rva = GetU32(optional_header + data_directory_ofs + 16);
if (!resource_rva) {
// Is some kind of encrypted EXE -> Give up
return;
Expand Down Expand Up @@ -379,13 +391,13 @@ bool EXEReader::ResNameCheck(uint32_t i, const char* p) {
}

void EXEReader::FileInfo::Print() const {
Output::Debug("RPG_RT information: version={} logos={} code={:#x} cherry={:#x} geep={:#x} i386={} easyrpg={}", version_str, logos, code_size, cherry_size, geep_size, is_i386, is_easyrpg_player);
Output::Debug("RPG_RT information: version={} logos={} code={:#x} cherry={:#x} geep={:#x} arch={} easyrpg={}", version_str, logos, code_size, cherry_size, geep_size, kMachineTypes[machine_type], is_easyrpg_player);
}

int EXEReader::FileInfo::GetEngineType(bool& is_maniac_patch) const {
is_maniac_patch = false;

if (is_easyrpg_player || !is_i386) {
if (is_easyrpg_player || machine_type == MachineType::Unknown) {
return Player::EngineNone;
}

Expand Down
14 changes: 13 additions & 1 deletion src/exe_reader.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,26 @@ class EXEReader {
std::vector<uint8_t> GetExFont();
std::vector<std::vector<uint8_t>> GetLogos();

enum class MachineType {
Unknown,
i386,
amd64
};

static constexpr auto kMachineTypes = lcf::makeEnumTags<MachineType>(
"Unknown",
"i386",
"amd64"
);

struct FileInfo {
uint64_t version = 0;
int logos = 0;
std::string version_str;
uint32_t code_size = 0;
uint32_t cherry_size = 0;
uint32_t geep_size = 0;
bool is_i386 = true;
MachineType machine_type = MachineType::Unknown;
bool is_easyrpg_player = false;

int GetEngineType(bool& is_maniac_patch) const;
Expand Down

0 comments on commit fa12034

Please sign in to comment.