This commit is contained in:
elisha464 2014-01-18 23:36:42 +02:00
commit 4e4dd43646
36 changed files with 1375 additions and 447 deletions

View File

@ -21,6 +21,15 @@ enum
MFC_MASK_CMD = 0xffff,
};
// Atomic Status Update
enum
{
MFC_PUTLLC_SUCCESS = 0,
MFC_PUTLLC_FAILURE = 1, //reservation was lost
MFC_PUTLLUC_SUCCESS = 2,
MFC_GETLLAR_SUCCESS = 4,
};
enum
{
MFC_SPU_TO_PPU_MAILBOX_STATUS_MASK = 0x000000FF,

View File

@ -2,6 +2,9 @@
#include "PPCThread.h"
#include "Emu/event.h"
#include "MFC.h"
#include <mutex>
extern std::mutex g_SyncMutex; //can provide compatability for CellSyncMutex through SPU<>PPU and SPU<>SPU
static const char* spu_reg_name[128] =
{
@ -293,7 +296,7 @@ public:
};
volatile u64 m_indval;
};
wxCriticalSection m_lock;
std::mutex m_lock;
public:
@ -311,7 +314,7 @@ public:
{
if (max_count > 1 || x86)
{
wxCriticalSectionLocker lock(m_lock);
std::lock_guard<std::mutex> lock(m_lock);
if(!m_index)
{
return false;
@ -322,7 +325,7 @@ public:
}
else
{ //lock-free
if(!m_index)
if ((m_indval & 0xffffffff) == 0)
return false;
else
{
@ -337,7 +340,7 @@ public:
{
if (max_count > 1 || x86)
{
wxCriticalSectionLocker lock(m_lock);
std::lock_guard<std::mutex> lock(m_lock);
if(m_index >= max_count)
{
return false;
@ -347,11 +350,12 @@ public:
}
else
{ //lock-free
if(m_index)
if (m_indval & 0xffffffff)
return false;
else
{
m_indval = ((u64)value << 32) | 1;
const u64 new_value = ((u64)value << 32) | 1;
m_indval = new_value;
return true;
}
}
@ -361,7 +365,7 @@ public:
{
if (max_count > 1 || x86)
{
wxCriticalSectionLocker lock(m_lock);
std::lock_guard<std::mutex> lock(m_lock);
if(m_index >= max_count)
m_value[max_count-1] = value; //last message is overwritten
else
@ -369,7 +373,8 @@ public:
}
else
{ //lock-free
m_indval = ((u64)value << 32) | 1;
const u64 new_value = ((u64)value << 32) | 1;
m_indval = new_value;
}
}
@ -377,7 +382,7 @@ public:
{
if (max_count > 1 || x86)
{
wxCriticalSectionLocker lock(m_lock);
std::lock_guard<std::mutex> lock(m_lock);
if(m_index >= max_count)
m_value[max_count-1] |= value; //last message is logically ORed
else
@ -397,7 +402,7 @@ public:
{
if (max_count > 1 || x86)
{
wxCriticalSectionLocker lock(m_lock);
std::lock_guard<std::mutex> lock(m_lock);
if(!m_index)
res = 0; //result is undefined
else
@ -422,7 +427,7 @@ public:
{
if (max_count > 1 || x86)
{
wxCriticalSectionLocker lock(m_lock);
std::lock_guard<std::mutex> lock(m_lock);
return m_index;
}
else
@ -435,7 +440,7 @@ public:
{
if (max_count > 1 || x86)
{
wxCriticalSectionLocker lock(m_lock);
std::lock_guard<std::mutex> lock(m_lock);
return max_count - m_index;
}
else
@ -470,6 +475,7 @@ public:
Channel<1> QueryType;
Channel<1> QueryMask;
Channel<1> TagStatus;
Channel<1> AtomicStat;
} Prxy;
struct
@ -519,6 +525,29 @@ public:
}
break;
case MFC_GETLLAR_CMD:
case MFC_PUTLLC_CMD:
case MFC_PUTLLUC_CMD:
{
if (op == MFC_GETLLAR_CMD)
{
g_SyncMutex.lock();
}
ConLog.Warning("DMA %s: lsa=0x%x, ea = 0x%llx, (tag) = 0x%x, (size) = 0x%x, cmd = 0x%x",
op == MFC_GETLLAR_CMD ? "GETLLAR" : op == MFC_PUTLLC_CMD ? "PUTLLC" : "PUTLLUC",
lsa, ea, tag, size, cmd);
dmac.ProcessCmd(op == MFC_GETLLAR_CMD ? MFC_GET_CMD : MFC_PUT_CMD, tag, lsa, ea, 128);
Prxy.AtomicStat.PushUncond(op == MFC_GETLLAR_CMD ? MFC_GETLLAR_SUCCESS : op == MFC_PUTLLC_CMD ? MFC_PUTLLC_SUCCESS : MFC_PUTLLUC_SUCCESS);
if (op == MFC_PUTLLC_CMD || op == MFC_PUTLLUC_CMD)
{
g_SyncMutex.unlock();
}
}
break;
default:
ConLog.Error("Unknown MFC cmd. (opcode=0x%x, cmd=0x%x, lsa = 0x%x, ea = 0x%llx, tag = 0x%x, size = 0x%x)",
op, cmd, lsa, ea, tag, size);
@ -549,6 +578,9 @@ public:
case SPU_RdSigNotify2:
return SPU.SNR[1].GetCount();
case MFC_RdAtomicStat:
return Prxy.AtomicStat.GetCount();
default:
ConLog.Error("%s error: unknown/illegal channel (%d [%s]).", __FUNCTION__, ch, spu_ch_name[ch]);
break;
@ -641,6 +673,10 @@ public:
//ConLog.Warning("%s: 0x%x = %s", __FUNCTION__, v, spu_ch_name[ch]);
break;
case MFC_RdAtomicStat:
while (!Prxy.AtomicStat.Pop(v) && !Emu.IsStopped()) Sleep(1);
break;
default:
ConLog.Error("%s error: unknown/illegal channel (%d [%s]).", __FUNCTION__, ch, spu_ch_name[ch]);
break;

View File

@ -20,7 +20,11 @@ struct VFSManagerEntry
char* mount;
vfsDeviceType device;
VFSManagerEntry() : device(vfsDevice_LocalFile)
VFSManagerEntry()
: device(vfsDevice_LocalFile)
, device_path("")
, path("")
, mount("")
{
}
};

View File

@ -151,7 +151,7 @@ wxString GLVertexDecompilerThread::GetSRC(const u32 n, bool isSca)
return ret;
}
void GLVertexDecompilerThread::AddCode(bool is_sca, wxString code, bool src_mask)
void GLVertexDecompilerThread::AddCode(bool is_sca, wxString code, bool src_mask, bool set_dst)
{
if(d0.cond == 0) return;
enum
@ -179,7 +179,7 @@ void GLVertexDecompilerThread::AddCode(bool is_sca, wxString code, bool src_mask
}
//ConLog.Error("cond! %d (%d %s %d %d)", d0.cond, d0.dst_tmp, cond, d1.input_src, d1.const_src);
cond = wxString::Format("if(tmp%d.x %s 0) ", d0.dst_tmp, cond.mb_str());
cond = wxString::Format("if(rc %s 0) ", cond.mb_str());
}
wxString value = src_mask ? code + GetMask(is_sca) : code;
@ -189,40 +189,100 @@ void GLVertexDecompilerThread::AddCode(bool is_sca, wxString code, bool src_mask
value = "clamp(" + value + ", 0.0, 1.0)";
}
wxString dest;
if(d3.dst == 5 || d3.dst == 6)
if(set_dst)
{
int num = d3.dst == 5 ? 0 : 3;
if(d3.vec_writemask_x)
wxString dest;
if(d0.cond_update_enable_0)
{
ConLog.Error("Bad clip mask.");
dest = m_parr.AddParam(PARAM_NONE, "float", "rc");
}
else if(d3.dst == 5 || d3.dst == 6)
{
int num = d3.dst == 5 ? 0 : 3;
if(d3.vec_writemask_x)
{
ConLog.Error("Bad clip mask.");
}
//if(d3.vec_writemask_y) num += 0;
if(d3.vec_writemask_z) num += 1;
else if(d3.vec_writemask_w) num += 2;
dest = wxString::Format(GetDST(is_sca), num);
}
else
{
dest = GetDST(is_sca) + GetMask(is_sca);
}
//if(d3.vec_writemask_y) num += 0;
if(d3.vec_writemask_z) num += 1;
else if(d3.vec_writemask_w) num += 2;
dest = wxString::Format(GetDST(is_sca), num);
code = cond + dest + " = " + value;
}
else
{
dest = GetDST(is_sca) + GetMask(is_sca);
code = cond + value;
}
code = cond + dest + " = " + value;
main += "\t" + code + ";\n";
m_body.Add(code + wxString::Format(";//%d %d %d %d", d0.cond_reg_sel_1, d0.cond_test_enable, d0.cond_update_enable_0, d0.cond_update_enable_1));
}
void GLVertexDecompilerThread::AddVecCode(const wxString& code, bool src_mask)
wxString GLVertexDecompilerThread::GetFunc()
{
AddCode(false, code, src_mask);
u32 offset = (d2.iaddrh << 3) | d3.iaddrl;
wxString name = wxString::Format("func%u", offset);
for(uint i=0; i<m_funcs.GetCount(); ++i)
{
if(m_funcs[i].name.Cmp(name) == 0)
return name + "()";
}
uint idx = m_funcs.Add(new FuncInfo());
m_funcs[idx].offset = offset;
m_funcs[idx].name = name;
return name + "()";
}
void GLVertexDecompilerThread::AddScaCode(const wxString& code)
void GLVertexDecompilerThread::AddVecCode(const wxString& code, bool src_mask, bool set_dst)
{
AddCode(true, code, false);
AddCode(false, code, src_mask, set_dst);
}
void GLVertexDecompilerThread::AddScaCode(const wxString& code, bool set_dst)
{
AddCode(true, code, false, set_dst);
}
wxString GLVertexDecompilerThread::BuildFuncBody(const FuncInfo& func)
{
wxString result;
for(uint i=func.offset; i<m_body.GetCount(); ++i)
{
if(i != func.offset)
{
uint call_func = -1;
for(uint j=0; j<m_funcs.GetCount(); ++j)
{
if(m_funcs[j].offset == i)
{
call_func = j;
break;
}
}
if(call_func != -1)
{
result += '\t' + m_funcs[call_func].name + "();\n";
break;
}
}
result += '\t' + m_body[i] + '\n';
}
return result;
}
wxString GLVertexDecompilerThread::BuildCode()
@ -233,14 +293,31 @@ wxString GLVertexDecompilerThread::BuildCode()
{
p += m_parr.params[i].Format();
}
wxString fp = wxEmptyString;
for(int i=m_funcs.GetCount() - 1; i>=0; --i)
{
fp += wxString::Format("void %s();\n", m_funcs[i].name.mb_str());
}
wxString f = wxEmptyString;
f += wxString::Format("void %s()\n{\n\tgl_Position = vec4(0.0f, 0.0f, 0.0f, 1.0f);\n%s}\n", m_funcs[0].name.mb_str(), BuildFuncBody(m_funcs[0]).mb_str());
for(uint i=1; i<m_funcs.GetCount(); ++i)
{
f += wxString::Format("\nvoid %s()\n{\n%s}\n", m_funcs[i].name.mb_str(), BuildFuncBody(m_funcs[i]).mb_str());
}
static const wxString& prot =
"#version 330\n"
"\n"
"%s\n"
"void main()\n{\n\tgl_Position = vec4(0.0f, 0.0f, 0.0f, 1.0f);\n%s}\n";
"%s\n"
"%s";
return wxString::Format(prot, p.mb_str(), main.mb_str());
return wxString::Format(prot, p.mb_str(), fp.mb_str(), f.mb_str());
}
void GLVertexDecompilerThread::Task()
@ -268,11 +345,11 @@ void GLVertexDecompilerThread::Task()
case 0x05: AddScaCode("exp(" + GetSRC(2, true) + ")"); break; // EXP
case 0x06: AddScaCode("log(" + GetSRC(2, true) + ")"); break; // LOG
//case 0x07: break; // LIT
//case 0x08: break; // BRA
//case 0x09: break; // BRI : works differently (BRI o[1].x(TR) L0;)
//case 0x0a: break; // CAL : works same as BRI
//case 0x0b: break; // CLI : works same as BRI
//case 0x0c: break; // RET : works like BRI but shorter (RET o[1].x(TR);)
case 0x08: AddScaCode("{ /*BRA*/ " + GetFunc() + "; return; }", false); break; // BRA
case 0x09: AddScaCode("{ " + GetFunc() + "; return; }", false); break; // BRI : works differently (BRI o[1].x(TR) L0;)
case 0x0a: AddScaCode("/*CAL*/ " + GetFunc(), false); break; // CAL : works same as BRI
case 0x0b: AddScaCode("/*CLI*/ " + GetFunc(), false); break; // CLI : works same as BRI
case 0x0c: AddScaCode("return", false); break; // RET : works like BRI but shorter (RET o[1].x(TR);)
case 0x0d: AddScaCode("log2(" + GetSRC(2, true) + ")"); break; // LG2
case 0x0e: AddScaCode("exp2(" + GetSRC(2, true) + ")"); break; // EX2
case 0x0f: AddScaCode("sin(" + GetSRC(2, true) + ")"); break; // SIN
@ -283,6 +360,7 @@ void GLVertexDecompilerThread::Task()
//case 0x14: break; // POP : works differently (POP o[1].x;)
default:
m_body.Add(wxString::Format("//Unknown vp sca_opcode 0x%x", d1.sca_opcode));
ConLog.Error("Unknown vp sca_opcode 0x%x", d1.sca_opcode);
Emu.Pause();
break;
@ -314,17 +392,25 @@ void GLVertexDecompilerThread::Task()
case 0x16: AddVecCode("sign(" + GetSRC(0) + ")"); break; //SSG
default:
m_body.Add(wxString::Format("//Unknown vp opcode 0x%x", d1.vec_opcode));
ConLog.Error("Unknown vp opcode 0x%x", d1.vec_opcode);
Emu.Pause();
break;
}
if(d3.end) break;
if(d3.end)
{
if(i < m_data.GetCount())
ConLog.Error("Program end before buffer end.");
break;
}
}
m_shader = BuildCode();
main = wxEmptyString;
m_body.Clear();
m_funcs.RemoveAt(1, m_funcs.GetCount() - 1);
}
GLVertexProgram::GLVertexProgram()

View File

@ -127,7 +127,17 @@ struct GLVertexDecompilerThread : public ThreadBase
};
} src[3];
wxString main;
struct FuncInfo
{
u32 offset;
wxString name;
};
wxArrayString m_body;
ArrayF<FuncInfo> m_funcs;
//wxString main;
wxString& m_shader;
Array<u32>& m_data;
GLParamArray& m_parr;
@ -138,6 +148,10 @@ struct GLVertexDecompilerThread : public ThreadBase
, m_shader(shader)
, m_parr(parr)
{
m_funcs.Add(new FuncInfo());
m_funcs[0].offset = 0;
m_funcs[0].name = "main";
//m_cur_func->body = "\tgl_Position = vec4(0.0f, 0.0f, 0.0f, 1.0f);\n";
}
wxString GetMask(bool is_sca);
@ -145,9 +159,11 @@ struct GLVertexDecompilerThread : public ThreadBase
wxString GetScaMask();
wxString GetDST(bool is_sca = false);
wxString GetSRC(const u32 n, bool is_sca = false);
void AddCode(bool is_sca, wxString code, bool src_mask = true);
void AddVecCode(const wxString& code, bool src_mask = true);
void AddScaCode(const wxString& code);
wxString GetFunc();
void AddCode(bool is_sca, wxString code, bool src_mask = true, bool set_dst = true);
void AddVecCode(const wxString& code, bool src_mask = true, bool set_dst = true);
void AddScaCode(const wxString& code, bool set_dst = true);
wxString BuildFuncBody(const FuncInfo& func);
wxString BuildCode();
virtual void Task();

View File

@ -51,6 +51,8 @@ public:
void Init();
void Close();
bool IsInited() const { return m_render != nullptr; }
GSInfo& GetInfo() { return m_info; }
GSRender& GetRender() { assert(m_render); return *m_render; }

View File

@ -104,6 +104,41 @@ u32 RSXVertexData::GetTypeSize()
index = (cmd - a) / m; \
case a \
#define case_32(a, m) \
case a + m: \
case a + m * 2: \
case a + m * 3: \
case a + m * 4: \
case a + m * 5: \
case a + m * 6: \
case a + m * 7: \
case a + m * 8: \
case a + m * 9: \
case a + m * 10: \
case a + m * 11: \
case a + m * 12: \
case a + m * 13: \
case a + m * 14: \
case a + m * 15: \
case a + m * 16: \
case a + m * 17: \
case a + m * 18: \
case a + m * 19: \
case a + m * 20: \
case a + m * 21: \
case a + m * 22: \
case a + m * 23: \
case a + m * 24: \
case a + m * 25: \
case a + m * 26: \
case a + m * 27: \
case a + m * 28: \
case a + m * 29: \
case a + m * 30: \
case a + m * 31: \
index = (cmd - a) / m; \
case a \
void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u32 count)
{
#if CMD_DEBUG
@ -170,6 +205,13 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u3
//ConLog.Warning("texture addr = 0x%x #offset = 0x%x, location=%d", tex_addr, offset, location);
tex.SetOffset(tex_addr);
tex.SetFormat(cubemap, dimension, format, mipmap);
if(!tex.m_width || !tex.m_height)
{
gcmBuffer* buffers = (gcmBuffer*)Memory.GetMemFromAddr(m_gcm_buffers_addr);
if(!tex.m_width) tex.m_width = re(buffers[m_gcm_current_buffer].width);
if(!tex.m_height) tex.m_height = re(buffers[m_gcm_current_buffer].height);
}
}
break;
@ -308,10 +350,24 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u3
{
RSXTexture& tex = m_textures[index];
const u16 height = args[0] & 0xffff;
const u16 width = args[0] >> 16;
u16 height = args[0] & 0xffff;
u16 width = args[0] >> 16;
CMD_LOG("width=%d, height=%d", width, height);
if(!width || !height)
{
ConLog.Warning("Bad texture rect: %dx%d (%dx%d)", width, height, tex.m_width, tex.m_height);
for(int i=0; i<count; ++i)
{
ConLog.Warning("*** 0x%x", args[i]);
}
if(!width) width = tex.m_width;
if(!height) height = tex.m_height;
}
tex.SetRect(width, height);
}
break;
@ -665,6 +721,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u3
case NV4097_SET_TRANSFORM_PROGRAM_LOAD:
{
//ConLog.Warning("NV4097_SET_TRANSFORM_PROGRAM_LOAD: prog = %d", args[0]);
m_cur_vertex_prog = &m_vertex_progs[args[0]];
m_cur_vertex_prog->data.Clear();
@ -677,8 +735,10 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u3
}
break;
case NV4097_SET_TRANSFORM_PROGRAM:
case_32(NV4097_SET_TRANSFORM_PROGRAM, 4):
{
//ConLog.Warning("NV4097_SET_TRANSFORM_PROGRAM[%d](%d)", index, count);
if(!m_cur_vertex_prog)
{
ConLog.Warning("NV4097_SET_TRANSFORM_PROGRAM: m_cur_vertex_prog == NULL");

View File

@ -226,7 +226,7 @@ class RSXThread : public ThreadBase
{
public:
static const uint m_textures_count = 16;
static const uint m_vertex_count = 16;
static const uint m_vertex_count = 32;
static const uint m_fragment_count = 16;
static const uint m_tiles_count = 15;

View File

@ -103,6 +103,24 @@ struct Button
}
};
struct AnalogStick
{
u32 m_offset;
u32 m_keyCodeMin;
u32 m_keyCodeMax;
bool m_min_pressed;
bool m_max_pressed;
AnalogStick(u32 offset, u32 keyCodeMin, u32 keyCodeMax)
: m_min_pressed(false)
, m_max_pressed(false)
, m_offset(offset)
, m_keyCodeMin(keyCodeMin)
, m_keyCodeMax(keyCodeMax)
{
}
};
struct Pad
{
u32 m_port_status;
@ -111,6 +129,7 @@ struct Pad
u32 m_device_type;
Array<Button> m_buttons;
Array<AnalogStick> m_sticks;
s16 m_analog_left_x;
s16 m_analog_left_y;
@ -166,7 +185,7 @@ struct Pad
{
}
~Pad() { m_buttons.Clear(); }
~Pad() { m_buttons.Clear(); m_sticks.Clear(); }
};
struct PadInfo
@ -206,10 +225,29 @@ public:
button.m_pressed = pressed;
}
}
for(u32 s = 0; s < GetSticks(p).GetCount(); s++)
{
AnalogStick& stick = GetSticks(p).Get(s);
if (stick.m_keyCodeMax != code && stick.m_keyCodeMin != code) continue;
GetPads()[p].m_port_status |= CELL_PAD_STATUS_ASSIGN_CHANGES;
if (stick.m_keyCodeMax == code)
{
stick.m_min_pressed = false; //!!! need fix !!!
stick.m_max_pressed = pressed;
}
if (stick.m_keyCodeMin == code)
{
stick.m_max_pressed = false; //!!!
stick.m_min_pressed = pressed;
}
}
}
}
PadInfo& GetInfo() { return m_info; }
Array<Pad>& GetPads() { return m_pads; }
Array<Button>& GetButtons(const u32 pad) { return GetPads()[pad].m_buttons; }
Array<AnalogStick>& GetSticks(const u32 pad) { return GetPads()[pad].m_sticks; }
};

