Skip to content

Commit

Permalink
Merge branch 'master' of github.com:rajkosto/rpcs3 into mgs4
Browse files Browse the repository at this point in the history
  • Loading branch information
rajkosto committed Jan 14, 2020
2 parents 056645b + 9e47519 commit 1096788
Show file tree
Hide file tree
Showing 48 changed files with 964 additions and 341 deletions.
75 changes: 75 additions & 0 deletions Utilities/bin_patch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,3 +173,78 @@ std::size_t patch_engine::apply(const std::string& name, u8* dst) const

return found->second.size();
}

std::size_t patch_engine::apply_with_ls_check(const std::string& name, u8* dst, u32 filesz, u32 ls_addr) const
{
u32 rejected = 0;

const auto found = m_map.find(name);

if (found == m_map.cend())
{
return 0;
}

// Apply modifications sequentially
for (const auto& p : found->second)
{
auto ptr = dst + (p.offset - ls_addr);

if(p.offset < ls_addr || p.offset > (ls_addr + filesz))
{
// This patch is out of range for this segment
rejected++;
continue;
}

switch (p.type)
{
case patch_type::load:
{
// Invalid in this context
break;
}
case patch_type::byte:
{
*ptr = static_cast<u8>(p.value);
break;
}
case patch_type::le16:
{
*reinterpret_cast<le_t<u16, 1>*>(ptr) = static_cast<u16>(p.value);
break;
}
case patch_type::le32:
case patch_type::lef32:
{
*reinterpret_cast<le_t<u32, 1>*>(ptr) = static_cast<u32>(p.value);
break;
}
case patch_type::le64:
case patch_type::lef64:
{
*reinterpret_cast<le_t<u64, 1>*>(ptr) = static_cast<u64>(p.value);
break;
}
case patch_type::be16:
{
*reinterpret_cast<be_t<u16, 1>*>(ptr) = static_cast<u16>(p.value);
break;
}
case patch_type::be32:
case patch_type::bef32:
{
*reinterpret_cast<be_t<u32, 1>*>(ptr) = static_cast<u32>(p.value);
break;
}
case patch_type::be64:
case patch_type::bef64:
{
*reinterpret_cast<be_t<u64, 1>*>(ptr) = static_cast<u64>(p.value);
break;
}
}
}

return (found->second.size() - rejected);
}
2 changes: 2 additions & 0 deletions Utilities/bin_patch.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,6 @@ class patch_engine

// Apply patch (returns the number of entries applied)
std::size_t apply(const std::string& name, u8* dst) const;
// Apply patch with a check that the address exists in SPU local storage
std::size_t apply_with_ls_check(const std::string&name, u8*dst, u32 filesz, u32 ls_addr) const;
};
41 changes: 40 additions & 1 deletion Utilities/geometry.h
Original file line number Diff line number Diff line change
Expand Up @@ -856,14 +856,22 @@ struct color4_base
{
}

constexpr color4_base(T x, T y = {}, T z = {}, T w = {})
constexpr color4_base(T x, T y, T z, T w)
: x(x)
, y(y)
, z(z)
, w(w)
{
}

constexpr color4_base(T value)
: x(value)
, y(value)
, z(value)
, w(value)
{
}

constexpr bool operator == (const color4_base& rhs) const
{
return r == rhs.r && g == rhs.g && b == rhs.b && a == rhs.a;
Expand All @@ -874,6 +882,37 @@ struct color4_base
return !(*this == rhs);
}

void operator *= (const color4_base<T>& rhs)
{
r *= rhs.r;
g *= rhs.g;
b *= rhs.b;
a *= rhs.a;
}

void operator *= (const T& rhs)
{
r *= rhs;
g *= rhs;
b *= rhs;
a *= rhs;
}

constexpr color4_base<T> operator * (const color4_base<T>& rhs) const
{
return { r * rhs.r, g * rhs.g, b * rhs.b, a * rhs.a };
}

constexpr color4_base<T> operator * (const T& rhs) const
{
return { r * rhs, g * rhs, b * rhs, a * rhs };
}

constexpr color4_base<T> operator + (const color4_base<T>& rhs) const
{
return { r + rhs.r, g + rhs.g, b + rhs.b, a + rhs.a };
}

