mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-17 08:11:51 +00:00
Patch system improved
SPU patch rewritten PPU patch implemented
This commit is contained in:
parent
2ef2f0f63b
commit
e39ee10105
@ -1,5 +1,6 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "Utilities/VirtualMemory.h"
|
#include "Utilities/VirtualMemory.h"
|
||||||
|
#include "Utilities/bin_patch.h"
|
||||||
#include "Crypto/sha1.h"
|
#include "Crypto/sha1.h"
|
||||||
#include "Crypto/unself.h"
|
#include "Crypto/unself.h"
|
||||||
#include "Loader/ELF.h"
|
#include "Loader/ELF.h"
|
||||||
@ -954,6 +955,11 @@ void ppu_load_exec(const ppu_exec_object& elf)
|
|||||||
u32 primary_stacksize = 0x100000;
|
u32 primary_stacksize = 0x100000;
|
||||||
u32 malloc_pagesize = 0x100000;
|
u32 malloc_pagesize = 0x100000;
|
||||||
|
|
||||||
|
// Executable hash
|
||||||
|
sha1_context sha;
|
||||||
|
sha1_starts(&sha);
|
||||||
|
u8 sha1_hash[20];
|
||||||
|
|
||||||
// Allocate memory at fixed positions
|
// Allocate memory at fixed positions
|
||||||
for (const auto& prog : elf.progs)
|
for (const auto& prog : elf.progs)
|
||||||
{
|
{
|
||||||
@ -965,6 +971,10 @@ void ppu_load_exec(const ppu_exec_object& elf)
|
|||||||
const u32 type = _seg.type = prog.p_type;
|
const u32 type = _seg.type = prog.p_type;
|
||||||
const u32 flag = _seg.flags = prog.p_flags;
|
const u32 flag = _seg.flags = prog.p_flags;
|
||||||
|
|
||||||
|
// Hash big-endian values
|
||||||
|
sha1_update(&sha, (uchar*)&prog.p_type, sizeof(prog.p_type));
|
||||||
|
sha1_update(&sha, (uchar*)&prog.p_flags, sizeof(prog.p_flags));
|
||||||
|
|
||||||
if (type == 0x1 /* LOAD */ && prog.p_memsz)
|
if (type == 0x1 /* LOAD */ && prog.p_memsz)
|
||||||
{
|
{
|
||||||
if (prog.bin.size() > size || prog.bin.size() != prog.p_filesz)
|
if (prog.bin.size() > size || prog.bin.size() != prog.p_filesz)
|
||||||
@ -973,8 +983,11 @@ void ppu_load_exec(const ppu_exec_object& elf)
|
|||||||
if (!vm::falloc(addr, size, vm::main))
|
if (!vm::falloc(addr, size, vm::main))
|
||||||
fmt::throw_exception("vm::falloc() failed (addr=0x%x, memsz=0x%x)", addr, size);
|
fmt::throw_exception("vm::falloc() failed (addr=0x%x, memsz=0x%x)", addr, size);
|
||||||
|
|
||||||
// Copy segment data
|
// Copy segment data, hash it
|
||||||
std::memcpy(vm::base(addr), prog.bin.data(), prog.bin.size());
|
std::memcpy(vm::base(addr), prog.bin.data(), prog.bin.size());
|
||||||
|
sha1_update(&sha, (uchar*)&prog.p_vaddr, sizeof(prog.p_vaddr));
|
||||||
|
sha1_update(&sha, (uchar*)&prog.p_memsz, sizeof(prog.p_memsz));
|
||||||
|
sha1_update(&sha, prog.bin.data(), prog.bin.size());
|
||||||
|
|
||||||
// Initialize executable code if necessary
|
// Initialize executable code if necessary
|
||||||
if (prog.p_flags & 0x1)
|
if (prog.p_flags & 0x1)
|
||||||
@ -1004,6 +1017,28 @@ void ppu_load_exec(const ppu_exec_object& elf)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sha1_finish(&sha, sha1_hash);
|
||||||
|
|
||||||
|
// Format patch name
|
||||||
|
std::string hash("PPU-0000000000000000000000000000000000000000");
|
||||||
|
for (u32 i = 0; i < sizeof(sha1_hash); i++)
|
||||||
|
{
|
||||||
|
constexpr auto pal = "0123456789abcdef";
|
||||||
|
hash[4 + i * 2] = pal[sha1_hash[i] >> 4];
|
||||||
|
hash[5 + i * 2] = pal[sha1_hash[i] & 15];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply the patch
|
||||||
|
fxm::check_unlocked<patch_engine>()->apply(hash, vm::g_base_addr);
|
||||||
|
|
||||||
|
if (!Emu.GetTitleID().empty())
|
||||||
|
{
|
||||||
|
// Alternative patch
|
||||||
|
fxm::check_unlocked<patch_engine>()->apply(Emu.GetTitleID() + '-' + hash, vm::g_base_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_NOTICE(LOADER, "PPU executable hash: %s", hash);
|
||||||
|
|
||||||
// Initialize HLE modules
|
// Initialize HLE modules
|
||||||
ppu_initialize_modules(link);
|
ppu_initialize_modules(link);
|
||||||
|
|
||||||
|
@ -34,24 +34,13 @@ void sys_spu_image::load(const fs::file& stream)
|
|||||||
|
|
||||||
const u32 addr = this->segs.addr() + 4096;
|
const u32 addr = this->segs.addr() + 4096;
|
||||||
|
|
||||||
sha1_context ctx;
|
|
||||||
u8 output[20];
|
|
||||||
|
|
||||||
sha1_starts(&ctx);
|
|
||||||
sha1_update(&ctx, reinterpret_cast<const u8*>(&obj.header), sizeof(obj.header));
|
|
||||||
|
|
||||||
for (const auto& shdr : obj.shdrs)
|
for (const auto& shdr : obj.shdrs)
|
||||||
{
|
{
|
||||||
sha1_update(&ctx, reinterpret_cast<const u8*>(&shdr), sizeof(spu_exec_object::shdr_t));
|
|
||||||
|
|
||||||
LOG_NOTICE(SPU, "** Section: sh_type=0x%x, addr=0x%llx, size=0x%llx, flags=0x%x", shdr.sh_type, shdr.sh_addr, shdr.sh_size, shdr.sh_flags);
|
LOG_NOTICE(SPU, "** Section: sh_type=0x%x, addr=0x%llx, size=0x%llx, flags=0x%x", shdr.sh_type, shdr.sh_addr, shdr.sh_size, shdr.sh_flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& prog : obj.progs)
|
for (const auto& prog : obj.progs)
|
||||||
{
|
{
|
||||||
sha1_update(&ctx, reinterpret_cast<const u8*>(&prog), sizeof(spu_exec_object::phdr_t));
|
|
||||||
sha1_update(&ctx, reinterpret_cast<const u8*>(prog.bin.data()), prog.bin.size());
|
|
||||||
|
|
||||||
LOG_NOTICE(SPU, "** Segment: p_type=0x%x, p_vaddr=0x%llx, p_filesz=0x%llx, p_memsz=0x%llx, flags=0x%x", prog.p_type, prog.p_vaddr, prog.p_filesz, prog.p_memsz, prog.p_flags);
|
LOG_NOTICE(SPU, "** Segment: p_type=0x%x, p_vaddr=0x%llx, p_filesz=0x%llx, p_memsz=0x%llx, flags=0x%x", prog.p_type, prog.p_vaddr, prog.p_filesz, prog.p_memsz, prog.p_flags);
|
||||||
|
|
||||||
if (prog.p_type == SYS_SPU_SEGMENT_TYPE_COPY)
|
if (prog.p_type == SYS_SPU_SEGMENT_TYPE_COPY)
|
||||||
@ -85,22 +74,6 @@ void sys_spu_image::load(const fs::file& stream)
|
|||||||
LOG_ERROR(SPU, "Unknown program type (0x%x)", prog.p_type);
|
LOG_ERROR(SPU, "Unknown program type (0x%x)", prog.p_type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sha1_finish(&ctx, output);
|
|
||||||
|
|
||||||
// Format patch name
|
|
||||||
std::string hash("spu-");
|
|
||||||
for (u8 x : output) fmt::append(hash, "%02x", x);
|
|
||||||
LOG_NOTICE(LOADER, "Loaded SPU image: %s", hash);
|
|
||||||
|
|
||||||
// Apply the patch
|
|
||||||
fxm::check_unlocked<patch_engine>()->apply(hash, vm::g_base_addr + addr);
|
|
||||||
|
|
||||||
if (!Emu.GetTitleID().empty())
|
|
||||||
{
|
|
||||||
// Alternative patch
|
|
||||||
fxm::check_unlocked<patch_engine>()->apply(Emu.GetTitleID() + '-' + hash, vm::g_base_addr + addr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void sys_spu_image::free()
|
void sys_spu_image::free()
|
||||||
@ -113,15 +86,29 @@ void sys_spu_image::free()
|
|||||||
|
|
||||||
void sys_spu_image::deploy(u32 loc)
|
void sys_spu_image::deploy(u32 loc)
|
||||||
{
|
{
|
||||||
|
// Segment info dump
|
||||||
|
std::string dump;
|
||||||
|
|
||||||
|
// Executable hash
|
||||||
|
sha1_context sha;
|
||||||
|
sha1_starts(&sha);
|
||||||
|
u8 sha1_hash[20];
|
||||||
|
|
||||||
for (int i = 0; i < nsegs; i++)
|
for (int i = 0; i < nsegs; i++)
|
||||||
{
|
{
|
||||||
auto& seg = segs[i];
|
auto& seg = segs[i];
|
||||||
|
|
||||||
LOG_NOTICE(SPU, "*** Deploy: t=0x%x, ls=0x%x, size=0x%x, addr=0x%x", seg.type, seg.ls, seg.size, seg.addr);
|
fmt::append(dump, "\n\t[%d] t=0x%x, ls=0x%x, size=0x%x, addr=0x%x", i, seg.type, seg.ls, seg.size, seg.addr);
|
||||||
|
|
||||||
|
// Hash big-endian values
|
||||||
|
sha1_update(&sha, (uchar*)&seg.type, sizeof(seg.type));
|
||||||
|
sha1_update(&sha, (uchar*)&seg.size, sizeof(seg.size));
|
||||||
|
|
||||||
if (seg.type == SYS_SPU_SEGMENT_TYPE_COPY)
|
if (seg.type == SYS_SPU_SEGMENT_TYPE_COPY)
|
||||||
{
|
{
|
||||||
std::memcpy(vm::base(loc + seg.ls), vm::base(seg.addr), seg.size);
|
std::memcpy(vm::base(loc + seg.ls), vm::base(seg.addr), seg.size);
|
||||||
|
sha1_update(&sha, (uchar*)&seg.ls, sizeof(seg.ls));
|
||||||
|
sha1_update(&sha, vm::g_base_addr + seg.addr, seg.size);
|
||||||
}
|
}
|
||||||
else if (seg.type == SYS_SPU_SEGMENT_TYPE_FILL)
|
else if (seg.type == SYS_SPU_SEGMENT_TYPE_FILL)
|
||||||
{
|
{
|
||||||
@ -131,8 +118,32 @@ void sys_spu_image::deploy(u32 loc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::fill_n(vm::_ptr<u32>(loc + seg.ls), seg.size / 4, seg.addr);
|
std::fill_n(vm::_ptr<u32>(loc + seg.ls), seg.size / 4, seg.addr);
|
||||||
|
sha1_update(&sha, (uchar*)&seg.ls, sizeof(seg.ls));
|
||||||
|
sha1_update(&sha, (uchar*)&seg.addr, sizeof(seg.addr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sha1_finish(&sha, sha1_hash);
|
||||||
|
|
||||||
|
// Format patch name
|
||||||
|
std::string hash("SPU-0000000000000000000000000000000000000000");
|
||||||
|
for (u32 i = 0; i < sizeof(sha1_hash); i++)
|
||||||
|
{
|
||||||
|
constexpr auto pal = "0123456789abcdef";
|
||||||
|
hash[4 + i * 2] = pal[sha1_hash[i] >> 4];
|
||||||
|
hash[5 + i * 2] = pal[sha1_hash[i] & 15];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply the patch
|
||||||
|
fxm::check_unlocked<patch_engine>()->apply(hash, vm::g_base_addr + loc);
|
||||||
|
|
||||||
|
if (!Emu.GetTitleID().empty())
|
||||||
|
{
|
||||||
|
// Alternative patch
|
||||||
|
fxm::check_unlocked<patch_engine>()->apply(Emu.GetTitleID() + '-' + hash, vm::g_base_addr + loc);
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_NOTICE(LOADER, "Loaded SPU image: %s%s", hash, dump);
|
||||||
}
|
}
|
||||||
|
|
||||||
error_code sys_spu_initialize(u32 max_usable_spu, u32 max_raw_spu)
|
error_code sys_spu_initialize(u32 max_usable_spu, u32 max_raw_spu)
|
||||||
|
@ -98,13 +98,13 @@ struct elf_phdr<en_t, u32>
|
|||||||
template<template<typename T> class en_t, typename sz_t>
|
template<template<typename T> class en_t, typename sz_t>
|
||||||
struct elf_prog final : elf_phdr<en_t, sz_t>
|
struct elf_prog final : elf_phdr<en_t, sz_t>
|
||||||
{
|
{
|
||||||
std::vector<char> bin;
|
std::vector<uchar> bin;
|
||||||
|
|
||||||
using base = elf_phdr<en_t, sz_t>;
|
using base = elf_phdr<en_t, sz_t>;
|
||||||
|
|
||||||
elf_prog() = default;
|
elf_prog() = default;
|
||||||
|
|
||||||
elf_prog(u32 type, u32 flags, sz_t vaddr, sz_t memsz, sz_t align, std::vector<char>&& bin)
|
elf_prog(u32 type, u32 flags, sz_t vaddr, sz_t memsz, sz_t align, std::vector<uchar>&& bin)
|
||||||
: bin(std::move(bin))
|
: bin(std::move(bin))
|
||||||
{
|
{
|
||||||
base::p_type = type;
|
base::p_type = type;
|
||||||
|
Loading…
Reference in New Issue
Block a user