View File

@ -56,5 +56,10 @@ public:
m_pads[0].m_buttons.Move(new Button(CELL_PAD_BTN_OFFSET_DIGITAL2, static_cast<char>(Ini.PadHandlerL1.GetValue()), CELL_PAD_CTRL_L1));
m_pads[0].m_buttons.Move(new Button(CELL_PAD_BTN_OFFSET_DIGITAL2, static_cast<char>(Ini.PadHandlerR2.GetValue()), CELL_PAD_CTRL_R2));
m_pads[0].m_buttons.Move(new Button(CELL_PAD_BTN_OFFSET_DIGITAL2, static_cast<char>(Ini.PadHandlerL2.GetValue()), CELL_PAD_CTRL_L2));
m_pads[0].m_sticks.Move(new AnalogStick(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X, WXK_LEFT, WXK_RIGHT));
m_pads[0].m_sticks.Move(new AnalogStick(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y, WXK_UP, WXK_DOWN));
m_pads[0].m_sticks.Move(new AnalogStick(CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X, WXK_HOME, WXK_END));
m_pads[0].m_sticks.Move(new AnalogStick(CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y, WXK_PAGEUP, WXK_PAGEDOWN));
}
};

View File

@ -419,12 +419,27 @@ public:
{
}
u32 GetAddr() const { return m_addr; }
__forceinline u32 GetAddr() const { return m_addr; }
bool IsGood() const
__forceinline bool IsGood() const
{
return Memory.IsGoodAddr(m_addr, sizeof(T));
}
__forceinline operator u32() const
{
return m_addr;
}
__forceinline bool operator != (nullptr_t) const
{
return m_addr != 0;
}
__forceinline bool operator == (nullptr_t) const
{
return m_addr == 0;
}
};
template<typename T>
@ -435,6 +450,9 @@ public:
{
}
template<typename NT> operator mem_ptr_t<NT>&() { return (mem_ptr_t<NT>&)*this; }
template<typename NT> operator const mem_ptr_t<NT>&() const { return (const mem_ptr_t<NT>&)*this; }
T* operator -> ()
{
return (T*)&Memory[this->m_addr];
@ -513,8 +531,6 @@ public:
return (const T&)Memory[this->m_addr + sizeof(T) * index];
}
operator bool() const { return this->m_addr == 0; }
bool operator == (mem_ptr_t right) const { return this->m_addr == right.m_addr; }
bool operator != (mem_ptr_t right) const { return this->m_addr != right.m_addr; }
bool operator > (mem_ptr_t right) const { return this->m_addr > right.m_addr; }
@ -530,6 +546,32 @@ public:
bool operator <= (T* right) const { return (T*)&Memory[this->m_addr] <= right; }
};
template<>
class mem_ptr_t<void> : public mem_base_t<u8>
{
public:
mem_ptr_t(u32 addr) : mem_base_t<u8>(addr)
{
}
template<typename NT> operator mem_ptr_t<NT>&() { return (mem_ptr_t<NT>&)*this; }
template<typename NT> operator const mem_ptr_t<NT>&() const { return (const mem_ptr_t<NT>&)*this; }
bool operator == (mem_ptr_t right) const { return this->m_addr == right.m_addr; }
bool operator != (mem_ptr_t right) const { return this->m_addr != right.m_addr; }
bool operator > (mem_ptr_t right) const { return this->m_addr > right.m_addr; }
bool operator < (mem_ptr_t right) const { return this->m_addr < right.m_addr; }
bool operator >= (mem_ptr_t right) const { return this->m_addr >= right.m_addr; }
bool operator <= (mem_ptr_t right) const { return this->m_addr <= right.m_addr; }
bool operator == (void* right) const { return (void*)&Memory[this->m_addr] == right; }
bool operator != (void* right) const { return (void*)&Memory[this->m_addr] != right; }
bool operator > (void* right) const { return (void*)&Memory[this->m_addr] > right; }
bool operator < (void* right) const { return (void*)&Memory[this->m_addr] < right; }
bool operator >= (void* right) const { return (void*)&Memory[this->m_addr] >= right; }
bool operator <= (void* right) const { return (void*)&Memory[this->m_addr] <= right; }
};
template<typename T> static bool operator == (T* left, mem_ptr_t<T> right) { return left == (T*)&Memory[right.GetAddr()]; }
template<typename T> static bool operator != (T* left, mem_ptr_t<T> right) { return left != (T*)&Memory[right.GetAddr()]; }
template<typename T> static bool operator > (T* left, mem_ptr_t<T> right) { return left > (T*)&Memory[right.GetAddr()]; }
@ -551,6 +593,11 @@ public:
return *this;
}
__forceinline T GetValue()
{
return (be_t<T>&)Memory[this->m_addr];
}
operator const T() const
{
return (be_t<T>&)Memory[this->m_addr];
@ -639,6 +686,123 @@ public:
void SetAddr(const u64 addr) { m_addr = addr; }
};
template<typename T> class mem_func_ptr_t;
template<typename RT>
class mem_func_ptr_t<RT (*)()> : public mem_base_t<u64>
{
__forceinline void call_func(bool is_async)
{
Callback cb;
cb.SetAddr(m_addr);
cb.Branch(!is_async);
}
public:
__forceinline void operator()()
{
call_func(false);
}
__forceinline void async()
{
call_func(true);
}
};
template<typename RT, typename T1>
class mem_func_ptr_t<RT (*)(T1)> : public mem_base_t<u64>
{
__forceinline void call_func(bool is_async, T1 a1)
{
Callback cb;
cb.SetAddr(m_addr);
cb.Handle(a1);
cb.Branch(!is_async);
}
public:
__forceinline void operator()(T1 a1)
{
call_func(false, a1);
}
__forceinline void async(T1 a1)
{
call_func(true, a1);
}
};
template<typename RT, typename T1, typename T2>
class mem_func_ptr_t<RT (*)(T1, T2)> : public mem_base_t<u64>
{
__forceinline void call_func(bool is_async, T1 a1, T2 a2)
{
Callback cb;
cb.SetAddr(m_addr);
cb.Handle(a1, a2);
cb.Branch(!is_async);
}
public:
__forceinline void operator()(T1 a1, T2 a2)
{
call_func(false, a1, a2);
}
__forceinline void async(T1 a1, T2 a2)
{
call_func(true, a1, a2);
}
};
template<typename RT, typename T1, typename T2, typename T3>
class mem_func_ptr_t<RT (*)(T1, T2, T3)> : public mem_base_t<u64>
{
__forceinline void call_func(bool is_async, T1 a1, T2 a2, T3 a3)
{
Callback cb;
cb.SetAddr(m_addr);
cb.Handle(a1, a2, a3);
cb.Branch(!is_async);
}
public:
__forceinline void operator()(T1 a1, T2 a2, T3 a3)
{
call_func(false, a1, a2, a3);
}
__forceinline void async(T1 a1, T2 a2, T3 a3)
{
call_func(true, a1, a2, a3);
}
};
template<typename RT, typename T1, typename T2, typename T3, typename T4>
class mem_func_ptr_t<RT (*)(T1, T2, T3, T4)> : public mem_base_t<u64>
{
__forceinline void call_func(bool is_async, T1 a1, T2 a2, T3 a3, T4 a4)
{
Callback cb;
cb.SetAddr(m_addr);
cb.Handle(a1, a2, a3, a4);
cb.Branch(!is_async);
}
public:
__forceinline void operator()(T1 a1, T2 a2, T3 a3, T4 a4)
{
call_func(false, a1, a2, a3, a4);
}
__forceinline void async(T1 a1, T2 a2, T3 a3, T4 a4)
{
call_func(true, a1, a2, a3, a4);
}
};
template<typename T>
class MemoryAllocator
{

View File

@ -9,7 +9,9 @@ Callback::Callback(u32 slot, u64 addr)
, a1(0)
, a2(0)
, a3(0)
, a4(0)
, m_has_data(false)
, m_name("Callback")
{
}
@ -38,11 +40,12 @@ bool Callback::HasData() const
return m_has_data;
}
void Callback::Handle(u64 _a1, u64 _a2, u64 _a3)
void Callback::Handle(u64 _a1, u64 _a2, u64 _a3, u64 _a4)
{
a1 = _a1;
a2 = _a2;
a3 = _a3;
a4 = _a4;
m_has_data = true;
}
@ -55,11 +58,12 @@ void Callback::Branch(bool wait)
new_thread.SetEntry(m_addr);
new_thread.SetPrio(1001);
new_thread.SetStackSize(0x10000);
new_thread.SetName("Callback");
new_thread.SetName(m_name);
new_thread.SetArg(0, a1);
new_thread.SetArg(1, a2);
new_thread.SetArg(2, a3);
new_thread.SetArg(3, a4);
new_thread.Run();
new_thread.Exec();
@ -68,6 +72,11 @@ void Callback::Branch(bool wait)
GetCurrentPPCThread()->Wait(new_thread);
}
void Callback::SetName(const std::string& name)
{
m_name = name;
}
Callback::operator bool() const
{
return GetAddr() != 0;

View File

@ -8,10 +8,13 @@ protected:
bool m_has_data;
std::string m_name;
public:
u64 a1;
u64 a2;
u64 a3;
u64 a4;
u32 GetSlot() const;
u64 GetAddr() const;
@ -20,8 +23,9 @@ public:
bool HasData() const;
Callback(u32 slot = 0, u64 addr = 0);
void Handle(u64 a1 = 0, u64 a2 = 0, u64 a3 = 0);
void Handle(u64 a1 = 0, u64 a2 = 0, u64 a3 = 0, u64 a4 = 0);
void Branch(bool wait);
void SetName(const std::string& name);
operator bool() const;
};

View File

