loader: Add support for 3DSX special relocation types, fixes citra-emu/citra#2449

As per devkitPro/3dstools@47bea18
This commit is contained in:
Thomas Farr 2017-01-19 01:30:52 +13:00
parent 55c91ae782
commit bb1f277db1
No known key found for this signature in database
GPG Key ID: FD001548CA1FCF32
1 changed files with 25 additions and 9 deletions

View File

@ -177,18 +177,34 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr,
pos += table.skip; pos += table.skip;
s32 num_patches = table.patch; s32 num_patches = table.patch;
while (0 < num_patches && pos < end_pos) { while (0 < num_patches && pos < end_pos) {
u32 in_addr = u32 in_addr = base_addr + static_cast<u32>(reinterpret_cast<u8*>(pos) -
static_cast<u32>(reinterpret_cast<u8*>(pos) - program_image.data()); program_image.data());
u32 addr = TranslateAddr(*pos, &loadinfo, offsets); u32 orig_data = *pos;
LOG_TRACE(Loader, "Patching %08X <-- rel(%08X,%d) (%08X)", u32 sub_type = orig_data >> (32 - 4);
base_addr + in_addr, addr, current_segment_reloc_table, *pos); u32 addr = TranslateAddr(orig_data & ~0xF0000000, &loadinfo, offsets);
LOG_TRACE(Loader, "Patching %08X <-- rel(%08X,%d) (%08X)", in_addr, addr,
current_segment_reloc_table, *pos);
switch (current_segment_reloc_table) { switch (current_segment_reloc_table) {
case 0: case 0: {
*pos = (addr); if (sub_type != 0)
return ERROR_READ;
*pos = addr;
break; break;
case 1: }
*pos = static_cast<u32>(addr - in_addr); case 1: {
u32 data = addr - in_addr;
switch (sub_type) {
case 0: // 32-bit signed offset
*pos = data;
break;
case 1: // 31-bit signed offset
*pos = data & ~(1U << 31);
break;
default:
return ERROR_READ;
}
break; break;
}
default: default:
break; // this should never happen break; // this should never happen
} }