Merge pull request #1025 from Nekotekina/master

Various fixes
This commit is contained in:
Raul Tambre 2015-03-01 09:57:25 +02:00
commit 31bf130b1c
34 changed files with 1014 additions and 853 deletions

View file

@ -50,9 +50,9 @@ namespace Log
enum LogSeverity : u32
{
Success = 0,
Notice,
Notice = 0,
Warning,
Success,
Error,
};

View file

@ -465,7 +465,7 @@ typedef ucontext_t x64_context;
#define X64REG(context, reg) (darwin_x64reg(context, reg))
#define XMMREG(context, reg) (reinterpret_cast<u128*>(&(context)->uc_mcontext->__fs.__fpu_xmm0[reg]))
#define EFLAGS(context) ((context)->uc_mcontext->__ss.__eflags)
#define EFLAGS(context) ((context)->uc_mcontext->__ss.__rflags)
uint64_t* darwin_x64reg(x64_context *context, int reg)
{
@ -832,7 +832,7 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context)
return false;
}
memcpy(vm::get_priv_ptr(addr), XMMREG(context, reg - X64R_XMM0), 16);
memcpy(vm::priv_ptr(addr), XMMREG(context, reg - X64R_XMM0), 16);
break;
}
@ -842,7 +842,7 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context)
return false;
}
memcpy(vm::get_priv_ptr(addr), &reg_value, d_size);
memcpy(vm::priv_ptr(addr), &reg_value, d_size);
break;
}
case X64OP_MOVS:
@ -867,7 +867,7 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context)
// copy data
memcpy(&value, (void*)RSI(context), d_size);
memcpy(vm::get_priv_ptr(a_addr), &value, d_size);
memcpy(vm::priv_ptr(a_addr), &value, d_size);
// shift pointers
if (EFLAGS(context) & 0x400 /* direction flag */)
@ -925,7 +925,7 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context)
while (a_addr >> 12 == addr >> 12)
{
// fill data with value
memcpy(vm::get_priv_ptr(a_addr), &value, d_size);
memcpy(vm::priv_ptr(a_addr), &value, d_size);
// shift pointers
if (EFLAGS(context) & 0x400 /* direction flag */)
@ -966,10 +966,10 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context)
switch (d_size)
{
case 1: reg_value = vm::get_priv_ref<atomic_le_t<u8>>(addr).exchange((u8)reg_value); break;
case 2: reg_value = vm::get_priv_ref<atomic_le_t<u16>>(addr).exchange((u16)reg_value); break;
case 4: reg_value = vm::get_priv_ref<atomic_le_t<u32>>(addr).exchange((u32)reg_value); break;
case 8: reg_value = vm::get_priv_ref<atomic_le_t<u64>>(addr).exchange((u64)reg_value); break;
case 1: reg_value = vm::priv_ref<atomic_le_t<u8>>(addr).exchange((u8)reg_value); break;
case 2: reg_value = vm::priv_ref<atomic_le_t<u16>>(addr).exchange((u16)reg_value); break;
case 4: reg_value = vm::priv_ref<atomic_le_t<u32>>(addr).exchange((u32)reg_value); break;
case 8: reg_value = vm::priv_ref<atomic_le_t<u64>>(addr).exchange((u64)reg_value); break;
default: return false;
}
@ -989,10 +989,10 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context)
switch (d_size)
{
case 1: old_value = vm::get_priv_ref<atomic_le_t<u8>>(addr).compare_and_swap((u8)cmp_value, (u8)reg_value); break;
case 2: old_value = vm::get_priv_ref<atomic_le_t<u16>>(addr).compare_and_swap((u16)cmp_value, (u16)reg_value); break;
case 4: old_value = vm::get_priv_ref<atomic_le_t<u32>>(addr).compare_and_swap((u32)cmp_value, (u32)reg_value); break;
case 8: old_value = vm::get_priv_ref<atomic_le_t<u64>>(addr).compare_and_swap((u64)cmp_value, (u64)reg_value); break;
case 1: old_value = vm::priv_ref<atomic_le_t<u8>>(addr).compare_and_swap((u8)cmp_value, (u8)reg_value); break;
case 2: old_value = vm::priv_ref<atomic_le_t<u16>>(addr).compare_and_swap((u16)cmp_value, (u16)reg_value); break;
case 4: old_value = vm::priv_ref<atomic_le_t<u32>>(addr).compare_and_swap((u32)cmp_value, (u32)reg_value); break;
case 8: old_value = vm::priv_ref<atomic_le_t<u64>>(addr).compare_and_swap((u64)cmp_value, (u64)reg_value); break;
default: return false;
}

View file

@ -1,27 +0,0 @@
#include "stdafx.h"
#include "PPCThread.h"
#include "Emu/Memory/Memory.h"
PPCThread* GetCurrentPPCThread()
{
CPUThread* thread = GetCurrentCPUThread();
if(!thread || (thread->GetType() != CPU_THREAD_PPU && thread->GetType() != CPU_THREAD_SPU && thread->GetType() != CPU_THREAD_RAW_SPU))
{
throw std::string("GetCurrentPPCThread: bad thread");
}
return (PPCThread*)thread;
}
PPCThread::PPCThread(CPUThreadType type) : CPUThread(type)
{
}
PPCThread::~PPCThread()
{
}
void PPCThread::DoReset()
{
}

View file

@ -1,22 +0,0 @@
#pragma once
#include "Emu/CPU/CPUThread.h"
class PPCThread : public CPUThread
{
public:
virtual std::string GetThreadName() const
{
return fmt::format("%s[0x%08x]", GetFName(), PC);
}
protected:
PPCThread(CPUThreadType type);
public:
virtual ~PPCThread();
protected:
virtual void DoReset() override;
};
PPCThread* GetCurrentPPCThread();

View file

