int sys_event_flag_trywait(u32 eflag_id, u64 bitptn, u32 mode, mem64_t result) { sys_event_flag.Warning("sys_event_flag_trywait(eflag_id=%d, bitptn=0x%llx, mode=0x%x, result_addr=0x%x)", eflag_id, bitptn, mode, result.GetAddr()); if (result.IsGood()) result = 0; switch (mode & 0xf) { case SYS_EVENT_FLAG_WAIT_AND: break; case SYS_EVENT_FLAG_WAIT_OR: break; default: return CELL_EINVAL; } switch (mode & ~0xf) { case 0: break; // ??? case SYS_EVENT_FLAG_WAIT_CLEAR: break; case SYS_EVENT_FLAG_WAIT_CLEAR_ALL: break; default: return CELL_EINVAL; } EventFlag* ef; if(!sys_event_flag.CheckId(eflag_id, ef)) return CELL_ESRCH; SMutexLocker lock(ef->m_mutex); u64 flags = ef->flags; if (((mode & SYS_EVENT_FLAG_WAIT_AND) && (flags & bitptn) == bitptn) || ((mode & SYS_EVENT_FLAG_WAIT_OR) && (flags & bitptn))) { if (mode & SYS_EVENT_FLAG_WAIT_CLEAR) { ef->flags &= ~bitptn; } else if (mode & SYS_EVENT_FLAG_WAIT_CLEAR_ALL) { ef->flags = 0; } if (result.IsGood()) { result = flags; return CELL_OK; } if (!result.GetAddr()) { return CELL_OK; } return CELL_EFAULT; } return CELL_EBUSY; }
int cellFsStRead(u32 fd, u32 buf_addr, u64 size, mem64_t rsize) { sys_fs.Warning("TODO: cellFsStRead(fd=%d, buf_addr=0x%x, size=0x%llx, rsize_addr = 0x%x)", fd, buf_addr, size, rsize.GetAddr()); vfsStream* file; if(!sys_fs.CheckId(fd, file)) return CELL_ESRCH; if (rsize.GetAddr() && !rsize.IsGood()) return CELL_EFAULT; m_fs_config.m_regid += size; rsize = m_fs_config.m_regid; return CELL_OK; }
int cellPamfGetHeaderSize2(mem_ptr_t<PamfHeader> pAddr, u64 fileSize, u32 attribute, mem64_t pSize) { cellPamf.Warning("cellPamfGetHeaderSize2(pAddr=0x%x, fileSize=%d, attribute=0x%x, pSize_addr=0x%x)", pAddr.GetAddr(), fileSize, attribute, pSize.GetAddr()); if (!pAddr.IsGood() || !pSize.IsGood()) return CELL_PAMF_ERROR_INVALID_ARG; //if ((u32)pAddr->magic != 0x464d4150) //return CELL_PAMF_ERROR_UNKNOWN_TYPE; const u64 offset = (u64)pAddr->data_offset << 11; pSize = offset; return CELL_OK; }
int sceNpTrophyGetRequiredDiskSpace(u32 context, u32 handle, mem64_t reqspace, u64 options) { sceNpTrophy.Warning("sceNpTrophyGetRequiredDiskSpace(context=%d, handle=%d, reqspace_addr=0x%x, options=0x%llx)", context, handle, reqspace.GetAddr(), options); if (!s_npTrophyInstance.m_bInitialized) return SCE_NP_TROPHY_ERROR_NOT_INITIALIZED; if (!reqspace.IsGood()) return SCE_NP_TROPHY_ERROR_INVALID_ARGUMENT; // TODO: There are other possible errors sceNpTrophyInternalContext& ctxt = s_npTrophyInstance.contexts[context]; reqspace = ctxt.trp_stream->GetSize(); // TODO: This is not accurate. It's just an approximation of the real value return CELL_OK; }
int cellFsReaddir(u32 fd, mem_ptr_t<CellFsDirent> dir, mem64_t nread) { sys_fs.Log("cellFsReaddir(fd=%d, dir_addr=0x%x, nread_addr=0x%x)", fd, dir.GetAddr(), nread.GetAddr()); vfsDirBase* directory; if(!sys_fs.CheckId(fd, directory)) return CELL_ESRCH; if(!dir.IsGood() || !nread.IsGood()) return CELL_EFAULT; const DirEntryInfo* info = directory->Read(); if(info) { nread = 1; Memory.WriteString(dir.GetAddr()+2, info->name.wx_str()); dir->d_namlen = info->name.Length(); dir->d_type = (info->flags & DirEntry_TypeFile) ? CELL_FS_TYPE_REGULAR : CELL_FS_TYPE_DIRECTORY; } else { nread = 0; } return CELL_OK; }
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()); vfsStream* file; if(!sys_fs.CheckId(fd, file)) return CELL_ESRCH; if (nread.GetAddr() && !nread.IsGood()) return CELL_EFAULT; u32 res = 0; u32 count = nbytes; if (nbytes != (u64)count) return CELL_ENOMEM; if (!Memory.IsGoodAddr(buf_addr)) return CELL_EFAULT; if (count) if (u32 frag = buf_addr & 4095) // memory page fragment { u32 req = min(count, 4096 - frag); u32 read = file->Read(Memory + buf_addr, req); buf_addr += req; res += read; count -= req; if (read < req) goto fin; } for (u32 pages = count / 4096; pages > 0; pages--) // full pages { if (!Memory.IsGoodAddr(buf_addr)) goto fin; // ??? (probably EFAULT) u32 read = file->Read(Memory + buf_addr, 4096); buf_addr += 4096; res += read; count -= 4096; if (read < 4096) goto fin; } if (count) // last fragment { if (!Memory.IsGoodAddr(buf_addr)) goto fin; res += file->Read(Memory + buf_addr, count); } fin: if (nread.GetAddr()) nread = res; // write value if not NULL return CELL_OK; }
int cellPamfGetStreamOffsetAndSize(mem_ptr_t<PamfHeader> pAddr, u64 fileSize, mem64_t pOffset, mem64_t pSize) { cellPamf.Warning("cellPamfGetStreamOffsetAndSize(pAddr=0x%x, fileSize=%d, pOffset_addr=0x%x, pSize_addr=0x%x)", pAddr.GetAddr(), fileSize, pOffset.GetAddr(), pSize.GetAddr()); if (!pAddr.IsGood() || !pOffset.IsGood() || !pSize.IsGood()) return CELL_PAMF_ERROR_INVALID_ARG; //if ((u32)pAddr->magic != 0x464d4150) //return CELL_PAMF_ERROR_UNKNOWN_TYPE; const u64 offset = (u64)pAddr->data_offset << 11; pOffset = offset; const u64 size = (u64)pAddr->data_size << 11; pSize = size; return CELL_OK; }
s32 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()); vfsStream* file; if(!sys_fs->CheckId(fd, file)) return CELL_ESRCH; if (nbytes != (u32)nbytes) return CELL_ENOMEM; // TODO: checks const u64 res = nbytes ? file->Write(Memory.GetMemFromAddr(buf_addr), nbytes) : 0; if (nwrite.GetAddr()) nwrite = res; // write value if not NULL return CELL_OK; }
//182 int sys_spu_thread_read_ls(u32 id, u32 address, mem64_t value, u32 type) { sc_spu.Log("sys_spu_thread_read_ls(id=%d, address=0x%x, value_addr=0x%x, type=0x%x)", id, address, value.GetAddr(), type); CPUThread* thr = Emu.GetCPU().GetThread(id); if(!thr || (thr->GetType() != CPU_THREAD_SPU && thr->GetType() != CPU_THREAD_RAW_SPU)) { return CELL_ESRCH; } if (!thr->IsRunning()) { return CELL_ESTAT; } if(!value.IsGood()) { return CELL_EFAULT; } if (!(*(SPUThread*)thr).IsGoodLSA(address) || (address % type)) // +check alignment { return CELL_EINVAL; } switch (type) { case 1: value = (*(SPUThread*)thr).ReadLS8(address); return CELL_OK; case 2: value = (*(SPUThread*)thr).ReadLS16(address); return CELL_OK; case 4: value = (*(SPUThread*)thr).ReadLS32(address); return CELL_OK; case 8: value = (*(SPUThread*)thr).ReadLS64(address); return CELL_OK; default: return CELL_EINVAL; } }
int cellFsReadWithOffset(u32 fd, u64 offset, u32 buf_addr, u64 buffer_size, mem64_t nread) { sys_fs.Warning("cellFsReadWithOffset(fd=%d, offset=0x%llx, buf_addr=0x%x, buffer_size=%lld nread=0x%llx)", fd, offset, buf_addr, buffer_size, nread.GetAddr()); int ret; MemoryAllocator<be_t<u64>> oldPos, newPos; ret = cellFsLseek(fd, 0, CELL_SEEK_CUR, oldPos.GetAddr()); // Save the current position if (ret) return ret; ret = cellFsLseek(fd, offset, CELL_SEEK_SET, newPos.GetAddr()); // Move to the specified offset if (ret) return ret; ret = cellFsRead(fd, buf_addr, buffer_size, nread.GetAddr()); // Read the file if (ret) return ret; ret = cellFsLseek(fd, Memory.Read64(oldPos.GetAddr()), CELL_SEEK_SET, newPos.GetAddr()); // Return to the old position if (ret) return ret; return CELL_OK; }
int cellFsGetFreeSize(u32 path_addr, mem32_t block_size, mem64_t block_count) { const wxString& ps3_path = Memory.ReadString(path_addr); sys_fs.Warning("cellFsGetFreeSize(path=\"%s\", block_size_addr=0x%x, block_count_addr=0x%x)", ps3_path.wx_str(), block_size.GetAddr(), block_count.GetAddr()); if (!Memory.IsGoodAddr(path_addr) || !block_size.IsGood() || !block_count.IsGood()) return CELL_EFAULT; if (ps3_path.empty()) return CELL_EINVAL; // TODO: Get real values. Currently, it always returns 40 GB of free space divided in 4 KB blocks block_size = 4096; // ? block_count = 10485760; // ? return CELL_OK; }
int cellFsStReadGetCurrentAddr(u32 fd, mem32_t addr_addr, mem64_t size) { sys_fs.Warning("TODO: cellFsStReadGetCurrentAddr(fd=%d, addr_addr=0x%x, size_addr = 0x%x)", fd, addr_addr.GetAddr(), size.GetAddr()); vfsStream* file; if(!sys_fs.CheckId(fd, file)) return CELL_ESRCH; if (!addr_addr.IsGood() && !size.IsGood()) return CELL_EFAULT; return CELL_OK; }
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()); vfsStream* file; if(!sys_fs.CheckId(fd, file)) return CELL_ESRCH; if(Memory.IsGoodAddr(buf_addr) && !Memory.IsGoodAddr(buf_addr, nbytes)) { MemoryBlock& block = Memory.GetMemByAddr(buf_addr); nbytes = block.GetSize() - (buf_addr - block.GetStartAddr()); } const u64 res = nbytes ? file->Read(Memory.GetMemFromAddr(buf_addr), nbytes) : 0; if(nread.IsGood()) nread = res; return CELL_OK; }
int cellFsStReadGetStatus(u32 fd, mem64_t status) { sys_fs.Warning("cellFsStReadGetRingBuf(fd=%d, status_addr=0x%x)", fd, status.GetAddr()); vfsStream* file; if(!sys_fs.CheckId(fd, file)) return CELL_ESRCH; status = m_fs_config.m_fs_status; return CELL_OK; }
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()); vfsStream* file; if(!sys_fs.CheckId(fd, file)) return CELL_ESRCH; if(Memory.IsGoodAddr(buf_addr) && !Memory.IsGoodAddr(buf_addr, nbytes)) { MemoryBlock& block = Memory.GetMemByAddr(buf_addr); nbytes = block.GetSize() - (buf_addr - block.GetStartAddr()); } const u64 res = nbytes ? file->Write(Memory.GetMemFromAddr(buf_addr), nbytes) : 0; if(nwrite.IsGood()) nwrite = res; return CELL_OK; }
int cellFsStReadGetRegid(u32 fd, mem64_t regid) { sys_fs.Warning("cellFsStReadGetRingBuf(fd=%d, regid_addr=0x%x)", fd, regid.GetAddr()); vfsStream* file; if(!sys_fs.CheckId(fd, file)) return CELL_ESRCH; regid = m_fs_config.m_regid; return CELL_OK; }
//182 int sys_spu_thread_read_ls(u32 id, u32 address, mem64_t value, u32 type) { sc_spu.Warning("sys_spu_thread_read_ls(id=0x%x, address=0x%x, value_addr=0x%x, type=0x%x)", id, address, value.GetAddr(), type); CPUThread* thr = Emu.GetCPU().GetThread(id); if(!thr || (thr->GetType() != CPU_THREAD_SPU && thr->GetType() != CPU_THREAD_RAW_SPU)) { return CELL_ESRCH; } if(!value.IsGood() || !(*(SPUThread*)thr).IsGoodLSA(address)) { return CELL_EFAULT; } value = (*(SPUThread*)thr).ReadLS64(address); return CELL_OK; }
int UTF16stoUTF8s(mem16_ptr_t utf16, mem64_t utf16_len, mem8_ptr_t utf8, mem64_t utf8_len) { cellL10n.Warning("UTF16stoUTF8s(utf16_addr=0x%x, utf16_len_addr=0x%x, utf8_addr=0x%x, utf8_len_addr=0x%x)", utf16.GetAddr(), utf16_len.GetAddr(), utf8.GetAddr(), utf8_len.GetAddr()); if (!utf16.IsGood() || !utf16_len.IsGood() || !utf8_len.IsGood()) return SRCIllegal; std::u16string wstr =(char16_t*)Memory.VirtualToRealAddr(utf16); wstr.resize(utf16_len.GetValue()); // TODO: Is this really the role of utf16_len in this function? #ifdef _MSC_VER std::wstring_convert<std::codecvt_utf8_utf16<char16_t>,char16_t> convert; std::string str = convert.to_bytes(wstr); if (!utf8.IsGood() || utf8_len.GetValue() < str.size()) { utf8_len = str.size(); return DSTExhausted; } utf8_len = str.size(); Memory.WriteString(utf8, str.c_str()); #endif return ConversionOK; }
int UTF16stoUTF8s(mem16_ptr_t utf16, mem64_t utf16_len, mem8_ptr_t utf8, mem64_t utf8_len) { cellL10n.Warning("UTF16stoUTF8s(utf16_addr=0x%x, utf16_len_addr=0x%x, utf8_addr=0x%x, utf8_len_addr=0x%x)", utf16.GetAddr(), utf16_len.GetAddr(), utf8.GetAddr(), utf8_len.GetAddr()); if (!utf16.IsGood() || !utf16_len.IsGood() || !utf8_len.IsGood()) return SRCIllegal; std::wstring wstr = (wchar_t*)Memory.VirtualToRealAddr(utf16); std::string str; int len = min((int)utf16_len.GetValue(), (int)wstr.size()); int size = (int)WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), len, 0, 0, NULL, NULL); if (!utf8.IsGood()) utf8_len = size; if (utf8_len.GetValue() < size) return DSTExhausted; #ifdef WIN32 WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), len, &str[0], size, NULL, NULL); #else // TODO #endif Memory.WriteString(utf8, str); return ConversionOK; }
//TODO: Check the code in emulation. If support for UTF8/UTF16/UTF32/UCS2/UCS4 should use wider chars.. awful. int L10nConvertStr(int src_code, mem8_ptr_t src, mem64_t src_len, int dst_code, mem8_ptr_t dst, mem64_t dst_len) { LOG_ERROR(HLE, "L10nConvertStr(src_code=%d,src=0x%x,src_len=%ld,dst_code=%d,dst=0x%x,dst_len=%ld)", src_code, src.GetAddr(), src_len.GetValue(), dst_code, dst.GetAddr(), dst_len.GetValue()); LOG_ERROR(HLE, "L10nConvertStr: 1st char at dst: %x(Hex)", *((char*)Memory.VirtualToRealAddr(src.GetAddr()))); #ifdef _MSC_VER unsigned int srcCode = 0, dstCode = 0; //OEM code pages bool src_page_converted = _L10nCodeParse(src_code, srcCode); //Check if code is in list. bool dst_page_converted = _L10nCodeParse(dst_code, dstCode); if (((!src_page_converted) && (srcCode == 0)) || ((!dst_page_converted) && (dstCode == 0))) return ConverterUnknown; //if (strnlen_s((char*)src, *src_len) != *src_len) return SRCIllegal; std::string wrapped_source = (char*)Memory.VirtualToRealAddr(src.GetAddr()); //std::string wrapped_source((char*)src); if (wrapped_source.length() != src_len.GetValue()) return SRCIllegal; std::string target = _OemToOem(srcCode, dstCode, wrapped_source); if (target.length() > dst_len.GetValue()) return DSTExhausted; Memory.WriteString(dst, target.c_str()); return ConversionOK; #else std::string srcCode, dstCode; int retValue = ConversionOK; if ((_L10nCodeParse(src_code, srcCode)) && (_L10nCodeParse(dst_code, dstCode))) { iconv_t ict = iconv_open(srcCode.c_str(), dstCode.c_str()); char *srcBuf = (char*)Memory.VirtualToRealAddr(src.GetAddr()); char *dstBuf = (char*)Memory.VirtualToRealAddr(dst.GetAddr()); //char *srcBuf = (char*)src, *dstBuf = (char*)dst; //size_t srcLen = *src_len, dstLen = *dst_len; size_t srcLen = src_len.GetValue(), dstLen = dst_len.GetValue(); size_t ictd = iconv(ict, &srcBuf, &srcLen, &dstBuf, &dstLen); if (ictd != src_len.GetValue())//if (ictd != *src_len) { if (errno == EILSEQ) retValue = SRCIllegal; //Invalid multi-byte sequence else if (errno == E2BIG) retValue = DSTExhausted;//Not enough space else if (errno == EINVAL) retValue = SRCIllegal; } iconv_close(ict); //retValue = ConversionOK; } else retValue = ConverterUnknown; return retValue; #endif }
s32 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()); vfsStream* file; if(!sys_fs->CheckId(fd, file)) return CELL_ESRCH; if (nread.GetAddr() && !nread.IsGood()) { sys_fs->Error("cellFsRead(): bad nread_addr(0x%x)", nread.GetAddr()); return CELL_EFAULT; } if (nbytes != (u32)nbytes) return CELL_ENOMEM; // TODO: checks const u64 res = nbytes ? file->Read(Memory.GetMemFromAddr(buf_addr), nbytes) : 0; if (nread.GetAddr()) nread = res; // write value if not NULL return CELL_OK; }
//188 s32 sys_spu_thread_get_spu_cfg(u32 id, mem64_t value) { sc_spu.Warning("sys_spu_thread_get_spu_cfg(id=%d, value_addr=0x%x)", id, value.GetAddr()); CPUThread* thr = Emu.GetCPU().GetThread(id); if(!thr || (thr->GetType() != CPU_THREAD_SPU && thr->GetType() != CPU_THREAD_RAW_SPU)) { return CELL_ESRCH; } value = (*(SPUThread*)thr).cfg.value; return CELL_OK; }
int sys_event_flag_get(u32 eflag_id, mem64_t flags) { sys_event_flag.Warning("sys_event_flag_get(eflag_id=%d, flags_addr=0x%x)", eflag_id, flags.GetAddr()); EventFlag* ef; if(!sys_event_flag.CheckId(eflag_id, ef)) return CELL_ESRCH; if (!flags.IsGood()) { return CELL_EFAULT; } flags = ef->flags; // ??? return CELL_OK; }
s32 sys_raw_spu_get_int_mask(u32 id, u32 class_id, mem64_t mask) { sc_spu.Log("sys_raw_spu_get_int_mask(id=%d, class_id=%d, mask_addr=0x%x)", id, class_id, mask.GetAddr()); if (!mask.IsGood()) { return CELL_EFAULT; } RawSPUThread* t = Emu.GetCPU().GetRawSPUThread(id); if (!t) { return CELL_ESRCH; } if (class_id != 0 && class_id != 2) { return CELL_EINVAL; } mask = t->m_intrtag[class_id].mask; return CELL_OK; }
s32 sys_raw_spu_get_int_stat(u32 id, u32 class_id, mem64_t stat) { sc_spu.Log("sys_raw_spu_get_int_stat(id=%d, class_id=%d, stat_addr=0xx)", id, class_id, stat.GetAddr()); if (!stat.IsGood()) { return CELL_EFAULT; } RawSPUThread* t = Emu.GetCPU().GetRawSPUThread(id); if (!t) { return CELL_ESRCH; } if (class_id != 0 && class_id != 2) { return CELL_EINVAL; } stat = t->m_intrtag[class_id].stat; return CELL_OK; }
s32 sys_ppu_thread_create(mem64_t thread_id, u32 entry, u64 arg, s32 prio, u32 stacksize, u64 flags, u32 threadname_addr) { std::string threadname = ""; if (Memory.IsGoodAddr(threadname_addr)) { threadname = Memory.ReadString(threadname_addr); sysPrxForUser->Log("sys_ppu_thread_create(thread_id_addr=0x%x, entry=0x%x, arg=0x%llx, prio=%d, stacksize=0x%x, flags=0x%llx, threadname_addr=0x%x('%s'))", thread_id.GetAddr(), entry, arg, prio, stacksize, flags, threadname_addr, threadname.c_str()); } else { sysPrxForUser->Log("sys_ppu_thread_create(thread_id_addr=0x%x, entry=0x%x, arg=0x%llx, prio=%d, stacksize=0x%x, flags=0x%llx, threadname_addr=0x%x)", thread_id.GetAddr(), entry, arg, prio, stacksize, flags, threadname_addr); if (threadname_addr != 0) return CELL_EFAULT; } if (!Memory.IsGoodAddr(entry) || !thread_id.IsGood()) { return CELL_EFAULT; } bool is_joinable = false; bool is_interrupt = false; switch (flags) { case 0: break; case SYS_PPU_THREAD_CREATE_JOINABLE: { is_joinable = true; break; } case SYS_PPU_THREAD_CREATE_INTERRUPT: { is_interrupt = true; break; } default: sysPrxForUser->Error("sys_ppu_thread_create(): unknown flags value (0x%llx)", flags); return CELL_EPERM; } CPUThread& new_thread = Emu.GetCPU().AddThread(CPU_THREAD_PPU); thread_id = new_thread.GetId(); new_thread.SetEntry(entry); new_thread.SetArg(0, arg); new_thread.SetPrio(prio); new_thread.SetStackSize(stacksize); //new_thread.flags = flags; new_thread.m_has_interrupt = false; new_thread.m_is_interrupt = is_interrupt; new_thread.SetName(threadname); LOG_NOTICE(PPU, "*** New PPU Thread [%s] (flags=0x%llx, entry=0x%x): id = %d", new_thread.GetName().c_str(), flags, entry, new_thread.GetId()); if (!is_interrupt) { new_thread.Run(); new_thread.Exec(); } return CELL_OK; }
int cellFsGetBlockSize(u32 path_addr, mem64_t sector_size, mem64_t block_size) { sys_fs.Log("cellFsGetBlockSize(file: %s, sector_size_addr: 0x%x, block_size_addr: 0x%x)", Memory.ReadString(path_addr).wx_str(), sector_size.GetAddr(), block_size.GetAddr()); sector_size = 4096; // ? block_size = 4096; // ? return CELL_OK; }
int cellFsFGetBlockSize(u32 fd, mem64_t sector_size, mem64_t block_size) { sys_fs.Log("cellFsFGetBlockSize(fd=%d, sector_size_addr: 0x%x, block_size_addr: 0x%x)", fd, sector_size.GetAddr(), block_size.GetAddr()); vfsStream* file; if(!sys_fs.CheckId(fd, file)) return CELL_ESRCH; sector_size = 4096; // ? block_size = 4096; // ? return CELL_OK; }
int cellFsLseek(u32 fd, s64 offset, u32 whence, mem64_t pos) { vfsSeekMode seek_mode; sys_fs.Log("cellFsLseek(fd=%d, offset=0x%llx, whence=0x%x, pos_addr=0x%x)", fd, offset, whence, pos.GetAddr()); switch(whence) { case CELL_SEEK_SET: seek_mode = vfsSeekSet; break; case CELL_SEEK_CUR: seek_mode = vfsSeekCur; break; case CELL_SEEK_END: seek_mode = vfsSeekEnd; break; default: sys_fs.Error(fd, "Unknown seek whence! (0x%x)", whence); return CELL_EINVAL; } u32 attr; vfsStream* file; if(!sys_fs.CheckId(fd, file, attr) || attr != IDFlag_File) return CELL_ESRCH; pos = file->Seek(offset, seek_mode); return CELL_OK; }
s32 sys_ppu_thread_join(u64 thread_id, mem64_t vptr) { sysPrxForUser->Warning("sys_ppu_thread_join(thread_id=%lld, vptr_addr=0x%x)", thread_id, vptr.GetAddr()); CPUThread* thr = Emu.GetCPU().GetThread(thread_id); if(!thr) return CELL_ESRCH; while (thr->IsAlive()) { if (Emu.IsStopped()) { LOG_WARNING(PPU, "sys_ppu_thread_join(%d) aborted", thread_id); return CELL_OK; } std::this_thread::sleep_for(std::chrono::milliseconds(1)); } vptr = thr->GetExitStatus(); return CELL_OK; }