@ -570,6 +570,171 @@ s64 SysCalls::DoFunc(const u32 id)
case 0x56776c0d: FUNC_LOG_ERROR("TODO: cellKey2CharGetChar");
case 0xabf629c1: FUNC_LOG_ERROR("TODO: cellKey2CharOpen");
case 0xbfc03768: FUNC_LOG_ERROR("TODO: cellKey2CharSetMode");
case 0x005200e6: FUNC_LOG_ERROR("TODO: UCS2toEUCJP");
case 0x01b0cbf4: FUNC_LOG_ERROR("TODO: l10n_convert");
case 0x0356038c: FUNC_LOG_ERROR("TODO: UCS2toUTF32");
case 0x05028763: FUNC_LOG_ERROR("TODO: jis2kuten");
case 0x058addc8: FUNC_LOG_ERROR("TODO: UTF8toGB18030");
case 0x060ee3b2: FUNC_LOG_ERROR("TODO: JISstoUTF8s");
case 0x07168a83: FUNC_LOG_ERROR("TODO: SjisZen2Han");
case 0x0bc386c8: FUNC_LOG_ERROR("TODO: ToSjisLower");
case 0x0bedf77d: FUNC_LOG_ERROR("TODO: UCS2toGB18030");
case 0x0bf867e2: FUNC_LOG_ERROR("TODO: HZstoUCS2s");
case 0x0ce278fd: FUNC_LOG_ERROR("TODO: UCS2stoHZs");
case 0x0d90a48d: FUNC_LOG_ERROR("TODO: UCS2stoSJISs");
case 0x0f624540: FUNC_LOG_ERROR("TODO: kuten2eucjp");
case 0x14ee3649: FUNC_LOG_ERROR("TODO: sjis2jis");
case 0x14f504b8: FUNC_LOG_ERROR("TODO: EUCKRstoUCS2s");
case 0x16eaf5f1: FUNC_LOG_ERROR("TODO: UHCstoEUCKRs");
case 0x1758053c: FUNC_LOG_ERROR("TODO: jis2sjis");
case 0x1906ce6b: FUNC_LOG_ERROR("TODO: jstrnchk");
case 0x1ac0d23d: FUNC_LOG_ERROR("TODO: L10nConvert");
case 0x1ae2acee: FUNC_LOG_ERROR("TODO: EUCCNstoUTF8s");
case 0x1cb1138f: FUNC_LOG_ERROR("TODO: GBKstoUCS2s");
case 0x1da42d70: FUNC_LOG_ERROR("TODO: eucjphan2zen");
case 0x1ec712e0: FUNC_LOG_ERROR("TODO: ToSjisHira");
case 0x1fb50183: FUNC_LOG_ERROR("TODO: GBKtoUCS2");
case 0x21948c03: FUNC_LOG_ERROR("TODO: eucjp2jis");
case 0x21aa3045: FUNC_LOG_ERROR("TODO: UTF32stoUTF8s");
case 0x24fd32a9: FUNC_LOG_ERROR("TODO: sjishan2zen");
case 0x256b6861: FUNC_LOG_ERROR("TODO: UCS2toSBCS");
case 0x262a5ae2: FUNC_LOG_ERROR("TODO: UTF8stoGBKs");
case 0x28724522: FUNC_LOG_ERROR("TODO: UTF8toUCS2");
case 0x2ad091c6: FUNC_LOG_ERROR("TODO: UCS2stoUTF8s");
case 0x2b84030c: FUNC_LOG_ERROR("TODO: EUCKRstoUTF8s");
case 0x2efa7294: FUNC_LOG_ERROR("TODO: UTF16stoUTF32s");
case 0x2f9eb543: FUNC_LOG_ERROR("TODO: UTF8toEUCKR");
case 0x317ab7c2: FUNC_LOG_ERROR("TODO: UTF16toUTF8");
case 0x32689828: FUNC_LOG_ERROR("TODO: ARIBstoUTF8s");
case 0x33435818: FUNC_LOG_ERROR("TODO: SJISstoUTF8s");
case 0x33f8b35c: FUNC_LOG_ERROR("TODO: sjiszen2han");
case 0x3968f176: FUNC_LOG_ERROR("TODO: ToEucJpLower");
case 0x398a3dee: FUNC_LOG_ERROR("TODO: MSJIStoUTF8");
case 0x3a20bc34: FUNC_LOG_ERROR("TODO: UCS2stoMSJISs");
case 0x3dabd5a7: FUNC_LOG_ERROR("TODO: EUCJPtoUTF8");
case 0x3df65b64: FUNC_LOG_ERROR("TODO: eucjp2sjis");
case 0x408a622b: FUNC_LOG_ERROR("TODO: ToEucJpHira");
case 0x41b4a5ae: FUNC_LOG_ERROR("TODO: UHCstoUCS2s");
case 0x41ccf033: FUNC_LOG_ERROR("TODO: ToEucJpKata");
case 0x42838145: FUNC_LOG_ERROR("TODO: HZstoUTF8s");
case 0x4931b44e: FUNC_LOG_ERROR("TODO: UTF8toMSJIS");
case 0x4b3bbacb: FUNC_LOG_ERROR("TODO: BIG5toUTF8");
case 0x511d386b: FUNC_LOG_ERROR("TODO: EUCJPstoSJISs");
case 0x52b7883f: FUNC_LOG_ERROR("TODO: UTF8stoBIG5s");
case 0x53558b6b: FUNC_LOG_ERROR("TODO: UTF16stoUCS2s");
case 0x53764725: FUNC_LOG_ERROR("TODO: UCS2stoGB18030s");
case 0x53c71ac2: FUNC_LOG_ERROR("TODO: EUCJPtoSJIS");
case 0x54f59807: FUNC_LOG_ERROR("TODO: EUCJPtoUCS2");
case 0x55f6921c: FUNC_LOG_ERROR("TODO: UCS2stoGBKs");
case 0x58246762: FUNC_LOG_ERROR("TODO: EUCKRtoUHC");
case 0x596df41c: FUNC_LOG_ERROR("TODO: UCS2toSJIS");
case 0x5a4ab223: FUNC_LOG_ERROR("TODO: MSJISstoUTF8s");
case 0x5ac783dc: FUNC_LOG_ERROR("TODO: EUCJPstoUTF8s");
case 0x5b684dfb: FUNC_LOG_ERROR("TODO: UCS2toBIG5");
case 0x5cd29270: FUNC_LOG_ERROR("TODO: UTF8stoEUCKRs");
case 0x5e1d9330: FUNC_LOG_ERROR("TODO: UHCstoUTF8s");
case 0x60ffa0ec: FUNC_LOG_ERROR("TODO: GB18030stoUCS2s");
case 0x6122e000: FUNC_LOG_ERROR("TODO: SJIStoUTF8");
case 0x6169f205: FUNC_LOG_ERROR("TODO: JISstoSJISs");
case 0x61fb9442: FUNC_LOG_ERROR("TODO: UTF8toUTF16");
case 0x62b36bcf: FUNC_LOG_ERROR("TODO: UTF8stoMSJISs");
case 0x63219199: FUNC_LOG_ERROR("TODO: EUCKRtoUTF8");
case 0x638c2fc1: FUNC_LOG_ERROR("TODO: SjisHan2Zen");
case 0x64a10ec8: FUNC_LOG_ERROR("TODO: UCS2toUTF16");
case 0x65444204: FUNC_LOG_ERROR("TODO: UCS2toMSJIS");
case 0x6621a82c: FUNC_LOG_ERROR("TODO: sjis2kuten");
case 0x6a6f25d1: FUNC_LOG_ERROR("TODO: UCS2toUHC");
case 0x6c62d879: FUNC_LOG_ERROR("TODO: UTF32toUCS2");
case 0x6de4b508: FUNC_LOG_ERROR("TODO: ToSjisUpper");
case 0x6e0705c4: FUNC_LOG_ERROR("TODO: UTF8toEUCJP");
case 0x6e5906fd: FUNC_LOG_ERROR("TODO: UCS2stoEUCJPs");
case 0x6fc530b3: FUNC_LOG_ERROR("TODO: UTF16toUCS2");
case 0x714a9b4a: FUNC_LOG_ERROR("TODO: UCS2stoUTF16s");
case 0x71804d64: FUNC_LOG_ERROR("TODO: UCS2stoEUCCNs");
case 0x72632e53: FUNC_LOG_ERROR("TODO: SBCSstoUTF8s");
case 0x73f2cd21: FUNC_LOG_ERROR("TODO: SJISstoJISs");
case 0x74496718: FUNC_LOG_ERROR("TODO: SBCStoUTF8");
case 0x74871fe0: FUNC_LOG_ERROR("TODO: UTF8toUTF32");
case 0x750c363d: FUNC_LOG_ERROR("TODO: jstrchk");
case 0x7c5bde1c: FUNC_LOG_ERROR("TODO: UHCtoEUCKR");
case 0x7c912bda: FUNC_LOG_ERROR("TODO: kuten2jis");
case 0x7d07a1c2: FUNC_LOG_ERROR("TODO: UTF8toEUCCN");
case 0x8171c1cc: FUNC_LOG_ERROR("TODO: EUCCNtoUTF8");
case 0x82d5ecdf: FUNC_LOG_ERROR("TODO: EucJpZen2Han");
case 0x8555fe15: FUNC_LOG_ERROR("TODO: UTF32stoUTF16s");
case 0x860fc741: FUNC_LOG_ERROR("TODO: GBKtoUTF8");
case 0x867f7b8b: FUNC_LOG_ERROR("TODO: ToEucJpUpper");
case 0x88f8340b: FUNC_LOG_ERROR("TODO: UCS2stoJISs");
case 0x89236c86: FUNC_LOG_ERROR("TODO: UTF8stoGB18030s");
case 0x8a56f148: FUNC_LOG_ERROR("TODO: EUCKRstoUHCs");
case 0x8ccdba38: FUNC_LOG_ERROR("TODO: UTF8stoUTF32s");
case 0x8f472054: FUNC_LOG_ERROR("TODO: UTF8stoEUCCNs");
case 0x90e9b5d2: FUNC_LOG_ERROR("TODO: EUCJPstoUCS2s");
case 0x91a99765: FUNC_LOG_ERROR("TODO: UHCtoUCS2");
case 0x931ff25a: FUNC_LOG_ERROR("TODO: L10nConvertStr");
case 0x949bb14c: FUNC_LOG_ERROR("TODO: GBKstoUTF8s");
case 0x9557ac9b: FUNC_LOG_ERROR("TODO: UTF8toUHC");
case 0x9768b6d3: FUNC_LOG_ERROR("TODO: UTF32toUTF8");
case 0x9874020d: FUNC_LOG_ERROR("TODO: sjis2eucjp");
case 0x9a0e7d23: FUNC_LOG_ERROR("TODO: UCS2toEUCCN");
case 0x9a13d6b8: FUNC_LOG_ERROR("TODO: UTF8stoUHCs");
case 0x9a72059d: FUNC_LOG_ERROR("TODO: EUCKRtoUCS2");
case 0x9b1210c6: FUNC_LOG_ERROR("TODO: UTF32toUTF16");
case 0x9cd8135b: FUNC_LOG_ERROR("TODO: EUCCNstoUCS2s");
case 0x9ce52809: FUNC_LOG_ERROR("TODO: SBCSstoUCS2s");
case 0x9cf1ab77: FUNC_LOG_ERROR("TODO: UTF8stoJISs");
case 0x9d14dc46: FUNC_LOG_ERROR("TODO: ToSjisKata");
case 0x9dcde367: FUNC_LOG_ERROR("TODO: jis2eucjp");
case 0x9ec52258: FUNC_LOG_ERROR("TODO: BIG5toUCS2");
case 0xa0d463c0: FUNC_LOG_ERROR("TODO: UCS2toGBK");
case 0xa19fb9de: FUNC_LOG_ERROR("TODO: UTF16toUTF32");
case 0xa298cad2: FUNC_LOG_ERROR("TODO: l10n_convert_str");
case 0xa34fa0eb: FUNC_LOG_ERROR("TODO: EUCJPstoJISs");
case 0xa5146299: FUNC_LOG_ERROR("TODO: UTF8stoARIBs");
case 0xa609f3e9: FUNC_LOG_ERROR("TODO: JISstoEUCJPs");
case 0xa60ff5c9: FUNC_LOG_ERROR("TODO: EucJpHan2Zen");
case 0xa963619c: FUNC_LOG_ERROR("TODO: isEucJpKigou");
case 0xa9a76fb8: FUNC_LOG_ERROR("TODO: UCS2toUTF8");
case 0xaf18d499: FUNC_LOG_ERROR("TODO: GB18030toUCS2");
case 0xb3361be6: FUNC_LOG_ERROR("TODO: UHCtoUTF8");
case 0xb6e45343: FUNC_LOG_ERROR("TODO: MSJIStoUCS2");
case 0xb7cef4a6: FUNC_LOG_ERROR("TODO: UTF8toGBK");
case 0xb7e08f7a: FUNC_LOG_ERROR("TODO: kuten2sjis");
case 0xb9cf473d: FUNC_LOG_ERROR("TODO: UTF8toSBCS");
case 0xbdd44ee3: FUNC_LOG_ERROR("TODO: SJIStoUCS2");
case 0xbe42e661: FUNC_LOG_ERROR("TODO: eucjpzen2han");
case 0xbe8d5485: FUNC_LOG_ERROR("TODO: UCS2stoARIBs");
case 0xbefe3869: FUNC_LOG_ERROR("TODO: isSjisKigou");
case 0xc62b758d: FUNC_LOG_ERROR("TODO: UTF8stoEUCJPs");
case 0xc7bdcb4c: FUNC_LOG_ERROR("TODO: UCS2toEUCKR");
case 0xc944fa56: FUNC_LOG_ERROR("TODO: SBCStoUCS2");
case 0xc9b78f58: FUNC_LOG_ERROR("TODO: MSJISstoUCS2s");
case 0xcc1633cc: FUNC_LOG_ERROR("TODO: l10n_get_converter");
case 0xd02ef83d: FUNC_LOG_ERROR("TODO: GB18030stoUTF8s");
case 0xd8721e2c: FUNC_LOG_ERROR("TODO: SJISstoEUCJPs");
case 0xd8cb24cb: FUNC_LOG_ERROR("TODO: UTF32stoUCS2s");
case 0xd990858b: FUNC_LOG_ERROR("TODO: BIG5stoUTF8s");
case 0xd9fb1224: FUNC_LOG_ERROR("TODO: EUCCNtoUCS2");
case 0xda67b37f: FUNC_LOG_ERROR("TODO: UTF8stoSBCSs");
case 0xdc54886c: FUNC_LOG_ERROR("TODO: UCS2stoEUCKRs");
case 0xdd5ebdeb: FUNC_LOG_ERROR("TODO: UTF8stoSJISs");
case 0xdefa1c17: FUNC_LOG_ERROR("TODO: UTF8stoHZs");
case 0xe2eabb32: FUNC_LOG_ERROR("TODO: eucjp2kuten");
case 0xe6d9e234: FUNC_LOG_ERROR("TODO: UTF8toBIG5");
case 0xe6f5711b: FUNC_LOG_ERROR("TODO: UTF16stoUTF8s");
case 0xe956dc64: FUNC_LOG_ERROR("TODO: JISstoUCS2s");
case 0xeabc3d00: FUNC_LOG_ERROR("TODO: GB18030toUTF8");
case 0xeb3dc670: FUNC_LOG_ERROR("TODO: UTF8toSJIS");
case 0xeb41cc68: FUNC_LOG_ERROR("TODO: ARIBstoUCS2s");
case 0xeb685b83: FUNC_LOG_ERROR("TODO: UCS2stoUTF32s");
case 0xebae29c0: FUNC_LOG_ERROR("TODO: UCS2stoSBCSs");
case 0xee6c6a39: FUNC_LOG_ERROR("TODO: UCS2stoBIG5s");
case 0xf1dcfa71: FUNC_LOG_ERROR("TODO: UCS2stoUHCs");
case 0xf439728e: FUNC_LOG_ERROR("TODO: SJIStoEUCJP");
case 0xf7681b9a: FUNC_LOG_ERROR("TODO: UTF8stoUTF16s");
case 0xf9b1896d: FUNC_LOG_ERROR("TODO: SJISstoUCS2s");
case 0xfa4a675a: FUNC_LOG_ERROR("TODO: BIG5stoUCS2s");
case 0xfdbf6ac5: FUNC_LOG_ERROR("TODO: UTF8stoUCS2s");
case 0x0252efcc: FUNC_LOG_ERROR("TODO: cellUserTraceInit");
case 0x05893e7c: FUNC_LOG_ERROR("TODO: cellUserTraceRegister");
case 0x6d045c2e: FUNC_LOG_ERROR("TODO: cellUserTraceUnregister");

