Fixed the CRO linked list
This commit is contained in:
parent
300ae2cedd
commit
f5060b43d8
1 changed files with 64 additions and 36 deletions
|
@ -741,16 +741,20 @@ static u32 FindExportByName(CROHeader* header, char* str) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void LinkCROs(CROHeader* new_cro, u32 base) {
|
static void LinkCROs(CROHeader* crs, CROHeader* new_cro, u32 base) {
|
||||||
if (!loaded_cros.empty())
|
auto v3 = reinterpret_cast<CROHeader*>(Memory::GetPointer(crs->next_cro));
|
||||||
new_cro->previous_cro = loaded_cros.back();
|
|
||||||
|
|
||||||
if (new_cro->previous_cro) {
|
if (v3) {
|
||||||
CROHeader* previous_cro = reinterpret_cast<CROHeader*>(Memory::GetPointer(new_cro->previous_cro));
|
crs = reinterpret_cast<CROHeader*>(Memory::GetPointer(v3->previous_cro));
|
||||||
previous_cro->next_cro = base;
|
new_cro->previous_cro = v3->previous_cro;
|
||||||
|
new_cro->next_cro = 0;
|
||||||
|
v3->previous_cro = base;
|
||||||
} else {
|
} else {
|
||||||
|
new_cro->next_cro = 0;
|
||||||
new_cro->previous_cro = base;
|
new_cro->previous_cro = base;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
crs->next_cro = base;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ResultCode LoadCRO(u32 base, u32 size, u8* cro, 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) {
|
||||||
|
@ -828,8 +832,10 @@ static ResultCode LoadCRO(u32 base, u32 size, u8* cro, u32 data_section0, u32 da
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!crs) {
|
||||||
// Link the CROs
|
// Link the CROs
|
||||||
LinkCROs(header, base);
|
LinkCROs(reinterpret_cast<CROHeader*>(Memory::GetPointer(loaded_cros.front())), header, base);
|
||||||
|
}
|
||||||
|
|
||||||
loaded_cros.push_back(base);
|
loaded_cros.push_back(base);
|
||||||
|
|
||||||
|
@ -970,6 +976,11 @@ static void LoadExeCRO(Service::Interface* self) {
|
||||||
|
|
||||||
u32 level = cmd_buff[10];
|
u32 level = cmd_buff[10];
|
||||||
|
|
||||||
|
bool link = cmd_buff[9] & 0xFF;
|
||||||
|
|
||||||
|
if (link)
|
||||||
|
LOG_CRITICAL(HW_GPU, "Something here");
|
||||||
|
|
||||||
std::shared_ptr<std::vector<u8>> cro = std::make_shared<std::vector<u8>>(size);
|
std::shared_ptr<std::vector<u8>> cro = std::make_shared<std::vector<u8>>(size);
|
||||||
memcpy(cro->data(), cro_buffer, size);
|
memcpy(cro->data(), cro_buffer, size);
|
||||||
|
|
||||||
|
@ -1045,34 +1056,48 @@ static void LoadExeCRO(Service::Interface* self) {
|
||||||
header->always_zero = size - v24;
|
header->always_zero = size - v24;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < size; ++i) {
|
LOG_WARNING(Service_LDR, "Loading CRO address=%08X level=%08X", address, level);
|
||||||
u32 mem = Memory::Read32(address + i);
|
|
||||||
if (mem == 0x400001d9)
|
|
||||||
__debugbreak();
|
|
||||||
}
|
|
||||||
LOG_WARNING(Service_LDR, "Loading CRO address=%08X", address);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void UnlinkCRO(CROHeader* cro, u32 address) {
|
static void UnlinkCRO(CROHeader* crs, CROHeader* cro, u32 address) {
|
||||||
// TODO(Subv): Verify if this is correct
|
auto v5 = reinterpret_cast<CROHeader*>(Memory::GetPointer(crs->previous_cro));
|
||||||
for (auto itr = loaded_cros.begin(); itr != loaded_cros.end(); ++itr) {
|
auto v5_base = crs->previous_cro;
|
||||||
if (*itr == address)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
CROHeader* cro = reinterpret_cast<CROHeader*>(Memory::GetPointer(*itr));
|
if (v5_base == address) {
|
||||||
if (cro->next_cro == address) {
|
auto v7_base = v5->next_cro;
|
||||||
cro->next_cro = cro->next_cro;
|
if (v7_base) {
|
||||||
if (cro->next_cro != 0) {
|
auto v7 = reinterpret_cast<CROHeader*>(Memory::GetPointer(v7_base));
|
||||||
CROHeader* next = reinterpret_cast<CROHeader*>(Memory::GetPointer(cro->next_cro));
|
v7->previous_cro = v5->previous_cro;
|
||||||
next->previous_cro = *itr;
|
|
||||||
}
|
}
|
||||||
|
crs->previous_cro = v7_base;
|
||||||
|
} else {
|
||||||
|
auto v8_base = crs->next_cro;
|
||||||
|
auto v8 = reinterpret_cast<CROHeader*>(Memory::GetPointer(v8_base));
|
||||||
|
if (v8_base == address) {
|
||||||
|
auto v8 = reinterpret_cast<CROHeader*>(Memory::GetPointer(v8_base));
|
||||||
|
auto v9_base = v8->next_cro;
|
||||||
|
if (v9_base) {
|
||||||
|
auto v9 = reinterpret_cast<CROHeader*>(Memory::GetPointer(v9_base));
|
||||||
|
v9->previous_cro = v8->previous_cro;
|
||||||
}
|
}
|
||||||
|
crs->next_cro = v9_base;
|
||||||
if (cro->previous_cro == address) {
|
} else {
|
||||||
cro->previous_cro = cro->previous_cro;
|
auto v10_base = cro->next_cro;
|
||||||
if (cro->previous_cro != 0) {
|
if (v10_base) {
|
||||||
CROHeader* prev = reinterpret_cast<CROHeader*>(Memory::GetPointer(cro->previous_cro));
|
auto v11_base = cro->previous_cro;
|
||||||
prev->next_cro = *itr;
|
auto v11 = reinterpret_cast<CROHeader*>(Memory::GetPointer(v11_base));
|
||||||
|
auto v10 = reinterpret_cast<CROHeader*>(Memory::GetPointer(v10_base));
|
||||||
|
v11->next_cro = v10_base;
|
||||||
|
v10->previous_cro = v11_base;
|
||||||
|
} else {
|
||||||
|
auto v16_base = cro->previous_cro;
|
||||||
|
auto v16 = reinterpret_cast<CROHeader*>(Memory::GetPointer(v16_base));
|
||||||
|
if (v8_base && v8->previous_cro == address) {
|
||||||
|
v8->previous_cro = v16_base;
|
||||||
|
} else {
|
||||||
|
v5->previous_cro = v16_base;
|
||||||
|
}
|
||||||
|
v16->next_cro = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1307,10 +1332,11 @@ static ResultCode UnloadCRO(u32 address) {
|
||||||
return ResultCode(0xD9012C1E);
|
return ResultCode(0xD9012C1E);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CROHeader* crs = reinterpret_cast<CROHeader*>(Memory::GetPointer(loaded_cros.front()));
|
||||||
CROHeader* unload = reinterpret_cast<CROHeader*>(Memory::GetPointer(address));
|
CROHeader* unload = reinterpret_cast<CROHeader*>(Memory::GetPointer(address));
|
||||||
u32 size = unload->file_size;
|
u32 size = unload->file_size;
|
||||||
|
|
||||||
UnlinkCRO(unload, address);
|
UnlinkCRO(crs, unload, address);
|
||||||
|
|
||||||
u32 base_offset = CalculateBaseOffset(unload);
|
u32 base_offset = CalculateBaseOffset(unload);
|
||||||
|
|
||||||
|
@ -1318,7 +1344,6 @@ static ResultCode UnloadCRO(u32 address) {
|
||||||
UnloadImportTable2Patches(unload, base_offset);
|
UnloadImportTable2Patches(unload, base_offset);
|
||||||
UnloadImportTable3Patches(unload, base_offset);
|
UnloadImportTable3Patches(unload, base_offset);
|
||||||
|
|
||||||
CROHeader* crs = reinterpret_cast<CROHeader*>(Memory::GetPointer(loaded_cros.front()));
|
|
||||||
ApplyCRSUnloadPatches(crs, unload);
|
ApplyCRSUnloadPatches(crs, unload);
|
||||||
|
|
||||||
for (u32 base : loaded_cros) {
|
for (u32 base : loaded_cros) {
|
||||||
|
@ -1345,8 +1370,11 @@ static ResultCode UnloadCRO(u32 address) {
|
||||||
static void UnloadCRO(Service::Interface* self) {
|
static void UnloadCRO(Service::Interface* self) {
|
||||||
u32* cmd_buff = Kernel::GetCommandBuffer();
|
u32* cmd_buff = Kernel::GetCommandBuffer();
|
||||||
u32 address = cmd_buff[1];
|
u32 address = cmd_buff[1];
|
||||||
cmd_buff[1] = UnloadCRO(address).raw;
|
ResultCode res = UnloadCRO(address);
|
||||||
LOG_WARNING(Service_LDR, "Unloading CRO address=%08X", address);
|
cmd_buff[1] = res.raw;
|
||||||
|
// Clear the instruction cache
|
||||||
|
Core::g_app_core->ClearInstructionCache();
|
||||||
|
LOG_WARNING(Service_LDR, "Unloading CRO address=%08X res=%08X", address, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Interface::FunctionInfo FunctionTable[] = {
|
const Interface::FunctionInfo FunctionTable[] = {
|
||||||
|
|
Loading…
Reference in a new issue