diff --git a/Source/Core/Core/Src/Boot/Boot_ELF.cpp b/Source/Core/Core/Src/Boot/Boot_ELF.cpp index c80bc0e7c8..9fa86a9183 100644 --- a/Source/Core/Core/Src/Boot/Boot_ELF.cpp +++ b/Source/Core/Core/Src/Boot/Boot_ELF.cpp @@ -34,12 +34,35 @@ bool CBoot::IsElfWii(const char *filename) File::IOFile f(filename, "rb"); f.ReadBytes(mem, (size_t)filesize); } - - ElfReader reader(mem); - // TODO: Find a more reliable way to distinguish. - bool isWii = reader.GetEntryPoint() >= 0x80004000; - delete[] mem; + // Use the same method as the DOL loader uses: search for mfspr from HID4, + // which should only be used in Wii ELFs. + // + // Likely to have some false positives/negatives, patches implementing a + // better heuristic are welcome. + + u32 HID4_pattern = 0x7c13fba6; + u32 HID4_mask = 0xfc1fffff; + ElfReader reader(mem); + bool isWii = false; + + for (int i = 0; i < reader.GetNumSections(); ++i) + { + if (reader.IsCodeSection(i)) + { + for (unsigned int j = 0; j < reader.GetSectionSize(i) / sizeof (u32); ++j) + { + u32 word = Common::swap32(((u32*)reader.GetSectionDataPtr(i))[j]); + if ((word & HID4_mask) == HID4_pattern) + { + isWii = true; + break; + } + } + } + } + + delete[] mem; return isWii; } diff --git a/Source/Core/Core/Src/Boot/ElfReader.h b/Source/Core/Core/Src/Boot/ElfReader.h index 0d46bb390a..6a3c559296 100644 --- a/Source/Core/Core/Src/Boot/ElfReader.h +++ b/Source/Core/Core/Src/Boot/ElfReader.h @@ -59,7 +59,6 @@ public: bool LoadInto(u32 vaddr); bool LoadSymbols(); -private: int GetNumSegments() const { return (int)(header->e_phnum); } int GetNumSections() const { return (int)(header->e_shnum); } const u8 *GetPtr(int offset) const { return (u8*)base + offset; } @@ -73,6 +72,10 @@ private: else return 0; } + bool IsCodeSection(int section) const + { + return sections[section].sh_type == SHT_PROGBITS; + } const u8 *GetSegmentPtr(int segment) { return GetPtr(segments[segment].p_offset);