View File

@ -19,7 +19,7 @@ static const g_module_list[] =
{0x0002, "cellHttpUtil"},
{0x0003, "cellSsl"},
{0x0004, "cellHttps"},
{0x0005, "cellVdec"},
{0x0005, "libvdec"},
{0x0006, "cellAdec"},
{0x0007, "cellDmux"},
{0x0008, "cellVpost"},
@ -90,7 +90,6 @@ static const g_module_list[] =
{0x0050, "cellSpursJq"},
{0x0052, "cellPngEnc"},
{0x0053, "cellMusicDecode2"},
{0x0054, "cellSync"},
{0x0055, "cellSync2"},
{0x0056, "cellNpUtil"},
{0x0057, "cellRudp"},

View File

@ -4,7 +4,8 @@
#include "Emu/Audio/cellAudio.h"
void cellAudio_init();
Module cellAudio(0x0011, cellAudio_init);
void cellAudio_unload();
Module cellAudio(0x0011, cellAudio_init, nullptr, cellAudio_unload);
enum
{
@ -81,9 +82,9 @@ struct CellAudioPortConfig
struct CellAudioConfig //custom structure
{
bool g_is_audio_initialized;
bool g_is_audio_port_open;
bool g_is_audio_port_started;
bool m_is_audio_initialized;
bool m_is_audio_port_open;
bool m_is_audio_port_started;
};
CellAudioPortParam* m_param = new CellAudioPortParam;
@ -95,55 +96,55 @@ typedef void * CellAANHandle;
struct CellSSPlayerConfig
{
u32 channels;
u32 outputMode;
be_t<u32> channels;
be_t<u32> outputMode;
};
struct CellSSPlayerWaveParam
{
void *addr;
int format;
u32 samples;
u32 loopStartOffset;
u32 startOffset;
be_t<s32> format;
be_t<u32> samples;
be_t<u32> loopStartOffset;
be_t<u32> startOffset;
};
struct CellSSPlayerCommonParam
{
u32 loopMode;
u32 attackMode;
be_t<u32> loopMode;
be_t<u32> attackMode;
};
struct CellSurMixerPosition
{
float x;
float y;
float z;
be_t<float> x;
be_t<float> y;
be_t<float> z;
};
struct CellSSPlayerRuntimeInfo
{
float level;
float speed;
be_t<float> level;
be_t<float> speed;
CellSurMixerPosition position;
};
struct CellSurMixerConfig
{
s32 priority;
u32 chStrips1;
u32 chStrips2;
u32 chStrips6;
u32 chStrips8;
be_t<s32> priority;
be_t<u32> chStrips1;
be_t<u32> chStrips2;
be_t<u32> chStrips6;
be_t<u32> chStrips8;
};
struct CellSurMixerChStripParam
{
u32 param;
be_t<u32> param;
void *attribute;
int dBSwitch;
float floatVal;
int intVal;
be_t<s32> dBSwitch;
be_t<float> floatVal;
be_t<s32> intVal;
};
CellSSPlayerWaveParam current_SSPlayerWaveParam;
@ -164,31 +165,31 @@ struct CellSnd3KeyOnParam
u8 vel;
u8 pan;
u8 panEx;
s32 addPitch;
be_t<s32> addPitch;
};
struct CellSnd3VoiceBitCtx
{
u32 core; //[CELL_SND3_MAX_CORE], unknown identifier
be_t<u32> core; //[CELL_SND3_MAX_CORE], unknown identifier
};
struct CellSnd3RequestQueueCtx
{
void *frontQueue;
u32 frontQueueSize;
be_t<u32> frontQueueSize;
void *rearQueue;
u32 rearQueueSize;
be_t<u32> rearQueueSize;
};
//libsynt2 datatypes
struct CellSoundSynth2EffectAttr
{
u16 core;
u16 mode;
s16 depth_L;
s16 depth_R;
u16 delay;
u16 feedback;
be_t<u16> core;
be_t<u16> mode;
be_t<s16> depth_L;
be_t<s16> depth_R;
be_t<u16> delay;
be_t<u16> feedback;
};
// libaudio Functions
@ -196,28 +197,26 @@ struct CellSoundSynth2EffectAttr
int cellAudioInit()
{
cellAudio.Warning("cellAudioInit()");
if(m_config->g_is_audio_initialized == true) return CELL_AUDIO_ERROR_ALREADY_INIT;
m_config->g_is_audio_initialized = true;
if(m_config->m_is_audio_initialized == true) return CELL_AUDIO_ERROR_ALREADY_INIT;
m_config->m_is_audio_initialized = true;
return CELL_OK;
}
int cellAudioQuit()
{
cellAudio.Warning("cellAudioQuit()");
if (m_config->g_is_audio_initialized == false) return CELL_AUDIO_ERROR_NOT_INIT;
m_config->g_is_audio_initialized = false;
if (m_config->m_is_audio_initialized == false) return CELL_AUDIO_ERROR_NOT_INIT;
m_config->m_is_audio_initialized = false;
delete m_config;
return CELL_OK;
}
int cellAudioPortOpen(mem_ptr_t<CellAudioPortParam> audioParam, mem32_t portNum)
{
cellAudio.Warning("cellAudioPortOpen(audioParam_addr=0x%x,portNum_addr=0x%x)",audioParam.GetAddr(),portNum.GetAddr());
UNIMPLEMENTED_FUNC(cellAudio);
if(!audioParam.IsGood() || !portNum.IsGood()) return CELL_AUDIO_ERROR_PORT_OPEN;
m_config->g_is_audio_port_open = true;
m_config->m_is_audio_port_open = true;
m_param->nChannel = audioParam->nChannel;
m_param->nBlock = audioParam->nBlock;
@ -235,20 +234,22 @@ int cellAudioGetPortConfig(u32 portNum, mem_ptr_t<CellAudioPortConfig> portConfi
if(!portConfig.IsGood())
{
return CELL_AUDIO_ERROR_PARAM;
};
}
//if(portNum > 7) return CELL_AUDIO_ERROR_PORT_FULL;
if(m_config->g_is_audio_port_open == false)
if(m_config->m_is_audio_port_open == false)
{
portConfig->status = CELL_AUDIO_STATUS_CLOSE;
return CELL_OK;
};
}
if(m_config->g_is_audio_port_started == true)
if(m_config->m_is_audio_port_started == true)
{
portConfig->status = CELL_AUDIO_STATUS_RUN;
}
else
{
portConfig->status = CELL_AUDIO_STATUS_READY;
portConfig->nChannel = m_param->nChannel;
portConfig->nBlock = m_param->nBlock;
@ -258,36 +259,41 @@ int cellAudioGetPortConfig(u32 portNum, mem_ptr_t<CellAudioPortConfig> portConfi
// portAddr - readIndexAddr == 0xFFF0 on ps3
Memory.Write64(portConfig->readIndexAddr, 1);
return CELL_OK;
}
return CELL_OK;
}
int cellAudioPortStart(u32 portNum)
{
cellAudio.Warning("cellAudioPortStart(portNum=0x%x)",portNum);
if (m_config->g_is_audio_port_open == false) return CELL_AUDIO_ERROR_PORT_NOT_OPEN;
m_config->g_is_audio_port_started = true;
if (m_config->m_is_audio_port_open == true)
return CELL_AUDIO_ERROR_PORT_OPEN;
m_config->m_is_audio_port_started = true;
return CELL_OK;
}
int cellAudioPortClose(u32 portNum)
{
cellAudio.Warning("cellAudioPortClose(portNum=0x%x)",portNum);
if (m_config->g_is_audio_port_open == false) return CELL_AUDIO_ERROR_PORT_NOT_OPEN;
m_config->g_is_audio_port_open = false;
UNIMPLEMENTED_FUNC(cellAudio);
if (m_config->m_is_audio_port_open == false)
return CELL_AUDIO_ERROR_PORT_NOT_OPEN;
m_config->m_is_audio_port_open = false;
return CELL_OK;
}
int cellAudioPortStop(u32 portNum)
{
cellAudio.Warning("cellAudioPortStop(portNum=0x%x)",portNum);
if (m_config->g_is_audio_port_started == false) return CELL_AUDIO_ERROR_PORT_NOT_OPEN;
m_config->g_is_audio_port_started = false;
UNIMPLEMENTED_FUNC(cellAudio);
if (m_config->m_is_audio_port_started == false)
return CELL_AUDIO_ERROR_PORT_NOT_OPEN;
m_config->m_is_audio_port_started = false;
return CELL_OK;
}
@ -1006,3 +1012,10 @@ void cellAudio_init()
//TODO: Find addresses for libmixer, libsnd3 and libsynth2 functions
}
void cellAudio_unload()
{
m_config->m_is_audio_initialized = false;
m_config->m_is_audio_port_open = false;
m_config->m_is_audio_port_started = false;
}

View File

