- Fixed loading modules in debug mode.

- Improved Lwmutex.
- Implemented events syscalls.
- Fixed SPU local storage.
This commit is contained in:
DH 2013-07-06 02:49:38 +03:00
parent 991f281bbd
commit 6d7d3acb43
39 changed files with 1639 additions and 902 deletions

View File

@ -209,6 +209,61 @@ template<typename T> struct Stack : public Array<T>
}
};
template<typename T, size_t size> class SizedStack
{
T m_ptr[size];
uint m_count;
public:
SizedStack()
{
Clear();
}
~SizedStack()
{
Clear();
}
void Clear()
{
m_count = 0;
}
bool Pop(T& dst)
{
if(!m_count)
return false;
dst = m_ptr[--m_count];
return true;
}
bool Push(const T& src)
{
if(m_count + 1 > size)
return false;
m_ptr[m_count++] = src;
return true;
}
size_t GetFreeCount() const
{
return size - m_count;
}
size_t GetCount() const
{
return m_count;
}
size_t GetMaxCount() const
{
return size;
}
};
template<typename T> class ArrayF
{
u32 m_count;

View File

@ -23,7 +23,7 @@ protected:
{
case DumpMode:
{
wxString mem = wxString::Format("\t%x:\t", dump_pc);
wxString mem = wxString::Format("\t%08llx:\t", dump_pc);
for(u8 i=0; i < 4; ++i)
{
mem += wxString::Format("%02x", Memory.Read8(dump_pc + i));
@ -36,14 +36,11 @@ protected:
case InterpreterMode:
{
wxString mem = wxString::Format("[%x] ", dump_pc);
for(u8 i=0; i < 4; ++i)
{
mem += wxString::Format("%02x", Memory.Read8(dump_pc + i));
if(i < 3) mem += " ";
}
last_opcode = mem + ": " + value;
last_opcode = wxString::Format("[%08llx] %02x %02x %02x %02x: %s", dump_pc,
Memory.Read8(offset + dump_pc),
Memory.Read8(offset + dump_pc + 1),
Memory.Read8(offset + dump_pc + 2),
Memory.Read8(offset + dump_pc + 3), value);
}
break;
@ -55,12 +52,14 @@ protected:
public:
wxString last_opcode;
uint dump_pc;
u64 dump_pc;
u64 offset;
protected:
PPC_DisAsm(PPCThread& cpu, DisAsmModes mode = NormalMode)
: m_mode(mode)
, disasm_frame(NULL)
, offset(0)
{
if(m_mode != NormalMode) return;

View File

@ -17,6 +17,8 @@ PPCThread::PPCThread(PPCThreadType type)
, stack_addr(0)
, m_prio(0)
, m_offset(0)
, m_sync_wait(false)
, m_wait_thread_id(-1)
{
}
@ -39,6 +41,9 @@ void PPCThread::Reset()
{
CloseStack();
m_sync_wait = 0;
m_wait_thread_id = -1;
SetPc(0);
cycle = 0;
@ -92,6 +97,36 @@ void PPCThread::SetName(const wxString& name)
m_name = name;
}
void PPCThread::Wait(bool wait)
{
wxCriticalSectionLocker lock(m_cs_sync);
m_sync_wait = wait;
}
void PPCThread::Wait(const PPCThread& thr)
{
wxCriticalSectionLocker lock(m_cs_sync);
m_wait_thread_id = thr.GetId();
m_sync_wait = true;
}
bool PPCThread::Sync()
{
wxCriticalSectionLocker lock(m_cs_sync);
return m_sync_wait;
}
int PPCThread::ThreadStatus()
{
if(Emu.IsStopped()) return PPCThread_Stopped;
if(TestDestroy()) return PPCThread_Break;
if(Emu.IsPaused() || Sync())
return PPCThread_Sleeping;
return PPCThread_Running;
}
void PPCThread::NextBranchPc()
{
SetPc(nPC);
@ -127,9 +162,9 @@ void PPCThread::SetEntry(const u64 pc)
void PPCThread::SetBranch(const u64 pc)
{
if(!Memory.IsGoodAddr(pc))
if(!Memory.IsGoodAddr(m_offset + pc))
{
ConLog.Error("%s branch error: bad address 0x%llx #pc: 0x%llx", GetFName(), pc, PC);
ConLog.Error("%s branch error: bad address 0x%llx #pc: 0x%llx", GetFName(), m_offset+ pc, m_offset + PC);
Emu.Pause();
}
nPC = pc;
@ -255,9 +290,16 @@ void PPCThread::Task()
}
}
while(!Emu.IsStopped() && !TestDestroy())
while(true)
{
if(Emu.IsPaused())
int status = ThreadStatus();
if(status == PPCThread_Stopped || status == PPCThread_Break)
{
break;
}
if(status == PPCThread_Sleeping)
{
Sleep(1);
continue;

View File

@ -8,6 +8,16 @@ enum PPCThreadType
PPC_THREAD_SPU,
};
enum PPCThreadStatus
{
PPCThread_Ready,
PPCThread_Running,
PPCThread_Paused,
PPCThread_Stopped,
PPCThread_Sleeping,
PPCThread_Break,
};
class PPCThread : public ThreadBase
{
protected:
@ -43,6 +53,7 @@ public:
void SetName(const wxString& name);
void SetPrio(const u64 prio) { m_prio = prio; }
void SetOffset(const u64 offset) { m_offset = offset; }
u64 GetOffset() { return m_offset; }
u64 GetPrio() const { return m_prio; }
wxString GetName() const { return m_name; }
@ -88,6 +99,16 @@ protected:
public:
~PPCThread();
u32 m_wait_thread_id;
wxCriticalSection m_cs_sync;
bool m_sync_wait;
void Wait(bool wait);
void Wait(const PPCThread& thr);
bool Sync();
int ThreadStatus();
void NextPc();
void NextBranchPc();
void PrevPc();

View File

@ -35,14 +35,19 @@ void PPCThreadManager::RemoveThread(const u32 id)
{
for(u32 i=0; i<m_threads.GetCount(); ++i)
{
if(m_threads[i].m_wait_thread_id == id)
{
m_threads[i].Wait(false);
m_threads[i].m_wait_thread_id = -1;
}
if(m_threads[i].GetId() != id) continue;
wxGetApp().SendDbgCommand(DID_REMOVE_THREAD, &m_threads[i]);
m_threads[i].Close();
delete &m_threads[i];
m_threads.RemoveFAt(i);
break;
i--;
}
Emu.GetIdManager().RemoveID(id, false);

View File

@ -1051,9 +1051,9 @@ private:
{
DisAsm_R3("lwarx", rd, ra, rb);
}
void LDX(u32 ra, u32 rs, u32 rb)
void LDX(u32 rd, u32 ra, u32 rb)
{
DisAsm_R3("ldx", ra, rs, rb);
DisAsm_R3("ldx", rd, ra, rb);
}
void LWZX(u32 rd, u32 ra, u32 rb)
{

View File

@ -489,7 +489,7 @@ namespace PPU_instr
/*0x00b*/bind_instr(g1f_list, MULHWU, RD, RA, RB, RC);
/*0x013*/bind_instr(g1f_list, MFOCRF, L_11, RD, CRM);
/*0x014*/bind_instr(g1f_list, LWARX, RD, RA, RB);
/*0x015*/bind_instr(g1f_list, LDX, RA, RS, RB);
/*0x015*/bind_instr(g1f_list, LDX, RD, RA, RB);
/*0x017*/bind_instr(g1f_list, LWZX, RD, RA, RB);
/*0x018*/bind_instr(g1f_list, SLW, RA, RS, RB, RC);
/*0x01a*/bind_instr(g1f_list, CNTLZW, RA, RS, RC);

View File

@ -61,10 +61,10 @@ private:
void SysCall()
{
CPU.GPR[3] = CPU.DoSyscall(CPU.GPR[11]);
CPU.DoSyscall(CPU.GPR[11]);
//if((s32)CPU.GPR[3] < 0)
//ConLog.Warning("SysCall[%lld] done with code [0x%x]! #pc: 0x%llx", CPU.GPR[11], (u32)CPU.GPR[3], CPU.PC);
if(enable_log)
ConLog.Warning("SysCall[%lld] done with code [0x%llx]! #pc: 0x%llx", CPU.GPR[11], CPU.GPR[3], CPU.PC);
#ifdef HLE_CALL_DEBUG
ConLog.Write("SysCall[%lld] done with code [0x%llx]! #pc: 0x%llx", CPU.GPR[11], CPU.GPR[3], CPU.PC);
#endif
@ -2028,11 +2028,11 @@ private:
}
void CMPLI(u32 crfd, u32 l, u32 ra, u32 uimm16)
{
CPU.UpdateCRn<u64>(crfd, l ? CPU.GPR[ra] : (u32)CPU.GPR[ra], uimm16);
CPU.UpdateCRnU(l, crfd, CPU.GPR[ra], uimm16);
}
void CMPI(u32 crfd, u32 l, u32 ra, s32 simm16)
{
CPU.UpdateCRn<s64>(crfd, l ? CPU.GPR[ra] : (s32)CPU.GPR[ra], simm16);
CPU.UpdateCRnS(l, crfd, CPU.GPR[ra], simm16);
}
void ADDIC(u32 rd, u32 ra, s32 simm16)
{
@ -2172,12 +2172,12 @@ private:
void ANDI_(u32 ra, u32 rs, u32 uimm16)
{
CPU.GPR[ra] = CPU.GPR[rs] & uimm16;
CPU.UpdateCR0<s64>(CPU.GPR[ra]);
CPU.UpdateCR0<s32>(CPU.GPR[ra]);
}
void ANDIS_(u32 ra, u32 rs, u32 uimm16)
{
CPU.GPR[ra] = CPU.GPR[rs] & (uimm16 << 16);
CPU.UpdateCR0<s64>(CPU.GPR[ra]);
CPU.UpdateCR0<s32>(CPU.GPR[ra]);
}
void RLDICL(u32 ra, u32 rs, u32 sh, u32 mb, bool rc)
{
@ -2202,7 +2202,7 @@ private:
}
void CMP(u32 crfd, u32 l, u32 ra, u32 rb)
{
CPU.UpdateCRn<s64>(crfd, l ? CPU.GPR[ra] : (s32)CPU.GPR[ra], l ? CPU.GPR[rb] : (s32)CPU.GPR[rb]);
CPU.UpdateCRnS(l, crfd, CPU.GPR[ra], CPU.GPR[rb]);
}
void TW(u32 to, u32 ra, u32 rb)
{
@ -2256,7 +2256,7 @@ private:
{
const s64 RA = CPU.GPR[ra];
const s64 RB = CPU.GPR[rb];
CPU.GPR[rd] = RB - RA;
CPU.GPR[rd] = ~RA + RB + 1;
CPU.XER.CA = CPU.IsCarry(RA, RB);
if(oe) UNK("subfco");
if(rc) CPU.UpdateCR0<s64>(CPU.GPR[rd]);
@ -2334,9 +2334,9 @@ private:
CPU.reserve = true;
CPU.GPR[rd] = Memory.Read32(addr);
}
void LDX(u32 ra, u32 rs, u32 rb)
void LDX(u32 rd, u32 ra, u32 rb)
{
CPU.GPR[ra] = Memory.Read64(rs ? CPU.GPR[rs] + CPU.GPR[rb] : CPU.GPR[rb]);
CPU.GPR[rd] = Memory.Read64(ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]);
}
void LWZX(u32 rd, u32 ra, u32 rb)
{
@ -2362,11 +2362,16 @@ private:
CPU.GPR[ra] = i;
if(rc) CPU.UpdateCR0<u32>(CPU.GPR[ra]);
if(rc) CPU.UpdateCR0<s32>(CPU.GPR[ra]);
}
void SLD(u32 ra, u32 rs, u32 rb, bool rc)
{
CPU.GPR[ra] = CPU.GPR[rb] & 0x40 ? 0 : CPU.GPR[rs] << (CPU.GPR[rb] & 0x3f);
const u32 n = CPU.GPR[rb] & 0x3f;
const u64 r = rotl64(CPU.GPR[rs], n);
const u64 m = (CPU.GPR[rb] & 0x30) ? 0 : rotate_mask[0][63 - n];
CPU.GPR[ra] = r & m;
if(rc) CPU.UpdateCR0<s64>(CPU.GPR[ra]);
}
void AND(u32 ra, u32 rs, u32 rb, bool rc)
@ -2376,7 +2381,7 @@ private:
}
void CMPL(u32 crfd, u32 l, u32 ra, u32 rb)
{
CPU.UpdateCRn<u64>(crfd, l ? CPU.GPR[ra] : (u32)CPU.GPR[ra], l ? CPU.GPR[rb] : (u32)CPU.GPR[rb]);
CPU.UpdateCRnU(l, crfd, CPU.GPR[ra], CPU.GPR[rb]);
}
void LVSR(u32 vd, u32 ra, u32 rb)
{
@ -2570,21 +2575,23 @@ private:
void STWCX_(u32 rs, u32 ra, u32 rb)
{
CPU.SetCR(0, CPU.XER.SO ? CR_SO : 0);
if(!CPU.reserve) return;
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
if(addr == CPU.reserve_addr)
if(CPU.reserve)
{
Memory.Write32(addr, CPU.GPR[rs]);
CPU.SetCR_EQ(0, true);
}
else
{
static const bool u = 0;
if(u) Memory.Write32(addr, CPU.GPR[rs]);
CPU.SetCR_EQ(0, u);
CPU.reserve = false;
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
if(addr == CPU.reserve_addr)
{
Memory.Write32(addr, CPU.GPR[rs]);
CPU.SetCR_EQ(0, true);
}
else
{
static const bool u = 0;
if(u) Memory.Write32(addr, CPU.GPR[rs]);
CPU.SetCR_EQ(0, u);
CPU.reserve = false;
}
}
}
void STWX(u32 rs, u32 ra, u32 rb)
@ -2621,21 +2628,22 @@ private:
void STDCX_(u32 rs, u32 ra, u32 rb)
{
CPU.SetCR(0, CPU.XER.SO ? CR_SO : 0);
if(!CPU.reserve) return;
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
if(addr == CPU.reserve_addr)
if(!CPU.reserve)
{
Memory.Write64(addr, CPU.GPR[rs]);
CPU.SetCR_EQ(0, true);
}
else
{
static const bool u = 0;
if(u) Memory.Write64(addr, CPU.GPR[rs]);
CPU.SetCR_EQ(0, u);
CPU.reserve = false;
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
if(addr == CPU.reserve_addr)
{
Memory.Write64(addr, CPU.GPR[rs]);
CPU.SetCR_EQ(0, true);
}
else
{
static const bool u = 0;
if(u) Memory.Write64(addr, CPU.GPR[rs]);
CPU.SetCR_EQ(0, u);
CPU.reserve = false;
}
}
}
void STBX(u32 rs, u32 ra, u32 rb)
@ -2824,10 +2832,10 @@ private:
const s64 RA = CPU.GPR[ra];
const s64 RB = CPU.GPR[rb];
if (RB == 0 || ((u64)RA == 0x8000000000000000 && RB == -1))
if (RB == 0 || ((u64)RA == (1ULL << 63) && RB == -1))
{
if(oe) UNK("divdo");
CPU.GPR[rd] = (((u64)RA & 0x8000000000000000) && RB == 0) ? -1 : 0;
CPU.GPR[rd] = (((u64)RA & (1ULL << 63)) && RB == 0) ? -1 : 0;
}
else
{
@ -2841,10 +2849,10 @@ private:
const s32 RA = CPU.GPR[ra];
const s32 RB = CPU.GPR[rb];
if (RB == 0 || ((u32)RA == 0x80000000 && RB == -1))
if (RB == 0 || ((u32)RA == (1 << 31) && RB == -1))
{
if(oe) UNK("divwo");
CPU.GPR[rd] = (((u32)RA & 0x80000000) && RB == 0) ? -1 : 0;
CPU.GPR[rd] = (((u32)RA & (1 << 31)) && RB == 0) ? -1 : 0;
}
else
{
@ -2871,12 +2879,20 @@ private:
}
void SRW(u32 ra, u32 rs, u32 rb, bool rc)
{
CPU.GPR[ra] = CPU.GPR[rb] & 0x20 ? 0 : (u32)CPU.GPR[rs] >> (CPU.GPR[rb] & 0x1f);
u32 n = CPU.GPR[rb] & 0x1f;
u64 r = rotl32((u32)CPU.GPR[rs], 64 - n);
u64 m = CPU.GPR[rb] & 0x20 ? 0 : rotate_mask[32 + n][63];
CPU.GPR[ra] = r & m;
if(rc) CPU.UpdateCR0<s32>(CPU.GPR[ra]);
}
void SRD(u32 ra, u32 rs, u32 rb, bool rc)
{
CPU.GPR[ra] = CPU.GPR[rb] & 0x40 ? 0 : CPU.GPR[rs] >> (CPU.GPR[rb] & 0x3f);
u32 n = CPU.GPR[rb] & 0x3f;
u64 r = rotl64(CPU.GPR[rs], 64 - n);
u64 m = CPU.GPR[rb] & 0x40 ? 0 : rotate_mask[n][63];
CPU.GPR[ra] = r & m;
if(rc) CPU.UpdateCR0<s64>(CPU.GPR[ra]);
}
void LVRX(u32 vd, u32 ra, u32 rb)
@ -2940,7 +2956,7 @@ private:
CPU.GPR[rd] = (u16&)Memory[ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]];
}
void SRAW(u32 ra, u32 rs, u32 rb, bool rc)
{
{
s32 RS = CPU.GPR[rs];
s32 RB = CPU.GPR[rb];
CPU.GPR[ra] = RS >> RB;

View File

@ -60,13 +60,13 @@ void PPUThread::AddArgv(const wxString& arg)
void PPUThread::InitRegs()
{
const u32 entry = Memory.Read32(PC);
const u32 rtoc = Memory.Read32(PC + 4);
const u32 pc = Memory.Read32(entry);
const u32 rtoc = Memory.Read32(entry + 4);
ConLog.Write("entry = 0x%x", entry);
ConLog.Write("rtoc = 0x%x", rtoc);
SetPc(entry);
SetPc(pc);
u64 argc = m_arg;
u64 argv = 0;
@ -110,20 +110,18 @@ void PPUThread::InitRegs()
{
GPR[3] = argc;
GPR[4] = argv;
GPR[5] = argv ? argv - 0xc - 4 * argc : 0; //unk
GPR[5] = argv ? argv + 0xc + 4 * argc : 0; //unk
}
else
{
GPR[3] = m_arg;
}
GPR[0] = entry;
//GPR[7] = 0x80d90;
GPR[0] = pc;
GPR[8] = entry;
//GPR[10] = 0x131700;
GPR[11] = 0x80;
GPR[12] = Emu.GetMallocPageSize();
GPR[13] = Memory.MainMem.Alloc(0x10000) + 0x7060;
GPR[13] = Memory.PRXMem.Alloc(0x10000) + 0x7060 - 8;
GPR[28] = GPR[4];
GPR[29] = GPR[3];
GPR[31] = GPR[5];

View File

@ -652,6 +652,30 @@ public:
SetCR_SO(n, XER.SO);
}
void UpdateCRnU(const u8 l, const u8 n, const u64 a, const u64 b)
{
if(l)
{
UpdateCRn<u64>(n, a, b);
}
else
{
UpdateCRn<u32>(n, a, b);
}
}
void UpdateCRnS(const u8 l, const u8 n, const u64 a, const u64 b)
{
if(l)
{
UpdateCRn<s64>(n, a, b);
}
else
{
UpdateCRn<s32>(n, a, b);
}
}
template<typename T> void UpdateCR0(const T val)
{
UpdateCRn<T>(0, val, 0);

View File

@ -24,9 +24,3 @@ public:
(*SPU_instr::rrr_list)(m_op, code);
}
};
#undef START_OPCODES_GROUP_
#undef START_OPCODES_GROUP
#undef ADD_OPCODE
#undef ADD_NULL_OPCODE
#undef END_OPCODES_GROUP

File diff suppressed because it is too large Load Diff

View File

@ -27,18 +27,18 @@ private:
//0 - 10
void STOP(u32 code)
{
Emu.Pause();
CPU.Pause();
}
void LNOP()
{
}
void SYNC(u32 Cbit)
{
UNIMPLEMENTED();
//UNIMPLEMENTED();
}
void DSYNC()
{
UNIMPLEMENTED();
//UNIMPLEMENTED();
}
void MFSPR(u32 rt, u32 sa)
{
@ -51,7 +51,7 @@ private:
void RCHCNT(u32 rt, u32 ra)
{
CPU.GPR[rt].Reset();
CPU.GPR[rt]._u32[0] = CPU.GetChannelCount(ra);
CPU.GPR[rt]._u32[3] = CPU.GetChannelCount(ra);
}
void SF(u32 rt, u32 ra, u32 rb)
{
@ -280,16 +280,15 @@ private:
}
void STQX(u32 rt, u32 ra, u32 rb)
{
CPU.LSA = CPU.GPR[ra]._u32[0] + CPU.GPR[rb]._u32[0];
CPU.WriteLSA128(CPU.GPR[rt]._u128);
CPU.WriteLS128(CPU.GPR[ra]._u32[0] + CPU.GPR[rb]._u32[0], CPU.GPR[rt]._u128);
}
void BI(u32 ra)
{
CPU.SetBranch(CPU.GPR[ra]._u32[0] & 0xfffffffc);
CPU.SetBranch(CPU.GPR[ra]._u32[3] & 0xfffffffc);
}
void BISL(u32 rt, u32 ra)
{
CPU.SetBranch(CPU.GPR[ra]._u32[0] & 0xfffffffc);
CPU.SetBranch(CPU.GPR[ra]._u32[3] & 0xfffffffc);
CPU.GPR[rt].Reset();
CPU.GPR[rt]._u32[0] = CPU.PC + 4;
}
@ -353,8 +352,7 @@ private:
}
void LQX(u32 rt, u32 ra, u32 rb)
{
CPU.LSA = CPU.GPR[ra]._u32[0] + CPU.GPR[rb]._u32[0];
CPU.GPR[rt]._u128 = CPU.ReadLSA128();
CPU.GPR[rt]._u128 = CPU.ReadLS128(CPU.GPR[ra]._u32[0] + CPU.GPR[rb]._u32[0]);
}
void ROTQBYBI(u32 rt, u32 ra, u32 rb)
{
@ -870,8 +868,6 @@ private:
UNIMPLEMENTED();
}
//0 - 9
void CFLTS(u32 rt, u32 ra, s32 i8)
{
@ -890,35 +886,31 @@ private:
UNIMPLEMENTED();
}
//0 - 8
void BRZ(u32 rt, s32 i16)
{
if(!CPU.GPR[rt]._u32[0]) CPU.SetBranch(branchTarget(CPU.PC, i16));
if(!CPU.GPR[rt]._u32[3]) CPU.SetBranch(branchTarget(CPU.PC, i16));
}
void STQA(u32 rt, s32 i16)
{
CPU.LSA = i16 << 2;
CPU.WriteLSA128(CPU.GPR[rt]._u128);
CPU.WriteLS128(i16 << 2, CPU.GPR[rt]._u128);
}
void BRNZ(u32 rt, s32 i16)
{
if(CPU.GPR[rt]._u32[0] != 0)
if(CPU.GPR[rt]._u32[3] != 0)
CPU.SetBranch(branchTarget(CPU.PC, i16));
}
void BRHZ(u32 rt, s32 i16)
{
if(!CPU.GPR[rt]._u16[0]) CPU.SetBranch(branchTarget(CPU.PC, i16));
if(!CPU.GPR[rt]._u16[7]) CPU.SetBranch(branchTarget(CPU.PC, i16));
}
void BRHNZ(u32 rt, s32 i16)
{
if(CPU.GPR[rt]._u16[0]) CPU.SetBranch(branchTarget(CPU.PC, i16));
if(CPU.GPR[rt]._u16[7]) CPU.SetBranch(branchTarget(CPU.PC, i16));
}
void STQR(u32 rt, s32 i16)
{
CPU.LSA = branchTarget(CPU.PC, i16);
CPU.WriteLSA128(CPU.GPR[rt]._u128);
CPU.WriteLS128(branchTarget(CPU.PC, i16), CPU.GPR[rt]._u128);
}
void BRA(s32 i16)
{
@ -926,14 +918,7 @@ private:
}
void LQA(u32 rt, s32 i16)
{
CPU.LSA = i16 << 2;
if(!Memory.IsGoodAddr(CPU.LSA))
{
ConLog.Warning("LQA: Bad addr: 0x%x", CPU.LSA);
return;
}
CPU.GPR[rt]._u128 = CPU.ReadLSA128();
CPU.GPR[rt]._u128 = CPU.ReadLS128(i16 << 2);
}
void BRASL(u32 rt, s32 i16)
{
@ -964,19 +949,12 @@ private:
void BRSL(u32 rt, s32 i16)
{
CPU.GPR[rt].Reset();
CPU.GPR[rt]._u32[0] = CPU.PC + 4;
CPU.GPR[rt]._u32[3] = CPU.PC + 4;
CPU.SetBranch(branchTarget(CPU.PC, i16));
}
void LQR(u32 rt, s32 i16)
{
CPU.LSA = branchTarget(CPU.PC, i16);
if(!Memory.IsGoodAddr(CPU.LSA))
{
ConLog.Warning("LQR: Bad addr: 0x%x", CPU.LSA);
return;
}
CPU.GPR[rt]._u128 = CPU.ReadLSA128();
CPU.GPR[rt]._u128 = CPU.ReadLS128(branchTarget(CPU.PC, i16));
}
void IL(u32 rt, s32 i16)
{
@ -988,7 +966,7 @@ private:
void ILHU(u32 rt, s32 i16)
{
for (int w = 0; w < 4; w++)
CPU.GPR[rt]._u16[w*2] = i16;
CPU.GPR[rt]._u16[w*2 + 1] = i16;
}
void ILH(u32 rt, s32 i16)
{
@ -1061,13 +1039,11 @@ private:
}
void STQD(u32 rt, s32 i10, u32 ra)
{
CPU.LSA = branchTarget(0, i10 + CPU.GPR[ra]._u32[0]);
CPU.WriteLSA128(CPU.GPR[rt]._u128);
CPU.WriteLS128(CPU.GPR[ra]._u32[3] + i10, CPU.GPR[rt]._u128);
}
void LQD(u32 rt, s32 i10, u32 ra)
{
CPU.LSA = branchTarget(0, i10 + CPU.GPR[ra]._u32[0]);
CPU.GPR[rt]._u128 = CPU.ReadLSA128();
CPU.GPR[rt]._u128 = CPU.ReadLS128(CPU.GPR[ra]._u32[3] + i10);
}
void XORI(u32 rt, u32 ra, s32 i10)
{
@ -1167,10 +1143,6 @@ private:
}
void HBRR(s32 ro, s32 i16)
{
UNIMPLEMENTED();
//CHECK ME
//CPU.GPR[0]._u64[0] = branchTarget(CPU.PC, i16);
//CPU.SetBranch(branchTarget(CPU.PC, ro));
}
void ILA(u32 rt, s32 i18)
{
@ -1189,12 +1161,6 @@ private:
( CPU.GPR[rc]._u32[i] & CPU.GPR[rb]._u32[i]) |
(~CPU.GPR[rc]._u32[i] & CPU.GPR[ra]._u32[i]);
}
/*
CPU.GPR[rt] = _mm_or_si128(
_mm_and_si128(CPU.GPR[rc], CPU.GPR[rb]),
_mm_andnot_si128(CPU.GPR[rc], CPU.GPR[ra])
);
*/
}
void SHUFB(u32 rc, u32 ra, u32 rb, u32 rt)
{

View File

@ -231,8 +231,8 @@ class SPU_Opcodes
public:
static u32 branchTarget(const u64 pc, const s32 imm)
{
return (pc + ((imm << 2) & ~0x3)) & 0x3fff0;
}
return (pc + (imm << 2)) & 0x3fffc;
}
virtual void Exit()=0;

View File

@ -26,8 +26,6 @@ void SPUThread::DoReset()
{
//reset regs
for(u32 i=0; i<128; ++i) GPR[i].Reset();
LSA = 0;
}
void SPUThread::InitRegs()

View File

@ -1,29 +1,30 @@
#pragma once
#include "PPCThread.h"
#include "Emu/event.h"
static const wxString spu_reg_name[128] =
{
"$LR", "$SP", "$3", "$4", "$5", "$6", "$7", "$8",
"$9", "$10", "$11", "$12", "$13", "$14", "$15", "$16",
"$17", "$18", "$19", "$20", "$21", "$22", "$23", "$24",
"$25", "$26", "$27", "$28", "$29", "$30", "$31", "$32",
"$33", "$34", "$35", "$36", "$37", "$38", "$39", "$40",
"$41", "$42", "$43", "$44", "$45", "$46", "$47", "$48",
"$49", "$50", "$51", "$52", "$53", "$54", "$55", "$56",
"$57", "$58", "$59", "$60", "$61", "$62", "$63", "$64",
"$65", "$66", "$67", "$68", "$69", "$70", "$71", "$72",
"$73", "$74", "$75", "$76", "$77", "$78", "$79", "$80",
"$81", "$82", "$83", "$84", "$85", "$86", "$87", "$88",
"$89", "$90", "$91", "$92", "$93", "$94", "$95", "$96",
"$97", "$98", "$99", "$100", "$101", "$102", "$103", "$104",
"$105", "$106", "$107", "$108", "$109", "$110", "$111", "$112",
"$113", "$114", "$115", "$116", "$117", "$118", "$119", "$120",
"$121", "$122", "$123", "$124", "$125", "$126", "$127",
"$LR", "$SP", "$2", "$3", "$4", "$5", "$6", "$7",
"$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
"$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
"$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31",
"$32", "$33", "$34", "$35", "$36", "$37", "$38", "$39",
"$40", "$41", "$42", "$43", "$44", "$45", "$46", "$47",
"$48", "$49", "$50", "$51", "$52", "$53", "$54", "$55",
"$56", "$57", "$58", "$59", "$60", "$61", "$62", "$63",
"$64", "$65", "$66", "$67", "$68", "$69", "$70", "$71",
"$72", "$73", "$74", "$75", "$76", "$77", "$78", "$79",
"$80", "$81", "$82", "$83", "$84", "$85", "$86", "$87",
"$88", "$89", "$90", "$91", "$92", "$93", "$94", "$95",
"$96", "$97", "$98", "$99", "$100", "$101", "$102", "$103",
"$104", "$105", "$106", "$107", "$108", "$109", "$110", "$111",
"$112", "$113", "$114", "$115", "$116", "$117", "$118", "$119",
"$120", "$121", "$122", "$123", "$124", "$125", "$126", "$127",
};
static const wxString spu_ch_name[128] =
{
"$SPU_RdEventStat", "$SPU_WrEventMask", "$SPU_RdSigNotify1",
"$SPU_RdEventStat", "$SPU_WrEventMask", "$SPU_WrEventAck", "$SPU_RdSigNotify1",
"$SPU_RdSigNotify2", "$ch5", "$ch6", "$SPU_WrDec", "$SPU_RdDec",
"$MFC_WrMSSyncReq", "$ch10", "$SPU_RdEventMask", "$MFC_RdTagMask", "$SPU_RdMachStat",
"$SPU_WrSRR0", "$SPU_RdSRR0", "$MFC_LSA", "$MFC_EAH", "$MFC_EAL", "$MFC_Size",
@ -82,8 +83,6 @@ enum MFCchannels
union SPU_GPR_hdr
{
//__m128i _m128i;
u128 _u128;
s128 _i128;
u64 _u64[2];
@ -96,19 +95,6 @@ union SPU_GPR_hdr
s8 _i8[16];
SPU_GPR_hdr() {}
/*
SPU_GPR_hdr(const __m128i val){_u128._u64[0] = val.m128i_u64[0]; _u128._u64[1] = val.m128i_u64[1];}
SPU_GPR_hdr(const u128 val) { _u128 = val; }
SPU_GPR_hdr(const u64 val) { Reset(); _u64[0] = val; }
SPU_GPR_hdr(const u32 val) { Reset(); _u32[0] = val; }
SPU_GPR_hdr(const u16 val) { Reset(); _u16[0] = val; }
SPU_GPR_hdr(const u8 val) { Reset(); _u8[0] = val; }
SPU_GPR_hdr(const s128 val) { _i128 = val; }
SPU_GPR_hdr(const s64 val) { Reset(); _i64[0] = val; }
SPU_GPR_hdr(const s32 val) { Reset(); _i32[0] = val; }
SPU_GPR_hdr(const s16 val) { Reset(); _i16[0] = val; }
SPU_GPR_hdr(const s8 val) { Reset(); _i8[0] = val; }
*/
wxString ToString() const
{
@ -119,41 +105,17 @@ union SPU_GPR_hdr
{
memset(this, 0, sizeof(*this));
}
//operator __m128i() { __m128i ret; ret.m128i_u64[0]=_u128._u64[0]; ret.m128i_u64[1]=_u128._u64[1]; return ret; }
/*
SPU_GPR_hdr operator ^ (__m128i right) { return _mm_xor_si128(*this, right); }
SPU_GPR_hdr operator | (__m128i right) { return _mm_or_si128 (*this, right); }
SPU_GPR_hdr operator & (__m128i right) { return _mm_and_si128(*this, right); }
SPU_GPR_hdr operator << (int right) { return _mm_slli_epi32(*this, right); }
SPU_GPR_hdr operator << (__m128i right) { return _mm_sll_epi32(*this, right); }
SPU_GPR_hdr operator >> (int right) { return _mm_srai_epi32(*this, right); }
SPU_GPR_hdr operator >> (__m128i right) { return _mm_sra_epi32(*this, right); }
SPU_GPR_hdr operator | (__m128i right) { return _mm_or_si128 (*this, right); }
SPU_GPR_hdr operator & (__m128i right) { return _mm_and_si128(*this, right); }
SPU_GPR_hdr operator << (int right) { return _mm_slli_epi32(*this, right); }
SPU_GPR_hdr operator << (__m128i right) { return _mm_sll_epi32(*this, right); }
SPU_GPR_hdr operator >> (int right) { return _mm_srai_epi32(*this, right); }
SPU_GPR_hdr operator >> (__m128i right) { return _mm_sra_epi32(*this, right); }
SPU_GPR_hdr operator ^= (__m128i right) { return *this = *this ^ right; }
SPU_GPR_hdr operator |= (__m128i right) { return *this = *this | right; }
SPU_GPR_hdr operator &= (__m128i right) { return *this = *this & right; }
SPU_GPR_hdr operator <<= (int right) { return *this = *this << right; }
SPU_GPR_hdr operator <<= (__m128i right){ return *this = *this << right; }
SPU_GPR_hdr operator >>= (int right) { return *this = *this >> right; }
SPU_GPR_hdr operator >>= (__m128i right){ return *this = *this >> right; }
*/
};
class SPUThread : public PPCThread
{
public:
SPU_GPR_hdr GPR[128]; //General-Purpose Register
Stack<u32> Mbox;
SizedStack<u32, 1> OutMbox;
SizedStack<u32, 1> OutIntrMbox;
SizedStack<u32, 4> InMbox;
u32 LSA; //local storage address
u32 LSA;
union
{
@ -165,11 +127,14 @@ public:
{
switch(ch)
{
case SPU_WrOutMbox:
return OutMbox.GetFreeCount();
case SPU_RdInMbox:
return 1;
return InMbox.GetCount();
case SPU_WrOutIntrMbox:
return 0;
return 0;//return OutIntrMbox.GetFreeCount();
default:
ConLog.Error("%s error: unknown/illegal channel (%d).", __FUNCTION__, ch);
@ -181,12 +146,24 @@ public:
void WriteChannel(u32 ch, const SPU_GPR_hdr& r)
{
const u32 v = r._u32[0];
const u32 v = r._u32[3];
switch(ch)
{
case SPU_WrOutIntrMbox:
Mbox.Push(v);
ConLog.Warning("SPU_WrOutIntrMbox = 0x%x", v);
if(!OutIntrMbox.Push(v))
{
ConLog.Warning("Not enought free rooms.");
}
break;
case SPU_WrOutMbox:
ConLog.Warning("SPU_WrOutMbox = 0x%x", v);
if(!OutMbox.Push(v))
{
ConLog.Warning("Not enought free rooms.");
}
break;
default:
@ -198,12 +175,12 @@ public:
void ReadChannel(SPU_GPR_hdr& r, u32 ch)
{
r.Reset();
u32& v = r._u32[0];
u32& v = r._u32[3];
switch(ch)
{
case SPU_RdInMbox:
v = Mbox.Pop();
if(!InMbox.Pop(v)) v = 0;
break;
default:
@ -212,17 +189,18 @@ public:
}
}
u8 ReadLSA8 () { return Memory.Read8 (LSA + m_offset); }
u16 ReadLSA16 () { return Memory.Read16 (LSA + m_offset); }
u32 ReadLSA32 () { return Memory.Read32 (LSA + m_offset); }
u64 ReadLSA64 () { return Memory.Read64 (LSA + m_offset); }
u128 ReadLSA128() { return Memory.Read128(LSA + m_offset); }
bool IsGoodLSA(const u32 lsa) const { return Memory.IsGoodAddr(lsa); }
u8 ReadLS8 (const u32 lsa) const { return Memory.Read8 (lsa + (m_offset & 0x3fffc)); }
u16 ReadLS16 (const u32 lsa) const { return Memory.Read16 (lsa + m_offset); }
u32 ReadLS32 (const u32 lsa) const { return Memory.Read32 (lsa + m_offset); }
u64 ReadLS64 (const u32 lsa) const { return Memory.Read64 (lsa + m_offset); }
u128 ReadLS128(const u32 lsa) const { return Memory.Read128(lsa + m_offset); }
void WriteLSA8 (const u8& data) { Memory.Write8 (LSA + m_offset, data); }
void WriteLSA16 (const u16& data) { Memory.Write16 (LSA + m_offset, data); }
void WriteLSA32 (const u32& data) { Memory.Write32 (LSA + m_offset, data); }
void WriteLSA64 (const u64& data) { Memory.Write64 (LSA + m_offset, data); }
void WriteLSA128(const u128& data) { Memory.Write128(LSA + m_offset, data); }
void WriteLS8 (const u32 lsa, const u8& data) const { Memory.Write8 (lsa + m_offset, data); }
void WriteLS16 (const u32 lsa, const u16& data) const { Memory.Write16 (lsa + m_offset, data); }
void WriteLS32 (const u32 lsa, const u32& data) const { Memory.Write32 (lsa + m_offset, data); }
void WriteLS64 (const u32 lsa, const u64& data) const { Memory.Write64 (lsa + m_offset, data); }
void WriteLS128(const u32 lsa, const u128& data) const { Memory.Write128(lsa + m_offset, data); }
public:
SPUThread();

View File

@ -529,6 +529,8 @@ bool MemoryBase::Write128NN(u64 addr, const u128 data)
u8 MemoryBase::Read8(u64 addr)
{
if(enable_log && addr >= 0xd0010a84)
ConLog.Warning("Read8 from block: [%08llx]", addr);
MemoryBlock& mem = GetMemByAddr(addr);
if(mem.IsNULL())
{
@ -540,6 +542,8 @@ u8 MemoryBase::Read8(u64 addr)
u16 MemoryBase::Read16(u64 addr)
{
if(enable_log && addr >= 0xd0010a84)
ConLog.Warning("Read16 from block: [%08llx]", addr);
MemoryBlock& mem = GetMemByAddr(addr);
if(mem.IsNULL())
{
@ -551,6 +555,8 @@ u16 MemoryBase::Read16(u64 addr)
u32 MemoryBase::Read32(u64 addr)
{
if(enable_log && addr >= 0xd0010a84)
ConLog.Warning("Read32 from block: [%08llx]", addr);
MemoryBlock& mem = GetMemByAddr(addr);
if(mem.IsNULL())
{
@ -562,6 +568,8 @@ u32 MemoryBase::Read32(u64 addr)
u64 MemoryBase::Read64(u64 addr)
{
if(enable_log && addr >= 0xd0010a84)
ConLog.Warning("Read64 from block: [%08llx]", addr);
MemoryBlock& mem = GetMemByAddr(addr);
if(mem.IsNULL())
{

View File

@ -3583,7 +3583,7 @@ s64 SysCalls::DoFunc(const u32 id)
case 0x2f85c0ef: return sys_lwmutex_create(SC_ARGS_2);//FUNC_LOG_ERROR("TODO: sys_lwmutex_create");
case 0x3172759d: FUNC_LOG_ERROR("TODO: sys_game_get_temperature");
case 0x318f17e1: FUNC_LOG_ERROR("TODO: _sys_memalign");
case 0x350d454e: return sys_ppu_thread_get_id();//FUNC_LOG_ERROR("TODO: sys_ppu_thread_get_id");
case 0x350d454e: return sys_ppu_thread_get_id(SC_ARGS_1);//FUNC_LOG_ERROR("TODO: sys_ppu_thread_get_id");
case 0x35168520: return sys_heap_malloc(SC_ARGS_2); //FUNC_LOG_ERROR("TODO: _sys_heap_malloc");
case 0x3bd53c7b: FUNC_LOG_ERROR("TODO: _sys_memchr");
case 0x3dd4a957: FUNC_LOG_ERROR("TODO: sys_ppu_thread_register_atexit");
@ -3647,7 +3647,7 @@ s64 SysCalls::DoFunc(const u32 id)
case 0xa285139d: FUNC_LOG_ERROR("TODO: sys_spinlock_lock");
case 0xa2c7ba64: FUNC_LOG_ERROR("TODO: sys_prx_exitspawn_with_level");
case 0xa330ad84: FUNC_LOG_ERROR("TODO: sys_prx_load_module_on_memcontainer_by_fd");
case 0xa3e3be68: FUNC_LOG_ERROR("TODO: sys_ppu_thread_once");
case 0xa3e3be68: sys_ppu_thread_once(SC_ARGS_2); return SC_ARGS_1;//FUNC_LOG_ERROR("TODO: sys_ppu_thread_once");
case 0xa5d06bf0: FUNC_LOG_ERROR("TODO: sys_prx_get_module_list");
case 0xaa6d9bff: FUNC_LOG_ERROR("TODO: sys_prx_load_module_on_memcontainer");
case 0xac6fc404: FUNC_LOG_ERROR("TODO: sys_ppu_thread_unregister_atexit");

View File

@ -0,0 +1,235 @@
#include "stdafx.h"
#include "SysCalls.h"
#include "SC_FUNC.h"
Module* g_modules[50];
uint g_modules_count = 0;
ArrayF<ModuleFunc> g_modules_funcs_list;
bool IsLoadedFunc(u32 id)
{
for(u32 i=0; i<g_modules_funcs_list.GetCount(); ++i)
{
if(g_modules_funcs_list[i].id == id)
{
return true;
}
}
return false;
}
bool CallFunc(u32 id)
{
for(u32 i=0; i<g_modules_funcs_list.GetCount(); ++i)
{
if(g_modules_funcs_list[i].id == id)
{
(*g_modules_funcs_list[i].func)();
return true;
}
}
return false;
}
bool UnloadFunc(u32 id)
{
for(u32 i=0; i<g_modules_funcs_list.GetCount(); ++i)
{
if(g_modules_funcs_list[i].id == id)
{
g_modules_funcs_list.RemoveAt(i);
return true;
}
}
return false;
}
void UnloadModules()
{
for(u32 i=0; i<g_modules_count; ++i)
{
g_modules[i]->SetLoaded(false);
}
g_modules_funcs_list.Clear();
}
Module* GetModuleByName(const wxString& name)
{
for(u32 i=0; i<g_modules_count; ++i)
{
if(g_modules[i]->GetName().Cmp(name) == 0)
{
return g_modules[i];
}
}
return nullptr;
}
Module* GetModuleById(u16 id)
{
for(u32 i=0; i<g_modules_count; ++i)
{
if(g_modules[i]->GetID() == id)
{
return g_modules[i];
}
}
return nullptr;
}
Module::Module(const char* name, u16 id, void (*init)())
: m_is_loaded(false)
, m_name(name)
, m_id(id)
{
g_modules[g_modules_count++] = this;
init();
}
void Module::Load()
{
for(u32 i=0; i<m_funcs_list.GetCount(); ++i)
{
if(IsLoadedFunc(m_funcs_list[i].id)) continue;
g_modules_funcs_list.Add(m_funcs_list[i]);
}
}
void Module::UnLoad()
{
for(u32 i=0; i<m_funcs_list.GetCount(); ++i)
{
UnloadFunc(m_funcs_list[i].id);
}
}
bool Module::Load(u32 id)
{
if(IsLoadedFunc(id)) return false;
for(u32 i=0; i<m_funcs_list.GetCount(); ++i)
{
if(m_funcs_list[i].id == id)
{
g_modules_funcs_list.Add(m_funcs_list[i]);
return true;
}
}
return false;
}
bool Module::UnLoad(u32 id)
{
return UnloadFunc(id);
}
void Module::SetLoaded(bool loaded)
{
m_is_loaded = loaded;
}
bool Module::IsLoaded() const
{
return m_is_loaded;
}
u16 Module::GetID() const
{
return m_id;
}
wxString Module::GetName() const
{
return m_name;
}
void Module::Log(const u32 id, wxString fmt, ...)
{
if(enable_log)
{
va_list list;
va_start(list, fmt);
ConLog.Write(GetName() + wxString::Format("[%d]: ", id) + wxString::FormatV(fmt, list));
va_end(list);
}
}
void Module::Log(wxString fmt, ...)
{
if(enable_log)
{
va_list list;
va_start(list, fmt);
ConLog.Write(GetName() + ": " + wxString::FormatV(fmt, list));
va_end(list);
}
}
void Module::Warning(const u32 id, wxString fmt, ...)
{
va_list list;
va_start(list, fmt);
ConLog.Warning(GetName() + wxString::Format("[%d] warning: ", id) + wxString::FormatV(fmt, list));
va_end(list);
}
void Module::Warning(wxString fmt, ...)
{
va_list list;
va_start(list, fmt);
ConLog.Warning(GetName() + " warning: " + wxString::FormatV(fmt, list));
va_end(list);
}
void Module::Error(const u32 id, wxString fmt, ...)
{
va_list list;
va_start(list, fmt);
ConLog.Error(GetName() + wxString::Format("[%d] error: ", id) + wxString::FormatV(fmt, list));
va_end(list);
}
void Module::Error(wxString fmt, ...)
{
va_list list;
va_start(list, fmt);
ConLog.Error(GetName() + " error: " + wxString::FormatV(fmt, list));
va_end(list);
}
bool Module::CheckId(u32 id) const
{
return Emu.GetIdManager().CheckID(id) && !Emu.GetIdManager().GetIDData(id).m_name.Cmp(GetName());
}
bool Module::CheckId(u32 id, ID& _id) const
{
return Emu.GetIdManager().CheckID(id) && !(_id = Emu.GetIdManager().GetIDData(id)).m_name.Cmp(GetName());
}
template<typename T> bool Module::CheckId(u32 id, T*& data)
{
ID id_data;
if(!CheckId(id, id_data)) return false;
data = (T*)id_data.m_data;
return true;
}
u32 Module::GetNewId(void* data, u8 flags)
{
return Emu.GetIdManager().GetNewID(GetName(), data, flags);
}

View File

@ -0,0 +1,76 @@
#pragma once
#define declCPU PPUThread& CPU = GetCurrentPPUThread
class func_caller
{
public:
virtual void operator()() = 0;
};
static func_caller *null_func = nullptr;
//TODO
struct ModuleFunc
{
u32 id;
func_caller* func;
ModuleFunc(u32 id, func_caller* func)
: id(id)
, func(func)
{
}
};
class Module
{
const char* m_name;
const u16 m_id;
bool m_is_loaded;
public:
Array<ModuleFunc> m_funcs_list;
Module(const char* name, u16 id, void (*init)());
void Load();
void UnLoad();
bool Load(u32 id);
bool UnLoad(u32 id);
void SetLoaded(bool loaded = true);
bool IsLoaded() const;
u16 GetID() const;
wxString GetName() const;
public:
void Log(const u32 id, wxString fmt, ...);
void Log(wxString fmt, ...);
void Warning(const u32 id, wxString fmt, ...);
void Warning(wxString fmt, ...);
void Error(const u32 id, wxString fmt, ...);
void Error(wxString fmt, ...);
bool CheckId(u32 id) const;
bool CheckId(u32 id, ID& _id) const;
template<typename T> bool CheckId(u32 id, T*& data);
u32 GetNewId(void* data = nullptr, u8 flags = 0);
__forceinline void Module::AddFunc(u32 id, func_caller* func)
{
m_funcs_list.Move(new ModuleFunc(id, func));
}
};
bool IsLoadedFunc(u32 id);
bool CallFunc(u32 id);
bool UnloadFunc(u32 id);
void UnloadModules();
Module* GetModuleByName(const wxString& name);
Module* GetModuleById(u16 id);

View File

@ -2,7 +2,8 @@
#include "Emu/SysCalls/SysCalls.h"
#include "Emu/SysCalls/SC_FUNC.h"
Module cellGcmSys("cellGcmSys", 0x0010);
void cellGcmSys_init();
Module cellGcmSys("cellGcmSys", 0x0010, cellGcmSys_init);
s64 cellGcmFunc15()
{
@ -16,25 +17,22 @@ s64 cellGcmSetFlipCommandWithWaitLabel()
return 0;
}
struct _cellGcmSys_init
void cellGcmSys_init()
{
_cellGcmSys_init()
{
cellGcmSys.AddFunc(0x055bd74d, bind_func(cellGcmGetTiledPitchSize));
cellGcmSys.AddFunc(0x15bae46b, bind_func(cellGcmInit));
cellGcmSys.AddFunc(0x21397818, bind_func(cellGcmFlush));
cellGcmSys.AddFunc(0x21ac3697, bind_func(cellGcmAddressToOffset));
cellGcmSys.AddFunc(0x3a33c1fd, bind_func(cellGcmFunc15));
cellGcmSys.AddFunc(0x4ae8d215, bind_func(cellGcmSetFlipMode));
cellGcmSys.AddFunc(0x5e2ee0f0, bind_func(cellGcmGetDefaultCommandWordSize));
cellGcmSys.AddFunc(0x72a577ce, bind_func(cellGcmGetFlipStatus));
cellGcmSys.AddFunc(0x8cdf8c70, bind_func(cellGcmGetDefaultSegmentWordSize));
cellGcmSys.AddFunc(0x9ba451e4, bind_func(cellGcmSetDefaultFifoSize));
cellGcmSys.AddFunc(0xa53d12ae, bind_func(cellGcmSetDisplayBuffer));
cellGcmSys.AddFunc(0xa547adde, bind_func(cellGcmGetControlRegister));
cellGcmSys.AddFunc(0xb2e761d4, bind_func(cellGcmResetFlipStatus));
cellGcmSys.AddFunc(0xd8f88e1a, bind_func(cellGcmSetFlipCommandWithWaitLabel));
cellGcmSys.AddFunc(0xe315a0b2, bind_func(cellGcmGetConfiguration));
cellGcmSys.AddFunc(0x9dc04436, bind_func(cellGcmBindZcull));
}
} _cellGcmSys_init;
cellGcmSys.AddFunc(0x055bd74d, bind_func(cellGcmGetTiledPitchSize));
cellGcmSys.AddFunc(0x15bae46b, bind_func(cellGcmInit));
cellGcmSys.AddFunc(0x21397818, bind_func(cellGcmFlush));
cellGcmSys.AddFunc(0x21ac3697, bind_func(cellGcmAddressToOffset));
cellGcmSys.AddFunc(0x3a33c1fd, bind_func(cellGcmFunc15));
cellGcmSys.AddFunc(0x4ae8d215, bind_func(cellGcmSetFlipMode));
cellGcmSys.AddFunc(0x5e2ee0f0, bind_func(cellGcmGetDefaultCommandWordSize));
cellGcmSys.AddFunc(0x72a577ce, bind_func(cellGcmGetFlipStatus));
cellGcmSys.AddFunc(0x8cdf8c70, bind_func(cellGcmGetDefaultSegmentWordSize));
cellGcmSys.AddFunc(0x9ba451e4, bind_func(cellGcmSetDefaultFifoSize));
cellGcmSys.AddFunc(0xa53d12ae, bind_func(cellGcmSetDisplayBuffer));
cellGcmSys.AddFunc(0xa547adde, bind_func(cellGcmGetControlRegister));
cellGcmSys.AddFunc(0xb2e761d4, bind_func(cellGcmResetFlipStatus));
cellGcmSys.AddFunc(0xd8f88e1a, bind_func(cellGcmSetFlipCommandWithWaitLabel));
cellGcmSys.AddFunc(0xe315a0b2, bind_func(cellGcmGetConfiguration));
cellGcmSys.AddFunc(0x9dc04436, bind_func(cellGcmBindZcull));
}

View File

@ -2,7 +2,8 @@
#include "Emu/SysCalls/SysCalls.h"
#include "Emu/SysCalls/SC_FUNC.h"
Module sysPrxForUser("sysPrxForUser", -1);
void sysPrxForUser_init();
Module sysPrxForUser("sysPrxForUser", -1, sysPrxForUser_init);
void sys_initialize_tls()
{
@ -21,6 +22,12 @@ s64 sys_process_at_Exitspawn()
return 0;
}
int sys_spu_printf_initialize(int a1, int a2, int a3, int a4, int a5)
{
sysPrxForUser.Warning("sys_spu_printf_initialize(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)", a1, a2, a3, a4, a5);
return 0;
}
s64 sys_prx_register_library()
{
sysPrxForUser.Error("sys_prx_register_library()");
@ -40,36 +47,36 @@ s64 sys_strlen(u32 addr)
return str.Len();
}
struct _sysPrxForUser_init
void sysPrxForUser_init()
{
_sysPrxForUser_init()
{
sysPrxForUser.AddFunc(0x744680a2, bind_func(sys_initialize_tls));
sysPrxForUser.AddFunc(0x744680a2, bind_func(sys_initialize_tls));
sysPrxForUser.AddFunc(0x2f85c0ef, bind_func(sys_lwmutex_create));
sysPrxForUser.AddFunc(0xc3476d0c, bind_func(sys_lwmutex_destroy));
sysPrxForUser.AddFunc(0x1573dc3f, bind_func(sys_lwmutex_lock));
sysPrxForUser.AddFunc(0xaeb78725, bind_func(sys_lwmutex_trylock));
sysPrxForUser.AddFunc(0x1bc200f4, bind_func(sys_lwmutex_unlock));
sysPrxForUser.AddFunc(0x2f85c0ef, bind_func(sys_lwmutex_create));
sysPrxForUser.AddFunc(0xc3476d0c, bind_func(sys_lwmutex_destroy));
sysPrxForUser.AddFunc(0x1573dc3f, bind_func(sys_lwmutex_lock));
sysPrxForUser.AddFunc(0xaeb78725, bind_func(sys_lwmutex_trylock));
sysPrxForUser.AddFunc(0x1bc200f4, bind_func(sys_lwmutex_unlock));
sysPrxForUser.AddFunc(0x8461e528, bind_func(sys_time_get_system_time));
sysPrxForUser.AddFunc(0x8461e528, bind_func(sys_time_get_system_time));
sysPrxForUser.AddFunc(0xe6f2c1e7, bind_func(sys_process_exit));
sysPrxForUser.AddFunc(0x2c847572, bind_func(sys_process_atexitspawn));
sysPrxForUser.AddFunc(0x96328741, bind_func(sys_process_at_Exitspawn));
sysPrxForUser.AddFunc(0xe6f2c1e7, bind_func(sys_process_exit));
sysPrxForUser.AddFunc(0x2c847572, bind_func(sys_process_atexitspawn));
sysPrxForUser.AddFunc(0x96328741, bind_func(sys_process_at_Exitspawn));
sysPrxForUser.AddFunc(0x24a1ea07, bind_func(sys_ppu_thread_create));
sysPrxForUser.AddFunc(0x350d454e, bind_func(sys_ppu_thread_get_id));
sysPrxForUser.AddFunc(0xaff080a4, bind_func(sys_ppu_thread_exit));
sysPrxForUser.AddFunc(0xa3e3be68, bind_func(sys_ppu_thread_once));
sysPrxForUser.AddFunc(0x24a1ea07, bind_func(sys_ppu_thread_create));
sysPrxForUser.AddFunc(0x350d454e, bind_func(sys_ppu_thread_get_id));
sysPrxForUser.AddFunc(0xaff080a4, bind_func(sys_ppu_thread_exit));
sysPrxForUser.AddFunc(0x45fe2fce, bind_func(sys_spu_printf_initialize));
sysPrxForUser.AddFunc(0x42b23552, bind_func(sys_prx_register_library));
sysPrxForUser.AddFunc(0xa2c7ba64, bind_func(sys_prx_exitspawn_with_level));
sysPrxForUser.AddFunc(0x42b23552, bind_func(sys_prx_register_library));
sysPrxForUser.AddFunc(0xa2c7ba64, bind_func(sys_prx_exitspawn_with_level));
sysPrxForUser.AddFunc(0x2d36462b, bind_func(sys_strlen));
sysPrxForUser.AddFunc(0x2d36462b, bind_func(sys_strlen));
sysPrxForUser.AddFunc(0x35168520, bind_func(sys_heap_malloc));
//sysPrxForUser.AddFunc(0xaede4b03, bind_func(sys_heap_free>);
//sysPrxForUser.AddFunc(0x8a561d92, bind_func(sys_heap_delete_heap>);
sysPrxForUser.AddFunc(0xb2fcf2c8, bind_func(sys_heap_create_heap));
}
} sysPrxForUser_init;
sysPrxForUser.AddFunc(0x35168520, bind_func(sys_heap_malloc));
//sysPrxForUser.AddFunc(0xaede4b03, bind_func(sys_heap_free));
//sysPrxForUser.AddFunc(0x8a561d92, bind_func(sys_heap_delete_heap));
sysPrxForUser.AddFunc(0xb2fcf2c8, bind_func(sys_heap_create_heap));
}

View File

@ -2,25 +2,23 @@
#include "Emu/SysCalls/SysCalls.h"
#include "Emu/SysCalls/SC_FUNC.h"
Module sys_fs("sys_fs", 0x000e);
void sys_fs_init();
Module sys_fs("sys_fs", 0x000e, sys_fs_init);
struct _sys_fs_init
void sys_fs_init()
{
_sys_fs_init()
{
sys_fs.AddFunc(0x718bf5f8, bind_func(cellFsOpen));
sys_fs.AddFunc(0x4d5ff8e2, bind_func(cellFsRead));
sys_fs.AddFunc(0xecdcf2ab, bind_func(cellFsWrite));
sys_fs.AddFunc(0x2cb51f0d, bind_func(cellFsClose));
sys_fs.AddFunc(0x3f61245c, bind_func(cellFsOpendir));
sys_fs.AddFunc(0x5c74903d, bind_func(cellFsReaddir));
sys_fs.AddFunc(0xff42dcc3, bind_func(cellFsClosedir));
sys_fs.AddFunc(0x7de6dced, bind_func(cellFsStat));
sys_fs.AddFunc(0xef3efa34, bind_func(cellFsFstat));
sys_fs.AddFunc(0xba901fe6, bind_func(cellFsMkdir));
sys_fs.AddFunc(0xf12eecc8, bind_func(cellFsRename));
sys_fs.AddFunc(0x2796fdf3, bind_func(cellFsRmdir));
sys_fs.AddFunc(0x7f4677a8, bind_func(cellFsUnlink));
sys_fs.AddFunc(0xa397d042, bind_func(cellFsLseek));
}
} sys_fs_init;
sys_fs.AddFunc(0x718bf5f8, bind_func(cellFsOpen));
sys_fs.AddFunc(0x4d5ff8e2, bind_func(cellFsRead));
sys_fs.AddFunc(0xecdcf2ab, bind_func(cellFsWrite));
sys_fs.AddFunc(0x2cb51f0d, bind_func(cellFsClose));
sys_fs.AddFunc(0x3f61245c, bind_func(cellFsOpendir));
sys_fs.AddFunc(0x5c74903d, bind_func(cellFsReaddir));
sys_fs.AddFunc(0xff42dcc3, bind_func(cellFsClosedir));
sys_fs.AddFunc(0x7de6dced, bind_func(cellFsStat));
sys_fs.AddFunc(0xef3efa34, bind_func(cellFsFstat));
sys_fs.AddFunc(0xba901fe6, bind_func(cellFsMkdir));
sys_fs.AddFunc(0xf12eecc8, bind_func(cellFsRename));
sys_fs.AddFunc(0x2796fdf3, bind_func(cellFsRmdir));
sys_fs.AddFunc(0x7f4677a8, bind_func(cellFsUnlink));
sys_fs.AddFunc(0xa397d042, bind_func(cellFsLseek));
}

View File

@ -2,19 +2,17 @@
#include "Emu/SysCalls/SysCalls.h"
#include "Emu/SysCalls/SC_FUNC.h"
Module sys_io("sys_io", 0x0017);
void sys_io_init();
Module sys_io("sys_io", 0x0017, sys_io_init);
struct _sys_io_init
void sys_io_init()
{
_sys_io_init()
{
sys_io.AddFunc(0x1cf98800, bind_func(cellPadInit));
sys_io.AddFunc(0x4d9b75d5, bind_func(cellPadEnd));
sys_io.AddFunc(0x0d5f2c14, bind_func(cellPadClearBuf));
sys_io.AddFunc(0x8b72cda1, bind_func(cellPadGetData));
sys_io.AddFunc(0x6bc09c61, bind_func(cellPadGetDataExtra));
sys_io.AddFunc(0xf65544ee, bind_func(cellPadSetActDirect));
sys_io.AddFunc(0xa703a51d, bind_func(cellPadGetInfo2));
sys_io.AddFunc(0x578e3c98, bind_func(cellPadSetPortSetting));
}
} sys_io_init;
sys_io.AddFunc(0x1cf98800, bind_func(cellPadInit));
sys_io.AddFunc(0x4d9b75d5, bind_func(cellPadEnd));
sys_io.AddFunc(0x0d5f2c14, bind_func(cellPadClearBuf));
sys_io.AddFunc(0x8b72cda1, bind_func(cellPadGetData));
sys_io.AddFunc(0x6bc09c61, bind_func(cellPadGetDataExtra));
sys_io.AddFunc(0xf65544ee, bind_func(cellPadSetActDirect));
sys_io.AddFunc(0xa703a51d, bind_func(cellPadGetInfo2));
sys_io.AddFunc(0x578e3c98, bind_func(cellPadSetPortSetting));
}

View File

@ -1,137 +1,7 @@
#include "stdafx.h"
#include "SysCalls.h"
#include "Modules.h"
#include "SC_FUNC.h"
#include <vector>
ArrayF<ModuleFunc> g_modules_funcs_list;
ArrayF<Module> g_modules_list;
bool IsLoadedFunc(u32 id)
{
for(u32 i=0; i<g_modules_funcs_list.GetCount(); ++i)
{
if(g_modules_funcs_list[i].id == id)
{
return true;
}
}
return false;
}
bool CallFunc(u32 id)
{
for(u32 i=0; i<g_modules_funcs_list.GetCount(); ++i)
{
if(g_modules_funcs_list[i].id == id)
{
(*g_modules_funcs_list[i].func)();
return true;
}
}
return false;
}
bool UnloadFunc(u32 id)
{
for(u32 i=0; i<g_modules_funcs_list.GetCount(); ++i)
{
if(g_modules_funcs_list[i].id == id)
{
g_modules_funcs_list.RemoveAt(i);
return true;
}
}
return false;
}
void UnloadModules()
{
for(u32 i=0; i<g_modules_list.GetCount(); ++i)
{
g_modules_list[i].SetLoaded(false);
}
g_modules_funcs_list.Clear();
}
Module* GetModuleByName(const wxString& name)
{
for(u32 i=0; i<g_modules_list.GetCount(); ++i)
{
if(g_modules_list[i].GetName().Cmp(name) == 0)
{
return &g_modules_list[i];
}
}
return nullptr;
}
Module* GetModuleById(u16 id)
{
for(u32 i=0; i<g_modules_list.GetCount(); ++i)
{
if(g_modules_list[i].GetID() == id)
{
return &g_modules_list[i];
}
}
return nullptr;
}
Module::Module(const char* name, u16 id)
: m_is_loaded(false)
, m_name(name)
, m_id(id)
{
g_modules_list.Add(this);
}
void Module::Load()
{
for(u32 i=0; i<m_funcs_list.GetCount(); ++i)
{
if(IsLoadedFunc(m_funcs_list[i].id)) continue;
g_modules_funcs_list.Add(m_funcs_list[i]);
}
}
void Module::UnLoad()
{
for(u32 i=0; i<m_funcs_list.GetCount(); ++i)
{
UnloadFunc(m_funcs_list[i].id);
}
}
bool Module::Load(u32 id)
{
if(IsLoadedFunc(id)) return false;
for(u32 i=0; i<m_funcs_list.GetCount(); ++i)
{
if(m_funcs_list[i].id == id)
{
g_modules_funcs_list.Add(m_funcs_list[i]);
return true;
}
}
return false;
}
bool Module::UnLoad(u32 id)
{
return UnloadFunc(id);
}
static func_caller* sc_table[1024] =
{
@ -160,20 +30,20 @@ static func_caller* sc_table[1024] =
null_func, null_func, null_func, null_func, null_func, //114
null_func, null_func, null_func, null_func, null_func, //119
null_func, null_func, null_func, null_func, null_func, //124
null_func, null_func, null_func, null_func, null_func, //129
null_func, null_func, null_func, null_func, null_func, //134
null_func, null_func, null_func, null_func, null_func, //139
null_func, null_func, null_func, bind_func(sys_event_queue_create), null_func, //129
bind_func(sys_event_queue_receive), null_func, null_func, null_func, bind_func(sys_event_port_create), //134
null_func, bind_func(sys_event_port_connect_local), null_func, null_func, null_func, //139
null_func, null_func, null_func, null_func, null_func, //144
bind_func(sys_time_get_current_time), bind_func(sys_time_get_system_time), bind_func(sys_time_get_timebase_frequency), null_func, null_func, //149
null_func, null_func, null_func, null_func, null_func, //154
null_func, null_func, null_func, null_func, null_func, //159
null_func, bind_func(sys_spu_image_open), null_func, null_func, null_func, //159
bind_func(sys_raw_spu_create), null_func, null_func, null_func, null_func, //164
null_func, null_func, null_func, null_func, bind_func(sys_spu_initialize), //169
bind_func(sys_spu_thread_group_create), null_func, null_func, null_func, null_func, //174
bind_func(sys_spu_thread_group_create), null_func, bind_func(sys_spu_thread_initialize), bind_func(sys_spu_thread_group_start), null_func, //174
null_func, null_func, null_func, null_func, null_func, //179
null_func, null_func, null_func, null_func, null_func, //184
null_func, bind_func(sys_spu_thread_write_ls), bind_func(sys_spu_thread_read_ls), null_func, null_func, //184
null_func, null_func, null_func, null_func, null_func, //189
null_func, null_func, null_func, null_func, null_func, //194
bind_func(sys_spu_thread_write_spu_mb), null_func, null_func, null_func, null_func, //194
null_func, null_func, null_func, null_func, null_func, //199
null_func, null_func, null_func, null_func, null_func, //204
null_func, null_func, null_func, null_func, null_func, //209
@ -185,7 +55,7 @@ static func_caller* sc_table[1024] =
null_func, null_func, null_func, null_func, null_func, //239
null_func, null_func, null_func, null_func, null_func, //244
null_func, null_func, null_func, null_func, null_func, //249
null_func, null_func, null_func, null_func, null_func, //254
null_func, bind_func(sys_spu_thread_group_connect_event_all_threads), null_func, null_func, null_func, //254
null_func, null_func, null_func, null_func, null_func, //259
null_func, null_func, null_func, null_func, null_func, //264
null_func, null_func, null_func, null_func, null_func, //269
@ -350,55 +220,67 @@ SysCalls::~SysCalls()
{
}
s64 SysCalls::DoSyscall(u32 code)
bool enable_log = false;
void SysCalls::DoSyscall(u32 code)
{
if(code < 0x400)
{
if(sc_table[code])
{
(*sc_table[code])();
return SC_ARGS_1;
return;
}
//TODO: remove this
switch(code)
{
//process
case 2: return lv2ProcessWaitForChild(CPU);
case 4: return lv2ProcessGetStatus(CPU);
case 5: return lv2ProcessDetachChild(CPU);
case 12: return lv2ProcessGetNumberOfObject(CPU);
case 13: return lv2ProcessGetId(CPU);
case 18: return lv2ProcessGetPpid(CPU);
case 19: return lv2ProcessKill(CPU);
case 23: return lv2ProcessWaitForChild2(CPU);
case 25: return lv2ProcessGetSdkVersion(CPU);
case 2: RESULT(lv2ProcessWaitForChild(CPU)); return;
case 4: RESULT(lv2ProcessGetStatus(CPU)); return;
case 5: RESULT(lv2ProcessDetachChild(CPU)); return;
case 12: RESULT(lv2ProcessGetNumberOfObject(CPU)); return;
case 13: RESULT(lv2ProcessGetId(CPU)); return;
case 18: RESULT(lv2ProcessGetPpid(CPU)); return;
case 19: RESULT(lv2ProcessKill(CPU)); return;
case 23: RESULT(lv2ProcessWaitForChild2(CPU)); return;
case 25: RESULT(lv2ProcessGetSdkVersion(CPU)); return;
//timer
case 141:
case 142:
Sleep(SC_ARGS_1 / (1000 * 1000));
return 0;
RESULT(0);
return;
//tty
case 988:
ConLog.Warning("SysCall 988! r3: 0x%llx, r4: 0x%llx, pc: 0x%llx",
CPU.GPR[3], CPU.GPR[4], CPU.PC);
return 0;
RESULT(0);
return;
case 999:
dump_enable = !dump_enable;
ConLog.Warning("Dump %s", dump_enable ? "enabled" : "disabled");
return 0;
return;
case 1000:
enable_log = !enable_log;
ConLog.Warning("Log %s", enable_log ? "enabled" : "disabled");
return;
}
ConLog.Error("Unknown syscall: %d - %08x", code, code);
return 0;
RESULT(0);
return;
}
if(CallFunc(code)) return SC_ARGS_1;
if(CallFunc(code))
{
return;
}
//ConLog.Error("Unknown function 0x%08x", code);
//return 0;
//TODO: remove this
return DoFunc(code);
RESULT(DoFunc(code));
}

View File

@ -5,161 +5,7 @@
#define declCPU PPUThread& CPU = GetCurrentPPUThread
class func_caller
{
public:
virtual void operator()() = 0;
};
static func_caller *null_func = nullptr;
//TODO
struct ModuleFunc
{
u32 id;
func_caller* func;
ModuleFunc(u32 id, func_caller* func)
: id(id)
, func(func)
{
}
};
class Module
{
const char* m_name;
const u16 m_id;
bool m_is_loaded;
public:
Array<ModuleFunc> m_funcs_list;
Module(const char* name, u16 id);
void Load();
void UnLoad();
bool Load(u32 id);
bool UnLoad(u32 id);
void SetLoaded(bool loaded = true)
{
m_is_loaded = loaded;
}
bool IsLoaded() const
{
return m_is_loaded;
}
u16 GetID() const
{
return m_id;
}
wxString GetName() const
{
return m_name;
}
public:
void Log(const u32 id, wxString fmt, ...)
{
#ifdef SYSCALLS_DEBUG
va_list list;
va_start(list, fmt);
ConLog.Write(GetName() + wxString::Format("[%d]: ", id) + wxString::FormatV(fmt, list));
va_end(list);
#endif
}
void Log(wxString fmt, ...)
{
#ifdef SYSCALLS_DEBUG
va_list list;
va_start(list, fmt);
ConLog.Write(GetName() + ": " + wxString::FormatV(fmt, list));
va_end(list);
#endif
}
void Warning(const u32 id, wxString fmt, ...)
{
//#ifdef SYSCALLS_DEBUG
va_list list;
va_start(list, fmt);
ConLog.Warning(GetName() + wxString::Format("[%d] warning: ", id) + wxString::FormatV(fmt, list));
va_end(list);
//#endif
}
void Warning(wxString fmt, ...)
{
//#ifdef SYSCALLS_DEBUG
va_list list;
va_start(list, fmt);
ConLog.Warning(GetName() + " warning: " + wxString::FormatV(fmt, list));
va_end(list);
//#endif
}
void Error(const u32 id, wxString fmt, ...)
{
va_list list;
va_start(list, fmt);
ConLog.Error(GetName() + wxString::Format("[%d] error: ", id) + wxString::FormatV(fmt, list));
va_end(list);
}
void Error(wxString fmt, ...)
{
va_list list;
va_start(list, fmt);
ConLog.Error(GetName() + " error: " + wxString::FormatV(fmt, list));
va_end(list);
}
bool CheckId(u32 id) const
{
return Emu.GetIdManager().CheckID(id) && !Emu.GetIdManager().GetIDData(id).m_name.Cmp(GetName());
}
bool CheckId(u32 id, ID& _id) const
{
return Emu.GetIdManager().CheckID(id) && !(_id = Emu.GetIdManager().GetIDData(id)).m_name.Cmp(GetName());
}
template<typename T> bool CheckId(u32 id, T*& data)
{
ID id_data;
if(!CheckId(id, id_data)) return false;
data = (T*)id_data.m_data;
return true;
}
u32 GetNewId(void* data = nullptr, u8 flags = 0)
{
return Emu.GetIdManager().GetNewID(GetName(), data, flags);
}
//protected:
__forceinline void AddFunc(u32 id, func_caller* func)
{
m_funcs_list.Move(new ModuleFunc(id, func));
}
};
static s64 null_function() { return 0; }
bool IsLoadedFunc(u32 id);
bool CallFunc(u32 id);
bool UnloadFunc(u32 id);
void UnloadModules();
Module* GetModuleByName(const wxString& name);
Module* GetModuleById(u16 id);
extern bool enable_log;
class SysCallBase //Module
{
@ -178,22 +24,24 @@ public:
void Log(const u32 id, wxString fmt, ...)
{
#ifdef SYSCALLS_DEBUG
if(enable_log)
{
va_list list;
va_start(list, fmt);
ConLog.Write(GetName() + wxString::Format("[%d]: ", id) + wxString::FormatV(fmt, list));
va_end(list);
#endif
}
}
void Log(wxString fmt, ...)
{
#ifdef SYSCALLS_DEBUG
if(enable_log)
{
va_list list;
va_start(list, fmt);
ConLog.Write(GetName() + ": " + wxString::FormatV(fmt, list));
va_end(list);
#endif
}
}
void Warning(const u32 id, wxString fmt, ...)
@ -259,40 +107,18 @@ public:
}
};
/*
static bool CmpPath(const wxString& path1, const wxString& path2)
{
return path1.Len() >= path2.Len() && path1(0, path2.Len()).CmpNoCase(path2) == 0;
}
static wxString GetWinPath(const wxString& path)
{
if(!CmpPath(path, "/") && CmpPath(path(1, 1), ":")) return path;
wxString ppath = wxFileName(Emu.m_path).GetPath() + '/' + wxFileName(path).GetFullName();
if(wxFileExists(ppath)) return ppath;
if (CmpPath(path, "/dev_hdd0/") ||
CmpPath(path, "/dev_hdd1/") ||
CmpPath(path, "/dev_bdvd/") ||
CmpPath(path, "/dev_usb001/") ||
CmpPath(path, "/ps3_home/") ||
CmpPath(path, "/app_home/") ||
CmpPath(path, "/dev_flash/") ||
CmpPath(path, "/dev_flash2/") ||
CmpPath(path, "/dev_flash3/")
) return wxGetCwd() + path;
return wxFileName(Emu.m_path).GetPath() + (path[0] == '/' ? path : "/" + path);
}
*/
//process
extern int sys_process_getpid();
extern int sys_process_exit(int errorcode);
extern int sys_game_process_exitspawn(u32 path_addr, u32 argv_addr, u32 envp_addr,
u32 data, u32 data_size, int prio, u64 flags );
//sys_event
extern int sys_event_queue_create(u32 equeue_id_addr, u32 attr_addr, u64 event_queue_key, int size);
extern int sys_event_queue_receive(u32 equeue_id, u32 event_addr, u32 timeout);
extern int sys_event_port_create(u32 eport_id_addr, int port_type, u64 name);
extern int sys_event_port_connect_local(u32 event_port_id, u32 event_queue_id);
//sys_semaphore
extern int sys_semaphore_create(u32 sem_addr, u32 attr_addr, int initial_val, int max_val);
extern int sys_semaphore_destroy(u32 sem);
@ -333,7 +159,9 @@ extern int sys_ppu_thread_get_stack_information(u32 info_addr);
extern int sys_ppu_thread_stop(u32 thread_id);
extern int sys_ppu_thread_restart(u32 thread_id);
extern int sys_ppu_thread_create(u32 thread_id_addr, u32 entry, u32 arg, int prio, u32 stacksize, u64 flags, u32 threadname_addr);
extern int sys_ppu_thread_get_id();
extern void sys_ppu_thread_once(u32 once_ctrl_addr, u32 entry);
extern int sys_ppu_thread_get_id(const u32 id_addr);
extern int sys_spu_thread_group_connect_event_all_threads(u32 id, u32 eq, u64 req, u32 spup_addr);
//memory
extern int sys_memory_container_create(u32 cid_addr, u32 yield_size);
@ -421,10 +249,16 @@ extern int sys_heap_create_heap(const u32 heap_addr, const u32 start_addr, const
extern int sys_heap_malloc(const u32 heap_addr, const u32 size);
//sys_spu
extern int sys_spu_image_open(u32 img_addr, u32 path_addr);
extern int sys_spu_thread_initialize(u32 thread_addr, u32 group, u32 spu_num, u32 img_addr, u32 attr_addr, u32 arg_addr);
extern int sys_spu_thread_group_start(u32 id);
extern int sys_spu_thread_group_create(u64 id_addr, u32 num, int prio, u64 attr_addr);
extern int sys_spu_thread_create(u64 thread_id_addr, u64 entry_addr, u64 arg, int prio, u32 stacksize, u64 flags, u64 threadname_addr);
extern int sys_raw_spu_create(u32 id_addr, u32 attr_addr);
extern int sys_spu_initialize(u32 max_usable_spu, u32 max_raw_spu);
extern int sys_spu_thread_write_ls(u32 id, u32 address, u64 value, u32 type);
extern int sys_spu_thread_read_ls(u32 id, u32 address, u32 value_addr, u32 type);
extern int sys_spu_thread_write_spu_mb(u32 id, u32 value);
//sys_time
extern int sys_time_get_current_time(u32 sec_addr, u32 nsec_addr);
@ -469,7 +303,7 @@ protected:
~SysCalls();
public:
s64 DoSyscall(u32 code);
void DoSyscall(u32 code);
s64 DoFunc(const u32 id);
};

View File

@ -0,0 +1,137 @@
#include "stdafx.h"
#include "Emu/SysCalls/SysCalls.h"
#include "Emu/Cell/SPUThread.h"
#include "Emu/event.h"
SysCallBase sys_event("sys_event");
//128
int sys_event_queue_create(u32 equeue_id_addr, u32 attr_addr, u64 event_queue_key, int size)
{
sys_event.Warning("sys_event_queue_create(equeue_id_addr=0x%x, attr_addr=0x%x, event_queue_key=0x%llx, size=%d)",
equeue_id_addr, attr_addr, event_queue_key, size);
if(size <= 0 || size > 127)
{
return CELL_EINVAL;
}
if(!Memory.IsGoodAddr(equeue_id_addr, 4) || !Memory.IsGoodAddr(attr_addr, sizeof(sys_event_queue_attr)))
{
return CELL_EFAULT;
}
auto& attr = (sys_event_queue_attr&)Memory[attr_addr];
sys_event.Warning("name = %s", attr.name);
sys_event.Warning("type = %d", re(attr.type));
EventQueue* equeue = new EventQueue();
equeue->size = size;
equeue->pos = 0;
equeue->type = re(attr.type);
strncpy(equeue->name, attr.name, 8);
Memory.Write32(equeue_id_addr, sys_event.GetNewId(equeue));
return CELL_OK;
}
int sys_event_queue_receive(u32 equeue_id, u32 event_addr, u32 timeout)
{
sys_event.Warning("sys_event_queue_receive(equeue_id=0x%x, event_addr=0x%x, timeout=0x%x)",
equeue_id, event_addr, timeout);
if(!sys_event.CheckId(equeue_id))
{
return CELL_ESRCH;
}
PPCThread* thr = GetCurrentPPCThread();
while(true)
{
int status = thr->ThreadStatus();
if(status == PPCThread_Stopped)
{
return CELL_ECANCELED;
}
EventQueue* equeue = (EventQueue*)Emu.GetIdManager().GetIDData(equeue_id).m_data;
for(int i=0; i<equeue->pos; ++i)
{
if(!equeue->ports[i]->has_data && equeue->ports[i]->thread)
{
SPUThread* thr = (SPUThread*)equeue->ports[i]->thread;
if(thr->OutIntrMbox.GetCount())
{
u32 val;
thr->OutIntrMbox.Pop(val);
if(!thr->OutMbox.Pop(val)) val = 0;
equeue->ports[i]->data1 = val;
equeue->ports[i]->data2 = 0;
equeue->ports[i]->data3 = 0;
equeue->ports[i]->has_data = true;
}
}
}
bool has_data = false;
for(int i=0; i<equeue->pos; i++)
{
if(equeue->ports[i]->has_data)
{
has_data = true;
auto res = (sys_event_data&)Memory[event_addr];
re(res.source, equeue->ports[i]->name);
re(res.data1, equeue->ports[i]->data1);
re(res.data2, equeue->ports[i]->data2);
re(res.data3, equeue->ports[i]->data3);
equeue->ports[i]->has_data = false;
break;
}
}
if(has_data)
break;
Sleep(1);
}
return CELL_OK;
}
int sys_event_port_create(u32 eport_id_addr, int port_type, u64 name)
{
sys_event.Warning("sys_event_port_create(eport_id_addr=0x%x, port_type=0x%x, name=0x%llx)",
eport_id_addr, port_type, name);
if(!Memory.IsGoodAddr(eport_id_addr, 4))
{
return CELL_EFAULT;
}
EventPort* eport = new EventPort();
u32 id = sys_event.GetNewId(eport);
eport->has_data = false;
eport->name = name ? name : id;
Memory.Write32(eport_id_addr, id);
return CELL_OK;
}
int sys_event_port_connect_local(u32 event_port_id, u32 event_queue_id)
{
sys_event.Warning("sys_event_port_connect_local(event_port_id=0x%x, event_queue_id=0x%x)",
event_port_id, event_queue_id);
if(!sys_event.CheckId(event_port_id) || !sys_event.CheckId(event_queue_id))
{
return CELL_ESRCH;
}
EventPort* eport = (EventPort*)Emu.GetIdManager().GetIDData(event_port_id).m_data;
EventQueue* equeue = (EventQueue*)Emu.GetIdManager().GetIDData(event_queue_id).m_data;
equeue->ports[equeue->pos++] = eport;
return CELL_OK;
}

View File

@ -33,26 +33,15 @@ SysCallBase sc_lwmutex("sys_wmutex");
int sys_lwmutex_create(u64 lwmutex_addr, u64 lwmutex_attr_addr)
{
if(!Memory.IsGoodAddr(lwmutex_addr, 4) || !Memory.IsGoodAddr(lwmutex_attr_addr))
{
return CELL_EFAULT;
}
lwmutex& lmtx = (lwmutex&)Memory[lwmutex_addr];
lmtx.lock_var.all_info = 0;
lwmutex_attr& lmtx_attr = (lwmutex_attr&)Memory[lwmutex_attr_addr];
//sc_lwmutex.Warning("sys_lwmutex_create(lwmutex_addr = 0x%llx, lwmutex_attr_addr = 0x%llx)", lwmutex_addr, lwmutex_attr_addr);
lmtx.lock_var.info.owner = 0;
lmtx.lock_var.info.waiter = 0;
lmtx.attribute = Emu.GetIdManager().GetNewID(wxString::Format("lwmutex[%s]", lmtx_attr.name), nullptr, lwmutex_addr);
/*
ConLog.Write("r3:");
ConLog.Write("*** lock_var[owner: 0x%x, waiter: 0x%x]", re(lmtx.lock_var.info.owner), re(lmtx.lock_var.info.waiter));
ConLog.Write("*** attribute: 0x%x", re(lmtx.attribute));
ConLog.Write("*** recursive_count: 0x%x", re(lmtx.recursive_count));
ConLog.Write("*** sleep_queue: 0x%x", re(lmtx.sleep_queue));
ConLog.Write("r4:");
ConLog.Write("*** attr_protocol: 0x%x", re(lmtx_attr.attr_protocol));
ConLog.Write("*** attr_recursive: 0x%x", re(lmtx_attr.attr_recursive));
ConLog.Write("*** name: %s", lmtx_attr.name);
*/
return CELL_OK;
}
@ -60,39 +49,46 @@ int sys_lwmutex_destroy(u64 lwmutex_addr)
{
//sc_lwmutex.Warning("sys_lwmutex_destroy(lwmutex_addr = 0x%llx)", lwmutex_addr);
lwmutex& lmtx = (lwmutex&)Memory[lwmutex_addr];
Emu.GetIdManager().RemoveID(lmtx.attribute);
//lwmutex& lmtx = (lwmutex&)Memory[lwmutex_addr];
//Emu.GetIdManager().RemoveID(lmtx.attribute);
return CELL_OK;
}
int sys_lwmutex_lock(u64 lwmutex_addr, u64 timeout)
{
//sc_lwmutex.Warning("sys_lwmutex_lock(lwmutex_addr = 0x%llx, timeout = 0x%llx)", lwmutex_addr, timeout);
lwmutex& lmtx = (lwmutex&)Memory[lwmutex_addr];
PPCThread& thr = GetCurrentPPUThread();
if(thr.GetId() == re(lmtx.lock_var.info.owner))
{
re(lmtx.recursive_count, re(lmtx.recursive_count) + 1);
return CELL_OK;
}
if(!lmtx.lock_var.info.owner)
{
re(lmtx.lock_var.info.owner, GetCurrentPPUThread().GetId());
re(lmtx.recursive_count, 1);
}
else if(!lmtx.lock_var.info.waiter)
{
re(lmtx.lock_var.info.waiter, GetCurrentPPUThread().GetId());
while(re(lmtx.lock_var.info.owner) != GetCurrentPPUThread().GetId()) Sleep(1);
thr.Wait(true);
re(lmtx.lock_var.info.waiter, thr.GetId());
}
else
{
return -1;
ConLog.Warning("lwmutex has waiter!");
return CELL_EBUSY;
}
return CELL_OK;
}
int sys_lwmutex_trylock(u64 lwmutex_addr)
{
//sc_lwmutex.Warning("sys_lwmutex_trylock(lwmutex_addr = 0x%llx)", lwmutex_addr);
lwmutex& lmtx = (lwmutex&)Memory[lwmutex_addr];
if(lmtx.lock_var.info.owner) return CELL_EBUSY;
@ -105,8 +101,21 @@ int sys_lwmutex_unlock(u64 lwmutex_addr)
//sc_lwmutex.Warning("sys_lwmutex_unlock(lwmutex_addr = 0x%llx)", lwmutex_addr);
lwmutex& lmtx = (lwmutex&)Memory[lwmutex_addr];
lmtx.lock_var.info.owner = lmtx.lock_var.info.waiter;
lmtx.lock_var.info.waiter = 0;
re(lmtx.recursive_count, re(lmtx.recursive_count) - 1);
if(!lmtx.recursive_count)
{
if(lmtx.lock_var.info.owner = lmtx.lock_var.info.waiter)
{
lmtx.lock_var.info.waiter = 0;
PPCThread* thr = Emu.GetCPU().GetThread(lmtx.lock_var.info.owner);
if(thr)
{
thr->Wait(false);
}
}
}
return CELL_OK;
}

View File

@ -3,7 +3,12 @@
extern Module sysPrxForUser;
#define PPU_THREAD_ID_INVALID 0xFFFFFFFFU
static const u32 PPU_THREAD_ID_INVALID = 0xFFFFFFFFU;
enum
{
SYS_PPU_THREAD_ONCE_INIT,
SYS_PPU_THREAD_DONE_INIT,
};
int sys_ppu_thread_exit(int errorcode)
{
@ -15,9 +20,14 @@ int sys_ppu_thread_exit(int errorcode)
int sys_ppu_thread_yield()
{
sysPrxForUser.Log("sys_ppu_thread_yield()");
wxThread::Yield();
sysPrxForUser.Log("sys_ppu_thread_yield()");
enable_log = !enable_log;
dump_enable = !dump_enable;
if(!enable_log)
{
Emu.Pause();
}
return CELL_OK;
}
@ -110,7 +120,10 @@ int sys_ppu_thread_create(u32 thread_id_addr, u32 entry, u32 arg, int prio, u32
sysPrxForUser.Log("sys_ppu_thread_create(thread_id_addr=0x%x, entry=0x%x, arg=0x%x, prio=%d, stacksize=0x%x, flags=0x%llx, threadname_addr=0x%x('%s'))",
thread_id_addr, entry, arg, prio, stacksize, flags, threadname_addr, Memory.ReadString(threadname_addr));
if(!Memory.IsGoodAddr(entry) || !Memory.IsGoodAddr(thread_id_addr) || !Memory.IsGoodAddr(threadname_addr)) return CELL_EFAULT;
if(!Memory.IsGoodAddr(entry) || !Memory.IsGoodAddr(thread_id_addr) || !Memory.IsGoodAddr(threadname_addr))
{
return CELL_EFAULT;
}
PPCThread& new_thread = Emu.GetCPU().AddThread(true);
@ -127,9 +140,28 @@ int sys_ppu_thread_create(u32 thread_id_addr, u32 entry, u32 arg, int prio, u32
return CELL_OK;
}
int sys_ppu_thread_get_id()
void sys_ppu_thread_once(u32 once_ctrl_addr, u32 entry)
{
sysPrxForUser.Log("sys_ppu_thread_get_id()");
sysPrxForUser.Warning("sys_ppu_thread_once(once_ctrl_addr=0x%x, entry=0x%x)", once_ctrl_addr, entry);
return GetCurrentPPUThread().GetId();
if(Memory.IsGoodAddr(once_ctrl_addr, 4) && Memory.Read32(once_ctrl_addr) == SYS_PPU_THREAD_ONCE_INIT)
{
Memory.Write32(once_ctrl_addr, SYS_PPU_THREAD_DONE_INIT);
PPCThread& new_thread = Emu.GetCPU().AddThread(true);
new_thread.SetEntry(entry);
((PPUThread&)new_thread).LR = Emu.GetPPUThreadExit();
new_thread.Run();
new_thread.Exec();
GetCurrentPPUThread().Wait(new_thread);
}
}
int sys_ppu_thread_get_id(const u32 id_addr)
{
sysPrxForUser.Log("sys_ppu_thread_get_id(id_addr=0x%x)", id_addr);
Memory.Write32(id_addr, GetCurrentPPUThread().GetId());
return CELL_OK;
}

View File

@ -1,6 +1,7 @@
#include "stdafx.h"
#include "Emu/SysCalls/SysCalls.h"
#include "Loader/ELF.h"
#include "Emu/Cell/SPUThread.h"
SysCallBase sc_spu("sys_spu");
@ -12,6 +13,21 @@ struct sys_spu_thread_group_attribute
union{u32 ct;} option;
};
struct sys_spu_thread_attribute
{
u32 name_addr;
u32 name_len;
u32 option;
};
struct sys_spu_thread_argument
{
u64 arg1;
u64 arg2;
u64 arg3;
u64 arg4;
};
struct sys_spu_image
{
u32 type;
@ -20,25 +36,149 @@ struct sys_spu_image
int nsegs;
};
u32 LoadImage(vfsStream& stream)
struct SpuGroupInfo
{
PPCThread* threads[10];
sys_spu_thread_group_attribute& attr;
SpuGroupInfo(sys_spu_thread_group_attribute& attr) : attr(attr)
{
memset(threads, 0, sizeof(PPCThread*) * 10);
}
};
u64 g_spu_offset = 0;
u32 LoadSpuImage(vfsStream& stream)
{
ELFLoader l(stream);
l.LoadInfo();
l.LoadData(Memory.MainMem.Alloc(stream.GetSize()));
g_spu_offset = Memory.MainMem.Alloc(0xFFFFED - stream.GetSize());
l.LoadData(g_spu_offset);
return l.GetEntry();
return g_spu_offset + l.GetEntry();
}
int sys_spu_image_open(u32 img_addr, u32 path_addr)
{
//156
int sys_spu_image_open(u32 img_addr, u32 path_addr)
{
const wxString& path = Memory.ReadString(path_addr);
sc_spu.Warning("sys_spu_image_open(img_addr=0x%x, path_addr=0x%x [%s])", img_addr, path_addr, path);
vfsLocalFile stream(path);
LoadImage(stream);
if(!Memory.IsGoodAddr(img_addr, sizeof(sys_spu_image)) || !Memory.IsGoodAddr(path_addr))
{
return CELL_EFAULT;
}
vfsStream* stream = Emu.GetVFS().Open(path, vfsRead);
if(!stream || !stream->IsOpened())
{
sc_spu.Error("'%s' not found!", path);
delete stream;
return CELL_ENOENT;
}
u32 entry = LoadSpuImage(*stream);
delete stream;
sys_spu_image& ret = (sys_spu_image&)Memory[img_addr];
re(ret.type, 1);
re(ret.entry_point, entry);
re(ret.segs_addr, 0x0);
re(ret.nsegs, 0);
return CELL_OK;
}
}
//172
int sys_spu_thread_initialize(u32 thread_addr, u32 group, u32 spu_num, u32 img_addr, u32 attr_addr, u32 arg_addr)
{
sc_spu.Warning("sys_spu_thread_initialize(thread_addr=0x%x, group=0x%x, spu_num=%d, img_addr=0x%x, attr_addr=0x%x, arg_addr=0x%x)",
thread_addr, group, spu_num, img_addr, attr_addr, arg_addr);
if(!Emu.GetIdManager().CheckID(group))
{
return CELL_ESRCH;
}
if(
!Memory.IsGoodAddr(img_addr, sizeof(sys_spu_image)) ||
!Memory.IsGoodAddr(attr_addr, sizeof(sys_spu_thread_attribute)) ||
!Memory.IsGoodAddr(arg_addr, sizeof(sys_spu_thread_argument)))
{
return CELL_EFAULT;
}
sys_spu_image& img = (sys_spu_image&)Memory[img_addr];
sys_spu_thread_attribute& attr = (sys_spu_thread_attribute&)Memory[attr_addr];
sys_spu_thread_argument& arg = (sys_spu_thread_argument&)Memory[arg_addr];
if(!Memory.IsGoodAddr(re(attr.name_addr), re(attr.name_len)))
{
return CELL_EFAULT;
}
u32 entry = re(img.entry_point);
wxString name = Memory.ReadString(re(attr.name_addr), re(attr.name_len));
u64 a1 = re(arg.arg1);
u64 a2 = re(arg.arg2);
u64 a3 = re(arg.arg3);
u64 a4 = re(arg.arg4);
ConLog.Write("New SPU Thread:");
ConLog.Write("entry = 0x%x", entry);
ConLog.Write("name = %s", name);
ConLog.Write("a1 = 0x%x", a1);
ConLog.Write("a2 = 0x%x", a2);
ConLog.Write("a3 = 0x%x", a3);
ConLog.Write("a4 = 0x%x", a4);
ConLog.SkipLn();
PPCThread& new_thread = Emu.GetCPU().AddThread(false);
new_thread.SetOffset(g_spu_offset);
new_thread.SetEntry(entry - g_spu_offset);
new_thread.SetName(name);
SPU_GPR_hdr* GPR = ((SPUThread&)new_thread).GPR;
new_thread.Run();
new_thread.Pause();
GPR[3]._u64[1] = a1;
GPR[4]._u64[1] = a2;
GPR[5]._u64[1] = a3;
GPR[6]._u64[1] = a4;
ID& id = Emu.GetIdManager().GetIDData(group);
SpuGroupInfo& group_info = *(SpuGroupInfo*)id.m_data;
group_info.threads[spu_num] = &new_thread;
return CELL_OK;
}
//173
int sys_spu_thread_group_start(u32 id)
{
sc_spu.Warning("sys_spu_thread_group_start(id=0x%x)", id);
if(!Emu.GetIdManager().CheckID(id))
{
return CELL_ESRCH;
}
ID& id_data = Emu.GetIdManager().GetIDData(id);
SpuGroupInfo& group_info = *(SpuGroupInfo*)id_data.m_data;
Emu.Pause();
for(int i=0; i<10; i++)
{
if(group_info.threads[i])
{
group_info.threads[i]->Exec();
}
}
return CELL_OK;
}
//170
int sys_spu_thread_group_create(u64 id_addr, u32 num, int prio, u64 attr_addr)
@ -49,7 +189,7 @@ int sys_spu_thread_group_create(u64 id_addr, u32 num, int prio, u64 attr_addr)
ConLog.Write("*** prio=%d", prio);
ConLog.Write("*** attr_addr=0x%llx", attr_addr);
sys_spu_thread_group_attribute& attr = *new sys_spu_thread_group_attribute(*(sys_spu_thread_group_attribute*)&Memory[attr_addr]);
sys_spu_thread_group_attribute& attr = (sys_spu_thread_group_attribute&)Memory[attr_addr];
ConLog.Write("*** attr.name_len=%d", re(attr.name_len));
ConLog.Write("*** attr.name_addr=0x%x", re(attr.name_addr));
@ -60,7 +200,7 @@ int sys_spu_thread_group_create(u64 id_addr, u32 num, int prio, u64 attr_addr)
ConLog.Write("*** name='%s'", name);
Memory.Write32(id_addr,
Emu.GetIdManager().GetNewID(wxString::Format("sys_spu_thread_group %s", name), &attr, 0));
Emu.GetIdManager().GetNewID(wxString::Format("sys_spu_thread_group '%s'", name), new SpuGroupInfo(attr)));
return CELL_OK;
}
@ -76,10 +216,10 @@ int sys_raw_spu_create(u32 id_addr, u32 attr_addr)
{
sc_spu.Warning("sys_raw_spu_create(id_addr=0x%x, attr_addr=0x%x)", id_addr, attr_addr);
//PPCThread& new_thread = Emu.GetCPU().AddThread(false);
//Emu.GetIdManager().GetNewID("sys_raw_spu", new u32(attr_addr));
//Memory.Write32(id_addr, Emu.GetCPU().GetThreadNumById(false, new_thread.GetId()));
PPCThread& new_thread = Emu.GetCPU().AddThread(false);
Memory.Write32(id_addr, Emu.GetCPU().GetThreadNumById(false, new_thread.GetId()));
Memory.Write32(0xe0043014, 0);
return CELL_OK;
}
@ -88,10 +228,126 @@ int sys_spu_initialize(u32 max_usable_spu, u32 max_raw_spu)
{
sc_spu.Warning("sys_spu_initialize(max_usable_spu=%d, max_raw_spu=%d)", max_usable_spu, max_raw_spu);
if(max_raw_spu > 5)
{
return CELL_EINVAL;
}
if(!Memory.InitSpuRawMem(max_raw_spu))
{
//30010780;
//e0043004 - offset
//e004300c - entry
return CELL_UNKNOWN_ERROR;
}
//enable_log = true;
//dump_enable = true;
return CELL_OK;
}
//181
int sys_spu_thread_write_ls(u32 id, u32 address, u64 value, u32 type)
{
sc_spu.Warning("sys_spu_thread_write_ls(id=0x%x, address=0x%x, value=0x%llx, type=0x%x)",
id, address, value, type);
PPCThread* thr = Emu.GetCPU().GetThread(id);
if(!thr || !thr->IsSPU())
{
return CELL_ESRCH;
}
(*(SPUThread*)thr).WriteLS64(address, value);
return CELL_OK;
}
//182
int sys_spu_thread_read_ls(u32 id, u32 address, u32 value_addr, u32 type)
{
sc_spu.Warning("sys_spu_thread_read_ls(id=0x%x, address=0x%x, value_addr=0x%x, type=0x%x)",
id, address, value_addr, type);
PPCThread* thr = Emu.GetCPU().GetThread(id);
if(!thr || !thr->IsSPU())
{
return CELL_ESRCH;
}
if(!(*(SPUThread*)thr).IsGoodLSA(address))
{
return CELL_EFAULT;
}
Memory.Write64(value_addr, (*(SPUThread*)thr).ReadLS64(address));
return CELL_OK;
}
//190
int sys_spu_thread_write_spu_mb(u32 id, u32 value)
{
sc_spu.Warning("sys_spu_thread_write_spu_mb(id=0x%x, value=0x%x)", id, value);
PPCThread* thr = Emu.GetCPU().GetThread(id);
if(!thr || !thr->IsSPU())
{
return CELL_ESRCH;
}
if(!(*(SPUThread*)thr).InMbox.Push(value))
{
ConLog.Warning("sys_spu_thread_write_spu_mb(id=0x%x, value=0x%x): used all mbox items.");
return CELL_EBUSY; //?
}
return CELL_OK;
}
extern SysCallBase sys_event;
int sys_spu_thread_group_connect_event_all_threads(u32 id, u32 eq, u64 req, u32 spup_addr)
{
sc_spu.Warning("sys_spu_thread_group_connect_event_all_threads(id=0x%x, eq=0x%x, req=0x%llx, spup_addr=0x%x)",
id, eq, req, spup_addr);
if(!Emu.GetIdManager().CheckID(id) || !sys_event.CheckId(eq))
{
return CELL_ESRCH;
}
if(!req)
{
return CELL_EINVAL;
}
SpuGroupInfo* group = (SpuGroupInfo*)Emu.GetIdManager().GetIDData(id).m_data;
EventQueue* equeue = (EventQueue*)Emu.GetIdManager().GetIDData(eq).m_data;
for(int i=0; i<10; ++i)
{
if(group->threads[i])
{
bool finded_port = false;
for(int j=0; j<equeue->pos; ++j)
{
if(!equeue->ports[j]->thread)
{
finded_port = true;
equeue->ports[j]->thread = group->threads[i];
}
}
if(!finded_port)
{
return CELL_EISCONN;
}
}
}
return CELL_OK;
}

View File

@ -12,7 +12,10 @@ using namespace PPU_instr;
static const wxString& BreakPointsDBName = "BreakPoints.dat";
static const u16 bpdb_version = 0x1000;
//SysCalls SysCallsManager;
ModuleInitializer::ModuleInitializer()
{
Emu.AddModuleInit(this);
}
Emulator::Emulator()
: m_status(Stopped)
@ -24,6 +27,11 @@ Emulator::Emulator()
void Emulator::Init()
{
while(m_modules_init.GetCount())
{
m_modules_init[0].Init();
m_modules_init.RemoveAt(0);
}
//if(m_memory_viewer) m_memory_viewer->Close();
//m_memory_viewer = new MemoryViewerPanel(wxGetApp().m_MainFrame);
}
@ -108,7 +116,19 @@ void Emulator::Load()
LoadPoints(BreakPointsDBName);
PPCThread& thread = GetCPU().AddThread(l.GetMachine() == MACHINE_PPC64);
thread.SetEntry(l.GetEntry());
if(l.GetMachine() == MACHINE_SPU)
{
ConLog.Write("offset = 0x%llx", Memory.MainMem.GetStartAddr());
ConLog.Write("max addr = 0x%x", l.GetMaxAddr());
thread.SetOffset(Memory.MainMem.GetStartAddr());
Memory.MainMem.Alloc(Memory.MainMem.GetStartAddr() + l.GetMaxAddr(), 0xFFFFED - l.GetMaxAddr());
thread.SetEntry(l.GetEntry() - Memory.MainMem.GetStartAddr());
}
else
{
thread.SetEntry(l.GetEntry());
}
thread.SetArg(thread.GetId());
Memory.StackMem.Alloc(0x1000);
thread.InitStack();

View File

@ -8,6 +8,7 @@
#include "Emu/DbgConsole.h"
#include "Loader/Loader.h"
#include "SysCalls/Callback.h"
#include "SysCalls/Modules.h"
struct EmuInfo
{
@ -45,6 +46,14 @@ public:
u64 GetTLSMemsz() const { return tls_memsz; }
};
class ModuleInitializer
{
public:
ModuleInitializer();
virtual void Init() = 0;
};
class Emulator
{
enum Mode
@ -62,6 +71,7 @@ class Emulator
u32 m_ppu_thr_exit;
MemoryViewerPanel* m_memory_viewer;
//ArrayF<CPUThread> m_cpu_threads;
ArrayF<ModuleInitializer> m_modules_init;
Array<u64> m_break_points;
Array<u64> m_marked_points;
@ -93,6 +103,11 @@ public:
VFS& GetVFS() { return m_vfs; }
Array<u64>& GetBreakPoints() { return m_break_points; }
Array<u64>& GetMarkedPoints() { return m_marked_points; }
void AddModuleInit(ModuleInitializer* m)
{
m_modules_init.Add(m);
}
void SetTLSData(const u64 addr, const u64 filesz, const u64 memsz)
{

35
rpcs3/Emu/event.h Normal file
View File

@ -0,0 +1,35 @@
#pragma once
struct sys_event_queue_attr
{
u32 attr_protocol;
int type;
char name[8];
};
struct sys_event_data
{
u64 source;
u64 data1;
u64 data2;
u64 data3;
};
struct EventPort
{
u64 name;
u64 data1;
u64 data2;
u64 data3;
bool has_data;
PPCThread* thread;
};
struct EventQueue
{
EventPort* ports[127];
int size;
int pos;
int type;
char name[8];
};

View File

@ -164,16 +164,17 @@ void InterpreterDisAsmFrame::ShowAddr(const u64 addr)
{
PC = addr;
m_list->Freeze();
disasm->offset = CPU.GetOffset();
for(uint i=0; i<m_item_count; ++i, PC += 4)
{
if(!Memory.IsGoodAddr(PC, 4))
if(!Memory.IsGoodAddr(CPU.GetOffset() + PC, 4))
{
m_list->SetItem(i, 0, wxString::Format("[%08llx] illegal address", PC));
continue;
}
disasm->dump_pc = PC;
decoder->Decode(Memory.Read32(PC));
decoder->Decode(Memory.Read32(CPU.GetOffset() + PC));
if(IsBreakPoint(PC))
{

View File

@ -133,6 +133,16 @@ bool ELF32Loader::LoadPhdrData(u64 offset)
{
phdr_arr[i].Show();
if(phdr_arr[i].p_vaddr < min_addr)
{
min_addr = phdr_arr[i].p_vaddr;
}
if(phdr_arr[i].p_vaddr + phdr_arr[i].p_memsz > max_addr)
{
max_addr = phdr_arr[i].p_vaddr + phdr_arr[i].p_memsz;
}
if(phdr_arr[i].p_type == 0x00000001) //LOAD
{
if(phdr_arr[i].p_vaddr != phdr_arr[i].p_paddr)
@ -161,6 +171,7 @@ bool ELF32Loader::LoadShdrData(u64 offset)
for(u32 i=0; i<shdr_arr.GetCount(); ++i)
{
Elf32_Shdr& shdr = shdr_arr[i];
#ifdef LOADER_DEBUG
if(i < shdr_name_arr.GetCount()) ConLog.Write("Name: %s", shdr_name_arr[i]);
shdr.Show();
@ -168,6 +179,16 @@ bool ELF32Loader::LoadShdrData(u64 offset)
#endif
if((shdr.sh_flags & SHF_ALLOC) != SHF_ALLOC) continue;
if(shdr.sh_addr < min_addr)
{
min_addr = shdr.sh_addr;
}
if(shdr.sh_addr + shdr.sh_size > max_addr)
{
max_addr = shdr.sh_addr + shdr.sh_size;
}
//const s64 addr = shdr.sh_addr;
//const s64 size = shdr.sh_size;
//MemoryBlock* mem = nullptr;

View File

@ -207,6 +207,16 @@ bool ELF64Loader::LoadPhdrData(u64 offset)
{
phdr_arr[i].Show();
if(phdr_arr[i].p_vaddr < min_addr)
{
min_addr = phdr_arr[i].p_vaddr;
}
if(phdr_arr[i].p_vaddr + phdr_arr[i].p_memsz > max_addr)
{
max_addr = phdr_arr[i].p_vaddr + phdr_arr[i].p_memsz;
}
if(phdr_arr[i].p_vaddr != phdr_arr[i].p_paddr)
{
ConLog.Warning
@ -403,6 +413,16 @@ bool ELF64Loader::LoadShdrData(u64 offset)
{
Elf64_Shdr& shdr = shdr_arr[i];
if(shdr.sh_addr < min_addr)
{
min_addr = shdr.sh_addr;
}
if(shdr.sh_addr + shdr.sh_size > max_addr)
{
max_addr = shdr.sh_addr + shdr.sh_size;
}
if(i < shdr_name_arr.GetCount())
{
const wxString& name = shdr_name_arr[i];

View File

@ -144,11 +144,15 @@ class LoaderBase
{
protected:
u32 entry;
u32 min_addr;
u32 max_addr;
Elf_Machine machine;
LoaderBase()
: machine(MACHINE_Unknown)
, entry(0)
, min_addr(0)
, max_addr(0)
{
}
@ -157,6 +161,8 @@ public:
virtual bool LoadData(u64 offset = 0) { return false; }
Elf_Machine GetMachine() { return machine; }
u32 GetEntry() { return entry; }
u32 GetMinAddr() { return min_addr; }
u32 GetMaxAddr() { return min_addr; }
};
class Loader : public LoaderBase

View File

@ -224,6 +224,7 @@
<ClCompile Include="Emu\SysCalls\Callback.cpp" />
<ClCompile Include="Emu\SysCalls\FuncList.cpp" />
<ClCompile Include="Emu\SysCalls\lv2\SC_Condition.cpp" />
<ClCompile Include="Emu\SysCalls\lv2\SC_Event.cpp" />
<ClCompile Include="Emu\SysCalls\lv2\SC_FileSystem.cpp" />
<ClCompile Include="Emu\SysCalls\lv2\SC_GCM.cpp" />
<ClCompile Include="Emu\SysCalls\lv2\SC_Heap.cpp" />
@ -240,6 +241,7 @@
<ClCompile Include="Emu\SysCalls\lv2\SC_SysUtil_MsgDialog.cpp" />
<ClCompile Include="Emu\SysCalls\lv2\SC_Time.cpp" />
<ClCompile Include="Emu\SysCalls\lv2\SC_TTY.cpp" />
<ClCompile Include="Emu\SysCalls\Modules.cpp" />
<ClCompile Include="Emu\SysCalls\Modules\cellGcmSys.cpp" />
<ClCompile Include="Emu\SysCalls\Modules\sysPrxForUser.cpp" />
<ClCompile Include="Emu\SysCalls\Modules\sys_fs.cpp" />

View File

@ -250,6 +250,12 @@
<ClCompile Include="Emu\Cell\PPUProgramCompiler.cpp">
<Filter>Emu\CPU</Filter>
</ClCompile>
<ClCompile Include="Emu\SysCalls\lv2\SC_Event.cpp">
<Filter>Emu\SysCalls\lv2</Filter>
</ClCompile>
<ClCompile Include="Emu\SysCalls\Modules.cpp">
<Filter>Emu\SysCalls</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="rpcs3.rc" />