Skip to content

Commit 39b022f

Browse files
authored
Merge pull request #3317 from Ghabry/64bit-exe
ExeReader: Support 64 Bit executables
2 parents 2bf6dae + 4fdb5d1 commit 39b022f

File tree

2 files changed

+50
-11
lines changed

2 files changed

+50
-11
lines changed

src/exe_reader.cpp

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,19 +34,46 @@ namespace {
3434
EXEReader::EXEReader(Filesystem_Stream::InputStream core) : corefile(std::move(core)) {
3535
// The Incredibly Dumb PE parser (tm)
3636
// Extracts data from the resource section for engine detection and can read ExFont.
37-
uint32_t ofs = GetU32(0x3C);
37+
uint32_t ofs = GetU32(0x3C); // PE header offset
3838
uint16_t machine = GetU16(ofs + 4);
39-
if (machine != 0x14c) {
40-
// FIXME: Newer versions of Maniac Patch can be 64 Bit
41-
Output::Debug("EXEReader: Machine type is not i386 ({:#x})", machine);
42-
file_info.is_i386 = false;
43-
return;
39+
40+
switch (machine) {
41+
case 0x14c:
42+
file_info.machine_type = MachineType::i386;
43+
break;
44+
case 0x8664:
45+
file_info.machine_type = MachineType::amd64;
46+
break;
47+
default:
48+
Output::Debug("EXEReader: Unsupported machine type ({:#x})", machine);
49+
file_info.machine_type = MachineType::Unknown;
50+
return;
4451
}
4552

4653
// The largest known exe has 11 segments, guard against bogus section data here
4754
uint16_t sections = std::min<uint16_t>(GetU16(ofs + 6), 11);
48-
uint32_t sectionsOfs = ofs + 0x18 + GetU16(ofs + 0x14);
49-
resource_rva = GetU32(ofs + 0x88);
55+
uint32_t optional_header = ofs + 0x18;
56+
uint32_t oh_magic = GetU16(optional_header);
57+
58+
bool format_pe32;
59+
60+
switch (oh_magic) {
61+
case 0x10b:
62+
format_pe32 = true;
63+
break;
64+
case 0x20b:
65+
// PE32+ (for 64 bit executables)
66+
format_pe32 = false;
67+
break;
68+
default:
69+
Output::Debug("EXEReader: Unknown PE header magic ({:#x})", oh_magic);
70+
file_info.machine_type = MachineType::Unknown;
71+
return;
72+
}
73+
74+
uint32_t sectionsOfs = optional_header + GetU16(ofs + 0x14); // skip opt header
75+
uint32_t data_directory_ofs = (format_pe32 ? 0x60 : 0x70);
76+
resource_rva = GetU32(optional_header + data_directory_ofs + 16);
5077
if (!resource_rva) {
5178
// Is some kind of encrypted EXE -> Give up
5279
return;
@@ -379,13 +406,13 @@ bool EXEReader::ResNameCheck(uint32_t i, const char* p) {
379406
}
380407

381408
void EXEReader::FileInfo::Print() const {
382-
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);
409+
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);
383410
}
384411

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

388-
if (is_easyrpg_player || !is_i386) {
415+
if (is_easyrpg_player || machine_type == MachineType::Unknown) {
389416
return Player::EngineNone;
390417
}
391418

src/exe_reader.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,26 @@ class EXEReader {
4343
std::vector<uint8_t> GetExFont();
4444
std::vector<std::vector<uint8_t>> GetLogos();
4545

46+
enum class MachineType {
47+
Unknown,
48+
i386,
49+
amd64
50+
};
51+
52+
static constexpr auto kMachineTypes = lcf::makeEnumTags<MachineType>(
53+
"Unknown",
54+
"i386",
55+
"amd64"
56+
);
57+
4658
struct FileInfo {
4759
uint64_t version = 0;
4860
int logos = 0;
4961
std::string version_str;
5062
uint32_t code_size = 0;
5163
uint32_t cherry_size = 0;
5264
uint32_t geep_size = 0;
53-
bool is_i386 = true;
65+
MachineType machine_type = MachineType::Unknown;
5466
bool is_easyrpg_player = false;
5567

5668
int GetEngineType(bool& is_maniac_patch) const;

0 commit comments

Comments
 (0)