@ -415,6 +415,44 @@ void cellGcmSetFlipStatus()
Emu.GetGSManager().GetRender().m_flip_status = 0;
}
int cellGcmSetTile(u8 index, u8 location, u32 offset, u32 size, u32 pitch, u8 comp, u16 base, u8 bank)
{
cellGcmSys.Warning("cellGcmSetTile(index=%d, location=%d, offset=%d, size=%d, pitch=%d, comp=%d, base=%d, bank=%d)",
index, location, offset, size, pitch, comp, base, bank);
//copied form cellGcmSetTileInfo
if(index >= RSXThread::m_tiles_count || base >= 800 || bank >= 4)
{
return CELL_GCM_ERROR_INVALID_VALUE;
}
if(offset & 0xffff || size & 0xffff || pitch & 0xf)
{
return CELL_GCM_ERROR_INVALID_ALIGNMENT;
}
if(location >= 2 || (comp != 0 && (comp < 7 || comp > 12)))
{
return CELL_GCM_ERROR_INVALID_ENUM;
}
if(comp)
{
cellGcmSys.Error("cellGcmSetTileInfo: bad comp! (%d)", comp);
}
auto& tile = Emu.GetGSManager().GetRender().m_tiles[index];
tile.m_location = location;
tile.m_offset = offset;
tile.m_size = size;
tile.m_pitch = pitch;
tile.m_comp = comp;
tile.m_base = base;
tile.m_bank = bank;
Memory.WriteData(Emu.GetGSManager().GetRender().m_tiles_addr + sizeof(CellGcmTileInfo) * index, tile.Pack());
return CELL_OK;
}
int cellGcmSetTileInfo(u8 index, u8 location, u32 offset, u32 size, u32 pitch, u8 comp, u16 base, u8 bank)
{
cellGcmSys.Warning("cellGcmSetTileInfo(index=%d, location=%d, offset=%d, size=%d, pitch=%d, comp=%d, base=%d, bank=%d)",
@ -720,6 +758,7 @@ void cellGcmSys_init()
cellGcmSys.AddFunc(0x93806525, cellGcmGetCurrentDisplayBufferId);
cellGcmSys.AddFunc(0xbc982946, cellGcmSetDefaultCommandBuffer);
cellGcmSys.AddFunc(0xa47c09ff, cellGcmSetFlipStatus);
cellGcmSys.AddFunc(0xd0b1d189, cellGcmSetTile);
cellGcmSys.AddFunc(0xbd100dbc, cellGcmSetTileInfo);
cellGcmSys.AddFunc(0x4524cccd, cellGcmBindTile);
cellGcmSys.AddFunc(0x0b4b62d5, cellGcmSetPrepareFlip);

View File

@ -186,7 +186,8 @@ struct PamfHeader
be_t<u32> mux_rate_max; //== 0x01D470 (400 bps per unit, == 48000000 bps)
be_t<u32> mux_rate_min; //== 0x0107AC (?????)
u16 reserved2; // ?????
be_t<u16> stream_count; //total stream count
u8 reserved3;
u8 stream_count; //total stream count (reduced to 1 byte)
be_t<u16> unk1; //== 1 (?????)
be_t<u32> table_data_size; //== table_size - 0x20 == 0x14 + (0x30 * total_stream_num) (?????)
//TODO: check relative offset of stream structs (could be from 0x0c to 0x14, currently 0x14)
@ -245,7 +246,8 @@ int cellPamfGetStreamOffsetAndSize(mem_ptr_t<PamfHeader> pAddr, u64 fileSize, me
cellPamf.Warning("cellPamfGetStreamOffsetAndSize(pAddr=0x%x, fileSize=%d, pOffset_addr=0x%x, pSize_addr=0x%x)",
pAddr.GetAddr(), fileSize, pOffset.GetAddr(), pSize.GetAddr());
pOffset = (u64)pAddr->data_offset << 11;
const u64 size = (u64)pAddr->data_offset << 11;
pOffset = size;
pSize = (u64)pAddr->data_size << 11;
return CELL_OK;
}
@ -327,6 +329,9 @@ int cellPamfReaderGetNumberOfSpecificStreams(mem_ptr_t<CellPamfReader> pSelf, u8
int counts[6] = {0, 0, 0, 0, 0, 0};
/*if (!pAddr->magic)
return 1; /*hack*/
for (int i = 0; i < pAddr->stream_count; i++)
{
switch (pAddr->stream_headers[i].type)
@ -338,6 +343,7 @@ int cellPamfReaderGetNumberOfSpecificStreams(mem_ptr_t<CellPamfReader> pSelf, u8
default:
cellPamf.Error("cellPamfReaderGetNumberOfSpecificStreams: unsupported stream type found(0x%x)",
pAddr->stream_headers[i].type);
break;
}
}
@ -356,7 +362,7 @@ int cellPamfReaderGetNumberOfSpecificStreams(mem_ptr_t<CellPamfReader> pSelf, u8
return counts[CELL_PAMF_STREAM_TYPE_ATRAC3PLUS] +
counts[CELL_PAMF_STREAM_TYPE_PAMF_LPCM] + counts[CELL_PAMF_STREAM_TYPE_AC3];
default:
return 0;
return 0;
}
}
@ -394,6 +400,9 @@ int cellPamfReaderSetStreamWithTypeAndIndex(mem_ptr_t<CellPamfReader> pSelf, u8
u32 found = 0;
/*if (!pAddr->magic)
return 0; /*hack*/
for (int i = 0; i < pAddr->stream_count; i++)
{
switch (pAddr->stream_headers[i].type)

View File

@ -1,9 +1,12 @@
#include "stdafx.h"
#include "Emu/SysCalls/SysCalls.h"
#include "Emu/SysCalls/SC_FUNC.h"
#include <mutex>
void cellSync_init();
Module cellSync(0x0054, cellSync_init);
void cellSync_unload();
Module cellSync("cellSync", cellSync_init, nullptr, cellSync_unload);
std::mutex g_SyncMutex;
// Return Codes
enum
@ -22,73 +25,122 @@ enum
CELL_SYNC_ERROR_NO_SPU_CONTEXT_STORAGE = 0x80410114,
};
int cellSyncMutexInitialize(mem32_t mutex)
#pragma pack(push, 1)
struct CellSyncMutex {
union {
struct {
be_t<u16> m_freed;
be_t<u16> m_order;
};
volatile u32 m_data;
};
/*
(???) Initialize: set zeros
(???) Lock: increase m_order and wait until m_freed == old m_order
(???) Unlock: increase m_freed
(???) TryLock: ?????
*/
};
#pragma pack(pop)
int cellSyncMutexInitialize(mem_ptr_t<CellSyncMutex> mutex)
{
const u32 mutex_addr = mutex.GetAddr();
if (!mutex_addr)
cellSync.Log("cellSyncMutexInitialize(mutex=0x%x)", mutex.GetAddr());
if (!mutex.IsGood())
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (mutex_addr % 4)
if (mutex.GetAddr() % 4)
{
return CELL_SYNC_ERROR_ALIGN;
}
mutex = 0;
{ // global mutex
std::lock_guard<std::mutex> lock(g_SyncMutex); //???
mutex->m_data = 0;
return CELL_OK;
}
}
int cellSyncMutexLock(mem_ptr_t<CellSyncMutex> mutex)
{
cellSync.Log("cellSyncMutexLock(mutex=0x%x)", mutex.GetAddr());
if (!mutex.IsGood())
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (mutex.GetAddr() % 4)
{
return CELL_SYNC_ERROR_ALIGN;
}
be_t<u16> old_order;
{ // global mutex
std::lock_guard<std::mutex> lock(g_SyncMutex);
old_order = mutex->m_order;
mutex->m_order = mutex->m_order + 1;
}
int counter = 0;
while (*(u16*)&old_order != *(u16*)&mutex->m_freed)
{
Sleep(1);
if (++counter >= 5000)
{
Emu.Pause();
cellSync.Error("cellSyncMutexLock(mutex=0x%x, old_order=%d, order=%d, freed=%d): TIMEOUT",
mutex.GetAddr(), (u16)old_order, (u16)mutex->m_order, (u16)mutex->m_freed);
break;
}
}
//while (_InterlockedExchange((volatile long*)&mutex->m_data, 1)) Sleep(1);
_mm_mfence();
return CELL_OK;
}
int cellSyncMutexLock(mem32_t mutex)
int cellSyncMutexTryLock(mem_ptr_t<CellSyncMutex> mutex)
{
const u32 mutex_addr = mutex.GetAddr();
if (!mutex_addr)
cellSync.Log("cellSyncMutexTryLock(mutex=0x%x)", mutex.GetAddr());
if (!mutex.IsGood())
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (mutex_addr % 4)
if (mutex.GetAddr() % 4)
{
return CELL_SYNC_ERROR_ALIGN;
}
while (_InterlockedExchange((volatile long*)Memory.VirtualToRealAddr(mutex_addr), 1 << 24));
//need to check how does SPU work with these mutexes, also obtainment order is not guaranteed
_mm_lfence();
return CELL_OK;
{ /* global mutex */
std::lock_guard<std::mutex> lock(g_SyncMutex);
if (mutex->m_order != mutex->m_freed)
{
return CELL_SYNC_ERROR_BUSY;
}
mutex->m_order = mutex->m_order + 1;
return CELL_OK;
}
}
int cellSyncMutexTryLock(mem32_t mutex)
int cellSyncMutexUnlock(mem_ptr_t<CellSyncMutex> mutex)
{
const u32 mutex_addr = mutex.GetAddr();
if (!mutex_addr)
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (mutex_addr % 4)
{
return CELL_SYNC_ERROR_ALIGN;
}
//check cellSyncMutexLock
if (_InterlockedExchange((volatile long*)Memory.VirtualToRealAddr(mutex_addr), 1 << 24))
{
return CELL_SYNC_ERROR_BUSY;
}
_mm_lfence();
return CELL_OK;
}
cellSync.Log("cellSyncMutexUnlock(mutex=0x%x)", mutex.GetAddr());
int cellSyncMutexUnlock(mem32_t mutex)
{
const u32 mutex_addr = mutex.GetAddr();
if (!mutex_addr)
if (!mutex.IsGood())
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (mutex_addr % 4)
if (mutex.GetAddr() % 4)
{
return CELL_SYNC_ERROR_ALIGN;
}
//check cellSyncMutexLock
_mm_sfence();
_InterlockedExchange((volatile long*)Memory.VirtualToRealAddr(mutex_addr), 0);
return CELL_OK;
{ /* global mutex */
std::lock_guard<std::mutex> lock(g_SyncMutex);
mutex->m_freed = mutex->m_freed + 1;
return CELL_OK;
}
}
void cellSync_init()
@ -97,4 +149,9 @@ void cellSync_init()
cellSync.AddFunc(0x1bb675c2, cellSyncMutexLock);
cellSync.AddFunc(0xd06918c4, cellSyncMutexTryLock);
cellSync.AddFunc(0x91f2b7b0, cellSyncMutexUnlock);
}
void cellSync_unload()
{
g_SyncMutex.unlock();
}

View File

@ -106,9 +106,6 @@ enum
CELL_SYSUTIL_PAD_RUMBLE_ON = 1,
};
void cellSysutil_init();
Module cellSysutil(0x0015, cellSysutil_init);
enum
{
@ -132,6 +129,11 @@ enum CellMsgDialogType
CELL_MSGDIALOG_DEFAULT_CURSOR_NO = 0x00000100,
};
typedef void (*CellMsgDialogCallback)(int buttonType, mem_ptr_t<void> userData);
void cellSysutil_init();
Module cellSysutil(0x0015, cellSysutil_init);
int cellSysutilGetSystemParamInt(int id, mem32_t value)
{
cellSysutil.Log("cellSysutilGetSystemParamInt(id=0x%x, value_addr=0x%x)", id, value.GetAddr());
@ -232,14 +234,18 @@ int cellSysutilGetSystemParamString(s32 id, mem_list_ptr_t<u8> buf, u32 bufsize)
if (!buf.IsGood())
return CELL_EFAULT;
memset(buf, 0, bufsize);
switch(id)
{
case CELL_SYSUTIL_SYSTEMPARAM_ID_NICKNAME:
cellSysutil.Warning("cellSysutilGetSystemParamString: CELL_SYSUTIL_SYSTEMPARAM_ID_NICKNAME");
memcpy(buf, "Unknown", 8); //for example
break;
case CELL_SYSUTIL_SYSTEMPARAM_ID_CURRENT_USERNAME:
cellSysutil.Warning("cellSysutilGetSystemParamString: CELL_SYSUTIL_SYSTEMPARAM_ID_CURRENT_USERNAME");
memcpy(buf, "Unknown", 8);
break;
default:
@ -477,7 +483,7 @@ int cellSysutilUnregisterCallback(int slot)
return CELL_OK;
}
int cellMsgDialogOpen2(u32 type, char* msgString, u32 callback_addr, u32 userData, u32 extParam)
int cellMsgDialogOpen2(u32 type, char* msgString, mem_func_ptr_t<CellMsgDialogCallback> callback, mem_ptr_t<void> userData, u32 extParam)
{
long style = 0;
@ -520,17 +526,16 @@ int cellMsgDialogOpen2(u32 type, char* msgString, u32 callback_addr, u32 userDat
break;
}
Callback2 callback(0, callback_addr, userData);
callback.Handle(status);
callback.Branch(true);
if(callback)
callback(status, userData);
return CELL_OK;
}
int cellMsgDialogOpenErrorCode(u32 errorCode, u32 callback_addr, u32 userData, u32 extParam)
int cellMsgDialogOpenErrorCode(u32 errorCode, mem_func_ptr_t<CellMsgDialogCallback> callback, mem_ptr_t<void> userData, u32 extParam)
{
cellSysutil.Warning("cellMsgDialogOpenErrorCode(errorCode=0x%x, callback_addr=0x%x, userData=%d, extParam=%d)",
errorCode, callback_addr, userData, extParam);
errorCode, callback.GetAddr(), userData, extParam);
std::string errorMessage;
switch(errorCode)
@ -622,10 +627,8 @@ int cellMsgDialogOpenErrorCode(u32 errorCode, u32 callback_addr, u32 userData, u
break;
}
// TODO: The following lines produce an infinite loop of cellMsgDialogOpenErrorCode's
/*Callback2 callback(0, callback_addr, userData);
callback.Handle(status);
callback.Branch(true);*/
if(callback)
callback(status, userData);
return CELL_OK;
}
@ -649,7 +652,7 @@ int cellAudioOutGetSoundAvailability(u32 audioOut, u32 type, u32 fs, u32 option)
case CELL_AUDIO_OUT_FS_192KHZ:
break;
default: CELL_AUDIO_OUT_ERROR_UNSUPPORTED_SOUND_MODE;
default: return CELL_AUDIO_OUT_ERROR_UNSUPPORTED_SOUND_MODE;
}
switch(type)
@ -659,7 +662,7 @@ int cellAudioOutGetSoundAvailability(u32 audioOut, u32 type, u32 fs, u32 option)
case CELL_AUDIO_OUT_CODING_TYPE_DTS:
break;
default: CELL_AUDIO_OUT_ERROR_UNSUPPORTED_SOUND_MODE;
default: return CELL_AUDIO_OUT_ERROR_UNSUPPORTED_SOUND_MODE;
}
switch(audioOut)
@ -668,8 +671,7 @@ int cellAudioOutGetSoundAvailability(u32 audioOut, u32 type, u32 fs, u32 option)
case CELL_AUDIO_OUT_SECONDARY: return 0;
}
CELL_AUDIO_OUT_ERROR_ILLEGAL_CONFIGURATION;
return CELL_AUDIO_OUT_ERROR_ILLEGAL_CONFIGURATION;
}
int cellAudioOutGetSoundAvailability2(u32 audioOut, u32 type, u32 fs, u32 ch, u32 option)
@ -690,7 +692,7 @@ int cellAudioOutGetSoundAvailability2(u32 audioOut, u32 type, u32 fs, u32 ch, u3
case CELL_AUDIO_OUT_FS_192KHZ:
break;
default: CELL_AUDIO_OUT_ERROR_UNSUPPORTED_SOUND_MODE;
default: return CELL_AUDIO_OUT_ERROR_UNSUPPORTED_SOUND_MODE;
}
switch(ch)
@ -700,7 +702,7 @@ int cellAudioOutGetSoundAvailability2(u32 audioOut, u32 type, u32 fs, u32 ch, u3
case 8:
break;
default: CELL_AUDIO_OUT_ERROR_UNSUPPORTED_SOUND_MODE;
default: return CELL_AUDIO_OUT_ERROR_UNSUPPORTED_SOUND_MODE;
}
switch(type)
@ -710,7 +712,7 @@ int cellAudioOutGetSoundAvailability2(u32 audioOut, u32 type, u32 fs, u32 ch, u3
case CELL_AUDIO_OUT_CODING_TYPE_DTS:
break;
default: CELL_AUDIO_OUT_ERROR_UNSUPPORTED_SOUND_MODE;
default: return CELL_AUDIO_OUT_ERROR_UNSUPPORTED_SOUND_MODE;
}
switch(audioOut)
@ -719,8 +721,7 @@ int cellAudioOutGetSoundAvailability2(u32 audioOut, u32 type, u32 fs, u32 ch, u3
case CELL_AUDIO_OUT_SECONDARY: return 0;
}
CELL_AUDIO_OUT_ERROR_ILLEGAL_CONFIGURATION;
return CELL_AUDIO_OUT_ERROR_ILLEGAL_CONFIGURATION;
}
int cellAudioOutGetState(u32 audioOut, u32 deviceIndex, u32 state_addr)
@ -831,7 +832,7 @@ int cellAudioOutGetNumberOfDevice(u32 audioOut)
case CELL_AUDIO_OUT_SECONDARY: return 0;
}
CELL_AUDIO_OUT_ERROR_UNSUPPORTED_AUDIO_OUT;
return CELL_AUDIO_OUT_ERROR_UNSUPPORTED_AUDIO_OUT;
}
int cellAudioOutGetDeviceInfo(u32 audioOut, u32 deviceIndex, mem_ptr_t<CellAudioOutDeviceInfo> info)
@ -863,7 +864,7 @@ int cellAudioOutSetCopyControl(u32 audioOut, u32 control)
case CELL_AUDIO_OUT_SECONDARY:
break;
default: CELL_AUDIO_OUT_ERROR_UNSUPPORTED_AUDIO_OUT;
default: return CELL_AUDIO_OUT_ERROR_UNSUPPORTED_AUDIO_OUT;
}
switch(control)
@ -873,7 +874,7 @@ int cellAudioOutSetCopyControl(u32 audioOut, u32 control)
case CELL_AUDIO_OUT_COPY_CONTROL_COPY_NEVER:
break;
default: CELL_AUDIO_OUT_ERROR_ILLEGAL_PARAMETER;
default: return CELL_AUDIO_OUT_ERROR_ILLEGAL_PARAMETER;
}
return CELL_AUDIO_OUT_SUCCEEDED;

View File

@ -81,11 +81,12 @@ int sys_spu_image_import(mem_ptr_t<sys_spu_image> img, u32 src, u32 type)
}
vfsStreamMemory f(src);
u32 entry = LoadSpuImage(f);
u32 entry;
u32 offset = LoadSpuImage(f, entry);
img->type = 1;
img->type = type;
img->entry_point = entry;
img->segs_addr = 0x0;
img->segs_addr = offset;
img->nsegs = 0;
return CELL_OK;
@ -119,15 +120,13 @@ int sys_raw_spu_load(int id, u32 path_addr, mem32_t entry)
return CELL_OK;
}
extern u64 g_last_spu_offset;
int sys_raw_spu_image_load(int id, mem_ptr_t<sys_spu_image> img)
{
sysPrxForUser.Warning("sys_raw_spu_image_load(id=0x%x, img_addr=0x%x)", id, img.GetAddr());
memcpy(Memory + RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * id, Memory + g_last_spu_offset, 256 * 1024);
memcpy(Memory + RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * id, Memory + (u32)img->segs_addr, 256 * 1024);
Memory.Write32(RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * id + RAW_SPU_PROB_OFFSET + SPU_NPC_offs,
img->entry_point - g_last_spu_offset);
(u32)img->entry_point);
return CELL_OK;
}

View File

@ -3,7 +3,10 @@
#include "Emu/SysCalls/SC_FUNC.h"
void sys_fs_init();
Module sys_fs(0x000e, sys_fs_init);
void sys_fs_unload();
Module sys_fs(0x000e, sys_fs_init, nullptr, sys_fs_unload);
std::atomic<u32> g_FsAioReadID = 0;
Array<vfsStream*> FDs;
bool sdata_check(u32 version, u32 flags, u64 filesizeInput, u64 filesizeTmp)
{
@ -135,6 +138,80 @@ int cellFsSdataOpen(u32 path_addr, int flags, mem32_t fd, mem32_t arg, u64 size)
return CELL_OK;
}
void fsAioRead(u32 fd, mem_ptr_t<CellFsAio> aio, int xid, mem_func_ptr_t<void (*)(u32 xaio_addr, u32 error, int xid, u64 size)> func)
{
vfsFileBase& orig_file = *(vfsFileBase*)FDs[fd];
const wxString path = orig_file.GetPath().AfterFirst('/');
u64 nbytes = (u64)aio->size;
const u32 buf_addr = (u32)aio->buf_addr;
u64 res;
u32 error;
if(Memory.IsGoodAddr(buf_addr))
{
//open the file again (to prevent access conflicts roughly)
vfsLocalFile file(path, vfsRead);
if(!Memory.IsGoodAddr(buf_addr, nbytes))
{
MemoryBlock& block = Memory.GetMemByAddr(buf_addr);
nbytes = block.GetSize() - (buf_addr - block.GetStartAddr());
}
file.Seek((u64)aio->offset);
res = nbytes ? file.Read(Memory.GetMemFromAddr(buf_addr), nbytes) : 0;
error = CELL_OK;
}
else
{
res = 0;
error = CELL_EFAULT;
}
//start callback thread
//if(func)
//func.async(aio.GetAddr(), error, xid, res);
ConLog.Warning("*** fsAioRead(fd=%d, offset=0x%llx, buf_addr=0x%x, size=%d, res=%d, xid=%d [%s])",
fd, (u64)aio->offset, buf_addr, (u64)aio->size, res, xid, path.c_str());
}
int cellFsAioRead(mem_ptr_t<CellFsAio> aio, mem32_t aio_id, mem_func_ptr_t<void (*)(u32 xaio_addr, u32 error, int xid, u64 size)> func)
{
sys_fs.Warning("cellFsAioRead(aio_addr=0x%x, id_addr=0x%x, func_addr=0x%x)", aio.GetAddr(), aio_id.GetAddr(), func.GetAddr());
//ID id;
u32 fd = (u32)aio->fd;
//if(!sys_fs.CheckId(fd, id)) return CELL_ESRCH;
if (fd >= FDs.GetCount()) return CELL_ESRCH;
if (FDs[fd] == nullptr) return CELL_ESRCH;
//vfsFileBase& orig_file = *(vfsFileBase*)id.m_data;
vfsFileBase& orig_file = *(vfsFileBase*)FDs[fd];
//get a unique id for the callback
const u32 xid = g_FsAioReadID++;
aio_id = xid;
//std::thread t(fsAioRead, fd, aio, xid, func);
//t.detach();
//read data immediately (actually it should be read in special thread):
fsAioRead(fd, aio, xid, func);
return CELL_OK;
}
int cellFsAioInit(mem8_ptr_t mount_point)
{
sys_fs.Warning("cellFsAioInit(mount_point_addr=0x%x)", mount_point.GetAddr());
return CELL_OK;
}
int cellFsAioFinish(mem8_ptr_t mount_point)
{
sys_fs.Warning("cellFsAioFinish(mount_point_addr=0x%x)", mount_point.GetAddr());
return CELL_OK;
}
void sys_fs_init()
{
sys_fs.AddFunc(0x718bf5f8, cellFsOpen);
@ -155,6 +232,20 @@ void sys_fs_init()
sys_fs.AddFunc(0x0e2939e5, cellFsFtruncate);
sys_fs.AddFunc(0xc9dc3ac5, cellFsTruncate);
sys_fs.AddFunc(0xcb588dba, cellFsFGetBlockSize);
sys_fs.AddFunc(0xc1c507e7, cellFsAioRead);
sys_fs.AddFunc(0xdb869f20, cellFsAioInit);
sys_fs.AddFunc(0x9f951810, cellFsAioFinish);
}
void sys_fs_unload()
{
for (u32 i = 0; i < FDs.GetCount(); i++)
{
if (FDs[i])
{
FDs[i]->Close();
delete FDs[i];
}
}
FDs.Clear();
}

