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 cellVdecOpen(const mem_ptr_t<CellVdecType> type, const mem_ptr_t<CellVdecResource> res, const mem_ptr_t<CellVdecCb> cb, mem32_t handle) { cellVdec.Warning("cellVdecOpen(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; }
int sys_process_get_id(u32 object, mem32_ptr_t buffer, u32 size, mem32_t set_size) { sc_p.Warning("TODO: sys_process_get_id(object=%d, buffer_addr=0x%x, size=%d, set_size_addr=0x%x)", object, buffer.GetAddr(), size, set_size.GetAddr()); switch(object) { #define ADD_OBJECTS(objects) { \ u32 i=0; \ for(auto id=objects.begin(); i<size && id!=objects.end(); id++, i++) \ buffer[i] = *id; \ set_size = i; \ } case SYS_MEM_OBJECT: ADD_OBJECTS(procObjects.mem_objects); break; case SYS_MUTEX_OBJECT: ADD_OBJECTS(procObjects.mutex_objects); break; case SYS_COND_OBJECT: ADD_OBJECTS(procObjects.cond_objects); break; case SYS_RWLOCK_OBJECT: ADD_OBJECTS(procObjects.rwlock_objects); break; case SYS_INTR_TAG_OBJECT: ADD_OBJECTS(procObjects.intr_tag_objects); break; case SYS_INTR_SERVICE_HANDLE_OBJECT: ADD_OBJECTS(procObjects.intr_service_handle_objects); break; case SYS_EVENT_QUEUE_OBJECT: ADD_OBJECTS(procObjects.event_queue_objects); break; case SYS_EVENT_PORT_OBJECT: ADD_OBJECTS(procObjects.event_port_objects); break; case SYS_TRACE_OBJECT: ADD_OBJECTS(procObjects.trace_objects); break; case SYS_SPUIMAGE_OBJECT: ADD_OBJECTS(procObjects.spuimage_objects); break; case SYS_PRX_OBJECT: ADD_OBJECTS(procObjects.prx_objects); break; case SYS_SPUPORT_OBJECT: ADD_OBJECTS(procObjects.spuport_objects); break; case SYS_LWMUTEX_OBJECT: ADD_OBJECTS(procObjects.lwmutex_objects); break; case SYS_TIMER_OBJECT: ADD_OBJECTS(procObjects.timer_objects); break; case SYS_SEMAPHORE_OBJECT: ADD_OBJECTS(procObjects.semaphore_objects); break; case SYS_FS_FD_OBJECT: ADD_OBJECTS(procObjects.fs_fd_objects); break; case SYS_LWCOND_OBJECT: ADD_OBJECTS(procObjects.lwcond_objects); break; case SYS_EVENT_FLAG_OBJECT: ADD_OBJECTS(procObjects.event_flag_objects); break; #undef ADD_OBJECTS default: return CELL_EINVAL; } 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; }
//170 int sys_spu_thread_group_create(mem32_t id, u32 num, int prio, mem_ptr_t<sys_spu_thread_group_attribute> attr) { ConLog.Write("sys_spu_thread_group_create:"); ConLog.Write("*** id_addr=0x%x", id.GetAddr()); ConLog.Write("*** num=%d", num); ConLog.Write("*** prio=%d", prio); ConLog.Write("*** attr_addr=0x%x", attr.GetAddr()); ConLog.Write("*** attr.name_len=%d", attr->name_len.ToLE()); ConLog.Write("*** attr.name_addr=0x%x", attr->name_addr.ToLE()); ConLog.Write("*** attr.type=%d", attr->type.ToLE()); ConLog.Write("*** attr.option.ct=%d", attr->option.ct.ToLE()); const wxString name = Memory.ReadString(attr->name_addr, attr->name_len).mb_str(); ConLog.Write("*** name='%s'", name.c_str()); id = Emu.GetIdManager().GetNewID(wxString::Format("sys_spu_thread_group '%s'", name), new SpuGroupInfo(*attr)); 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; }
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; }
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_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; }
int sys_semaphore_get_value(u32 sem_id, mem32_t count) { sys_sem.Log("sys_semaphore_get_value(sem_id=%d, count_addr=0x%x)", sem_id, count.GetAddr()); if (!count.IsGood()) { return CELL_EFAULT; } Semaphore* sem; if (!Emu.GetIdManager().GetIDData(sem_id, sem)) { return CELL_ESRCH; } std::lock_guard<std::mutex> lock(sem->m_mutex); count = sem->m_value; return CELL_OK; }
int sys_raw_spu_load(int id, u32 path_addr, mem32_t entry) { const std::string path = Memory.ReadString(path_addr); sysPrxForUser->Warning("sys_raw_spu_load(id=0x%x, path=0x%x [%s], entry_addr=0x%x)", id, path_addr, path.c_str(), entry.GetAddr()); vfsFile f(path); if(!f.IsOpened()) { sysPrxForUser->Error("sys_raw_spu_load error: '%s' not found!", path.c_str()); return CELL_ENOENT; } ELFLoader l(f); l.LoadInfo(); l.LoadData(RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * id); entry = l.GetEntry(); 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->Todo("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.GetAddr() % 128 != 0) { cellSpurs->Error("cellSpursCreateTask : CELL_SPURS_TASK_ERROR_ALIGN"); return CELL_SPURS_TASK_ERROR_ALIGN; } if (!taskset.IsGood()) { cellSpurs->Error("cellSpursCreateTask : CELL_SPURS_TASK_ERROR_NULL_POINTER"); return CELL_SPURS_TASK_ERROR_NULL_POINTER; } return CELL_OK; }
int cellPngDecOpen(u32 mainHandle, mem32_t subHandle, mem_ptr_t<CellPngDecSrc> src, u32 openInfo) { cellPngDec.Warning("cellPngDecOpen(mainHandle=0x%x, subHandle=0x%x, src_addr=0x%x, openInfo=0x%x)", mainHandle, subHandle.GetAddr(), src.GetAddr(), openInfo); if (!subHandle.IsGood() || !src.IsGood()) return CELL_PNGDEC_ERROR_ARG; CellPngDecSubHandle *current_subHandle = new CellPngDecSubHandle; current_subHandle->fd = NULL; current_subHandle->src = *src; switch(src->srcSelect.ToBE()) { case const_se_t<u32, CELL_PNGDEC_BUFFER>::value: current_subHandle->fileSize = src->streamSize.ToLE(); break; case const_se_t<u32, CELL_PNGDEC_FILE>::value: // Get file descriptor MemoryAllocator<be_t<u32>> fd; int ret = cellFsOpen(src->fileName_addr, 0, fd.GetAddr(), NULL, 0); current_subHandle->fd = fd->ToLE(); if(ret != CELL_OK) return CELL_PNGDEC_ERROR_OPEN_FILE; // Get size of file MemoryAllocator<CellFsStat> sb; // Alloc a CellFsStat struct ret = cellFsFstat(current_subHandle->fd, sb.GetAddr()); if(ret != CELL_OK) return ret; current_subHandle->fileSize = sb->st_size; // Get CellFsStat.st_size break; } // From now, every u32 subHandle argument is a pointer to a CellPngDecSubHandle struct. subHandle = cellPngDec.GetNewId(current_subHandle); return CELL_OK; }
// Utility Functions int cellAudioCreateNotifyEventQueue(mem32_t id, mem64_t key) { cellAudio.Warning("cellAudioCreateNotifyEventQueue(id_addr=0x%x, key_addr=0x%x)", id.GetAddr(), key.GetAddr()); if (Emu.GetEventManager().CheckKey(0x80004d494f323221)) { return CELL_AUDIO_ERROR_EVENT_QUEUE; } EventQueue* eq = new EventQueue(SYS_SYNC_FIFO, SYS_PPU_QUEUE, 0x80004d494f323221, 0x80004d494f323221, 32); if (!Emu.GetEventManager().RegisterKey(eq, 0x80004d494f323221)) { delete eq; return CELL_AUDIO_ERROR_EVENT_QUEUE; } id = cellAudio.GetNewId(eq); key = 0x80004d494f323221; return CELL_OK; }
int sceNpTrophyCreateContext(mem32_t context, mem_ptr_t<SceNpCommunicationId> commID, mem_ptr_t<SceNpCommunicationSignature> commSign, u64 options) { sceNpTrophy.Warning("sceNpTrophyCreateContext(context_addr=0x%x, commID_addr=0x%x, commSign_addr=0x%x, options=0x%llx)", context.GetAddr(), commID.GetAddr(), commSign.GetAddr(), options); if (!s_npTrophyInstance.m_bInitialized) return SCE_NP_TROPHY_ERROR_NOT_INITIALIZED; if (!context.IsGood()) return SCE_NP_TROPHY_ERROR_INVALID_ARGUMENT; if (options & (~(u64)1)) SCE_NP_TROPHY_ERROR_NOT_SUPPORTED; // TODO: There are other possible errors // TODO: Is the TROPHY.TRP file necessarily located in this path? vfsDir dir("/app_home/TROPDIR/"); if(!dir.IsOpened()) return SCE_NP_TROPHY_ERROR_CONF_DOES_NOT_EXIST; // TODO: Following method will retrieve the TROPHY.TRP of the first folder that contains such file for(const DirEntryInfo* entry = dir.Read(); entry; entry = dir.Read()) { if (entry->flags & DirEntry_TypeDir) { std::shared_ptr<vfsFileBase> f(Emu.GetVFS().OpenFile("/app_home/TROPDIR/" + entry->name + "/TROPHY.TRP", vfsRead)); if (f && f->IsOpened()) { sceNpTrophyInternalContext ctxt; ctxt.trp_stream = f.get(); ctxt.trp_name = entry->name; s_npTrophyInstance.contexts.push_back(ctxt); f = nullptr; return CELL_OK; } } } return SCE_NP_TROPHY_ERROR_CONF_DOES_NOT_EXIST; }
//170 s32 sys_spu_thread_group_create(mem32_t id, u32 num, int prio, mem_ptr_t<sys_spu_thread_group_attribute> attr) { sc_spu.Warning("sys_spu_thread_group_create(id_addr=0x%x, num=%d, prio=%d, attr_addr=0x%x)", id.GetAddr(), num, prio, attr.GetAddr()); if (!id.IsGood() || !attr.IsGood()) return CELL_EFAULT; if (!Memory.IsGoodAddr(attr->name_addr, attr->name_len)) return CELL_EFAULT; if (num > 256) return CELL_EINVAL; if (prio < 16 || prio > 255) return CELL_EINVAL; const std::string name = Memory.ReadString(attr->name_addr, attr->name_len); id = sc_spu.GetNewId(new SpuGroupInfo(name, num, prio, attr->type, attr->ct)); sc_spu.Warning("*** SPU Thread Group created [%s] (type=0x%x, option.ct=0x%x): id=%d", name.c_str(), (int)attr->type, (u32)attr->ct, id.GetValue()); return CELL_OK; }
int sys_event_flag_create(mem32_t eflag_id, mem_ptr_t<sys_event_flag_attr> attr, u64 init) { sys_event_flag.Warning("sys_event_flag_create(eflag_id_addr=0x%x, attr_addr=0x%x, init=0x%llx)", eflag_id.GetAddr(), attr.GetAddr(), init); if(!eflag_id.IsGood() || !attr.IsGood()) { return CELL_EFAULT; } switch (attr->protocol.ToBE()) { case se32(SYS_SYNC_PRIORITY): break; case se32(SYS_SYNC_RETRY): sys_event_flag.Warning("TODO: SYS_SYNC_RETRY attr"); break; case se32(SYS_SYNC_PRIORITY_INHERIT): sys_event_flag.Warning("TODO: SYS_SYNC_PRIORITY_INHERIT attr"); break; case se32(SYS_SYNC_FIFO): break; default: return CELL_EINVAL; } if (attr->pshared.ToBE() != se32(0x200)) { return CELL_EINVAL; } switch (attr->type.ToBE()) { case se32(SYS_SYNC_WAITER_SINGLE): break; case se32(SYS_SYNC_WAITER_MULTIPLE): break; default: return CELL_EINVAL; } eflag_id = sys_event_flag.GetNewId(new EventFlag(init, (u32)attr->protocol, (int)attr->type)); sys_event_flag.Warning("*** event_flag created [%s] (protocol=0x%x, type=0x%x): id = %d", std::string(attr->name, 8).c_str(), (u32)attr->protocol, (int)attr->type, eflag_id.GetValue()); return CELL_OK; }
int sys_semaphore_create(mem32_t sem, mem_ptr_t<sys_semaphore_attribute> attr, int initial_count, int max_count) { sys_sem.Warning("sys_semaphore_create(sem_addr=0x%x, attr_addr=0x%x, initial_count=%d, max_count=%d)", sem.GetAddr(), attr.GetAddr(), initial_count, max_count); if (!sem.IsGood() || !attr.IsGood()) { return CELL_EFAULT; } if (max_count <= 0 || initial_count > max_count || initial_count < 0) { sys_sem.Error("sys_semaphore_create(): invalid parameters (initial_count=%d, max_count=%d)", initial_count, max_count); return CELL_EINVAL; } if (attr->pshared.ToBE() != se32(0x200)) { sys_sem.Error("sys_semaphore_create(): invalid pshared value(0x%x)", (u32)attr->pshared); return CELL_EINVAL; } switch (attr->protocol.ToBE()) { case se32(SYS_SYNC_FIFO): break; case se32(SYS_SYNC_PRIORITY): break; case se32(SYS_SYNC_PRIORITY_INHERIT): sys_sem.Warning("TODO: SYS_SYNC_PRIORITY_INHERIT protocol"); break; case se32(SYS_SYNC_RETRY): sys_sem.Error("Invalid SYS_SYNC_RETRY protocol"); return CELL_EINVAL; default: sys_sem.Error("Unknown protocol attribute(0x%x)", (u32)attr->protocol); return CELL_EINVAL; } sem = sys_sem.GetNewId(new Semaphore(initial_count, max_count, attr->protocol, attr->name_u64)); ConLog.Write("*** semaphore created [%s] (protocol=0x%x): id = %d", std::string(attr->name, 8).c_str(), (u32)attr->protocol, sem.GetValue()); return CELL_OK; }
int sceNpTrophyUnlockTrophy(u32 context, u32 handle, s32 trophyId, mem32_t platinumId) { sceNpTrophy->Warning("sceNpTrophyUnlockTrophy(context=%d, handle=%d, trophyId=%d, platinumId_addr=0x%x)", context, handle, trophyId, platinumId.GetAddr()); if (!s_npTrophyInstance.m_bInitialized) return SCE_NP_TROPHY_ERROR_NOT_INITIALIZED; // TODO: There are other possible errors sceNpTrophyInternalContext& ctxt = s_npTrophyInstance.contexts[context]; if (trophyId >= (s32)ctxt.tropusr->GetTrophiesCount()) return SCE_NP_TROPHY_ERROR_INVALID_TROPHY_ID; if (ctxt.tropusr->GetTrophyUnlockState(trophyId)) return SCE_NP_TROPHY_ERROR_ALREADY_UNLOCKED; u64 timestamp1 = get_system_time(); // TODO: Either timestamp1 or timestamp2 is wrong u64 timestamp2 = get_system_time(); // TODO: Either timestamp1 or timestamp2 is wrong ctxt.tropusr->UnlockTrophy(trophyId, timestamp1, timestamp2); std::string trophyPath = "/dev_hdd0/home/00000001/trophy/" + ctxt.trp_name + "/TROPUSR.DAT"; ctxt.tropusr->Save(trophyPath); platinumId = SCE_NP_TROPHY_INVALID_TROPHY_ID; // TODO return CELL_OK; }
int cellJpgDecOpen(u32 mainHandle, mem32_t subHandle, mem_ptr_t<CellJpgDecSrc> src, mem_ptr_t<CellJpgDecOpnInfo> openInfo) { cellJpgDec.Warning("cellJpgDecOpen(mainHandle=0x%x, subHandle=0x%x, src_addr=0x%x, openInfo=0x%x)", mainHandle, subHandle.GetAddr(), src.GetAddr(), openInfo); CellJpgDecSubHandle *current_subHandle = new CellJpgDecSubHandle; // Get file descriptor MemoryAllocator<be_t<u32>> fd; int ret = cellFsOpen(src->fileName, 0, fd, NULL, 0); current_subHandle->fd = fd->ToLE(); if(ret != CELL_OK) return CELL_JPGDEC_ERROR_OPEN_FILE; // Get size of file MemoryAllocator<CellFsStat> sb; // Alloc a CellFsStat struct ret = cellFsFstat(current_subHandle->fd, sb.GetAddr()); if(ret != CELL_OK) return ret; current_subHandle->fileSize = sb->st_size; // Get CellFsStat.st_size // From now, every u32 subHandle argument is a pointer to a CellPngDecSubHandle struct. subHandle = cellJpgDec.GetNewId(current_subHandle); return CELL_OK; }
int sys_event_port_create(mem32_t eport_id, int port_type, u64 name) { sys_event.Warning("sys_event_port_create(eport_id_addr=0x%x, port_type=0x%x, name=0x%llx)", eport_id.GetAddr(), port_type, name); if (!eport_id.IsGood()) { return CELL_EFAULT; } if (port_type != SYS_EVENT_PORT_LOCAL) { sys_event.Error("sys_event_port_create: invalid port_type(0x%x)", port_type); return CELL_EINVAL; } EventPort* eport = new EventPort(); u32 id = sys_event.GetNewId(eport); eport->name = name ? name : ((u64)sys_process_getpid() << 32) | (u64)id; eport_id = id; sys_event.Warning("*** sys_event_port created: id = %d", id); 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; }
int cellFsOpen(u32 path_addr, int flags, mem32_t fd, mem32_t arg, u64 size) { const wxString& path = Memory.ReadString(path_addr); sys_fs.Log("cellFsOpen(path=\"%s\", flags=0x%x, fd_addr=0x%x, arg_addr=0x%x, size=0x%llx)", path.wx_str(), flags, fd.GetAddr(), arg.GetAddr(), size); const wxString& ppath = path; //ConLog.Warning("path: %s [%s]", ppath.wx_str(), path.wx_str()); s32 _oflags = flags; if(flags & CELL_O_CREAT) { _oflags &= ~CELL_O_CREAT; Emu.GetVFS().CreateFile(ppath); } vfsOpenMode o_mode; switch(flags & CELL_O_ACCMODE) { case CELL_O_RDONLY: _oflags &= ~CELL_O_RDONLY; o_mode = vfsRead; break; case CELL_O_WRONLY: _oflags &= ~CELL_O_WRONLY; if(flags & CELL_O_APPEND) { _oflags &= ~CELL_O_APPEND; o_mode = vfsWriteAppend; } else if(flags & CELL_O_EXCL) { _oflags &= ~CELL_O_EXCL; o_mode = vfsWriteExcl; } else //if (flags & CELL_O_TRUNC) { _oflags &= ~CELL_O_TRUNC; o_mode = vfsWrite; } break; case CELL_O_RDWR: _oflags &= ~CELL_O_RDWR; if (flags & CELL_O_TRUNC) { _oflags &= ~CELL_O_TRUNC; //truncate file before opening it as read/write Emu.GetVFS().OpenFile(ppath, vfsWrite); } o_mode = vfsReadWrite; break; } if(_oflags != 0) { sys_fs.Error("\"%s\" has unknown flags! flags: 0x%08x", ppath.wx_str(), flags); return CELL_EINVAL; } vfsFileBase* stream = Emu.GetVFS().OpenFile(ppath, o_mode); if(!stream || !stream->IsOpened()) { sys_fs.Error("\"%s\" not found! flags: 0x%08x", ppath.wx_str(), flags); return CELL_ENOENT; } fd = sys_fs.GetNewId(stream, IDFlag_File); ConLog.Warning("*** cellFsOpen(path=\"%s\"): fd = %d", path.wx_str(), fd.GetValue()); return CELL_OK; }
int cellSysutilGetSystemParamInt(int id, mem32_t value) { cellSysutil->Log("cellSysutilGetSystemParamInt(id=0x%x, value_addr=0x%x)", id, value.GetAddr()); switch(id) { case CELL_SYSUTIL_SYSTEMPARAM_ID_LANG: cellSysutil->Warning("cellSysutilGetSystemParamInt: CELL_SYSUTIL_SYSTEMPARAM_ID_LANG"); value = Ini.SysLanguage.GetValue(); break; case CELL_SYSUTIL_SYSTEMPARAM_ID_ENTER_BUTTON_ASSIGN: cellSysutil->Warning("cellSysutilGetSystemParamInt: CELL_SYSUTIL_SYSTEMPARAM_ID_ENTER_BUTTON_ASSIGN"); value = CELL_SYSUTIL_ENTER_BUTTON_ASSIGN_CROSS; break; case CELL_SYSUTIL_SYSTEMPARAM_ID_DATE_FORMAT: cellSysutil->Warning("cellSysutilGetSystemParamInt: CELL_SYSUTIL_SYSTEMPARAM_ID_DATE_FORMAT"); value = CELL_SYSUTIL_DATE_FMT_DDMMYYYY; break; case CELL_SYSUTIL_SYSTEMPARAM_ID_TIME_FORMAT: cellSysutil->Warning("cellSysutilGetSystemParamInt: CELL_SYSUTIL_SYSTEMPARAM_ID_TIME_FORMAT"); value = CELL_SYSUTIL_TIME_FMT_CLOCK24; break; case CELL_SYSUTIL_SYSTEMPARAM_ID_TIMEZONE: cellSysutil->Warning("cellSysutilGetSystemParamInt: CELL_SYSUTIL_SYSTEMPARAM_ID_TIMEZONE"); value = 3; break; case CELL_SYSUTIL_SYSTEMPARAM_ID_SUMMERTIME: cellSysutil->Warning("cellSysutilGetSystemParamInt: CELL_SYSUTIL_SYSTEMPARAM_ID_SUMMERTIME"); value = 1; break; case CELL_SYSUTIL_SYSTEMPARAM_ID_GAME_PARENTAL_LEVEL: cellSysutil->Warning("cellSysutilGetSystemParamInt: CELL_SYSUTIL_SYSTEMPARAM_ID_GAME_PARENTAL_LEVEL"); value = CELL_SYSUTIL_GAME_PARENTAL_OFF; break; case CELL_SYSUTIL_SYSTEMPARAM_ID_GAME_PARENTAL_LEVEL0_RESTRICT: cellSysutil->Warning("cellSysutilGetSystemParamInt: CELL_SYSUTIL_SYSTEMPARAM_ID_GAME_PARENTAL_LEVEL0_RESTRICT"); value = CELL_SYSUTIL_GAME_PARENTAL_LEVEL0_RESTRICT_OFF; break; case CELL_SYSUTIL_SYSTEMPARAM_ID_CURRENT_USER_HAS_NP_ACCOUNT: cellSysutil->Warning("cellSysutilGetSystemParamInt: CELL_SYSUTIL_SYSTEMPARAM_ID_CURRENT_USER_HAS_NP_ACCOUNT"); value = 0; break; case CELL_SYSUTIL_SYSTEMPARAM_ID_CAMERA_PLFREQ: cellSysutil->Warning("cellSysutilGetSystemParamInt: CELL_SYSUTIL_SYSTEMPARAM_ID_CAMERA_PLFREQ"); value = CELL_SYSUTIL_CAMERA_PLFREQ_DISABLED; break; case CELL_SYSUTIL_SYSTEMPARAM_ID_PAD_RUMBLE: cellSysutil->Warning("cellSysutilGetSystemParamInt: CELL_SYSUTIL_SYSTEMPARAM_ID_PAD_RUMBLE"); value = CELL_SYSUTIL_PAD_RUMBLE_OFF; break; case CELL_SYSUTIL_SYSTEMPARAM_ID_KEYBOARD_TYPE: cellSysutil->Warning("cellSysutilGetSystemParamInt: CELL_SYSUTIL_SYSTEMPARAM_ID_KEYBOARD_TYPE"); value = 0; break; case CELL_SYSUTIL_SYSTEMPARAM_ID_JAPANESE_KEYBOARD_ENTRY_METHOD: cellSysutil->Warning("cellSysutilGetSystemParamInt: CELL_SYSUTIL_SYSTEMPARAM_ID_JAPANESE_KEYBOARD_ENTRY_METHOD"); value = 0; break; case CELL_SYSUTIL_SYSTEMPARAM_ID_CHINESE_KEYBOARD_ENTRY_METHOD: cellSysutil->Warning("cellSysutilGetSystemParamInt: CELL_SYSUTIL_SYSTEMPARAM_ID_CHINESE_KEYBOARD_ENTRY_METHOD"); value = 0; break; case CELL_SYSUTIL_SYSTEMPARAM_ID_PAD_AUTOOFF: cellSysutil->Warning("cellSysutilGetSystemParamInt: CELL_SYSUTIL_SYSTEMPARAM_ID_PAD_AUTOOFF"); value = 0; break; default: return CELL_EINVAL; } return CELL_OK; }
int cellFsGetDirectoryEntries(u32 fd, mem_ptr_t<CellFsDirectoryEntry> entries, u32 entries_size, mem32_t data_count) { sys_fs.Log("cellFsGetDirectoryEntries(fd=%d, entries_addr=0x%x, entries_size = 0x%x, data_count_addr=0x%x)", fd, entries.GetAddr(), entries_size, data_count.GetAddr()); vfsDirBase* directory; if(!sys_fs.CheckId(fd, directory)) return CELL_ESRCH; if(!entries.IsGood() || !data_count.IsGood()) return CELL_EFAULT; const DirEntryInfo* info = directory->Read(); if(info) { data_count = 1; Memory.WriteString(entries.GetAddr()+2, info->name.wx_str()); entries->entry_name.d_namlen = info->name.Length(); entries->entry_name.d_type = (info->flags & DirEntry_TypeFile) ? CELL_FS_TYPE_REGULAR : CELL_FS_TYPE_DIRECTORY; entries->attribute.st_mode = CELL_FS_S_IRUSR | CELL_FS_S_IWUSR | CELL_FS_S_IXUSR | CELL_FS_S_IRGRP | CELL_FS_S_IWGRP | CELL_FS_S_IXGRP | CELL_FS_S_IROTH | CELL_FS_S_IWOTH | CELL_FS_S_IXOTH; entries->attribute.st_uid = 0; entries->attribute.st_gid = 0; entries->attribute.st_atime_ = 0; //TODO entries->attribute.st_mtime_ = 0; //TODO entries->attribute.st_ctime_ = 0; //TODO entries->attribute.st_blksize = 4096; } else { data_count = 0; } return CELL_OK; }
//172 s32 sys_spu_thread_initialize(mem32_t thread, u32 group, u32 spu_num, mem_ptr_t<sys_spu_image> img, mem_ptr_t<sys_spu_thread_attribute> attr, mem_ptr_t<sys_spu_thread_argument> arg) { sc_spu.Warning("sys_spu_thread_initialize(thread_addr=0x%x, group=0x%x, spu_num=%d, img_addr=0x%x, attr_addr=0x%x, arg_addr=0x%x)", thread.GetAddr(), group, spu_num, img.GetAddr(), attr.GetAddr(), arg.GetAddr()); SpuGroupInfo* group_info; if(!Emu.GetIdManager().GetIDData(group, group_info)) { return CELL_ESRCH; } if(!thread.IsGood() || !img.IsGood() || !attr.IsGood() || !arg.IsGood()) { return CELL_EFAULT; } if (attr->name_addr) { if(!Memory.IsGoodAddr(attr->name_addr, attr->name_len)) { return CELL_EFAULT; } } if(spu_num >= group_info->list.size()) { return CELL_EINVAL; } if(group_info->list[spu_num]) { return CELL_EBUSY; } u32 spu_ep = (u32)img->entry_point; std::string name = "SPUThread"; if (attr->name_addr) { name = Memory.ReadString(attr->name_addr, attr->name_len); } u64 a1 = arg->arg1; u64 a2 = arg->arg2; u64 a3 = arg->arg3; u64 a4 = arg->arg4; //copy SPU image: auto spu_offset = Memory.MainMem.AllocAlign(256 * 1024); if (!Memory.Copy(spu_offset, (u32)img->segs_addr, 256 * 1024)) { return CELL_EFAULT; } CPUThread& new_thread = Emu.GetCPU().AddThread(CPU_THREAD_SPU); //initialize from new place: new_thread.SetOffset(spu_offset); new_thread.SetEntry(spu_ep); new_thread.SetName(name); new_thread.SetArg(0, a1); new_thread.SetArg(1, a2); new_thread.SetArg(2, a3); new_thread.SetArg(3, a4); new_thread.Run(); thread = group_info->list[spu_num] = new_thread.GetId(); (*(SPUThread*)&new_thread).group = group_info; sc_spu.Warning("*** New SPU Thread [%s] (img_offset=0x%x, ls_offset=0x%x, ep=0x%x, a1=0x%llx, a2=0x%llx, a3=0x%llx, a4=0x%llx): id=%d", (attr->name_addr ? name.c_str() : ""), (u32) img->segs_addr, ((SPUThread&) new_thread).dmac.ls_offset, spu_ep, a1, a2, a3, a4, thread.GetValue()); return CELL_OK; }
s32 sys_raw_spu_create_interrupt_tag(u32 id, u32 class_id, u32 hwthread, mem32_t intrtag) { sc_spu.Error("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; }
s32 sys_spu_thread_create(mem32_t thread_id, mem32_t entry, u64 arg, int prio, u32 stacksize, u64 flags, u32 threadname_addr) { sc_spu.Error("sys_spu_thread_create(thread_id_addr=0x%x, entry_addr=0x%x, arg=0x%llx, prio=%d, stacksize=0x%x, flags=0x%llx, threadname_addr=0x%x", thread_id.GetAddr(), entry.GetAddr(), arg, prio, stacksize, flags, threadname_addr); 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; }
//178 s32 sys_spu_thread_group_join(u32 id, mem32_t cause, mem32_t status) { sc_spu.Warning("sys_spu_thread_group_join(id=%d, cause_addr=0x%x, status_addr=0x%x)", id, cause.GetAddr(), status.GetAddr()); SpuGroupInfo* group_info; if(!Emu.GetIdManager().GetIDData(id, group_info)) { return CELL_ESRCH; } if (group_info->lock.exchange(1)) // acquire lock { return CELL_EBUSY; } cause = SYS_SPU_THREAD_GROUP_JOIN_ALL_THREADS_EXIT; status = 0; //unspecified because of ALL_THREADS_EXIT for (u32 i = 0; i < group_info->list.size(); i++) { while (CPUThread* t = Emu.GetCPU().GetThread(group_info->list[i])) { if (!t->IsRunning()) { break; } if (Emu.IsStopped()) { LOG_WARNING(Log::SPU, "sys_spu_thread_group_join(id=%d, ...) aborted", id); return CELL_OK; } std::this_thread::sleep_for(std::chrono::milliseconds(1)); } } group_info->lock = 0; // release lock return CELL_OK; }