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, 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 enum
{ {
MFC_SPU_TO_PPU_MAILBOX_STATUS_MASK = 0x000000FF, MFC_SPU_TO_PPU_MAILBOX_STATUS_MASK = 0x000000FF,

View file

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

View file

@ -20,7 +20,11 @@ struct VFSManagerEntry
char* mount; char* mount;
vfsDeviceType device; 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; 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; if(d0.cond == 0) return;
enum 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); //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; 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)"; value = "clamp(" + value + ", 0.0, 1.0)";
} }
wxString dest; if(set_dst)
if(d3.dst == 5 || d3.dst == 6)
{ {
int num = d3.dst == 5 ? 0 : 3; wxString dest;
if(d0.cond_update_enable_0)
if(d3.vec_writemask_x)
{ {
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; code = cond + dest + " = " + value;
if(d3.vec_writemask_z) num += 1;
else if(d3.vec_writemask_w) num += 2;
dest = wxString::Format(GetDST(is_sca), num);
} }
else else
{ {
dest = GetDST(is_sca) + GetMask(is_sca); code = cond + value;
} }
code = cond + dest + " = " + value; 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));
main += "\t" + code + ";\n";
} }
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() wxString GLVertexDecompilerThread::BuildCode()
@ -233,14 +293,31 @@ wxString GLVertexDecompilerThread::BuildCode()
{ {
p += m_parr.params[i].Format(); 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 = static const wxString& prot =
"#version 330\n" "#version 330\n"
"\n" "\n"
"%s\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() void GLVertexDecompilerThread::Task()
@ -268,11 +345,11 @@ void GLVertexDecompilerThread::Task()
case 0x05: AddScaCode("exp(" + GetSRC(2, true) + ")"); break; // EXP case 0x05: AddScaCode("exp(" + GetSRC(2, true) + ")"); break; // EXP
case 0x06: AddScaCode("log(" + GetSRC(2, true) + ")"); break; // LOG case 0x06: AddScaCode("log(" + GetSRC(2, true) + ")"); break; // LOG
//case 0x07: break; // LIT //case 0x07: break; // LIT
//case 0x08: break; // BRA case 0x08: AddScaCode("{ /*BRA*/ " + GetFunc() + "; return; }", false); break; // BRA
//case 0x09: break; // BRI : works differently (BRI o[1].x(TR) L0;) case 0x09: AddScaCode("{ " + GetFunc() + "; return; }", false); break; // BRI : works differently (BRI o[1].x(TR) L0;)
//case 0x0a: break; // CAL : works same as BRI case 0x0a: AddScaCode("/*CAL*/ " + GetFunc(), false); break; // CAL : works same as BRI
//case 0x0b: break; // CLI : works same as BRI case 0x0b: AddScaCode("/*CLI*/ " + GetFunc(), false); break; // CLI : works same as BRI
//case 0x0c: break; // RET : works like BRI but shorter (RET o[1].x(TR);) 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 0x0d: AddScaCode("log2(" + GetSRC(2, true) + ")"); break; // LG2
case 0x0e: AddScaCode("exp2(" + GetSRC(2, true) + ")"); break; // EX2 case 0x0e: AddScaCode("exp2(" + GetSRC(2, true) + ")"); break; // EX2
case 0x0f: AddScaCode("sin(" + GetSRC(2, true) + ")"); break; // SIN 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;) //case 0x14: break; // POP : works differently (POP o[1].x;)
default: 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); ConLog.Error("Unknown vp sca_opcode 0x%x", d1.sca_opcode);
Emu.Pause(); Emu.Pause();
break; break;
@ -314,17 +392,25 @@ void GLVertexDecompilerThread::Task()
case 0x16: AddVecCode("sign(" + GetSRC(0) + ")"); break; //SSG case 0x16: AddVecCode("sign(" + GetSRC(0) + ")"); break; //SSG
default: default:
m_body.Add(wxString::Format("//Unknown vp opcode 0x%x", d1.vec_opcode));
ConLog.Error("Unknown vp opcode 0x%x", d1.vec_opcode); ConLog.Error("Unknown vp opcode 0x%x", d1.vec_opcode);
Emu.Pause(); Emu.Pause();
break; break;
} }
if(d3.end) break; if(d3.end)
{
if(i < m_data.GetCount())
ConLog.Error("Program end before buffer end.");
break;
}
} }
m_shader = BuildCode(); m_shader = BuildCode();
main = wxEmptyString; m_body.Clear();
m_funcs.RemoveAt(1, m_funcs.GetCount() - 1);
} }
GLVertexProgram::GLVertexProgram() GLVertexProgram::GLVertexProgram()

View file

@ -127,7 +127,17 @@ struct GLVertexDecompilerThread : public ThreadBase
}; };
} src[3]; } src[3];
wxString main; struct FuncInfo
{
u32 offset;
wxString name;
};
wxArrayString m_body;
ArrayF<FuncInfo> m_funcs;
//wxString main;
wxString& m_shader; wxString& m_shader;
Array<u32>& m_data; Array<u32>& m_data;
GLParamArray& m_parr; GLParamArray& m_parr;
@ -138,6 +148,10 @@ struct GLVertexDecompilerThread : public ThreadBase
, m_shader(shader) , m_shader(shader)
, m_parr(parr) , 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); wxString GetMask(bool is_sca);
@ -145,9 +159,11 @@ struct GLVertexDecompilerThread : public ThreadBase
wxString GetScaMask(); wxString GetScaMask();
wxString GetDST(bool is_sca = false); wxString GetDST(bool is_sca = false);
wxString GetSRC(const u32 n, bool is_sca = false); wxString GetSRC(const u32 n, bool is_sca = false);
void AddCode(bool is_sca, wxString code, bool src_mask = true); wxString GetFunc();
void AddVecCode(const wxString& code, bool src_mask = true); void AddCode(bool is_sca, wxString code, bool src_mask = true, bool set_dst = true);
void AddScaCode(const wxString& code); 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(); wxString BuildCode();
virtual void Task(); virtual void Task();

View file

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

View file

