diff --git a/rpcs3/Emu/Cell/PPCThread.h b/rpcs3/Emu/Cell/PPCThread.h index a4f2f5ae33..63ba891b28 100644 --- a/rpcs3/Emu/Cell/PPCThread.h +++ b/rpcs3/Emu/Cell/PPCThread.h @@ -159,6 +159,8 @@ public: void Stop(); virtual wxString RegsToString() { return wxEmptyString; } + virtual wxString ReadRegString(wxString reg) { return wxEmptyString; } + virtual bool WriteRegString(wxString reg, wxString value) { return false; } virtual void Exec(); void ExecOnce(); diff --git a/rpcs3/Emu/Cell/PPUThread.h b/rpcs3/Emu/Cell/PPUThread.h index 6954c31412..49baf84edf 100644 --- a/rpcs3/Emu/Cell/PPUThread.h +++ b/rpcs3/Emu/Cell/PPUThread.h @@ -753,6 +753,69 @@ public: return ret; } + virtual wxString ReadRegString(wxString reg) + { + if (reg.Contains("[")) + { + long reg_index; + reg.AfterFirst('[').RemoveLast().ToLong(®_index); + if (reg.StartsWith("GPR")) return wxString::Format("%016llx", GPR[reg_index]); + if (reg.StartsWith("FPR")) return wxString::Format("%016llx", FPR[reg_index]); + if (reg.StartsWith("VPR")) return wxString::Format("%016llx%016llx", VPR[reg_index]._u64[1], VPR[reg_index]._u64[0]); + } + if (reg == "CR") return wxString::Format("%08x", CR); + if (reg == "LR") return wxString::Format("%016llx", LR); + if (reg == "CTR") return wxString::Format("%016llx", CTR); + if (reg == "XER") return wxString::Format("%016llx", XER); + if (reg == "FPSCR") return wxString::Format("%08x", FPSCR); + return wxEmptyString; + } + + bool WriteRegString(wxString reg, wxString value) { + while (value.Len() < 32) value = "0"+value; + if (reg.Contains("[")) + { + long reg_index; + reg.AfterFirst('[').RemoveLast().ToLong(®_index); + if (reg.StartsWith("GPR") || (reg.StartsWith("FPR"))) + { + unsigned long long reg_value; + if (!value.SubString(16,31).ToULongLong(®_value, 16)) return false; + if (reg.StartsWith("GPR")) GPR[reg_index] = (u64)reg_value; + if (reg.StartsWith("FPR")) FPR[reg_index] = (u64)reg_value; + return true; + } + if (reg.StartsWith("VPR")) + { + unsigned long long reg_value0; + unsigned long long reg_value1; + if (!value.SubString(16,31).ToULongLong(®_value0, 16)) return false; + if (!value.SubString(0,15).ToULongLong(®_value1, 16)) return false; + VPR[reg_index]._u64[0] = (u64)reg_value0; + VPR[reg_index]._u64[1] = (u64)reg_value1; + return true; + } + } + if (reg == "LR" || reg == "CTR" || reg == "XER") + { + unsigned long long reg_value; + if (!value.SubString(16,31).ToULongLong(®_value, 16)) return false; + if (reg == "LR") LR = (u64)reg_value; + if (reg == "CTR") CTR = (u64)reg_value; + if (reg == "XER") XER.XER = (u64)reg_value; + return true; + } + if (reg == "CR" || reg == "FPSCR") + { + unsigned long reg_value; + if (!value.SubString(24,31).ToULong(®_value, 16)) return false; + if (reg == "CR") CR.CR = (u32)reg_value; + if (reg == "FPSCR") FPSCR.FPSCR = (u32)reg_value; + return true; + } + return false; + } + virtual void AddArgv(const wxString& arg); public: diff --git a/rpcs3/Emu/Cell/SPUInterpreter.h b/rpcs3/Emu/Cell/SPUInterpreter.h index d34c42512f..2097e6fe9b 100644 --- a/rpcs3/Emu/Cell/SPUInterpreter.h +++ b/rpcs3/Emu/Cell/SPUInterpreter.h @@ -674,23 +674,36 @@ private: } void FCGT(u32 rt, u32 ra, u32 rb) { - UNIMPLEMENTED(); + CPU.GPR[rt]._u32[0] = CPU.GPR[ra]._f[0] > CPU.GPR[rb]._f[0] ? 0xffffffff : 0; + CPU.GPR[rt]._u32[1] = CPU.GPR[ra]._f[1] > CPU.GPR[rb]._f[1] ? 0xffffffff : 0; + CPU.GPR[rt]._u32[2] = CPU.GPR[ra]._f[2] > CPU.GPR[rb]._f[2] ? 0xffffffff : 0; + CPU.GPR[rt]._u32[3] = CPU.GPR[ra]._f[3] > CPU.GPR[rb]._f[3] ? 0xffffffff : 0; } void DFCGT(u32 rt, u32 ra, u32 rb) { - UNIMPLEMENTED(); + CPU.GPR[rt]._u64[0] = CPU.GPR[ra]._d[0] > CPU.GPR[rb]._d[0] ? 0xffffffffffffffff : 0; + CPU.GPR[rt]._u64[1] = CPU.GPR[ra]._d[1] > CPU.GPR[rb]._d[1] ? 0xffffffffffffffff : 0; } void FA(u32 rt, u32 ra, u32 rb) { - UNIMPLEMENTED(); + CPU.GPR[rt]._f[0] = CPU.GPR[ra]._f[0] + CPU.GPR[rb]._f[0]; + CPU.GPR[rt]._f[1] = CPU.GPR[ra]._f[1] + CPU.GPR[rb]._f[1]; + CPU.GPR[rt]._f[2] = CPU.GPR[ra]._f[2] + CPU.GPR[rb]._f[2]; + CPU.GPR[rt]._f[3] = CPU.GPR[ra]._f[3] + CPU.GPR[rb]._f[3]; } void FS(u32 rt, u32 ra, u32 rb) { - UNIMPLEMENTED(); + CPU.GPR[rt]._f[0] = CPU.GPR[ra]._f[0] - CPU.GPR[rb]._f[0]; + CPU.GPR[rt]._f[1] = CPU.GPR[ra]._f[1] - CPU.GPR[rb]._f[1]; + CPU.GPR[rt]._f[2] = CPU.GPR[ra]._f[2] - CPU.GPR[rb]._f[2]; + CPU.GPR[rt]._f[3] = CPU.GPR[ra]._f[3] - CPU.GPR[rb]._f[3]; } void FM(u32 rt, u32 ra, u32 rb) { - UNIMPLEMENTED(); + CPU.GPR[rt]._f[0] = CPU.GPR[ra]._f[0] * CPU.GPR[rb]._f[0]; + CPU.GPR[rt]._f[1] = CPU.GPR[ra]._f[1] * CPU.GPR[rb]._f[1]; + CPU.GPR[rt]._f[2] = CPU.GPR[ra]._f[2] * CPU.GPR[rb]._f[2]; + CPU.GPR[rt]._f[3] = CPU.GPR[ra]._f[3] * CPU.GPR[rb]._f[3]; } void CLGTH(u32 rt, u32 ra, u32 rb) { @@ -704,23 +717,30 @@ private: } void FCMGT(u32 rt, u32 ra, u32 rb) { - UNIMPLEMENTED(); + CPU.GPR[rt]._u32[0] = fabs(CPU.GPR[ra]._f[0]) > fabs(CPU.GPR[rb]._f[0]) ? 0xffffffff : 0; + CPU.GPR[rt]._u32[1] = fabs(CPU.GPR[ra]._f[1]) > fabs(CPU.GPR[rb]._f[1]) ? 0xffffffff : 0; + CPU.GPR[rt]._u32[2] = fabs(CPU.GPR[ra]._f[2]) > fabs(CPU.GPR[rb]._f[2]) ? 0xffffffff : 0; + CPU.GPR[rt]._u32[3] = fabs(CPU.GPR[ra]._f[3]) > fabs(CPU.GPR[rb]._f[3]) ? 0xffffffff : 0; } void DFCMGT(u32 rt, u32 ra, u32 rb) { - UNIMPLEMENTED(); + CPU.GPR[rt]._u64[0] = fabs(CPU.GPR[ra]._d[0]) > fabs(CPU.GPR[rb]._d[0]) ? 0xffffffffffffffff : 0; + CPU.GPR[rt]._u64[1] = fabs(CPU.GPR[ra]._d[1]) > fabs(CPU.GPR[rb]._d[1]) ? 0xffffffffffffffff : 0; } void DFA(u32 rt, u32 ra, u32 rb) { - UNIMPLEMENTED(); + CPU.GPR[rt]._d[0] = CPU.GPR[ra]._d[0] + CPU.GPR[rb]._d[0]; + CPU.GPR[rt]._d[1] = CPU.GPR[ra]._d[1] + CPU.GPR[rb]._d[1]; } void DFS(u32 rt, u32 ra, u32 rb) { - UNIMPLEMENTED(); + CPU.GPR[rt]._d[0] = CPU.GPR[ra]._d[0] - CPU.GPR[rb]._d[0]; + CPU.GPR[rt]._d[1] = CPU.GPR[ra]._d[1] - CPU.GPR[rb]._d[1]; } void DFM(u32 rt, u32 ra, u32 rb) { - UNIMPLEMENTED(); + CPU.GPR[rt]._d[0] = CPU.GPR[ra]._d[0] * CPU.GPR[rb]._d[0]; + CPU.GPR[rt]._d[1] = CPU.GPR[ra]._d[1] * CPU.GPR[rb]._d[1]; } void CLGTB(u32 rt, u32 ra, u32 rb) { @@ -733,19 +753,23 @@ private: } void DFMA(u32 rt, u32 ra, u32 rb) { - UNIMPLEMENTED(); + CPU.GPR[rt]._d[0] += CPU.GPR[ra]._d[0] * CPU.GPR[rb]._d[0]; + CPU.GPR[rt]._d[1] += CPU.GPR[ra]._d[1] * CPU.GPR[rb]._d[1]; } void DFMS(u32 rt, u32 ra, u32 rb) { - UNIMPLEMENTED(); + CPU.GPR[rt]._d[0] = CPU.GPR[ra]._d[0] * CPU.GPR[rb]._d[0] - CPU.GPR[rt]._d[0]; + CPU.GPR[rt]._d[1] = CPU.GPR[ra]._d[1] * CPU.GPR[rb]._d[1] - CPU.GPR[rt]._d[1]; } void DFNMS(u32 rt, u32 ra, u32 rb) { - UNIMPLEMENTED(); + CPU.GPR[rt]._d[0] -= CPU.GPR[ra]._d[0] * CPU.GPR[rb]._d[0]; + CPU.GPR[rt]._d[1] -= CPU.GPR[ra]._d[1] * CPU.GPR[rb]._d[1]; } void DFNMA(u32 rt, u32 ra, u32 rb) { - UNIMPLEMENTED(); + CPU.GPR[rt]._d[0] = - CPU.GPR[ra]._d[0] * CPU.GPR[rb]._d[0] - CPU.GPR[rt]._d[0] ; + CPU.GPR[rt]._d[1] = - CPU.GPR[ra]._d[1] * CPU.GPR[rb]._d[1] - CPU.GPR[rt]._d[1] ; } void CEQ(u32 rt, u32 ra, u32 rb) { @@ -798,11 +822,15 @@ private: } void FESD(u32 rt, u32 ra) { - UNIMPLEMENTED(); + CPU.GPR[rt]._d[0] = (double)CPU.GPR[ra]._f[0]; + CPU.GPR[rt]._d[1] = (double)CPU.GPR[ra]._f[2]; } void FRDS(u32 rt, u32 ra) { - UNIMPLEMENTED(); + CPU.GPR[rt]._f[0] = (float)CPU.GPR[ra]._d[0]; + CPU.GPR[rt]._f[1] = 0x00000000; + CPU.GPR[rt]._f[2] = (float)CPU.GPR[ra]._d[1]; + CPU.GPR[rt]._f[3] = 0x00000000; } void FSCRWR(u32 rt, u32 ra) { @@ -814,11 +842,15 @@ private: } void FCEQ(u32 rt, u32 ra, u32 rb) { - UNIMPLEMENTED(); + CPU.GPR[rt]._u32[0] = CPU.GPR[ra]._f[0] == CPU.GPR[rb]._f[0] ? 0xffffffff : 0; + CPU.GPR[rt]._u32[1] = CPU.GPR[ra]._f[1] == CPU.GPR[rb]._f[1] ? 0xffffffff : 0; + CPU.GPR[rt]._u32[2] = CPU.GPR[ra]._f[2] == CPU.GPR[rb]._f[2] ? 0xffffffff : 0; + CPU.GPR[rt]._u32[3] = CPU.GPR[ra]._f[3] == CPU.GPR[rb]._f[3] ? 0xffffffff : 0; } void DFCEQ(u32 rt, u32 ra, u32 rb) { - UNIMPLEMENTED(); + CPU.GPR[rt]._u64[0] = CPU.GPR[ra]._d[0] == CPU.GPR[rb]._d[0] ? 0xffffffffffffffff : 0; + CPU.GPR[rt]._u64[1] = CPU.GPR[ra]._d[1] == CPU.GPR[rb]._d[1] ? 0xffffffffffffffff : 0; } void MPY(u32 rt, u32 ra, u32 rb) { @@ -847,11 +879,15 @@ private: } void FCMEQ(u32 rt, u32 ra, u32 rb) { - UNIMPLEMENTED(); + CPU.GPR[rt]._u32[0] = fabs(CPU.GPR[ra]._f[0]) == fabs(CPU.GPR[rb]._f[0]) ? 0xffffffff : 0; + CPU.GPR[rt]._u32[1] = fabs(CPU.GPR[ra]._f[1]) == fabs(CPU.GPR[rb]._f[1]) ? 0xffffffff : 0; + CPU.GPR[rt]._u32[2] = fabs(CPU.GPR[ra]._f[2]) == fabs(CPU.GPR[rb]._f[2]) ? 0xffffffff : 0; + CPU.GPR[rt]._u32[3] = fabs(CPU.GPR[ra]._f[3]) == fabs(CPU.GPR[rb]._f[3]) ? 0xffffffff : 0; } void DFCMEQ(u32 rt, u32 ra, u32 rb) { - UNIMPLEMENTED(); + CPU.GPR[rt]._u64[0] = fabs(CPU.GPR[ra]._d[0]) == fabs(CPU.GPR[rb]._d[0]) ? 0xffffffffffffffff : 0; + CPU.GPR[rt]._u64[1] = fabs(CPU.GPR[ra]._d[1]) == fabs(CPU.GPR[rb]._d[1]) ? 0xffffffffffffffff : 0; } void MPYU(u32 rt, u32 ra, u32 rb) { @@ -1177,15 +1213,24 @@ private: } void FNMS(u32 rt, u32 ra, u32 rb, u32 rc) { - UNIMPLEMENTED(); + CPU.GPR[rt]._f[0] -= CPU.GPR[ra]._f[0] * CPU.GPR[rb]._f[0]; + CPU.GPR[rt]._f[1] -= CPU.GPR[ra]._f[1] * CPU.GPR[rb]._f[1]; + CPU.GPR[rt]._f[2] -= CPU.GPR[ra]._f[2] * CPU.GPR[rb]._f[2]; + CPU.GPR[rt]._f[3] -= CPU.GPR[ra]._f[3] * CPU.GPR[rb]._f[3]; } void FMA(u32 rc, u32 ra, u32 rb, u32 rt) { - UNIMPLEMENTED(); + CPU.GPR[rt]._f[0] += CPU.GPR[ra]._f[0] * CPU.GPR[rb]._f[0]; + CPU.GPR[rt]._f[1] += CPU.GPR[ra]._f[1] * CPU.GPR[rb]._f[1]; + CPU.GPR[rt]._f[2] += CPU.GPR[ra]._f[2] * CPU.GPR[rb]._f[2]; + CPU.GPR[rt]._f[3] += CPU.GPR[ra]._f[3] * CPU.GPR[rb]._f[3]; } void FMS(u32 rc, u32 ra, u32 rb, u32 rt) { - UNIMPLEMENTED(); + CPU.GPR[rt]._f[0] = CPU.GPR[ra]._f[0] * CPU.GPR[rb]._f[0] - CPU.GPR[rt]._f[0]; + CPU.GPR[rt]._f[1] = CPU.GPR[ra]._f[1] * CPU.GPR[rb]._f[1] - CPU.GPR[rt]._f[1]; + CPU.GPR[rt]._f[2] = CPU.GPR[ra]._f[2] * CPU.GPR[rb]._f[2] - CPU.GPR[rt]._f[2]; + CPU.GPR[rt]._f[3] = CPU.GPR[ra]._f[3] * CPU.GPR[rb]._f[3] - CPU.GPR[rt]._f[3]; } void UNK(u32 code, u32 opcode, u32 gcode) diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index 26775a6ec9..77a260989b 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -110,6 +110,8 @@ union SPU_GPR_hdr s16 _i16[8]; u8 _u8[16]; s8 _i8[16]; + double _d[2]; + float _f[4]; SPU_GPR_hdr() {} @@ -249,6 +251,37 @@ public: return ret; } + virtual wxString ReadRegString(wxString reg) + { + if (reg.Contains("[")) + { + long reg_index; + reg.AfterFirst('[').RemoveLast().ToLong(®_index); + if (reg.StartsWith("GPR")) return wxString::Format("%016llx%016llx", GPR[reg_index]._u64[1], GPR[reg_index]._u64[0]); + } + return wxEmptyString; + } + + bool WriteRegString(wxString reg, wxString value) { + while (value.Len() < 32) value = "0"+value; + if (reg.Contains("[")) + { + long reg_index; + reg.AfterFirst('[').RemoveLast().ToLong(®_index); + if (reg.StartsWith("GPR")) + { + unsigned long long reg_value0; + unsigned long long reg_value1; + if (!value.SubString(16,31).ToULongLong(®_value0, 16)) return false; + if (!value.SubString(0,15).ToULongLong(®_value1, 16)) return false; + GPR[reg_index]._u64[0] = (u64)reg_value0; + GPR[reg_index]._u64[1] = (u64)reg_value1; + return true; + } + } + return false; + } + public: virtual void InitRegs(); virtual u64 GetFreeStackSize() const; diff --git a/rpcs3/Emu/SysCalls/Modules/cellGifDec.cpp b/rpcs3/Emu/SysCalls/Modules/cellGifDec.cpp index e35da3dd45..b8175f944c 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGifDec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellGifDec.cpp @@ -193,14 +193,9 @@ int cellGifDecDecodeData(u32 mainHandle, u32 subHandle, u32 data_addr, u32 dataC //Decode GIF file. (TODO: Is there any faster alternative? Can we do it without external libraries?) int width, height, actual_components; - unsigned char *gif = new unsigned char [fileSize]; - for(u32 i = 0; i < fileSize; i++){ - gif[i] = Memory.Read8(buffer+i); - } + unsigned char *gif = (unsigned char*)Memory.VirtualToRealAddr(buffer); + unsigned char *image = stbi_load_from_memory(gif, fileSize, &width, &height, &actual_components, 4); Memory.Free(buffer); - - unsigned char *image = stbi_load_from_memory((const unsigned char*)gif, fileSize, &width, &height, &actual_components, 4); - delete[] gif; if (!image) return CELL_GIFDEC_ERROR_STREAM_FORMAT; u32 image_size = width * height * 4; diff --git a/rpcs3/Emu/SysCalls/Modules/cellJpgDec.cpp b/rpcs3/Emu/SysCalls/Modules/cellJpgDec.cpp index c9cbaba239..8f0f82c40e 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellJpgDec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellJpgDec.cpp @@ -213,14 +213,9 @@ int cellJpgDecDecodeData(u32 mainHandle, u32 subHandle, u32 data_addr, u32 dataC //Decode JPG file. (TODO: Is there any faster alternative? Can we do it without external libraries?) int width, height, actual_components; - unsigned char *jpg = new unsigned char [fileSize]; - for(u32 i = 0; i < fileSize; i++){ - jpg[i] = Memory.Read8(buffer+i); - } + unsigned char *jpg = (unsigned char*)Memory.VirtualToRealAddr(buffer); + unsigned char *image = stbi_load_from_memory(jpg, fileSize, &width, &height, &actual_components, 4); Memory.Free(buffer); - - unsigned char *image = stbi_load_from_memory((const unsigned char*)jpg, fileSize, &width, &height, &actual_components, 4); - delete[] jpg; if (!image) return CELL_JPGDEC_ERROR_STREAM_FORMAT; u32 image_size = width * height * 4; diff --git a/rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp b/rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp index 1a93351259..783ba3738e 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp @@ -198,14 +198,9 @@ int cellPngDecDecodeData(u32 mainHandle, u32 subHandle, u32 data_addr, u32 dataC //Decode PNG file. (TODO: Is there any faster alternative? Can we do it without external libraries?) int width, height, actual_components; - unsigned char *png = new unsigned char [fileSize]; - for(u32 i = 0; i < fileSize; i++){ - png[i] = Memory.Read8(buffer+i); - } + unsigned char *png = (unsigned char*)Memory.VirtualToRealAddr(buffer); + unsigned char *image = stbi_load_from_memory(png, fileSize, &width, &height, &actual_components, 4); Memory.Free(buffer); - - unsigned char *image = stbi_load_from_memory((const unsigned char*)png, fileSize, &width, &height, &actual_components, 4); - delete[] png; if (!image) return CELL_PNGDEC_ERROR_STREAM_FORMAT; u32 image_size = width * height * 4; diff --git a/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp b/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp index c4d4736cff..79cf6f1cba 100644 --- a/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp @@ -21,4 +21,7 @@ void sys_fs_init() sys_fs.AddFunc(0x2796fdf3, cellFsRmdir); sys_fs.AddFunc(0x7f4677a8, cellFsUnlink); sys_fs.AddFunc(0xa397d042, cellFsLseek); + sys_fs.AddFunc(0x0e2939e5, cellFsFtruncate); + sys_fs.AddFunc(0xc9dc3ac5, cellFsTruncate); + sys_fs.AddFunc(0xcb588dba, cellFsFGetBlockSize); } diff --git a/rpcs3/Emu/SysCalls/SysCalls.h b/rpcs3/Emu/SysCalls/SysCalls.h index 159f168d57..c54bfc70cc 100644 --- a/rpcs3/Emu/SysCalls/SysCalls.h +++ b/rpcs3/Emu/SysCalls/SysCalls.h @@ -189,6 +189,9 @@ extern int cellFsRename(u32 from_addr, u32 to_addr); extern int cellFsRmdir(u32 path_addr); extern int cellFsUnlink(u32 path_addr); extern int cellFsLseek(u32 fd, s64 offset, u32 whence, u32 pos_addr); +extern int cellFsFtruncate(u32 fd, u64 size); +extern int cellFsTruncate(u32 path_addr, u64 size); +extern int cellFsFGetBlockSize(u32 fd, u32 sector_size_addr, u32 block_size_addr); //cellVideo extern int cellVideoOutGetState(u32 videoOut, u32 deviceIndex, u32 state_addr); diff --git a/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp b/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp index a281671f61..6c409df644 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp @@ -247,6 +247,16 @@ int cellFsStat(const u32 path_addr, const u32 sb_addr) const wxString& path = Memory.ReadString(path_addr); sys_fs.Log("cellFsFstat(path: %s, sb_addr: 0x%x)", path, sb_addr); + // Check if path is a mount point. (TODO: Add information in sb_addr) + for(u32 i=0; iIsOpened()) { @@ -322,7 +332,9 @@ int cellFsFstat(u32 fd, u32 sb_addr) int cellFsMkdir(u32 path_addr, u32 mode) { - const wxString& path = Memory.ReadString(path_addr); + const wxString& ps3_path = Memory.ReadString(path_addr); + wxString path; + Emu.GetVFS().GetDevice(ps3_path, path); sys_fs.Log("cellFsMkdir(path: %s, mode: 0x%x)", path, mode); if(wxDirExists(path)) return CELL_EEXIST; if(!wxMkdir(path)) return CELL_EBUSY; @@ -331,27 +343,36 @@ int cellFsMkdir(u32 path_addr, u32 mode) int cellFsRename(u32 from_addr, u32 to_addr) { - const wxString& from = Memory.ReadString(from_addr); - const wxString& to = Memory.ReadString(to_addr); + const wxString& ps3_from = Memory.ReadString(from_addr); + const wxString& ps3_to = Memory.ReadString(to_addr); + wxString from; + wxString to; + Emu.GetVFS().GetDevice(ps3_from, from); + Emu.GetVFS().GetDevice(ps3_to, to); + sys_fs.Log("cellFsRename(from: %s, to: %s)", from, to); if(!wxFileExists(from)) return CELL_ENOENT; if(wxFileExists(to)) return CELL_EEXIST; - if(!wxRenameFile(from, to)) return CELL_EBUSY; + if(!wxRenameFile(from, to)) return CELL_EBUSY; // (TODO: RenameFile(a,b) = CopyFile(a,b) + RemoveFile(a), therefore file "a" will not be removed if it is opened) return CELL_OK; } int cellFsRmdir(u32 path_addr) { - const wxString& path = Memory.ReadString(path_addr); + const wxString& ps3_path = Memory.ReadString(path_addr); + wxString path; + Emu.GetVFS().GetDevice(ps3_path, path); sys_fs.Log("cellFsRmdir(path: %s)", path); if(!wxDirExists(path)) return CELL_ENOENT; - if(!wxRmdir(path)) return CELL_EBUSY; + if(!wxRmdir(path)) return CELL_EBUSY; // (TODO: Under certain conditions it is not able to delete the folder) return CELL_OK; } int cellFsUnlink(u32 path_addr) { - const wxString& path = Memory.ReadString(path_addr); + const wxString& ps3_path = Memory.ReadString(path_addr); + wxString path; + Emu.GetVFS().GetDevice(ps3_path, path); sys_fs.Error("cellFsUnlink(path: %s)", path); return CELL_OK; } @@ -373,5 +394,86 @@ int cellFsLseek(u32 fd, s64 offset, u32 whence, u32 pos_addr) if(!sys_fs.CheckId(fd, id)) return CELL_ESRCH; vfsStream& file = *(vfsStream*)id.m_data; Memory.Write64(pos_addr, file.Seek(offset, seek_mode)); + return CELL_OK; +} + +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; + u64 initialSize = file.GetSize(); + + if (initialSize < size) // Is there any better way to fill the remaining bytes with 0, without allocating huge buffers in memory, or writing such a spaghetti code? + { + u64 last_pos = file.Tell(); + file.Seek(0, vfsSeekEnd); + char* nullblock = (char*)calloc(4096, sizeof(char)); + for(u64 i = (size-initialSize)/4096; i > 0; i--){ + file.Write(nullblock, 4096); + } + free(nullblock); + char nullbyte = 0; + for(u64 i = (size-initialSize)%4096; i > 0; i--){ + file.Write(&nullbyte, 1); + } + file.Seek(last_pos, vfsSeekSet); + } + + if (initialSize > size) + { + // (TODO) + } + + return CELL_OK; +} + +int cellFsTruncate(u32 path_addr, u64 size) +{ + const wxString& path = Memory.ReadString(path_addr); + sys_fs.Log("cellFsTruncate(path_addr: %s, size: %lld)", path, size); + + vfsStream* f = Emu.GetVFS().Open(path, vfsRead); + if(!f || !f->IsOpened()) + { + sys_fs.Warning("cellFsTruncate: '%s' not found.", path); + Emu.GetVFS().Close(f); + return CELL_ENOENT; + } + u64 initialSize = f->GetSize(); + + if (initialSize < size) // Is there any better way to fill the remaining bytes with 0, without allocating huge buffers in memory, or writing such a spaghetti code? + { + u64 last_pos = f->Tell(); + f->Seek(0, vfsSeekEnd); + char* nullblock = (char*)calloc(4096, sizeof(char)); + for(u64 i = (size-initialSize)/4096; i > 0; i--){ + f->Write(nullblock, 4096); + } + free(nullblock); + char nullbyte = 0; + for(u64 i = (size-initialSize)%4096; i > 0; i--){ + f->Write(&nullbyte, 1); + } + f->Seek(last_pos, vfsSeekSet); + } + + if (initialSize > size) + { + // (TODO) + } + + Emu.GetVFS().Close(f); + return CELL_OK; +} + +int cellFsFGetBlockSize(u32 fd, u32 sector_size_addr, u32 block_size_addr) +{ + sys_fs.Log("cellFsFGetBlockSize(fd: %d, sector_size_addr: 0x%x, block_size_addr: 0x%x)", fd, sector_size_addr, block_size_addr); + + Memory.Write64(sector_size_addr, 4096); // ? + Memory.Write64(block_size_addr, 4096); // ? + return CELL_OK; } \ No newline at end of file diff --git a/rpcs3/Gui/InstructionEditor.cpp b/rpcs3/Gui/InstructionEditor.cpp new file mode 100644 index 0000000000..cb5491e368 --- /dev/null +++ b/rpcs3/Gui/InstructionEditor.cpp @@ -0,0 +1,103 @@ +class InstructionEditorDialog + : public wxDialog +{ + u64 pc; + PPC_DisAsm* disasm; + PPC_Decoder* decoder; + wxTextCtrl* t2_instr; + wxStaticText* t3_preview; + +public: + PPCThread* CPU; + +public: + InstructionEditorDialog(wxPanel *parent, u64 _pc, PPCThread* _CPU, PPC_Decoder* _decoder, PPC_DisAsm* _disasm); + + void updatePreview(wxCommandEvent& event); +}; + +InstructionEditorDialog::InstructionEditorDialog(wxPanel *parent, u64 _pc, PPCThread* _CPU, PPC_Decoder* _decoder, PPC_DisAsm* _disasm) + : wxDialog(parent, wxID_ANY, "Edit instruction", wxDefaultPosition) + , pc(_pc) + , CPU(_CPU) + , decoder(_decoder) + , disasm(_disasm) +{ + wxBoxSizer* s_panel_margin_x(new wxBoxSizer(wxHORIZONTAL)); + wxBoxSizer* s_panel_margin_y(new wxBoxSizer(wxVERTICAL)); + + wxBoxSizer* s_panel(new wxBoxSizer(wxVERTICAL)); + wxBoxSizer* s_t1_panel(new wxBoxSizer(wxHORIZONTAL)); + wxBoxSizer* s_t2_panel(new wxBoxSizer(wxHORIZONTAL)); + wxBoxSizer* s_t3_panel(new wxBoxSizer(wxHORIZONTAL)); + wxBoxSizer* s_b_panel(new wxBoxSizer(wxHORIZONTAL)); + + wxStaticText* t1_text = new wxStaticText(this, wxID_ANY, "Address: "); + wxStaticText* t1_addr = new wxStaticText(this, wxID_ANY, wxString::Format("%08x",pc)); + wxStaticText* t2_text = new wxStaticText(this, wxID_ANY, "Instruction:"); + t2_instr = new wxTextCtrl(this, wxID_ANY); + wxStaticText* t3_text = new wxStaticText(this, wxID_ANY, "Preview: "); + t3_preview = new wxStaticText(this, wxID_ANY, ""); + + s_t1_panel->Add(t1_text); + s_t1_panel->AddSpacer(8); + s_t1_panel->Add(t1_addr); + + s_t2_panel->Add(t2_text); + s_t2_panel->AddSpacer(8); + s_t2_panel->Add(t2_instr); + + s_t3_panel->Add(t3_text); + s_t3_panel->AddSpacer(8); + s_t3_panel->Add(t3_preview); + + s_b_panel->Add(new wxButton(this, wxID_OK), wxLEFT, 0, 5); + s_b_panel->AddSpacer(5); + s_b_panel->Add(new wxButton(this, wxID_CANCEL), wxRIGHT, 0, 5); + + s_panel->Add(s_t1_panel); + s_panel->AddSpacer(8); + s_panel->Add(s_t3_panel); + s_panel->AddSpacer(8); + s_panel->Add(s_t2_panel); + s_panel->AddSpacer(16); + s_panel->Add(s_b_panel); + + s_panel_margin_y->AddSpacer(12); + s_panel_margin_y->Add(s_panel); + s_panel_margin_y->AddSpacer(12); + s_panel_margin_x->AddSpacer(12); + s_panel_margin_x->Add(s_panel_margin_y); + s_panel_margin_x->AddSpacer(12); + + this->Connect(wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(InstructionEditorDialog::updatePreview)); + t2_instr->SetValue(wxString::Format("%08x", Memory.Read32(CPU->GetOffset() + pc))); + + this->SetSizerAndFit(s_panel_margin_x); + + if(this->ShowModal() == wxID_OK) + { + unsigned long opcode; + if (!t2_instr->GetValue().ToULong(&opcode, 16)) + wxMessageBox("This instruction could not be parsed.\nNo changes were made.","Error"); + else + Memory.Write32(CPU->GetOffset() + pc, (u32)opcode); + } +} + +void InstructionEditorDialog::updatePreview(wxCommandEvent& event) +{ + unsigned long opcode; + if (t2_instr->GetValue().ToULong(&opcode, 16)) + { + decoder->Decode((u32)opcode); + wxString preview = disasm->last_opcode; + while (preview[0] != ':') preview.Remove(0,1); + preview.Remove(0,1); + t3_preview->SetLabel(preview); + } + else + { + t3_preview->SetLabel("Could not parse instruction."); + } +} \ No newline at end of file diff --git a/rpcs3/Gui/InterpreterDisAsm.cpp b/rpcs3/Gui/InterpreterDisAsm.cpp index 346a03810c..cc671c6e9d 100644 --- a/rpcs3/Gui/InterpreterDisAsm.cpp +++ b/rpcs3/Gui/InterpreterDisAsm.cpp @@ -1,6 +1,9 @@ #include "stdafx.h" #include "InterpreterDisAsm.h" +#include "InstructionEditor.cpp" +#include "RegisterEditor.cpp" + //static const int show_lines = 30; u64 InterpreterDisAsmFrame::CentrePc(const u64 pc) const @@ -67,6 +70,7 @@ InterpreterDisAsmFrame::InterpreterDisAsmFrame(wxWindow* parent) Connect(m_btn_step->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(InterpreterDisAsmFrame::DoStep)); Connect(m_btn_run->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(InterpreterDisAsmFrame::DoRun)); Connect(m_btn_pause->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(InterpreterDisAsmFrame::DoPause)); + Connect(m_list->GetId(), wxEVT_COMMAND_LIST_KEY_DOWN, wxListEventHandler(InterpreterDisAsmFrame::InstrKey)); Connect(m_list->GetId(), wxEVT_COMMAND_LIST_ITEM_ACTIVATED, wxListEventHandler(InterpreterDisAsmFrame::DClick)); Connect(m_choice_units->GetId(),wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler(InterpreterDisAsmFrame::OnSelectUnit)); Connect(wxEVT_SIZE, wxSizeEventHandler(InterpreterDisAsmFrame::OnResize)); @@ -442,6 +446,27 @@ void InterpreterDisAsmFrame::DoStep(wxCommandEvent& WXUNUSED(event)) ThreadBase::Start(); } +void InterpreterDisAsmFrame::InstrKey(wxListEvent& event) +{ + long i = m_list->GetFirstSelected(); + if(i < 0) return; + + const u64 start_pc = PC - m_item_count*4; + const u64 pc = start_pc + i*4; + + switch(event.GetKeyCode()) + { + case 'E': + InstructionEditorDialog(this, pc, CPU, decoder, disasm); + DoUpdate(); + return; + case 'R': + RegisterEditorDialog(this, pc, CPU, decoder, disasm); + DoUpdate(); + return; + } +} + void InterpreterDisAsmFrame::DClick(wxListEvent& event) { long i = m_list->GetFirstSelected(); diff --git a/rpcs3/Gui/InterpreterDisAsm.h b/rpcs3/Gui/InterpreterDisAsm.h index b86db3ab2a..f14068db35 100644 --- a/rpcs3/Gui/InterpreterDisAsm.h +++ b/rpcs3/Gui/InterpreterDisAsm.h @@ -46,6 +46,7 @@ public: void DoRun(wxCommandEvent& event); void DoPause(wxCommandEvent& event); void DoStep(wxCommandEvent& event); + void InstrKey(wxListEvent& event); void DClick(wxListEvent& event); void MouseWheel(wxMouseEvent& event); diff --git a/rpcs3/Gui/RegisterEditor.cpp b/rpcs3/Gui/RegisterEditor.cpp new file mode 100644 index 0000000000..da190f2e11 --- /dev/null +++ b/rpcs3/Gui/RegisterEditor.cpp @@ -0,0 +1,105 @@ +class RegisterEditorDialog + : public wxDialog +{ + u64 pc; + PPC_DisAsm* disasm; + PPC_Decoder* decoder; + wxComboBox* t1_register; + wxTextCtrl* t2_value; + wxStaticText* t3_preview; + +public: + PPCThread* CPU; + +public: + RegisterEditorDialog(wxPanel *parent, u64 _pc, PPCThread* _CPU, PPC_Decoder* _decoder, PPC_DisAsm* _disasm); + + void updateRegister(wxCommandEvent& event); + void updatePreview(wxCommandEvent& event); +}; + +RegisterEditorDialog::RegisterEditorDialog(wxPanel *parent, u64 _pc, PPCThread* _CPU, PPC_Decoder* _decoder, PPC_DisAsm* _disasm) + : wxDialog(parent, wxID_ANY, "Edit registers", wxDefaultPosition) + , pc(_pc) + , CPU(_CPU) + , decoder(_decoder) + , disasm(_disasm) +{ + wxBoxSizer* s_panel_margin_x(new wxBoxSizer(wxHORIZONTAL)); + wxBoxSizer* s_panel_margin_y(new wxBoxSizer(wxVERTICAL)); + + wxBoxSizer* s_panel(new wxBoxSizer(wxVERTICAL)); + wxBoxSizer* s_t1_panel(new wxBoxSizer(wxHORIZONTAL)); + wxBoxSizer* s_t2_panel(new wxBoxSizer(wxHORIZONTAL)); + wxBoxSizer* s_t3_panel(new wxBoxSizer(wxHORIZONTAL)); + wxBoxSizer* s_b_panel(new wxBoxSizer(wxHORIZONTAL)); + + wxStaticText* t1_text = new wxStaticText(this, wxID_ANY, "Register: "); + t1_register = new wxComboBox(this, wxID_ANY, wxEmptyString); + wxStaticText* t2_text = new wxStaticText(this, wxID_ANY, "Value (Hex):"); + t2_value = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(200,-1)); + + s_t1_panel->Add(t1_text); + s_t1_panel->AddSpacer(8); + s_t1_panel->Add(t1_register); + + s_t2_panel->Add(t2_text); + s_t2_panel->AddSpacer(8); + s_t2_panel->Add(t2_value); + + s_b_panel->Add(new wxButton(this, wxID_OK), wxLEFT, 0, 5); + s_b_panel->AddSpacer(5); + s_b_panel->Add(new wxButton(this, wxID_CANCEL), wxLEFT, 0, 5); + + s_panel->Add(s_t1_panel); + s_panel->AddSpacer(8); + s_panel->Add(s_t2_panel); + s_panel->AddSpacer(16); + s_panel->Add(s_b_panel); + + s_panel_margin_y->AddSpacer(12); + s_panel_margin_y->Add(s_panel); + s_panel_margin_y->AddSpacer(12); + s_panel_margin_x->AddSpacer(12); + s_panel_margin_x->Add(s_panel_margin_y); + s_panel_margin_x->AddSpacer(12); + + this->Connect(wxEVT_COMMAND_COMBOBOX_SELECTED, wxCommandEventHandler(RegisterEditorDialog::updateRegister)); + + if (CPU->GetType() == PPC_THREAD_PPU) + { + for (int i=0; i<32; i++) t1_register->Append(wxString::Format("GPR[%d]",i)); + for (int i=0; i<32; i++) t1_register->Append(wxString::Format("FPR[%d]",i)); + for (int i=0; i<32; i++) t1_register->Append(wxString::Format("VPR[%d]",i)); + t1_register->Append("CR"); + t1_register->Append("LR"); + t1_register->Append("CTR"); + t1_register->Append("XER"); + t1_register->Append("FPSCR"); + } + if (CPU->GetType() == PPC_THREAD_SPU) + { + for (int i=0; i<128; i++) t1_register->Append(wxString::Format("GPR[%d]",i)); + } + if (CPU->GetType() == PPC_THREAD_RAW_SPU) + { + wxMessageBox("RawSPU threads not yet supported.","Error"); + return; + } + + this->SetSizerAndFit(s_panel_margin_x); + + if(this->ShowModal() == wxID_OK) + { + wxString reg = t1_register->GetStringSelection(); + wxString value = t2_value->GetValue(); + if (!CPU->WriteRegString(reg,value)) + wxMessageBox("This value could not be converted.\nNo changes were made.","Error"); + } +} + +void RegisterEditorDialog::updateRegister(wxCommandEvent& event) +{ + wxString reg = t1_register->GetStringSelection(); + t2_value->SetValue(CPU->ReadRegString(reg)); +} \ No newline at end of file