@ -652,22 +652,53 @@ namespace PPU_instr
r12, r13, r14, r15, r16, r17, r18, r19, r20, r21,
r22, r23, r24, r25, r26, r27, r28, r29, r30, r31
};
enum
{
cr0, cr1, cr2, cr3, cr4, cr5, cr6, cr7
};
}
namespace implicts
{
using namespace lists;
//static auto LIS = std::bind(ADDIS, std::placeholders::_1, r0, std::placeholders::_2);
//static auto LI = std::bind(ADDI, std::placeholders::_1, r0, std::placeholders::_2);
static auto NOP = std::bind(ORI, r0, r0, 0);
static auto MR = std::bind(OR, std::placeholders::_1, std::placeholders::_2, std::placeholders::_2, false);
static auto BLR = std::bind(BCLR, 0x10 | 0x04, 0, 0, 0);
static auto BCTR = std::bind(BCCTR, 0x10 | 0x04, 0, 0, 0);
static auto BCTRL = std::bind(BCCTR, 0x10 | 0x04, 0, 0, 1);
static auto MTCTR = std::bind(MTSPR, (0x1 << 5) | 0x8, std::placeholders::_1);
}
inline u32 LIS(u32 reg, u32 imm) { return ADDIS(reg, r0, imm); }
inline u32 LI_(u32 reg, u32 imm) { return ADDI(reg, r0, imm); }
inline u32 NOP() { return ORI(r0, r0, 0); }
inline u32 MR(u32 x, u32 y) { return OR(x, y, y, false); }
inline u32 BLR() { return BCLR(0x10 | 0x04, 0, 0, 0); }
inline u32 BCTR() { return BCCTR(0x10 | 0x04, 0, 0, 0); }
inline u32 BCTRL() { return BCCTR(0x10 | 0x04, 0, 0, 1); }
inline u32 MFCTR(u32 reg) { return MFSPR(reg, 9 << 5); }
inline u32 MTCTR(u32 reg) { return MTSPR(9 << 5, reg); }
inline u32 MFLR(u32 reg) { return MFSPR(reg, 8 << 5); }
inline u32 MTLR(u32 reg) { return MTSPR(8 << 5, reg); }
inline u32 BNE(u32 cr, s32 imm) { return BC(4, 2 | cr << 2, imm, 0, 0); }
inline u32 BEQ(u32 cr, s32 imm) { return BC(12, 2 | cr << 2, imm, 0, 0); }
inline u32 BGT(u32 cr, s32 imm) { return BC(12, 1 | cr << 2, imm, 0, 0); }
inline u32 BNE(s32 imm) { return BNE(cr0, imm); }
inline u32 BEQ(s32 imm) { return BEQ(cr0, imm); }
inline u32 BGT(s32 imm) { return BGT(cr0, imm); }
inline u32 CMPDI(u32 cr, u32 reg, u32 imm) { return CMPI(cr, 1, reg, imm); }
inline u32 CMPDI(u32 reg, u32 imm) { return CMPDI(cr0, reg, imm); }
inline u32 CMPWI(u32 cr, u32 reg, u32 imm) { return CMPI(cr, 0, reg, imm); }
inline u32 CMPWI(u32 reg, u32 imm) { return CMPWI(cr0, reg, imm); }
inline u32 CMPLDI(u32 cr, u32 reg, u32 imm) { return CMPLI(cr, 1, reg, imm); }
inline u32 CMPLDI(u32 reg, u32 imm) { return CMPLDI(cr0, reg, imm); }
inline u32 CMPLWI(u32 cr, u32 reg, u32 imm) { return CMPLI(cr, 0, reg, imm); }
inline u32 CMPLWI(u32 reg, u32 imm) { return CMPLWI(cr0, reg, imm); }
inline u32 EXTRDI(u32 x, u32 y, u32 n, u32 b) { return RLDICL(x, y, b + n, 64 - b, false); }
inline u32 SRDI(u32 x, u32 y, u32 n) { return RLDICL(x, y, 64 - n, n, false); }
inline u32 CLRLDI(u32 x, u32 y, u32 n) { return RLDICL(x, y, 0, n, false); }
}
using namespace lists;
using namespace implicts;

View file

@ -1,7 +1,7 @@
#pragma once
#include "PPUInstrTable.h"
/*#include "PPUInstrTable.h"
#include "Loader/ELF64.h"
/*
enum ArgType
{
ARG_ERR = 0,

View file

@ -19,14 +19,14 @@ extern void ppu_free_tls(u32 thread);
PPUThread& GetCurrentPPUThread()
{
PPCThread* thread = GetCurrentPPCThread();
CPUThread* thread = GetCurrentCPUThread();
if(!thread || thread->GetType() != CPU_THREAD_PPU) throw std::string("GetCurrentPPUThread: bad thread");
return *(PPUThread*)thread;
}
PPUThread::PPUThread() : PPCThread(CPU_THREAD_PPU)
PPUThread::PPUThread() : CPUThread(CPU_THREAD_PPU)
{
owned_mutexes = 0;
Reset();
@ -39,8 +39,6 @@ PPUThread::~PPUThread()
void PPUThread::DoReset()
{
PPCThread::DoReset();
//reset regs
memset(VPR, 0, sizeof(VPR));
memset(FPR, 0, sizeof(FPR));

View file

@ -1,6 +1,6 @@
#pragma once
#include "Emu/Cell/Common.h"
#include "Emu/Cell/PPCThread.h"
#include "Emu/CPU/CPUThread.h"
#include "Emu/Memory/vm.h"
enum
@ -467,7 +467,7 @@ struct FPRdouble
static int Cmp(PPCdouble a, PPCdouble b);
};
class PPUThread : public PPCThread
class PPUThread : public CPUThread
{
public:
PPCdouble FPR[32]; //Floating Point Register

View file

@ -47,7 +47,7 @@ bool RawSPUThread::Read32(const u32 addr, u32* value)
case SPU_MBox_Status_offs:
{
*value = (SPU.Out_MBox.GetCount() & 0xff) | (SPU.In_MBox.GetFreeCount() << 8);
*value = (SPU.Out_MBox.GetCount() & 0xff) | (SPU.In_MBox.GetFreeCount() << 8) | (SPU.Out_IntrMBox.GetCount() << 16);
break;
}

View file

@ -23,7 +23,7 @@
SPUThread& GetCurrentSPUThread()
{
PPCThread* thread = GetCurrentPPCThread();
CPUThread* thread = GetCurrentCPUThread();
if(!thread || (thread->GetType() != CPU_THREAD_SPU && thread->GetType() != CPU_THREAD_RAW_SPU))
{
@ -33,7 +33,7 @@ SPUThread& GetCurrentSPUThread()
return *(SPUThread*)thread;
}
SPUThread::SPUThread(CPUThreadType type) : PPCThread(type)
SPUThread::SPUThread(CPUThreadType type) : CPUThread(type)
{
assert(type == CPU_THREAD_SPU || type == CPU_THREAD_RAW_SPU);
@ -73,10 +73,8 @@ void SPUThread::Task()
void SPUThread::DoReset()
{
PPCThread::DoReset();
//reset regs
memset(GPR, 0, sizeof(u128) * 128);
memset(GPR, 0, sizeof(GPR));
}
void SPUThread::InitRegs()
@ -412,7 +410,7 @@ void SPUThread::EnqMfcCmd(MFCReg& MFCArgs)
{
vm::reservation_op(vm::cast(ea), 128, [this, tag, lsa, ea]()
{
memcpy(vm::get_priv_ptr(vm::cast(ea)), vm::get_ptr(ls_offset + lsa), 128);
memcpy(vm::priv_ptr(vm::cast(ea)), vm::get_ptr(ls_offset + lsa), 128);
});
if (op == MFC_PUTLLUC_CMD)
@ -568,7 +566,7 @@ void SPUThread::WriteChannel(u32 ch, const u128& r)
return;
}
//if (Ini.HLELogging.GetValue())
if (Ini.HLELogging.GetValue())
{
LOG_WARNING(Log::SPU, "sys_spu_thread_throw_event(spup=%d, data0=0x%x, data1=0x%x)", spup, v & 0x00ffffff, data);
}

View file

@ -1,7 +1,7 @@
#pragma once
#include "Emu/Cell/Common.h"
#include "Emu/CPU/CPUThread.h"
#include "Emu/Memory/atomic_type.h"
#include "PPCThread.h"
#include "Emu/SysCalls/lv2/sleep_queue_type.h"
#include "Emu/SysCalls/lv2/sys_event.h"
#include "Emu/Event.h"
@ -115,8 +115,6 @@ enum
struct g_imm_table_struct
{
//u16 cntb_table[65536];
__m128i fsmb_table[65536];
__m128i fsmh_table[256];
__m128i fsm_table[16];
@ -127,20 +125,8 @@ struct g_imm_table_struct
g_imm_table_struct()
{
/*static_assert(offsetof(g_imm_table_struct, cntb_table) == 0, "offsetof(cntb_table) != 0");
for (u32 i = 0; i < sizeof(cntb_table) / sizeof(cntb_table[0]); i++)
{
u32 cnt_low = 0, cnt_high = 0;
for (u32 j = 0; j < 8; j++)
{
cnt_low += (i >> j) & 1;
cnt_high += (i >> (j + 8)) & 1;
}
cntb_table[i] = (cnt_high << 8) | cnt_low;
}*/
for (u32 i = 0; i < sizeof(fsm_table) / sizeof(fsm_table[0]); i++)
{
for (u32 j = 0; j < 4; j++) mmToU32Ptr(fsm_table[i])[j] = (i & (1 << j)) ? ~0 : 0;
}
for (u32 i = 0; i < sizeof(fsmh_table) / sizeof(fsmh_table[0]); i++)
@ -287,7 +273,7 @@ union SPU_SNRConfig_hdr
struct SpuGroupInfo;
class SPUThread : public PPCThread
class SPUThread : public CPUThread
{
public:
u128 GPR[128]; // General-Purpose Registers

View file

@ -264,7 +264,7 @@ namespace vm
_reservation_set(addr, true);
// update memory using privileged access
memcpy(vm::get_priv_ptr(addr), data, size);
memcpy(vm::priv_ptr(addr), data, size);
// remove callback to not call it on successful update
g_reservation_cb = nullptr;
@ -362,7 +362,7 @@ namespace vm
}
void* real_addr = vm::get_ptr(addr);
void* priv_addr = vm::get_priv_ptr(addr);
void* priv_addr = vm::priv_ptr(addr);
#ifdef _WIN32
auto protection = flags & page_writable ? PAGE_READWRITE : (flags & page_readable ? PAGE_READONLY : PAGE_NOACCESS);
@ -464,7 +464,7 @@ namespace vm
}
void* real_addr = vm::get_ptr(addr);
void* priv_addr = vm::get_priv_ptr(addr);
void* priv_addr = vm::priv_ptr(addr);
#ifdef _WIN32
DWORD old;

