From cbeadcf872f2560941eb49656f600ca2e762bfff Mon Sep 17 00:00:00 2001 From: DH Date: Tue, 7 Jan 2014 09:30:41 +0200 Subject: [PATCH 1/8] Improved RSX Debugger - Fixed crash in debug build. - Implemented texture selection. --- rpcs3/Emu/GS/GSManager.h | 2 + rpcs3/Gui/RSXDebugger.cpp | 365 +++++++++++++++++++++++--------------- rpcs3/Gui/RSXDebugger.h | 7 +- 3 files changed, 234 insertions(+), 140 deletions(-) diff --git a/rpcs3/Emu/GS/GSManager.h b/rpcs3/Emu/GS/GSManager.h index 7ab4fda396..bafa6961c3 100644 --- a/rpcs3/Emu/GS/GSManager.h +++ b/rpcs3/Emu/GS/GSManager.h @@ -51,6 +51,8 @@ public: void Init(); void Close(); + bool IsInited() const { return m_render != nullptr; } + GSInfo& GetInfo() { return m_info; } GSRender& GetRender() { assert(m_render); return *m_render; } diff --git a/rpcs3/Gui/RSXDebugger.cpp b/rpcs3/Gui/RSXDebugger.cpp index 67a7ec7f0a..d675ab8b3f 100644 --- a/rpcs3/Gui/RSXDebugger.cpp +++ b/rpcs3/Gui/RSXDebugger.cpp @@ -16,6 +16,7 @@ RSXDebugger::RSXDebugger(wxWindow* parent) : wxFrame(parent, wxID_ANY, "RSX Debugger", wxDefaultPosition, wxSize(700, 450)) , m_item_count(23) , m_addr(0x0) + , m_cur_texture(0) , exit(false) { this->SetBackgroundColour(wxColour(240,240,240)); //This fix the ugly background color under Windows @@ -101,8 +102,17 @@ RSXDebugger::RSXDebugger(wxWindow* parent) m_list_flags->InsertColumn(1, "Value", 0, 270); m_list_lightning->InsertColumn(0, "Name", 0, 170); m_list_lightning->InsertColumn(1, "Value", 0, 270); - m_list_texture->InsertColumn(0, "Name", 0, 170); - m_list_texture->InsertColumn(1, "Value", 0, 270); + + m_list_texture->InsertColumn(0, "Index"); + m_list_texture->InsertColumn(1, "Address"); + m_list_texture->InsertColumn(2, "Cubemap"); + m_list_texture->InsertColumn(3, "Dimension"); + m_list_texture->InsertColumn(4, "Enabled"); + m_list_texture->InsertColumn(5, "Format"); + m_list_texture->InsertColumn(6, "Mipmap"); + m_list_texture->InsertColumn(7, "Pitch"); + m_list_texture->InsertColumn(8, "Size"); + m_list_settings->InsertColumn(0, "Name", 0, 170); m_list_settings->InsertColumn(1, "Value", 0, 270); @@ -182,22 +192,24 @@ RSXDebugger::RSXDebugger(wxWindow* parent) SetSizerAndFit(&s_panel); //Events - Connect(wxID_ANY, wxEVT_KEY_DOWN, wxKeyEventHandler(RSXDebugger::OnKeyDown), NULL, this); + m_app_connector.Connect(wxID_ANY, wxEVT_KEY_DOWN, wxKeyEventHandler(RSXDebugger::OnKeyDown), nullptr, this); Connect(t_addr->GetId(), wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler(RSXDebugger::OnChangeToolsAddr)); Connect(b_goto_get->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(RSXDebugger::GoToGet)); Connect(b_goto_put->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(RSXDebugger::GoToPut)); - p_buffer_colorA->Connect(wxID_ANY, wxEVT_LEFT_DOWN, wxMouseEventHandler(RSXDebugger::OnClickBuffer), NULL, this); - p_buffer_colorB->Connect(wxID_ANY, wxEVT_LEFT_DOWN, wxMouseEventHandler(RSXDebugger::OnClickBuffer), NULL, this); - p_buffer_colorC->Connect(wxID_ANY, wxEVT_LEFT_DOWN, wxMouseEventHandler(RSXDebugger::OnClickBuffer), NULL, this); - p_buffer_colorD->Connect(wxID_ANY, wxEVT_LEFT_DOWN, wxMouseEventHandler(RSXDebugger::OnClickBuffer), NULL, this); + p_buffer_colorA->Connect(wxID_ANY, wxEVT_LEFT_DOWN, wxMouseEventHandler(RSXDebugger::OnClickBuffer), nullptr, this); + p_buffer_colorB->Connect(wxID_ANY, wxEVT_LEFT_DOWN, wxMouseEventHandler(RSXDebugger::OnClickBuffer), nullptr, this); + p_buffer_colorC->Connect(wxID_ANY, wxEVT_LEFT_DOWN, wxMouseEventHandler(RSXDebugger::OnClickBuffer), nullptr, this); + p_buffer_colorD->Connect(wxID_ANY, wxEVT_LEFT_DOWN, wxMouseEventHandler(RSXDebugger::OnClickBuffer), nullptr, this); //Connect(p_buffer_depth->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(RSXDebugger::OnClickBuffer)); //Connect(p_buffer_stencil->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(RSXDebugger::OnClickBuffer)); - p_buffer_tex->Connect(wxID_ANY, wxEVT_LEFT_DOWN, wxMouseEventHandler(RSXDebugger::OnClickBuffer), NULL, this); + p_buffer_tex->Connect(wxID_ANY, wxEVT_LEFT_DOWN, wxMouseEventHandler(RSXDebugger::OnClickBuffer), nullptr, this); - m_list_commands->Connect(wxEVT_MOUSEWHEEL, wxMouseEventHandler(RSXDebugger::OnScrollMemory), NULL, this); - m_list_flags->Connect(wxEVT_COMMAND_LIST_ITEM_ACTIVATED, wxListEventHandler(RSXDebugger::SetFlags), NULL, this); + m_list_commands->Connect(wxEVT_MOUSEWHEEL, wxMouseEventHandler(RSXDebugger::OnScrollMemory), nullptr, this); + m_list_flags->Connect(wxEVT_COMMAND_LIST_ITEM_ACTIVATED, wxListEventHandler(RSXDebugger::SetFlags), nullptr, this); + + m_list_texture->Connect(wxID_ANY, wxEVT_COMMAND_LIST_ITEM_ACTIVATED, wxListEventHandler(RSXDebugger::OnSelectTexture), nullptr, this); //Fill the frame UpdateInformation(); @@ -205,10 +217,15 @@ RSXDebugger::RSXDebugger(wxWindow* parent) void RSXDebugger::OnKeyDown(wxKeyEvent& event) { - switch(event.GetKeyCode()) + if(wxGetActiveWindow() == wxGetTopLevelParent(this)) { - case WXK_F5: UpdateInformation(); break; + switch(event.GetKeyCode()) + { + case WXK_F5: UpdateInformation(); return; + } } + + event.Skip(); } void RSXDebugger::OnChangeToolsAddr(wxCommandEvent& event) @@ -221,8 +238,34 @@ void RSXDebugger::OnChangeToolsAddr(wxCommandEvent& event) void RSXDebugger::OnScrollMemory(wxMouseEvent& event) { - m_addr -= (event.ControlDown() ? m_item_count : 1) * 4 * (event.GetWheelRotation() / event.GetWheelDelta()); - t_addr->SetValue(wxString::Format("%08x", m_addr)); + if(Memory.IsGoodAddr(m_addr)) + { + int items = event.ControlDown() ? m_item_count : 1; + + for(int i=0; i> 18) & 0x7ff; + + offset = 1 + count; + } + else + { + offset = 1; + } + + m_addr -= 4 * offset * (event.GetWheelRotation() / event.GetWheelDelta()); + } + } + else + { + m_addr -= (event.ControlDown() ? m_item_count : 1) * 4 * (event.GetWheelRotation() / event.GetWheelDelta()); + } + UpdateInformation(); event.Skip(); } @@ -233,10 +276,17 @@ void RSXDebugger::OnClickBuffer(wxMouseEvent& event) const GSRender& render = Emu.GetGSManager().GetRender(); const mem_ptr_t buffers = render.m_gcm_buffers_addr; + if(!buffers.IsGood()) + return; + // TODO: Is there any better way to choose the color buffers #define SHOW_BUFFER(id) \ - MemoryViewerPanel::ShowImage(this, render.m_local_mem_addr + re(buffers[id].offset), \ - 3, re(buffers[id].width), re(buffers[id].height), true); + { \ + u32 addr = render.m_local_mem_addr + re(buffers[id].offset); \ + if(Memory.IsGoodAddr(addr) && buffers[id].width && buffers[id].height) \ + MemoryViewerPanel::ShowImage(this, addr, 3, re(buffers[id].width), re(buffers[id].height), true); \ + return; \ + } \ if (event.GetId() == p_buffer_colorA->GetId()) SHOW_BUFFER(0); if (event.GetId() == p_buffer_colorB->GetId()) SHOW_BUFFER(1); @@ -244,10 +294,11 @@ void RSXDebugger::OnClickBuffer(wxMouseEvent& event) if (event.GetId() == p_buffer_colorD->GetId()) SHOW_BUFFER(3); if (event.GetId() == p_buffer_tex->GetId()) { - MemoryViewerPanel::ShowImage(this, - render.m_textures[0].m_offset, 0, - render.m_textures[0].m_width, - render.m_textures[0].m_height, false); + if(Memory.IsGoodAddr(render.m_textures[m_cur_texture].m_offset) && render.m_textures[m_cur_texture].m_width && render.m_textures[m_cur_texture].m_height) + MemoryViewerPanel::ShowImage(this, + render.m_textures[m_cur_texture].m_offset, 0, + render.m_textures[m_cur_texture].m_width, + render.m_textures[m_cur_texture].m_height, false); } #undef SHOW_BUFFER @@ -275,6 +326,7 @@ void RSXDebugger::GoToPut(wxCommandEvent& event) void RSXDebugger::UpdateInformation() { + t_addr->SetValue(wxString::Format("%08x", m_addr)); GetMemory(); GetBuffers(); GetFlags(); @@ -289,26 +341,24 @@ void RSXDebugger::GetMemory() for(u32 i=0; iSetItem(i, 2, wxEmptyString); + u32 ioAddr = RSXReady() ? Emu.GetGSManager().GetRender().m_ioAddress : 0; + // Write information - for(u32 i=0; iSetItem(i, 0, wxString::Format("%08x", addr)); - if (Memory.IsGoodAddr(addr)) + if (ioAddr && Memory.IsGoodAddr(addr)) { u32 cmd = Memory.Read32(addr); u32 count = (cmd >> 18) & 0x7ff; - u32 ioAddr = Emu.GetGSManager().GetRender().m_ioAddress; m_list_commands->SetItem(i, 1, wxString::Format("%08x", cmd)); m_list_commands->SetItem(i, 3, wxString::Format("%d", count)); - if (count > 0) + m_list_commands->SetItem(i, 2, DisAsmCommand(cmd, count, addr, ioAddr)); + + if(!(cmd & (CELL_GCM_METHOD_FLAG_JUMP | CELL_GCM_METHOD_FLAG_CALL)) && cmd != CELL_GCM_METHOD_FLAG_RETURN) { - wxString disasm = DisAsmCommand(cmd, count, addr, ioAddr); - for (u32 j=0; jSetItem(i+j, 2, disasm); - } + addr += 4 * count; } } else @@ -327,8 +377,15 @@ void RSXDebugger::GetBuffers() // TODO: Currently it only supports color buffers for (u32 bufferId=0; bufferId < render.m_gcm_buffers_count; bufferId++) { + if(!Memory.IsGoodAddr(render.m_gcm_buffers_addr)) + continue; + gcmBuffer* buffers = (gcmBuffer*)Memory.GetMemFromAddr(render.m_gcm_buffers_addr); u32 RSXbuffer_addr = render.m_local_mem_addr + re(buffers[bufferId].offset); + + if(!Memory.IsGoodAddr(RSXbuffer_addr)) + continue; + unsigned char* RSXbuffer = (unsigned char*)Memory.VirtualToRealAddr(RSXbuffer_addr); u32 width = re(buffers[bufferId].width); @@ -361,11 +418,15 @@ void RSXDebugger::GetBuffers() } // Draw Texture - u32 TexBuffer_addr = render.m_textures[0].m_offset; + u32 TexBuffer_addr = render.m_textures[m_cur_texture].m_offset; + + if(!Memory.IsGoodAddr(TexBuffer_addr)) + return; + unsigned char* TexBuffer = (unsigned char*)Memory.VirtualToRealAddr(TexBuffer_addr); - u32 width = render.m_textures[0].m_width; - u32 height = render.m_textures[0].m_height; + u32 width = render.m_textures[m_cur_texture].m_width; + u32 height = render.m_textures[m_cur_texture].m_height; unsigned char* buffer = (unsigned char*)malloc(width * height * 3); memcpy(buffer, TexBuffer, width * height * 3); @@ -421,24 +482,23 @@ void RSXDebugger::GetTexture() if (!RSXReady()) return; const GSRender& render = Emu.GetGSManager().GetRender(); m_list_texture->DeleteAllItems(); - int i=0; -#define LIST_TEXTURE_ADD(name, value) \ - m_list_texture->InsertItem(i, name); m_list_texture->SetItem(i, 1, value); i++; + for(uint i=0; iInsertItem(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("%d x %d", + render.m_textures[i].m_width, + render.m_textures[i].m_height)); - LIST_TEXTURE_ADD("Texture #0 Address:", wxString::Format("0x%x", render.m_textures[0].m_offset)); - LIST_TEXTURE_ADD("Texture #0 Cubemap:", render.m_textures[0].m_cubemap ? "True" : "False"); - LIST_TEXTURE_ADD("Texture #0 Depth:", wxString::Format("0x%x", render.m_textures[0].m_depth)); - LIST_TEXTURE_ADD("Texture #0 Dimension:", wxString::Format("0x%x", render.m_textures[0].m_dimension)); - LIST_TEXTURE_ADD("Texture #0 Enabled:", render.m_textures[0].m_enabled ? "True" : "False"); - LIST_TEXTURE_ADD("Texture #0 Format:", wxString::Format("0x%x", render.m_textures[0].m_format)); - LIST_TEXTURE_ADD("Texture #0 Mipmap:", wxString::Format("0x%x", render.m_textures[0].m_mipmap)); - LIST_TEXTURE_ADD("Texture #0 Pitch:", wxString::Format("0x%x", render.m_textures[0].m_pitch)); - LIST_TEXTURE_ADD("Texture #0 Size:", wxString::Format("%d x %d", - render.m_textures[0].m_width, - render.m_textures[0].m_height)); - -#undef LIST_TEXTURE_ADD + m_list_texture->SetItemBackgroundColour(i, wxColour(m_cur_texture == i ? "Wheat" : "White")); + } } void RSXDebugger::GetSettings() @@ -524,6 +584,15 @@ void RSXDebugger::SetFlags(wxListEvent& event) case 11: render.m_set_poly_offset_point ^= true; break; case 12: render.m_set_stencil_test ^= true; break; } + + UpdateInformation(); +} + +void RSXDebugger::OnSelectTexture(wxListEvent& event) +{ + if(event.GetIndex() >= 0) + m_cur_texture = event.GetIndex(); + UpdateInformation(); } @@ -616,117 +685,135 @@ wxString RSXDebugger::ParseGCMEnum(u32 value, u32 type) wxString RSXDebugger::DisAsmCommand(u32 cmd, u32 count, u32 currentAddr, u32 ioAddr) { wxString disasm = wxEmptyString; + +#define DISASM(string, ...) if(disasm.IsEmpty()) disasm = wxString::Format((string), ##__VA_ARGS__); else disasm += (wxString(' ') + wxString::Format((string), ##__VA_ARGS__)) if(cmd & CELL_GCM_METHOD_FLAG_JUMP) { u32 jumpAddr = cmd & ~(CELL_GCM_METHOD_FLAG_JUMP | CELL_GCM_METHOD_FLAG_NON_INCREMENT); - disasm = wxString::Format("JUMP: %08x -> %08x", currentAddr, ioAddr+jumpAddr); + DISASM("JUMP: %08x -> %08x", currentAddr, ioAddr+jumpAddr); } - if(cmd & CELL_GCM_METHOD_FLAG_CALL) + else if(cmd & CELL_GCM_METHOD_FLAG_CALL) { u32 callAddr = cmd & ~CELL_GCM_METHOD_FLAG_CALL; - disasm = wxString::Format("CALL: %08x -> %08x", currentAddr, ioAddr+callAddr); + DISASM("CALL: %08x -> %08x", currentAddr, ioAddr+callAddr); } if(cmd == CELL_GCM_METHOD_FLAG_RETURN) { - disasm = "RETURN"; - } - if(cmd & CELL_GCM_METHOD_FLAG_NON_INCREMENT) - { - disasm = "Non Increment cmd"; + DISASM("RETURN"); } + if(cmd == 0) { - disasm = "Null cmd"; + DISASM("Null cmd"); } - - u32 index = 0; - mem32_ptr_t args(currentAddr + 4); - switch(cmd & 0x3ffff) + else if(!(cmd & (CELL_GCM_METHOD_FLAG_JUMP | CELL_GCM_METHOD_FLAG_CALL)) && cmd != CELL_GCM_METHOD_FLAG_RETURN) { - case 0x3fead: - disasm = "???"; break; - case NV4097_NO_OPERATION: - disasm = "NOP"; break; - case NV406E_SET_REFERENCE: - disasm = "???"; break; + mem32_ptr_t args(currentAddr + 4); - case_16(NV4097_SET_TEXTURE_OFFSET, 0x20): - disasm = wxString::Format(" Texture Offset: %08x", args[0]); - switch ((args[1] & 0x3) - 1) + u32 index = 0; + switch(cmd & 0x3ffff) { - case CELL_GCM_LOCATION_LOCAL: disasm += " (Local memory);"; break; - case CELL_GCM_LOCATION_MAIN: disasm += " (Main memory);"; break; - default: disasm += " (Bad location!);"; break; - } - disasm += wxString::Format(" Cubemap:%s; Dimension:0x%x; Format:0x%x; Mipmap:0x%x", - ((args[1] >> 2) & 0x1) ? "True" : "False", - ((args[1] >> 4) & 0xf), - ((args[1] >> 8) & 0xff), - ((args[1] >> 16) & 0xffff)); - break; - - case NV4097_SET_COLOR_MASK: - disasm = wxString::Format(" Color mask: True (A:%d, R:%d, G:%d, B:%d)", - args[0] & 0x1000000 ? "1" : "0", - args[0] & 0x0010000 ? "1" : "0", - args[0] & 0x0000100 ? "1" : "0", - args[0] & 0x0000001 ? "1" : "0"); - break; - - case NV4097_SET_ALPHA_TEST_ENABLE: - disasm = args[0] ? "Alpha test: Enable" : "Alpha test: Disable"; - break; - - case NV4097_SET_BLEND_ENABLE: - disasm = args[0] ? "Blend: Enable" : "Blend: Disable"; - break; - - case NV4097_SET_DEPTH_BOUNDS_TEST_ENABLE: - disasm = args[0] ? "Depth bounds test: Enable" : "Depth bounds test: Disable"; - break; - - case NV4097_SET_CONTEXT_DMA_COLOR_A: - disasm = wxString::Format("Context DMA Color A: 0x%x", args[0]); - break; - - case NV4097_SET_CONTEXT_DMA_COLOR_B: - disasm = wxString::Format("Context DMA Color B: 0x%x", args[0]); - break; - - case NV4097_SET_CONTEXT_DMA_COLOR_C: - disasm = wxString::Format("Context DMA Color C: 0x%x", args[0]); - if(count > 1) - disasm = wxString::Format("Context DMA Color C: 0x%x", args[1]); - break; - - case NV4097_SET_CONTEXT_DMA_ZETA: - disasm = wxString::Format("Context DMA Zeta: 0x%x", args[0]); - break; - - case NV4097_SET_SURFACE_PITCH_C: - disasm = wxString::Format("Surface Pitch C: 0x%x; ", args[0]); - disasm += wxString::Format("Surface Pitch D: 0x%x; ", args[1]); - disasm += wxString::Format("Surface Offset C: 0x%x; ", args[2]); - disasm += wxString::Format("Surface Offset D: 0x%x", args[3]); - break; - - case NV4097_SET_SURFACE_PITCH_Z: - disasm = wxString::Format("Surface Pitch Z: 0x%x; ", args[0]); - break; - - default: + case 0x3fead: + DISASM("Flip and change current buffer: %d", args[0]); break; + + case NV4097_NO_OPERATION: + DISASM("NOP"); + break; + + case NV406E_SET_REFERENCE: + DISASM("Set reference: 0x%x", args[0]); + break; + + case_16(NV4097_SET_TEXTURE_OFFSET, 0x20): + DISASM("Texture Offset[%d]: %08x", index, args[0]); + switch ((args[1] & 0x3) - 1) + { + case CELL_GCM_LOCATION_LOCAL: DISASM("(Local memory);"); break; + case CELL_GCM_LOCATION_MAIN: DISASM("(Main memory);"); break; + default: DISASM("(Bad location!);"); break; + } + DISASM(" Cubemap:%s; Dimension:0x%x; Format:0x%x; Mipmap:0x%x", + ((args[1] >> 2) & 0x1) ? "True" : "False", + ((args[1] >> 4) & 0xf), + ((args[1] >> 8) & 0xff), + ((args[1] >> 16) & 0xffff)); + break; + + case NV4097_SET_COLOR_MASK: + DISASM(" Color mask: True (A:%c, R:%c, G:%c, B:%c)", + args[0] & 0x1000000 ? '1' : '0', + args[0] & 0x0010000 ? '1' : '0', + args[0] & 0x0000100 ? '1' : '0', + args[0] & 0x0000001 ? '1' : '0'); + break; + + case NV4097_SET_ALPHA_TEST_ENABLE: + DISASM(args[0] ? "Alpha test: Enable" : "Alpha test: Disable"); + break; + + case NV4097_SET_BLEND_ENABLE: + DISASM(args[0] ? "Blend: Enable" : "Blend: Disable"); + break; + + case NV4097_SET_DEPTH_BOUNDS_TEST_ENABLE: + DISASM(args[0] ? "Depth bounds test: Enable" : "Depth bounds test: Disable"); + break; + + case NV4097_SET_CONTEXT_DMA_COLOR_A: + DISASM("Context DMA Color A: 0x%x", args[0]); + break; + + case NV4097_SET_CONTEXT_DMA_COLOR_B: + DISASM("Context DMA Color B: 0x%x", args[0]); + break; + + case NV4097_SET_CONTEXT_DMA_COLOR_C: + DISASM("Context DMA Color C: 0x%x", args[0]); + if(count > 1) + DISASM("0x%x", args[1]); + break; + + case NV4097_SET_CONTEXT_DMA_ZETA: + DISASM("Context DMA Zeta: 0x%x", args[0]); + break; + + case NV4097_SET_SURFACE_PITCH_C: + DISASM("Surface Pitch C: 0x%x;", args[0]); + DISASM("Surface Pitch D: 0x%x;", args[1]); + DISASM("Surface Offset C: 0x%x;", args[2]); + DISASM("Surface Offset D: 0x%x", args[3]); + break; + + case NV4097_SET_SURFACE_PITCH_Z: + DISASM("Surface Pitch Z: 0x%x;", args[0]); + break; + + default: + break; + } + + if(cmd & CELL_GCM_METHOD_FLAG_NON_INCREMENT) + { + DISASM("Non Increment cmd"); + } + + DISASM("[0x%08x(", cmd); + + for(uint i=0; i Date: Tue, 7 Jan 2014 22:11:02 +0200 Subject: [PATCH 2/8] Improved Vertex Shader Decompiler. Fixed VFS Manager crash. Fixed SPU image loader. Draft implementation of cellFsAioRead. Improved Callbacks. --- rpcs3/Emu/FS/VFS.h | 6 +- rpcs3/Emu/GS/GL/GLVertexProgram.cpp | 148 ++++++++++++++++++----- rpcs3/Emu/GS/GL/GLVertexProgram.h | 24 +++- rpcs3/Emu/GS/RSXThread.cpp | 66 +++++++++- rpcs3/Emu/GS/RSXThread.h | 2 +- rpcs3/Emu/SysCalls/Callback.cpp | 13 +- rpcs3/Emu/SysCalls/Callback.h | 6 +- rpcs3/Emu/SysCalls/Modules/sys_fs.cpp | 27 ++++- rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp | 15 ++- rpcs3/Gui/RSXDebugger.cpp | 2 +- rpcs3/Gui/VFSManager.cpp | 2 +- rpcs3/Loader/ELF32.cpp | 4 +- 12 files changed, 262 insertions(+), 53 deletions(-) diff --git a/rpcs3/Emu/FS/VFS.h b/rpcs3/Emu/FS/VFS.h index d46182fc51..2a09f20b74 100644 --- a/rpcs3/Emu/FS/VFS.h +++ b/rpcs3/Emu/FS/VFS.h @@ -20,7 +20,11 @@ struct VFSManagerEntry char* mount; vfsDeviceType device; - VFSManagerEntry() : device(vfsDevice_LocalFile) + VFSManagerEntry() + : device(vfsDevice_LocalFile) + , device_path("") + , path("") + , mount("") { } }; diff --git a/rpcs3/Emu/GS/GL/GLVertexProgram.cpp b/rpcs3/Emu/GS/GL/GLVertexProgram.cpp index 6dca47ffe7..96232ebd02 100644 --- a/rpcs3/Emu/GS/GL/GLVertexProgram.cpp +++ b/rpcs3/Emu/GS/GL/GLVertexProgram.cpp @@ -151,7 +151,7 @@ wxString GLVertexDecompilerThread::GetSRC(const u32 n, bool isSca) return ret; } -void GLVertexDecompilerThread::AddCode(bool is_sca, wxString code, bool src_mask) +void GLVertexDecompilerThread::AddCode(bool is_sca, wxString code, bool src_mask, bool set_dst) { if(d0.cond == 0) return; enum @@ -179,7 +179,7 @@ void GLVertexDecompilerThread::AddCode(bool is_sca, wxString code, bool src_mask } //ConLog.Error("cond! %d (%d %s %d %d)", d0.cond, d0.dst_tmp, cond, d1.input_src, d1.const_src); - cond = wxString::Format("if(tmp%d.x %s 0) ", d0.dst_tmp, cond.mb_str()); + cond = wxString::Format("if(rc %s 0) ", cond.mb_str()); } wxString value = src_mask ? code + GetMask(is_sca) : code; @@ -189,40 +189,100 @@ void GLVertexDecompilerThread::AddCode(bool is_sca, wxString code, bool src_mask value = "clamp(" + value + ", 0.0, 1.0)"; } - wxString dest; - if(d3.dst == 5 || d3.dst == 6) + if(set_dst) { - int num = d3.dst == 5 ? 0 : 3; - - if(d3.vec_writemask_x) + wxString dest; + if(d0.cond_update_enable_0) { - ConLog.Error("Bad clip mask."); + dest = m_parr.AddParam(PARAM_NONE, "float", "rc"); + } + else if(d3.dst == 5 || d3.dst == 6) + { + int num = d3.dst == 5 ? 0 : 3; + + if(d3.vec_writemask_x) + { + ConLog.Error("Bad clip mask."); + } + + //if(d3.vec_writemask_y) num += 0; + if(d3.vec_writemask_z) num += 1; + else if(d3.vec_writemask_w) num += 2; + + dest = wxString::Format(GetDST(is_sca), num); + } + else + { + dest = GetDST(is_sca) + GetMask(is_sca); } - //if(d3.vec_writemask_y) num += 0; - if(d3.vec_writemask_z) num += 1; - else if(d3.vec_writemask_w) num += 2; - - dest = wxString::Format(GetDST(is_sca), num); + code = cond + dest + " = " + value; } else { - dest = GetDST(is_sca) + GetMask(is_sca); + code = cond + value; } - code = cond + dest + " = " + value; - - main += "\t" + code + ";\n"; + m_body.Add(code + wxString::Format(";//%d %d %d %d", d0.cond_reg_sel_1, d0.cond_test_enable, d0.cond_update_enable_0, d0.cond_update_enable_1)); } -void GLVertexDecompilerThread::AddVecCode(const wxString& code, bool src_mask) +wxString GLVertexDecompilerThread::GetFunc() { - AddCode(false, code, src_mask); + u32 offset = (d2.iaddrh << 3) | d3.iaddrl; + wxString name = wxString::Format("func%u", offset); + + for(uint i=0; i=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; + + //wxString main; wxString& m_shader; Array& m_data; GLParamArray& m_parr; @@ -138,6 +148,10 @@ struct GLVertexDecompilerThread : public ThreadBase , m_shader(shader) , m_parr(parr) { + m_funcs.Add(new FuncInfo()); + m_funcs[0].offset = 0; + m_funcs[0].name = "main"; + //m_cur_func->body = "\tgl_Position = vec4(0.0f, 0.0f, 0.0f, 1.0f);\n"; } wxString GetMask(bool is_sca); @@ -145,9 +159,11 @@ struct GLVertexDecompilerThread : public ThreadBase wxString GetScaMask(); wxString GetDST(bool is_sca = false); wxString GetSRC(const u32 n, bool is_sca = false); - void AddCode(bool is_sca, wxString code, bool src_mask = true); - void AddVecCode(const wxString& code, bool src_mask = true); - void AddScaCode(const wxString& code); + wxString GetFunc(); + void AddCode(bool is_sca, wxString code, bool src_mask = true, bool set_dst = true); + void AddVecCode(const wxString& code, bool src_mask = true, bool set_dst = true); + void AddScaCode(const wxString& code, bool set_dst = true); + wxString BuildFuncBody(const FuncInfo& func); wxString BuildCode(); virtual void Task(); diff --git a/rpcs3/Emu/GS/RSXThread.cpp b/rpcs3/Emu/GS/RSXThread.cpp index c8f4c84c19..626b7c4236 100644 --- a/rpcs3/Emu/GS/RSXThread.cpp +++ b/rpcs3/Emu/GS/RSXThread.cpp @@ -104,6 +104,41 @@ u32 RSXVertexData::GetTypeSize() index = (cmd - a) / m; \ case a \ +#define case_32(a, m) \ + case a + m: \ + case a + m * 2: \ + case a + m * 3: \ + case a + m * 4: \ + case a + m * 5: \ + case a + m * 6: \ + case a + m * 7: \ + case a + m * 8: \ + case a + m * 9: \ + case a + m * 10: \ + case a + m * 11: \ + case a + m * 12: \ + case a + m * 13: \ + case a + m * 14: \ + case a + m * 15: \ + case a + m * 16: \ + case a + m * 17: \ + case a + m * 18: \ + case a + m * 19: \ + case a + m * 20: \ + case a + m * 21: \ + case a + m * 22: \ + case a + m * 23: \ + case a + m * 24: \ + case a + m * 25: \ + case a + m * 26: \ + case a + m * 27: \ + case a + m * 28: \ + case a + m * 29: \ + case a + m * 30: \ + case a + m * 31: \ + index = (cmd - a) / m; \ + case a \ + void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u32 count) { #if CMD_DEBUG @@ -170,6 +205,13 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u3 //ConLog.Warning("texture addr = 0x%x #offset = 0x%x, location=%d", tex_addr, offset, location); tex.SetOffset(tex_addr); tex.SetFormat(cubemap, dimension, format, mipmap); + + if(!tex.m_width || !tex.m_height) + { + gcmBuffer* buffers = (gcmBuffer*)Memory.GetMemFromAddr(m_gcm_buffers_addr); + if(!tex.m_width) tex.m_width = re(buffers[m_gcm_current_buffer].width); + if(!tex.m_height) tex.m_height = re(buffers[m_gcm_current_buffer].height); + } } break; @@ -308,10 +350,24 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u3 { RSXTexture& tex = m_textures[index]; - const u16 height = args[0] & 0xffff; - const u16 width = args[0] >> 16; + u16 height = args[0] & 0xffff; + u16 width = args[0] >> 16; CMD_LOG("width=%d, height=%d", width, height); + + if(!width || !height) + { + ConLog.Warning("Bad texture rect: %dx%d (%dx%d)", width, height, tex.m_width, tex.m_height); + for(int i=0; idata.Clear(); @@ -677,8 +735,10 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u3 } break; - case NV4097_SET_TRANSFORM_PROGRAM: + case_32(NV4097_SET_TRANSFORM_PROGRAM, 4): { + //ConLog.Warning("NV4097_SET_TRANSFORM_PROGRAM[%d](%d)", index, count); + if(!m_cur_vertex_prog) { ConLog.Warning("NV4097_SET_TRANSFORM_PROGRAM: m_cur_vertex_prog == NULL"); diff --git a/rpcs3/Emu/GS/RSXThread.h b/rpcs3/Emu/GS/RSXThread.h index 48bdb55bfd..7f43d589a0 100644 --- a/rpcs3/Emu/GS/RSXThread.h +++ b/rpcs3/Emu/GS/RSXThread.h @@ -226,7 +226,7 @@ class RSXThread : public ThreadBase { public: static const uint m_textures_count = 16; - static const uint m_vertex_count = 16; + static const uint m_vertex_count = 32; static const uint m_fragment_count = 16; static const uint m_tiles_count = 15; diff --git a/rpcs3/Emu/SysCalls/Callback.cpp b/rpcs3/Emu/SysCalls/Callback.cpp index c062292092..af7013fd8e 100644 --- a/rpcs3/Emu/SysCalls/Callback.cpp +++ b/rpcs3/Emu/SysCalls/Callback.cpp @@ -9,7 +9,9 @@ Callback::Callback(u32 slot, u64 addr) , a1(0) , a2(0) , a3(0) + , a4(0) , m_has_data(false) + , m_name("Callback") { } @@ -38,11 +40,12 @@ bool Callback::HasData() const return m_has_data; } -void Callback::Handle(u64 _a1, u64 _a2, u64 _a3) +void Callback::Handle(u64 _a1, u64 _a2, u64 _a3, u64 _a4) { a1 = _a1; a2 = _a2; a3 = _a3; + a4 = _a4; m_has_data = true; } @@ -55,11 +58,12 @@ void Callback::Branch(bool wait) new_thread.SetEntry(m_addr); new_thread.SetPrio(1001); new_thread.SetStackSize(0x10000); - new_thread.SetName("Callback"); + new_thread.SetName(m_name); new_thread.SetArg(0, a1); new_thread.SetArg(1, a2); new_thread.SetArg(2, a3); + new_thread.SetArg(3, a4); new_thread.Run(); new_thread.Exec(); @@ -68,6 +72,11 @@ void Callback::Branch(bool wait) GetCurrentPPCThread()->Wait(new_thread); } +void Callback::SetName(const std::string& name) +{ + m_name = name; +} + Callback::operator bool() const { return GetAddr() != 0; diff --git a/rpcs3/Emu/SysCalls/Callback.h b/rpcs3/Emu/SysCalls/Callback.h index 49395f3527..a21709aee0 100644 --- a/rpcs3/Emu/SysCalls/Callback.h +++ b/rpcs3/Emu/SysCalls/Callback.h @@ -8,10 +8,13 @@ protected: bool m_has_data; + std::string m_name; + public: u64 a1; u64 a2; u64 a3; + u64 a4; u32 GetSlot() const; u64 GetAddr() const; @@ -20,8 +23,9 @@ public: bool HasData() const; Callback(u32 slot = 0, u64 addr = 0); - void Handle(u64 a1 = 0, u64 a2 = 0, u64 a3 = 0); + void Handle(u64 a1 = 0, u64 a2 = 0, u64 a3 = 0, u64 a4 = 0); void Branch(bool wait); + void SetName(const std::string& name); operator bool() const; }; diff --git a/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp b/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp index d904646a77..59124cadaf 100644 --- a/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp @@ -135,6 +135,32 @@ int cellFsSdataOpen(u32 path_addr, int flags, mem32_t fd, mem32_t arg, u64 size) return CELL_OK; } +struct CellFsAio +{ + be_t fd; + be_t offset; + be_t buf_addr; + be_t size; + be_t user_data; +}; + +int cellFsAioRead(mem_ptr_t aio, mem32_t id, mem32_t func_addr) +{ + if(!aio.IsGood() || !id.IsGood() || !func_addr.IsGood()) + return CELL_EFAULT; + + //CellFsAio *xaio, CellFsErrno error, int xid, uint64_t size; + Callback callback; + callback.SetAddr(func_addr); + callback.SetName("cellFsAioReadCallback"); + MemoryAllocator> nread; + int error = cellFsRead(aio->fd, id.GetAddr(), aio->size, nread); + callback.Handle(aio.GetAddr(), error, id, *nread); + callback.Branch(true); + + return CELL_OK; +} + void sys_fs_init() { sys_fs.AddFunc(0x718bf5f8, cellFsOpen); @@ -155,6 +181,5 @@ void sys_fs_init() sys_fs.AddFunc(0x0e2939e5, cellFsFtruncate); sys_fs.AddFunc(0xc9dc3ac5, cellFsTruncate); sys_fs.AddFunc(0xcb588dba, cellFsFGetBlockSize); - sys_fs.AddFunc(0xc1c507e7, cellFsAioRead); } diff --git a/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp b/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp index f0de6b262e..b66ffbaccb 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp @@ -24,16 +24,21 @@ struct SpuGroupInfo }; u64 g_last_spu_offset = 0; +static const u64 g_spu_alloc_size = 0x1000000; -u32 LoadSpuImage(vfsStream& stream) +u32 LoadSpuImage(vfsStream& stream, u64 address) { ELFLoader l(stream); l.LoadInfo(); - u32 alloc_size = 0xFFFFED - stream.GetSize(); - g_last_spu_offset = Memory.MainMem.Alloc(alloc_size); - l.LoadData(g_last_spu_offset); + l.LoadData(address); - return g_last_spu_offset + l.GetEntry(); + 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 diff --git a/rpcs3/Gui/RSXDebugger.cpp b/rpcs3/Gui/RSXDebugger.cpp index d675ab8b3f..5f5beceeb7 100644 --- a/rpcs3/Gui/RSXDebugger.cpp +++ b/rpcs3/Gui/RSXDebugger.cpp @@ -493,7 +493,7 @@ void RSXDebugger::GetTexture() 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("%d x %d", + m_list_texture->SetItem(i, 8, wxString::Format("%dx%d", render.m_textures[i].m_width, render.m_textures[i].m_height)); diff --git a/rpcs3/Gui/VFSManager.cpp b/rpcs3/Gui/VFSManager.cpp index 44d276b398..2215be3949 100644 --- a/rpcs3/Gui/VFSManager.cpp +++ b/rpcs3/Gui/VFSManager.cpp @@ -188,7 +188,7 @@ void VFSManagerDialog::OnAdd(wxCommandEvent& event) m_list->SetItemState(i, i == idx ? wxLIST_STATE_SELECTED : ~wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED); } - wxCommandEvent ce; + wxCommandEvent ce; OnEntryConfig(ce); } diff --git a/rpcs3/Loader/ELF32.cpp b/rpcs3/Loader/ELF32.cpp index 6684a4f584..34e997753b 100644 --- a/rpcs3/Loader/ELF32.cpp +++ b/rpcs3/Loader/ELF32.cpp @@ -119,8 +119,8 @@ bool ELF32Loader::LoadShdrInfo() if(ehdr.e_shstrndx >= shdr_arr.GetCount()) { - ConLog.Error("LoadShdr32 error: shstrndx too big!"); - return false; + ConLog.Warning("LoadShdr32 error: shstrndx too big!"); + return true; } for(u32 i=0; i Date: Wed, 8 Jan 2014 00:27:34 +0400 Subject: [PATCH 3/8] Small fixes --- rpcs3/Emu/SysCalls/Modules.cpp | 1 - rpcs3/Emu/SysCalls/Modules/cellPamf.cpp | 15 ++++++++--- rpcs3/Emu/SysCalls/Modules/cellSync.cpp | 13 ++++++--- rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp | 13 +++++---- rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp | 11 ++++---- rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp | 28 ++++++++++---------- rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.h | 13 ++++++--- rpcs3/Loader/ELF32.cpp | 4 +-- 8 files changed, 59 insertions(+), 39 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules.cpp b/rpcs3/Emu/SysCalls/Modules.cpp index 313b91676f..68fb88c772 100644 --- a/rpcs3/Emu/SysCalls/Modules.cpp +++ b/rpcs3/Emu/SysCalls/Modules.cpp @@ -90,7 +90,6 @@ static const g_module_list[] = {0x0050, "cellSpursJq"}, {0x0052, "cellPngEnc"}, {0x0053, "cellMusicDecode2"}, - {0x0054, "cellSync"}, {0x0055, "cellSync2"}, {0x0056, "cellNpUtil"}, {0x0057, "cellRudp"}, diff --git a/rpcs3/Emu/SysCalls/Modules/cellPamf.cpp b/rpcs3/Emu/SysCalls/Modules/cellPamf.cpp index 980d297d53..f97bc3c8d1 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellPamf.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellPamf.cpp @@ -186,7 +186,8 @@ struct PamfHeader be_t mux_rate_max; //== 0x01D470 (400 bps per unit, == 48000000 bps) be_t mux_rate_min; //== 0x0107AC (?????) u16 reserved2; // ????? - be_t stream_count; //total stream count + u8 reserved3; + u8 stream_count; //total stream count (reduced to 1 byte) be_t unk1; //== 1 (?????) be_t table_data_size; //== table_size - 0x20 == 0x14 + (0x30 * total_stream_num) (?????) //TODO: check relative offset of stream structs (could be from 0x0c to 0x14, currently 0x14) @@ -245,7 +246,8 @@ int cellPamfGetStreamOffsetAndSize(mem_ptr_t pAddr, u64 fileSize, me cellPamf.Warning("cellPamfGetStreamOffsetAndSize(pAddr=0x%x, fileSize=%d, pOffset_addr=0x%x, pSize_addr=0x%x)", pAddr.GetAddr(), fileSize, pOffset.GetAddr(), pSize.GetAddr()); - pOffset = (u64)pAddr->data_offset << 11; + const u64 size = (u64)pAddr->data_offset << 11; + pOffset = size; pSize = (u64)pAddr->data_size << 11; return CELL_OK; } @@ -327,6 +329,9 @@ int cellPamfReaderGetNumberOfSpecificStreams(mem_ptr_t pSelf, u8 int counts[6] = {0, 0, 0, 0, 0, 0}; + /*if (!pAddr->magic) + return 1; /*hack*/ + for (int i = 0; i < pAddr->stream_count; i++) { switch (pAddr->stream_headers[i].type) @@ -338,6 +343,7 @@ int cellPamfReaderGetNumberOfSpecificStreams(mem_ptr_t pSelf, u8 default: cellPamf.Error("cellPamfReaderGetNumberOfSpecificStreams: unsupported stream type found(0x%x)", pAddr->stream_headers[i].type); + break; } } @@ -356,7 +362,7 @@ int cellPamfReaderGetNumberOfSpecificStreams(mem_ptr_t pSelf, u8 return counts[CELL_PAMF_STREAM_TYPE_ATRAC3PLUS] + counts[CELL_PAMF_STREAM_TYPE_PAMF_LPCM] + counts[CELL_PAMF_STREAM_TYPE_AC3]; default: - return 0; + return 0; } } @@ -394,6 +400,9 @@ int cellPamfReaderSetStreamWithTypeAndIndex(mem_ptr_t pSelf, u8 u32 found = 0; + /*if (!pAddr->magic) + return 0; /*hack*/ + for (int i = 0; i < pAddr->stream_count; i++) { switch (pAddr->stream_headers[i].type) diff --git a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp index c6e8d163b4..451d61d1cc 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp @@ -3,7 +3,7 @@ #include "Emu/SysCalls/SC_FUNC.h" void cellSync_init(); -Module cellSync(0x0054, cellSync_init); +Module cellSync("cellSync", cellSync_init); // Return Codes enum @@ -24,6 +24,7 @@ enum int cellSyncMutexInitialize(mem32_t mutex) { + cellSync.Log("cellSyncMutexInitialize(mutex=0x%x)", mutex.GetAddr()); const u32 mutex_addr = mutex.GetAddr(); if (!mutex_addr) { @@ -34,11 +35,13 @@ int cellSyncMutexInitialize(mem32_t mutex) return CELL_SYNC_ERROR_ALIGN; } mutex = 0; + _mm_sfence(); return CELL_OK; } int cellSyncMutexLock(mem32_t mutex) { + cellSync.Log("cellSyncMutexLock(mutex=0x%x)", mutex.GetAddr()); const u32 mutex_addr = mutex.GetAddr(); if (!mutex_addr) { @@ -48,7 +51,7 @@ int cellSyncMutexLock(mem32_t mutex) { return CELL_SYNC_ERROR_ALIGN; } - while (_InterlockedExchange((volatile long*)Memory.VirtualToRealAddr(mutex_addr), 1 << 24)); + while (_InterlockedExchange((volatile long*)(Memory + mutex_addr), 1 << 24)); //need to check how does SPU work with these mutexes, also obtainment order is not guaranteed _mm_lfence(); return CELL_OK; @@ -56,6 +59,7 @@ int cellSyncMutexLock(mem32_t mutex) int cellSyncMutexTryLock(mem32_t mutex) { + cellSync.Log("cellSyncMutexTryLock(mutex=0x%x)", mutex.GetAddr()); const u32 mutex_addr = mutex.GetAddr(); if (!mutex_addr) { @@ -66,7 +70,7 @@ int cellSyncMutexTryLock(mem32_t mutex) return CELL_SYNC_ERROR_ALIGN; } //check cellSyncMutexLock - if (_InterlockedExchange((volatile long*)Memory.VirtualToRealAddr(mutex_addr), 1 << 24)) + if (_InterlockedExchange((volatile long*)(Memory + mutex_addr), 1 << 24)) { return CELL_SYNC_ERROR_BUSY; } @@ -76,6 +80,7 @@ int cellSyncMutexTryLock(mem32_t mutex) int cellSyncMutexUnlock(mem32_t mutex) { + cellSync.Log("cellSyncMutexUnlock(mutex=0x%x)", mutex.GetAddr()); const u32 mutex_addr = mutex.GetAddr(); if (!mutex_addr) { @@ -87,7 +92,7 @@ int cellSyncMutexUnlock(mem32_t mutex) } //check cellSyncMutexLock _mm_sfence(); - _InterlockedExchange((volatile long*)Memory.VirtualToRealAddr(mutex_addr), 0); + _InterlockedExchange((volatile long*)(Memory + mutex_addr), 0); return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp b/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp index d73bb69ed4..e08e90cae4 100644 --- a/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp +++ b/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp @@ -81,11 +81,12 @@ int sys_spu_image_import(mem_ptr_t img, u32 src, u32 type) } vfsStreamMemory f(src); - u32 entry = LoadSpuImage(f); + u32 entry; + u32 offset = LoadSpuImage(f, entry); - img->type = 1; + img->type = type; img->entry_point = entry; - img->segs_addr = 0x0; + img->segs_addr = offset; img->nsegs = 0; return CELL_OK; @@ -119,15 +120,13 @@ int sys_raw_spu_load(int id, u32 path_addr, mem32_t entry) return CELL_OK; } -extern u64 g_last_spu_offset; - int sys_raw_spu_image_load(int id, mem_ptr_t img) { sysPrxForUser.Warning("sys_raw_spu_image_load(id=0x%x, img_addr=0x%x)", id, img.GetAddr()); - memcpy(Memory + RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * id, Memory + g_last_spu_offset, 256 * 1024); + memcpy(Memory + RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * id, Memory + (u32)img->segs_addr, 256 * 1024); Memory.Write32(RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * id + RAW_SPU_PROB_OFFSET + SPU_NPC_offs, - img->entry_point - g_last_spu_offset); + (u32)img->entry_point); return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp b/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp index a99b13a5b7..67574f3a15 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp @@ -390,14 +390,12 @@ std::atomic g_FsAioReadID = 0; int cellFsAioRead(mem_ptr_t 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); + vfsStream& file = vfsLocalFile(orig_file.GetPath().AfterFirst('/'), vfsRead); u64 nbytes = (u64)aio->size; const u32 buf_addr = (u32)aio->buf_addr; @@ -416,8 +414,11 @@ int cellFsAioRead(mem_ptr_t aio, mem32_t aio_id, u32 func_addr) const u32 xid = g_FsAioReadID++; aio_id = xid; + sys_fs.Warning("cellFsAioRead(aio_addr: 0x%x[%s], id_addr: 0x%x, func_addr: 0x%x[res=%d, addr=0x%x])", aio.GetAddr(), + orig_file.GetPath().c_str(), aio_id.GetAddr(), func_addr, res, (u32)aio->buf_addr); + //TODO: init the callback - /*CPUThread& new_thread = Emu.GetCPU().AddThread(CPU_THREAD_PPU); + CPUThread& new_thread = Emu.GetCPU().AddThread(CPU_THREAD_PPU); new_thread.SetEntry(func_addr); new_thread.SetPrio(1001); new_thread.SetStackSize(0x10000); @@ -427,7 +428,7 @@ int cellFsAioRead(mem_ptr_t aio, mem32_t aio_id, u32 func_addr) new_thread.SetArg(2, xid); //xid (unique id) new_thread.SetArg(3, res); //size (bytes read) new_thread.Run(); - new_thread.Exec();*/ + new_thread.Exec(); return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp b/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp index f0de6b262e..1b07784925 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp @@ -23,17 +23,15 @@ struct SpuGroupInfo } }; -u64 g_last_spu_offset = 0; - -u32 LoadSpuImage(vfsStream& stream) +u32 LoadSpuImage(vfsStream& stream, u32& spu_ep) { ELFLoader l(stream); l.LoadInfo(); - u32 alloc_size = 0xFFFFED - stream.GetSize(); - g_last_spu_offset = Memory.MainMem.Alloc(alloc_size); - l.LoadData(g_last_spu_offset); - - return g_last_spu_offset + l.GetEntry(); + const u32 alloc_size = 256 * 1024 /*0x1000000 - stream.GetSize()*/; + u32 spu_offset = Memory.MainMem.Alloc(alloc_size); + l.LoadData(spu_offset); + spu_ep = l.GetEntry(); + return spu_offset; } //156 @@ -54,11 +52,12 @@ int sys_spu_image_open(mem_ptr_t img, u32 path_addr) return CELL_ENOENT; } - u32 entry = LoadSpuImage(f); + u32 entry; + u32 offset = LoadSpuImage(f, entry); img->type = 1; img->entry_point = entry; - img->segs_addr = 0x0; + img->segs_addr = offset; img->nsegs = 0; return CELL_OK; @@ -97,7 +96,7 @@ int sys_spu_thread_initialize(mem32_t thread, u32 group, u32 spu_num, mem_ptr_t< return CELL_EBUSY; } - u32 ls_entry = img->entry_point - g_last_spu_offset; + u32 spu_ep = (u32)img->entry_point; std::string name = Memory.ReadString(attr->name_addr, attr->name_len).mb_str(); u64 a1 = arg->arg1; u64 a2 = arg->arg2; @@ -107,10 +106,10 @@ int sys_spu_thread_initialize(mem32_t thread, u32 group, u32 spu_num, mem_ptr_t< CPUThread& new_thread = Emu.GetCPU().AddThread(CPU_THREAD_SPU); //copy SPU image: u32 spu_offset = Memory.MainMem.Alloc(256 * 1024); - memcpy(Memory + spu_offset, Memory + g_last_spu_offset, 256 * 1024); + memcpy(Memory + spu_offset, Memory + (u32)img->segs_addr, 256 * 1024); //initialize from new place: new_thread.SetOffset(spu_offset); - new_thread.SetEntry(ls_entry); + new_thread.SetEntry(spu_ep); new_thread.SetName(name); new_thread.SetArg(0, a1); new_thread.SetArg(1, a2); @@ -123,7 +122,8 @@ int sys_spu_thread_initialize(mem32_t thread, u32 group, u32 spu_num, mem_ptr_t< group_info.threads[spu_num] = &new_thread; ConLog.Write("New SPU Thread:"); - ConLog.Write("ls_entry = 0x%x", ls_entry); + ConLog.Write("SPU img offset = 0x%x", (u32)img->segs_addr); + ConLog.Write("entry_point = 0x%x", spu_ep); ConLog.Write("name = %s", name.c_str()); ConLog.Write("a1 = 0x%x", a1); ConLog.Write("a2 = 0x%x", a2); diff --git a/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.h b/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.h index 9c82c6aee9..acac792dc8 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.h +++ b/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.h @@ -1,6 +1,6 @@ #pragma once -u32 LoadSpuImage(vfsStream& stream); +u32 LoadSpuImage(vfsStream& stream, u32& spu_ep); enum { @@ -9,6 +9,13 @@ enum SYS_SPU_THREAD_GROUP_JOIN_TERMINATED = 0x0004 }; +enum +{ + SYS_SPU_SEGMENT_TYPE_COPY = 0x0001, + SYS_SPU_SEGMENT_TYPE_FILL = 0x0002, + SYS_SPU_SEGMENT_TYPE_INFO = 0x0004, +}; + struct sys_spu_thread_group_attribute { be_t name_len; @@ -35,8 +42,8 @@ struct sys_spu_thread_argument struct sys_spu_image { be_t type; - be_t entry_point; - be_t segs_addr; + be_t entry_point; + be_t segs_addr; //temporarily used as offset of LS image after elf loading be_t nsegs; }; diff --git a/rpcs3/Loader/ELF32.cpp b/rpcs3/Loader/ELF32.cpp index 6684a4f584..34e997753b 100644 --- a/rpcs3/Loader/ELF32.cpp +++ b/rpcs3/Loader/ELF32.cpp @@ -119,8 +119,8 @@ bool ELF32Loader::LoadShdrInfo() if(ehdr.e_shstrndx >= shdr_arr.GetCount()) { - ConLog.Error("LoadShdr32 error: shstrndx too big!"); - return false; + ConLog.Warning("LoadShdr32 error: shstrndx too big!"); + return true; } for(u32 i=0; i Date: Wed, 8 Jan 2014 23:16:13 +0200 Subject: [PATCH 4/8] Implemented mem_func_ptr_t. Improved cellFsAioRead. Fixed cellAudioOut* return error codes. --- rpcs3/Emu/Memory/Memory.h | 167 ++++++++++++++++++++- rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp | 47 +++--- rpcs3/Emu/SysCalls/Modules/sys_fs.cpp | 78 ++++------ rpcs3/Emu/SysCalls/SC_FUNC.h | 4 +- rpcs3/Emu/SysCalls/SysCalls.h | 1 - 5 files changed, 214 insertions(+), 83 deletions(-) diff --git a/rpcs3/Emu/Memory/Memory.h b/rpcs3/Emu/Memory/Memory.h index 34b1426e52..5a50c3a2c8 100644 --- a/rpcs3/Emu/Memory/Memory.h +++ b/rpcs3/Emu/Memory/Memory.h @@ -418,12 +418,27 @@ public: { } - u32 GetAddr() const { return m_addr; } + __forceinline u32 GetAddr() const { return m_addr; } - bool IsGood() const + __forceinline bool IsGood() const { return Memory.IsGoodAddr(m_addr, sizeof(T)); } + + __forceinline operator bool() const + { + return m_addr != 0; + } + + __forceinline bool operator != (nullptr_t) const + { + return m_addr != 0; + } + + __forceinline bool operator == (nullptr_t) const + { + return m_addr == 0; + } }; template @@ -434,6 +449,9 @@ public: { } + template operator mem_ptr_t&() { return (mem_ptr_t&)*this; } + template operator const mem_ptr_t&() const { return (const mem_ptr_t&)*this; } + T* operator -> () { return (T*)&Memory[this->m_addr]; @@ -512,8 +530,6 @@ public: return (const T&)Memory[this->m_addr + sizeof(T) * index]; } - operator bool() const { return this->m_addr == 0; } - bool operator == (mem_ptr_t right) const { return this->m_addr == right.m_addr; } bool operator != (mem_ptr_t right) const { return this->m_addr != right.m_addr; } bool operator > (mem_ptr_t right) const { return this->m_addr > right.m_addr; } @@ -529,6 +545,32 @@ public: bool operator <= (T* right) const { return (T*)&Memory[this->m_addr] <= right; } }; +template<> +class mem_ptr_t : public mem_base_t +{ +public: + mem_ptr_t(u32 addr) : mem_base_t(addr) + { + } + + template operator mem_ptr_t&() { return (mem_ptr_t&)*this; } + template operator const mem_ptr_t&() const { return (const mem_ptr_t&)*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 static bool operator == (T* left, mem_ptr_t right) { return left == (T*)&Memory[right.GetAddr()]; } template static bool operator != (T* left, mem_ptr_t right) { return left != (T*)&Memory[right.GetAddr()]; } template static bool operator > (T* left, mem_ptr_t right) { return left > (T*)&Memory[right.GetAddr()]; } @@ -638,6 +680,123 @@ public: void SetAddr(const u64 addr) { m_addr = addr; } }; +template class mem_func_ptr_t; + +template +class mem_func_ptr_t : public mem_base_t +{ + __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 +class mem_func_ptr_t : public mem_base_t +{ + __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 +class mem_func_ptr_t : public mem_base_t +{ + __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 +class mem_func_ptr_t : public mem_base_t +{ + __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 +class mem_func_ptr_t : public mem_base_t +{ + __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 class MemoryAllocator { diff --git a/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp b/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp index 81a16f804c..1c2866b22b 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp @@ -106,9 +106,6 @@ enum CELL_SYSUTIL_PAD_RUMBLE_ON = 1, }; -void cellSysutil_init(); -Module cellSysutil(0x0015, cellSysutil_init); - enum { @@ -132,6 +129,11 @@ enum CellMsgDialogType CELL_MSGDIALOG_DEFAULT_CURSOR_NO = 0x00000100, }; +typedef void (*CellMsgDialogCallback)(int buttonType, mem_ptr_t userData); + +void cellSysutil_init(); +Module cellSysutil(0x0015, cellSysutil_init); + int cellSysutilGetSystemParamInt(int id, mem32_t value) { cellSysutil.Log("cellSysutilGetSystemParamInt(id=0x%x, value_addr=0x%x)", id, value.GetAddr()); @@ -477,7 +479,7 @@ int cellSysutilUnregisterCallback(int slot) return CELL_OK; } -int cellMsgDialogOpen2(u32 type, char* msgString, u32 callback_addr, u32 userData, u32 extParam) +int cellMsgDialogOpen2(u32 type, char* msgString, mem_func_ptr_t callback, mem_ptr_t userData, u32 extParam) { long style = 0; @@ -520,17 +522,16 @@ int cellMsgDialogOpen2(u32 type, char* msgString, u32 callback_addr, u32 userDat break; } - Callback2 callback(0, callback_addr, userData); - callback.Handle(status); - callback.Branch(true); + if(callback) + callback(status, userData); return CELL_OK; } -int cellMsgDialogOpenErrorCode(u32 errorCode, u32 callback_addr, u32 userData, u32 extParam) +int cellMsgDialogOpenErrorCode(u32 errorCode, mem_func_ptr_t callback, mem_ptr_t userData, u32 extParam) { cellSysutil.Warning("cellMsgDialogOpenErrorCode(errorCode=0x%x, callback_addr=0x%x, userData=%d, extParam=%d)", - errorCode, callback_addr, userData, extParam); + errorCode, callback.GetAddr(), userData, extParam); std::string errorMessage; switch(errorCode) @@ -622,10 +623,8 @@ int cellMsgDialogOpenErrorCode(u32 errorCode, u32 callback_addr, u32 userData, u break; } - // TODO: The following lines produce an infinite loop of cellMsgDialogOpenErrorCode's - /*Callback2 callback(0, callback_addr, userData); - callback.Handle(status); - callback.Branch(true);*/ + if(callback) + callback(status, userData); return CELL_OK; } @@ -649,7 +648,7 @@ int cellAudioOutGetSoundAvailability(u32 audioOut, u32 type, u32 fs, u32 option) case CELL_AUDIO_OUT_FS_192KHZ: break; - default: CELL_AUDIO_OUT_ERROR_UNSUPPORTED_SOUND_MODE; + default: return CELL_AUDIO_OUT_ERROR_UNSUPPORTED_SOUND_MODE; } switch(type) @@ -659,7 +658,7 @@ int cellAudioOutGetSoundAvailability(u32 audioOut, u32 type, u32 fs, u32 option) case CELL_AUDIO_OUT_CODING_TYPE_DTS: break; - default: CELL_AUDIO_OUT_ERROR_UNSUPPORTED_SOUND_MODE; + default: return CELL_AUDIO_OUT_ERROR_UNSUPPORTED_SOUND_MODE; } switch(audioOut) @@ -668,8 +667,7 @@ int cellAudioOutGetSoundAvailability(u32 audioOut, u32 type, u32 fs, u32 option) case CELL_AUDIO_OUT_SECONDARY: return 0; } - CELL_AUDIO_OUT_ERROR_ILLEGAL_CONFIGURATION; - + return CELL_AUDIO_OUT_ERROR_ILLEGAL_CONFIGURATION; } int cellAudioOutGetSoundAvailability2(u32 audioOut, u32 type, u32 fs, u32 ch, u32 option) @@ -690,7 +688,7 @@ int cellAudioOutGetSoundAvailability2(u32 audioOut, u32 type, u32 fs, u32 ch, u3 case CELL_AUDIO_OUT_FS_192KHZ: break; - default: CELL_AUDIO_OUT_ERROR_UNSUPPORTED_SOUND_MODE; + default: return CELL_AUDIO_OUT_ERROR_UNSUPPORTED_SOUND_MODE; } switch(ch) @@ -700,7 +698,7 @@ int cellAudioOutGetSoundAvailability2(u32 audioOut, u32 type, u32 fs, u32 ch, u3 case 8: break; - default: CELL_AUDIO_OUT_ERROR_UNSUPPORTED_SOUND_MODE; + default: return CELL_AUDIO_OUT_ERROR_UNSUPPORTED_SOUND_MODE; } switch(type) @@ -710,7 +708,7 @@ int cellAudioOutGetSoundAvailability2(u32 audioOut, u32 type, u32 fs, u32 ch, u3 case CELL_AUDIO_OUT_CODING_TYPE_DTS: break; - default: CELL_AUDIO_OUT_ERROR_UNSUPPORTED_SOUND_MODE; + default: return CELL_AUDIO_OUT_ERROR_UNSUPPORTED_SOUND_MODE; } switch(audioOut) @@ -719,8 +717,7 @@ int cellAudioOutGetSoundAvailability2(u32 audioOut, u32 type, u32 fs, u32 ch, u3 case CELL_AUDIO_OUT_SECONDARY: return 0; } - CELL_AUDIO_OUT_ERROR_ILLEGAL_CONFIGURATION; - + return CELL_AUDIO_OUT_ERROR_ILLEGAL_CONFIGURATION; } int cellAudioOutGetState(u32 audioOut, u32 deviceIndex, u32 state_addr) @@ -831,7 +828,7 @@ int cellAudioOutGetNumberOfDevice(u32 audioOut) case CELL_AUDIO_OUT_SECONDARY: return 0; } - CELL_AUDIO_OUT_ERROR_UNSUPPORTED_AUDIO_OUT; + return CELL_AUDIO_OUT_ERROR_UNSUPPORTED_AUDIO_OUT; } int cellAudioOutGetDeviceInfo(u32 audioOut, u32 deviceIndex, mem_ptr_t info) @@ -863,7 +860,7 @@ int cellAudioOutSetCopyControl(u32 audioOut, u32 control) case CELL_AUDIO_OUT_SECONDARY: break; - default: CELL_AUDIO_OUT_ERROR_UNSUPPORTED_AUDIO_OUT; + default: return CELL_AUDIO_OUT_ERROR_UNSUPPORTED_AUDIO_OUT; } switch(control) @@ -873,7 +870,7 @@ int cellAudioOutSetCopyControl(u32 audioOut, u32 control) case CELL_AUDIO_OUT_COPY_CONTROL_COPY_NEVER: break; - default: CELL_AUDIO_OUT_ERROR_ILLEGAL_PARAMETER; + default: return CELL_AUDIO_OUT_ERROR_ILLEGAL_PARAMETER; } return CELL_AUDIO_OUT_SUCCEEDED; diff --git a/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp b/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp index 297335e8e1..9819ef8fbd 100644 --- a/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp @@ -135,76 +135,52 @@ int cellFsSdataOpen(u32 path_addr, int flags, mem32_t fd, mem32_t arg, u64 size) return CELL_OK; } -/*struct CellFsAio -{ - be_t fd; - be_t offset; - be_t buf_addr; - be_t size; - be_t user_data; -}; - -int cellFsAioRead(mem_ptr_t aio, mem32_t id, mem32_t func_addr) -{ - if(!aio.IsGood() || !id.IsGood() || !func_addr.IsGood()) - return CELL_EFAULT; - - //CellFsAio *xaio, CellFsErrno error, int xid, uint64_t size; - Callback callback; - callback.SetAddr(func_addr); - callback.SetName("cellFsAioReadCallback"); - MemoryAllocator> nread; - int error = cellFsRead(aio->fd, id.GetAddr(), aio->size, nread); - callback.Handle(aio.GetAddr(), error, id, *nread); - callback.Branch(true); - - return CELL_OK; -}*/ - std::atomic g_FsAioReadID = 0; -int cellFsAioRead(mem_ptr_t aio, mem32_t aio_id, u32 func_addr) +int cellFsAioRead(mem_ptr_t aio, mem32_t aio_id, mem_func_ptr_t xaio, u32 error, int xid, u64 size)> func) { 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 = vfsLocalFile(orig_file.GetPath().AfterFirst('/'), 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(); + u64 res; + u32 error; + + if(Memory.IsGoodAddr(buf_addr)) + { + vfsFile file(orig_file.GetPath().AfterFirst('/'), vfsRead); + if(!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); + res = nbytes ? file.Read(Memory.GetMemFromAddr(buf_addr), nbytes) : 0; + error = CELL_OK; + } + else + { + res = 0; + error = CELL_EFAULT; + } //get a unique id for the callback const u32 xid = g_FsAioReadID++; aio_id = xid; sys_fs.Warning("cellFsAioRead(aio_addr: 0x%x[%s], id_addr: 0x%x, func_addr: 0x%x[res=%d, addr=0x%x])", aio.GetAddr(), - orig_file.GetPath().c_str(), aio_id.GetAddr(), func_addr, res, (u32)aio->buf_addr); + orig_file.GetPath().c_str(), aio_id.GetAddr(), func.GetAddr(), res, (u32)aio->buf_addr); + + if(func) + func(aio, error, xid, res); - //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; } diff --git a/rpcs3/Emu/SysCalls/SC_FUNC.h b/rpcs3/Emu/SysCalls/SC_FUNC.h index 0965ae90f1..832e0bf2b4 100644 --- a/rpcs3/Emu/SysCalls/SC_FUNC.h +++ b/rpcs3/Emu/SysCalls/SC_FUNC.h @@ -302,6 +302,8 @@ public: virtual void operator()() { declCPU(); m_call(ARG(1), ARG(2), ARG(3), ARG(4), ARG(5), ARG(6), ARG(7), ARG(8), ARG(9), ARG(10), ARG(11), ARG(12)); } }; +#undef ARG + template 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(call); } - -#undef ARG(n) diff --git a/rpcs3/Emu/SysCalls/SysCalls.h b/rpcs3/Emu/SysCalls/SysCalls.h index d9d1eab390..0342c60861 100644 --- a/rpcs3/Emu/SysCalls/SysCalls.h +++ b/rpcs3/Emu/SysCalls/SysCalls.h @@ -225,7 +225,6 @@ extern int cellFsLseek(u32 fd, s64 offset, u32 whence, mem64_t pos); extern int cellFsFtruncate(u32 fd, u64 size); extern int cellFsTruncate(u32 path_addr, u64 size); extern int cellFsFGetBlockSize(u32 fd, mem64_t sector_size, mem64_t block_size); -extern int cellFsAioRead(mem_ptr_t aio, mem32_t id, u32 func_addr); //cellVideo extern int cellVideoOutGetState(u32 videoOut, u32 deviceIndex, u32 state_addr); From 1be7454bc47ec815c04942613f653805d64aa2dc Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Fri, 10 Jan 2014 05:30:59 +0400 Subject: [PATCH 5/8] Fixed errors, improvements cellSync review, MFC channel AtomicStat added, draft implementation of MFC_GETLLAR_CMD, MFC_PUTLLC_CMD etc, memory allocating hacks for alignment. --- rpcs3/Emu/Cell/MFC.h | 9 +++ rpcs3/Emu/Cell/SPUThread.h | 60 +++++++++++++++++ rpcs3/Emu/Memory/Memory.h | 9 ++- rpcs3/Emu/SysCalls/Modules/cellSync.cpp | 77 +++++++++++++--------- rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp | 2 + rpcs3/Emu/SysCalls/Modules/sys_fs.cpp | 7 +- rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp | 1 + rpcs3/Emu/SysCalls/lv2/SC_Memory.cpp | 18 +++-- 8 files changed, 142 insertions(+), 41 deletions(-) diff --git a/rpcs3/Emu/Cell/MFC.h b/rpcs3/Emu/Cell/MFC.h index 839987cd68..5ddf7a073a 100644 --- a/rpcs3/Emu/Cell/MFC.h +++ b/rpcs3/Emu/Cell/MFC.h @@ -21,6 +21,15 @@ enum MFC_MASK_CMD = 0xffff, }; +// Atomic Status Update +enum +{ + MFC_PUTLLC_SUCCESS = 0, + MFC_PUTLLC_FAILURE = 1, //reservation was lost + MFC_PUTLLUC_SUCCESS = 2, + MFC_GETLLAR_SUCCESS = 4, +}; + enum { MFC_SPU_TO_PPU_MAILBOX_STATUS_MASK = 0x000000FF, diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index 7dd9b2d636..38788022f1 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -470,6 +470,7 @@ public: Channel<1> QueryType; Channel<1> QueryMask; Channel<1> TagStatus; + Channel<1> AtomicStat; } Prxy; struct @@ -519,6 +520,58 @@ public: } break; + case MFC_GETLLAR_CMD: + case MFC_PUTLLC_CMD: + case MFC_PUTLLUC_CMD: + { + extern wxMutex g_SyncMutex; + const CPUThread& current = *GetCurrentPPCThread(); + if (op == MFC_GETLLAR_CMD) + { + g_SyncMutex.Lock(); + /* for (u32 i = 0; i < Emu.GetCPU().GetThreads().GetCount(); i++) + { + CPUThread& t = *Emu.GetCPU().GetThread(i); + if (&t != ¤t && &t) + { + while (!t.IsRunning()) Sleep(1); + t.Pause(); + } + } + for (u32 i = 0; i < Emu.GetCPU().GetThreads().GetCount(); i++) + { + CPUThread& t = *Emu.GetCPU().GetThread(i); + if (&t != ¤t && &t) + { + if (!t.IsPaused()) Sleep(1); + } + } */ + } + + 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); + //draft implementation + _mm_mfence(); + 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); + _mm_mfence(); + + if (op != MFC_GETLLAR_CMD) + { + /*for (u32 i = 0; i < Emu.GetCPU().GetThreads().GetCount(); i++) + { + CPUThread& t = *Emu.GetCPU().GetThread(i); + if (&t != ¤t && &t) + { + t.Resume(); //it's wrong (some threads shall not be resumed) + } + }*/ + g_SyncMutex.Unlock(); + } + } + break; + default: ConLog.Error("Unknown MFC cmd. (opcode=0x%x, cmd=0x%x, lsa = 0x%x, ea = 0x%llx, tag = 0x%x, size = 0x%x)", op, cmd, lsa, ea, tag, size); @@ -549,6 +602,9 @@ public: case SPU_RdSigNotify2: return SPU.SNR[1].GetCount(); + case MFC_RdAtomicStat: + return Prxy.AtomicStat.GetCount(); + default: ConLog.Error("%s error: unknown/illegal channel (%d [%s]).", __FUNCTION__, ch, spu_ch_name[ch]); break; @@ -641,6 +697,10 @@ public: //ConLog.Warning("%s: 0x%x = %s", __FUNCTION__, v, spu_ch_name[ch]); break; + case MFC_RdAtomicStat: + while (!Prxy.AtomicStat.Pop(v) && !Emu.IsStopped()) Sleep(1); + break; + default: ConLog.Error("%s error: unknown/illegal channel (%d [%s]).", __FUNCTION__, ch, spu_ch_name[ch]); break; diff --git a/rpcs3/Emu/Memory/Memory.h b/rpcs3/Emu/Memory/Memory.h index 5a50c3a2c8..9f53cad357 100644 --- a/rpcs3/Emu/Memory/Memory.h +++ b/rpcs3/Emu/Memory/Memory.h @@ -425,9 +425,9 @@ public: return Memory.IsGoodAddr(m_addr, sizeof(T)); } - __forceinline operator bool() const + __forceinline operator u32() const { - return m_addr != 0; + return m_addr; } __forceinline bool operator != (nullptr_t) const @@ -592,6 +592,11 @@ public: return *this; } + __forceinline T GetValue() + { + return (be_t&)Memory[this->m_addr]; + } + operator const T() const { return (be_t&)Memory[this->m_addr]; diff --git a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp index 451d61d1cc..987a1d1db1 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp @@ -4,6 +4,7 @@ void cellSync_init(); Module cellSync("cellSync", cellSync_init); +wxMutex g_SyncMutex; // Return Codes enum @@ -22,77 +23,93 @@ enum CELL_SYNC_ERROR_NO_SPU_CONTEXT_STORAGE = 0x80410114, }; -int cellSyncMutexInitialize(mem32_t mutex) +struct CellSyncMutex { + be_t m_freed; + be_t m_order; + /* + (???) Lock: increase m_order and wait until m_freed == old m_order + (???) Unlock: increase m_freed + (???) TryLock: ????? + */ +}; + +int cellSyncMutexInitialize(mem_ptr_t mutex) { cellSync.Log("cellSyncMutexInitialize(mutex=0x%x)", mutex.GetAddr()); - const u32 mutex_addr = mutex.GetAddr(); - if (!mutex_addr) + + if (!mutex.IsGood()) { return CELL_SYNC_ERROR_NULL_POINTER; } - if (mutex_addr % 4) + if (mutex.GetAddr() % 4) { return CELL_SYNC_ERROR_ALIGN; } - mutex = 0; - _mm_sfence(); + { + wxMutexLocker lock(g_SyncMutex); + mutex->m_freed = 0; + mutex->m_order = 0; + } return CELL_OK; } -int cellSyncMutexLock(mem32_t mutex) +int cellSyncMutexLock(mem_ptr_t mutex) { - cellSync.Log("cellSyncMutexLock(mutex=0x%x)", mutex.GetAddr()); - const u32 mutex_addr = mutex.GetAddr(); - if (!mutex_addr) + if (!mutex.IsGood()) { return CELL_SYNC_ERROR_NULL_POINTER; } - if (mutex_addr % 4) + if (mutex.GetAddr() % 4) { return CELL_SYNC_ERROR_ALIGN; } - while (_InterlockedExchange((volatile long*)(Memory + mutex_addr), 1 << 24)); - //need to check how does SPU work with these mutexes, also obtainment order is not guaranteed - _mm_lfence(); + + be_t old_order; + { + wxMutexLocker lock(g_SyncMutex); + cellSync.Log("cellSyncMutexLock(mutex=0x%x[order=%d,freed=%d])", mutex.GetAddr(), (u16)mutex->m_order, (u16)mutex->m_freed); + old_order = mutex->m_order; + mutex->m_order = mutex->m_order + 1; + } + while (old_order != mutex->m_freed) Sleep(1); return CELL_OK; } -int cellSyncMutexTryLock(mem32_t mutex) +int cellSyncMutexTryLock(mem_ptr_t mutex) { - cellSync.Log("cellSyncMutexTryLock(mutex=0x%x)", mutex.GetAddr()); - const u32 mutex_addr = mutex.GetAddr(); - if (!mutex_addr) + if (!mutex.IsGood()) { return CELL_SYNC_ERROR_NULL_POINTER; } - if (mutex_addr % 4) + if (mutex.GetAddr() % 4) { return CELL_SYNC_ERROR_ALIGN; } - //check cellSyncMutexLock - if (_InterlockedExchange((volatile long*)(Memory + mutex_addr), 1 << 24)) + + wxMutexLocker lock(g_SyncMutex); + cellSync.Log("cellSyncMutexTryLock(mutex=0x%x[order=%d,freed=%d])", mutex.GetAddr(), (u16)mutex->m_order, (u16)mutex->m_freed); + if (mutex->m_order != mutex->m_freed) { return CELL_SYNC_ERROR_BUSY; } - _mm_lfence(); + mutex->m_order = mutex->m_order + 1; return CELL_OK; } -int cellSyncMutexUnlock(mem32_t mutex) +int cellSyncMutexUnlock(mem_ptr_t mutex) { - cellSync.Log("cellSyncMutexUnlock(mutex=0x%x)", mutex.GetAddr()); - const u32 mutex_addr = mutex.GetAddr(); - if (!mutex_addr) + if (!mutex.IsGood()) { return CELL_SYNC_ERROR_NULL_POINTER; } - if (mutex_addr % 4) + if (mutex.GetAddr() % 4) { return CELL_SYNC_ERROR_ALIGN; } - //check cellSyncMutexLock - _mm_sfence(); - _InterlockedExchange((volatile long*)(Memory + mutex_addr), 0); + + wxMutexLocker lock(g_SyncMutex); + cellSync.Log("cellSyncMutexUnlock(mutex=0x%x[order=%d,freed=%d])", mutex.GetAddr(), (u16)mutex->m_order, (u16)mutex->m_freed); + mutex->m_freed = mutex->m_freed + 1; return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp b/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp index 1c2866b22b..28584b91c6 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp @@ -238,10 +238,12 @@ int cellSysutilGetSystemParamString(s32 id, mem_list_ptr_t buf, u32 bufsize) { case CELL_SYSUTIL_SYSTEMPARAM_ID_NICKNAME: cellSysutil.Warning("cellSysutilGetSystemParamString: CELL_SYSUTIL_SYSTEMPARAM_ID_NICKNAME"); + memcpy(buf, "Unknown", 8); //for example break; case CELL_SYSUTIL_SYSTEMPARAM_ID_CURRENT_USERNAME: cellSysutil.Warning("cellSysutilGetSystemParamString: CELL_SYSUTIL_SYSTEMPARAM_ID_CURRENT_USERNAME"); + memcpy(buf, "Unknown", 8); break; default: diff --git a/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp b/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp index 9819ef8fbd..9bfc0ef639 100644 --- a/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp @@ -143,7 +143,6 @@ int cellFsAioRead(mem_ptr_t aio, mem32_t aio_id, mem_func_ptr_tfd; 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) u64 nbytes = (u64)aio->size; const u32 buf_addr = (u32)aio->buf_addr; @@ -153,7 +152,8 @@ int cellFsAioRead(mem_ptr_t aio, mem32_t aio_id, mem_func_ptr_t aio, mem32_t aio_id, mem_func_ptr_tbuf_addr); - if(func) - func(aio, error, xid, res); + //if(func) func.async(aio, error, xid, res); return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp b/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp index 8e873b7972..d7bf58f94b 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp @@ -95,6 +95,7 @@ int cellFsOpen(u32 path_addr, int flags, mem32_t fd, mem32_t arg, u64 size) } fd = sys_fs.GetNewId(stream, flags); + sys_fs.Warning("cellFsOpen(path: %s): fd == %d", path.mb_str(), fd.GetValue()); return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Memory.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Memory.cpp index 7d7d866995..f1674f6ab4 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Memory.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Memory.cpp @@ -6,20 +6,26 @@ SysCallBase sc_mem("memory"); int sys_memory_container_create(u32 cid_addr, u32 yield_size) { - sc_mem.Warning("sys_memory_container_create(cid_addr=0x%x,yield_size=0x%x)", cid_addr, yield_size); + sc_mem.Warning("(HACK!) sys_memory_container_create(cid_addr=0x%x,yield_size=0x%x)", cid_addr, yield_size); if(!Memory.IsGoodAddr(cid_addr, 4)) { return CELL_EFAULT; } - u64 addr = Memory.Alloc(yield_size, 1); + yield_size &= ~0xfffff; //round down to 1 MB granularity + + //alignment hack (Memory.Alloc does not support alignment yet): alloc size is increased + u64 addr = Memory.Alloc(yield_size + 0x100000, 0x100000); //1 MB alignment (???) if(!addr) { return CELL_ENOMEM; } + //fix alignment: + addr = (addr + 0x100000) & ~0xfffff; + Memory.Write32(cid_addr, sc_mem.GetNewId(new MemoryContainerInfo(addr, yield_size))); return CELL_OK; } @@ -43,18 +49,20 @@ int sys_memory_container_destroy(u32 cid) int sys_memory_allocate(u32 size, u32 flags, u32 alloc_addr_addr) { //0x30000100; - sc_mem.Log("sys_memory_allocate(size=0x%x, flags=0x%x)", size, flags); + sc_mem.Warning("(HACK!) sys_memory_allocate(size=0x%x, flags=0x%x)", size, flags); u32 addr; switch(flags) { case SYS_MEMORY_PAGE_SIZE_1M: if(size & 0xfffff) return CELL_EALIGN; - addr = Memory.Alloc(size, 0x100000); + addr = Memory.Alloc(size + 0x100000, 0x100000); + addr = (addr + 0x100000) & ~0xfffff; break; case SYS_MEMORY_PAGE_SIZE_64K: if(size & 0xffff) return CELL_EALIGN; - addr = Memory.Alloc(size, 0x10000); + addr = Memory.Alloc(size + 0x10000, 0x10000); + addr = (addr + 0x10000) & ~0xffff; break; default: return CELL_EINVAL; From 2506810a2ea9427c3d47216cee1d7f637e0968ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandro=20S=C3=A1nchez=20Bach?= Date: Fri, 10 Jan 2014 22:06:22 +0100 Subject: [PATCH 6/8] cellAudio updated cellAudio: * Change endianness of datatypes. * Fixed port handling. * Uninitialize module when restarting. * Minor syntax fixes. --- rpcs3/Emu/SysCalls/Modules/cellAudio.cpp | 133 +++++++++++++---------- rpcs3/Gui/MemoryViewer.cpp | 1 - rpcs3/Gui/RSXDebugger.cpp | 3 +- 3 files changed, 74 insertions(+), 63 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp b/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp index ea53995fa0..118abc319a 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp @@ -4,7 +4,8 @@ #include "Emu/Audio/cellAudio.h" void cellAudio_init(); -Module cellAudio(0x0011, cellAudio_init); +void cellAudio_unload(); +Module cellAudio(0x0011, cellAudio_init, nullptr, cellAudio_unload); enum { @@ -81,9 +82,9 @@ struct CellAudioPortConfig struct CellAudioConfig //custom structure { - bool g_is_audio_initialized; - bool g_is_audio_port_open; - bool g_is_audio_port_started; + bool m_is_audio_initialized; + bool m_is_audio_port_open; + bool m_is_audio_port_started; }; CellAudioPortParam* m_param = new CellAudioPortParam; @@ -95,55 +96,55 @@ typedef void * CellAANHandle; struct CellSSPlayerConfig { - u32 channels; - u32 outputMode; + be_t channels; + be_t outputMode; }; struct CellSSPlayerWaveParam { void *addr; - int format; - u32 samples; - u32 loopStartOffset; - u32 startOffset; + be_t format; + be_t samples; + be_t loopStartOffset; + be_t startOffset; }; struct CellSSPlayerCommonParam { - u32 loopMode; - u32 attackMode; + be_t loopMode; + be_t attackMode; }; struct CellSurMixerPosition { - float x; - float y; - float z; + be_t x; + be_t y; + be_t z; }; struct CellSSPlayerRuntimeInfo { - float level; - float speed; + be_t level; + be_t speed; CellSurMixerPosition position; }; struct CellSurMixerConfig { - s32 priority; - u32 chStrips1; - u32 chStrips2; - u32 chStrips6; - u32 chStrips8; + be_t priority; + be_t chStrips1; + be_t chStrips2; + be_t chStrips6; + be_t chStrips8; }; struct CellSurMixerChStripParam { - u32 param; + be_t param; void *attribute; - int dBSwitch; - float floatVal; - int intVal; + be_t dBSwitch; + be_t floatVal; + be_t intVal; }; CellSSPlayerWaveParam current_SSPlayerWaveParam; @@ -164,31 +165,31 @@ struct CellSnd3KeyOnParam u8 vel; u8 pan; u8 panEx; - s32 addPitch; + be_t addPitch; }; struct CellSnd3VoiceBitCtx { - u32 core; //[CELL_SND3_MAX_CORE], unknown identifier + be_t core; //[CELL_SND3_MAX_CORE], unknown identifier }; struct CellSnd3RequestQueueCtx { void *frontQueue; - u32 frontQueueSize; + be_t frontQueueSize; void *rearQueue; - u32 rearQueueSize; + be_t rearQueueSize; }; //libsynt2 datatypes struct CellSoundSynth2EffectAttr { - u16 core; - u16 mode; - s16 depth_L; - s16 depth_R; - u16 delay; - u16 feedback; + be_t core; + be_t mode; + be_t depth_L; + be_t depth_R; + be_t delay; + be_t feedback; }; // libaudio Functions @@ -196,28 +197,26 @@ struct CellSoundSynth2EffectAttr int cellAudioInit() { cellAudio.Warning("cellAudioInit()"); - if(m_config->g_is_audio_initialized == true) return CELL_AUDIO_ERROR_ALREADY_INIT; - m_config->g_is_audio_initialized = true; + if(m_config->m_is_audio_initialized == true) return CELL_AUDIO_ERROR_ALREADY_INIT; + m_config->m_is_audio_initialized = true; return CELL_OK; } int cellAudioQuit() { cellAudio.Warning("cellAudioQuit()"); - if (m_config->g_is_audio_initialized == false) return CELL_AUDIO_ERROR_NOT_INIT; - m_config->g_is_audio_initialized = false; + if (m_config->m_is_audio_initialized == false) return CELL_AUDIO_ERROR_NOT_INIT; + m_config->m_is_audio_initialized = false; - delete m_config; return CELL_OK; } int cellAudioPortOpen(mem_ptr_t audioParam, mem32_t portNum) { cellAudio.Warning("cellAudioPortOpen(audioParam_addr=0x%x,portNum_addr=0x%x)",audioParam.GetAddr(),portNum.GetAddr()); - UNIMPLEMENTED_FUNC(cellAudio); if(!audioParam.IsGood() || !portNum.IsGood()) return CELL_AUDIO_ERROR_PORT_OPEN; - m_config->g_is_audio_port_open = true; + m_config->m_is_audio_port_open = true; m_param->nChannel = audioParam->nChannel; m_param->nBlock = audioParam->nBlock; @@ -235,20 +234,22 @@ int cellAudioGetPortConfig(u32 portNum, mem_ptr_t portConfi if(!portConfig.IsGood()) { return CELL_AUDIO_ERROR_PARAM; - }; + } //if(portNum > 7) return CELL_AUDIO_ERROR_PORT_FULL; - if(m_config->g_is_audio_port_open == false) + if(m_config->m_is_audio_port_open == false) { portConfig->status = CELL_AUDIO_STATUS_CLOSE; return CELL_OK; - }; + } - if(m_config->g_is_audio_port_started == true) + if(m_config->m_is_audio_port_started == true) + { portConfig->status = CELL_AUDIO_STATUS_RUN; - + } else + { portConfig->status = CELL_AUDIO_STATUS_READY; portConfig->nChannel = m_param->nChannel; portConfig->nBlock = m_param->nBlock; @@ -258,36 +259,41 @@ int cellAudioGetPortConfig(u32 portNum, mem_ptr_t portConfi // portAddr - readIndexAddr == 0xFFF0 on ps3 Memory.Write64(portConfig->readIndexAddr, 1); - return CELL_OK; + } + + return CELL_OK; } int cellAudioPortStart(u32 portNum) { cellAudio.Warning("cellAudioPortStart(portNum=0x%x)",portNum); - if (m_config->g_is_audio_port_open == false) return CELL_AUDIO_ERROR_PORT_NOT_OPEN; - m_config->g_is_audio_port_started = true; - + if (m_config->m_is_audio_port_open == true) + return CELL_AUDIO_ERROR_PORT_OPEN; + + m_config->m_is_audio_port_started = true; return CELL_OK; } int cellAudioPortClose(u32 portNum) { cellAudio.Warning("cellAudioPortClose(portNum=0x%x)",portNum); - if (m_config->g_is_audio_port_open == false) return CELL_AUDIO_ERROR_PORT_NOT_OPEN; - m_config->g_is_audio_port_open = false; - - UNIMPLEMENTED_FUNC(cellAudio); + + if (m_config->m_is_audio_port_open == false) + return CELL_AUDIO_ERROR_PORT_NOT_OPEN; + + m_config->m_is_audio_port_open = false; return CELL_OK; } int cellAudioPortStop(u32 portNum) { cellAudio.Warning("cellAudioPortStop(portNum=0x%x)",portNum); - if (m_config->g_is_audio_port_started == false) return CELL_AUDIO_ERROR_PORT_NOT_OPEN; - m_config->g_is_audio_port_started = false; - - UNIMPLEMENTED_FUNC(cellAudio); + + if (m_config->m_is_audio_port_started == false) + return CELL_AUDIO_ERROR_PORT_NOT_OPEN; + + m_config->m_is_audio_port_started = false; return CELL_OK; } @@ -1006,3 +1012,10 @@ void cellAudio_init() //TODO: Find addresses for libmixer, libsnd3 and libsynth2 functions } + +void cellAudio_unload() +{ + m_config->m_is_audio_initialized = false; + m_config->m_is_audio_port_open = false; + m_config->m_is_audio_port_started = false; +} \ No newline at end of file diff --git a/rpcs3/Gui/MemoryViewer.cpp b/rpcs3/Gui/MemoryViewer.cpp index c7bc0a0460..c3a95a74ad 100644 --- a/rpcs3/Gui/MemoryViewer.cpp +++ b/rpcs3/Gui/MemoryViewer.cpp @@ -1,6 +1,5 @@ #include "stdafx.h" #include "MemoryViewer.h" -#include "Emu/Memory/Memory.h" MemoryViewerPanel::MemoryViewerPanel(wxWindow* parent) : wxFrame(parent, wxID_ANY, "Memory Viewer", wxDefaultPosition, wxSize(700, 450)) diff --git a/rpcs3/Gui/RSXDebugger.cpp b/rpcs3/Gui/RSXDebugger.cpp index 5f5beceeb7..cd6be3881f 100644 --- a/rpcs3/Gui/RSXDebugger.cpp +++ b/rpcs3/Gui/RSXDebugger.cpp @@ -1,6 +1,5 @@ #include "stdafx.h" #include "RSXDebugger.h" -#include "Emu/Memory/Memory.h" #include "Emu/GS/sysutil_video.h" #include "Emu/GS/GCM.h" @@ -26,7 +25,7 @@ RSXDebugger::RSXDebugger(wxWindow* parent) wxBoxSizer& s_tools = *new wxBoxSizer(wxVERTICAL); // Controls - wxStaticBoxSizer& s_controls = *new wxStaticBoxSizer(wxHORIZONTAL, this, "Memory Viewer Options"); + wxStaticBoxSizer& s_controls = *new wxStaticBoxSizer(wxHORIZONTAL, this, "RSX Debugger Controls"); // Controls: Address wxStaticBoxSizer& s_controls_addr = *new wxStaticBoxSizer(wxHORIZONTAL, this, "Address:"); From 970b834f2e82ef7d379a25fe74063b3d5b6d7165 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sun, 12 Jan 2014 14:27:59 +0400 Subject: [PATCH 7/8] CellSync review (mutexes, SPU). File descriptors temporarily detached from ID manager. Some logs disabled. --- rpcs3/Emu/Cell/SPUThread.h | 39 +++----------- rpcs3/Emu/SysCalls/Modules/cellSync.cpp | 69 ++++++++++++++++-------- rpcs3/Emu/SysCalls/Modules/sys_fs.cpp | 46 ++++++++++++---- rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp | 65 ++++++++++++++-------- rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp | 4 +- rpcs3/Loader/Loader.h | 2 +- 6 files changed, 138 insertions(+), 87 deletions(-) diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index 38788022f1..84618e74a1 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -524,50 +524,23 @@ public: case MFC_PUTLLC_CMD: case MFC_PUTLLUC_CMD: { - extern wxMutex g_SyncMutex; - const CPUThread& current = *GetCurrentPPCThread(); + extern std::mutex g_SyncMutex; + //can provide compatability for CellSyncMutex through SPU<>PPU and SPU<>SPU if (op == MFC_GETLLAR_CMD) { - g_SyncMutex.Lock(); - /* for (u32 i = 0; i < Emu.GetCPU().GetThreads().GetCount(); i++) - { - CPUThread& t = *Emu.GetCPU().GetThread(i); - if (&t != ¤t && &t) - { - while (!t.IsRunning()) Sleep(1); - t.Pause(); - } - } - for (u32 i = 0; i < Emu.GetCPU().GetThreads().GetCount(); i++) - { - CPUThread& t = *Emu.GetCPU().GetThread(i); - if (&t != ¤t && &t) - { - if (!t.IsPaused()) Sleep(1); - } - } */ + 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); - //draft implementation - _mm_mfence(); + 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); - _mm_mfence(); - if (op != MFC_GETLLAR_CMD) + if (op == MFC_PUTLLC_CMD || op == MFC_PUTLLUC_CMD) { - /*for (u32 i = 0; i < Emu.GetCPU().GetThreads().GetCount(); i++) - { - CPUThread& t = *Emu.GetCPU().GetThread(i); - if (&t != ¤t && &t) - { - t.Resume(); //it's wrong (some threads shall not be resumed) - } - }*/ - g_SyncMutex.Unlock(); + g_SyncMutex.unlock(); } } break; diff --git a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp index 987a1d1db1..ee0ae0d43e 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp @@ -1,10 +1,12 @@ #include "stdafx.h" #include "Emu/SysCalls/SysCalls.h" #include "Emu/SysCalls/SC_FUNC.h" +#include void cellSync_init(); -Module cellSync("cellSync", cellSync_init); -wxMutex g_SyncMutex; +void cellSync_unload(); +Module cellSync("cellSync", cellSync_init, nullptr, cellSync_unload); +std::mutex g_SyncMutex; // Return Codes enum @@ -27,6 +29,7 @@ struct CellSyncMutex { be_t m_freed; be_t m_order; /* + (???) Initialize: set zeros (???) Lock: increase m_order and wait until m_freed == old m_order (???) Unlock: increase m_freed (???) TryLock: ????? @@ -45,16 +48,19 @@ int cellSyncMutexInitialize(mem_ptr_t mutex) { return CELL_SYNC_ERROR_ALIGN; } - { - wxMutexLocker lock(g_SyncMutex); + + { /* global mutex */ + std::lock_guard lock(g_SyncMutex); //??? mutex->m_freed = 0; mutex->m_order = 0; + return CELL_OK; } - return CELL_OK; } int cellSyncMutexLock(mem_ptr_t mutex) { + cellSync.Log("cellSyncMutexLock(mutex=0x%x)", mutex.GetAddr()); + if (!mutex.IsGood()) { return CELL_SYNC_ERROR_NULL_POINTER; @@ -65,18 +71,31 @@ int cellSyncMutexLock(mem_ptr_t mutex) } be_t old_order; - { - wxMutexLocker lock(g_SyncMutex); - cellSync.Log("cellSyncMutexLock(mutex=0x%x[order=%d,freed=%d])", mutex.GetAddr(), (u16)mutex->m_order, (u16)mutex->m_freed); + { /* global mutex */ + std::lock_guard lock(g_SyncMutex); old_order = mutex->m_order; mutex->m_order = mutex->m_order + 1; } - while (old_order != mutex->m_freed) Sleep(1); + + int counter = 0; + while (old_order != 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; + } + } return CELL_OK; } int cellSyncMutexTryLock(mem_ptr_t mutex) { + cellSync.Log("cellSyncMutexTryLock(mutex=0x%x)", mutex.GetAddr()); + if (!mutex.IsGood()) { return CELL_SYNC_ERROR_NULL_POINTER; @@ -85,19 +104,21 @@ int cellSyncMutexTryLock(mem_ptr_t mutex) { return CELL_SYNC_ERROR_ALIGN; } - - wxMutexLocker lock(g_SyncMutex); - cellSync.Log("cellSyncMutexTryLock(mutex=0x%x[order=%d,freed=%d])", mutex.GetAddr(), (u16)mutex->m_order, (u16)mutex->m_freed); - if (mutex->m_order != mutex->m_freed) - { - return CELL_SYNC_ERROR_BUSY; + { /* global mutex */ + std::lock_guard lock(g_SyncMutex); + if (mutex->m_order != mutex->m_freed) + { + return CELL_SYNC_ERROR_BUSY; + } + mutex->m_order = mutex->m_order + 1; + return CELL_OK; } - mutex->m_order = mutex->m_order + 1; - return CELL_OK; } int cellSyncMutexUnlock(mem_ptr_t mutex) { + cellSync.Log("cellSyncMutexUnlock(mutex=0x%x)", mutex.GetAddr()); + if (!mutex.IsGood()) { return CELL_SYNC_ERROR_NULL_POINTER; @@ -107,10 +128,11 @@ int cellSyncMutexUnlock(mem_ptr_t mutex) return CELL_SYNC_ERROR_ALIGN; } - wxMutexLocker lock(g_SyncMutex); - cellSync.Log("cellSyncMutexUnlock(mutex=0x%x[order=%d,freed=%d])", mutex.GetAddr(), (u16)mutex->m_order, (u16)mutex->m_freed); - mutex->m_freed = mutex->m_freed + 1; - return CELL_OK; + { /* global mutex */ + std::lock_guard lock(g_SyncMutex); + mutex->m_freed = mutex->m_freed + 1; + return CELL_OK; + } } void cellSync_init() @@ -119,4 +141,9 @@ void cellSync_init() cellSync.AddFunc(0x1bb675c2, cellSyncMutexLock); cellSync.AddFunc(0xd06918c4, cellSyncMutexTryLock); cellSync.AddFunc(0x91f2b7b0, cellSyncMutexUnlock); +} + +void cellSync_unload() +{ + g_SyncMutex.unlock(); } \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp b/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp index 9bfc0ef639..ca291901f1 100644 --- a/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp @@ -3,7 +3,9 @@ #include "Emu/SysCalls/SC_FUNC.h" void sys_fs_init(); -Module sys_fs(0x000e, sys_fs_init); +void sys_fs_unload(); +Module sys_fs(0x000e, sys_fs_init, nullptr, sys_fs_unload); +Array FDs; bool sdata_check(u32 version, u32 flags, u64 filesizeInput, u64 filesizeTmp) { @@ -137,12 +139,9 @@ int cellFsSdataOpen(u32 path_addr, int flags, mem32_t fd, mem32_t arg, u64 size) std::atomic g_FsAioReadID = 0; -int cellFsAioRead(mem_ptr_t aio, mem32_t aio_id, mem_func_ptr_t xaio, u32 error, int xid, u64 size)> func) +void fsAioRead(u32 fd, mem_ptr_t aio, mem32_t aio_id, mem_func_ptr_t xaio, u32 error, int xid, u64 size)> func) { - ID id; - u32 fd = (u32)aio->fd; - if(!sys_fs.CheckId(fd, id)) return CELL_ESRCH; - vfsFileBase& orig_file = *(vfsFileBase*)id.m_data; + vfsFileBase& orig_file = *(vfsFileBase*)FDs[fd]; u64 nbytes = (u64)aio->size; const u32 buf_addr = (u32)aio->buf_addr; @@ -175,10 +174,26 @@ int cellFsAioRead(mem_ptr_t aio, mem32_t aio_id, mem_func_ptr_tbuf_addr); + //start callback thread + if(func) + func.async(aio.GetAddr(), error, xid, res); +} - //if(func) func.async(aio, error, xid, res); +int cellFsAioRead(mem_ptr_t aio, mem32_t aio_id, mem_func_ptr_t xaio, u32 error, int xid, u64 size)> func) +{ + //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]; + + std::thread t(fsAioRead, fd, aio, aio_id, func); + t.detach(); + + sys_fs.Warning("cellFsAioRead(aio_addr: 0x%x[%s, addr=0x%x], id_addr: 0x%x, func_addr: 0x%x)", aio.GetAddr(), + orig_file.GetPath().c_str(), (u32)aio->buf_addr, aio_id.GetAddr(), func.GetAddr()); return CELL_OK; } @@ -205,3 +220,16 @@ void sys_fs_init() sys_fs.AddFunc(0xcb588dba, cellFsFGetBlockSize); sys_fs.AddFunc(0xc1c507e7, cellFsAioRead); } + +void sys_fs_unload() +{ + for (u32 i = 0; i < FDs.GetCount(); i++) + { + if (FDs[i]) + { + FDs[i]->Close(); + delete FDs[i]; + } + } + FDs.Clear(); +} \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp b/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp index d7bf58f94b..fb4ad1ddf5 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp @@ -3,6 +3,7 @@ #include "Emu/SysCalls/SysCalls.h" extern Module sys_fs; +extern Array FDs; int cellFsOpen(u32 path_addr, int flags, mem32_t fd, mem32_t arg, u64 size) { @@ -94,7 +95,8 @@ int cellFsOpen(u32 path_addr, int flags, mem32_t fd, mem32_t arg, u64 size) return CELL_ENOENT; } - fd = sys_fs.GetNewId(stream, flags); + fd = FDs.AddCpy(stream); + //fd = sys_fs.GetNewId(stream, flags); sys_fs.Warning("cellFsOpen(path: %s): fd == %d", path.mb_str(), fd.GetValue()); return CELL_OK; @@ -104,9 +106,12 @@ int cellFsRead(u32 fd, u32 buf_addr, u64 nbytes, mem64_t nread) { sys_fs.Log("cellFsRead(fd: %d, buf_addr: 0x%x, nbytes: 0x%llx, nread_addr: 0x%x)", fd, buf_addr, nbytes, nread.GetAddr()); - ID id; - if(!sys_fs.CheckId(fd, id)) return CELL_ESRCH; - vfsStream& file = *(vfsStream*)id.m_data; + //ID id; + //if(!sys_fs.CheckId(fd, id)) return CELL_ESRCH; + if (fd >= FDs.GetCount()) return CELL_ESRCH; + if (FDs[fd] == nullptr) return CELL_ESRCH; + //vfsStream& file = *(vfsStream*)id.m_data; + vfsStream& file = *(vfsStream*)FDs[fd]; if(Memory.IsGoodAddr(buf_addr) && !Memory.IsGoodAddr(buf_addr, nbytes)) { @@ -126,9 +131,13 @@ int cellFsWrite(u32 fd, u32 buf_addr, u64 nbytes, mem64_t nwrite) { sys_fs.Log("cellFsWrite(fd: %d, buf_addr: 0x%x, nbytes: 0x%llx, nwrite_addr: 0x%x)", fd, buf_addr, nbytes, nwrite.GetAddr()); - ID id; - if(!sys_fs.CheckId(fd, id)) return CELL_ESRCH; - vfsStream& file = *(vfsStream*)id.m_data; + //ID id; + //if(!sys_fs.CheckId(fd, id)) return CELL_ESRCH; + if (fd >= FDs.GetCount()) return CELL_ESRCH; + if (FDs[fd] == nullptr) return CELL_ESRCH; + //vfsStream& file = *(vfsStream*)id.m_data; + vfsStream& file = *(vfsStream*)FDs[fd]; + if(Memory.IsGoodAddr(buf_addr) && !Memory.IsGoodAddr(buf_addr, nbytes)) { MemoryBlock& block = Memory.GetMemByAddr(buf_addr); @@ -145,12 +154,17 @@ int cellFsWrite(u32 fd, u32 buf_addr, u64 nbytes, mem64_t nwrite) int cellFsClose(u32 fd) { - sys_fs.Log("cellFsClose(fd: %d)", fd); - ID id; - if(!sys_fs.CheckId(fd, id)) return CELL_ESRCH; - vfsStream& file = *(vfsStream*)id.m_data; + sys_fs.Warning("cellFsClose(fd: %d)", fd); + //ID id; + //if(!sys_fs.CheckId(fd, id)) return CELL_ESRCH; + if (fd >= FDs.GetCount()) return CELL_ESRCH; + if (FDs[fd] == nullptr) return CELL_ESRCH; + //vfsStream& file = *(vfsStream*)id.m_data; + vfsStream& file = *(vfsStream*)FDs[fd]; file.Close(); - Emu.GetIdManager().RemoveID(fd); + delete FDs[fd]; + //Emu.GetIdManager().RemoveID(fd); + FDs[fd] = nullptr; return CELL_OK; } @@ -232,9 +246,12 @@ int cellFsStat(const u32 path_addr, mem_ptr_t sb) int cellFsFstat(u32 fd, mem_ptr_t sb) { sys_fs.Log("cellFsFstat(fd: %d, sb_addr: 0x%x)", fd, sb.GetAddr()); - ID id; - if(!sys_fs.CheckId(fd, id)) return CELL_ESRCH; - vfsStream& file = *(vfsStream*)id.m_data; + //ID id; + //if(!sys_fs.CheckId(fd, id)) return CELL_ESRCH; + if (fd >= FDs.GetCount()) return CELL_ESRCH; + if (FDs[fd] == nullptr) return CELL_ESRCH; + //vfsStream& file = *(vfsStream*)id.m_data; + vfsStream& file = *(vfsStream*)FDs[fd]; sb->st_mode = CELL_FS_S_IRUSR | CELL_FS_S_IWUSR | CELL_FS_S_IXUSR | @@ -313,9 +330,12 @@ int cellFsLseek(u32 fd, s64 offset, u32 whence, mem64_t pos) sys_fs.Error(fd, "Unknown seek whence! (%d)", whence); return CELL_EINVAL; } - ID id; - if(!sys_fs.CheckId(fd, id)) return CELL_ESRCH; - vfsStream& file = *(vfsStream*)id.m_data; + //ID id; + //if(!sys_fs.CheckId(fd, id)) return CELL_ESRCH; + if (fd >= FDs.GetCount()) return CELL_ESRCH; + if (FDs[fd] == nullptr) return CELL_ESRCH; + //vfsStream& file = *(vfsStream*)id.m_data; + vfsStream& file = *(vfsStream*)FDs[fd]; pos = file.Seek(offset, seek_mode); return CELL_OK; } @@ -323,9 +343,12 @@ int cellFsLseek(u32 fd, s64 offset, u32 whence, mem64_t pos) int cellFsFtruncate(u32 fd, u64 size) { sys_fs.Log("cellFsFtruncate(fd: %d, size: %lld)", fd, size); - ID id; - if(!sys_fs.CheckId(fd, id)) return CELL_ESRCH; - vfsStream& file = *(vfsStream*)id.m_data; + //ID id; + //if(!sys_fs.CheckId(fd, id)) return CELL_ESRCH; + if (fd >= FDs.GetCount()) return CELL_ESRCH; + if (FDs[fd] == nullptr) return CELL_ESRCH; + //vfsStream& file = *(vfsStream*)id.m_data; + vfsStream& file = *(vfsStream*)FDs[fd]; u64 initialSize = file.GetSize(); if (initialSize < size) diff --git a/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp b/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp index 2f1c27f98c..543e72d975 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp @@ -138,7 +138,7 @@ int sys_spu_thread_initialize(mem32_t thread, u32 group, u32 spu_num, mem_ptr_t< group_info.threads[spu_num] = &new_thread; - ConLog.Write("New SPU Thread:"); + /*ConLog.Write("New SPU Thread:"); ConLog.Write("SPU img offset = 0x%x", (u32)img->segs_addr); ConLog.Write("entry_point = 0x%x", spu_ep); ConLog.Write("name = %s", name.c_str()); @@ -147,7 +147,7 @@ int sys_spu_thread_initialize(mem32_t thread, u32 group, u32 spu_num, mem_ptr_t< ConLog.Write("a3 = 0x%x", a3); ConLog.Write("a4 = 0x%x", a4); ConLog.Write("ls_offset = 0x%x", ((SPUThread&)new_thread).dmac.ls_offset); - ConLog.SkipLn(); + ConLog.SkipLn();*/ return CELL_OK; } diff --git a/rpcs3/Loader/Loader.h b/rpcs3/Loader/Loader.h index ab5c974c20..8e5ec023bd 100644 --- a/rpcs3/Loader/Loader.h +++ b/rpcs3/Loader/Loader.h @@ -2,7 +2,7 @@ #include "Emu/FS/vfsFileBase.h" #ifdef _DEBUG - #define LOADER_DEBUG + //#define LOADER_DEBUG #endif enum Elf_Machine From e41f21abc758c03da2c92228a8de053578d2fbcb Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Tue, 14 Jan 2014 23:03:48 +0400 Subject: [PATCH 8/8] Simple analog stick support (from KB) Left stick: arrows; right stick: PgDn/PgUp (vertical) and Home/End (horizontal) Added L10n functions' list (copied from old distr) Fixed "LoadShdr64 error: shstrndx too big" in ELF64 loader Other minor changes --- rpcs3/Emu/Cell/SPUThread.h | 31 ++-- rpcs3/Emu/Io/PadHandler.h | 40 ++++- rpcs3/Emu/Io/Windows/WindowsPadHandler.h | 5 + rpcs3/Emu/SysCalls/FuncList.cpp | 165 +++++++++++++++++++++ rpcs3/Emu/SysCalls/Modules.cpp | 2 +- rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp | 39 +++++ rpcs3/Emu/SysCalls/Modules/cellSync.cpp | 22 ++- rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp | 2 + rpcs3/Emu/SysCalls/Modules/sys_fs.cpp | 48 ++++-- rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp | 2 +- rpcs3/Emu/SysCalls/lv2/SC_Pad.cpp | 31 +++- rpcs3/Loader/ELF64.cpp | 4 +- 12 files changed, 345 insertions(+), 46 deletions(-) diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index 84618e74a1..c6aadacdc7 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -2,6 +2,9 @@ #include "PPCThread.h" #include "Emu/event.h" #include "MFC.h" +#include + +extern std::mutex g_SyncMutex; //can provide compatability for CellSyncMutex through SPU<>PPU and SPU<>SPU static const char* spu_reg_name[128] = { @@ -293,7 +296,7 @@ public: }; volatile u64 m_indval; }; - wxCriticalSection m_lock; + std::mutex m_lock; public: @@ -311,7 +314,7 @@ public: { if (max_count > 1 || x86) { - wxCriticalSectionLocker lock(m_lock); + std::lock_guard lock(m_lock); if(!m_index) { return false; @@ -322,7 +325,7 @@ public: } else { //lock-free - if(!m_index) + if ((m_indval & 0xffffffff) == 0) return false; else { @@ -337,7 +340,7 @@ public: { if (max_count > 1 || x86) { - wxCriticalSectionLocker lock(m_lock); + std::lock_guard lock(m_lock); if(m_index >= max_count) { return false; @@ -347,11 +350,12 @@ public: } else { //lock-free - if(m_index) + if (m_indval & 0xffffffff) return false; else { - m_indval = ((u64)value << 32) | 1; + const u64 new_value = ((u64)value << 32) | 1; + m_indval = new_value; return true; } } @@ -361,7 +365,7 @@ public: { if (max_count > 1 || x86) { - wxCriticalSectionLocker lock(m_lock); + std::lock_guard lock(m_lock); if(m_index >= max_count) m_value[max_count-1] = value; //last message is overwritten else @@ -369,7 +373,8 @@ public: } else { //lock-free - m_indval = ((u64)value << 32) | 1; + const u64 new_value = ((u64)value << 32) | 1; + m_indval = new_value; } } @@ -377,7 +382,7 @@ public: { if (max_count > 1 || x86) { - wxCriticalSectionLocker lock(m_lock); + std::lock_guard lock(m_lock); if(m_index >= max_count) m_value[max_count-1] |= value; //last message is logically ORed else @@ -397,7 +402,7 @@ public: { if (max_count > 1 || x86) { - wxCriticalSectionLocker lock(m_lock); + std::lock_guard lock(m_lock); if(!m_index) res = 0; //result is undefined else @@ -422,7 +427,7 @@ public: { if (max_count > 1 || x86) { - wxCriticalSectionLocker lock(m_lock); + std::lock_guard lock(m_lock); return m_index; } else @@ -435,7 +440,7 @@ public: { if (max_count > 1 || x86) { - wxCriticalSectionLocker lock(m_lock); + std::lock_guard lock(m_lock); return max_count - m_index; } else @@ -524,8 +529,6 @@ public: case MFC_PUTLLC_CMD: case MFC_PUTLLUC_CMD: { - extern std::mutex g_SyncMutex; - //can provide compatability for CellSyncMutex through SPU<>PPU and SPU<>SPU if (op == MFC_GETLLAR_CMD) { g_SyncMutex.lock(); diff --git a/rpcs3/Emu/Io/PadHandler.h b/rpcs3/Emu/Io/PadHandler.h index 4e83d11cc7..d56be02df3 100644 --- a/rpcs3/Emu/Io/PadHandler.h +++ b/rpcs3/Emu/Io/PadHandler.h @@ -103,6 +103,24 @@ struct Button } }; +struct AnalogStick +{ + u32 m_offset; + u32 m_keyCodeMin; + u32 m_keyCodeMax; + bool m_min_pressed; + bool m_max_pressed; + + AnalogStick(u32 offset, u32 keyCodeMin, u32 keyCodeMax) + : m_min_pressed(false) + , m_max_pressed(false) + , m_offset(offset) + , m_keyCodeMin(keyCodeMin) + , m_keyCodeMax(keyCodeMax) + { + } +}; + struct Pad { u32 m_port_status; @@ -111,6 +129,7 @@ struct Pad u32 m_device_type; Array