1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-22 10:42:36 +01:00

- Implemented MTCRF instruction.

- Implemented sys_spu_thread_set_argument syscall.
- Improved Debugger.
This commit is contained in:
DH 2013-07-08 16:24:46 +03:00
parent 6d7d3acb43
commit fb57bb9c4e
21 changed files with 456 additions and 276 deletions

View File

@ -11,7 +11,6 @@ PPCThread::PPCThread(PPCThreadType type)
: ThreadBase(true, "PPCThread") : ThreadBase(true, "PPCThread")
, m_type(type) , m_type(type)
, DisAsmFrame(NULL) , DisAsmFrame(NULL)
, m_arg(0)
, m_dec(NULL) , m_dec(NULL)
, stack_size(0) , stack_size(0)
, stack_addr(0) , stack_addr(0)
@ -43,6 +42,7 @@ void PPCThread::Reset()
m_sync_wait = 0; m_sync_wait = 0;
m_wait_thread_id = -1; m_wait_thread_id = -1;
memset(m_args, 0, sizeof(u64) * 4);
SetPc(0); SetPc(0);
cycle = 0; cycle = 0;
@ -88,8 +88,6 @@ void PPCThread::CloseStack()
void PPCThread::SetId(const u32 id) void PPCThread::SetId(const u32 id)
{ {
m_id = id; m_id = id;
ID& thread = Emu.GetIdManager().GetIDData(m_id);
thread.m_name = GetName();
} }
void PPCThread::SetName(const wxString& name) void PPCThread::SetName(const wxString& name)
@ -119,10 +117,20 @@ bool PPCThread::Sync()
int PPCThread::ThreadStatus() int PPCThread::ThreadStatus()
{ {
if(Emu.IsStopped()) return PPCThread_Stopped; if(Emu.IsStopped())
if(TestDestroy()) return PPCThread_Break; {
return PPCThread_Stopped;
}
if(TestDestroy())
{
return PPCThread_Break;
}
if(Emu.IsPaused() || Sync()) if(Emu.IsPaused() || Sync())
{
return PPCThread_Sleeping; return PPCThread_Sleeping;
}
return PPCThread_Running; return PPCThread_Running;
} }
@ -186,7 +194,7 @@ void PPCThread::SetError(const u32 error)
wxArrayString PPCThread::ErrorToString(const u32 error) wxArrayString PPCThread::ErrorToString(const u32 error)
{ {
wxArrayString earr; wxArrayString earr;
earr.Clear();
if(error == 0) return earr; if(error == 0) return earr;
earr.Add("Unknown error"); earr.Add("Unknown error");

View File

@ -27,12 +27,13 @@ protected:
wxWindow* DisAsmFrame; wxWindow* DisAsmFrame;
u32 m_id; u32 m_id;
PPCThreadType m_type; PPCThreadType m_type;
u64 m_arg; u64 m_args[4];
u64 m_prio; u64 m_prio;
bool m_joinable; bool m_joinable;
bool m_joining; bool m_joining;
Array<u64> argv_addr; Array<u64> argv_addr;
u64 m_offset; u64 m_offset;
u32 m_exit_status;
public: public:
u64 stack_size; u64 stack_size;
@ -47,14 +48,17 @@ public:
virtual u64 GetStackAddr() const { return stack_addr; } virtual u64 GetStackAddr() const { return stack_addr; }
virtual u64 GetStackSize() const { return stack_size; } virtual u64 GetStackSize() const { return stack_size; }
virtual u64 GetFreeStackSize() const=0; virtual u64 GetFreeStackSize() const=0;
void SetArg(const u64 arg) { m_arg = arg; } void SetArg(const uint pos, const u64 arg) { assert(pos < 4); m_args[pos] = arg; }
void SetId(const u32 id); void SetId(const u32 id);
void SetName(const wxString& name); void SetName(const wxString& name);
void SetPrio(const u64 prio) { m_prio = prio; } void SetPrio(const u64 prio) { m_prio = prio; }
void SetOffset(const u64 offset) { m_offset = offset; } void SetOffset(const u64 offset) { m_offset = offset; }
u64 GetOffset() { return m_offset; } void SetExitStatus(const u32 status) { m_exit_status = status; }
u64 GetOffset() const { return m_offset; }
u32 GetExitStatus() const { return m_exit_status; }
u64 GetPrio() const { return m_prio; } u64 GetPrio() const { return m_prio; }
wxString GetName() const { return m_name; } wxString GetName() const { return m_name; }
wxString GetFName() const wxString GetFName() const

View File

@ -274,9 +274,9 @@ private:
{ {
DisAsm_V2("vlogefp", vd, vb); DisAsm_V2("vlogefp", vd, vb);
} }
void VMADDFP(u32 vd, u32 va, u32 vb, u32 vc) void VMADDFP(u32 vd, u32 va, u32 vc, u32 vb)
{ {
DisAsm_V4("vmaddfp", vd, va, vb, vc); DisAsm_V4("vmaddfp", vd, va, vc, vb);
} }
void VMAXFP(u32 vd, u32 va, u32 vb) void VMAXFP(u32 vd, u32 va, u32 vb)
{ {
@ -1166,10 +1166,17 @@ private:
{ {
DisAsm_R3_OE_RC("adde", rd, ra, rb, oe, rc); DisAsm_R3_OE_RC("adde", rd, ra, rb, oe, rc);
} }
void MTOCRF(u32 crm, u32 rs) void MTOCRF(u32 l, u32 crm, u32 rs)
{
if(l)
{ {
DisAsm_INT1_R1("mtocrf", crm, rs); DisAsm_INT1_R1("mtocrf", crm, rs);
} }
else
{
DisAsm_INT1_R1("mtcrf", crm, rs);
}
}
void STDX(u32 rs, u32 ra, u32 rb) void STDX(u32 rs, u32 ra, u32 rb)
{ {
DisAsm_R3("stdx.", rs, ra, rb); DisAsm_R3("stdx.", rs, ra, rb);
@ -1284,10 +1291,6 @@ private:
{ {
DisAsm_V1_R2("lvxl", vd, ra, rb); DisAsm_V1_R2("lvxl", vd, ra, rb);
} }
void ABS(u32 rd, u32 ra, u32 oe, bool rc)
{
DisAsm_R2_OE_RC("abs", rd, ra, oe, rc);
}
void MFTB(u32 rd, u32 spr) void MFTB(u32 rd, u32 spr)
{ {
const u32 n = (spr >> 5) | ((spr & 0x1f) << 5); const u32 n = (spr >> 5) | ((spr & 0x1f) << 5);

View File

@ -125,8 +125,10 @@ namespace PPU_instr
*/ */
static CodeField<30> AA; static CodeField<30> AA;
static CodeFieldSignedOffset<6, 29, 2> LI(FIELD_BRANCH);
// //
static CodeFieldSigned<6, 31> LL(FIELD_BRANCH); static CodeFieldSignedOffset<6, 29, 2> LL(FIELD_BRANCH);
/* /*
Link bit. Link bit.
0 Does not update the link register (LR). 0 Does not update the link register (LR).
@ -177,36 +179,7 @@ namespace PPU_instr
static CodeFieldSigned<16, 31> D; static CodeFieldSigned<16, 31> D;
// //
struct : public CodeFieldSigned<16, 31> static CodeFieldSignedOffset<16, 29, 2> DS;
{
static __forceinline u32 decode(u32 data)
{
int res = sign<size>((data & mask) >> shift);
if(res < 0) return res - 1;
return res;
}
static __forceinline void encode(u32& data, u32 value)
{
if((s32)value < 0)
{
value++;
}
data &= ~mask;
data |= (value << shift) & mask;
}
virtual u32 operator ()(u32 data) const
{
return decode(data);
}
virtual void operator ()(u32& data, u32 value) const
{
return encode(data, value);
}
} static DS;
//This immediate field is used to specify a 16-bit signed integer //This immediate field is used to specify a 16-bit signed integer
static CodeFieldSigned<16, 31> simm16; static CodeFieldSigned<16, 31> simm16;
@ -269,7 +242,7 @@ namespace PPU_instr
bind_instr(main_list, ADDIS, RD, RA, simm16); bind_instr(main_list, ADDIS, RD, RA, simm16);
bind_instr(main_list, BC, BO, BI, BD, AA, LK); bind_instr(main_list, BC, BO, BI, BD, AA, LK);
bind_instr(main_list, SC, SYS); bind_instr(main_list, SC, SYS);
bind_instr(main_list, B, LL, AA, LK); bind_instr(main_list, B, LI, AA, LK);
bind_instr(main_list, RLWIMI, RA, RS, SH, MB, ME, RC); bind_instr(main_list, RLWIMI, RA, RS, SH, MB, ME, RC);
bind_instr(main_list, RLWINM, RA, RS, SH, MB, ME, RC); bind_instr(main_list, RLWINM, RA, RS, SH, MB, ME, RC);
bind_instr(main_list, RLWNM, RA, RS, RB, MB, ME, RC); bind_instr(main_list, RLWNM, RA, RS, RB, MB, ME, RC);
@ -302,7 +275,7 @@ namespace PPU_instr
bind_instr(main_list, STFD, FRS, RA, D); bind_instr(main_list, STFD, FRS, RA, D);
bind_instr(main_list, STFDU, FRS, RA, D); bind_instr(main_list, STFDU, FRS, RA, D);
bind_instr(g04_list, VMADDFP, VD, VA, VB, VC); bind_instr(g04_list, VMADDFP, VD, VA, VC, VB);
bind_instr(g04_list, VMHADDSHS, VD, VA, VB, VC); bind_instr(g04_list, VMHADDSHS, VD, VA, VB, VC);
bind_instr(g04_list, VMHRADDSHS, VD, VA, VB, VC); bind_instr(g04_list, VMHRADDSHS, VD, VA, VB, VC);
bind_instr(g04_list, VMLADDUHM, VD, VA, VB, VC); bind_instr(g04_list, VMLADDUHM, VD, VA, VB, VC);
@ -515,7 +488,7 @@ namespace PPU_instr
/*0x087*/bind_instr(g1f_list, STVEBX, VS, RA, RB); /*0x087*/bind_instr(g1f_list, STVEBX, VS, RA, RB);
/*0x088*/bind_instr(g1f_list, SUBFE, RD, RA, RB, OE, RC); /*0x088*/bind_instr(g1f_list, SUBFE, RD, RA, RB, OE, RC);
/*0x08a*/bind_instr(g1f_list, ADDE, RD, RA, RB, OE, RC); /*0x08a*/bind_instr(g1f_list, ADDE, RD, RA, RB, OE, RC);
/*0x090*/bind_instr(g1f_list, MTOCRF, CRM, RS); /*0x090*/bind_instr(g1f_list, MTOCRF, L_11, CRM, RS);
/*0x095*/bind_instr(g1f_list, STDX, RS, RA, RB); /*0x095*/bind_instr(g1f_list, STDX, RS, RA, RB);
/*0x096*/bind_instr(g1f_list, STWCX_, RS, RA, RB); /*0x096*/bind_instr(g1f_list, STWCX_, RS, RA, RB);
/*0x097*/bind_instr(g1f_list, STWX, RS, RA, RB); /*0x097*/bind_instr(g1f_list, STWX, RS, RA, RB);
@ -541,7 +514,6 @@ namespace PPU_instr
/*0x156*/bind_instr(g1f_list, DST, RA, RB, STRM, L_6); /*0x156*/bind_instr(g1f_list, DST, RA, RB, STRM, L_6);
/*0x157*/bind_instr(g1f_list, LHAX, RD, RA, RB); /*0x157*/bind_instr(g1f_list, LHAX, RD, RA, RB);
/*0x167*/bind_instr(g1f_list, LVXL, VD, RA, RB); /*0x167*/bind_instr(g1f_list, LVXL, VD, RA, RB);
/*0x168*/bind_instr(g1f_list, ABS, RD, RA, OE, RC);
/*0x173*/bind_instr(g1f_list, MFTB, RD, SPR); /*0x173*/bind_instr(g1f_list, MFTB, RD, SPR);
/*0x176*/bind_instr(g1f_list, DSTST, RA, RB, STRM, L_6); /*0x176*/bind_instr(g1f_list, DSTST, RA, RB, STRM, L_6);
/*0x177*/bind_instr(g1f_list, LHAUX, RD, RA, RB); /*0x177*/bind_instr(g1f_list, LHAUX, RD, RA, RB);
@ -554,7 +526,7 @@ namespace PPU_instr
/*0x1d3*/bind_instr(g1f_list, MTSPR, SPR, RS); /*0x1d3*/bind_instr(g1f_list, MTSPR, SPR, RS);
/*0x1d6*///DCBI /*0x1d6*///DCBI
/*0x1dc*/bind_instr(g1f_list, NAND, RA, RS, RB, RC); /*0x1dc*/bind_instr(g1f_list, NAND, RA, RS, RB, RC);
/*0x1e7*/bind_instr(g1f_list, STVXL, RS, RA, RB); /*0x1e7*/bind_instr(g1f_list, STVXL, VS, RA, RB);
/*0x1e9*/bind_instr(g1f_list, DIVD, RD, RA, RB, OE, RC); /*0x1e9*/bind_instr(g1f_list, DIVD, RD, RA, RB, OE, RC);
/*0x1eb*/bind_instr(g1f_list, DIVW, RD, RA, RB, OE, RC); /*0x1eb*/bind_instr(g1f_list, DIVW, RD, RA, RB, OE, RC);
/*0x207*/bind_instr(g1f_list, LVLX, VD, RA, RB); /*0x207*/bind_instr(g1f_list, LVLX, VD, RA, RB);
@ -568,9 +540,9 @@ namespace PPU_instr
/*0x257*/bind_instr(g1f_list, LFDX, FRD, RA, RB); /*0x257*/bind_instr(g1f_list, LFDX, FRD, RA, RB);
/*0x277*/bind_instr(g1f_list, LFDUX, FRD, RA, RB); /*0x277*/bind_instr(g1f_list, LFDUX, FRD, RA, RB);
/*0x287*/bind_instr(g1f_list, STVLX, VS, RA, RB); /*0x287*/bind_instr(g1f_list, STVLX, VS, RA, RB);
/*0x297*/bind_instr(g1f_list, STFSX, RS, RA, RB); /*0x297*/bind_instr(g1f_list, STFSX, FRS, RA, RB);
/*0x2a7*/bind_instr(g1f_list, STVRX, VS, RA, RB); /*0x2a7*/bind_instr(g1f_list, STVRX, VS, RA, RB);
/*0x2d7*/bind_instr(g1f_list, STFDX, RS, RA, RB); /*0x2d7*/bind_instr(g1f_list, STFDX, FRS, RA, RB);
/*0x307*/bind_instr(g1f_list, LVLXL, VD, RA, RB); /*0x307*/bind_instr(g1f_list, LVLXL, VD, RA, RB);
/*0x316*/bind_instr(g1f_list, LHBRX, RD, RA, RB); /*0x316*/bind_instr(g1f_list, LHBRX, RD, RA, RB);
/*0x318*/bind_instr(g1f_list, SRAW, RA, RS, RB, RC); /*0x318*/bind_instr(g1f_list, SRAW, RA, RS, RB, RC);
@ -588,7 +560,7 @@ namespace PPU_instr
/*0x3d6*///ICBI /*0x3d6*///ICBI
/*0x3f6*/bind_instr(g1f_list, DCBZ, RA, RB); /*0x3f6*/bind_instr(g1f_list, DCBZ, RA, RB);
bind_instr(g3a_list, LD, RD, RA, D); bind_instr(g3a_list, LD, RD, RA, DS);
bind_instr(g3a_list, LDU, RD, RA, DS); bind_instr(g3a_list, LDU, RD, RA, DS);
bind_instr(g3b_list, FDIVS, FRD, FRA, FRB, RC); bind_instr(g3b_list, FDIVS, FRD, FRA, FRB, RC);
@ -602,7 +574,7 @@ namespace PPU_instr
bind_instr(g3b_list, FNMSUBS, FRD, FRA, FRC, FRB, RC); bind_instr(g3b_list, FNMSUBS, FRD, FRA, FRC, FRB, RC);
bind_instr(g3b_list, FNMADDS, FRD, FRA, FRC, FRB, RC); bind_instr(g3b_list, FNMADDS, FRD, FRA, FRC, FRB, RC);
bind_instr(g3e_list, STD, RS, RA, D); bind_instr(g3e_list, STD, RS, RA, DS);
bind_instr(g3e_list, STDU, RS, RA, DS); bind_instr(g3e_list, STDU, RS, RA, DS);
bind_instr(g3f_list, FSEL, FRD, FRA, FRC, FRB, RC); bind_instr(g3f_list, FSEL, FRD, FRA, FRC, FRB, RC);

View File

@ -97,18 +97,12 @@ private:
const u8 bo1 = (bo & 0x08) ? 1 : 0; const u8 bo1 = (bo & 0x08) ? 1 : 0;
const u8 bo2 = (bo & 0x04) ? 1 : 0; const u8 bo2 = (bo & 0x04) ? 1 : 0;
const u8 bo3 = (bo & 0x02) ? 1 : 0; const u8 bo3 = (bo & 0x02) ? 1 : 0;
const u8 bo4 = (bo & 0x01) ? 1 : 0;
if(!bo2) --CPU.CTR; if(!bo2) --CPU.CTR;
const u8 ctr_ok = bo2 | ((CPU.CTR != 0) ^ bo3); const u8 ctr_ok = bo2 | ((CPU.CTR != 0) ^ bo3);
const u8 cond_ok = bo0 | (CPU.IsCR(bi) ^ (~bo1 & 0x1)); const u8 cond_ok = bo0 | (CPU.IsCR(bi) ^ (~bo1 & 0x1));
//if(bo1) CPU.SetCR(bi, bo4 ? 1 : 0);
//if(bo1) return !bo4;
//ConLog.Write("bo0: 0x%x, bo1: 0x%x, bo2: 0x%x, bo3: 0x%x", bo0, bo1, bo2, bo3);
return ctr_ok && cond_ok; return ctr_ok && cond_ok;
} }
@ -805,7 +799,7 @@ private:
CPU.VPR[vd]._f[w] = log(CPU.VPR[vb]._f[w]) / log(2.0f); CPU.VPR[vd]._f[w] = log(CPU.VPR[vb]._f[w]) / log(2.0f);
} }
} }
void VMADDFP(u32 vd, u32 va, u32 vb, u32 vc) void VMADDFP(u32 vd, u32 va, u32 vc, u32 vb)
{ {
for (uint w = 0; w < 4; w++) for (uint w = 0; w < 4; w++)
{ {
@ -2549,7 +2543,9 @@ private:
if(rc) CPU.UpdateCR0<s64>(CPU.GPR[rd]); if(rc) CPU.UpdateCR0<s64>(CPU.GPR[rd]);
if(oe) UNK("addeo"); if(oe) UNK("addeo");
} }
void MTOCRF(u32 crm, u32 rs) void MTOCRF(u32 l, u32 crm, u32 rs)
{
if(l)
{ {
u32 n = 0, count = 0; u32 n = 0, count = 0;
for(u32 i=0; i<8; ++i) for(u32 i=0; i<8; ++i)
@ -2566,7 +2562,19 @@ private:
//CR[4*n : 4*n+3] = RS[32+4*n : 32+4*n+3]; //CR[4*n : 4*n+3] = RS[32+4*n : 32+4*n+3];
CPU.SetCR(n, (CPU.GPR[rs] >> (4*n)) & 0xf); CPU.SetCR(n, (CPU.GPR[rs] >> (4*n)) & 0xf);
} }
else CPU.CR.CR = 0; else
CPU.CR.CR = 0;
}
else
{
for(u32 i=0; i<8; ++i)
{
if(crm & (1 << i))
{
CPU.SetCR(i, CPU.GPR[rs] & (0xf << i));
}
}
}
} }
void STDX(u32 rs, u32 ra, u32 rb) void STDX(u32 rs, u32 ra, u32 rb)
{ {
@ -2584,6 +2592,7 @@ private:
{ {
Memory.Write32(addr, CPU.GPR[rs]); Memory.Write32(addr, CPU.GPR[rs]);
CPU.SetCR_EQ(0, true); CPU.SetCR_EQ(0, true);
CPU.reserve = false;
} }
else else
{ {
@ -2732,12 +2741,6 @@ private:
{ {
CPU.VPR[vd]._u128 = Memory.Read128((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~0xfULL); CPU.VPR[vd]._u128 = Memory.Read128((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~0xfULL);
} }
void ABS(u32 rd, u32 ra, u32 oe, bool rc)
{
CPU.GPR[rd] = abs((s64)CPU.GPR[ra]);
if(oe) UNK("abso");
if(rc) CPU.UpdateCR0<s64>(CPU.GPR[rd]);
}
void MFTB(u32 rd, u32 spr) void MFTB(u32 rd, u32 spr)
{ {
const u32 n = (spr >> 5) | ((spr & 0x1f) << 5); const u32 n = (spr >> 5) | ((spr & 0x1f) << 5);
@ -3175,8 +3178,41 @@ private:
} }
void FDIVS(u32 frd, u32 fra, u32 frb, bool rc) void FDIVS(u32 frd, u32 fra, u32 frb, bool rc)
{ {
if(CPU.FPR[frb] == 0.0) CPU.SetFPSCRException(FPSCR_ZX); if(FPRdouble::IsNaN(CPU.FPR[fra]))
CPU.FPR[frd] = static_cast<float>(CPU.FPR[fra] / CPU.FPR[frb]); {
CPU.FPR[frd] = CPU.FPR[fra];
}
else if(FPRdouble::IsNaN(CPU.FPR[frb]))
{
CPU.FPR[frd] = CPU.FPR[frb];
}
else
{
if(CPU.FPR[frb] == 0.0)
{
if(CPU.FPR[fra] == 0.0)
{
CPU.FPSCR.VXZDZ = true;
CPU.FPR[frd] = FPR_NAN;
}
else
{
CPU.FPR[frd] = (float)(CPU.FPR[fra] / CPU.FPR[frb]);
}
CPU.FPSCR.ZX = true;
}
else if(FPRdouble::IsINF(CPU.FPR[fra]) && FPRdouble::IsINF(CPU.FPR[frb]))
{
CPU.FPSCR.VXIDI = true;
CPU.FPR[frd] = FPR_NAN;
}
else
{
CPU.FPR[frd] = (float)(CPU.FPR[fra] / CPU.FPR[frb]);
}
}
CPU.FPSCR.FPRF = PPCdouble(CPU.FPR[frd]).GetType(); CPU.FPSCR.FPRF = PPCdouble(CPU.FPR[frd]).GetType();
if(rc) UNK("fdivs.");//CPU.UpdateCR1(CPU.FPR[frd]); if(rc) UNK("fdivs.");//CPU.UpdateCR1(CPU.FPR[frd]);
} }
@ -3194,13 +3230,17 @@ private:
} }
void FSQRTS(u32 frd, u32 frb, bool rc) void FSQRTS(u32 frd, u32 frb, bool rc)
{ {
CPU.FPR[frd] = static_cast<float>(sqrt((float)CPU.FPR[frb])); CPU.FPR[frd] = static_cast<float>(sqrt(CPU.FPR[frb]));
CPU.FPSCR.FPRF = PPCdouble(CPU.FPR[frd]).GetType();
if(rc) UNK("fsqrts.");//CPU.UpdateCR1(CPU.FPR[frd]); if(rc) UNK("fsqrts.");//CPU.UpdateCR1(CPU.FPR[frd]);
} }
void FRES(u32 frd, u32 frb, bool rc) void FRES(u32 frd, u32 frb, bool rc)
{ {
if(CPU.FPR[frb] == 0.0) CPU.SetFPSCRException(FPSCR_ZX); if(CPU.FPR[frb] == 0.0) CPU.SetFPSCRException(FPSCR_ZX);
CPU.FPR[frd] = static_cast<float>(1.0f/CPU.FPR[frb]); CPU.FPR[frd] = static_cast<float>(1.0f/CPU.FPR[frb]);
CPU.FPSCR.FPRF = PPCdouble(CPU.FPR[frd]).GetType();
CPU.FPSCR.FI = 0;
CPU.FPSCR.FR = 0;
if(rc) UNK("fres.");//CPU.UpdateCR1(CPU.FPR[frd]); if(rc) UNK("fres.");//CPU.UpdateCR1(CPU.FPR[frd]);
} }
void FMULS(u32 frd, u32 fra, u32 frc, bool rc) void FMULS(u32 frd, u32 fra, u32 frc, bool rc)

View File

@ -318,7 +318,6 @@ namespace PPU_opcodes
DST = 0x156, //Data Stream Touch DST = 0x156, //Data Stream Touch
LHAX = 0x157, LHAX = 0x157,
LVXL = 0x167, //Load Vector Indexed Last LVXL = 0x167, //Load Vector Indexed Last
ABS = 0x168,
MFTB = 0x173, MFTB = 0x173,
DSTST = 0x176, //Data Stream Touch for Store DSTST = 0x176, //Data Stream Touch for Store
LHAUX = 0x177, LHAUX = 0x177,
@ -436,7 +435,7 @@ public:
static u64 branchTarget(const u64 pc, const u64 imm) static u64 branchTarget(const u64 pc, const u64 imm)
{ {
return pc + (imm & ~0x3); return pc + (imm & ~0x3ULL);
} }
virtual void NULL_OP() = 0; virtual void NULL_OP() = 0;
@ -498,7 +497,7 @@ public:
virtual void VCTUXS(u32 vd, u32 uimm5, u32 vb) = 0; virtual void VCTUXS(u32 vd, u32 uimm5, u32 vb) = 0;
virtual void VEXPTEFP(u32 vd, u32 vb) = 0; virtual void VEXPTEFP(u32 vd, u32 vb) = 0;
virtual void VLOGEFP(u32 vd, u32 vb) = 0; virtual void VLOGEFP(u32 vd, u32 vb) = 0;
virtual void VMADDFP(u32 vd, u32 va, u32 vb, u32 vc) = 0; virtual void VMADDFP(u32 vd, u32 va, u32 vc, u32 vb) = 0;
virtual void VMAXFP(u32 vd, u32 va, u32 vb) = 0; virtual void VMAXFP(u32 vd, u32 va, u32 vb) = 0;
virtual void VMAXSB(u32 vd, u32 va, u32 vb) = 0; virtual void VMAXSB(u32 vd, u32 va, u32 vb) = 0;
virtual void VMAXSH(u32 vd, u32 va, u32 vb) = 0; virtual void VMAXSH(u32 vd, u32 va, u32 vb) = 0;
@ -675,7 +674,7 @@ public:
virtual void STVEBX(u32 vs, u32 ra, u32 rb) = 0; virtual void STVEBX(u32 vs, u32 ra, u32 rb) = 0;
virtual void SUBFE(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) = 0; virtual void SUBFE(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) = 0;
virtual void ADDE(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) = 0; virtual void ADDE(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) = 0;
virtual void MTOCRF(u32 crm, u32 rs) = 0; virtual void MTOCRF(u32 l, u32 crm, u32 rs) = 0;
virtual void STDX(u32 rs, u32 ra, u32 rb) = 0; virtual void STDX(u32 rs, u32 ra, u32 rb) = 0;
virtual void STWCX_(u32 rs, u32 ra, u32 rb) = 0; virtual void STWCX_(u32 rs, u32 ra, u32 rb) = 0;
virtual void STWX(u32 rs, u32 ra, u32 rb) = 0; virtual void STWX(u32 rs, u32 ra, u32 rb) = 0;
@ -701,7 +700,6 @@ public:
virtual void DST(u32 ra, u32 rb, u32 strm, u32 t) = 0; virtual void DST(u32 ra, u32 rb, u32 strm, u32 t) = 0;
virtual void LHAX(u32 rd, u32 ra, u32 rb) = 0; virtual void LHAX(u32 rd, u32 ra, u32 rb) = 0;
virtual void LVXL(u32 vd, u32 ra, u32 rb) = 0; virtual void LVXL(u32 vd, u32 ra, u32 rb) = 0;
virtual void ABS(u32 rd, u32 ra, u32 oe, bool rc) = 0;
virtual void MFTB(u32 rd, u32 spr) = 0; virtual void MFTB(u32 rd, u32 spr) = 0;
virtual void DSTST(u32 ra, u32 rb, u32 strm, u32 t) = 0; virtual void DSTST(u32 ra, u32 rb, u32 strm, u32 t) = 0;
virtual void LHAUX(u32 rd, u32 ra, u32 rb) = 0; virtual void LHAUX(u32 rd, u32 ra, u32 rb) = 0;

View File

@ -68,19 +68,6 @@ void PPUThread::InitRegs()
SetPc(pc); SetPc(pc);
u64 argc = m_arg;
u64 argv = 0;
if(argv_addr.GetCount())
{
argc = argv_addr.GetCount();
stack_point -= 0xc + 4 * argc;
argv = stack_point;
mem64_t argv_list(argv);
for(int i=0; i<argc; ++i) argv_list += argv_addr[i];
}
const s32 thread_num = Emu.GetCPU().GetThreadNumById(!IsSPU(), GetId()); const s32 thread_num = Emu.GetCPU().GetThreadNumById(!IsSPU(), GetId());
if(thread_num < 0) if(thread_num < 0)
@ -106,22 +93,41 @@ void PPUThread::InitRegs()
GPR[1] = stack_point; GPR[1] = stack_point;
GPR[2] = rtoc; GPR[2] = rtoc;
if(argc) for(int i=4; i<32; ++i)
{ {
if(i != 6)
GPR[i] = (i+1) * 0x10000;
}
if(argv_addr.GetCount())
{
u64 argc = argv_addr.GetCount();
stack_point -= 0xc + 4 * argc;
u64 argv = stack_point;
mem64_t argv_list(argv);
for(int i=0; i<argc; ++i) argv_list += argv_addr[i];
GPR[3] = argc; GPR[3] = argc;
GPR[4] = argv; GPR[4] = argv;
GPR[5] = argv ? argv + 0xc + 4 * argc : 0; //unk GPR[5] = argv ? argv + 0xc + 4 * argc : 0; //unk
} }
else else
{ {
GPR[3] = m_arg; GPR[3] = m_args[0];
GPR[4] = m_args[1];
GPR[5] = m_args[2];
GPR[6] = m_args[3];
} }
u32 prx_mem = Memory.PRXMem.Alloc(0x10000);
Memory.Write64(prx_mem, 0xDEADBEEFABADCAFE);
GPR[0] = pc; GPR[0] = pc;
GPR[8] = entry; GPR[8] = entry;
GPR[11] = 0x80; GPR[11] = 0x80;
GPR[12] = Emu.GetMallocPageSize(); GPR[12] = Emu.GetMallocPageSize();
GPR[13] = Memory.PRXMem.Alloc(0x10000) + 0x7060 - 8; GPR[13] = prx_mem + 0x7060;
GPR[28] = GPR[4]; GPR[28] = GPR[4];
GPR[29] = GPR[3]; GPR[29] = GPR[3];
GPR[31] = GPR[5]; GPR[31] = GPR[5];
@ -172,15 +178,30 @@ bool dump_enable = false;
void PPUThread::DoCode(const s32 code) void PPUThread::DoCode(const s32 code)
{ {
static bool is_last_enabled = false;
if(dump_enable) if(dump_enable)
{ {
static wxFile f("dump.txt", wxFile::write); static wxFile f("dump.txt", wxFile::write);
static PPU_DisAsm disasm(*this, DumpMode); static PPU_DisAsm disasm(*this, DumpMode);
static PPU_Decoder decoder(disasm); static PPU_Decoder decoder(disasm);
if(!is_last_enabled)
{
f.Write(RegsToString() + "\n");
}
disasm.dump_pc = PC; disasm.dump_pc = PC;
decoder.Decode(code); decoder.Decode(code);
f.Write(disasm.last_opcode); f.Write(disasm.last_opcode);
is_last_enabled = true;
} }
else
{
is_last_enabled = false;
}
if(++cycle > 220) if(++cycle > 220)
{ {
@ -193,7 +214,7 @@ void PPUThread::DoCode(const s32 code)
bool FPRdouble::IsINF(PPCdouble d) bool FPRdouble::IsINF(PPCdouble d)
{ {
return wxFinite(d) ? 1 : 0; return d.GetType() == FPR_INF;
} }
bool FPRdouble::IsNaN(PPCdouble d) bool FPRdouble::IsNaN(PPCdouble d)

View File

@ -18,6 +18,18 @@ enum
CR_SO = 0x1, CR_SO = 0x1,
}; };
enum
{
PPU_THREAD_STATUS_IDLE = (1 << 0),
PPU_THREAD_STATUS_RUNNABLE = (1 << 1),
PPU_THREAD_STATUS_ONPROC = (1 << 2),
PPU_THREAD_STATUS_SLEEP = (1 << 3),
PPU_THREAD_STATUS_STOP = (1 << 4),
PPU_THREAD_STATUS_ZOMBIE = (1 << 5),
PPU_THREAD_STATUS_DELETED = (1 << 6),
PPU_THREAD_STATUS_UNKNOWN = (1 << 7),
};
enum FPSCR_EXP enum FPSCR_EXP
{ {
FPSCR_FX = 0x80000000, FPSCR_FX = 0x80000000,
@ -302,6 +314,9 @@ enum FPRType
FPR_ND = 0x18, FPR_ND = 0x18,
}; };
static const u64 FPR_NAN_I = 0x7FF8000000000000ULL;
static const double& FPR_NAN = (double&)FPR_NAN_I;
struct PPCdouble struct PPCdouble
{ {
union union

View File

@ -30,7 +30,11 @@ void SPUThread::DoReset()
void SPUThread::InitRegs() void SPUThread::InitRegs()
{ {
GPR[1]._u64[0] = stack_point; //GPR[1]._u64[0] = stack_point;
GPR[3]._u64[1] = m_args[0];
GPR[4]._u64[1] = m_args[1];
GPR[5]._u64[1] = m_args[2];
GPR[6]._u64[1] = m_args[3];
} }
u64 SPUThread::GetFreeStackSize() const u64 SPUThread::GetFreeStackSize() const

View File

@ -461,7 +461,7 @@ void GLGSRender::InitVertexData()
void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_t& args, const u32 count) void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_t& args, const u32 count)
{ {
#if CMD_DEBUG #if CMD_DEBUG
wxString debug = getMethodName(cmd); wxString debug = GetMethodName(cmd);
debug += "("; debug += "(";
for(u32 i=0; i<count; ++i) debug += (i ? ", " : "") + wxString::Format("0x%x", args[i]); for(u32 i=0; i<count; ++i) debug += (i ? ", " : "") + wxString::Format("0x%x", args[i]);
debug += ")"; debug += ")";
@ -757,7 +757,7 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_t& args, const u32 c
m_indexed_array.m_data.InsertRoomEnd(4); m_indexed_array.m_data.InsertRoomEnd(4);
index = Memory.Read32(m_indexed_array.m_addr + i * 4); index = Memory.Read32(m_indexed_array.m_addr + i * 4);
*(u32*)&m_indexed_array.m_data[pos] = index; *(u32*)&m_indexed_array.m_data[pos] = index;
ConLog.Warning("index 4: %d", *(u32*)&m_indexed_array.m_data[pos]); //ConLog.Warning("index 4: %d", *(u32*)&m_indexed_array.m_data[pos]);
} }
break; break;
@ -766,8 +766,8 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_t& args, const u32 c
int pos = m_indexed_array.m_data.GetCount(); int pos = m_indexed_array.m_data.GetCount();
m_indexed_array.m_data.InsertRoomEnd(2); m_indexed_array.m_data.InsertRoomEnd(2);
index = Memory.Read16(m_indexed_array.m_addr + i * 2); index = Memory.Read16(m_indexed_array.m_addr + i * 2);
ConLog.Warning("index 2: %d", index); //ConLog.Warning("index 2: %d", index);
*(u32*)&m_indexed_array.m_data[pos] = index; *(u16*)&m_indexed_array.m_data[pos] = index;
} }
break; break;
} }
@ -1294,13 +1294,13 @@ void GLGSRender::ExecCMD()
case 0: case 0:
glDrawElements(m_draw_mode, m_indexed_array.m_count, GL_UNSIGNED_INT, nullptr); glDrawElements(m_draw_mode, m_indexed_array.m_count, GL_UNSIGNED_INT, nullptr);
checkForGlError("glDrawElements #4"); checkForGlError("glDrawElements #4");
for(uint i=0; i<m_indexed_array.m_count; i+=4) log.Write(wxString::Format("index 4: %d\n", (u32&)m_indexed_array.m_data[i])); //for(uint i=0; i<m_indexed_array.m_count; i+=4) log.Write(wxString::Format("index 4: %d\n", (u32&)m_indexed_array.m_data[i]));
break; break;
case 1: case 1:
glDrawElements(m_draw_mode, m_indexed_array.m_count, GL_UNSIGNED_SHORT, nullptr); glDrawElements(m_draw_mode, m_indexed_array.m_count, GL_UNSIGNED_SHORT, nullptr);
checkForGlError("glDrawElements #2"); checkForGlError("glDrawElements #2");
for(uint i=0; i<m_indexed_array.m_count; i+=2) log.Write(wxString::Format("index 2: %d\n", (u16&)m_indexed_array.m_data[i])); //for(uint i=0; i<m_indexed_array.m_count; i+=2) log.Write(wxString::Format("index 2: %d\n", (u16&)m_indexed_array.m_data[i]));
break; break;
default: default:
@ -1310,7 +1310,7 @@ void GLGSRender::ExecCMD()
DisableVertexData(); DisableVertexData();
m_indexed_array.Reset(); m_indexed_array.Reset();
Emu.Pause(); //Emu.Pause();
} }
if(m_draw_array_count) if(m_draw_array_count)

View File

@ -39,7 +39,7 @@ static func_caller* sc_table[1024] =
null_func, bind_func(sys_spu_image_open), 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 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 null_func, null_func, null_func, null_func, bind_func(sys_spu_initialize), //169
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 bind_func(sys_spu_thread_group_create), bind_func(sys_spu_thread_set_argument), 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, //179
null_func, bind_func(sys_spu_thread_write_ls), bind_func(sys_spu_thread_read_ls), 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, //189
@ -260,6 +260,7 @@ void SysCalls::DoSyscall(u32 code)
case 999: case 999:
dump_enable = !dump_enable; dump_enable = !dump_enable;
Emu.Pause();
ConLog.Warning("Dump %s", dump_enable ? "enabled" : "disabled"); ConLog.Warning("Dump %s", dump_enable ? "enabled" : "disabled");
return; return;

View File

@ -251,6 +251,7 @@ extern int sys_heap_malloc(const u32 heap_addr, const u32 size);
//sys_spu //sys_spu
extern int sys_spu_image_open(u32 img_addr, u32 path_addr); 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_initialize(u32 thread_addr, u32 group, u32 spu_num, u32 img_addr, u32 attr_addr, u32 arg_addr);
extern int sys_spu_thread_set_argument(u32 id, u32 arg_addr);
extern int sys_spu_thread_group_start(u32 id); 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_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_spu_thread_create(u64 thread_id_addr, u64 entry_addr, u64 arg, int prio, u32 stacksize, u64 flags, u64 threadname_addr);

View File

@ -7,6 +7,14 @@ extern Module cellGcmSys;
CellGcmConfig current_config; CellGcmConfig current_config;
CellGcmContextData current_context; CellGcmContextData current_context;
gcmInfo gcm_info; gcmInfo gcm_info;
struct gcm_offset
{
u16 ea;
u16 offset;
};
u32 map_offset_addr = 0;
u32 map_offset_pos = 0;
int cellGcmMapMainMemory(u32 address, u32 size, u32 offset_addr) int cellGcmMapMainMemory(u32 address, u32 size, u32 offset_addr)
{ {
@ -24,6 +32,8 @@ int cellGcmInit(u32 context_addr, u32 cmdSize, u32 ioSize, u32 ioAddress)
const u32 local_size = 0xf900000; //TODO const u32 local_size = 0xf900000; //TODO
const u32 local_addr = Memory.RSXFBMem.GetStartAddr(); const u32 local_addr = Memory.RSXFBMem.GetStartAddr();
map_offset_addr = 0;
map_offset_pos = 0;
current_config.ioSize = re32(ioSize); current_config.ioSize = re32(ioSize);
current_config.ioAddress = re32(ioAddress); current_config.ioAddress = re32(ioAddress);
current_config.localSize = re32(local_size); current_config.localSize = re32(local_size);
@ -91,10 +101,19 @@ int cellGcmAddressToOffset(u32 address, u32 offset_addr)
cellGcmSys.Log("cellGcmAddressToOffset(address=0x%x,offset_addr=0x%x)", address, offset_addr); cellGcmSys.Log("cellGcmAddressToOffset(address=0x%x,offset_addr=0x%x)", address, offset_addr);
if(!Memory.IsGoodAddr(offset_addr, sizeof(u32))) return CELL_EFAULT; if(!Memory.IsGoodAddr(offset_addr, sizeof(u32))) return CELL_EFAULT;
Memory.Write32(offset_addr, if(!map_offset_addr)
Memory.RSXFBMem.IsInMyRange(address) {
? address - Memory.RSXFBMem.GetStartAddr() map_offset_addr = Memory.Alloc(4*50, 4);
: address - re(current_context.begin)); }
u32 sa = Memory.RSXFBMem.IsInMyRange(address) ? Memory.RSXFBMem.GetStartAddr() : re(current_context.begin);
u16 ea = (sa + address - sa) >> 16;
u32 offset = address - sa;
//Memory.Write16(map_offset_addr + map_offset_pos + 0, ea);
//Memory.Write16(map_offset_addr + map_offset_pos + 2, offset);
//map_offset_pos += 4;
Memory.Write32(offset_addr, offset);
return CELL_OK; return CELL_OK;
} }

View File

@ -129,7 +129,7 @@ int sys_ppu_thread_create(u32 thread_id_addr, u32 entry, u32 arg, int prio, u32
Memory.Write32(thread_id_addr, new_thread.GetId()); Memory.Write32(thread_id_addr, new_thread.GetId());
new_thread.SetEntry(entry); new_thread.SetEntry(entry);
new_thread.SetArg(arg); new_thread.SetArg(0, arg);
new_thread.SetPrio(prio); new_thread.SetPrio(prio);
new_thread.stack_size = stacksize; new_thread.stack_size = stacksize;
//new_thread.flags = flags; //new_thread.flags = flags;

View File

@ -36,14 +36,16 @@ struct sys_spu_image
int nsegs; int nsegs;
}; };
static const u32 g_spu_group_thr_count = 255;
struct SpuGroupInfo struct SpuGroupInfo
{ {
PPCThread* threads[10]; PPCThread* threads[g_spu_group_thr_count];
sys_spu_thread_group_attribute& attr; sys_spu_thread_group_attribute& attr;
SpuGroupInfo(sys_spu_thread_group_attribute& attr) : attr(attr) SpuGroupInfo(sys_spu_thread_group_attribute& attr) : attr(attr)
{ {
memset(threads, 0, sizeof(PPCThread*) * 10); memset(threads, 0, sizeof(PPCThread*) * g_spu_group_thr_count);
} }
}; };
@ -74,7 +76,7 @@ int sys_spu_image_open(u32 img_addr, u32 path_addr)
if(!stream || !stream->IsOpened()) if(!stream || !stream->IsOpened())
{ {
sc_spu.Error("'%s' not found!", path); sc_spu.Error("sys_spu_image_open error: '%s' not found!", path);
delete stream; delete stream;
return CELL_ENOENT; return CELL_ENOENT;
@ -83,7 +85,7 @@ int sys_spu_image_open(u32 img_addr, u32 path_addr)
u32 entry = LoadSpuImage(*stream); u32 entry = LoadSpuImage(*stream);
delete stream; delete stream;
sys_spu_image& ret = (sys_spu_image&)Memory[img_addr]; auto& ret = (sys_spu_image&)Memory[img_addr];
re(ret.type, 1); re(ret.type, 1);
re(ret.entry_point, entry); re(ret.entry_point, entry);
re(ret.segs_addr, 0x0); re(ret.segs_addr, 0x0);
@ -103,6 +105,8 @@ int sys_spu_thread_initialize(u32 thread_addr, u32 group, u32 spu_num, u32 img_a
return CELL_ESRCH; return CELL_ESRCH;
} }
SpuGroupInfo& group_info = *(SpuGroupInfo*)Emu.GetIdManager().GetIDData(group).m_data;
if( if(
!Memory.IsGoodAddr(img_addr, sizeof(sys_spu_image)) || !Memory.IsGoodAddr(img_addr, sizeof(sys_spu_image)) ||
!Memory.IsGoodAddr(attr_addr, sizeof(sys_spu_thread_attribute)) || !Memory.IsGoodAddr(attr_addr, sizeof(sys_spu_thread_attribute)) ||
@ -111,15 +115,25 @@ int sys_spu_thread_initialize(u32 thread_addr, u32 group, u32 spu_num, u32 img_a
return CELL_EFAULT; return CELL_EFAULT;
} }
sys_spu_image& img = (sys_spu_image&)Memory[img_addr]; auto& img = (sys_spu_image&)Memory[img_addr];
sys_spu_thread_attribute& attr = (sys_spu_thread_attribute&)Memory[attr_addr]; auto& attr = (sys_spu_thread_attribute&)Memory[attr_addr];
sys_spu_thread_argument& arg = (sys_spu_thread_argument&)Memory[arg_addr]; auto& arg = (sys_spu_thread_argument&)Memory[arg_addr];
if(!Memory.IsGoodAddr(re(attr.name_addr), re(attr.name_len))) if(!Memory.IsGoodAddr(re(attr.name_addr), re(attr.name_len)))
{ {
return CELL_EFAULT; return CELL_EFAULT;
} }
if(spu_num >= g_spu_group_thr_count)
{
return CELL_EINVAL;
}
if(group_info.threads[spu_num])
{
return CELL_EBUSY;
}
u32 entry = re(img.entry_point); u32 entry = re(img.entry_point);
wxString name = Memory.ReadString(re(attr.name_addr), re(attr.name_len)); wxString name = Memory.ReadString(re(attr.name_addr), re(attr.name_len));
u64 a1 = re(arg.arg1); u64 a1 = re(arg.arg1);
@ -140,21 +154,43 @@ int sys_spu_thread_initialize(u32 thread_addr, u32 group, u32 spu_num, u32 img_a
new_thread.SetOffset(g_spu_offset); new_thread.SetOffset(g_spu_offset);
new_thread.SetEntry(entry - g_spu_offset); new_thread.SetEntry(entry - g_spu_offset);
new_thread.SetName(name); new_thread.SetName(name);
SPU_GPR_hdr* GPR = ((SPUThread&)new_thread).GPR;
new_thread.Run(); new_thread.Run();
new_thread.Pause(); new_thread.Pause();
GPR[3]._u64[1] = a1; new_thread.SetArg(0, a1);
GPR[4]._u64[1] = a2; new_thread.SetArg(1, a2);
GPR[5]._u64[1] = a3; new_thread.SetArg(2, a3);
GPR[6]._u64[1] = a4; new_thread.SetArg(3, a4);
ID& id = Emu.GetIdManager().GetIDData(group);
SpuGroupInfo& group_info = *(SpuGroupInfo*)id.m_data;
group_info.threads[spu_num] = &new_thread; group_info.threads[spu_num] = &new_thread;
return CELL_OK; return CELL_OK;
} }
//166
int sys_spu_thread_set_argument(u32 id, u32 arg_addr)
{
sc_spu.Warning("sys_spu_thread_set_argument(id=0x%x, arg_addr=0x%x)", id, arg_addr);
PPCThread* thr = Emu.GetCPU().GetThread(id);
if(!thr || !thr->IsSPU())
{
return CELL_ESRCH;
}
if(!Memory.IsGoodAddr(arg_addr, sizeof(sys_spu_thread_argument)))
{
return CELL_EFAULT;
}
auto& arg = (sys_spu_thread_argument&)Memory[arg_addr];
thr->SetArg(0, re(arg.arg1));
thr->SetArg(1, re(arg.arg2));
thr->SetArg(2, re(arg.arg3));
thr->SetArg(3, re(arg.arg4));
return CELL_OK;
}
//173 //173
int sys_spu_thread_group_start(u32 id) int sys_spu_thread_group_start(u32 id)
{ {
@ -169,7 +205,7 @@ int sys_spu_thread_group_start(u32 id)
SpuGroupInfo& group_info = *(SpuGroupInfo*)id_data.m_data; SpuGroupInfo& group_info = *(SpuGroupInfo*)id_data.m_data;
Emu.Pause(); Emu.Pause();
for(int i=0; i<10; i++) for(int i=0; i<g_spu_group_thr_count; i++)
{ {
if(group_info.threads[i]) if(group_info.threads[i])
{ {
@ -211,6 +247,21 @@ int sys_spu_thread_create(u64 thread_id_addr, u64 entry_addr, u64 arg,
return CELL_OK; return CELL_OK;
} }
int sys_spu_thread_connect_event(u32 id, u32 eq, u32 et, u8 spup)
{
if(!Emu.GetIdManager().CheckID(id))
{
return CELL_ESRCH;
}
if(spup > 63)
{
return CELL_EINVAL;
}
return CELL_OK;
}
//160 //160
int sys_raw_spu_create(u32 id_addr, u32 attr_addr) int sys_raw_spu_create(u32 id_addr, u32 attr_addr)
{ {
@ -329,7 +380,7 @@ int sys_spu_thread_group_connect_event_all_threads(u32 id, u32 eq, u64 req, u32
SpuGroupInfo* group = (SpuGroupInfo*)Emu.GetIdManager().GetIDData(id).m_data; SpuGroupInfo* group = (SpuGroupInfo*)Emu.GetIdManager().GetIDData(id).m_data;
EventQueue* equeue = (EventQueue*)Emu.GetIdManager().GetIDData(eq).m_data; EventQueue* equeue = (EventQueue*)Emu.GetIdManager().GetIDData(eq).m_data;
for(int i=0; i<10; ++i) for(int i=0; i<g_spu_group_thr_count; ++i)
{ {
if(group->threads[i]) if(group->threads[i])
{ {

View File

@ -85,8 +85,6 @@ void Emulator::Load()
Memory.Init(); Memory.Init();
GetInfo().Reset(); GetInfo().Reset();
Memory.Write64(Memory.PRXMem.Alloc(8), 0xDEADBEEFABADCAFE);
bool is_error; bool is_error;
vfsLocalFile f(m_path); vfsLocalFile f(m_path);
Loader l(f); Loader l(f);
@ -127,9 +125,6 @@ void Emulator::Load()
else else
{ {
thread.SetEntry(l.GetEntry()); thread.SetEntry(l.GetEntry());
}
thread.SetArg(thread.GetId());
Memory.StackMem.Alloc(0x1000); Memory.StackMem.Alloc(0x1000);
thread.InitStack(); thread.InitStack();
thread.AddArgv(m_path); thread.AddArgv(m_path);
@ -149,6 +144,7 @@ void Emulator::Load()
ppu_thr_exit_data += ADDI(11, 0, 41); ppu_thr_exit_data += ADDI(11, 0, 41);
ppu_thr_exit_data += SC(2); ppu_thr_exit_data += SC(2);
ppu_thr_exit_data += BCLR(0x10 | 0x04, 0, 0, 0); ppu_thr_exit_data += BCLR(0x10 | 0x04, 0, 0, 0);
}
thread.Run(); thread.Run();

View File

@ -99,16 +99,9 @@ DebuggerPanel::DebuggerPanel(wxWindow* parent) : wxPanel(parent, wxID_ANY, wxDef
{ {
m_aui_mgr.SetManagedWindow(this); m_aui_mgr.SetManagedWindow(this);
m_nb = new wxAuiNotebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
wxAUI_NB_TOP | wxAUI_NB_TAB_SPLIT |
wxAUI_NB_TAB_EXTERNAL_MOVE | wxAUI_NB_SCROLL_BUTTONS |
wxAUI_NB_WINDOWLIST_BUTTON | wxAUI_NB_TAB_MOVE | wxNO_BORDER);
m_aui_mgr.AddPane(new DbgEmuPanel(this), wxAuiPaneInfo().Top()); m_aui_mgr.AddPane(new DbgEmuPanel(this), wxAuiPaneInfo().Top());
m_aui_mgr.AddPane(m_nb, wxAuiPaneInfo().Center().CaptionVisible(false).CloseButton().MaximizeButton()); m_aui_mgr.AddPane(new InterpreterDisAsmFrame(this), wxAuiPaneInfo().Center().CaptionVisible(false).CloseButton().MaximizeButton());
m_aui_mgr.Update(); m_aui_mgr.Update();
m_app_connector.Connect(wxEVT_DBG_COMMAND, wxCommandEventHandler(DebuggerPanel::HandleCommand), (wxObject*)0, this);
} }
DebuggerPanel::~DebuggerPanel() DebuggerPanel::~DebuggerPanel()
@ -119,30 +112,3 @@ DebuggerPanel::~DebuggerPanel()
void DebuggerPanel::UpdateUI() void DebuggerPanel::UpdateUI()
{ {
} }
void DebuggerPanel::HandleCommand(wxCommandEvent& event)
{
PPCThread* thr = (PPCThread*)event.GetClientData();
switch(event.GetId())
{
case DID_CREATE_THREAD:
m_nb->AddPage(new InterpreterDisAsmFrame(m_nb, thr), thr->GetFName());
break;
case DID_REMOVE_THREAD:
for(uint i=0; i<m_nb->GetPageCount(); ++i)
{
InterpreterDisAsmFrame* page = (InterpreterDisAsmFrame*)m_nb->GetPage(i);
if(page->CPU.GetId() == thr->GetId())
{
m_nb->DeletePage(i);
break;
}
}
break;
}
event.Skip();
}

View File

@ -5,13 +5,10 @@
class DebuggerPanel : public wxPanel class DebuggerPanel : public wxPanel
{ {
wxAuiManager m_aui_mgr; wxAuiManager m_aui_mgr;
wxAuiNotebook* m_nb;
AppConnector m_app_connector;
public: public:
DebuggerPanel(wxWindow* parent); DebuggerPanel(wxWindow* parent);
~DebuggerPanel(); ~DebuggerPanel();
void UpdateUI(); void UpdateUI();
void HandleCommand(wxCommandEvent& event);
}; };

View File

@ -3,35 +3,25 @@
//static const int show_lines = 30; //static const int show_lines = 30;
u32 InterpreterDisAsmFrame::CentrePc(const u32 pc) const u64 InterpreterDisAsmFrame::CentrePc(const u64 pc) const
{ {
return pc - ((m_item_count / 2) * 4); return pc - ((m_item_count / 2) * 4);
} }
InterpreterDisAsmFrame::InterpreterDisAsmFrame(wxWindow* parent, PPCThread* cpu) InterpreterDisAsmFrame::InterpreterDisAsmFrame(wxWindow* parent)
: wxPanel(parent, wxID_ANY, wxDefaultPosition, wxSize(500, 700), wxTAB_TRAVERSAL) : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxSize(500, 700), wxTAB_TRAVERSAL)
, ThreadBase(false, "DisAsmFrame Thread") , ThreadBase(false, "DisAsmFrame Thread")
, CPU(*cpu)
, PC(0) , PC(0)
, CPU(nullptr)
, m_item_count(30) , m_item_count(30)
, decoder(nullptr)
, disasm(nullptr)
{ {
if(CPU.IsSPU())
{
SPU_DisAsm& dis_asm = *new SPU_DisAsm(CPU, InterpreterMode);
decoder = new SPU_Decoder(dis_asm);
disasm = &dis_asm;
}
else
{
PPU_DisAsm& dis_asm = *new PPU_DisAsm(CPU, InterpreterMode);
decoder = new PPU_Decoder(dis_asm);
disasm = &dis_asm;
}
wxBoxSizer& s_p_main = *new wxBoxSizer(wxVERTICAL); wxBoxSizer& s_p_main = *new wxBoxSizer(wxVERTICAL);
wxBoxSizer& s_b_main = *new wxBoxSizer(wxHORIZONTAL); wxBoxSizer& s_b_main = *new wxBoxSizer(wxHORIZONTAL);
m_list = new wxListView(this); m_list = new wxListView(this);
m_choice_units = new wxChoice(this, wxID_ANY);
wxButton& b_go_to_addr = *new wxButton(this, wxID_ANY, "Go To Address"); wxButton& b_go_to_addr = *new wxButton(this, wxID_ANY, "Go To Address");
wxButton& b_go_to_pc = *new wxButton(this, wxID_ANY, "Go To PC"); wxButton& b_go_to_pc = *new wxButton(this, wxID_ANY, "Go To PC");
@ -45,6 +35,7 @@ InterpreterDisAsmFrame::InterpreterDisAsmFrame(wxWindow* parent, PPCThread* cpu)
s_b_main.Add(m_btn_step, wxSizerFlags().Border(wxALL, 5)); s_b_main.Add(m_btn_step, wxSizerFlags().Border(wxALL, 5));
s_b_main.Add(m_btn_run, wxSizerFlags().Border(wxALL, 5)); s_b_main.Add(m_btn_run, wxSizerFlags().Border(wxALL, 5));
s_b_main.Add(m_btn_pause, wxSizerFlags().Border(wxALL, 5)); s_b_main.Add(m_btn_pause, wxSizerFlags().Border(wxALL, 5));
s_b_main.Add(m_choice_units, wxSizerFlags().Border(wxALL, 5));
m_regs = new wxTextCtrl(this, wxID_ANY, wxEmptyString, m_regs = new wxTextCtrl(this, wxID_ANY, wxEmptyString,
wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_DONTWRAP|wxNO_BORDER|wxTE_RICH2); wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_DONTWRAP|wxNO_BORDER|wxTE_RICH2);
@ -77,12 +68,14 @@ InterpreterDisAsmFrame::InterpreterDisAsmFrame(wxWindow* parent, PPCThread* cpu)
Connect(m_btn_run->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(InterpreterDisAsmFrame::DoRun)); Connect(m_btn_run->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(InterpreterDisAsmFrame::DoRun));
Connect(m_btn_pause->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(InterpreterDisAsmFrame::DoPause)); Connect(m_btn_pause->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(InterpreterDisAsmFrame::DoPause));
Connect(m_list->GetId(), wxEVT_COMMAND_LIST_ITEM_ACTIVATED, wxListEventHandler(InterpreterDisAsmFrame::DClick)); Connect(m_list->GetId(), wxEVT_COMMAND_LIST_ITEM_ACTIVATED, wxListEventHandler(InterpreterDisAsmFrame::DClick));
Connect(m_choice_units->GetId(),wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler(InterpreterDisAsmFrame::OnSelectUnit));
Connect(wxEVT_SIZE, wxSizeEventHandler(InterpreterDisAsmFrame::OnResize)); Connect(wxEVT_SIZE, wxSizeEventHandler(InterpreterDisAsmFrame::OnResize));
m_app_connector.Connect(m_list->GetId(), wxEVT_MOUSEWHEEL, wxMouseEventHandler(InterpreterDisAsmFrame::MouseWheel), (wxObject*)0, this); m_app_connector.Connect(m_list->GetId(), wxEVT_MOUSEWHEEL, wxMouseEventHandler(InterpreterDisAsmFrame::MouseWheel), (wxObject*)0, this);
m_app_connector.Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(InterpreterDisAsmFrame::OnKeyDown), (wxObject*)0, this); m_app_connector.Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(InterpreterDisAsmFrame::OnKeyDown), (wxObject*)0, this);
m_app_connector.Connect(wxEVT_DBG_COMMAND, wxCommandEventHandler(InterpreterDisAsmFrame::HandleCommand), (wxObject*)0, this); m_app_connector.Connect(wxEVT_DBG_COMMAND, wxCommandEventHandler(InterpreterDisAsmFrame::HandleCommand), (wxObject*)0, this);
WriteRegs();
ShowAddr(CentrePc(PC));
UpdateUnitList();
} }
InterpreterDisAsmFrame::~InterpreterDisAsmFrame() InterpreterDisAsmFrame::~InterpreterDisAsmFrame()
@ -90,6 +83,48 @@ InterpreterDisAsmFrame::~InterpreterDisAsmFrame()
ThreadBase::Stop(); ThreadBase::Stop();
} }
void InterpreterDisAsmFrame::UpdateUnitList()
{
m_choice_units->Freeze();
m_choice_units->Clear();
auto& thrs = Emu.GetCPU().GetThreads();
for(uint i=0; i<thrs.GetCount(); ++i)
{
m_choice_units->Append(thrs[i].GetFName(), &thrs[i]);
}
m_choice_units->Thaw();
}
void InterpreterDisAsmFrame::OnSelectUnit(wxCommandEvent& event)
{
CPU = (PPCThread*)event.GetClientData();
delete decoder;
//delete disasm;
decoder = nullptr;
disasm = nullptr;
if(CPU)
{
if(CPU->IsSPU())
{
SPU_DisAsm& dis_asm = *new SPU_DisAsm(*CPU, InterpreterMode);
decoder = new SPU_Decoder(dis_asm);
disasm = &dis_asm;
}
else
{
PPU_DisAsm& dis_asm = *new PPU_DisAsm(*CPU, InterpreterMode);
decoder = new PPU_Decoder(dis_asm);
disasm = &dis_asm;
}
}
DoUpdate();
}
void InterpreterDisAsmFrame::OnKeyDown(wxKeyEvent& event) void InterpreterDisAsmFrame::OnKeyDown(wxKeyEvent& event)
{ {
if(wxGetActiveWindow() != wxGetTopLevelParent(this)) if(wxGetActiveWindow() != wxGetTopLevelParent(this))
@ -164,17 +199,27 @@ void InterpreterDisAsmFrame::ShowAddr(const u64 addr)
{ {
PC = addr; PC = addr;
m_list->Freeze(); m_list->Freeze();
disasm->offset = CPU.GetOffset();
if(!CPU)
{
for(uint i=0; i<m_item_count; ++i, PC += 4) for(uint i=0; i<m_item_count; ++i, PC += 4)
{ {
if(!Memory.IsGoodAddr(CPU.GetOffset() + PC, 4)) m_list->SetItem(i, 0, wxString::Format("[%08llx] illegal address", PC));
}
}
else
{
disasm->offset = CPU->GetOffset();
for(uint i=0; i<m_item_count; ++i, PC += 4)
{
if(!Memory.IsGoodAddr(CPU->GetOffset() + PC, 4))
{ {
m_list->SetItem(i, 0, wxString::Format("[%08llx] illegal address", PC)); m_list->SetItem(i, 0, wxString::Format("[%08llx] illegal address", PC));
continue; continue;
} }
disasm->dump_pc = PC; disasm->dump_pc = PC;
decoder->Decode(Memory.Read32(CPU.GetOffset() + PC)); decoder->Decode(Memory.Read32(CPU->GetOffset() + PC));
if(IsBreakPoint(PC)) if(IsBreakPoint(PC))
{ {
@ -187,7 +232,7 @@ void InterpreterDisAsmFrame::ShowAddr(const u64 addr)
wxColour colour; wxColour colour;
if((!CPU.IsRunned() || !Emu.IsRunned()) && PC == CPU.PC) if((!CPU->IsRunned() || !Emu.IsRunned()) && PC == CPU->PC)
{ {
colour = wxColour("Green"); colour = wxColour("Green");
} }
@ -207,6 +252,7 @@ void InterpreterDisAsmFrame::ShowAddr(const u64 addr)
m_list->SetItemBackgroundColour( i, colour ); m_list->SetItemBackgroundColour( i, colour );
} }
}
while(remove_markedPC.GetCount()) while(remove_markedPC.GetCount())
{ {
@ -234,7 +280,7 @@ void InterpreterDisAsmFrame::WriteRegs()
{ {
m_regs->Freeze(); m_regs->Freeze();
m_regs->Clear(); m_regs->Clear();
m_regs->WriteText(CPU.RegsToString()); if(CPU) m_regs->WriteText(CPU->RegsToString());
m_regs->Thaw(); m_regs->Thaw();
} }
@ -253,7 +299,7 @@ void InterpreterDisAsmFrame::HandleCommand(wxCommandEvent& event)
break; break;
} }
} }
else if(thr->GetId() == CPU.GetId()) else if(CPU && thr->GetId() == CPU->GetId())
{ {
switch(event.GetId()) switch(event.GetId())
{ {
@ -266,7 +312,6 @@ void InterpreterDisAsmFrame::HandleCommand(wxCommandEvent& event)
DoUpdate(); DoUpdate();
break; break;
case DID_START_THREAD: case DID_START_THREAD:
case DID_EXEC_THREAD: case DID_EXEC_THREAD:
case DID_RESUME_THREAD: case DID_RESUME_THREAD:
@ -285,6 +330,36 @@ void InterpreterDisAsmFrame::HandleCommand(wxCommandEvent& event)
m_btn_run->Disable(); m_btn_run->Disable();
m_btn_step->Disable(); m_btn_step->Disable();
m_btn_pause->Disable(); m_btn_pause->Disable();
if(event.GetId() == DID_REMOVE_THREAD)
{
m_choice_units->SetSelection(-1);
wxCommandEvent event;
event.SetInt(-1);
//event.SetClientData(nullptr);
OnSelectUnit(event);
UpdateUnitList();
}
DoUpdate();
break;
}
}
else
{
switch(event.GetId())
{
case DID_CREATE_THREAD:
UpdateUnitList();
if(m_choice_units->GetSelection() == -1)
{
m_choice_units->SetSelection(0);
wxCommandEvent event;
event.SetInt(0);
event.SetClientData(&Emu.GetCPU().GetThreads()[0]);
OnSelectUnit(event);
DoUpdate();
}
break; break;
} }
} }
@ -313,11 +388,11 @@ void InterpreterDisAsmFrame::Show_Val(wxCommandEvent& WXUNUSED(event))
diag->SetSizerAndFit( s_panel ); diag->SetSizerAndFit( s_panel );
p_pc->SetLabel(wxString::Format("%llx", CPU.PC)); if(CPU) p_pc->SetLabel(wxString::Format("%llx", CPU->PC));
if(diag->ShowModal() == wxID_OK) if(diag->ShowModal() == wxID_OK)
{ {
u64 pc = CPU.PC; u64 pc = CPU ? CPU->PC : 0x0;
sscanf(p_pc->GetLabel(), "%llx", &pc); sscanf(p_pc->GetLabel(), "%llx", &pc);
remove_markedPC.AddCpy(Emu.GetMarkedPoints().AddCpy(pc)); remove_markedPC.AddCpy(Emu.GetMarkedPoints().AddCpy(pc));
ShowAddr(CentrePc(pc)); ShowAddr(CentrePc(pc));
@ -326,17 +401,19 @@ void InterpreterDisAsmFrame::Show_Val(wxCommandEvent& WXUNUSED(event))
void InterpreterDisAsmFrame::Show_PC(wxCommandEvent& WXUNUSED(event)) void InterpreterDisAsmFrame::Show_PC(wxCommandEvent& WXUNUSED(event))
{ {
ShowAddr(CentrePc(CPU.PC)); if(CPU) ShowAddr(CentrePc(CPU->PC));
} }
extern bool dump_enable; extern bool dump_enable;
void InterpreterDisAsmFrame::DoRun(wxCommandEvent& WXUNUSED(event)) void InterpreterDisAsmFrame::DoRun(wxCommandEvent& WXUNUSED(event))
{ {
if(CPU.IsPaused()) CPU.Resume(); if(!CPU) return;
if(CPU->IsPaused()) CPU->Resume();
if(!Emu.IsPaused()) if(!Emu.IsPaused())
{ {
CPU.Exec(); CPU->Exec();
} }
//ThreadBase::Start(); //ThreadBase::Start();
@ -344,7 +421,7 @@ void InterpreterDisAsmFrame::DoRun(wxCommandEvent& WXUNUSED(event))
void InterpreterDisAsmFrame::DoPause(wxCommandEvent& WXUNUSED(event)) void InterpreterDisAsmFrame::DoPause(wxCommandEvent& WXUNUSED(event))
{ {
CPU.Pause(); if(CPU) CPU->Pause();
} }
void InterpreterDisAsmFrame::DoStep(wxCommandEvent& WXUNUSED(event)) void InterpreterDisAsmFrame::DoStep(wxCommandEvent& WXUNUSED(event))
@ -418,7 +495,8 @@ bool InterpreterDisAsmFrame::RemoveBreakPoint(u64 pc)
void InterpreterDisAsmFrame::Task() void InterpreterDisAsmFrame::Task()
{ {
wxGetApp().SendDbgCommand(DID_RESUME_THREAD, &CPU); if(!CPU) return;
wxGetApp().SendDbgCommand(DID_RESUME_THREAD, CPU);
bool dump_status = dump_enable; bool dump_status = dump_enable;
@ -428,9 +506,9 @@ void InterpreterDisAsmFrame::Task()
{ {
do do
{ {
CPU.ExecOnce(); CPU->ExecOnce();
} }
while(CPU.IsRunned() && Emu.IsRunned() && !TestDestroy() && !IsBreakPoint(CPU.PC) && dump_status == dump_enable); while(CPU->IsRunned() && Emu.IsRunned() && !TestDestroy() && !IsBreakPoint(CPU->PC) && dump_status == dump_enable);
} }
catch(const wxString& e) catch(const wxString& e)
{ {
@ -443,5 +521,5 @@ void InterpreterDisAsmFrame::Task()
//CPU.FreeTls(); //CPU.FreeTls();
wxGetApp().SendDbgCommand(DID_PAUSE_THREAD, &CPU); wxGetApp().SendDbgCommand(DID_PAUSE_THREAD, CPU);
} }

View File

@ -20,16 +20,19 @@ class InterpreterDisAsmFrame
wxButton* m_btn_pause; wxButton* m_btn_pause;
AppConnector m_app_connector; AppConnector m_app_connector;
u32 m_item_count; u32 m_item_count;
wxChoice* m_choice_units;
public: public:
PPCThread& CPU; PPCThread* CPU;
public: public:
InterpreterDisAsmFrame(wxWindow* parent, PPCThread* cpu); InterpreterDisAsmFrame(wxWindow* parent);
~InterpreterDisAsmFrame(); ~InterpreterDisAsmFrame();
u32 CentrePc(const u32 pc) const; void UpdateUnitList();
u64 CentrePc(const u64 pc) const;
void OnSelectUnit(wxCommandEvent& event);
void OnKeyDown(wxKeyEvent& event); void OnKeyDown(wxKeyEvent& event);
void OnResize(wxSizeEvent& event); void OnResize(wxSizeEvent& event);
void DoUpdate(); void DoUpdate();

View File

@ -30,13 +30,16 @@ bool SELFLoader::LoadData(u64 offset)
if( !l.LoadEhdrInfo(self_hdr.se_elfoff) || if( !l.LoadEhdrInfo(self_hdr.se_elfoff) ||
!l.LoadPhdrInfo(self_hdr.se_phdroff) || !l.LoadPhdrInfo(self_hdr.se_phdroff) ||
!l.LoadShdrInfo(self_hdr.se_shdroff) || !l.LoadShdrInfo(self_hdr.se_shdroff) ||
!l.LoadData(offset) ) !l.LoadData(self_hdr.se_appinfooff) )
{ {
ConLog.Error("Broken SELF file."); ConLog.Error("Broken SELF file.");
return false; return false;
} }
machine = l.GetMachine();
entry = l.GetEntry();
return true; return true;
ConLog.Error("Boot SELF not supported yet!"); ConLog.Error("Boot SELF not supported yet!");