View file

@ -77,15 +77,15 @@ namespace vm
}
template<typename T = void>
T* const get_priv_ptr(u32 addr)
T* const priv_ptr(u32 addr)
{
return reinterpret_cast<T*>(static_cast<u8*>(g_priv_addr) + addr);
}
template<typename T>
T& get_priv_ref(u32 addr)
T& priv_ref(u32 addr)
{
return *get_priv_ptr<T>(addr);
return *priv_ptr<T>(addr);
}
u32 get_addr(const void* real_pointer);

View file

@ -214,9 +214,9 @@ namespace vm
return vm::get_ptr<T>(vm::cast(m_addr));
}
T* get_priv_ptr() const
T* priv_ptr() const
{
return vm::get_priv_ptr<T>(vm::cast(m_addr));
return vm::priv_ptr<T>(vm::cast(m_addr));
}
static const _ptr_base make(const AT& addr)
@ -248,9 +248,9 @@ namespace vm
return vm::get_ptr<void>(vm::cast(m_addr));
}
void* get_priv_ptr() const
void* priv_ptr() const
{
return vm::get_priv_ptr<void>(vm::cast(m_addr));
return vm::priv_ptr<void>(vm::cast(m_addr));
}
explicit operator void*() const
@ -311,9 +311,9 @@ namespace vm
return vm::get_ptr<const void>(vm::cast(m_addr));
}
const void* get_priv_ptr() const
const void* priv_ptr() const
{
return vm::get_priv_ptr<const void>(vm::cast(m_addr));
return vm::priv_ptr<const void>(vm::cast(m_addr));
}
explicit operator const void*() const

View file

@ -53,6 +53,7 @@ extern Module sys_fs;
extern Module sys_io;
extern Module sys_net;
extern Module sysPrxForUser;
extern Module sys_libc;
struct ModuleInfo
{
@ -166,24 +167,27 @@ static const g_module_list[] =
{ -1, "cellSysmodule", &cellSysmodule },
{ -1, "libmixer", &libmixer },
{ -1, "sysPrxForUser", &sysPrxForUser },
{ -1, "sys_libc", &sys_libc },
};
void ModuleManager::Init()
{
if (!initialized)
if (initialized)
{
clear_ppu_functions();
for (auto& m : g_module_list)
{
if (m.module)
{
m.module->Init();
}
}
initialized = true;
Close();
}
clear_ppu_functions();
for (auto& m : g_module_list)
{
if (m.module)
{
m.module->Init();
}
}
initialized = true;
}
ModuleManager::ModuleManager()

View file

