//128 int sys_event_queue_create(mem32_t equeue_id, mem_ptr_t<sys_event_queue_attr> attr, u64 event_queue_key, int size) { sys_event.Warning("sys_event_queue_create(equeue_id_addr=0x%x, attr_addr=0x%x, event_queue_key=0x%llx, size=%d)", equeue_id.GetAddr(), attr.GetAddr(), event_queue_key, size); if(size <= 0 || size > 127) { return CELL_EINVAL; } if(!equeue_id.IsGood() || !attr.IsGood()) { return CELL_EFAULT; } switch (attr->protocol.ToBE()) { case se32(SYS_SYNC_PRIORITY): break; case se32(SYS_SYNC_RETRY): sys_event.Error("Invalid SYS_SYNC_RETRY protocol attr"); return CELL_EINVAL; case se32(SYS_SYNC_PRIORITY_INHERIT): sys_event.Error("Invalid SYS_SYNC_PRIORITY_INHERIT protocol attr"); return CELL_EINVAL; case se32(SYS_SYNC_FIFO): break; default: sys_event.Error("Unknown 0x%x protocol attr", (u32)attr->protocol); return CELL_EINVAL; } switch (attr->type.ToBE()) { case se32(SYS_PPU_QUEUE): break; case se32(SYS_SPU_QUEUE): break; default: sys_event.Error("Unknown 0x%x type attr", (u32)attr->type); return CELL_EINVAL; } if (event_queue_key && Emu.GetEventManager().CheckKey(event_queue_key)) { return CELL_EEXIST; } EventQueue* eq = new EventQueue((u32)attr->protocol, (int)attr->type, attr->name_u64, event_queue_key, size); if (event_queue_key && !Emu.GetEventManager().RegisterKey(eq, event_queue_key)) { delete eq; return CELL_EAGAIN; } equeue_id = sys_event.GetNewId(eq); sys_event.Warning("*** event_queue created [%s] (protocol=0x%x, type=0x%x): id = %d", wxString(attr->name, 8).wx_str(), (u32)attr->protocol, (int)attr->type, equeue_id.GetValue()); 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; }
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 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; }
//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 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; }
//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; }
int sys_cond_create(mem32_t cond_id, u32 mutex_id, mem_ptr_t<sys_cond_attribute> attr) { sys_cond.Log("sys_cond_create(cond_id_addr=0x%x, mutex_id=%d, attr_addr=0x%x)", cond_id.GetAddr(), mutex_id, attr.GetAddr()); if (!cond_id.IsGood() || !attr.IsGood()) { return CELL_EFAULT; } if (attr->pshared.ToBE() != se32(0x200)) { sys_cond.Error("Invalid pshared attribute(0x%x)", (u32)attr->pshared); return CELL_EINVAL; } Mutex* mutex; if (!Emu.GetIdManager().GetIDData(mutex_id, mutex)) { return CELL_ESRCH; } if (mutex->is_recursive) { sys_cond.Warning("*** condition on recursive mutex(%d)", mutex_id); } Cond* cond = new Cond(mutex, attr->name_u64); u32 id = sys_cond.GetNewId(cond); cond_id = id; mutex->cond_count++; sys_cond.Warning("*** condition created [%s] (mutex_id=%d): id = %d", wxString(attr->name, 8).wx_str(), mutex_id, cond_id.GetValue()); return CELL_OK; }