s32 sys_mmapper_allocate_memory(u32 size, u64 flags, mem32_t mem_id) { sys_mmapper.Warning("sys_mmapper_allocate_memory(size=0x%x, flags=0x%llx, mem_id_addr=0x%x)", size, flags, mem_id.GetAddr()); if(!mem_id.IsGood()) return CELL_EFAULT; // Check page granularity. u32 addr; switch(flags & (SYS_MEMORY_PAGE_SIZE_1M | SYS_MEMORY_PAGE_SIZE_64K)) { case SYS_MEMORY_PAGE_SIZE_1M: if(size & 0xfffff) return CELL_EALIGN; addr = Memory.Alloc(size, 0x100000); break; case SYS_MEMORY_PAGE_SIZE_64K: if(size & 0xffff) return CELL_EALIGN; addr = Memory.Alloc(size, 0x10000); break; default: return CELL_EINVAL; } if(!addr) return CELL_ENOMEM; // Generate a new mem ID. mem_id = sys_mmapper.GetNewId(new mmapper_info(addr, size, flags)); return CELL_OK; }
int cellFsAioRead(mem_ptr_t<CellFsAio> aio, mem32_t aio_id, mem_func_ptr_t<void (*)(mem_ptr_t<CellFsAio> xaio, int error, int xid, u64 size)> func) { sys_fs.Warning("cellFsAioRead(aio_addr=0x%x, id_addr=0x%x, func_addr=0x%x)", aio.GetAddr(), aio_id.GetAddr(), func.GetAddr()); if (!aio.IsGood() || !aio_id.IsGood() || !func.IsGood()) { return CELL_EFAULT; } if (!aio_init) { return CELL_ENXIO; } vfsFileBase* orig_file; u32 fd = aio->fd; if (!sys_fs.CheckId(fd, orig_file)) return CELL_EBADF; //get a unique id for the callback (may be used by cellFsAioCancel) const u32 xid = g_FsAioReadID++; aio_id = xid; { thread t("fsAioRead", std::bind(fsAioRead, fd, aio, xid, func)); t.detach(); } return CELL_OK; }
s32 sys_raw_spu_create_interrupt_tag(u32 id, u32 class_id, u32 hwthread, mem32_t intrtag) { sc_spu.Warning("sys_raw_spu_create_interrupt_tag(id=%d, class_id=%d, hwthread=0x%x, intrtag_addr=0x%x)", id, class_id, hwthread, intrtag.GetAddr()); RawSPUThread* t = Emu.GetCPU().GetRawSPUThread(id); if (!t) { return CELL_ESRCH; } if (class_id != 0 && class_id != 2) { return CELL_EINVAL; } if (!intrtag.IsGood()) { return CELL_EFAULT; } if (t->m_intrtag[class_id].enabled) { return CELL_EAGAIN; } t->m_intrtag[class_id].enabled = 1; intrtag = (id & 0xff) | (class_id << 8); return CELL_OK; }
int cellAdecOpenEx(mem_ptr_t<CellAdecType> type, mem_ptr_t<CellAdecResourceEx> res, mem_ptr_t<CellAdecCb> cb, mem32_t handle) { cellAdec.Warning("cellAdecOpenEx(type_addr=0x%x, res_addr=0x%x, cb_addr=0x%x, handle_addr=0x%x)", type.GetAddr(), res.GetAddr(), cb.GetAddr(), handle.GetAddr()); if (!type.IsGood() || !res.IsGood() || !cb.IsGood() || !handle.IsGood()) { return CELL_ADEC_ERROR_FATAL; } if (!adecCheckType(type->audioCodecType)) return CELL_ADEC_ERROR_ARG; handle = adecOpen(new AudioDecoder(type->audioCodecType, res->startAddr, res->totalMemSize, cb->cbFunc, cb->cbArg)); return CELL_OK; }
int cellGameBootCheck(mem32_t type, mem32_t attributes, mem_ptr_t<CellGameContentSize> size, mem_list_ptr_t<u8> dirName) { cellGame.Warning("cellGameBootCheck(type_addr=0x%x, attributes_addr=0x%x, size_addr=0x%x, dirName_addr=0x%x)", type.GetAddr(), attributes.GetAddr(), size.GetAddr(), dirName.GetAddr()); if (!type.IsGood() || !attributes.IsGood() || !size.IsGood() || !dirName.IsGood()) return CELL_GAME_ERROR_PARAM; type = CELL_GAME_GAMETYPE_DISC; attributes = 0; size->hddFreeSizeKB = 40000000; //40 GB, TODO: Use the free space of the computer's HDD where RPCS3 is being run. size->sizeKB = CELL_GAME_SIZEKB_NOTCALC; size->sysSizeKB = 0; //TODO: dirName return CELL_OK; }
int cellFsOpendir(u32 path_addr, mem32_t fd) { const wxString& path = Memory.ReadString(path_addr); sys_fs.Error("cellFsOpendir(path_addr: 0x%x(%s), fd_addr: 0x%x)", path_addr, path.mb_str(), fd.GetAddr()); if(!Memory.IsGoodAddr(path_addr) || !fd.IsGood()) return CELL_EFAULT; return CELL_OK; }
int cellVdecOpenEx(const mem_ptr_t<CellVdecTypeEx> type, const mem_ptr_t<CellVdecResourceEx> res, const mem_ptr_t<CellVdecCb> cb, mem32_t handle) { cellVdec->Warning("cellVdecOpenEx(type_addr=0x%x, res_addr=0x%x, cb_addr=0x%x, handle_addr=0x%x)", type.GetAddr(), res.GetAddr(), cb.GetAddr(), handle.GetAddr()); handle = vdecOpen(new VideoDecoder(type->codecType, type->profileLevel, res->memAddr, res->memSize, cb->cbFunc, cb->cbArg)); return CELL_OK; }
int cellSpursGetTasksetId(mem_ptr_t<CellSpursTaskset> taskset, mem32_t workloadId) { cellSpurs.Error("cellSpursGetTasksetId(taskset_addr=0x%x, workloadId_addr=0x%x)", taskset.GetAddr(), workloadId.GetAddr()); if(!taskset.IsGood() || !workloadId.IsGood()) return CELL_SPURS_TASK_ERROR_NULL_POINTER; return CELL_OK; }
s32 sys_raw_spu_get_spu_cfg(u32 id, mem32_t value) { sc_spu.Log("sys_raw_spu_get_spu_afg(id=%d, value_addr=0x%x)", id, value.GetAddr()); if (!value.IsGood()) { return CELL_EFAULT; } RawSPUThread* t = Emu.GetCPU().GetRawSPUThread(id); if (!t) { return CELL_ESRCH; } value = t->cfg.value; return CELL_OK; }
int cellUserInfoGetList(mem32_t listNum, mem_ptr_t<CellUserInfoUserList> listBuf, mem32_t currentUserId) { cellUserInfo->Warning("cellUserInfoGetList(listNum_addr=0x%x, listBuf_addr=0x%x, currentUserId_addr=0x%x)", listNum.GetAddr(), listBuf.GetAddr(), currentUserId.GetAddr()); // If only listNum is NULL, an error will be returned if (listBuf.GetAddr() && !listNum.GetAddr()) return CELL_USERINFO_ERROR_PARAM; if (listNum.GetAddr()) listNum = 1; if (listBuf.GetAddr()) listBuf->userId[0] = 1; if (currentUserId.GetAddr()) currentUserId = 1; return CELL_OK; }
int cellFsOpendir(u32 path_addr, mem32_t fd) { const wxString& path = Memory.ReadString(path_addr); sys_fs.Warning("cellFsOpendir(path=\"%s\", fd_addr=0x%x)", path.wx_str(), fd.GetAddr()); if(!Memory.IsGoodAddr(path_addr) || !fd.IsGood()) return CELL_EFAULT; vfsDirBase* dir = Emu.GetVFS().OpenDir(path); if(!dir || !dir->IsOpened()) { delete dir; return CELL_ENOENT; } fd = sys_fs.GetNewId(dir, IDFlag_Dir); return CELL_OK; }
int cellSpursGetSpuThreadId(mem_ptr_t<CellSpurs> spurs, mem32_t thread, mem32_t nThreads) { cellSpurs->Todo("cellSpursGetSpuThreadId(spurs_addr=0x%x, thread_addr=0x%x, nThreads_addr=0x%x)", spurs.GetAddr(), thread.GetAddr(), nThreads.GetAddr()); if (spurs.GetAddr() % 128 != 0) { cellSpurs->Error("cellSpursGetSpuThreadId : CELL_SPURS_CORE_ERROR_ALIGN"); return CELL_SPURS_CORE_ERROR_ALIGN; } if (!spurs.IsGood() || !thread.IsGood() || nThreads.IsGood()) { cellSpurs->Error("cellSpursGetSpuThreadId : CELL_SPURS_CORE_ERROR_NULL_POINTER"); return CELL_SPURS_CORE_ERROR_NULL_POINTER; } 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 sys_event_flag_cancel(u32 eflag_id, mem32_t num) { sys_event_flag.Warning("sys_event_flag_cancel(eflag_id=%d, num_addr=0x%x)", eflag_id, num.GetAddr()); EventFlag* ef; if(!sys_event_flag.CheckId(eflag_id, ef)) return CELL_ESRCH; Array<u32> tids; { SMutexLocker lock(ef->m_mutex); tids.SetCount(ef->waiters.GetCount()); for (u32 i = 0; i < ef->waiters.GetCount(); i++) { tids[i] = ef->waiters[i].tid; } ef->waiters.Clear(); } for (u32 i = 0; i < tids.GetCount(); i++) { if (Emu.IsStopped()) break; ef->signal.lock(tids[i]); } if (Emu.IsStopped()) { ConLog.Warning("sys_event_flag_cancel(id=%d) aborted", eflag_id); return CELL_OK; } if (num.IsGood()) { num = tids.GetCount(); return CELL_OK; } if (!num.GetAddr()) { return CELL_OK; } return CELL_EFAULT; }
int cellFontGetEffectSlant(mem_ptr_t<CellFont> font, mem32_t slantParam) { cellFont->Warning("cellFontSetEffectSlant(font_addr=0x%x, slantParam_addr=0x%x)", font.GetAddr(), slantParam.GetAddr()); if (!font.IsGood() || !slantParam.IsGood()) return CELL_FONT_ERROR_INVALID_PARAMETER; slantParam = font->slant; //Does this conversion from be_t<float> to *mem32_t work? return CELL_FONT_OK; }
int cellFontGetEffectSlant(mem_ptr_t<CellFont> font, mem32_t slantParam) { cellFont.Warning("cellFontSetEffectSlant(font_addr=0x%x, slantParam_addr=0x%x)", font.GetAddr(), slantParam.GetAddr()); if (!font.IsGood() || !slantParam.IsGood()) return CELL_FONT_ERROR_INVALID_PARAMETER; slantParam = font->slant; return CELL_FONT_OK; }
int sceNpManagerGetStatus(mem32_t status) { sceNp->Log("sceNpManagerGetStatus(status_addr=0x%x)", status.GetAddr()); // TODO: Check if sceNpInit() was called, if not return SCE_NP_ERROR_NOT_INITIALIZED // TODO: Support different statuses status = SCE_NP_MANAGER_STATUS_OFFLINE; return CELL_OK; }
int cellPadGetCapabilityInfo(u32 port_no, mem32_t info_addr) { sys_io->Log("cellPadGetCapabilityInfo[port_no: %d, data_addr: 0x%x]", port_no, info_addr.GetAddr()); if (!Emu.GetPadManager().IsInited()) return CELL_PAD_ERROR_UNINITIALIZED; const PadInfo& rinfo = Emu.GetPadManager().GetInfo(); if (port_no >= rinfo.max_connect) return CELL_PAD_ERROR_INVALID_PARAMETER; if (port_no >= rinfo.now_connect) return CELL_PAD_ERROR_NO_DEVICE; const std::vector<Pad>& pads = Emu.GetPadManager().GetPads(); CellCapabilityInfo data = {}; //Should return the same as device capability mask, psl1ght has it backwards in pad.h data.info[0] = pads[port_no].m_device_capability; Memory.WriteData(info_addr.GetAddr(), data); return CELL_OK; }
int cellVdecOpenEx(const mem_ptr_t<CellVdecTypeEx> type, const mem_ptr_t<CellVdecResourceEx> res, const mem_ptr_t<CellVdecCb> cb, mem32_t handle) { cellVdec->Warning("cellVdecOpenEx(type_addr=0x%x, res_addr=0x%x, cb_addr=0x%x, handle_addr=0x%x)", type.GetAddr(), res.GetAddr(), cb.GetAddr(), handle.GetAddr()); if (!type.IsGood() || !res.IsGood() || !cb.IsGood() || !handle.IsGood()) { return CELL_VDEC_ERROR_FATAL; } if (!Memory.IsGoodAddr(res->memAddr, res->memSize) || !Memory.IsGoodAddr(cb->cbFunc)) { return CELL_VDEC_ERROR_FATAL; } handle = vdecOpen(new VideoDecoder(type->codecType, type->profileLevel, res->memAddr, res->memSize, cb->cbFunc, cb->cbArg)); return CELL_OK; }
s32 sys_mutex_create(mem32_t mutex_id, mem_ptr_t<sys_mutex_attribute> attr) { sys_mutex.Log("sys_mutex_create(mutex_id_addr=0x%x, attr_addr=0x%x)", mutex_id.GetAddr(), attr.GetAddr()); switch (attr->protocol.ToBE()) { case se32(SYS_SYNC_FIFO): break; case se32(SYS_SYNC_PRIORITY): break; case se32(SYS_SYNC_PRIORITY_INHERIT): sys_mutex.Todo("sys_mutex_create(): SYS_SYNC_PRIORITY_INHERIT"); break; case se32(SYS_SYNC_RETRY): sys_mutex.Error("sys_mutex_create(): SYS_SYNC_RETRY"); return CELL_EINVAL; default: sys_mutex.Error("Unknown protocol attribute(0x%x)", (u32)attr->protocol); return CELL_EINVAL; } bool is_recursive; switch (attr->recursive.ToBE()) { case se32(SYS_SYNC_RECURSIVE): is_recursive = true; break; case se32(SYS_SYNC_NOT_RECURSIVE): is_recursive = false; break; default: sys_mutex.Error("Unknown recursive attribute(0x%x)", (u32)attr->recursive); return CELL_EINVAL; } if (attr->pshared.ToBE() != se32(0x200)) { sys_mutex.Error("Unknown pshared attribute(0x%x)", (u32)attr->pshared); return CELL_EINVAL; } u32 tid = GetCurrentPPUThread().GetId(); Mutex* mutex = new Mutex((u32)attr->protocol, is_recursive, attr->name_u64); u32 id = sys_mutex.GetNewId(mutex, TYPE_MUTEX); mutex->m_mutex.lock(tid); mutex->id = id; mutex_id = id; mutex->m_mutex.unlock(tid); sys_mutex.Warning("*** mutex created [%s] (protocol=0x%x, recursive=%s): id = %d", std::string(attr->name, 8).c_str(), (u32) attr->protocol, (is_recursive ? "true" : "false"), mutex_id.GetValue()); // TODO: unlock mutex when owner thread does exit return CELL_OK; }
// Functions s32 sys_time_get_timezone(mem32_t timezone, mem32_t summertime) { sys_time.Warning("sys_time_get_timezone(timezone_addr=0x%x, summertime_addr=0x%x)", timezone.GetAddr(), summertime.GetAddr()); int ret; ret = cellSysutilGetSystemParamInt(0x0116, timezone); //0x0116 = CELL_SYSUTIL_SYSTEMPARAM_ID_TIMEZONE if (ret != CELL_OK) return ret; ret = cellSysutilGetSystemParamInt(0x0117, summertime); //0x0117 = CELL_SYSUTIL_SYSTEMPARAM_ID_TIMEZONE if (ret != CELL_OK) return ret; return CELL_OK; }
int sys_net_initialize_network_ex(mem_ptr_t<sys_net_initialize_parameter> param) { sys_net->Warning("sys_net_initialize_network_ex(param_addr=0x%x)", param.GetAddr()); g_lastError.SetAddr(Memory.Alloc(4, 1)); #ifdef _WIN32 WSADATA wsaData; WORD wVersionRequested = MAKEWORD(1,1); WSAStartup(wVersionRequested, &wsaData); #endif 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; }
s32 sys_raw_spu_read_puint_mb(u32 id, mem32_t value) { sc_spu.Log("sys_raw_spu_read_puint_mb(id=%d, value_addr=0x%x)", id, value.GetAddr()); if (!value.IsGood()) { return CELL_EFAULT; } RawSPUThread* t = Emu.GetCPU().GetRawSPUThread(id); if (!t) { return CELL_ESRCH; } u32 v; t->SPU.Out_IntrMBox.PopUncond(v); value = v; return CELL_OK; }
//160 s32 sys_raw_spu_create(mem32_t id, u32 attr_addr) { sc_spu.Warning("sys_raw_spu_create(id_addr=0x%x, attr_addr=0x%x)", id.GetAddr(), attr_addr); //Emu.GetIdManager().GetNewID("sys_raw_spu", new u32(attr_addr)); CPUThread& new_thread = Emu.GetCPU().AddThread(CPU_THREAD_RAW_SPU); id = ((RawSPUThread&)new_thread).GetIndex(); new_thread.Run(); return CELL_OK; }
s32 sys_mmapper_allocate_memory_from_container(u32 size, u32 cid, u64 flags, mem32_t mem_id) { sys_mmapper.Warning("sys_mmapper_allocate_memory_from_container(size=0x%x, cid=%d, flags=0x%llx, mem_id_addr=0x%x)", size, cid, flags, mem_id.GetAddr()); if(!mem_id.IsGood()) return CELL_EFAULT; // Check if this container ID is valid. MemoryContainerInfo* ct; if(!sys_mmapper.CheckId(cid, ct)) return CELL_ESRCH; // Check page granularity. switch(flags & (SYS_MEMORY_PAGE_SIZE_1M | SYS_MEMORY_PAGE_SIZE_64K)) { case SYS_MEMORY_PAGE_SIZE_1M: if(size & 0xfffff) return CELL_EALIGN; ct->addr = Memory.Alloc(size, 0x100000); break; case SYS_MEMORY_PAGE_SIZE_64K: if(size & 0xffff) return CELL_EALIGN; ct->addr = Memory.Alloc(size, 0x10000); break; default: return CELL_EINVAL; } if(!ct->addr) return CELL_ENOMEM; ct->size = size; // Generate a new mem ID. mem_id = sys_mmapper.GetNewId(new mmapper_info(ct->addr, ct->size, flags)); return CELL_OK; }
int sys_mutex_create(mem32_t mutex_id, mem_ptr_t<sys_mutex_attribute> attr) { sys_mtx.Log("sys_mutex_create(mutex_id_addr=0x%x, attr_addr=0x%x)", mutex_id.GetAddr(), attr.GetAddr()); if (!mutex_id.IsGood() || !attr.IsGood()) { return CELL_EFAULT; } switch (attr->protocol.ToBE()) { case se32(SYS_SYNC_FIFO): break; case se32(SYS_SYNC_PRIORITY): break; case se32(SYS_SYNC_PRIORITY_INHERIT): sys_mtx.Warning("TODO: SYS_SYNC_PRIORITY_INHERIT protocol"); break; case se32(SYS_SYNC_RETRY): sys_mtx.Error("Invalid SYS_SYNC_RETRY protocol"); return CELL_EINVAL; default: sys_mtx.Error("Unknown protocol attribute(0x%x)", (u32)attr->protocol); return CELL_EINVAL; } bool is_recursive; switch (attr->recursive.ToBE()) { case se32(SYS_SYNC_RECURSIVE): is_recursive = true; break; case se32(SYS_SYNC_NOT_RECURSIVE): is_recursive = false; break; default: sys_mtx.Error("Unknown recursive attribute(0x%x)", (u32)attr->recursive); return CELL_EINVAL; } if (attr->pshared.ToBE() != se32(0x200)) { sys_mtx.Error("Unknown pshared attribute(0x%x)", (u32)attr->pshared); return CELL_EINVAL; } mutex_id = sys_mtx.GetNewId(new Mutex((u32)attr->protocol, is_recursive, attr->name_u64)); sys_mtx.Warning("*** mutex created [%s] (protocol=0x%x, recursive=%s): id = %d", wxString(attr->name, 8).wx_str(), (u32)attr->protocol, wxString(is_recursive ? "true" : "false").wx_str(), mutex_id.GetValue()); // TODO: unlock mutex when owner thread does exit return CELL_OK; }
int cellGcmMapMainMemory(u32 address, u32 size, mem32_t offset) { cellGcmSys.Warning("cellGcmMapMainMemory(address=0x%x,size=0x%x,offset_addr=0x%x)", address, size, offset.GetAddr()); if(!offset.IsGood()) return CELL_EFAULT; Emu.GetGSManager().GetRender().m_main_mem_addr = Emu.GetGSManager().GetRender().m_ioAddress; offset = address - Emu.GetGSManager().GetRender().m_main_mem_addr; Emu.GetGSManager().GetRender().m_main_mem_info.AddCpy(MemInfo(address, size)); return CELL_OK; }
int cellSpursCreateTask(mem_ptr_t<CellSpursTaskset> taskset, mem32_t taskID, mem_ptr_t<void> elf_addr, mem_ptr_t<void> context_addr, u32 context_size, mem_ptr_t<CellSpursTaskLsPattern> lsPattern, mem_ptr_t<CellSpursTaskArgument> argument) { cellSpurs.Error("cellSpursCreateTask(taskset_addr=0x%x, taskID_addr=0x%x, elf_addr_addr=0x%x, context_addr_addr=0x%x, context_size=%u, lsPattern_addr=0x%x, argument_addr=0x%x)", taskset.GetAddr(), taskID.GetAddr(), elf_addr.GetAddr(), context_addr.GetAddr(), context_size, lsPattern.GetAddr(), argument.GetAddr()); if(!taskset.IsGood()) return CELL_SPURS_TASK_ERROR_NULL_POINTER; return CELL_OK; }
int sys_memory_container_create(mem32_t cid, u32 yield_size) { sc_mem.Warning("sys_memory_container_create(cid_addr=0x%x, yield_size=0x%x)", cid.GetAddr(), yield_size); if (!cid.IsGood()) return CELL_EFAULT; yield_size &= ~0xfffff; //round down to 1 MB granularity u64 addr = Memory.Alloc(yield_size, 0x100000); //1 MB alignment if(!addr) return CELL_ENOMEM; // Wrap the allocated memory in a memory container. MemoryContainerInfo *ct = new MemoryContainerInfo(addr, yield_size); cid = sc_mem.GetNewId(ct); sc_mem.Warning("*** memory_container created(addr=0x%llx): id = %d", addr, cid.GetValue()); return CELL_OK; }