@ -30,21 +30,29 @@ u32 add_ppu_func_sub(StaticFunc func)
return func.index;
}
u32 add_ppu_func_sub(const char group[8], const u64 ops[], const char* name, Module* module, ppu_func_caller func)
u32 add_ppu_func_sub(const char group[8], const SearchPatternEntry ops[], const size_t count, const char* name, Module* module, ppu_func_caller func)
{
char group_name[9] = {};
if (group)
{
strcpy_trunc(group_name, group);
}
StaticFunc sf;
sf.index = add_ppu_func(ModuleFunc(get_function_id(name), 0, module, func));
sf.name = name;
sf.group = *(u64*)group;
sf.group = *(u64*)group_name;
sf.found = 0;
// TODO: check for self-inclusions, use CRC
for (u32 i = 0; ops[i]; i++)
for (u32 i = 0; i < count; i++)
{
SFuncOp op;
op.mask = re32((u32)(ops[i] >> 32));
op.crc = re32((u32)(ops[i]));
if (op.mask) op.crc &= op.mask;
SearchPatternEntry op;
op.type = ops[i].type;
op.data = re32(ops[i].data);
op.mask = re32(ops[i].mask);
op.num = ops[i].num;
assert(!op.mask || (op.data & ~op.mask) == 0);
sf.ops.push_back(op);
}
@ -166,90 +174,155 @@ u32 get_function_id(const char* name)
return (u32&)output[0];
}
void hook_ppu_funcs(u32* base, u32 size)
void hook_ppu_func(vm::ptr<u32> base, u32 pos, u32 size)
{
size /= 4;
using namespace PPU_instr;
for (auto& sub : g_ppu_func_subs)
{
bool found = true;
for (u32 k = pos, x = 0; x + 1 <= sub.ops.size(); k++, x++)
{
if (k >= size)
{
found = false;
break;
}
// skip NOP
if (base[k].data() == se32(0x60000000))
{
x--;
continue;
}
const u32 data = sub.ops[x].data;
const u32 mask = sub.ops[x].mask;
const bool match = (base[k].data() & mask) == data;
switch (sub.ops[x].type)
{
case SPET_MASKED_OPCODE:
{
// masked pattern
if (!match)
{
found = false;
}
break;
}
case SPET_OPTIONAL_MASKED_OPCODE:
{
// optional masked pattern
if (!match)
{
k--;
}
break;
}
case SPET_LABEL:
{
const auto addr = (base + k--).addr();
const auto lnum = data;
const auto label = sub.labels.find(lnum);
if (label == sub.labels.end()) // register the label
{
sub.labels[lnum] = addr;
}
else if (label->second != addr) // or check registered label
{
found = false;
}
break;
}
case SPET_BRANCH_TO_LABEL:
{
if (!match)
{
found = false;
break;
}
const auto addr = (base[k].data() & se32(2) ? 0 : (base + k).addr()) + ((s32)base[k] << cntlz32(mask) >> (cntlz32(mask) + 2));
const auto lnum = sub.ops[x].num;
const auto label = sub.labels.find(lnum);
if (label == sub.labels.end()) // register the label
{
sub.labels[lnum] = addr;
}
else if (label->second != addr) // or check registered label
{
found = false;
}
break;
}
//case SPET_BRANCH_TO_FUNC:
//{
// if (!match)
// {
// found = false;
// break;
// }
// const auto addr = (base[k].data() & se32(2) ? 0 : (base + k).addr()) + ((s32)base[k] << cntlz32(mask) >> (cntlz32(mask) + 2));
// const auto nid = sub.ops[x].num;
// // TODO: recursive call
//}
default:
{
LOG_ERROR(LOADER, "Unknown search pattern type (%d)", sub.ops[x].type);
assert(0);
return;
}
}
if (!found)
{
break;
}
}
if (found)
{
LOG_SUCCESS(LOADER, "Function '%s' hooked (addr=0x%x)", sub.name, (base + pos).addr());
sub.found++;
base[pos] = HACK(sub.index | EIF_PERFORM_BLR);
}
if (sub.labels.size())
{
sub.labels.clear();
}
}
}
void hook_ppu_funcs(vm::ptr<u32> base, u32 size)
{
using namespace PPU_instr;
if (!Ini.HLEHookStFunc.GetValue())
{
return;
}
// TODO: optimize search
for (u32 i = 0; i < size; i++)
{
for (u32 j = 0; j < g_ppu_func_subs.size(); j++)
// skip NOP
if (base[i].data() == se32(0x60000000))
{
if ((base[i] & g_ppu_func_subs[j].ops[0].mask) == g_ppu_func_subs[j].ops[0].crc)
{
bool found = true;
u32 can_skip = 0;
for (u32 k = i, x = 0; x + 1 <= g_ppu_func_subs[j].ops.size(); k++, x++)
{
if (k >= size)
{
found = false;
break;
}
// skip NOP
if (base[k] == se32(0x60000000))
{
x--;
continue;
}
const u32 mask = g_ppu_func_subs[j].ops[x].mask;
const u32 crc = g_ppu_func_subs[j].ops[x].crc;
if (!mask)
{
// TODO: define syntax
if (crc < 4) // skip various number of instructions that don't match next pattern entry
{
can_skip += crc;
k--; // process this position again
}
else if (base[k] != crc) // skippable pattern ("optional" instruction), no mask allowed
{
k--;
if (can_skip) // cannot define this behaviour properly
{
LOG_WARNING(LOADER, "hook_ppu_funcs(): can_skip = %d (unchanged)", can_skip);
}
}
else
{
if (can_skip) // cannot define this behaviour properly
{
LOG_WARNING(LOADER, "hook_ppu_funcs(): can_skip = %d (set to 0)", can_skip);
can_skip = 0;
}
}
}
else if ((base[k] & mask) != crc) // masked pattern
{
if (can_skip)
{
can_skip--;
}
else
{
found = false;
break;
}
}
else
{
can_skip = 0;
}
}
if (found)
{
LOG_NOTICE(LOADER, "Function '%s' hooked (addr=0x%x)", g_ppu_func_subs[j].name, vm::get_addr(base + i * 4));
g_ppu_func_subs[j].found++;
base[i] = re32(0x04000000 | g_ppu_func_subs[j].index | EIF_PERFORM_BLR); // hack
}
}
continue;
}
hook_ppu_func(base, i, size);
}
// check function groups
@ -259,6 +332,12 @@ void hook_ppu_funcs(u32* base, u32 size)
{
const u64 group = g_ppu_func_subs[i].group;
if (!group)
{
// skip if group not set
continue;
}
enum GroupSearchResult : u32
{
GSR_SUCCESS = 0, // every function from this group has been found once
@ -320,17 +399,17 @@ void hook_ppu_funcs(u32* base, u32 size)
if (g_ppu_func_subs[j].group == group) g_ppu_func_subs[j].found = 0;
}
char name[9] = "????????";
char group_name[9] = {};
*(u64*)name = group;
*(u64*)group_name = group;
if (res == GSR_SUCCESS)
{
LOG_SUCCESS(LOADER, "Function group [%s] successfully hooked", std::string(name, 9).c_str());
LOG_SUCCESS(LOADER, "Function group [%s] successfully hooked", group_name);
}
else
{
LOG_ERROR(LOADER, "Function group [%s] failed:%s%s", std::string(name, 9).c_str(),
LOG_ERROR(LOADER, "Function group [%s] failed:%s%s", group_name,
(res & GSR_MISSING ? " missing;" : ""),
(res & GSR_EXCESS ? " excess;" : ""));
}
@ -338,6 +417,102 @@ void hook_ppu_funcs(u32* base, u32 size)
}
}
bool patch_ppu_import(u32 addr, u32 index)
{
const auto data = vm::ptr<const u32>::make(addr);
using namespace PPU_instr;
// check different patterns:
if (vm::check_addr(addr, 32) &&
(data[0] & 0xffff0000) == LI_(r12, 0) &&
(data[1] & 0xffff0000) == ORIS(r12, r12, 0) &&
(data[2] & 0xffff0000) == LWZ(r12, r12, 0) &&
data[3] == STD(r2, r1, 0x28) &&
data[4] == LWZ(r0, r12, 0) &&
data[5] == LWZ(r2, r12, 4) &&
data[6] == MTCTR(r0) &&
data[7] == BCTR())
{
vm::write32(addr, HACK(index | EIF_SAVE_RTOC | EIF_PERFORM_BLR));
return true;
}
if (vm::check_addr(addr, 12) &&
(data[0] & 0xffff0000) == LI_(r0, 0) &&
(data[1] & 0xffff0000) == ORIS(r0, r0, 0) &&
(data[2] & 0xfc000003) == B(0, 0, 0))
{
const auto sub = vm::ptr<const u32>::make(addr + 8 + ((s32)data[2] << 6 >> 8 << 2));
if (vm::check_addr(sub.addr(), 60) &&
sub[0x0] == STDU(r1, r1, -0x80) &&
sub[0x1] == STD(r2, r1, 0x70) &&
sub[0x2] == MR(r2, r0) &&
sub[0x3] == MFLR(r0) &&
sub[0x4] == STD(r0, r1, 0x90) &&
sub[0x5] == LWZ(r2, r2, 0) &&
sub[0x6] == LWZ(r0, r2, 0) &&
sub[0x7] == LWZ(r2, r2, 4) &&
sub[0x8] == MTCTR(r0) &&
sub[0x9] == BCTRL() &&
sub[0xa] == LD(r2, r1, 0x70) &&
sub[0xb] == ADDI(r1, r1, 0x80) &&
sub[0xc] == LD(r0, r1, 0x10) &&
sub[0xd] == MTLR(r0) &&
sub[0xe] == BLR())
{
vm::write32(addr, HACK(index | EIF_PERFORM_BLR));
return true;
}
}
if (vm::check_addr(addr, 64) &&
data[0x0] == MFLR(r0) &&
data[0x1] == STD(r0, r1, 0x10) &&
data[0x2] == STDU(r1, r1, -0x80) &&
data[0x3] == STD(r2, r1, 0x70) &&
(data[0x4] & 0xffff0000) == LI_(r2, 0) &&
(data[0x5] & 0xffff0000) == ORIS(r2, r2, 0) &&
data[0x6] == LWZ(r2, r2, 0) &&
data[0x7] == LWZ(r0, r2, 0) &&
data[0x8] == LWZ(r2, r2, 4) &&
data[0x9] == MTCTR(r0) &&
data[0xa] == BCTRL() &&
data[0xb] == LD(r2, r1, 0x70) &&
data[0xc] == ADDI(r1, r1, 0x80) &&
data[0xd] == LD(r0, r1, 0x10) &&
data[0xe] == MTLR(r0) &&
data[0xf] == BLR())
{
vm::write32(addr, HACK(index | EIF_PERFORM_BLR));
return true;
}
if (vm::check_addr(addr, 56) &&
(data[0x0] & 0xffff0000) == LI_(r12, 0) &&
(data[0x1] & 0xffff0000) == ORIS(r12, r12, 0) &&
(data[0x2] & 0xffff0000) == LWZ(r12, r12, 0) &&
data[0x3] == STD(r2, r1, 0x28) &&
data[0x4] == MFLR(r0) &&
data[0x5] == STD(r0, r1, 0x20) &&
data[0x6] == LWZ(r0, r12, 0) &&
data[0x7] == LWZ(r2, r12, 4) &&
data[0x8] == MTCTR(r0) &&
data[0x9] == BCTRL() &&
data[0xa] == LD(r0, r1, 0x20) &&
data[0xb] == MTLR(r0) &&
data[0xc] == LD(r2, r1, 0x28) &&
data[0xd] == BLR())
{
vm::write32(addr, HACK(index | EIF_PERFORM_BLR));
return true;
}
return false;
}
Module::Module(const char* name, void(*init)())
: m_is_loaded(false)
, m_name(name)

View file

@ -43,19 +43,31 @@ struct ModuleFunc
}
};
struct SFuncOp
enum : u32
{
u32 crc;
SPET_MASKED_OPCODE,
SPET_OPTIONAL_MASKED_OPCODE,
SPET_LABEL,
SPET_BRANCH_TO_LABEL,
SPET_BRANCH_TO_FUNC,
};
struct SearchPatternEntry
{
u32 type;
u32 data;
u32 mask;
u32 num; // supplement info
};
struct StaticFunc
{
u32 index;
const char* name;
std::vector<SFuncOp> ops;
std::vector<SearchPatternEntry> ops;
u64 group;
u32 found;
std::unordered_map<u32, u32> labels;
};
class Module : public LogBase
@ -138,17 +150,26 @@ void clear_ppu_functions();
u32 get_function_id(const char* name);
u32 add_ppu_func_sub(StaticFunc sf);
u32 add_ppu_func_sub(const char group[8], const u64 ops[], const char* name, Module* module, ppu_func_caller func);
u32 add_ppu_func_sub(const char group[8], const SearchPatternEntry ops[], size_t count, const char* name, Module* module, ppu_func_caller func);
void hook_ppu_funcs(u32* base, u32 size);
void hook_ppu_funcs(vm::ptr<u32> base, u32 size);
bool patch_ppu_import(u32 addr, u32 index);
#define REG_FUNC(module, name) add_ppu_func(ModuleFunc(get_function_id(#name), 0, &module, bind_func(name)))
#define REG_FUNC_FH(module, name) add_ppu_func(ModuleFunc(get_function_id(#name), MFF_FORCED_HLE, &module, bind_func(name)))
#define REG_UNNAMED(module, nid) add_ppu_func(ModuleFunc(0x##nid, 0, &module, bind_func(_nid_##nid)))
#define REG_SUB(module, group, name, ...) \
static const u64 name ## _table[] = {__VA_ARGS__ , 0}; \
if (name ## _table[0]) add_ppu_func_sub(group, name ## _table, #name, &module, bind_func(name))
#define REG_SUB(module, group, ns, name, ...) \
const SearchPatternEntry name##_table[] = {__VA_ARGS__}; \
add_ppu_func_sub(group, name##_table, sizeof(name##_table) / sizeof(SearchPatternEntry), #name, &module, bind_func(ns::name))
#define se_op_all(type, op, sup) []() { s32 XXX = 0; SearchPatternEntry res = { (type), (op), 0, (sup) }; XXX = -1; res.mask = (op) ^ ~res.data; return res; }()
#define se_op(op) se_op_all(SPET_MASKED_OPCODE, op, 0)
#define se_opt_op(op) se_op_all(SPET_OPTIONAL_MASKED_OPCODE, op, 0)
#define se_label(label) { SPET_LABEL, (label) }
#define se_br_label(op, label) se_op_all(SPET_BRANCH_TO_LABEL, op, label)
#define se_func_call(op, name) se_op_all(SPET_BRANCH_TO_FUNC, op, get_function_id(#name))
#define UNIMPLEMENTED_FUNC(module) module.Error("%s", __FUNCTION__)

View file

@ -168,7 +168,7 @@ bool spursKernel1SelectWorkload(SPUThread & spu) {
vm::reservation_op(vm::cast(ctxt->spurs.addr()), 128, [&]() {
// lock the first 0x80 bytes of spurs
auto spurs = ctxt->spurs.get_priv_ptr();
auto spurs = ctxt->spurs.priv_ptr();
// Calculate the contention (number of SPUs used) for each workload
u8 contention[CELL_SPURS_MAX_WORKLOAD];
@ -325,7 +325,7 @@ bool spursKernel2SelectWorkload(SPUThread & spu) {
vm::reservation_op(vm::cast(ctxt->spurs.addr()), 128, [&]() {
// lock the first 0x80 bytes of spurs
auto spurs = ctxt->spurs.get_priv_ptr();
auto spurs = ctxt->spurs.priv_ptr();
// Calculate the contention (number of SPUs used) for each workload
u8 contention[CELL_SPURS_MAX_WORKLOAD2];
@ -696,7 +696,7 @@ void spursSysServiceMain(SPUThread & spu, u32 pollStatus) {
vm::reservation_acquire(vm::get_ptr(spu.ls_offset + 0x100), vm::cast(ctxt->spurs.addr()), 128);
vm::reservation_op(vm::cast(ctxt->spurs.addr() + offsetof(CellSpurs, m.wklState1)), 128, [&]() {
auto spurs = ctxt->spurs.get_priv_ptr();
auto spurs = ctxt->spurs.priv_ptr();
// Halt if already initialised
if (spurs->m.sysSrvOnSpu & (1 << ctxt->spuNum)) {
@ -786,7 +786,7 @@ void spursSysServiceProcessRequests(SPUThread & spu, SpursKernelContext * ctxt)
bool terminate = false;
vm::reservation_op(vm::cast(ctxt->spurs.addr() + offsetof(CellSpurs, m.wklState1)), 128, [&]() {
auto spurs = ctxt->spurs.get_priv_ptr();
auto spurs = ctxt->spurs.priv_ptr();
// Terminate request
if (spurs->m.sysSrvMsgTerminate & (1 << ctxt->spuNum)) {
@ -853,7 +853,7 @@ void spursSysServiceActivateWorkload(SPUThread & spu, SpursKernelContext * ctxt)
}
vm::reservation_op(vm::cast(ctxt->spurs.addr() + offsetof(CellSpurs, m.wklState1)), 128, [&]() {
auto spurs = ctxt->spurs.get_priv_ptr();
auto spurs = ctxt->spurs.priv_ptr();
for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) {
// Update workload status and runnable flag based on the workload state
@ -910,7 +910,7 @@ void spursSysServiceUpdateShutdownCompletionEvents(SPUThread & spu, SpursKernelC
u32 wklNotifyBitSet;
u8 spuPort;
vm::reservation_op(vm::cast(ctxt->spurs.addr() + offsetof(CellSpurs, m.wklState1)), 128, [&]() {
auto spurs = ctxt->spurs.get_priv_ptr();
auto spurs = ctxt->spurs.priv_ptr();
wklNotifyBitSet = 0;
spuPort = spurs->m.spuPort;;
@ -952,7 +952,7 @@ void spursSysServiceTraceUpdate(SPUThread & spu, SpursKernelContext * ctxt, u32
u8 sysSrvMsgUpdateTrace;
vm::reservation_op(vm::cast(ctxt->spurs.addr() + offsetof(CellSpurs, m.wklState1)), 128, [&]() {
auto spurs = ctxt->spurs.get_priv_ptr();
auto spurs = ctxt->spurs.priv_ptr();
sysSrvMsgUpdateTrace = spurs->m.sysSrvMsgUpdateTrace;
spurs->m.sysSrvMsgUpdateTrace &= ~(1 << ctxt->spuNum);
@ -1006,7 +1006,7 @@ void spursSysServiceCleanupAfterSystemWorkload(SPUThread & spu, SpursKernelConte
bool do_return = false;
vm::reservation_op(vm::cast(ctxt->spurs.addr() + offsetof(CellSpurs, m.wklState1)), 128, [&]() {
auto spurs = ctxt->spurs.get_priv_ptr();
auto spurs = ctxt->spurs.priv_ptr();
if (spurs->m.sysSrvWorkload[ctxt->spuNum] == 0xFF) {
do_return = true;
@ -1024,7 +1024,7 @@ void spursSysServiceCleanupAfterSystemWorkload(SPUThread & spu, SpursKernelConte
spursSysServiceActivateWorkload(spu, ctxt);
vm::reservation_op(vm::cast(ctxt->spurs.addr()), 128, [&]() {
auto spurs = ctxt->spurs.get_priv_ptr();
auto spurs = ctxt->spurs.priv_ptr();
if (wklId >= CELL_SPURS_MAX_WORKLOAD) {
spurs->m.wklCurrentContention[wklId & 0x0F] -= 0x10;
@ -1158,7 +1158,7 @@ s32 spursTasksetProcessRequest(SPUThread & spu, s32 request, u32 * taskId, u32 *
s32 rc = CELL_OK;
s32 numNewlyReadyTasks;
vm::reservation_op(vm::cast(ctxt->taskset.addr()), 128, [&]() {
auto taskset = ctxt->taskset.get_priv_ptr();
auto taskset = ctxt->taskset.priv_ptr();
// Verify taskset state is valid
auto _0 = be_t<u128>::make(u128::from32(0));
@ -1299,7 +1299,7 @@ s32 spursTasksetProcessRequest(SPUThread & spu, s32 request, u32 * taskId, u32 *
// Increment the ready count of the workload by the number of tasks that have become ready
vm::reservation_op(vm::cast(kernelCtxt->spurs.addr()), 128, [&]() {
auto spurs = kernelCtxt->spurs.get_priv_ptr();
auto spurs = kernelCtxt->spurs.priv_ptr();
s32 readyCount = kernelCtxt->wklCurrentId < CELL_SPURS_MAX_WORKLOAD ? spurs->m.wklReadyCount1[kernelCtxt->wklCurrentId].read_relaxed() : spurs->m.wklIdleSpuCountOrReadyCount2[kernelCtxt->wklCurrentId & 0x0F].read_relaxed();
readyCount += numNewlyReadyTasks;

File diff suppressed because it is too large Load diff

View file

@ -559,13 +559,12 @@ s32 _sys_printf(vm::ptr<const char> fmt) // va_args...
return CELL_OK;
}
s32 _nid_E75C40F2(u32 dest)
s32 sys_process_get_paramsfo(vm::ptr<char> buffer)
{
sysPrxForUser.Todo("Unnamed function 0xE75C40F2 (dest=0x%x) -> CELL_ENOENT", dest);
sysPrxForUser.Warning("sys_process_get_paramsfo(buffer=0x%x)", buffer);
// prx: load some data (0x40 bytes) previously set by sys_process_get_paramsfo
//memset(Memory + dest, 0, 0x40);
return CELL_ENOENT;
// prx: load some data (0x40 bytes) previously set by _sys_process_get_paramsfo syscall
return _sys_process_get_paramsfo(buffer);
}
Module sysPrxForUser("sysPrxForUser", []()
@ -674,5 +673,5 @@ Module sysPrxForUser("sysPrxForUser", []()
REG_FUNC(sysPrxForUser, _sys_printf);
REG_UNNAMED(sysPrxForUser, E75C40F2);
REG_FUNC(sysPrxForUser, sys_process_get_paramsfo);
});

View file

@ -0,0 +1,33 @@
#include "stdafx.h"
#include "Emu/Memory/Memory.h"
#include "Emu/System.h"
#include "Emu/SysCalls/Modules.h"
#include "Emu/Cell/PPUInstrTable.h"
extern Module sys_libc;
namespace sys_libc_func
{
void memcpy(vm::ptr<void> dst, vm::ptr<const void> src, u32 size)
{
sys_libc.Warning("memcpy(dst=0x%x, src=0x%x, size=0x%x)", dst, src, size);
::memcpy(dst.get_ptr(), src.get_ptr(), size);
}
}
Module sys_libc("sys_libc", []()
{
using namespace PPU_instr;
REG_SUB(sys_libc, "", sys_libc_func, memcpy,
se_op(CMPLDI(cr7, r5, 7)),
se_op(CLRLDI(r3, r3, 32)),
se_op(CLRLDI(r4, r4, 32)),
se_op(MR(r11, r3)),
se_op(BGT(cr7, XXX & 0xff)),
se_op(CMPDI(r5, 0)),
se_opt_op(MR(r9, r3)),
{ SPET_MASKED_OPCODE, 0x4d820020, 0xffffffff },
);
});

View file

@ -80,7 +80,7 @@ const ppu_func_caller sc_table[1024] =
null_func,//bind_func(), //27 (0x01B) DBG
null_func,//bind_func(_sys_process_get_number_of_object)//28 (0x01C) ROOT
bind_func(sys_process_get_id), //29 (0x01D) ROOT
bind_func(sys_process_get_paramsfo), //30 (0x01E)
bind_func(_sys_process_get_paramsfo), //30 (0x01E)
null_func,//bind_func(sys_process_get_ppu_guid), //31 (0x01F)
null_func, null_func, null_func, null_func, null_func, null_func, null_func, null_func, null_func, //32-40 UNS

View file

@ -4,6 +4,8 @@
#include "Emu/System.h"
#include "Emu/SysCalls/SysCalls.h"
#include "Emu/FS/vfsFile.h"
#include "Loader/PSF.h"
#include "sys_memory.h"
#include "sys_process.h"
@ -286,29 +288,25 @@ s32 sys_process_is_spu_lock_line_reservation_address(u32 addr, u64 flags)
return process_is_spu_lock_line_reservation_address(addr, flags);
}
s32 sys_process_get_paramsfo(vm::ptr<u8> buffer)
s32 _sys_process_get_paramsfo(vm::ptr<char> buffer)
{
sys_process.Todo("sys_process_get_paramsfo(buffer_addr=0x%x) -> CELL_ENOENT", buffer.addr());
return CELL_ENOENT;
sys_process.Warning("_sys_process_get_paramsfo(buffer=0x%x)", buffer);
/*//Before uncommenting this code, we should check if it is actually working.
MemoryAllocator<be_t<u32>> fd;
char filePath [] = "/app_home/../PARAM.SFO";
if (!cellFsOpen(Memory.RealToVirtualAddr(filePath), 0, fd, NULL, 0))
if (!Emu.GetTitleID().length())
{
return CELL_ENOENT;
}
MemoryAllocator<be_t<u64>> pos, nread;
cellFsLseek(fd, 0, CELL_SEEK_SET, pos); //TODO: Move to the appropriate offset (probably 0x3F7)
cellFsRead(fd, buffer.addr(), 40, nread); //WARNING: If offset==0x3F7: The file will end before the buffer (40 bytes) is filled!
cellFsClose(fd);
memset(buffer.get_ptr(), 0, 0x40);
memcpy(buffer.get_ptr() + 1, Emu.GetTitleID().c_str(), std::min<size_t>(Emu.GetTitleID().length(), 9));
return CELL_OK;*/
return CELL_OK;
}
s32 process_get_sdk_version(u32 pid, s32& ver)
{
// TODO: get correct SDK version for selected pid
ver = Emu.m_sdk_version;
// get correct SDK version for selected pid
ver = Emu.GetSDKVersion();
return CELL_OK;
}

View file

@ -33,7 +33,7 @@ s32 sys_process_getpid();
s32 sys_process_getppid();
s32 sys_process_get_number_of_object(u32 object, vm::ptr<u32> nump);
s32 sys_process_get_id(u32 object, vm::ptr<u32> buffer, u32 size, vm::ptr<u32> set_size);
s32 sys_process_get_paramsfo(vm::ptr<u8> buffer);
s32 _sys_process_get_paramsfo(vm::ptr<char> buffer);
s32 sys_process_get_sdk_version(u32 pid, vm::ptr<s32> version);
s32 sys_process_get_status(u64 unk);
s32 sys_process_is_spu_lock_line_reservation_address(u32 addr, u64 flags);

View file

@ -38,11 +38,6 @@ static const std::string& BreakPointsDBName = "BreakPoints.dat";
static const u16 bpdb_version = 0x1000;
extern std::atomic<u32> g_thread_count;
ModuleInitializer::ModuleInitializer()
{
Emu.AddModuleInit(std::move(std::unique_ptr<ModuleInitializer>(this)));
}
Emulator::Emulator()
: m_status(Stopped)
, m_mode(DisAsm)
@ -82,11 +77,6 @@ Emulator::~Emulator()
void Emulator::Init()
{
while(m_modules_init.size())
{
m_modules_init[0]->Init();
m_modules_init.erase(m_modules_init.begin());
}
}
void Emulator::SetPath(const std::string& path, const std::string& elf_path)
@ -265,24 +255,7 @@ void Emulator::Load()
vm::close();
return;
}
// trying to load some info from PARAM.SFO
vfsFile f2("/app_home/../PARAM.SFO");
if (f2.IsOpened())
{
PSFLoader psf(f2);
if (psf.Load(false))
{
std::string version = psf.GetString("PS3_SYSTEM_VER");
const size_t dot = version.find('.');
if (dot != std::string::npos)
{
Emu.m_sdk_version = (std::stoi(version, nullptr, 16) << 20) | ((std::stoi(version.substr(dot + 1), nullptr, 16) & 0xffff) << 4) | 1;
}
}
}
LoadPoints(BreakPointsDBName);
m_status = Ready;

View file

@ -61,14 +61,6 @@ public:
u32 GetTLSMemsz() const { return tls_memsz; }
};
class ModuleInitializer
{
public:
ModuleInitializer();
virtual void Init() = 0;
};
class Emulator
{
enum Mode
@ -83,7 +75,6 @@ class Emulator
u32 m_rsx_callback;
u32 m_cpu_thr_stop;
std::vector<std::unique_ptr<ModuleInitializer>> m_modules_init;
std::vector<u64> m_break_points;
std::vector<u64> m_marked_points;
@ -112,7 +103,6 @@ public:
std::string m_emu_path;
std::string m_title_id;
std::string m_title;
s32 m_sdk_version;
Emulator();
~Emulator();
@ -132,12 +122,12 @@ public:
return m_emu_path;
}
std::string GetTitleID() const
const std::string& GetTitleID() const
{
return m_title_id;
}
std::string GetTitle() const
const std::string& GetTitle() const
{
return m_title;
}
@ -164,11 +154,6 @@ public:
ModuleManager& GetModuleManager() { return *m_module_manager; }
SyncPrimManager& GetSyncPrimManager() { return *m_sync_prim_manager; }
void AddModuleInit(std::unique_ptr<ModuleInitializer> m)
{
m_modules_init.push_back(std::move(m));
}
void SetTLSData(u32 addr, u32 filesz, u32 memsz)
{
m_info.SetTLSData(addr, filesz, memsz);
@ -191,6 +176,7 @@ public:
u32 GetTLSMemsz() const { return m_info.GetTLSMemsz(); }
u32 GetMallocPageSize() { return m_info.GetProcParam().malloc_pagesize; }
u32 GetSDKVersion() { return m_info.GetProcParam().sdk_version; }
u32 GetRSXCallback() const { return m_rsx_callback; }
u32 GetCPUThreadStop() const { return m_cpu_thr_stop; }

View file

@ -1,8 +1,9 @@
#include "stdafx_gui.h"
#include "Utilities/rMsgBox.h"
#include "Emu/Cell/PPUProgramCompiler.h"
using namespace PPU_opcodes;
//#include "Emu/Cell/PPUProgramCompiler.h"
//using namespace PPU_opcodes;
#include "CompilerELF.h"
enum CompilerIDs
@ -392,8 +393,8 @@ void CompilerELF::LoadElf(wxCommandEvent& event)
LoadElf(fmt::ToUTF8(ctrl.GetPath()));
}
#include "Emu/Cell/PPUDisAsm.h"
#include "Emu/Cell/PPUDecoder.h"
//#include "Emu/Cell/PPUDisAsm.h"
//#include "Emu/Cell/PPUDecoder.h"
void CompilerELF::LoadElf(const std::string& path)
{

View file

@ -29,20 +29,22 @@ struct wxWriter : Log::LogListener
wxTextAttr m_color_white;
wxTextAttr m_color_yellow;
wxTextAttr m_color_red;
wxTextAttr m_color_green;
MTRingbuffer<char, BUFFER_MAX_SIZE> messages;
std::atomic<bool> newLog;
bool inited;
wxWriter(wxTextCtrl* p_log, wxTextCtrl* p_tty) :
m_color_white(wxColour(255, 255, 255)) ,
m_color_yellow(wxColour(255, 255, 0)) ,
m_color_red(wxColour(255, 0, 0)) ,
m_log(p_log),
m_tty(p_tty),
newLog(false),
inited(false)
wxWriter(wxTextCtrl* p_log, wxTextCtrl* p_tty)
: m_color_white(wxColour(255, 255, 255))
, m_color_yellow(wxColour(255, 255, 0))
, m_color_red(wxColour(255, 0, 0))
, m_color_green(wxColour(0, 255, 0))
, m_log(p_log)
, m_tty(p_tty)
, newLog(false)
, inited(false)
{
m_log->Bind(EVT_LOG_COMMAND, [this](wxCommandEvent &evt){this->write(evt);});
m_log->Bind(EVT_LOG_COMMAND, [this](wxCommandEvent &evt){ this->write(evt); });
}
wxWriter(wxWriter &other) = delete;
@ -83,6 +85,9 @@ struct wxWriter : Log::LogListener
case Log::Error:
llogcon->SetDefaultStyle(m_color_red);
break;
case Log::Success:
llogcon->SetDefaultStyle(m_color_green);
break;
default:
break;
}

View file

@ -7,7 +7,7 @@
#include "Debugger.h"
#include "InterpreterDisAsm.h"
#include "Emu/CPU/CPUThreadManager.h"
#include "Emu/Cell/PPCThread.h"
#include "Emu/CPU/CPUThread.h"
class DbgEmuPanel : public wxPanel
@ -95,7 +95,7 @@ public:
break;
case DID_EXIT_THR_SYSCALL:
Emu.GetCPU().RemoveThread(((PPCThread*)event.GetClientData())->GetId());
Emu.GetCPU().RemoveThread(((CPUThread*)event.GetClientData())->GetId());
break;
}

View file

@ -62,7 +62,7 @@ void GLGSFrame::Flip(void* context)
canvas->SwapBuffers();
m_frames++;
const std::string sub_title = Emu.GetTitle() += Emu.GetTitleID().length() ? " [" + Emu.GetTitleID() + "] | " : " | ";
const std::string sub_title = Emu.GetTitle() + (Emu.GetTitleID().length() ? " [" + Emu.GetTitleID() + "] | " : " | ");
if (fps_t.GetElapsedTimeInSec() >= 0.5)
{

View file

@ -487,8 +487,8 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event))
cbox_camera_type->Append("USB Video Class 1.1");
cbox_hle_loglvl->Append("All");
cbox_hle_loglvl->Append("Success");
cbox_hle_loglvl->Append("Warnings");
cbox_hle_loglvl->Append("Success");
cbox_hle_loglvl->Append("Errors");
cbox_hle_loglvl->Append("Nothing");

View file

@ -307,8 +307,6 @@ namespace loader
return load_sprx(info);
}
Emu.m_sdk_version = -1;
//store elf to memory
vm::ps3::init();
@ -467,14 +465,10 @@ namespace loader
LOG_NOTICE(LOADER, "Imported function '%s' (0x%x)", SysCalls::GetHLEFuncName(nid), addr);
}
if (!vm::check_addr(addr, 4))
if (!patch_ppu_import(addr, index))
{
LOG_ERROR(LOADER, "Failed to inject code for function '%s' (0x%x)", SysCalls::GetHLEFuncName(nid), addr);
}
else
{
vm::write32(addr, HACK(index | EIF_SAVE_RTOC | EIF_PERFORM_BLR));
}
}
}
}
@ -576,7 +570,7 @@ namespace loader
{
m_stream->Seek(handler::get_stream_offset() + phdr.p_offset);
m_stream->Read(phdr.p_vaddr.get_ptr(), phdr.p_filesz);
hook_ppu_funcs((u32*)phdr.p_vaddr.get_ptr(), vm::cast(phdr.p_filesz));
hook_ppu_funcs(vm::ptr<u32>::make(phdr.p_vaddr.addr()), vm::cast(phdr.p_filesz) / 4);
}
}
break;
@ -618,7 +612,6 @@ namespace loader
*/
info = proc_param.info;
Emu.m_sdk_version = info.sdk_version;
}
}
break;
@ -689,7 +682,10 @@ namespace loader
LOG_NOTICE(LOADER, "Imported %sfunction '%s' in '%s' module (0x%x)", is_lle ? "LLE " : "", SysCalls::GetHLEFuncName(nid), module_name, addr);
}
vm::write32(addr, HACK(index | EIF_SAVE_RTOC | EIF_PERFORM_BLR));
if (!patch_ppu_import(addr, index))
{
LOG_ERROR(LOADER, "Failed to inject code at address 0x%x", addr);
}
//if (!func || !func->lle_func)
//{

View file

@ -131,7 +131,6 @@
<ClCompile Include="Emu\Audio\XAudio2\XAudio2Thread.cpp" />
<ClCompile Include="Emu\Cell\MFC.cpp" />
<ClCompile Include="Emu\Cell\PPCDecoder.cpp" />
<ClCompile Include="Emu\Cell\PPCThread.cpp" />
<ClCompile Include="Emu\Cell\PPULLVMRecompilerTests.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug - MemLeak|x64'">true</ExcludedFromBuild>
@ -279,6 +278,7 @@
<ClCompile Include="Emu\SysCalls\Modules\sysPrxForUser.cpp" />
<ClCompile Include="Emu\SysCalls\Modules\sys_http.cpp" />
<ClCompile Include="Emu\SysCalls\Modules\sys_io.cpp" />
<ClCompile Include="Emu\SysCalls\Modules\sys_libc.cpp" />
<ClCompile Include="Emu\SysCalls\Modules\sys_net.cpp" />
<ClCompile Include="Emu\SysCalls\SyncPrimitivesManager.cpp" />
<ClCompile Include="Emu\SysCalls\SysCalls.cpp" />
@ -362,7 +362,6 @@
<ClInclude Include="Emu\Cell\PPCDecoder.h" />
<ClInclude Include="Emu\Cell\PPCDisAsm.h" />
<ClInclude Include="Emu\Cell\PPCInstrTable.h" />
<ClInclude Include="Emu\Cell\PPCThread.h" />
<ClInclude Include="Emu\Cell\PPUDecoder.h" />
<ClInclude Include="Emu\Cell\PPUDisAsm.h" />
<ClInclude Include="Emu\Cell\PPUInstrTable.h" />

View file

@ -341,9 +341,6 @@
<ClCompile Include="Emu\Cell\PPCDecoder.cpp">
<Filter>Emu\CPU\Cell</Filter>
</ClCompile>
<ClCompile Include="Emu\Cell\PPCThread.cpp">
<Filter>Emu\CPU\Cell</Filter>
</ClCompile>
<ClCompile Include="Emu\Cell\PPUThread.cpp">
<Filter>Emu\CPU\Cell</Filter>
</ClCompile>
@ -860,6 +857,9 @@
<ClCompile Include="Emu\RSX\CgBinaryVertexProgram.cpp">
<Filter>Emu\GPU\RSX</Filter>
</ClCompile>
<ClCompile Include="Emu\SysCalls\Modules\sys_libc.cpp">
<Filter>Emu\SysCalls\Modules</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Crypto\aes.h">
@ -1105,9 +1105,6 @@
<ClInclude Include="Emu\Cell\PPCInstrTable.h">
<Filter>Emu\CPU\Cell</Filter>
</ClInclude>
<ClInclude Include="Emu\Cell\PPCThread.h">
<Filter>Emu\CPU\Cell</Filter>
</ClInclude>
<ClInclude Include="Emu\Cell\PPUDecoder.h">
<Filter>Emu\CPU\Cell</Filter>
</ClInclude>