@ -104,6 +104,41 @@ u32 RSXVertexData::GetTypeSize()
index = (cmd - a) / m; \ index = (cmd - a) / m; \
case a \ 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) void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u32 count)
{ {
#if CMD_DEBUG #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); //ConLog.Warning("texture addr = 0x%x #offset = 0x%x, location=%d", tex_addr, offset, location);
tex.SetOffset(tex_addr); tex.SetOffset(tex_addr);
tex.SetFormat(cubemap, dimension, format, mipmap); 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; 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]; RSXTexture& tex = m_textures[index];
const u16 height = args[0] & 0xffff; u16 height = args[0] & 0xffff;
const u16 width = args[0] >> 16; u16 width = args[0] >> 16;
CMD_LOG("width=%d, height=%d", width, height); 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); tex.SetRect(width, height);
} }
break; 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: 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 = &m_vertex_progs[args[0]];
m_cur_vertex_prog->data.Clear(); 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; 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) if(!m_cur_vertex_prog)
{ {
ConLog.Warning("NV4097_SET_TRANSFORM_PROGRAM: m_cur_vertex_prog == NULL"); ConLog.Warning("NV4097_SET_TRANSFORM_PROGRAM: m_cur_vertex_prog == NULL");

View file

@ -226,7 +226,7 @@ class RSXThread : public ThreadBase
{ {
public: public:
static const uint m_textures_count = 16; 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_fragment_count = 16;
static const uint m_tiles_count = 15; 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 struct Pad
{ {
u32 m_port_status; u32 m_port_status;
@ -111,6 +129,7 @@ struct Pad
u32 m_device_type; u32 m_device_type;
Array<Button> m_buttons; Array<Button> m_buttons;
Array<AnalogStick> m_sticks;
s16 m_analog_left_x; s16 m_analog_left_x;
s16 m_analog_left_y; s16 m_analog_left_y;
@ -166,7 +185,7 @@ struct Pad
{ {
} }
~Pad() { m_buttons.Clear(); } ~Pad() { m_buttons.Clear(); m_sticks.Clear(); }
}; };
struct PadInfo struct PadInfo
@ -206,10 +225,29 @@ public:
button.m_pressed = pressed; 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; } PadInfo& GetInfo() { return m_info; }
Array<Pad>& GetPads() { return m_pads; } Array<Pad>& GetPads() { return m_pads; }
Array<Button>& GetButtons(const u32 pad) { return GetPads()[pad].m_buttons; } 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.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.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_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)); 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> 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 -> () T* operator -> ()
{ {
return (T*)&Memory[this->m_addr]; return (T*)&Memory[this->m_addr];
@ -513,8 +531,6 @@ public:
return (const T&)Memory[this->m_addr + sizeof(T) * index]; 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; } 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; } 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()]; } 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; return *this;
} }
__forceinline T GetValue()
{
return (be_t<T>&)Memory[this->m_addr];
}
operator const T() const operator const T() const
{ {
return (be_t<T>&)Memory[this->m_addr]; return (be_t<T>&)Memory[this->m_addr];
@ -639,6 +686,123 @@ public:
void SetAddr(const u64 addr) { m_addr = addr; } 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> template<typename T>
class MemoryAllocator class MemoryAllocator
{ {

View file

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

View file

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

View file

@ -570,6 +570,171 @@ s64 SysCalls::DoFunc(const u32 id)
case 0x56776c0d: FUNC_LOG_ERROR("TODO: cellKey2CharGetChar"); case 0x56776c0d: FUNC_LOG_ERROR("TODO: cellKey2CharGetChar");
case 0xabf629c1: FUNC_LOG_ERROR("TODO: cellKey2CharOpen"); case 0xabf629c1: FUNC_LOG_ERROR("TODO: cellKey2CharOpen");
case 0xbfc03768: FUNC_LOG_ERROR("TODO: cellKey2CharSetMode"); 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 0x0252efcc: FUNC_LOG_ERROR("TODO: cellUserTraceInit");
case 0x05893e7c: FUNC_LOG_ERROR("TODO: cellUserTraceRegister"); case 0x05893e7c: FUNC_LOG_ERROR("TODO: cellUserTraceRegister");
case 0x6d045c2e: FUNC_LOG_ERROR("TODO: cellUserTraceUnregister"); case 0x6d045c2e: FUNC_LOG_ERROR("TODO: cellUserTraceUnregister");

View file

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

View file

@ -4,7 +4,8 @@
#include "Emu/Audio/cellAudio.h" #include "Emu/Audio/cellAudio.h"
void cellAudio_init(); void cellAudio_init();
Module cellAudio(0x0011, cellAudio_init); void cellAudio_unload();
Module cellAudio(0x0011, cellAudio_init, nullptr, cellAudio_unload);
enum enum
{ {
@ -81,9 +82,9 @@ struct CellAudioPortConfig
struct CellAudioConfig //custom structure struct CellAudioConfig //custom structure
{ {
bool g_is_audio_initialized; bool m_is_audio_initialized;
bool g_is_audio_port_open; bool m_is_audio_port_open;
bool g_is_audio_port_started; bool m_is_audio_port_started;
}; };
CellAudioPortParam* m_param = new CellAudioPortParam; CellAudioPortParam* m_param = new CellAudioPortParam;
@ -95,55 +96,55 @@ typedef void * CellAANHandle;
struct CellSSPlayerConfig struct CellSSPlayerConfig
{ {
u32 channels; be_t<u32> channels;
u32 outputMode; be_t<u32> outputMode;
}; };
struct CellSSPlayerWaveParam struct CellSSPlayerWaveParam
{ {
void *addr; void *addr;
int format; be_t<s32> format;
u32 samples; be_t<u32> samples;
u32 loopStartOffset; be_t<u32> loopStartOffset;
u32 startOffset; be_t<u32> startOffset;
}; };
struct CellSSPlayerCommonParam struct CellSSPlayerCommonParam
{ {
u32 loopMode; be_t<u32> loopMode;
u32 attackMode; be_t<u32> attackMode;
}; };
struct CellSurMixerPosition struct CellSurMixerPosition
{ {
float x; be_t<float> x;
float y; be_t<float> y;
float z; be_t<float> z;
}; };
struct CellSSPlayerRuntimeInfo struct CellSSPlayerRuntimeInfo
{ {
float level; be_t<float> level;
float speed; be_t<float> speed;
CellSurMixerPosition position; CellSurMixerPosition position;
}; };
struct CellSurMixerConfig struct CellSurMixerConfig
{ {
s32 priority; be_t<s32> priority;
u32 chStrips1; be_t<u32> chStrips1;
u32 chStrips2; be_t<u32> chStrips2;
u32 chStrips6; be_t<u32> chStrips6;
u32 chStrips8; be_t<u32> chStrips8;
}; };
struct CellSurMixerChStripParam struct CellSurMixerChStripParam
{ {
u32 param; be_t<u32> param;
void *attribute; void *attribute;
int dBSwitch; be_t<s32> dBSwitch;
float floatVal; be_t<float> floatVal;
int intVal; be_t<s32> intVal;
}; };
CellSSPlayerWaveParam current_SSPlayerWaveParam; CellSSPlayerWaveParam current_SSPlayerWaveParam;
@ -164,31 +165,31 @@ struct CellSnd3KeyOnParam
u8 vel; u8 vel;
u8 pan; u8 pan;
u8 panEx; u8 panEx;
s32 addPitch; be_t<s32> addPitch;
}; };
struct CellSnd3VoiceBitCtx struct CellSnd3VoiceBitCtx
{ {
u32 core; //[CELL_SND3_MAX_CORE], unknown identifier be_t<u32> core; //[CELL_SND3_MAX_CORE], unknown identifier
}; };
struct CellSnd3RequestQueueCtx struct CellSnd3RequestQueueCtx
{ {
void *frontQueue; void *frontQueue;
u32 frontQueueSize; be_t<u32> frontQueueSize;
void *rearQueue; void *rearQueue;
u32 rearQueueSize; be_t<u32> rearQueueSize;
}; };
//libsynt2 datatypes //libsynt2 datatypes
struct CellSoundSynth2EffectAttr struct CellSoundSynth2EffectAttr
{ {
u16 core; be_t<u16> core;
u16 mode; be_t<u16> mode;
s16 depth_L; be_t<s16> depth_L;
s16 depth_R; be_t<s16> depth_R;
u16 delay; be_t<u16> delay;
u16 feedback; be_t<u16> feedback;
}; };
// libaudio Functions // libaudio Functions
@ -196,28 +197,26 @@ struct CellSoundSynth2EffectAttr
int cellAudioInit() int cellAudioInit()
{ {
cellAudio.Warning("cellAudioInit()"); cellAudio.Warning("cellAudioInit()");
if(m_config->g_is_audio_initialized == true) return CELL_AUDIO_ERROR_ALREADY_INIT; if(m_config->m_is_audio_initialized == true) return CELL_AUDIO_ERROR_ALREADY_INIT;
m_config->g_is_audio_initialized = true; m_config->m_is_audio_initialized = true;
return CELL_OK; return CELL_OK;
} }
int cellAudioQuit() int cellAudioQuit()
{ {
cellAudio.Warning("cellAudioQuit()"); cellAudio.Warning("cellAudioQuit()");
if (m_config->g_is_audio_initialized == false) return CELL_AUDIO_ERROR_NOT_INIT; if (m_config->m_is_audio_initialized == false) return CELL_AUDIO_ERROR_NOT_INIT;
m_config->g_is_audio_initialized = false; m_config->m_is_audio_initialized = false;
delete m_config;
return CELL_OK; return CELL_OK;
} }
int cellAudioPortOpen(mem_ptr_t<CellAudioPortParam> audioParam, mem32_t portNum) 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()); 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; 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->nChannel = audioParam->nChannel;
m_param->nBlock = audioParam->nBlock; m_param->nBlock = audioParam->nBlock;
@ -235,20 +234,22 @@ int cellAudioGetPortConfig(u32 portNum, mem_ptr_t<CellAudioPortConfig> portConfi
if(!portConfig.IsGood()) if(!portConfig.IsGood())
{ {
return CELL_AUDIO_ERROR_PARAM; return CELL_AUDIO_ERROR_PARAM;
}; }
//if(portNum > 7) return CELL_AUDIO_ERROR_PORT_FULL; //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; portConfig->status = CELL_AUDIO_STATUS_CLOSE;
return CELL_OK; 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; portConfig->status = CELL_AUDIO_STATUS_RUN;
}
else else
{
portConfig->status = CELL_AUDIO_STATUS_READY; portConfig->status = CELL_AUDIO_STATUS_READY;
portConfig->nChannel = m_param->nChannel; portConfig->nChannel = m_param->nChannel;
portConfig->nBlock = m_param->nBlock; portConfig->nBlock = m_param->nBlock;
@ -258,36 +259,41 @@ int cellAudioGetPortConfig(u32 portNum, mem_ptr_t<CellAudioPortConfig> portConfi
// portAddr - readIndexAddr == 0xFFF0 on ps3 // portAddr - readIndexAddr == 0xFFF0 on ps3
Memory.Write64(portConfig->readIndexAddr, 1); Memory.Write64(portConfig->readIndexAddr, 1);
return CELL_OK; }
return CELL_OK;
} }
int cellAudioPortStart(u32 portNum) int cellAudioPortStart(u32 portNum)
{ {
cellAudio.Warning("cellAudioPortStart(portNum=0x%x)",portNum); cellAudio.Warning("cellAudioPortStart(portNum=0x%x)",portNum);
if (m_config->g_is_audio_port_open == false) return CELL_AUDIO_ERROR_PORT_NOT_OPEN; if (m_config->m_is_audio_port_open == true)
m_config->g_is_audio_port_started = true; return CELL_AUDIO_ERROR_PORT_OPEN;
m_config->m_is_audio_port_started = true;
return CELL_OK; return CELL_OK;
} }
int cellAudioPortClose(u32 portNum) int cellAudioPortClose(u32 portNum)
{ {
cellAudio.Warning("cellAudioPortClose(portNum=0x%x)",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; if (m_config->m_is_audio_port_open == false)
return CELL_AUDIO_ERROR_PORT_NOT_OPEN;
UNIMPLEMENTED_FUNC(cellAudio);
m_config->m_is_audio_port_open = false;
return CELL_OK; return CELL_OK;
} }
int cellAudioPortStop(u32 portNum) int cellAudioPortStop(u32 portNum)
{ {
cellAudio.Warning("cellAudioPortStop(portNum=0x%x)",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; if (m_config->m_is_audio_port_started == false)
return CELL_AUDIO_ERROR_PORT_NOT_OPEN;
UNIMPLEMENTED_FUNC(cellAudio);
m_config->m_is_audio_port_started = false;
return CELL_OK; return CELL_OK;
} }
@ -1006,3 +1012,10 @@ void cellAudio_init()
//TODO: Find addresses for libmixer, libsnd3 and libsynth2 functions //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; 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) 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)", 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(0x93806525, cellGcmGetCurrentDisplayBufferId);
cellGcmSys.AddFunc(0xbc982946, cellGcmSetDefaultCommandBuffer); cellGcmSys.AddFunc(0xbc982946, cellGcmSetDefaultCommandBuffer);
cellGcmSys.AddFunc(0xa47c09ff, cellGcmSetFlipStatus); cellGcmSys.AddFunc(0xa47c09ff, cellGcmSetFlipStatus);
cellGcmSys.AddFunc(0xd0b1d189, cellGcmSetTile);
cellGcmSys.AddFunc(0xbd100dbc, cellGcmSetTileInfo); cellGcmSys.AddFunc(0xbd100dbc, cellGcmSetTileInfo);
cellGcmSys.AddFunc(0x4524cccd, cellGcmBindTile); cellGcmSys.AddFunc(0x4524cccd, cellGcmBindTile);
cellGcmSys.AddFunc(0x0b4b62d5, cellGcmSetPrepareFlip); 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_max; //== 0x01D470 (400 bps per unit, == 48000000 bps)
be_t<u32> mux_rate_min; //== 0x0107AC (?????) be_t<u32> mux_rate_min; //== 0x0107AC (?????)
u16 reserved2; // ????? 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<u16> unk1; //== 1 (?????)
be_t<u32> table_data_size; //== table_size - 0x20 == 0x14 + (0x30 * total_stream_num) (?????) 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) //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)", cellPamf.Warning("cellPamfGetStreamOffsetAndSize(pAddr=0x%x, fileSize=%d, pOffset_addr=0x%x, pSize_addr=0x%x)",
pAddr.GetAddr(), fileSize, pOffset.GetAddr(), pSize.GetAddr()); 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; pSize = (u64)pAddr->data_size << 11;
return CELL_OK; return CELL_OK;
} }
@ -327,6 +329,9 @@ int cellPamfReaderGetNumberOfSpecificStreams(mem_ptr_t<CellPamfReader> pSelf, u8
int counts[6] = {0, 0, 0, 0, 0, 0}; int counts[6] = {0, 0, 0, 0, 0, 0};
/*if (!pAddr->magic)
return 1; /*hack*/
for (int i = 0; i < pAddr->stream_count; i++) for (int i = 0; i < pAddr->stream_count; i++)
{ {
switch (pAddr->stream_headers[i].type) switch (pAddr->stream_headers[i].type)
@ -338,6 +343,7 @@ int cellPamfReaderGetNumberOfSpecificStreams(mem_ptr_t<CellPamfReader> pSelf, u8
default: default:
cellPamf.Error("cellPamfReaderGetNumberOfSpecificStreams: unsupported stream type found(0x%x)", cellPamf.Error("cellPamfReaderGetNumberOfSpecificStreams: unsupported stream type found(0x%x)",
pAddr->stream_headers[i].type); 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] + return counts[CELL_PAMF_STREAM_TYPE_ATRAC3PLUS] +
counts[CELL_PAMF_STREAM_TYPE_PAMF_LPCM] + counts[CELL_PAMF_STREAM_TYPE_AC3]; counts[CELL_PAMF_STREAM_TYPE_PAMF_LPCM] + counts[CELL_PAMF_STREAM_TYPE_AC3];
default: default:
return 0; return 0;
} }
} }
@ -394,6 +400,9 @@ int cellPamfReaderSetStreamWithTypeAndIndex(mem_ptr_t<CellPamfReader> pSelf, u8
u32 found = 0; u32 found = 0;
/*if (!pAddr->magic)
return 0; /*hack*/
for (int i = 0; i < pAddr->stream_count; i++) for (int i = 0; i < pAddr->stream_count; i++)
{ {
switch (pAddr->stream_headers[i].type) switch (pAddr->stream_headers[i].type)

View file

@ -1,9 +1,12 @@
#include "stdafx.h" #include "stdafx.h"
#include "Emu/SysCalls/SysCalls.h" #include "Emu/SysCalls/SysCalls.h"
#include "Emu/SysCalls/SC_FUNC.h" #include "Emu/SysCalls/SC_FUNC.h"
#include <mutex>
void cellSync_init(); 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 // Return Codes
enum enum
@ -22,73 +25,122 @@ enum
CELL_SYNC_ERROR_NO_SPU_CONTEXT_STORAGE = 0x80410114, 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(); cellSync.Log("cellSyncMutexInitialize(mutex=0x%x)", mutex.GetAddr());
if (!mutex_addr)
if (!mutex.IsGood())
{ {
return CELL_SYNC_ERROR_NULL_POINTER; return CELL_SYNC_ERROR_NULL_POINTER;
} }
if (mutex_addr % 4) if (mutex.GetAddr() % 4)
{ {
return CELL_SYNC_ERROR_ALIGN; 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; return CELL_OK;
} }
int cellSyncMutexLock(mem32_t mutex) int cellSyncMutexTryLock(mem_ptr_t<CellSyncMutex> mutex)
{ {
const u32 mutex_addr = mutex.GetAddr(); cellSync.Log("cellSyncMutexTryLock(mutex=0x%x)", mutex.GetAddr());
if (!mutex_addr)
if (!mutex.IsGood())
{ {
return CELL_SYNC_ERROR_NULL_POINTER; return CELL_SYNC_ERROR_NULL_POINTER;
} }
if (mutex_addr % 4) if (mutex.GetAddr() % 4)
{ {
return CELL_SYNC_ERROR_ALIGN; return CELL_SYNC_ERROR_ALIGN;
} }
while (_InterlockedExchange((volatile long*)Memory.VirtualToRealAddr(mutex_addr), 1 << 24)); { /* global mutex */
//need to check how does SPU work with these mutexes, also obtainment order is not guaranteed std::lock_guard<std::mutex> lock(g_SyncMutex);
_mm_lfence(); if (mutex->m_order != mutex->m_freed)
return CELL_OK; {
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(); cellSync.Log("cellSyncMutexUnlock(mutex=0x%x)", 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;
}
int cellSyncMutexUnlock(mem32_t mutex) if (!mutex.IsGood())
{
const u32 mutex_addr = mutex.GetAddr();
if (!mutex_addr)
{ {
return CELL_SYNC_ERROR_NULL_POINTER; return CELL_SYNC_ERROR_NULL_POINTER;
} }
if (mutex_addr % 4) if (mutex.GetAddr() % 4)
{ {
return CELL_SYNC_ERROR_ALIGN; return CELL_SYNC_ERROR_ALIGN;
} }
//check cellSyncMutexLock
_mm_sfence(); { /* global mutex */
_InterlockedExchange((volatile long*)Memory.VirtualToRealAddr(mutex_addr), 0); std::lock_guard<std::mutex> lock(g_SyncMutex);
return CELL_OK; mutex->m_freed = mutex->m_freed + 1;
return CELL_OK;
}
} }
void cellSync_init() void cellSync_init()
@ -97,4 +149,9 @@ void cellSync_init()
cellSync.AddFunc(0x1bb675c2, cellSyncMutexLock); cellSync.AddFunc(0x1bb675c2, cellSyncMutexLock);
cellSync.AddFunc(0xd06918c4, cellSyncMutexTryLock); cellSync.AddFunc(0xd06918c4, cellSyncMutexTryLock);
cellSync.AddFunc(0x91f2b7b0, cellSyncMutexUnlock); cellSync.AddFunc(0x91f2b7b0, cellSyncMutexUnlock);
}
void cellSync_unload()
{
g_SyncMutex.unlock();
} }

View file

@ -106,9 +106,6 @@ enum
CELL_SYSUTIL_PAD_RUMBLE_ON = 1, CELL_SYSUTIL_PAD_RUMBLE_ON = 1,
}; };
void cellSysutil_init();
Module cellSysutil(0x0015, cellSysutil_init);
enum enum
{ {
@ -132,6 +129,11 @@ enum CellMsgDialogType
CELL_MSGDIALOG_DEFAULT_CURSOR_NO = 0x00000100, 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) int cellSysutilGetSystemParamInt(int id, mem32_t value)
{ {
cellSysutil.Log("cellSysutilGetSystemParamInt(id=0x%x, value_addr=0x%x)", id, value.GetAddr()); 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()) if (!buf.IsGood())
return CELL_EFAULT; return CELL_EFAULT;
memset(buf, 0, bufsize);
switch(id) switch(id)
{ {
case CELL_SYSUTIL_SYSTEMPARAM_ID_NICKNAME: case CELL_SYSUTIL_SYSTEMPARAM_ID_NICKNAME:
cellSysutil.Warning("cellSysutilGetSystemParamString: CELL_SYSUTIL_SYSTEMPARAM_ID_NICKNAME"); cellSysutil.Warning("cellSysutilGetSystemParamString: CELL_SYSUTIL_SYSTEMPARAM_ID_NICKNAME");
memcpy(buf, "Unknown", 8); //for example
break; break;
case CELL_SYSUTIL_SYSTEMPARAM_ID_CURRENT_USERNAME: case CELL_SYSUTIL_SYSTEMPARAM_ID_CURRENT_USERNAME:
cellSysutil.Warning("cellSysutilGetSystemParamString: CELL_SYSUTIL_SYSTEMPARAM_ID_CURRENT_USERNAME"); cellSysutil.Warning("cellSysutilGetSystemParamString: CELL_SYSUTIL_SYSTEMPARAM_ID_CURRENT_USERNAME");
memcpy(buf, "Unknown", 8);
break; break;
default: default:
@ -477,7 +483,7 @@ int cellSysutilUnregisterCallback(int slot)
return CELL_OK; 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; long style = 0;
@ -520,17 +526,16 @@ int cellMsgDialogOpen2(u32 type, char* msgString, u32 callback_addr, u32 userDat
break; break;
} }
Callback2 callback(0, callback_addr, userData); if(callback)
callback.Handle(status); callback(status, userData);
callback.Branch(true);
return CELL_OK; 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)", 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; std::string errorMessage;
switch(errorCode) switch(errorCode)
@ -622,10 +627,8 @@ int cellMsgDialogOpenErrorCode(u32 errorCode, u32 callback_addr, u32 userData, u
break; break;
} }
// TODO: The following lines produce an infinite loop of cellMsgDialogOpenErrorCode's if(callback)
/*Callback2 callback(0, callback_addr, userData); callback(status, userData);
callback.Handle(status);
callback.Branch(true);*/
return CELL_OK; return CELL_OK;
} }
@ -649,7 +652,7 @@ int cellAudioOutGetSoundAvailability(u32 audioOut, u32 type, u32 fs, u32 option)
case CELL_AUDIO_OUT_FS_192KHZ: case CELL_AUDIO_OUT_FS_192KHZ:
break; break;
default: CELL_AUDIO_OUT_ERROR_UNSUPPORTED_SOUND_MODE; default: return CELL_AUDIO_OUT_ERROR_UNSUPPORTED_SOUND_MODE;
} }
switch(type) switch(type)
@ -659,7 +662,7 @@ int cellAudioOutGetSoundAvailability(u32 audioOut, u32 type, u32 fs, u32 option)
case CELL_AUDIO_OUT_CODING_TYPE_DTS: case CELL_AUDIO_OUT_CODING_TYPE_DTS:
break; break;
default: CELL_AUDIO_OUT_ERROR_UNSUPPORTED_SOUND_MODE; default: return CELL_AUDIO_OUT_ERROR_UNSUPPORTED_SOUND_MODE;
} }
switch(audioOut) switch(audioOut)
@ -668,8 +671,7 @@ int cellAudioOutGetSoundAvailability(u32 audioOut, u32 type, u32 fs, u32 option)
case CELL_AUDIO_OUT_SECONDARY: return 0; 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) 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: case CELL_AUDIO_OUT_FS_192KHZ:
break; break;
default: CELL_AUDIO_OUT_ERROR_UNSUPPORTED_SOUND_MODE; default: return CELL_AUDIO_OUT_ERROR_UNSUPPORTED_SOUND_MODE;
} }
switch(ch) switch(ch)
@ -700,7 +702,7 @@ int cellAudioOutGetSoundAvailability2(u32 audioOut, u32 type, u32 fs, u32 ch, u3
case 8: case 8:
break; break;
default: CELL_AUDIO_OUT_ERROR_UNSUPPORTED_SOUND_MODE; default: return CELL_AUDIO_OUT_ERROR_UNSUPPORTED_SOUND_MODE;
} }
switch(type) switch(type)
@ -710,7 +712,7 @@ int cellAudioOutGetSoundAvailability2(u32 audioOut, u32 type, u32 fs, u32 ch, u3
case CELL_AUDIO_OUT_CODING_TYPE_DTS: case CELL_AUDIO_OUT_CODING_TYPE_DTS:
break; break;
default: CELL_AUDIO_OUT_ERROR_UNSUPPORTED_SOUND_MODE; default: return CELL_AUDIO_OUT_ERROR_UNSUPPORTED_SOUND_MODE;
} }
switch(audioOut) switch(audioOut)
@ -719,8 +721,7 @@ int cellAudioOutGetSoundAvailability2(u32 audioOut, u32 type, u32 fs, u32 ch, u3
case CELL_AUDIO_OUT_SECONDARY: return 0; 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) int cellAudioOutGetState(u32 audioOut, u32 deviceIndex, u32 state_addr)
@ -831,7 +832,7 @@ int cellAudioOutGetNumberOfDevice(u32 audioOut)
case CELL_AUDIO_OUT_SECONDARY: return 0; 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) 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: case CELL_AUDIO_OUT_SECONDARY:
break; break;
default: CELL_AUDIO_OUT_ERROR_UNSUPPORTED_AUDIO_OUT; default: return CELL_AUDIO_OUT_ERROR_UNSUPPORTED_AUDIO_OUT;
} }
switch(control) switch(control)
@ -873,7 +874,7 @@ int cellAudioOutSetCopyControl(u32 audioOut, u32 control)
case CELL_AUDIO_OUT_COPY_CONTROL_COPY_NEVER: case CELL_AUDIO_OUT_COPY_CONTROL_COPY_NEVER:
break; break;
default: CELL_AUDIO_OUT_ERROR_ILLEGAL_PARAMETER; default: return CELL_AUDIO_OUT_ERROR_ILLEGAL_PARAMETER;
} }
return CELL_AUDIO_OUT_SUCCEEDED; 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); 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->entry_point = entry;
img->segs_addr = 0x0; img->segs_addr = offset;
img->nsegs = 0; img->nsegs = 0;
return CELL_OK; return CELL_OK;
@ -119,15 +120,13 @@ int sys_raw_spu_load(int id, u32 path_addr, mem32_t entry)
return CELL_OK; return CELL_OK;
} }
extern u64 g_last_spu_offset;
int sys_raw_spu_image_load(int id, mem_ptr_t<sys_spu_image> img) 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()); 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, 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; return CELL_OK;
} }

