mirror of
https://github.com/citra-emu/citra.git
synced 2024-11-25 00:11:06 +00:00
Services/LDR: Updated the code after the latest rebase.
Mario & Luigi Dream Team boots now! Pokemon X still doesn't boot.
This commit is contained in:
parent
b79df70c8b
commit
a43bcd3262
@ -6,6 +6,8 @@
|
||||
#include "common/logging/log.h"
|
||||
|
||||
#include "core/hle/service/ldr_ro.h"
|
||||
#include "core/hle/kernel/process.h"
|
||||
#include "core/hle/kernel/vm_manager.h"
|
||||
#include "common/file_util.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -309,11 +311,11 @@ static void ApplyImportPatches(CROHeader* header, u32 base) {
|
||||
}
|
||||
}
|
||||
|
||||
static void ApplyListPatches(CROHeader* header, Patch* first_patch, u32 patch_base) {
|
||||
static void ApplyListPatches(CROHeader* header, Patch* first_patch, u32 patch_base, bool relocated = false) {
|
||||
Patch* current_patch = first_patch;
|
||||
|
||||
do {
|
||||
SegmentTableEntry* target_segment = header->GetSegmentTableEntry(current_patch->GetTargetSegment());
|
||||
SegmentTableEntry* target_segment = header->GetSegmentTableEntry(current_patch->GetTargetSegment(), relocated);
|
||||
ApplyPatch(current_patch, patch_base, target_segment->segment_offset + current_patch->GetSegmentOffset());
|
||||
} while (!(current_patch++)->unk);
|
||||
|
||||
@ -378,7 +380,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);
|
||||
ApplyListPatches(header, first_patch, patch_base, relocated);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -409,7 +411,7 @@ static void ApplyUnk2Patches(CROHeader* header, u32 base, bool relocated) {
|
||||
SegmentTableEntry* target_base_segment = patch_cro->GetSegmentTableEntry(target_segment_id, relocated);
|
||||
|
||||
Patch* first_patch = reinterpret_cast<Patch*>(Memory::GetPointer(base + table1_entry->patches_offset));
|
||||
ApplyListPatches(header, first_patch, target_base_segment->segment_offset + target_segment_offset);
|
||||
ApplyListPatches(header, first_patch, target_base_segment->segment_offset + target_segment_offset, relocated);
|
||||
}
|
||||
|
||||
// Apply the patches from the second table
|
||||
@ -420,7 +422,7 @@ static void ApplyUnk2Patches(CROHeader* header, u32 base, bool relocated) {
|
||||
SegmentTableEntry* target_base_segment = patch_cro->GetSegmentTableEntry(target_segment_id, relocated);
|
||||
|
||||
Patch* first_patch = reinterpret_cast<Patch*>(Memory::GetPointer(base + table2_entry->patches_offset));
|
||||
ApplyListPatches(header, first_patch, target_base_segment->segment_offset + target_segment_offset);
|
||||
ApplyListPatches(header, first_patch, target_base_segment->segment_offset + target_segment_offset, relocated);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -472,10 +474,12 @@ static void LinkCROs(CROHeader* new_cro, u32 base) {
|
||||
if (new_cro->previous_cro) {
|
||||
CROHeader* previous_cro = reinterpret_cast<CROHeader*>(Memory::GetPointer(new_cro->previous_cro));
|
||||
previous_cro->next_cro = base;
|
||||
} else {
|
||||
new_cro->previous_cro = base;
|
||||
}
|
||||
}
|
||||
|
||||
static void LoadCRO(u32 base, u8* cro, bool relocate_segments, u32 data_section0, u32 data_section1) {
|
||||
static void LoadCRO(u32 base, u8* cro, bool relocate_segments, u32 data_section0, u32 data_section1, bool crs) {
|
||||
CROHeader* header = reinterpret_cast<CROHeader*>(cro);
|
||||
memcpy(header->magic, "FIXD", 4);
|
||||
|
||||
@ -529,8 +533,10 @@ static void LoadCRO(u32 base, u8* cro, bool relocate_segments, u32 data_section0
|
||||
// Relocate all offsets
|
||||
header->RelocateOffsets(base);
|
||||
|
||||
// Link the CROs
|
||||
LinkCROs(header, base);
|
||||
if (!crs) {
|
||||
// Link the CROs
|
||||
LinkCROs(header, base);
|
||||
}
|
||||
|
||||
loaded_cros.push_back(base);
|
||||
|
||||
@ -555,24 +561,27 @@ static void Initialize(Service::Interface* self) {
|
||||
u32* cmd_buff = Kernel::GetCommandBuffer();
|
||||
u8* crs_buffer_ptr = Memory::GetPointer(cmd_buff[1]);
|
||||
u32 crs_size = cmd_buff[2];
|
||||
u8* address = Memory::GetPointer(cmd_buff[3]);
|
||||
u32 address = cmd_buff[3];
|
||||
u32 value = cmd_buff[4];
|
||||
u32 process = cmd_buff[5];
|
||||
|
||||
if (value != 0) {
|
||||
LOG_ERROR(Service_LDR, "This value should be zero, but is actually %u!", value);
|
||||
LOG_WARNING(Service_LDR, "This value should be zero, but is actually %u!", value);
|
||||
}
|
||||
|
||||
loaded_exports.clear();
|
||||
loaded_cros.clear();
|
||||
|
||||
memcpy(address, crs_buffer_ptr, crs_size);
|
||||
std::shared_ptr<std::vector<u8>> cro = std::make_shared<std::vector<u8>>(crs_size);
|
||||
memcpy(cro->data(), crs_buffer_ptr, crs_size);
|
||||
|
||||
LoadCRO(cmd_buff[3], address, false, 0, 0);
|
||||
// TODO(Subv): Check what the real hardware returns for MemoryState
|
||||
Kernel::g_current_process->address_space->MapMemoryBlock(address, cro, 0, crs_size, Kernel::MemoryState::Code);
|
||||
|
||||
// TODO(purpasmart96): Verify return header on HW
|
||||
LoadCRO(address, Memory::GetPointer(address), false, 0, 0, true);
|
||||
|
||||
cmd_buff[1] = RESULT_SUCCESS.raw; // No error
|
||||
cmd_buff[0] = IPC::MakeHeader(1, 1, 0);
|
||||
cmd_buff[1] = RESULT_SUCCESS.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);
|
||||
@ -597,12 +606,11 @@ static void LoadCRR(Service::Interface* self) {
|
||||
u32 process = cmd_buff[4];
|
||||
|
||||
if (value != 0) {
|
||||
LOG_ERROR(Service_LDR, "This value should be zero, but is actually %u!", value);
|
||||
LOG_WARNING(Service_LDR, "This value should be zero, but is actually %u!", value);
|
||||
}
|
||||
|
||||
// TODO(purpasmart96): Verify return header on HW
|
||||
|
||||
cmd_buff[1] = RESULT_SUCCESS.raw; // No error
|
||||
cmd_buff[0] = IPC::MakeHeader(2, 1, 0);
|
||||
cmd_buff[1] = RESULT_SUCCESS.raw;
|
||||
|
||||
LOG_WARNING(Service_LDR, "(STUBBED) called. crs_buffer_ptr=0x%08X, crs_size=0x%08X, value=0x%08X, process=0x%08X",
|
||||
crs_buffer_ptr, crs_size, value, process);
|
||||
@ -610,17 +618,56 @@ static void LoadCRR(Service::Interface* self) {
|
||||
|
||||
static void LoadExeCRO(Service::Interface* self) {
|
||||
u32* cmd_buff = Kernel::GetCommandBuffer();
|
||||
u32 base = cmd_buff[2];
|
||||
u8* dst = Memory::GetPointer(base);
|
||||
u8* cro_buffer = Memory::GetPointer(cmd_buff[1]);
|
||||
u32 address = cmd_buff[2];
|
||||
u32 size = cmd_buff[3];
|
||||
|
||||
memcpy(dst, Memory::GetPointer(cmd_buff[1]), size);
|
||||
std::shared_ptr<std::vector<u8>> cro = std::make_shared<std::vector<u8>>(size);
|
||||
memcpy(cro->data(), cro_buffer, size);
|
||||
|
||||
LoadCRO(base, dst, true, cmd_buff[4], cmd_buff[7]);
|
||||
// TODO(Subv): Check what the real hardware returns for MemoryState
|
||||
Kernel::g_current_process->address_space->MapMemoryBlock(address, cro, 0, size, Kernel::MemoryState::Code);
|
||||
|
||||
cmd_buff[1] = 0;
|
||||
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[2] = 0;
|
||||
LOG_WARNING(Service_APT, "Loading CRO base=%08X", base);
|
||||
LOG_WARNING(Service_LDR, "Loading CRO address=%08X", address);
|
||||
}
|
||||
|
||||
static void UnloadCRO(Service::Interface* self) {
|
||||
u32* cmd_buff = Kernel::GetCommandBuffer();
|
||||
u32 address = cmd_buff[1];
|
||||
CROHeader* unload = reinterpret_cast<CROHeader*>(Memory::GetPointer(address));
|
||||
for (auto itr = loaded_cros.begin(); itr != loaded_cros.end(); ++itr) {
|
||||
if (*itr == address)
|
||||
continue;
|
||||
|
||||
CROHeader* cro = reinterpret_cast<CROHeader*>(Memory::GetPointer(*itr));
|
||||
if (cro->next_cro == address) {
|
||||
cro->next_cro = unload->next_cro;
|
||||
if (unload->next_cro != 0) {
|
||||
CROHeader* next = reinterpret_cast<CROHeader*>(Memory::GetPointer(unload->next_cro));
|
||||
next->previous_cro = *itr;
|
||||
}
|
||||
}
|
||||
|
||||
if (cro->previous_cro == address) {
|
||||
cro->previous_cro = unload->previous_cro;
|
||||
if (unload->previous_cro != 0) {
|
||||
CROHeader* prev = reinterpret_cast<CROHeader*>(Memory::GetPointer(unload->previous_cro));
|
||||
prev->next_cro = *itr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
loaded_cros.erase(std::remove(loaded_cros.begin(), loaded_cros.end(), address), loaded_cros.end());
|
||||
|
||||
// TODO(Subv): Unload symbols and unmap memory
|
||||
|
||||
cmd_buff[1] = RESULT_SUCCESS.raw;
|
||||
LOG_WARNING(Service_LDR, "Unloading CRO address=%08X", address);
|
||||
}
|
||||
|
||||
const Interface::FunctionInfo FunctionTable[] = {
|
||||
@ -628,7 +675,7 @@ const Interface::FunctionInfo FunctionTable[] = {
|
||||
{0x00020082, LoadCRR, "LoadCRR"},
|
||||
{0x00030042, nullptr, "UnloadCCR"},
|
||||
{0x000402C2, LoadExeCRO, "LoadExeCRO"},
|
||||
{0x000500C2, nullptr, "LoadCROSymbols"},
|
||||
{0x000500C2, UnloadCRO, "UnloadCRO"},
|
||||
{0x00060042, nullptr, "CRO_Load?"},
|
||||
{0x00070042, nullptr, "LoadCROSymbols"},
|
||||
{0x00080042, nullptr, "Shutdown"},
|
||||
|
Loading…
Reference in New Issue
Block a user