mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2026-04-29 23:41:19 -06:00
Early memory regions setup
Needed to enable flexible allocations before mapping the eboot
This commit is contained in:
parent
95ba5918dd
commit
da1552d4ac
@ -74,41 +74,6 @@ void Linker::Execute(const std::vector<std::string>& args) {
|
||||
Relocate(m.get());
|
||||
}
|
||||
|
||||
// Configure the direct and flexible memory regions.
|
||||
u64 fmem_size = ORBIS_FLEXIBLE_MEMORY_SIZE;
|
||||
bool use_extended_mem1 = true, use_extended_mem2 = true;
|
||||
|
||||
const auto* proc_param = GetProcParam();
|
||||
ASSERT(proc_param);
|
||||
|
||||
Core::OrbisKernelMemParam mem_param{};
|
||||
if (proc_param->size >= offsetof(OrbisProcParam, mem_param) + sizeof(OrbisKernelMemParam*)) {
|
||||
if (proc_param->mem_param) {
|
||||
mem_param = *proc_param->mem_param;
|
||||
if (mem_param.size >=
|
||||
offsetof(OrbisKernelMemParam, flexible_memory_size) + sizeof(u64*)) {
|
||||
if (const auto* flexible_size = mem_param.flexible_memory_size) {
|
||||
fmem_size = *flexible_size + ORBIS_FLEXIBLE_MEMORY_BASE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mem_param.size < offsetof(OrbisKernelMemParam, extended_memory_1) + sizeof(u64*)) {
|
||||
mem_param.extended_memory_1 = nullptr;
|
||||
}
|
||||
if (mem_param.size < offsetof(OrbisKernelMemParam, extended_memory_2) + sizeof(u64*)) {
|
||||
mem_param.extended_memory_2 = nullptr;
|
||||
}
|
||||
|
||||
const u64 sdk_ver = proc_param->sdk_version;
|
||||
if (sdk_ver < Common::ElfInfo::FW_50) {
|
||||
use_extended_mem1 = mem_param.extended_memory_1 ? *mem_param.extended_memory_1 : false;
|
||||
use_extended_mem2 = mem_param.extended_memory_2 ? *mem_param.extended_memory_2 : false;
|
||||
}
|
||||
|
||||
memory->SetupMemoryRegions(fmem_size, use_extended_mem1, use_extended_mem2);
|
||||
|
||||
main_thread.Run([this, module, &args](std::stop_token) {
|
||||
Common::SetCurrentThreadName("Game:Main");
|
||||
#ifndef _WIN32 // Clear any existing signal mask for game threads.
|
||||
|
||||
@ -33,8 +33,23 @@ MemoryManager::MemoryManager() {
|
||||
|
||||
MemoryManager::~MemoryManager() = default;
|
||||
|
||||
void MemoryManager::SetupMemoryRegions(u64 flexible_size, bool use_extended_mem1,
|
||||
bool use_extended_mem2) {
|
||||
void MemoryManager::SetupMemoryRegions(u64* flexible_size, u8* extended_memory_1,
|
||||
u8* extended_memory_2) {
|
||||
u64 fmem_size = ORBIS_FLEXIBLE_MEMORY_SIZE;
|
||||
bool use_extended_mem1 = true, use_extended_mem2 = true;
|
||||
|
||||
if (flexible_size) {
|
||||
fmem_size = *flexible_size + ORBIS_FLEXIBLE_MEMORY_BASE;
|
||||
}
|
||||
|
||||
s32 sdk_ver;
|
||||
ASSERT_MSG(::Libraries::Kernel::sceKernelGetCompiledSdkVersion(&sdk_ver) == ORBIS_OK,
|
||||
"Failed to get SDK version");
|
||||
if (sdk_ver < Common::ElfInfo::FW_50) {
|
||||
use_extended_mem1 = extended_memory_1 ? *extended_memory_1 : false;
|
||||
use_extended_mem2 = extended_memory_2 ? *extended_memory_2 : false;
|
||||
}
|
||||
|
||||
const bool is_neo = ::Libraries::Kernel::sceKernelIsNeoMode();
|
||||
auto total_size = is_neo ? ORBIS_KERNEL_TOTAL_MEM_PRO : ORBIS_KERNEL_TOTAL_MEM;
|
||||
if (EmulatorSettings.IsDevKit()) {
|
||||
@ -53,8 +68,8 @@ void MemoryManager::SetupMemoryRegions(u64 flexible_size, bool use_extended_mem1
|
||||
if (!use_extended_mem2 && !is_neo) {
|
||||
total_size -= 128_MB;
|
||||
}
|
||||
total_flexible_size = flexible_size - ORBIS_FLEXIBLE_MEMORY_BASE;
|
||||
total_direct_size = total_size - flexible_size;
|
||||
total_flexible_size = fmem_size - ORBIS_FLEXIBLE_MEMORY_BASE;
|
||||
total_direct_size = total_size - fmem_size;
|
||||
|
||||
// Insert an area that covers the direct memory physical address block.
|
||||
// Note that this should never be called after direct memory allocations have been made.
|
||||
|
||||
@ -240,7 +240,7 @@ public:
|
||||
|
||||
bool TryWriteBacking(void* address, const void* data, u64 size);
|
||||
|
||||
void SetupMemoryRegions(u64 flexible_size, bool use_extended_mem1, bool use_extended_mem2);
|
||||
void SetupMemoryRegions(u64* flexible_size, u8* extended_memory_1, u8* extended_memory_2);
|
||||
|
||||
PAddr PoolExpand(PAddr search_start, PAddr search_end, u64 size, u64 alignment);
|
||||
|
||||
|
||||
103
src/emulator.cpp
103
src/emulator.cpp
@ -92,6 +92,106 @@ s32 ReadCompiledSdkVersion(const std::filesystem::path& file) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void InitializeMemoryRegions(const std::filesystem::path& file) {
|
||||
Core::Loader::Elf elf;
|
||||
elf.Open(file);
|
||||
if (!elf.IsElfFile()) {
|
||||
return;
|
||||
}
|
||||
const auto elf_pheader = elf.GetProgramHeader();
|
||||
auto i_procparam = std::find_if(elf_pheader.begin(), elf_pheader.end(), [](const auto& entry) {
|
||||
return entry.p_type == PT_SCE_PROCPARAM;
|
||||
});
|
||||
|
||||
if (i_procparam != elf_pheader.end()) {
|
||||
Core::OrbisProcParam param{};
|
||||
elf.LoadSegment(std::bit_cast<u64>(¶m), i_procparam->p_offset, i_procparam->p_filesz);
|
||||
|
||||
// We need to convert virtual addresses to their physical file offset.
|
||||
// To do this, search through program headers and calculate the offset for
|
||||
// the block the address is in.
|
||||
const auto get_offset = [](std::span<const elf_program_header> phdr, void* offset) {
|
||||
s64 virtual_offset = std::bit_cast<u64>(offset);
|
||||
auto block =
|
||||
std::find_if(phdr.begin(), phdr.end(), [virtual_offset](const auto& entry) {
|
||||
return (entry.p_type == PT_SCE_RELRO || entry.p_type == PT_LOAD) &&
|
||||
entry.p_vaddr <= virtual_offset &&
|
||||
entry.p_vaddr + entry.p_memsz > virtual_offset;
|
||||
});
|
||||
if (block != phdr.end()) {
|
||||
return virtual_offset + block->p_offset - block->p_vaddr;
|
||||
}
|
||||
return static_cast<u64>(0);
|
||||
};
|
||||
|
||||
// Read raw memory parameter data
|
||||
Core::OrbisKernelMemParam* mem_param = new Core::OrbisKernelMemParam();
|
||||
if (param.mem_param) {
|
||||
u64 offset = get_offset(elf_pheader, param.mem_param);
|
||||
u64 vaddr = std::bit_cast<u64>(mem_param);
|
||||
elf.LoadSegment(vaddr, offset, sizeof(*mem_param));
|
||||
} else {
|
||||
delete (mem_param);
|
||||
mem_param = nullptr;
|
||||
}
|
||||
|
||||
// Read flexible memory size
|
||||
u64* flexible_memory_size = new u64();
|
||||
if (mem_param && mem_param->flexible_memory_size) {
|
||||
u64 offset = get_offset(elf_pheader, mem_param->flexible_memory_size);
|
||||
u64 vaddr = std::bit_cast<u64>(flexible_memory_size);
|
||||
elf.LoadSegment(vaddr, offset, sizeof(*flexible_memory_size));
|
||||
} else {
|
||||
delete (flexible_memory_size);
|
||||
flexible_memory_size = nullptr;
|
||||
}
|
||||
|
||||
// Read the extended memory parameters
|
||||
u8* extended_memory_1 = new u8();
|
||||
if (mem_param && mem_param->extended_memory_1) {
|
||||
u64 offset = get_offset(elf_pheader, mem_param->extended_memory_1);
|
||||
u64 vaddr = std::bit_cast<u64>(extended_memory_1);
|
||||
elf.LoadSegment(vaddr, offset, sizeof(*extended_memory_1));
|
||||
} else {
|
||||
delete (extended_memory_1);
|
||||
extended_memory_1 = nullptr;
|
||||
}
|
||||
u8* extended_memory_2 = new u8();
|
||||
if (mem_param && mem_param->extended_memory_2) {
|
||||
u64 offset = get_offset(elf_pheader, mem_param->extended_memory_2);
|
||||
u64 vaddr = std::bit_cast<u64>(extended_memory_2);
|
||||
elf.LoadSegment(vaddr, offset, sizeof(*extended_memory_2));
|
||||
} else {
|
||||
delete (extended_memory_2);
|
||||
extended_memory_2 = nullptr;
|
||||
}
|
||||
|
||||
// Run memory initialization with these parameters.
|
||||
auto* memory = Core::Memory::Instance();
|
||||
memory->SetupMemoryRegions(flexible_memory_size, extended_memory_1, extended_memory_2);
|
||||
|
||||
// Clean up
|
||||
if (mem_param) {
|
||||
delete (mem_param);
|
||||
mem_param = nullptr;
|
||||
}
|
||||
if (flexible_memory_size) {
|
||||
delete (flexible_memory_size);
|
||||
flexible_memory_size = nullptr;
|
||||
}
|
||||
if (extended_memory_1) {
|
||||
delete (extended_memory_1);
|
||||
extended_memory_1 = nullptr;
|
||||
}
|
||||
if (extended_memory_2) {
|
||||
delete (extended_memory_2);
|
||||
extended_memory_2 = nullptr;
|
||||
}
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void Emulator::Run(std::filesystem::path file, std::vector<std::string> args,
|
||||
std::optional<std::filesystem::path> p_game_folder) {
|
||||
Common::SetCurrentThreadName("shadPS4:Main");
|
||||
@ -450,6 +550,9 @@ void Emulator::Run(std::filesystem::path file, std::vector<std::string> args,
|
||||
LOG_WARNING(Loader, "No dumped system fonts, expect missing text or instability");
|
||||
}
|
||||
|
||||
// Initialize memory regions
|
||||
InitializeMemoryRegions(eboot_path);
|
||||
|
||||
// Initialize kernel and library facilities.
|
||||
Libraries::InitHLELibs(&linker->GetHLESymbols());
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user