View file

@ -3,7 +3,10 @@
#include "Emu/SysCalls/SC_FUNC.h" #include "Emu/SysCalls/SC_FUNC.h"
void sys_fs_init(); 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) 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; 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() void sys_fs_init()
{ {
sys_fs.AddFunc(0x718bf5f8, cellFsOpen); sys_fs.AddFunc(0x718bf5f8, cellFsOpen);
@ -155,6 +232,20 @@ void sys_fs_init()
sys_fs.AddFunc(0x0e2939e5, cellFsFtruncate); sys_fs.AddFunc(0x0e2939e5, cellFsFtruncate);
sys_fs.AddFunc(0xc9dc3ac5, cellFsTruncate); sys_fs.AddFunc(0xc9dc3ac5, cellFsTruncate);
sys_fs.AddFunc(0xcb588dba, cellFsFGetBlockSize); sys_fs.AddFunc(0xcb588dba, cellFsFGetBlockSize);
sys_fs.AddFunc(0xc1c507e7, cellFsAioRead); 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)); } 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> template<typename TR>
func_caller* bind_func(TR (*call)()) 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); 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 cellFsFtruncate(u32 fd, u64 size);
extern int cellFsTruncate(u32 path_addr, 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 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 //cellVideo
extern int cellVideoOutGetState(u32 videoOut, u32 deviceIndex, u32 state_addr); extern int cellVideoOutGetState(u32 videoOut, u32 deviceIndex, u32 state_addr);

View file

@ -3,6 +3,7 @@
#include "Emu/SysCalls/SysCalls.h" #include "Emu/SysCalls/SysCalls.h"
extern Module sys_fs; extern Module sys_fs;
extern Array<vfsStream*> FDs;
int cellFsOpen(u32 path_addr, int flags, mem32_t fd, mem32_t arg, u64 size) 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; 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; 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)", sys_fs.Log("cellFsRead(fd: %d, buf_addr: 0x%x, nbytes: 0x%llx, nread_addr: 0x%x)",
fd, buf_addr, nbytes, nread.GetAddr()); fd, buf_addr, nbytes, nread.GetAddr());
ID id; //ID id;
if(!sys_fs.CheckId(fd, id)) return CELL_ESRCH; //if(!sys_fs.CheckId(fd, id)) return CELL_ESRCH;
vfsStream& file = *(vfsStream*)id.m_data; 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)) 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)", sys_fs.Log("cellFsWrite(fd: %d, buf_addr: 0x%x, nbytes: 0x%llx, nwrite_addr: 0x%x)",
fd, buf_addr, nbytes, nwrite.GetAddr()); fd, buf_addr, nbytes, nwrite.GetAddr());
ID id; //ID id;
if(!sys_fs.CheckId(fd, id)) return CELL_ESRCH; //if(!sys_fs.CheckId(fd, id)) return CELL_ESRCH;
vfsStream& file = *(vfsStream*)id.m_data; 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)) if(Memory.IsGoodAddr(buf_addr) && !Memory.IsGoodAddr(buf_addr, nbytes))
{ {
MemoryBlock& block = Memory.GetMemByAddr(buf_addr); 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) int cellFsClose(u32 fd)
{ {
sys_fs.Log("cellFsClose(fd: %d)", fd); sys_fs.Warning("cellFsClose(fd: %d)", fd);
ID id; //ID id;
if(!sys_fs.CheckId(fd, id)) return CELL_ESRCH; //if(!sys_fs.CheckId(fd, id)) return CELL_ESRCH;
vfsStream& file = *(vfsStream*)id.m_data; 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(); file.Close();
Emu.GetIdManager().RemoveID(fd); delete FDs[fd];
//Emu.GetIdManager().RemoveID(fd);
FDs[fd] = nullptr;
return CELL_OK; 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) int cellFsFstat(u32 fd, mem_ptr_t<CellFsStat> sb)
{ {
sys_fs.Log("cellFsFstat(fd: %d, sb_addr: 0x%x)", fd, sb.GetAddr()); sys_fs.Log("cellFsFstat(fd: %d, sb_addr: 0x%x)", fd, sb.GetAddr());
ID id; //ID id;
if(!sys_fs.CheckId(fd, id)) return CELL_ESRCH; //if(!sys_fs.CheckId(fd, id)) return CELL_ESRCH;
vfsStream& file = *(vfsStream*)id.m_data; 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 = sb->st_mode =
CELL_FS_S_IRUSR | CELL_FS_S_IWUSR | CELL_FS_S_IXUSR | 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); sys_fs.Error(fd, "Unknown seek whence! (%d)", whence);
return CELL_EINVAL; return CELL_EINVAL;
} }
ID id; //ID id;
if(!sys_fs.CheckId(fd, id)) return CELL_ESRCH; //if(!sys_fs.CheckId(fd, id)) return CELL_ESRCH;
vfsStream& file = *(vfsStream*)id.m_data; 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); pos = file.Seek(offset, seek_mode);
return CELL_OK; return CELL_OK;
} }
@ -322,9 +343,12 @@ int cellFsLseek(u32 fd, s64 offset, u32 whence, mem64_t pos)
int cellFsFtruncate(u32 fd, u64 size) int cellFsFtruncate(u32 fd, u64 size)
{ {
sys_fs.Log("cellFsFtruncate(fd: %d, size: %lld)", fd, size); sys_fs.Log("cellFsFtruncate(fd: %d, size: %lld)", fd, size);
ID id; //ID id;
if(!sys_fs.CheckId(fd, id)) return CELL_ESRCH; //if(!sys_fs.CheckId(fd, id)) return CELL_ESRCH;
vfsStream& file = *(vfsStream*)id.m_data; 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(); u64 initialSize = file.GetSize();
if (initialSize < size) if (initialSize < size)
@ -385,49 +409,3 @@ int cellFsFGetBlockSize(u32 fd, mem64_t sector_size, mem64_t block_size)
return CELL_OK; 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) 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)) if(!Memory.IsGoodAddr(cid_addr, 4))
{ {
return CELL_EFAULT; 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) if(!addr)
{ {
return CELL_ENOMEM; return CELL_ENOMEM;
} }
//fix alignment:
addr = (addr + 0x100000) & ~0xfffff;
Memory.Write32(cid_addr, sc_mem.GetNewId(new MemoryContainerInfo(addr, yield_size))); Memory.Write32(cid_addr, sc_mem.GetNewId(new MemoryContainerInfo(addr, yield_size)));
return CELL_OK; 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) int sys_memory_allocate(u32 size, u32 flags, u32 alloc_addr_addr)
{ {
//0x30000100; //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; u32 addr;
switch(flags) switch(flags)
{ {
case SYS_MEMORY_PAGE_SIZE_1M: case SYS_MEMORY_PAGE_SIZE_1M:
if(size & 0xfffff) return CELL_EALIGN; if(size & 0xfffff) return CELL_EALIGN;
addr = Memory.Alloc(size, 0x100000); addr = Memory.Alloc(size + 0x100000, 0x100000);
addr = (addr + 0x100000) & ~0xfffff;
break; break;
case SYS_MEMORY_PAGE_SIZE_64K: case SYS_MEMORY_PAGE_SIZE_64K:
if(size & 0xffff) return CELL_EALIGN; if(size & 0xffff) return CELL_EALIGN;
addr = Memory.Alloc(size, 0x10000); addr = Memory.Alloc(size + 0x10000, 0x10000);
addr = (addr + 0x10000) & ~0xffff;
break; break;
default: return CELL_EINVAL; 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.len = re(len);
data.button[CELL_PAD_BTN_OFFSET_DIGITAL1] = re(d1); data.button[CELL_PAD_BTN_OFFSET_DIGITAL1] = re(d1);
data.button[CELL_PAD_BTN_OFFSET_DIGITAL2] = re(d2); 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_X] = re(rx);
data.button[CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y] = re(pad.m_analog_right_y); data.button[CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y] = re(ry);
data.button[CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X] = re(pad.m_analog_left_x); data.button[CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X] = re(lx);
data.button[CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y] = re(pad.m_analog_left_y); 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_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_LEFT] = re(pad.m_press_left);
data.button[CELL_PAD_BTN_OFFSET_PRESS_UP] = re(pad.m_press_up); 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& spu_ep)
u32 LoadSpuImage(vfsStream& stream)
{ {
ELFLoader l(stream); ELFLoader l(stream);
l.LoadInfo(); l.LoadInfo();
u32 alloc_size = 0xFFFFED - stream.GetSize(); const u32 alloc_size = 256 * 1024 /*0x1000000 - stream.GetSize()*/;
g_last_spu_offset = Memory.MainMem.Alloc(alloc_size); u32 spu_offset = Memory.MainMem.Alloc(alloc_size);
l.LoadData(g_last_spu_offset); l.LoadData(spu_offset);
spu_ep = l.GetEntry();
return g_last_spu_offset + 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 //156
int sys_spu_image_open(mem_ptr_t<sys_spu_image> img, u32 path_addr) 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; return CELL_ENOENT;
} }
u32 entry = LoadSpuImage(f); u32 entry;
u32 offset = LoadSpuImage(f, entry);
img->type = 1; img->type = 1;
img->entry_point = entry; img->entry_point = entry;
img->segs_addr = 0x0; img->segs_addr = offset;
img->nsegs = 0; img->nsegs = 0;
return CELL_OK; 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; 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(); std::string name = Memory.ReadString(attr->name_addr, attr->name_len).mb_str();
u64 a1 = arg->arg1; u64 a1 = arg->arg1;
u64 a2 = arg->arg2; 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); CPUThread& new_thread = Emu.GetCPU().AddThread(CPU_THREAD_SPU);
//copy SPU image: //copy SPU image:
u32 spu_offset = Memory.MainMem.Alloc(256 * 1024); 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: //initialize from new place:
new_thread.SetOffset(spu_offset); new_thread.SetOffset(spu_offset);
new_thread.SetEntry(ls_entry); new_thread.SetEntry(spu_ep);
new_thread.SetName(name); new_thread.SetName(name);
new_thread.SetArg(0, a1); new_thread.SetArg(0, a1);
new_thread.SetArg(1, a2); 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; group_info.threads[spu_num] = &new_thread;
ConLog.Write("New SPU Thread:"); /*ConLog.Write("New SPU Thread:");
ConLog.Write("ls_entry = 0x%x", ls_entry); 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("name = %s", name.c_str());
ConLog.Write("a1 = 0x%x", a1); ConLog.Write("a1 = 0x%x", a1);
ConLog.Write("a2 = 0x%x", a2); ConLog.Write("a2 = 0x%x", a2);
ConLog.Write("a3 = 0x%x", a3); ConLog.Write("a3 = 0x%x", a3);
ConLog.Write("a4 = 0x%x", a4); ConLog.Write("a4 = 0x%x", a4);
ConLog.Write("ls_offset = 0x%x", ((SPUThread&)new_thread).dmac.ls_offset); ConLog.Write("ls_offset = 0x%x", ((SPUThread&)new_thread).dmac.ls_offset);
ConLog.SkipLn(); ConLog.SkipLn();*/
return CELL_OK; return CELL_OK;
} }

