mirror of
https://github.com/citra-emu/citra.git
synced 2024-11-25 02:10:13 +00:00
Properly relocate all offsets at the start.
Handle some errors.
This commit is contained in:
parent
bab307b1f4
commit
2e4730a3cc
@ -101,7 +101,9 @@ struct CROHeader {
|
||||
u32 next_cro;
|
||||
u32 previous_cro;
|
||||
u32 file_size;
|
||||
INSERT_PADDING_WORDS(0x6);
|
||||
u32 unk_size1;
|
||||
u32 always_zero;
|
||||
INSERT_PADDING_WORDS(0x4);
|
||||
u32 segment_offset;
|
||||
u32 code_offset;
|
||||
u32 code_size;
|
||||
@ -141,11 +143,11 @@ struct CROHeader {
|
||||
u8 GetImportPatchesTargetSegment() { return segment_offset & 0xF; }
|
||||
u32 GetImportPatchesSegmentOffset() { return segment_offset >> 4; }
|
||||
|
||||
SegmentTableEntry* GetSegmentTableEntry(u32 index, bool relocated = false);
|
||||
void RelocateSegmentsTable(u32 base, u32 data_section0, u32 data_section1, u32& prev_data_section0);
|
||||
SegmentTableEntry* GetSegmentTableEntry(u32 index);
|
||||
ResultCode RelocateSegmentsTable(u32 base, u32 size, u32 data_section0, u32 data_section1, u32& prev_data_section0);
|
||||
|
||||
ExportTableEntry* GetExportTableEntry(u32 index);
|
||||
void RelocateExportsTable(u32 base);
|
||||
ResultCode RelocateExportsTable(u32 base);
|
||||
|
||||
ExportTreeEntry* GetExportTreeEntry(u32 index);
|
||||
|
||||
@ -170,20 +172,19 @@ struct CROHeader {
|
||||
|
||||
void RelocateUnk2Patches(u32 base);
|
||||
|
||||
void RelocateOffsets(u32 base);
|
||||
bool VerifyAndRelocateOffsets(u32 base, u32 size);
|
||||
};
|
||||
|
||||
static std::unordered_map<std::string, ExportedSymbol> loaded_exports;
|
||||
static std::vector<u32> loaded_cros;
|
||||
|
||||
SegmentTableEntry* CROHeader::GetSegmentTableEntry(u32 index, bool relocated) {
|
||||
if (relocated)
|
||||
SegmentTableEntry* CROHeader::GetSegmentTableEntry(u32 index) {
|
||||
return reinterpret_cast<SegmentTableEntry*>(Memory::GetPointer(segment_table_offset + sizeof(SegmentTableEntry) * index));
|
||||
|
||||
return reinterpret_cast<SegmentTableEntry*>(reinterpret_cast<u8*>(this) + segment_table_offset + sizeof(SegmentTableEntry) * index);
|
||||
}
|
||||
|
||||
void CROHeader::RelocateSegmentsTable(u32 base, u32 data_section0, u32 data_section1, u32& prev_data_section0) {
|
||||
ResultCode CROHeader::RelocateSegmentsTable(u32 base, u32 size, u32 data_section0, u32 data_section1, u32& prev_data_section0) {
|
||||
u32 cro_end = base + size;
|
||||
|
||||
prev_data_section0 = 0;
|
||||
for (int i = 0; i < segment_table_num; ++i) {
|
||||
SegmentTableEntry* entry = GetSegmentTableEntry(i);
|
||||
@ -194,44 +195,54 @@ void CROHeader::RelocateSegmentsTable(u32 base, u32 data_section0, u32 data_sect
|
||||
entry->segment_offset = data_section1;
|
||||
} else if (entry->segment_offset) {
|
||||
entry->segment_offset += base;
|
||||
if (entry->segment_offset > cro_end)
|
||||
return ResultCode(0xD9012C19);
|
||||
}
|
||||
}
|
||||
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
ExportTreeEntry* CROHeader::GetExportTreeEntry(u32 index) {
|
||||
return reinterpret_cast<ExportTreeEntry*>(reinterpret_cast<u8*>(this) + export_tree_offset + sizeof(ExportTreeEntry) * index);
|
||||
return reinterpret_cast<ExportTreeEntry*>(Memory::GetPointer(export_tree_offset + sizeof(ExportTreeEntry) * index));
|
||||
}
|
||||
|
||||
u32 CROHeader::GetUnk1TableEntry(u32 index) {
|
||||
return *reinterpret_cast<u32*>(reinterpret_cast<u8*>(this) + unk1_offset + sizeof(u32) * index);
|
||||
return *reinterpret_cast<u32*>(Memory::GetPointer(unk1_offset + sizeof(u32) * index));
|
||||
}
|
||||
|
||||
ExportTableEntry* CROHeader::GetExportTableEntry(u32 index) {
|
||||
return reinterpret_cast<ExportTableEntry*>(reinterpret_cast<u8*>(this) + export_table_offset + sizeof(ExportTableEntry) * index);
|
||||
return reinterpret_cast<ExportTableEntry*>(Memory::GetPointer(export_table_offset + sizeof(ExportTableEntry) * index));
|
||||
}
|
||||
|
||||
void CROHeader::RelocateExportsTable(u32 base) {
|
||||
ResultCode CROHeader::RelocateExportsTable(u32 base) {
|
||||
for (int i = 0; i < export_table_num; ++i) {
|
||||
ExportTableEntry* entry = GetExportTableEntry(i);
|
||||
if (entry->name_offset)
|
||||
entry->name_offset += base;
|
||||
|
||||
if (entry->name_offset < export_strings_offset ||
|
||||
entry->name_offset > export_strings_offset + export_strings_num)
|
||||
return ResultCode(0xD9012C11);
|
||||
}
|
||||
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
Patch* CROHeader::GetImportPatch(u32 index) {
|
||||
return reinterpret_cast<Patch*>(reinterpret_cast<u8*>(this) + import_patches_offset + sizeof(Patch) * index);
|
||||
return reinterpret_cast<Patch*>(Memory::GetPointer(import_patches_offset + sizeof(Patch) * index));
|
||||
}
|
||||
|
||||
ImportTableEntry* CROHeader::GetImportTable1Entry(u32 index) {
|
||||
return reinterpret_cast<ImportTableEntry*>(reinterpret_cast<u8*>(this) + import_table1_offset + sizeof(ImportTableEntry) * index);
|
||||
return reinterpret_cast<ImportTableEntry*>(Memory::GetPointer(import_table1_offset + sizeof(ImportTableEntry) * index));
|
||||
}
|
||||
|
||||
ImportTableEntry* CROHeader::GetImportTable2Entry(u32 index) {
|
||||
return reinterpret_cast<ImportTableEntry*>(reinterpret_cast<u8*>(this) + import_table2_offset + sizeof(ImportTableEntry) * index);
|
||||
return reinterpret_cast<ImportTableEntry*>(Memory::GetPointer(import_table2_offset + sizeof(ImportTableEntry) * index));
|
||||
}
|
||||
|
||||
ImportTableEntry* CROHeader::GetImportTable3Entry(u32 index) {
|
||||
return reinterpret_cast<ImportTableEntry*>(reinterpret_cast<u8*>(this) + import_table3_offset + sizeof(ImportTableEntry) * index);
|
||||
return reinterpret_cast<ImportTableEntry*>(Memory::GetPointer(import_table3_offset + sizeof(ImportTableEntry) * index));
|
||||
}
|
||||
|
||||
void CROHeader::RelocateImportTable1(u32 base) {
|
||||
@ -273,25 +284,219 @@ void CROHeader::RelocateUnk2Patches(u32 base) {
|
||||
}
|
||||
|
||||
Unk3Patch* CROHeader::GetUnk3PatchEntry(u32 index) {
|
||||
return reinterpret_cast<Unk3Patch*>(reinterpret_cast<u8*>(this) + unk3_offset * sizeof(Unk3Patch) * index);
|
||||
return reinterpret_cast<Unk3Patch*>(Memory::GetPointer(unk3_offset * sizeof(Unk3Patch) * index));
|
||||
}
|
||||
|
||||
Patch* CROHeader::GetRelocationPatchEntry(u32 index) {
|
||||
return reinterpret_cast<Patch*>(reinterpret_cast<u8*>(this) + relocation_patches_offset + sizeof(Patch) * index);
|
||||
return reinterpret_cast<Patch*>(Memory::GetPointer(relocation_patches_offset + sizeof(Patch) * index));
|
||||
}
|
||||
|
||||
Unk2Patch* CROHeader::GetUnk2PatchEntry(u32 index) {
|
||||
return reinterpret_cast<Unk2Patch*>(reinterpret_cast<u8*>(this) + unk2_offset + sizeof(Unk2Patch) * index);
|
||||
return reinterpret_cast<Unk2Patch*>(Memory::GetPointer(unk2_offset + sizeof(Unk2Patch) * index));
|
||||
}
|
||||
|
||||
void CROHeader::RelocateOffsets(u32 base) {
|
||||
memcpy(magic, "FIXD", 4);
|
||||
segment_table_offset += base;
|
||||
export_strings_offset += base;
|
||||
export_table_offset += base;
|
||||
export_tree_offset += base;
|
||||
bool CROHeader::VerifyAndRelocateOffsets(u32 base, u32 size) {
|
||||
u32 end = base + size;
|
||||
|
||||
// Error if the magic is invalid
|
||||
if (strcmp(magic, "CRO0") != 0)
|
||||
return false;
|
||||
|
||||
// If these values are set the game might be trying to load the same CRO multiple times
|
||||
if (next_cro || previous_cro)
|
||||
return false;
|
||||
|
||||
// This seems to be a hard limit set by the RO module
|
||||
if (file_size >= 0x10000000 || unk_size1 >= 0x10000000)
|
||||
return false;
|
||||
|
||||
if (always_zero != 0)
|
||||
return false;
|
||||
|
||||
// Hard limit set by the RO module, it is unknown what the value means
|
||||
if (code_offset < 0x138)
|
||||
return false;
|
||||
|
||||
if (module_name_offset < code_offset)
|
||||
return false;
|
||||
|
||||
if (module_name_offset > segment_table_offset)
|
||||
return false;
|
||||
|
||||
if (export_table_offset < segment_table_offset)
|
||||
return false;
|
||||
|
||||
if (export_table_offset > export_tree_offset)
|
||||
return false;
|
||||
|
||||
if (unk1_offset < export_tree_offset)
|
||||
return false;
|
||||
|
||||
if (unk1_offset > export_strings_offset)
|
||||
return false;
|
||||
|
||||
if (unk2_offset < export_strings_offset)
|
||||
return false;
|
||||
|
||||
if (unk2_offset > import_patches_offset)
|
||||
return false;
|
||||
|
||||
if (import_table1_offset < import_patches_offset)
|
||||
return false;
|
||||
|
||||
if (import_table1_offset > import_table2_offset)
|
||||
return false;
|
||||
|
||||
if (import_table3_offset < import_table2_offset)
|
||||
return false;
|
||||
|
||||
if (import_table3_offset > import_strings_offset)
|
||||
return false;
|
||||
|
||||
if (unk3_offset < import_strings_offset)
|
||||
return false;
|
||||
|
||||
if (unk3_offset > relocation_patches_offset)
|
||||
return false;
|
||||
|
||||
if (unk4_offset < relocation_patches_offset)
|
||||
return false;
|
||||
|
||||
if (unk4_offset > unk_offset)
|
||||
return false;
|
||||
|
||||
if (unk_offset > file_size)
|
||||
return false;
|
||||
|
||||
if (name_offset) {
|
||||
name_offset += base;
|
||||
if (name_offset >= end)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (code_offset) {
|
||||
code_offset += base;
|
||||
if (code_offset >= end)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (unk_offset) {
|
||||
unk_offset += base;
|
||||
if (unk_offset >= end)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (module_name_offset) {
|
||||
module_name_offset += base;
|
||||
if (module_name_offset >= end)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (segment_table_offset) {
|
||||
segment_table_offset += base;
|
||||
if (segment_table_offset >= end)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (export_table_offset) {
|
||||
export_table_offset += base;
|
||||
if (export_table_offset >= end)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (unk1_offset) {
|
||||
unk1_offset += base;
|
||||
if (unk1_offset >= end)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (export_strings_offset) {
|
||||
export_strings_offset += base;
|
||||
if (export_strings_offset >= end)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (export_tree_offset) {
|
||||
export_tree_offset += base;
|
||||
if (export_tree_offset >= end)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (unk2_offset) {
|
||||
unk2_offset += base;
|
||||
if (unk2_offset >= end)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (import_patches_offset) {
|
||||
import_patches_offset += base;
|
||||
if (import_patches_offset >= end)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (import_table1_offset) {
|
||||
import_table1_offset += base;
|
||||
if (import_table1_offset >= end)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (import_table2_offset) {
|
||||
import_table2_offset += base;
|
||||
if (import_table2_offset >= end)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (import_table3_offset) {
|
||||
import_table3_offset += base;
|
||||
if (import_table3_offset >= end)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (import_strings_offset) {
|
||||
import_strings_offset += base;
|
||||
if (import_strings_offset >= end)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (unk3_offset) {
|
||||
unk3_offset += base;
|
||||
if (unk3_offset >= end)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (relocation_patches_offset) {
|
||||
relocation_patches_offset += base;
|
||||
if (relocation_patches_offset >= end)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (unk4_offset) {
|
||||
unk4_offset += base;
|
||||
if (unk4_offset >= end)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (code_offset + code_size > end ||
|
||||
unk_offset + unk_size > end ||
|
||||
module_name_offset + module_name_size > end ||
|
||||
segment_table_offset + sizeof(SegmentTableEntry) * segment_table_num > end ||
|
||||
export_table_offset + sizeof(ExportTableEntry) * export_table_num > end ||
|
||||
unk1_offset + sizeof(u32) * unk1_size > end ||
|
||||
export_strings_offset + export_strings_num > end ||
|
||||
export_tree_offset + sizeof(ExportTreeEntry) * export_tree_num > end ||
|
||||
unk2_offset + sizeof(Unk2Patch) * unk2_num > end ||
|
||||
import_patches_offset + sizeof(Patch) * import_patches_num ||
|
||||
import_table1_offset + sizeof(ImportTableEntry) * import_table1_num ||
|
||||
import_table2_offset + sizeof(ImportTableEntry) * import_table2_num ||
|
||||
import_table3_offset + sizeof(ImportTableEntry) * import_table3_num ||
|
||||
import_strings_offset + import_strings_num > end ||
|
||||
unk3_offset + sizeof(Unk3Patch) * unk3_num > end ||
|
||||
relocation_patches_offset + sizeof(Patch) * relocation_patches_num > end ||
|
||||
unk4_offset + 12 * unk4_num > end) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void ApplyPatch(Patch* patch, u32 patch_base, u32 patch_address, u32* patch_address1 = nullptr) {
|
||||
@ -329,11 +534,11 @@ static void ApplyImportPatches(CROHeader* header, u32 base) {
|
||||
}
|
||||
}
|
||||
|
||||
static void ApplyListPatches(CROHeader* header, Patch* first_patch, u32 patch_base, bool relocated = false) {
|
||||
static void ApplyListPatches(CROHeader* header, Patch* first_patch, u32 patch_base) {
|
||||
Patch* current_patch = first_patch;
|
||||
|
||||
while (1) {
|
||||
SegmentTableEntry* target_segment = header->GetSegmentTableEntry(current_patch->GetTargetSegment(), relocated);
|
||||
SegmentTableEntry* target_segment = header->GetSegmentTableEntry(current_patch->GetTargetSegment());
|
||||
ApplyPatch(current_patch, patch_base, target_segment->segment_offset + current_patch->GetSegmentOffset());
|
||||
|
||||
if (current_patch->unk)
|
||||
@ -396,7 +601,7 @@ static void ApplyExitPatches(CROHeader* header, u32 base) {
|
||||
LOG_ERROR(Service_LDR, "Could not find __aeabi_atexit in the CRO imports!");
|
||||
}
|
||||
|
||||
static void ApplyImportTable1Patches(CROHeader* header, u32 base, bool relocated) {
|
||||
static void ApplyImportTable1Patches(CROHeader* header, u32 base) {
|
||||
for (int i = 0; i < header->import_table1_num; ++i) {
|
||||
ImportTableEntry* entry = header->GetImportTable1Entry(i);
|
||||
Patch* patch = reinterpret_cast<Patch*>(Memory::GetPointer(entry->symbol_offset));
|
||||
@ -410,7 +615,7 @@ static void ApplyImportTable1Patches(CROHeader* header, u32 base, bool relocated
|
||||
u32 patch_base = export_->second.cro_offset;
|
||||
|
||||
Patch* first_patch = reinterpret_cast<Patch*>(Memory::GetPointer(entry->symbol_offset));
|
||||
ApplyListPatches(header, first_patch, patch_base, relocated);
|
||||
ApplyListPatches(header, first_patch, patch_base);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -426,7 +631,7 @@ static u32 GetCROBaseByName(char* name) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ApplyUnk2Patches(CROHeader* header, u32 base, bool relocated) {
|
||||
static void ApplyUnk2Patches(CROHeader* header, u32 base) {
|
||||
for (int i = 0; i < header->unk2_num; ++i) {
|
||||
Unk2Patch* entry = header->GetUnk2PatchEntry(i);
|
||||
u32 cro_base = GetCROBaseByName(reinterpret_cast<char*>(Memory::GetPointer(entry->string_offset)));
|
||||
@ -440,10 +645,10 @@ static void ApplyUnk2Patches(CROHeader* header, u32 base, bool relocated) {
|
||||
u32 unk1_table_entry = patch_cro->GetUnk1TableEntry(table1_entry->offset_or_index);
|
||||
u32 base_segment_id = unk1_table_entry & 0xF;
|
||||
u32 base_segment_offset = unk1_table_entry >> 4;
|
||||
SegmentTableEntry* base_segment = patch_cro->GetSegmentTableEntry(base_segment_id, true);
|
||||
SegmentTableEntry* base_segment = patch_cro->GetSegmentTableEntry(base_segment_id);
|
||||
|
||||
Patch* first_patch = reinterpret_cast<Patch*>(Memory::GetPointer(base + table1_entry->patches_offset));
|
||||
ApplyListPatches(header, first_patch, base_segment->segment_offset + base_segment_offset, relocated);
|
||||
ApplyListPatches(header, first_patch, base_segment->segment_offset + base_segment_offset);
|
||||
}
|
||||
|
||||
// Apply the patches from the second table
|
||||
@ -451,10 +656,10 @@ static void ApplyUnk2Patches(CROHeader* header, u32 base, bool relocated) {
|
||||
Unk2TableEntry* table2_entry = entry->GetTable2Entry(j);
|
||||
u32 base_segment_id = table2_entry->offset_or_index & 0xF;
|
||||
u32 base_segment_offset = table2_entry->offset_or_index >> 4;
|
||||
SegmentTableEntry* base_segment = patch_cro->GetSegmentTableEntry(base_segment_id, true);
|
||||
SegmentTableEntry* base_segment = patch_cro->GetSegmentTableEntry(base_segment_id);
|
||||
|
||||
Patch* first_patch = reinterpret_cast<Patch*>(Memory::GetPointer(table2_entry->patches_offset));
|
||||
ApplyListPatches(header, first_patch, base_segment->segment_offset + base_segment_offset, relocated);
|
||||
ApplyListPatches(header, first_patch, base_segment->segment_offset + base_segment_offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -475,10 +680,10 @@ static void BackApplyUnk2Patches(CROHeader* header, u32 base, CROHeader* new_hea
|
||||
u32 unk1_table_entry = patch_cro->GetUnk1TableEntry(table1_entry->offset_or_index);
|
||||
u32 base_segment_id = unk1_table_entry & 0xF;
|
||||
u32 base_segment_offset = unk1_table_entry >> 4;
|
||||
SegmentTableEntry* base_segment = patch_cro->GetSegmentTableEntry(base_segment_id, false);
|
||||
SegmentTableEntry* base_segment = patch_cro->GetSegmentTableEntry(base_segment_id);
|
||||
|
||||
Patch* first_patch = reinterpret_cast<Patch*>(Memory::GetPointer(base + table1_entry->patches_offset));
|
||||
ApplyListPatches(header, first_patch, base_segment->segment_offset + base_segment_offset, true);
|
||||
ApplyListPatches(header, first_patch, base_segment->segment_offset + base_segment_offset);
|
||||
}
|
||||
|
||||
// Apply the patches from the second table
|
||||
@ -486,10 +691,10 @@ static void BackApplyUnk2Patches(CROHeader* header, u32 base, CROHeader* new_hea
|
||||
Unk2TableEntry* table2_entry = entry->GetTable2Entry(j);
|
||||
u32 base_segment_id = table2_entry->offset_or_index & 0xF;
|
||||
u32 base_segment_offset = table2_entry->offset_or_index >> 4;
|
||||
SegmentTableEntry* base_segment = patch_cro->GetSegmentTableEntry(base_segment_id, false);
|
||||
SegmentTableEntry* base_segment = patch_cro->GetSegmentTableEntry(base_segment_id);
|
||||
|
||||
Patch* first_patch = reinterpret_cast<Patch*>(Memory::GetPointer(table2_entry->patches_offset));
|
||||
ApplyListPatches(header, first_patch, base_segment->segment_offset + base_segment_offset, true);
|
||||
ApplyListPatches(header, first_patch, base_segment->segment_offset + base_segment_offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -546,17 +751,38 @@ static void LinkCROs(CROHeader* new_cro, u32 base) {
|
||||
}
|
||||
}
|
||||
|
||||
static void LoadCRO(u32 base, u8* cro, bool relocate_segments, u32 data_section0, u32 data_section1, bool crs) {
|
||||
static ResultCode LoadCRO(u32 base, u32 size, u8* cro, u32 data_section0, u32 data_section1, bool crs) {
|
||||
CROHeader* header = reinterpret_cast<CROHeader*>(cro);
|
||||
|
||||
// Relocate all offsets
|
||||
if (!header->VerifyAndRelocateOffsets(base, size))
|
||||
return ResultCode(0xD9012C11);
|
||||
|
||||
if (header->module_name_size &&
|
||||
Memory::Read8(header->module_name_offset + header->module_name_size - 1) != 0) {
|
||||
// The module name must end with '\0'
|
||||
return ResultCode(0xD9012C0B);
|
||||
}
|
||||
|
||||
u32 prev_section0 = 0;
|
||||
if (relocate_segments) {
|
||||
ResultCode result = RESULT_SUCCESS;
|
||||
|
||||
if (!crs) {
|
||||
// Relocate segments
|
||||
header->RelocateSegmentsTable(base, data_section0, data_section1, prev_section0);
|
||||
result = header->RelocateSegmentsTable(base, size, data_section0, data_section1, prev_section0);
|
||||
if (result.IsError())
|
||||
return result;
|
||||
}
|
||||
|
||||
// Rebase export table
|
||||
header->RelocateExportsTable(base);
|
||||
result = header->RelocateExportsTable(base);
|
||||
|
||||
if (result.IsError())
|
||||
return result;
|
||||
|
||||
if (header->export_strings_num &&
|
||||
Memory::Read8(header->export_strings_offset + header->export_strings_num - 1) != 0)
|
||||
return ResultCode(0xD9012C0B);
|
||||
|
||||
// Rebase unk2
|
||||
header->RelocateUnk2Patches(base);
|
||||
@ -581,10 +807,10 @@ static void LoadCRO(u32 base, u8* cro, bool relocate_segments, u32 data_section0
|
||||
ApplyExitPatches(header, base);
|
||||
|
||||
// Import Table 1
|
||||
ApplyImportTable1Patches(header, base, false);
|
||||
ApplyImportTable1Patches(header, base);
|
||||
|
||||
// Apply unk2 patches
|
||||
ApplyUnk2Patches(header, base, false);
|
||||
ApplyUnk2Patches(header, base);
|
||||
|
||||
// Load exports
|
||||
LoadExportsTable(header, base);
|
||||
@ -594,21 +820,24 @@ static void LoadCRO(u32 base, u8* cro, bool relocate_segments, u32 data_section0
|
||||
for (auto itr = loaded_cros.rbegin(); itr != loaded_cros.rend(); ++itr) {
|
||||
u32 cro_base = *itr;
|
||||
CROHeader* cro_header = reinterpret_cast<CROHeader*>(Memory::GetPointer(cro_base));
|
||||
ApplyImportTable1Patches(cro_header, cro_base, true);
|
||||
ApplyImportTable1Patches(cro_header, cro_base);
|
||||
BackApplyUnk2Patches(cro_header, cro_base, header, base);
|
||||
}
|
||||
|
||||
// Relocate all offsets
|
||||
header->RelocateOffsets(base);
|
||||
|
||||
// Link the CROs
|
||||
LinkCROs(header, base);
|
||||
|
||||
loaded_cros.push_back(base);
|
||||
|
||||
memcpy(header->magic, "FIXD", 4);
|
||||
|
||||
LOG_WARNING(Service_LDR, "Loaded CRO name %s", reinterpret_cast<char*>(Memory::GetPointer(header->name_offset)));
|
||||
|
||||
FileUtil::IOFile file(std::to_string(base) + ".cro", "wb+");
|
||||
file.WriteBytes(header, header->file_size);
|
||||
file.Close();
|
||||
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -644,10 +873,8 @@ static void Initialize(Service::Interface* self) {
|
||||
// TODO(Subv): Check what the real hardware returns for MemoryState
|
||||
Kernel::g_current_process->vm_manager.MapMemoryBlock(address, cro, 0, crs_size, Kernel::MemoryState::Code);
|
||||
|
||||
LoadCRO(address, Memory::GetPointer(address), false, 0, 0, true);
|
||||
|
||||
cmd_buff[0] = IPC::MakeHeader(1, 1, 0);
|
||||
cmd_buff[1] = RESULT_SUCCESS.raw;
|
||||
cmd_buff[1] = LoadCRO(address, crs_size, Memory::GetPointer(address), 0, 0, true).raw;
|
||||
|
||||
LOG_WARNING(Service_LDR, "(STUBBED) called. crs_buffer_ptr=0x%08X, crs_size=0x%08X, address=0x%08X, value=0x%08X, process=0x%08X",
|
||||
crs_buffer_ptr, crs_size, address, value, process);
|
||||
@ -694,11 +921,10 @@ static void LoadExeCRO(Service::Interface* self) {
|
||||
// TODO(Subv): Check what the real hardware returns for MemoryState
|
||||
Kernel::g_current_process->vm_manager.MapMemoryBlock(address, cro, 0, size, Kernel::MemoryState::Code);
|
||||
|
||||
LoadCRO(address, Memory::GetPointer(address), true, cmd_buff[4], cmd_buff[7], false);
|
||||
|
||||
cmd_buff[0] = IPC::MakeHeader(4, 2, 0);
|
||||
cmd_buff[1] = RESULT_SUCCESS.raw;
|
||||
cmd_buff[1] = LoadCRO(address, size, Memory::GetPointer(address), cmd_buff[4], cmd_buff[7], false).raw;
|
||||
cmd_buff[2] = 0;
|
||||
|
||||
LOG_WARNING(Service_LDR, "Loading CRO address=%08X", address);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user