template<typename NT>
constexpr operator color4_base<NT>() const
{
Expand Down
2 changes: 1 addition & 1 deletion appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ version: '{build}'
image: Visual Studio 2019

environment:
QTDIR: C:\Qt\5.13\msvc2017_64
QTDIR: C:\Qt\5.14\msvc2017_64
QT_URL: https://cdn.discordapp.com/attachments/442667232489897997/614126952953020416/msvc2017_64.7z
LLVMLIBS: https://github.com/RPCS3/llvm/releases/download/continuous-master/llvmlibs.7z
GLSLANG: https://www.dropbox.com/s/6e8w6t5dxh3ad4l/glslang.7z?dl=1
Expand Down
10 changes: 10 additions & 0 deletions rpcs3/Emu/Cell/Modules/sceNpTrophy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -819,9 +819,19 @@ error_code sceNpTrophyUnlockTrophy(u32 context, u32 handle, s32 trophyId, vm::pt
}

if (trophyId < 0 || trophyId >= static_cast<s32>(ctxt->tropusr->GetTrophiesCount()))
{
return SCE_NP_TROPHY_ERROR_INVALID_TROPHY_ID;
}

if (ctxt->tropusr->GetTrophyGrade(trophyId) == SCE_NP_TROPHY_GRADE_PLATINUM)
{
return SCE_NP_TROPHY_ERROR_CANNOT_UNLOCK_PLATINUM;
}

if (ctxt->tropusr->GetTrophyUnlockState(trophyId))
{
return SCE_NP_TROPHY_ERROR_ALREADY_UNLOCKED;
}

ctxt->tropusr->UnlockTrophy(trophyId, 0, 0); // TODO: add timestamps

Expand Down
74 changes: 74 additions & 0 deletions rpcs3/Emu/Cell/PPUModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1152,6 +1152,80 @@ void ppu_load_exec(const ppu_exec_object& elf)
// Initialize HLE modules
ppu_initialize_modules(link);

// Embedded SPU elf patching
for (u32 i = _main->segs[0].addr; i < (_main->segs[0].addr + _main->segs[0].size); i += 4)
{
uchar* elf_header = vm::_ptr<u8>(i);
const spu_exec_object obj(fs::file(vm::base(vm::cast(i, HERE)), u32(0 - i)));

if (obj != elf_error::ok)
{
// This address does not have an SPU elf
continue;
}

// Segment info dump
std::string dump;

applied = 0;

// Executable hash
sha1_context sha2;
sha1_starts(&sha2);
u8 sha1_hash[20];

for (const auto& prog : obj.progs)
{
// Only hash the data, we are not loading it
sha1_update(&sha2, reinterpret_cast<const uchar*>(&prog.p_vaddr), sizeof(prog.p_vaddr));
sha1_update(&sha2, reinterpret_cast<const uchar*>(&prog.p_memsz), sizeof(prog.p_memsz));
sha1_update(&sha2, reinterpret_cast<const uchar*>(&prog.p_filesz), sizeof(prog.p_filesz));

fmt::append(dump, "\n\tSegment: p_type=0x%x, p_vaddr=0x%llx, p_filesz=0x%llx, p_memsz=0x%llx, p_offset=0x%llx", prog.p_type, prog.p_vaddr, prog.p_filesz, prog.p_memsz, prog.p_offset);

if (prog.p_type == 0x1 /* LOAD */ && prog.p_filesz > 0)
{
sha1_update(&sha2, (elf_header + prog.p_offset), prog.p_filesz);
}

else if (prog.p_type == 0x4 /* NOTE */ && prog.p_filesz > 0)
{
sha1_update(&sha2, (elf_header + prog.p_offset), prog.p_filesz);

// We assume that the string SPUNAME exists 0x14 bytes into the NOTE segment
const std::string spu_name = reinterpret_cast<const char*>(elf_header + prog.p_offset + 0x14);
fmt::append(dump, "\n\tSPUNAME: '%s'", spu_name);
}
}

sha1_finish(&sha2, 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];
}

// Try to patch each segment, will only succeed if the address exists in SPU local storage
for (const auto& prog : obj.progs)
{
// Apply the patch
applied += g_fxo->get<patch_engine>()->apply_with_ls_check(hash, (elf_header + prog.p_offset), prog.p_filesz, prog.p_vaddr);

if (!Emu.GetTitleID().empty())
{
// Alternative patch
applied += g_fxo->get<patch_engine>()->apply_with_ls_check(Emu.GetTitleID() + '-' + hash, (elf_header + prog.p_offset), prog.p_filesz, prog.p_vaddr);
}
}

LOG_NOTICE(LOADER, "SPU executable hash: %s (<- %u)%s", hash, applied, dump);

}

// Static HLE patching
if (g_cfg.core.hook_functions)
{
Expand Down
Loading

0 comments on commit 1096788

Please sign in to comment.