View file

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

View file

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

View file

@ -1,6 +1,5 @@
#include "stdafx.h" #include "stdafx.h"
#include "RSXDebugger.h" #include "RSXDebugger.h"
#include "Emu/Memory/Memory.h"
#include "Emu/GS/sysutil_video.h" #include "Emu/GS/sysutil_video.h"
#include "Emu/GS/GCM.h" #include "Emu/GS/GCM.h"
@ -16,6 +15,7 @@ RSXDebugger::RSXDebugger(wxWindow* parent)
: wxFrame(parent, wxID_ANY, "RSX Debugger", wxDefaultPosition, wxSize(700, 450)) : wxFrame(parent, wxID_ANY, "RSX Debugger", wxDefaultPosition, wxSize(700, 450))
, m_item_count(23) , m_item_count(23)
, m_addr(0x0) , m_addr(0x0)
, m_cur_texture(0)
, exit(false) , exit(false)
{ {
this->SetBackgroundColour(wxColour(240,240,240)); //This fix the ugly background color under Windows 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); wxBoxSizer& s_tools = *new wxBoxSizer(wxVERTICAL);
// Controls // Controls
wxStaticBoxSizer& s_controls = *new wxStaticBoxSizer(wxHORIZONTAL, this, "Memory Viewer Options"); wxStaticBoxSizer& s_controls = *new wxStaticBoxSizer(wxHORIZONTAL, this, "RSX Debugger Controls");
// Controls: Address // Controls: Address
wxStaticBoxSizer& s_controls_addr = *new wxStaticBoxSizer(wxHORIZONTAL, this, "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_flags->InsertColumn(1, "Value", 0, 270);
m_list_lightning->InsertColumn(0, "Name", 0, 170); m_list_lightning->InsertColumn(0, "Name", 0, 170);
m_list_lightning->InsertColumn(1, "Value", 0, 270); 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(0, "Name", 0, 170);
m_list_settings->InsertColumn(1, "Value", 0, 270); m_list_settings->InsertColumn(1, "Value", 0, 270);
@ -182,22 +191,24 @@ RSXDebugger::RSXDebugger(wxWindow* parent)
SetSizerAndFit(&s_panel); SetSizerAndFit(&s_panel);
//Events //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(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_get->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(RSXDebugger::GoToGet));
Connect(b_goto_put->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(RSXDebugger::GoToPut)); 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_colorA->Connect(wxID_ANY, wxEVT_LEFT_DOWN, wxMouseEventHandler(RSXDebugger::OnClickBuffer), nullptr, this);
p_buffer_colorB->Connect(wxID_ANY, wxEVT_LEFT_DOWN, wxMouseEventHandler(RSXDebugger::OnClickBuffer), NULL, 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), NULL, 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), NULL, 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_depth->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(RSXDebugger::OnClickBuffer));
//Connect(p_buffer_stencil->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_commands->Connect(wxEVT_MOUSEWHEEL, wxMouseEventHandler(RSXDebugger::OnScrollMemory), nullptr, this);
m_list_flags->Connect(wxEVT_COMMAND_LIST_ITEM_ACTIVATED, wxListEventHandler(RSXDebugger::SetFlags), NULL, 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 //Fill the frame
UpdateInformation(); UpdateInformation();
@ -205,10 +216,15 @@ RSXDebugger::RSXDebugger(wxWindow* parent)
void RSXDebugger::OnKeyDown(wxKeyEvent& event) 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) void RSXDebugger::OnChangeToolsAddr(wxCommandEvent& event)
@ -221,8 +237,34 @@ void RSXDebugger::OnChangeToolsAddr(wxCommandEvent& event)
void RSXDebugger::OnScrollMemory(wxMouseEvent& event) void RSXDebugger::OnScrollMemory(wxMouseEvent& event)
{ {
m_addr -= (event.ControlDown() ? m_item_count : 1) * 4 * (event.GetWheelRotation() / event.GetWheelDelta()); if(Memory.IsGoodAddr(m_addr))
t_addr->SetValue(wxString::Format("%08x", 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(); UpdateInformation();
event.Skip(); event.Skip();
} }
@ -233,10 +275,17 @@ void RSXDebugger::OnClickBuffer(wxMouseEvent& event)
const GSRender& render = Emu.GetGSManager().GetRender(); const GSRender& render = Emu.GetGSManager().GetRender();
const mem_ptr_t<gcmBuffer> buffers = render.m_gcm_buffers_addr; 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 // TODO: Is there any better way to choose the color buffers
#define SHOW_BUFFER(id) \ #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_colorA->GetId()) SHOW_BUFFER(0);
if (event.GetId() == p_buffer_colorB->GetId()) SHOW_BUFFER(1); 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_colorD->GetId()) SHOW_BUFFER(3);
if (event.GetId() == p_buffer_tex->GetId()) if (event.GetId() == p_buffer_tex->GetId())
{ {
MemoryViewerPanel::ShowImage(this, 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)
render.m_textures[0].m_offset, 0, MemoryViewerPanel::ShowImage(this,
render.m_textures[0].m_width, render.m_textures[m_cur_texture].m_offset, 0,
render.m_textures[0].m_height, false); render.m_textures[m_cur_texture].m_width,
render.m_textures[m_cur_texture].m_height, false);
} }
#undef SHOW_BUFFER #undef SHOW_BUFFER
@ -275,6 +325,7 @@ void RSXDebugger::GoToPut(wxCommandEvent& event)
void RSXDebugger::UpdateInformation() void RSXDebugger::UpdateInformation()
{ {
t_addr->SetValue(wxString::Format("%08x", m_addr));
GetMemory(); GetMemory();
GetBuffers(); GetBuffers();
GetFlags(); GetFlags();
@ -289,26 +340,24 @@ void RSXDebugger::GetMemory()
for(u32 i=0; i<m_item_count; i++) for(u32 i=0; i<m_item_count; i++)
m_list_commands->SetItem(i, 2, wxEmptyString); m_list_commands->SetItem(i, 2, wxEmptyString);
u32 ioAddr = RSXReady() ? Emu.GetGSManager().GetRender().m_ioAddress : 0;
// Write information // 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)); 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 cmd = Memory.Read32(addr);
u32 count = (cmd >> 18) & 0x7ff; 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, 1, wxString::Format("%08x", cmd));
m_list_commands->SetItem(i, 3, wxString::Format("%d", count)); 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); addr += 4 * count;
for (u32 j=0; j<count && i+j<m_item_count; j++)
{
m_list_commands->SetItem(i+j, 2, disasm);
}
} }
} }
else else
@ -327,8 +376,15 @@ void RSXDebugger::GetBuffers()
// TODO: Currently it only supports color buffers // TODO: Currently it only supports color buffers
for (u32 bufferId=0; bufferId < render.m_gcm_buffers_count; bufferId++) 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); gcmBuffer* buffers = (gcmBuffer*)Memory.GetMemFromAddr(render.m_gcm_buffers_addr);
u32 RSXbuffer_addr = render.m_local_mem_addr + re(buffers[bufferId].offset); 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); unsigned char* RSXbuffer = (unsigned char*)Memory.VirtualToRealAddr(RSXbuffer_addr);
u32 width = re(buffers[bufferId].width); u32 width = re(buffers[bufferId].width);
@ -361,11 +417,15 @@ void RSXDebugger::GetBuffers()
} }
// Draw Texture // 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); unsigned char* TexBuffer = (unsigned char*)Memory.VirtualToRealAddr(TexBuffer_addr);
u32 width = render.m_textures[0].m_width; u32 width = render.m_textures[m_cur_texture].m_width;
u32 height = render.m_textures[0].m_height; u32 height = render.m_textures[m_cur_texture].m_height;
unsigned char* buffer = (unsigned char*)malloc(width * height * 3); unsigned char* buffer = (unsigned char*)malloc(width * height * 3);
memcpy(buffer, TexBuffer, width * height * 3); memcpy(buffer, TexBuffer, width * height * 3);
@ -421,24 +481,23 @@ void RSXDebugger::GetTexture()
if (!RSXReady()) return; if (!RSXReady()) return;
const GSRender& render = Emu.GetGSManager().GetRender(); const GSRender& render = Emu.GetGSManager().GetRender();
m_list_texture->DeleteAllItems(); m_list_texture->DeleteAllItems();
int i=0;
#define LIST_TEXTURE_ADD(name, value) \ for(uint i=0; i<RSXThread::m_textures_count; ++i)
m_list_texture->InsertItem(i, name); m_list_texture->SetItem(i, 1, value); 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)); m_list_texture->SetItemBackgroundColour(i, wxColour(m_cur_texture == i ? "Wheat" : "White"));
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
} }
void RSXDebugger::GetSettings() void RSXDebugger::GetSettings()
@ -524,6 +583,15 @@ void RSXDebugger::SetFlags(wxListEvent& event)
case 11: render.m_set_poly_offset_point ^= true; break; case 11: render.m_set_poly_offset_point ^= true; break;
case 12: render.m_set_stencil_test ^= 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(); UpdateInformation();
} }
@ -616,117 +684,135 @@ wxString RSXDebugger::ParseGCMEnum(u32 value, u32 type)
wxString RSXDebugger::DisAsmCommand(u32 cmd, u32 count, u32 currentAddr, u32 ioAddr) wxString RSXDebugger::DisAsmCommand(u32 cmd, u32 count, u32 currentAddr, u32 ioAddr)
{ {
wxString disasm = wxEmptyString; 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) if(cmd & CELL_GCM_METHOD_FLAG_JUMP)
{ {
u32 jumpAddr = cmd & ~(CELL_GCM_METHOD_FLAG_JUMP | CELL_GCM_METHOD_FLAG_NON_INCREMENT); 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; 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) if(cmd == CELL_GCM_METHOD_FLAG_RETURN)
{ {
disasm = "RETURN"; DISASM("RETURN");
}
if(cmd & CELL_GCM_METHOD_FLAG_NON_INCREMENT)
{
disasm = "Non Increment cmd";
} }
if(cmd == 0) if(cmd == 0)
{ {
disasm = "Null cmd"; DISASM("Null cmd");
} }
else if(!(cmd & (CELL_GCM_METHOD_FLAG_JUMP | CELL_GCM_METHOD_FLAG_CALL)) && cmd != CELL_GCM_METHOD_FLAG_RETURN)
u32 index = 0;
mem32_ptr_t args(currentAddr + 4);
switch(cmd & 0x3ffff)
{ {
case 0x3fead: mem32_ptr_t args(currentAddr + 4);
disasm = "???"; break;
case NV4097_NO_OPERATION:
disasm = "NOP"; break;
case NV406E_SET_REFERENCE:
disasm = "???"; break;
case_16(NV4097_SET_TEXTURE_OFFSET, 0x20): u32 index = 0;
disasm = wxString::Format(" Texture Offset: %08x", args[0]); switch(cmd & 0x3ffff)
switch ((args[1] & 0x3) - 1)
{ {
case CELL_GCM_LOCATION_LOCAL: disasm += " (Local memory);"; break; case 0x3fead:
case CELL_GCM_LOCATION_MAIN: disasm += " (Main memory);"; break; DISASM("Flip and change current buffer: %d", args[0]);
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:
break; 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; return disasm;
} }
bool RSXDebugger::RSXReady() 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 return Emu.GetGSManager().IsInited();
const GSRender& render = Emu.GetGSManager().GetRender();
if (!&render)
{
return false;
}
return true;
} }

View file

@ -4,6 +4,8 @@
class RSXDebugger : public wxFrame class RSXDebugger : public wxFrame
{ {
AppConnector m_app_connector;
u32 m_addr; u32 m_addr;
u32 m_panel_width; u32 m_panel_width;
@ -28,6 +30,8 @@ class RSXDebugger : public wxFrame
wxPanel* p_buffer_stencil; wxPanel* p_buffer_stencil;
wxPanel* p_buffer_tex; wxPanel* p_buffer_tex;
uint m_cur_texture;
public: public:
bool exit; bool exit;
RSXDebugger(wxWindow* parent); RSXDebugger(wxWindow* parent);
@ -53,7 +57,8 @@ public:
virtual void GetSettings(); virtual void GetSettings();
virtual void SetFlags(wxListEvent& event); virtual void SetFlags(wxListEvent& event);
virtual void OnSelectTexture(wxListEvent& event);
wxString ParseGCMEnum(u32 value, u32 type); wxString ParseGCMEnum(u32 value, u32 type);
wxString DisAsmCommand(u32 cmd, u32 count, u32 currentAddr, u32 ioAddr); 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); m_list->SetItemState(i, i == idx ? wxLIST_STATE_SELECTED : ~wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
} }
wxCommandEvent ce; wxCommandEvent ce;
OnEntryConfig(ce); OnEntryConfig(ce);
} }

View file

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

View file

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