View File

@ -302,6 +302,8 @@ public:
virtual void operator()() { declCPU(); m_call(ARG(1), ARG(2), ARG(3), ARG(4), ARG(5), ARG(6), ARG(7), ARG(8), ARG(9), ARG(10), ARG(11), ARG(12)); }
};
#undef ARG
template<typename TR>
func_caller* bind_func(TR (*call)())
{
@ -379,5 +381,3 @@ func_caller* bind_func(TR (*call)(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
{
return new binder_func_12<TR, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12>(call);
}
#undef ARG(n)

View File

@ -225,7 +225,6 @@ extern int cellFsLseek(u32 fd, s64 offset, u32 whence, mem64_t pos);
extern int cellFsFtruncate(u32 fd, u64 size);
extern int cellFsTruncate(u32 path_addr, u64 size);
extern int cellFsFGetBlockSize(u32 fd, mem64_t sector_size, mem64_t block_size);
extern int cellFsAioRead(mem_ptr_t<CellFsAio> aio, mem32_t id, u32 func_addr);
//cellVideo
extern int cellVideoOutGetState(u32 videoOut, u32 deviceIndex, u32 state_addr);

View File

@ -3,6 +3,7 @@
#include "Emu/SysCalls/SysCalls.h"
extern Module sys_fs;
extern Array<vfsStream*> FDs;
int cellFsOpen(u32 path_addr, int flags, mem32_t fd, mem32_t arg, u64 size)
{
@ -94,7 +95,9 @@ int cellFsOpen(u32 path_addr, int flags, mem32_t fd, mem32_t arg, u64 size)
return CELL_ENOENT;
}
fd = sys_fs.GetNewId(stream, flags);
fd = FDs.AddCpy(stream);
//fd = sys_fs.GetNewId(stream, flags);
ConLog.Warning("*** cellFsOpen(path: %s): fd=%d", path.mb_str(), fd.GetValue());
return CELL_OK;
}
@ -103,9 +106,12 @@ int cellFsRead(u32 fd, u32 buf_addr, u64 nbytes, mem64_t nread)
{
sys_fs.Log("cellFsRead(fd: %d, buf_addr: 0x%x, nbytes: 0x%llx, nread_addr: 0x%x)",
fd, buf_addr, nbytes, nread.GetAddr());
ID id;
if(!sys_fs.CheckId(fd, id)) return CELL_ESRCH;
vfsStream& file = *(vfsStream*)id.m_data;
//ID id;
//if(!sys_fs.CheckId(fd, id)) return CELL_ESRCH;
if (fd >= FDs.GetCount()) return CELL_ESRCH;
if (FDs[fd] == nullptr) return CELL_ESRCH;
//vfsStream& file = *(vfsStream*)id.m_data;
vfsStream& file = *(vfsStream*)FDs[fd];
if(Memory.IsGoodAddr(buf_addr) && !Memory.IsGoodAddr(buf_addr, nbytes))
{
@ -125,9 +131,13 @@ int cellFsWrite(u32 fd, u32 buf_addr, u64 nbytes, mem64_t nwrite)
{
sys_fs.Log("cellFsWrite(fd: %d, buf_addr: 0x%x, nbytes: 0x%llx, nwrite_addr: 0x%x)",
fd, buf_addr, nbytes, nwrite.GetAddr());
ID id;
if(!sys_fs.CheckId(fd, id)) return CELL_ESRCH;
vfsStream& file = *(vfsStream*)id.m_data;
//ID id;
//if(!sys_fs.CheckId(fd, id)) return CELL_ESRCH;
if (fd >= FDs.GetCount()) return CELL_ESRCH;
if (FDs[fd] == nullptr) return CELL_ESRCH;
//vfsStream& file = *(vfsStream*)id.m_data;
vfsStream& file = *(vfsStream*)FDs[fd];
if(Memory.IsGoodAddr(buf_addr) && !Memory.IsGoodAddr(buf_addr, nbytes))
{
MemoryBlock& block = Memory.GetMemByAddr(buf_addr);
@ -144,12 +154,17 @@ int cellFsWrite(u32 fd, u32 buf_addr, u64 nbytes, mem64_t nwrite)
int cellFsClose(u32 fd)
{
sys_fs.Log("cellFsClose(fd: %d)", fd);
ID id;
if(!sys_fs.CheckId(fd, id)) return CELL_ESRCH;
vfsStream& file = *(vfsStream*)id.m_data;
sys_fs.Warning("cellFsClose(fd: %d)", fd);
//ID id;
//if(!sys_fs.CheckId(fd, id)) return CELL_ESRCH;
if (fd >= FDs.GetCount()) return CELL_ESRCH;
if (FDs[fd] == nullptr) return CELL_ESRCH;
//vfsStream& file = *(vfsStream*)id.m_data;
vfsStream& file = *(vfsStream*)FDs[fd];
file.Close();
Emu.GetIdManager().RemoveID(fd);
delete FDs[fd];
//Emu.GetIdManager().RemoveID(fd);
FDs[fd] = nullptr;
return CELL_OK;
}
@ -231,9 +246,12 @@ int cellFsStat(const u32 path_addr, mem_ptr_t<CellFsStat> sb)
int cellFsFstat(u32 fd, mem_ptr_t<CellFsStat> sb)
{
sys_fs.Log("cellFsFstat(fd: %d, sb_addr: 0x%x)", fd, sb.GetAddr());
ID id;
if(!sys_fs.CheckId(fd, id)) return CELL_ESRCH;
vfsStream& file = *(vfsStream*)id.m_data;
//ID id;
//if(!sys_fs.CheckId(fd, id)) return CELL_ESRCH;
if (fd >= FDs.GetCount()) return CELL_ESRCH;
if (FDs[fd] == nullptr) return CELL_ESRCH;
//vfsStream& file = *(vfsStream*)id.m_data;
vfsStream& file = *(vfsStream*)FDs[fd];
sb->st_mode =
CELL_FS_S_IRUSR | CELL_FS_S_IWUSR | CELL_FS_S_IXUSR |
@ -312,9 +330,12 @@ int cellFsLseek(u32 fd, s64 offset, u32 whence, mem64_t pos)
sys_fs.Error(fd, "Unknown seek whence! (%d)", whence);
return CELL_EINVAL;
}
ID id;
if(!sys_fs.CheckId(fd, id)) return CELL_ESRCH;
vfsStream& file = *(vfsStream*)id.m_data;
//ID id;
//if(!sys_fs.CheckId(fd, id)) return CELL_ESRCH;
if (fd >= FDs.GetCount()) return CELL_ESRCH;
if (FDs[fd] == nullptr) return CELL_ESRCH;
//vfsStream& file = *(vfsStream*)id.m_data;
vfsStream& file = *(vfsStream*)FDs[fd];
pos = file.Seek(offset, seek_mode);
return CELL_OK;
}
@ -322,9 +343,12 @@ int cellFsLseek(u32 fd, s64 offset, u32 whence, mem64_t pos)
int cellFsFtruncate(u32 fd, u64 size)
{
sys_fs.Log("cellFsFtruncate(fd: %d, size: %lld)", fd, size);
ID id;
if(!sys_fs.CheckId(fd, id)) return CELL_ESRCH;
vfsStream& file = *(vfsStream*)id.m_data;
//ID id;
//if(!sys_fs.CheckId(fd, id)) return CELL_ESRCH;
if (fd >= FDs.GetCount()) return CELL_ESRCH;
if (FDs[fd] == nullptr) return CELL_ESRCH;
//vfsStream& file = *(vfsStream*)id.m_data;
vfsStream& file = *(vfsStream*)FDs[fd];
u64 initialSize = file.GetSize();
if (initialSize < size)
@ -385,49 +409,3 @@ int cellFsFGetBlockSize(u32 fd, mem64_t sector_size, mem64_t block_size)
return CELL_OK;
}
std::atomic<u32> g_FsAioReadID = 0;
int cellFsAioRead(mem_ptr_t<CellFsAio> aio, mem32_t aio_id, u32 func_addr)
{
sys_fs.Warning("cellFsAioRead(aio_addr: 0x%x, id_addr: 0x%x, func_addr: 0x%x)", aio.GetAddr(), aio_id.GetAddr(), func_addr);
ID id;
u32 fd = (u32)aio->fd;
if(!sys_fs.CheckId(fd, id)) return CELL_ESRCH;
vfsFileBase& orig_file = *(vfsFileBase*)id.m_data;
//open the file again (to prevent access conflicts roughly)
vfsStream file = *Emu.GetVFS().Open(orig_file.GetPath(), vfsRead);
u64 nbytes = (u64)aio->size;
const u32 buf_addr = (u32)aio->buf_addr;
if(Memory.IsGoodAddr(buf_addr) && !Memory.IsGoodAddr(buf_addr, nbytes))
{
MemoryBlock& block = Memory.GetMemByAddr(buf_addr);
nbytes = block.GetSize() - (buf_addr - block.GetStartAddr());
}
//read data immediately (actually it should be read in special thread)
file.Seek((u64)aio->offset);
const u64 res = nbytes ? file.Read(Memory.GetMemFromAddr(buf_addr), nbytes) : 0;
file.Close();
//get a unique id for the callback
const u32 xid = g_FsAioReadID++;
aio_id = xid;
//TODO: init the callback
/*CPUThread& new_thread = Emu.GetCPU().AddThread(CPU_THREAD_PPU);
new_thread.SetEntry(func_addr);
new_thread.SetPrio(1001);
new_thread.SetStackSize(0x10000);
new_thread.SetName("FsAioReadCallback");
new_thread.SetArg(0, aio.GetAddr()); //xaio
new_thread.SetArg(1, CELL_OK); //error code
new_thread.SetArg(2, xid); //xid (unique id)
new_thread.SetArg(3, res); //size (bytes read)
new_thread.Run();
new_thread.Exec();*/
return CELL_OK;
}

View File

@ -6,20 +6,26 @@ SysCallBase sc_mem("memory");
int sys_memory_container_create(u32 cid_addr, u32 yield_size)
{
sc_mem.Warning("sys_memory_container_create(cid_addr=0x%x,yield_size=0x%x)", cid_addr, yield_size);
sc_mem.Warning("(HACK!) sys_memory_container_create(cid_addr=0x%x,yield_size=0x%x)", cid_addr, yield_size);
if(!Memory.IsGoodAddr(cid_addr, 4))
{
return CELL_EFAULT;
}
u64 addr = Memory.Alloc(yield_size, 1);
yield_size &= ~0xfffff; //round down to 1 MB granularity
//alignment hack (Memory.Alloc does not support alignment yet): alloc size is increased
u64 addr = Memory.Alloc(yield_size + 0x100000, 0x100000); //1 MB alignment (???)
if(!addr)
{
return CELL_ENOMEM;
}
//fix alignment:
addr = (addr + 0x100000) & ~0xfffff;
Memory.Write32(cid_addr, sc_mem.GetNewId(new MemoryContainerInfo(addr, yield_size)));
return CELL_OK;
}
@ -43,18 +49,20 @@ int sys_memory_container_destroy(u32 cid)
int sys_memory_allocate(u32 size, u32 flags, u32 alloc_addr_addr)
{
//0x30000100;
sc_mem.Log("sys_memory_allocate(size=0x%x, flags=0x%x)", size, flags);
sc_mem.Warning("(HACK!) sys_memory_allocate(size=0x%x, flags=0x%x)", size, flags);
u32 addr;
switch(flags)
{
case SYS_MEMORY_PAGE_SIZE_1M:
if(size & 0xfffff) return CELL_EALIGN;
addr = Memory.Alloc(size, 0x100000);
addr = Memory.Alloc(size + 0x100000, 0x100000);
addr = (addr + 0x100000) & ~0xfffff;
break;
case SYS_MEMORY_PAGE_SIZE_64K:
if(size & 0xffff) return CELL_EALIGN;
addr = Memory.Alloc(size, 0x10000);
addr = Memory.Alloc(size + 0x10000, 0x10000);
addr = (addr + 0x10000) & ~0xffff;
break;
default: return CELL_EINVAL;

View File

@ -107,13 +107,36 @@ int cellPadGetData(u32 port_no, u32 data_addr)
}
}
u16 lx = 128;
u16 ly = 128;
u16 rx = 128;
u16 ry = 128;
const Array<AnalogStick>& sticks = pads[port_no].m_sticks;
for (u32 s = 0; s < sticks.GetCount(); s++)
{
u16* res;
switch (sticks[s].m_offset)
{
case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X: res = &lx; break;
case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y: res = &ly; break;
case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X: res = &rx; break;
case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y: res = &ry; break;
default: continue;
}
if (sticks[s].m_max_pressed && !sticks[s].m_min_pressed)
*res = 255;
if (sticks[s].m_min_pressed && !sticks[s].m_max_pressed)
*res = 0;
}
data.len = re(len);
data.button[CELL_PAD_BTN_OFFSET_DIGITAL1] = re(d1);
data.button[CELL_PAD_BTN_OFFSET_DIGITAL2] = re(d2);
data.button[CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X] = re(pad.m_analog_right_x);
data.button[CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y] = re(pad.m_analog_right_y);
data.button[CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X] = re(pad.m_analog_left_x);
data.button[CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y] = re(pad.m_analog_left_y);
data.button[CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X] = re(rx);
data.button[CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y] = re(ry);
data.button[CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X] = re(lx);
data.button[CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y] = re(ly);
data.button[CELL_PAD_BTN_OFFSET_PRESS_RIGHT] = re(pad.m_press_right);
data.button[CELL_PAD_BTN_OFFSET_PRESS_LEFT] = re(pad.m_press_left);
data.button[CELL_PAD_BTN_OFFSET_PRESS_UP] = re(pad.m_press_up);

View File

@ -23,18 +23,33 @@ struct SpuGroupInfo
}
};
u64 g_last_spu_offset = 0;
u32 LoadSpuImage(vfsStream& stream)
u32 LoadSpuImage(vfsStream& stream, u32& spu_ep)
{
ELFLoader l(stream);
l.LoadInfo();
u32 alloc_size = 0xFFFFED - stream.GetSize();
g_last_spu_offset = Memory.MainMem.Alloc(alloc_size);
l.LoadData(g_last_spu_offset);
return g_last_spu_offset + l.GetEntry();
const u32 alloc_size = 256 * 1024 /*0x1000000 - stream.GetSize()*/;
u32 spu_offset = Memory.MainMem.Alloc(alloc_size);
l.LoadData(spu_offset);
spu_ep = l.GetEntry();
return spu_offset;
}
/*u64 g_last_spu_offset = 0;
static const u64 g_spu_alloc_size = 0x1000000;
u32 LoadSpuImage(vfsStream& stream, u64 address)
{
ELFLoader l(stream);
l.LoadInfo();
l.LoadData(address);
return address + l.GetEntry();
}
u32 LoadSpuImage(vfsStream& stream)
{
g_last_spu_offset = Memory.MainMem.Alloc(g_spu_alloc_size);
return LoadSpuImage(stream, g_last_spu_offset);
}*/
//156
int sys_spu_image_open(mem_ptr_t<sys_spu_image> img, u32 path_addr)
@ -54,11 +69,12 @@ int sys_spu_image_open(mem_ptr_t<sys_spu_image> img, u32 path_addr)
return CELL_ENOENT;
}
u32 entry = LoadSpuImage(f);
u32 entry;
u32 offset = LoadSpuImage(f, entry);
img->type = 1;
img->entry_point = entry;
img->segs_addr = 0x0;
img->segs_addr = offset;
img->nsegs = 0;
return CELL_OK;
@ -97,7 +113,7 @@ int sys_spu_thread_initialize(mem32_t thread, u32 group, u32 spu_num, mem_ptr_t<
return CELL_EBUSY;
}
u32 ls_entry = img->entry_point - g_last_spu_offset;
u32 spu_ep = (u32)img->entry_point;
std::string name = Memory.ReadString(attr->name_addr, attr->name_len).mb_str();
u64 a1 = arg->arg1;
u64 a2 = arg->arg2;
@ -107,10 +123,10 @@ int sys_spu_thread_initialize(mem32_t thread, u32 group, u32 spu_num, mem_ptr_t<
CPUThread& new_thread = Emu.GetCPU().AddThread(CPU_THREAD_SPU);
//copy SPU image:
u32 spu_offset = Memory.MainMem.Alloc(256 * 1024);
memcpy(Memory + spu_offset, Memory + g_last_spu_offset, 256 * 1024);
memcpy(Memory + spu_offset, Memory + (u32)img->segs_addr, 256 * 1024);
//initialize from new place:
new_thread.SetOffset(spu_offset);
new_thread.SetEntry(ls_entry);
new_thread.SetEntry(spu_ep);
new_thread.SetName(name);
new_thread.SetArg(0, a1);
new_thread.SetArg(1, a2);
@ -122,15 +138,16 @@ int sys_spu_thread_initialize(mem32_t thread, u32 group, u32 spu_num, mem_ptr_t<
group_info.threads[spu_num] = &new_thread;
ConLog.Write("New SPU Thread:");
ConLog.Write("ls_entry = 0x%x", ls_entry);
/*ConLog.Write("New SPU Thread:");
ConLog.Write("SPU img offset = 0x%x", (u32)img->segs_addr);
ConLog.Write("entry_point = 0x%x", spu_ep);
ConLog.Write("name = %s", name.c_str());
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.Write("ls_offset = 0x%x", ((SPUThread&)new_thread).dmac.ls_offset);
ConLog.SkipLn();
ConLog.SkipLn();*/
return CELL_OK;
}

View File

@ -1,6 +1,6 @@
#pragma once
u32 LoadSpuImage(vfsStream& stream);
u32 LoadSpuImage(vfsStream& stream, u32& spu_ep);
enum
{
@ -9,6 +9,13 @@ enum
SYS_SPU_THREAD_GROUP_JOIN_TERMINATED = 0x0004
};
enum
{
SYS_SPU_SEGMENT_TYPE_COPY = 0x0001,
SYS_SPU_SEGMENT_TYPE_FILL = 0x0002,
SYS_SPU_SEGMENT_TYPE_INFO = 0x0004,
};
struct sys_spu_thread_group_attribute
{
be_t<u32> name_len;
@ -35,8 +42,8 @@ struct sys_spu_thread_argument
struct sys_spu_image
{
be_t<u32> type;
be_t<u32> entry_point;
be_t<u32> segs_addr;
be_t<u32> entry_point;
be_t<u32> segs_addr; //temporarily used as offset of LS image after elf loading
be_t<int> nsegs;
};

View File

@ -1,6 +1,5 @@
#include "stdafx.h"
#include "MemoryViewer.h"
#include "Emu/Memory/Memory.h"
MemoryViewerPanel::MemoryViewerPanel(wxWindow* parent)
: wxFrame(parent, wxID_ANY, "Memory Viewer", wxDefaultPosition, wxSize(700, 450))

View File

@ -1,6 +1,5 @@
#include "stdafx.h"
#include "RSXDebugger.h"
#include "Emu/Memory/Memory.h"
#include "Emu/GS/sysutil_video.h"
#include "Emu/GS/GCM.h"
@ -16,6 +15,7 @@ RSXDebugger::RSXDebugger(wxWindow* parent)
: wxFrame(parent, wxID_ANY, "RSX Debugger", wxDefaultPosition, wxSize(700, 450))
, m_item_count(23)
, m_addr(0x0)
, m_cur_texture(0)
, exit(false)
{
this->SetBackgroundColour(wxColour(240,240,240)); //This fix the ugly background color under Windows
@ -25,7 +25,7 @@ RSXDebugger::RSXDebugger(wxWindow* parent)
wxBoxSizer& s_tools = *new wxBoxSizer(wxVERTICAL);
// Controls
wxStaticBoxSizer& s_controls = *new wxStaticBoxSizer(wxHORIZONTAL, this, "Memory Viewer Options");
wxStaticBoxSizer& s_controls = *new wxStaticBoxSizer(wxHORIZONTAL, this, "RSX Debugger Controls");
// Controls: Address
wxStaticBoxSizer& s_controls_addr = *new wxStaticBoxSizer(wxHORIZONTAL, this, "Address:");
@ -101,8 +101,17 @@ RSXDebugger::RSXDebugger(wxWindow* parent)
m_list_flags->InsertColumn(1, "Value", 0, 270);
m_list_lightning->InsertColumn(0, "Name", 0, 170);
m_list_lightning->InsertColumn(1, "Value", 0, 270);
m_list_texture->InsertColumn(0, "Name", 0, 170);
m_list_texture->InsertColumn(1, "Value", 0, 270);
m_list_texture->InsertColumn(0, "Index");
m_list_texture->InsertColumn(1, "Address");
m_list_texture->InsertColumn(2, "Cubemap");
m_list_texture->InsertColumn(3, "Dimension");
m_list_texture->InsertColumn(4, "Enabled");
m_list_texture->InsertColumn(5, "Format");
m_list_texture->InsertColumn(6, "Mipmap");
m_list_texture->InsertColumn(7, "Pitch");
m_list_texture->InsertColumn(8, "Size");
m_list_settings->InsertColumn(0, "Name", 0, 170);
m_list_settings->InsertColumn(1, "Value", 0, 270);
@ -182,22 +191,24 @@ RSXDebugger::RSXDebugger(wxWindow* parent)
SetSizerAndFit(&s_panel);
//Events
Connect(wxID_ANY, wxEVT_KEY_DOWN, wxKeyEventHandler(RSXDebugger::OnKeyDown), NULL, this);
m_app_connector.Connect(wxID_ANY, wxEVT_KEY_DOWN, wxKeyEventHandler(RSXDebugger::OnKeyDown), nullptr, this);
Connect(t_addr->GetId(), wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler(RSXDebugger::OnChangeToolsAddr));
Connect(b_goto_get->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(RSXDebugger::GoToGet));
Connect(b_goto_put->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(RSXDebugger::GoToPut));
p_buffer_colorA->Connect(wxID_ANY, wxEVT_LEFT_DOWN, wxMouseEventHandler(RSXDebugger::OnClickBuffer), NULL, this);
p_buffer_colorB->Connect(wxID_ANY, wxEVT_LEFT_DOWN, wxMouseEventHandler(RSXDebugger::OnClickBuffer), NULL, this);
p_buffer_colorC->Connect(wxID_ANY, wxEVT_LEFT_DOWN, wxMouseEventHandler(RSXDebugger::OnClickBuffer), NULL, this);
p_buffer_colorD->Connect(wxID_ANY, wxEVT_LEFT_DOWN, wxMouseEventHandler(RSXDebugger::OnClickBuffer), NULL, this);
p_buffer_colorA->Connect(wxID_ANY, wxEVT_LEFT_DOWN, wxMouseEventHandler(RSXDebugger::OnClickBuffer), nullptr, this);
p_buffer_colorB->Connect(wxID_ANY, wxEVT_LEFT_DOWN, wxMouseEventHandler(RSXDebugger::OnClickBuffer), nullptr, this);
p_buffer_colorC->Connect(wxID_ANY, wxEVT_LEFT_DOWN, wxMouseEventHandler(RSXDebugger::OnClickBuffer), nullptr, this);
p_buffer_colorD->Connect(wxID_ANY, wxEVT_LEFT_DOWN, wxMouseEventHandler(RSXDebugger::OnClickBuffer), nullptr, this);
//Connect(p_buffer_depth->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(RSXDebugger::OnClickBuffer));
//Connect(p_buffer_stencil->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(RSXDebugger::OnClickBuffer));
p_buffer_tex->Connect(wxID_ANY, wxEVT_LEFT_DOWN, wxMouseEventHandler(RSXDebugger::OnClickBuffer), NULL, this);
p_buffer_tex->Connect(wxID_ANY, wxEVT_LEFT_DOWN, wxMouseEventHandler(RSXDebugger::OnClickBuffer), nullptr, this);
m_list_commands->Connect(wxEVT_MOUSEWHEEL, wxMouseEventHandler(RSXDebugger::OnScrollMemory), NULL, this);
m_list_flags->Connect(wxEVT_COMMAND_LIST_ITEM_ACTIVATED, wxListEventHandler(RSXDebugger::SetFlags), NULL, this);
m_list_commands->Connect(wxEVT_MOUSEWHEEL, wxMouseEventHandler(RSXDebugger::OnScrollMemory), nullptr, this);
m_list_flags->Connect(wxEVT_COMMAND_LIST_ITEM_ACTIVATED, wxListEventHandler(RSXDebugger::SetFlags), nullptr, this);
m_list_texture->Connect(wxID_ANY, wxEVT_COMMAND_LIST_ITEM_ACTIVATED, wxListEventHandler(RSXDebugger::OnSelectTexture), nullptr, this);
//Fill the frame
UpdateInformation();
@ -205,10 +216,15 @@ RSXDebugger::RSXDebugger(wxWindow* parent)
void RSXDebugger::OnKeyDown(wxKeyEvent& event)
{
switch(event.GetKeyCode())
if(wxGetActiveWindow() == wxGetTopLevelParent(this))
{
case WXK_F5: UpdateInformation(); break;
switch(event.GetKeyCode())
{
case WXK_F5: UpdateInformation(); return;
}
}
event.Skip();
}
void RSXDebugger::OnChangeToolsAddr(wxCommandEvent& event)
@ -221,8 +237,34 @@ void RSXDebugger::OnChangeToolsAddr(wxCommandEvent& event)
void RSXDebugger::OnScrollMemory(wxMouseEvent& event)
{
m_addr -= (event.ControlDown() ? m_item_count : 1) * 4 * (event.GetWheelRotation() / event.GetWheelDelta());
t_addr->SetValue(wxString::Format("%08x", m_addr));
if(Memory.IsGoodAddr(m_addr))
{
int items = event.ControlDown() ? m_item_count : 1;
for(int i=0; i<items; ++i)
{
u32 offset;
if(Memory.IsGoodAddr(m_addr))
{
u32 cmd = Memory.Read32(m_addr);
u32 count = (cmd & (CELL_GCM_METHOD_FLAG_JUMP | CELL_GCM_METHOD_FLAG_CALL))
|| cmd == CELL_GCM_METHOD_FLAG_RETURN ? 0 : (cmd >> 18) & 0x7ff;
offset = 1 + count;
}
else
{
offset = 1;
}
m_addr -= 4 * offset * (event.GetWheelRotation() / event.GetWheelDelta());
}
}
else
{
m_addr -= (event.ControlDown() ? m_item_count : 1) * 4 * (event.GetWheelRotation() / event.GetWheelDelta());
}
UpdateInformation();
event.Skip();
}
@ -233,10 +275,17 @@ void RSXDebugger::OnClickBuffer(wxMouseEvent& event)
const GSRender& render = Emu.GetGSManager().GetRender();
const mem_ptr_t<gcmBuffer> buffers = render.m_gcm_buffers_addr;
if(!buffers.IsGood())
return;
// TODO: Is there any better way to choose the color buffers
#define SHOW_BUFFER(id) \
MemoryViewerPanel::ShowImage(this, render.m_local_mem_addr + re(buffers[id].offset), \
3, re(buffers[id].width), re(buffers[id].height), true);
{ \
u32 addr = render.m_local_mem_addr + re(buffers[id].offset); \
if(Memory.IsGoodAddr(addr) && buffers[id].width && buffers[id].height) \
MemoryViewerPanel::ShowImage(this, addr, 3, re(buffers[id].width), re(buffers[id].height), true); \
return; \
} \
if (event.GetId() == p_buffer_colorA->GetId()) SHOW_BUFFER(0);
if (event.GetId() == p_buffer_colorB->GetId()) SHOW_BUFFER(1);
@ -244,10 +293,11 @@ void RSXDebugger::OnClickBuffer(wxMouseEvent& event)
if (event.GetId() == p_buffer_colorD->GetId()) SHOW_BUFFER(3);
if (event.GetId() == p_buffer_tex->GetId())
{
MemoryViewerPanel::ShowImage(this,
render.m_textures[0].m_offset, 0,
render.m_textures[0].m_width,
render.m_textures[0].m_height, false);
if(Memory.IsGoodAddr(render.m_textures[m_cur_texture].m_offset) && render.m_textures[m_cur_texture].m_width && render.m_textures[m_cur_texture].m_height)
MemoryViewerPanel::ShowImage(this,
render.m_textures[m_cur_texture].m_offset, 0,
render.m_textures[m_cur_texture].m_width,
render.m_textures[m_cur_texture].m_height, false);
}
#undef SHOW_BUFFER
@ -275,6 +325,7 @@ void RSXDebugger::GoToPut(wxCommandEvent& event)
void RSXDebugger::UpdateInformation()
{
t_addr->SetValue(wxString::Format("%08x", m_addr));
GetMemory();
GetBuffers();
GetFlags();
@ -289,26 +340,24 @@ void RSXDebugger::GetMemory()
for(u32 i=0; i<m_item_count; i++)
m_list_commands->SetItem(i, 2, wxEmptyString);
u32 ioAddr = RSXReady() ? Emu.GetGSManager().GetRender().m_ioAddress : 0;
// Write information
for(u32 i=0; i<m_item_count; i++)
for(u32 i=0, addr = m_addr; i<m_item_count; i++, addr += 4)
{
u32 addr = m_addr + 4*i;
m_list_commands->SetItem(i, 0, wxString::Format("%08x", addr));
if (Memory.IsGoodAddr(addr))
if (ioAddr && Memory.IsGoodAddr(addr))
{
u32 cmd = Memory.Read32(addr);
u32 count = (cmd >> 18) & 0x7ff;
u32 ioAddr = Emu.GetGSManager().GetRender().m_ioAddress;
m_list_commands->SetItem(i, 1, wxString::Format("%08x", cmd));
m_list_commands->SetItem(i, 3, wxString::Format("%d", count));
if (count > 0)
m_list_commands->SetItem(i, 2, DisAsmCommand(cmd, count, addr, ioAddr));
if(!(cmd & (CELL_GCM_METHOD_FLAG_JUMP | CELL_GCM_METHOD_FLAG_CALL)) && cmd != CELL_GCM_METHOD_FLAG_RETURN)
{
wxString disasm = DisAsmCommand(cmd, count, addr, ioAddr);
for (u32 j=0; j<count && i+j<m_item_count; j++)
{
m_list_commands->SetItem(i+j, 2, disasm);
}
addr += 4 * count;
}
}
else
@ -327,8 +376,15 @@ void RSXDebugger::GetBuffers()
// TODO: Currently it only supports color buffers
for (u32 bufferId=0; bufferId < render.m_gcm_buffers_count; bufferId++)
{
if(!Memory.IsGoodAddr(render.m_gcm_buffers_addr))
continue;
gcmBuffer* buffers = (gcmBuffer*)Memory.GetMemFromAddr(render.m_gcm_buffers_addr);
u32 RSXbuffer_addr = render.m_local_mem_addr + re(buffers[bufferId].offset);
if(!Memory.IsGoodAddr(RSXbuffer_addr))
continue;
unsigned char* RSXbuffer = (unsigned char*)Memory.VirtualToRealAddr(RSXbuffer_addr);
u32 width = re(buffers[bufferId].width);
@ -361,11 +417,15 @@ void RSXDebugger::GetBuffers()
}
// Draw Texture
u32 TexBuffer_addr = render.m_textures[0].m_offset;
u32 TexBuffer_addr = render.m_textures[m_cur_texture].m_offset;
if(!Memory.IsGoodAddr(TexBuffer_addr))
return;
unsigned char* TexBuffer = (unsigned char*)Memory.VirtualToRealAddr(TexBuffer_addr);
u32 width = render.m_textures[0].m_width;
u32 height = render.m_textures[0].m_height;
u32 width = render.m_textures[m_cur_texture].m_width;
u32 height = render.m_textures[m_cur_texture].m_height;
unsigned char* buffer = (unsigned char*)malloc(width * height * 3);
memcpy(buffer, TexBuffer, width * height * 3);
@ -421,24 +481,23 @@ void RSXDebugger::GetTexture()
if (!RSXReady()) return;
const GSRender& render = Emu.GetGSManager().GetRender();
m_list_texture->DeleteAllItems();
int i=0;
#define LIST_TEXTURE_ADD(name, value) \
m_list_texture->InsertItem(i, name); m_list_texture->SetItem(i, 1, value); i++;
for(uint i=0; i<RSXThread::m_textures_count; ++i)
{
m_list_texture->InsertItem(i, wxString::Format("%d", i));
m_list_texture->SetItem(i, 1, wxString::Format("0x%x", render.m_textures[i].m_offset));
m_list_texture->SetItem(i, 2, render.m_textures[i].m_cubemap ? "True" : "False");
m_list_texture->SetItem(i, 3, wxString::Format("%dD", render.m_textures[i].m_dimension));
m_list_texture->SetItem(i, 4, render.m_textures[i].m_enabled ? "True" : "False");
m_list_texture->SetItem(i, 5, wxString::Format("0x%x", render.m_textures[i].m_format));
m_list_texture->SetItem(i, 6, wxString::Format("0x%x", render.m_textures[i].m_mipmap));
m_list_texture->SetItem(i, 7, wxString::Format("0x%x", render.m_textures[i].m_pitch));
m_list_texture->SetItem(i, 8, wxString::Format("%dx%d",
render.m_textures[i].m_width,
render.m_textures[i].m_height));
LIST_TEXTURE_ADD("Texture #0 Address:", wxString::Format("0x%x", render.m_textures[0].m_offset));
LIST_TEXTURE_ADD("Texture #0 Cubemap:", render.m_textures[0].m_cubemap ? "True" : "False");
LIST_TEXTURE_ADD("Texture #0 Depth:", wxString::Format("0x%x", render.m_textures[0].m_depth));
LIST_TEXTURE_ADD("Texture #0 Dimension:", wxString::Format("0x%x", render.m_textures[0].m_dimension));
LIST_TEXTURE_ADD("Texture #0 Enabled:", render.m_textures[0].m_enabled ? "True" : "False");
LIST_TEXTURE_ADD("Texture #0 Format:", wxString::Format("0x%x", render.m_textures[0].m_format));
LIST_TEXTURE_ADD("Texture #0 Mipmap:", wxString::Format("0x%x", render.m_textures[0].m_mipmap));
LIST_TEXTURE_ADD("Texture #0 Pitch:", wxString::Format("0x%x", render.m_textures[0].m_pitch));
LIST_TEXTURE_ADD("Texture #0 Size:", wxString::Format("%d x %d",
render.m_textures[0].m_width,
render.m_textures[0].m_height));
#undef LIST_TEXTURE_ADD
m_list_texture->SetItemBackgroundColour(i, wxColour(m_cur_texture == i ? "Wheat" : "White"));
}
}
void RSXDebugger::GetSettings()
@ -524,6 +583,15 @@ void RSXDebugger::SetFlags(wxListEvent& event)
case 11: render.m_set_poly_offset_point ^= true; break;
case 12: render.m_set_stencil_test ^= true; break;
}
UpdateInformation();
}
void RSXDebugger::OnSelectTexture(wxListEvent& event)
{
if(event.GetIndex() >= 0)
m_cur_texture = event.GetIndex();
UpdateInformation();
}
@ -616,117 +684,135 @@ wxString RSXDebugger::ParseGCMEnum(u32 value, u32 type)
wxString RSXDebugger::DisAsmCommand(u32 cmd, u32 count, u32 currentAddr, u32 ioAddr)
{
wxString disasm = wxEmptyString;
#define DISASM(string, ...) if(disasm.IsEmpty()) disasm = wxString::Format((string), ##__VA_ARGS__); else disasm += (wxString(' ') + wxString::Format((string), ##__VA_ARGS__))
if(cmd & CELL_GCM_METHOD_FLAG_JUMP)
{
u32 jumpAddr = cmd & ~(CELL_GCM_METHOD_FLAG_JUMP | CELL_GCM_METHOD_FLAG_NON_INCREMENT);
disasm = wxString::Format("JUMP: %08x -> %08x", currentAddr, ioAddr+jumpAddr);
DISASM("JUMP: %08x -> %08x", currentAddr, ioAddr+jumpAddr);
}
if(cmd & CELL_GCM_METHOD_FLAG_CALL)
else if(cmd & CELL_GCM_METHOD_FLAG_CALL)
{
u32 callAddr = cmd & ~CELL_GCM_METHOD_FLAG_CALL;
disasm = wxString::Format("CALL: %08x -> %08x", currentAddr, ioAddr+callAddr);
DISASM("CALL: %08x -> %08x", currentAddr, ioAddr+callAddr);
}
if(cmd == CELL_GCM_METHOD_FLAG_RETURN)
{
disasm = "RETURN";
}
if(cmd & CELL_GCM_METHOD_FLAG_NON_INCREMENT)
{
disasm = "Non Increment cmd";
DISASM("RETURN");
}
if(cmd == 0)
{
disasm = "Null cmd";
DISASM("Null cmd");
}
u32 index = 0;
mem32_ptr_t args(currentAddr + 4);
switch(cmd & 0x3ffff)
else if(!(cmd & (CELL_GCM_METHOD_FLAG_JUMP | CELL_GCM_METHOD_FLAG_CALL)) && cmd != CELL_GCM_METHOD_FLAG_RETURN)
{
case 0x3fead:
disasm = "???"; break;
case NV4097_NO_OPERATION:
disasm = "NOP"; break;
case NV406E_SET_REFERENCE:
disasm = "???"; break;
mem32_ptr_t args(currentAddr + 4);
case_16(NV4097_SET_TEXTURE_OFFSET, 0x20):
disasm = wxString::Format(" Texture Offset: %08x", args[0]);
switch ((args[1] & 0x3) - 1)
u32 index = 0;
switch(cmd & 0x3ffff)
{
case CELL_GCM_LOCATION_LOCAL: disasm += " (Local memory);"; break;
case CELL_GCM_LOCATION_MAIN: disasm += " (Main memory);"; break;
default: disasm += " (Bad location!);"; break;
}
disasm += wxString::Format(" Cubemap:%s; Dimension:0x%x; Format:0x%x; Mipmap:0x%x",
((args[1] >> 2) & 0x1) ? "True" : "False",
((args[1] >> 4) & 0xf),
((args[1] >> 8) & 0xff),
((args[1] >> 16) & 0xffff));
break;
case NV4097_SET_COLOR_MASK:
disasm = wxString::Format(" Color mask: True (A:%d, R:%d, G:%d, B:%d)",
args[0] & 0x1000000 ? "1" : "0",
args[0] & 0x0010000 ? "1" : "0",
args[0] & 0x0000100 ? "1" : "0",
args[0] & 0x0000001 ? "1" : "0");
break;
case NV4097_SET_ALPHA_TEST_ENABLE:
disasm = args[0] ? "Alpha test: Enable" : "Alpha test: Disable";
break;
case NV4097_SET_BLEND_ENABLE:
disasm = args[0] ? "Blend: Enable" : "Blend: Disable";
break;
case NV4097_SET_DEPTH_BOUNDS_TEST_ENABLE:
disasm = args[0] ? "Depth bounds test: Enable" : "Depth bounds test: Disable";
break;
case NV4097_SET_CONTEXT_DMA_COLOR_A:
disasm = wxString::Format("Context DMA Color A: 0x%x", args[0]);
break;
case NV4097_SET_CONTEXT_DMA_COLOR_B:
disasm = wxString::Format("Context DMA Color B: 0x%x", args[0]);
break;
case NV4097_SET_CONTEXT_DMA_COLOR_C:
disasm = wxString::Format("Context DMA Color C: 0x%x", args[0]);
if(count > 1)
disasm = wxString::Format("Context DMA Color C: 0x%x", args[1]);
break;
case NV4097_SET_CONTEXT_DMA_ZETA:
disasm = wxString::Format("Context DMA Zeta: 0x%x", args[0]);
break;
case NV4097_SET_SURFACE_PITCH_C:
disasm = wxString::Format("Surface Pitch C: 0x%x; ", args[0]);
disasm += wxString::Format("Surface Pitch D: 0x%x; ", args[1]);
disasm += wxString::Format("Surface Offset C: 0x%x; ", args[2]);
disasm += wxString::Format("Surface Offset D: 0x%x", args[3]);
break;
case NV4097_SET_SURFACE_PITCH_Z:
disasm = wxString::Format("Surface Pitch Z: 0x%x; ", args[0]);
break;
default:
case 0x3fead:
DISASM("Flip and change current buffer: %d", args[0]);
break;
case NV4097_NO_OPERATION:
DISASM("NOP");
break;
case NV406E_SET_REFERENCE:
DISASM("Set reference: 0x%x", args[0]);
break;
case_16(NV4097_SET_TEXTURE_OFFSET, 0x20):
DISASM("Texture Offset[%d]: %08x", index, args[0]);
switch ((args[1] & 0x3) - 1)
{
case CELL_GCM_LOCATION_LOCAL: DISASM("(Local memory);"); break;
case CELL_GCM_LOCATION_MAIN: DISASM("(Main memory);"); break;
default: DISASM("(Bad location!);"); break;
}
DISASM(" Cubemap:%s; Dimension:0x%x; Format:0x%x; Mipmap:0x%x",
((args[1] >> 2) & 0x1) ? "True" : "False",
((args[1] >> 4) & 0xf),
((args[1] >> 8) & 0xff),
((args[1] >> 16) & 0xffff));
break;
case NV4097_SET_COLOR_MASK:
DISASM(" Color mask: True (A:%c, R:%c, G:%c, B:%c)",
args[0] & 0x1000000 ? '1' : '0',
args[0] & 0x0010000 ? '1' : '0',
args[0] & 0x0000100 ? '1' : '0',
args[0] & 0x0000001 ? '1' : '0');
break;
case NV4097_SET_ALPHA_TEST_ENABLE:
DISASM(args[0] ? "Alpha test: Enable" : "Alpha test: Disable");
break;
case NV4097_SET_BLEND_ENABLE:
DISASM(args[0] ? "Blend: Enable" : "Blend: Disable");
break;
case NV4097_SET_DEPTH_BOUNDS_TEST_ENABLE:
DISASM(args[0] ? "Depth bounds test: Enable" : "Depth bounds test: Disable");
break;
case NV4097_SET_CONTEXT_DMA_COLOR_A:
DISASM("Context DMA Color A: 0x%x", args[0]);
break;
case NV4097_SET_CONTEXT_DMA_COLOR_B:
DISASM("Context DMA Color B: 0x%x", args[0]);
break;
case NV4097_SET_CONTEXT_DMA_COLOR_C:
DISASM("Context DMA Color C: 0x%x", args[0]);
if(count > 1)
DISASM("0x%x", args[1]);
break;
case NV4097_SET_CONTEXT_DMA_ZETA:
DISASM("Context DMA Zeta: 0x%x", args[0]);
break;
case NV4097_SET_SURFACE_PITCH_C:
DISASM("Surface Pitch C: 0x%x;", args[0]);
DISASM("Surface Pitch D: 0x%x;", args[1]);
DISASM("Surface Offset C: 0x%x;", args[2]);
DISASM("Surface Offset D: 0x%x", args[3]);
break;
case NV4097_SET_SURFACE_PITCH_Z:
DISASM("Surface Pitch Z: 0x%x;", args[0]);
break;
default:
break;
}
if(cmd & CELL_GCM_METHOD_FLAG_NON_INCREMENT)
{
DISASM("Non Increment cmd");
}
DISASM("[0x%08x(", cmd);
for(uint i=0; i<count; ++i)
{
if(i != 0) disasm += ", ";
disasm += wxString::Format("0x%x", args[i]);
}
disasm += ")]";
}
#undef DISASM
return disasm;
}
bool RSXDebugger::RSXReady()
{
// TODO: This is a *very* ugly way of checking if m_render was initialized. It throws an error while debugging in VS
const GSRender& render = Emu.GetGSManager().GetRender();
if (!&render)
{
return false;
}
return true;
return Emu.GetGSManager().IsInited();
}

View File

@ -4,6 +4,8 @@
class RSXDebugger : public wxFrame
{
AppConnector m_app_connector;
u32 m_addr;
u32 m_panel_width;
@ -28,6 +30,8 @@ class RSXDebugger : public wxFrame
wxPanel* p_buffer_stencil;
wxPanel* p_buffer_tex;
uint m_cur_texture;
public:
bool exit;
RSXDebugger(wxWindow* parent);
@ -53,7 +57,8 @@ public:
virtual void GetSettings();
virtual void SetFlags(wxListEvent& event);
virtual void OnSelectTexture(wxListEvent& event);
wxString ParseGCMEnum(u32 value, u32 type);
wxString DisAsmCommand(u32 cmd, u32 count, u32 currentAddr, u32 ioAddr);

View File

@ -188,7 +188,7 @@ void VFSManagerDialog::OnAdd(wxCommandEvent& event)
m_list->SetItemState(i, i == idx ? wxLIST_STATE_SELECTED : ~wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
}
wxCommandEvent ce;
wxCommandEvent ce;
OnEntryConfig(ce);
}

View File

@ -119,8 +119,8 @@ bool ELF32Loader::LoadShdrInfo()
if(ehdr.e_shstrndx >= shdr_arr.GetCount())
{
ConLog.Error("LoadShdr32 error: shstrndx too big!");
return false;
ConLog.Warning("LoadShdr32 error: shstrndx too big!");
return true;
}
for(u32 i=0; i<shdr_arr.GetCount(); ++i)

View File

@ -169,8 +169,8 @@ bool ELF64Loader::LoadShdrInfo(s64 offset)
if(ehdr.e_shstrndx >= shdr_arr.GetCount())
{
ConLog.Error("LoadShdr64 error: shstrndx too big!");
return false;
ConLog.Warning("LoadShdr64 error: shstrndx too big!");
return true;
}
for(u32 i=0; i<shdr_arr.GetCount(); ++i)

View File

@ -2,7 +2,7 @@
#include "Emu/FS/vfsFileBase.h"
#ifdef _DEBUG
#define LOADER_DEBUG
//#define LOADER_DEBUG
#endif
enum Elf_Machine