s32 sceNpTrophyGetTrophyUnlockState(u32 context, u32 handle, vm::ptr<SceNpTrophyFlagArray> flags, vm::ptr<u32> count) { sceNpTrophy.error("sceNpTrophyGetTrophyUnlockState(context=0x%x, handle=0x%x, flags=*0x%x, count=*0x%x)", context, handle, flags, count); const auto ctxt = idm::get<trophy_context_t>(context); if (!ctxt) { return SCE_NP_TROPHY_ERROR_UNKNOWN_CONTEXT; } const auto hndl = idm::get<trophy_handle_t>(handle); if (!hndl) { return SCE_NP_TROPHY_ERROR_UNKNOWN_HANDLE; } u32 count_ = ctxt->tropusr->GetTrophiesCount(); *count = count_; if (count_ > 128) sceNpTrophy.error("sceNpTrophyGetTrophyUnlockState: More than 128 trophies detected!"); // Pack up to 128 bools in u32 flag_bits[4] for (u32 id = 0; id < count_; id++) { if (ctxt->tropusr->GetTrophyUnlockState(id)) flags->flag_bits[id/32] |= 1<<(id%32); else flags->flag_bits[id/32] &= ~(1<<(id%32)); } return CELL_OK; }
s32 pngDecClose(PPUThread& ppu, PHandle handle, PStream stream) { // Remove the file descriptor, if a file descriptor was used for decoding if (stream->buffer->file) { idm::remove<lv2_file_t>(stream->buffer->fd); } // Deallocate the PNG buffer structure used to decode from memory, if we decoded from memory if (stream->buffer) { if (handle->free(ppu, stream->buffer, handle->free_arg) != 0) { cellPngDec.error("PNG buffer decoding structure deallocation failed."); return CELL_PNGDEC_ERROR_FATAL; } } // Free the memory allocated by libpng png_destroy_read_struct(&stream->png_ptr, &stream->info_ptr, nullptr); // Deallocate the stream memory if (handle->free(ppu, stream, handle->free_arg) != 0) { cellPngDec.error("PNG stream deallocation failed."); return CELL_PNGDEC_ERROR_FATAL; } return CELL_OK; }
s32 sys_semaphore_create(vm::ptr<u32> sem_id, vm::ptr<sys_semaphore_attribute_t> attr, s32 initial_val, s32 max_val) { sys_semaphore.warning("sys_semaphore_create(sem_id=*0x%x, attr=*0x%x, initial_val=%d, max_val=%d)", sem_id, attr, initial_val, max_val); if (!sem_id || !attr) { return CELL_EFAULT; } if (max_val <= 0 || initial_val > max_val || initial_val < 0) { sys_semaphore.error("sys_semaphore_create(): invalid parameters (initial_val=%d, max_val=%d)", initial_val, max_val); return CELL_EINVAL; } const u32 protocol = attr->protocol; if (protocol != SYS_SYNC_FIFO && protocol != SYS_SYNC_PRIORITY && protocol != SYS_SYNC_PRIORITY_INHERIT) { sys_semaphore.error("sys_semaphore_create(): unknown protocol (0x%x)", protocol); return CELL_EINVAL; } if (attr->pshared != SYS_SYNC_NOT_PROCESS_SHARED || attr->ipc_key || attr->flags) { sys_semaphore.error("sys_semaphore_create(): unknown attributes (pshared=0x%x, ipc_key=0x%x, flags=0x%x)", attr->pshared, attr->ipc_key, attr->flags); return CELL_EINVAL; } *sem_id = idm::make<lv2_sema_t>(protocol, max_val, attr->name_u64, initial_val); return CELL_OK; }
error_code sys_event_queue_create(vm::ptr<u32> equeue_id, vm::ptr<sys_event_queue_attribute_t> attr, u64 event_queue_key, s32 size) { sys_event.warning("sys_event_queue_create(equeue_id=*0x%x, attr=*0x%x, event_queue_key=0x%llx, size=%d)", equeue_id, attr, event_queue_key, size); if (size <= 0 || size > 127) { return CELL_EINVAL; } const u32 protocol = attr->protocol; if (protocol != SYS_SYNC_FIFO && protocol != SYS_SYNC_PRIORITY) { sys_event.error("sys_event_queue_create(): unknown protocol (0x%x)", protocol); return CELL_EINVAL; } const u32 type = attr->type; if (type != SYS_PPU_QUEUE && type != SYS_SPU_QUEUE) { sys_event.error("sys_event_queue_create(): unknown type (0x%x)", type); return CELL_EINVAL; } if (event_queue_key == SYS_EVENT_QUEUE_LOCAL) { // Not an IPC queue if (const u32 _id = idm::make<lv2_obj, lv2_event_queue>(protocol, type, attr->name_u64, event_queue_key, size)) { *equeue_id = _id; return CELL_OK; } return CELL_EAGAIN; } std::shared_ptr<lv2_event_queue> result; // Create IPC queue if (!ipc_manager<lv2_event_queue, u64>::add(event_queue_key, [&]() -> const std::shared_ptr<lv2_event_queue>& { result = idm::make_ptr<lv2_obj, lv2_event_queue>(protocol, type, attr->name_u64, event_queue_key, size); return result; })) { return CELL_EEXIST; } if (result) { *equeue_id = idm::last_id(); return CELL_OK; } return CELL_EAGAIN; }
s32 cellSaveDataUserAutoLoad(ppu_thread& ppu, u32 version, u32 userId, vm::cptr<char> dirName, u32 errDialog, PSetBuf setBuf, PFuncStat funcStat, PFuncFile funcFile, u32 container, vm::ptr<void> userdata) { cellSaveData.error("cellSaveDataUserAutoLoad(version=%d, userId=%d, dirName=%s, errDialog=%d, setBuf=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x, userdata=*0x%x)", version, userId, dirName, errDialog, setBuf, funcStat, funcFile, container, userdata); return savedata_op(ppu, SAVEDATA_OP_AUTO_LOAD, version, dirName, errDialog, vm::null, setBuf, vm::null, vm::null, funcStat, funcFile, container, 6, userdata, userId, vm::null); }
s32 sys_process_get_number_of_object(u32 object, vm::ptr<u32> nump) { sys_process.error("sys_process_get_number_of_object(object=0x%x, nump=*0x%x)", object, nump); switch(object) { case SYS_MEM_OBJECT: *nump = idm_get_count<lv2_obj, lv2_memory>(); break; case SYS_MUTEX_OBJECT: *nump = idm_get_count<lv2_obj, lv2_mutex>(); break; case SYS_COND_OBJECT: *nump = idm_get_count<lv2_obj, lv2_cond>(); break; case SYS_RWLOCK_OBJECT: *nump = idm_get_count<lv2_obj, lv2_rwlock>(); break; case SYS_INTR_TAG_OBJECT: *nump = idm_get_count<lv2_obj, lv2_int_tag>(); break; case SYS_INTR_SERVICE_HANDLE_OBJECT: *nump = idm_get_count<lv2_obj, lv2_int_serv>(); break; case SYS_EVENT_QUEUE_OBJECT: *nump = idm_get_count<lv2_obj, lv2_event_queue>(); break; case SYS_EVENT_PORT_OBJECT: *nump = idm_get_count<lv2_obj, lv2_event_port>(); break; case SYS_TRACE_OBJECT: fmt::throw_exception("SYS_TRACE_OBJECT" HERE); case SYS_SPUIMAGE_OBJECT: fmt::throw_exception("SYS_SPUIMAGE_OBJECT" HERE); case SYS_PRX_OBJECT: *nump = idm_get_count<lv2_obj, lv2_prx>(); break; case SYS_SPUPORT_OBJECT: fmt::throw_exception("SYS_SPUPORT_OBJECT" HERE); case SYS_LWMUTEX_OBJECT: *nump = idm_get_count<lv2_obj, lv2_lwmutex>(); break; case SYS_TIMER_OBJECT: *nump = idm_get_count<lv2_obj, lv2_timer>(); break; case SYS_SEMAPHORE_OBJECT: *nump = idm_get_count<lv2_obj, lv2_sema>(); break; case SYS_FS_FD_OBJECT: *nump = idm_get_count<lv2_fs_object, lv2_fs_object>(); break; case SYS_LWCOND_OBJECT: *nump = idm_get_count<lv2_obj, lv2_lwcond>(); break; case SYS_EVENT_FLAG_OBJECT: *nump = idm_get_count<lv2_obj, lv2_event_flag>(); break; default: { return CELL_EINVAL; } } return CELL_OK; }
error_code sys_vm_memory_map(u32 vsize, u32 psize, u32 cid, u64 flag, u64 policy, vm::ptr<u32> addr) { sys_vm.error("sys_vm_memory_map(vsize=0x%x, psize=0x%x, cid=0x%x, flags=0x%llx, policy=0x%llx, addr=*0x%x)", vsize, psize, cid, flag, policy, addr); if (!vsize || !psize || vsize % 0x2000000 || vsize > 0x10000000 || psize > 0x10000000 || policy != SYS_VM_POLICY_AUTO_RECOMMENDED) { return CELL_EINVAL; } if (cid != SYS_MEMORY_CONTAINER_ID_INVALID && !idm::check<lv2_memory_container>(cid)) { return CELL_ESRCH; } // Look for unmapped space (roughly) for (u32 found = 0x60000000; found <= 0xC0000000 - vsize; found += 0x2000000) { // Try to map if (const auto area = vm::map(found, vsize, flag)) { // Alloc all memory (shall not fail) verify(HERE), area->alloc(vsize); // Write a pointer for the allocated memory *addr = found; return CELL_OK; } } return CELL_ENOMEM; }
error_code sys_mmapper_search_and_map(u32 start_addr, u32 mem_id, u64 flags, vm::ptr<u32> alloc_addr) { sys_mmapper.error("sys_mmapper_search_and_map(start_addr=0x%x, mem_id=0x%x, flags=0x%llx, alloc_addr=*0x%x)", start_addr, mem_id, flags, alloc_addr); const auto area = vm::get(vm::any, start_addr); if (!area || start_addr != area->addr || start_addr < 0x30000000 || start_addr >= 0xC0000000) { return CELL_EINVAL; } const auto mem = idm::get<lv2_memory>(mem_id); if (!mem) { return CELL_ESRCH; } if (const u32 old_addr = mem->addr.compare_and_swap(0, -1)) { sys_mmapper.warning("sys_mmapper_search_and_map(): Already mapped (mem_id=0x%x, addr=0x%x)", mem_id, old_addr); return CELL_OK; } const u32 addr = area->alloc(mem->size, mem->align); if (!addr) { mem->addr = 0; return CELL_ENOMEM; } *alloc_addr = mem->addr = addr; return CELL_OK; }
s32 pngDecCreate(PPUThread& ppu, PPHandle png_handle, PThreadInParam thread_in_param, PThreadOutParam thread_out_param, PExtThreadInParam extra_thread_in_param = vm::null, PExtThreadOutParam extra_thread_out_param = vm::null) { // Check if partial image decoding is used if (extra_thread_out_param) { throw EXCEPTION("Partial image decoding is not supported."); } // Allocate memory for the decoder handle auto handle = vm::ptr<PngHandle>::make(thread_in_param->cbCtrlMallocFunc(ppu, sizeof(PngHandle), thread_in_param->cbCtrlMallocArg).addr()); // Check if the memory allocation for the handle failed if (!handle) { cellPngDec.error("PNG decoder creation failed."); return CELL_PNGDEC_ERROR_FATAL; } // Set the allocation functions in the handle handle->malloc = thread_in_param->cbCtrlMallocFunc; handle->malloc_arg = thread_in_param->cbCtrlMallocArg; handle->free = thread_in_param->cbCtrlFreeFunc; handle->free_arg = thread_in_param->cbCtrlFreeArg; // Set handle pointer *png_handle = handle; // Set the version information thread_out_param->pngCodecVersion = PNGDEC_CODEC_VERSION; return CELL_OK; }
s32 cellSysmoduleUnloadModule(u16 id) { cellSysmodule.warning("cellSysmoduleUnloadModule(id=%s)", get_module_id(id)); const auto name = get_module_name(id); if (!name) { cellSysmodule.error("cellSysmoduleUnloadModule() failed: unknown module 0x%04X", id); return CELL_SYSMODULE_ERROR_UNKNOWN; } //if (Module<>* m = Emu.GetModuleManager().GetModuleById(id)) //{ // if (!m->IsLoaded()) // { // cellSysmodule.error("cellSysmoduleUnloadModule() failed: module not loaded (id=0x%04x)", id); // return CELL_SYSMODULE_ERROR_FATAL; // } // m->Unload(); //} return CELL_OK; }
s32 sys_raw_spu_load(s32 id, vm::cptr<char> path, vm::ptr<u32> entry) { sysPrxForUser.warning("sys_raw_spu_load(id=%d, path=*0x%x, entry=*0x%x)", id, path, entry); sysPrxForUser.warning("*** path = '%s'", path.get_ptr()); const fs::file f(vfs::get(path.get_ptr())); if (!f) { sysPrxForUser.error("sys_raw_spu_load() error: '%s' not found!", path.get_ptr()); return CELL_ENOENT; } SceHeader hdr; hdr.Load(f); if (hdr.CheckMagic()) { throw fmt::exception("sys_raw_spu_load() error: '%s' is encrypted! Try to decrypt it manually and try again.", path.get_ptr()); } f.seek(0); u32 _entry; LoadSpuImage(f, _entry, RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * id); *entry = _entry | 1; return CELL_OK; }
error_code sys_fs_ftruncate(u32 fd, u64 size) { sys_fs.warning("sys_fs_ftruncate(fd=%d, size=0x%llx)", fd, size); const auto file = idm::get<lv2_file>(fd); if (!file || !(file->flags & CELL_FS_O_ACCMODE)) { return CELL_EBADF; } std::lock_guard<std::mutex> lock(file->mp->mutex); if (!file->file.trunc(size)) { switch (auto error = fs::g_tls_error) { case fs::error::ok: default: sys_fs.error("sys_fs_ftruncate(): unknown error %s", error); } return CELL_EIO; // ??? } return CELL_OK; }
error_code sys_fs_stat(vm::cptr<char> path, vm::ptr<CellFsStat> sb) { sys_fs.warning("sys_fs_stat(path=%s, sb=*0x%x)", path, sb); const std::string& local_path = vfs::get(path.get_ptr()); if (local_path.empty()) { sys_fs.warning("sys_fs_stat(%s) failed: not mounted", path); return CELL_ENOTMOUNTED; } fs::stat_t info; if (!fs::stat(local_path, info)) { sys_fs.error("sys_fs_stat(%s) failed: not found", path); return CELL_ENOENT; } sb->mode = info.is_directory ? CELL_FS_S_IFDIR | 0777 : CELL_FS_S_IFREG | 0666; sb->uid = 1; // ??? sb->gid = 1; // ??? sb->atime = info.atime; sb->mtime = info.mtime; sb->ctime = info.ctime; sb->size = info.size; sb->blksize = 4096; // ??? return CELL_OK; }
error_code sys_mmapper_unmap_shared_memory(u32 addr, vm::ptr<u32> mem_id) { sys_mmapper.error("sys_mmapper_unmap_shared_memory(addr=0x%x, mem_id=*0x%x)", addr, mem_id); const auto area = vm::get(vm::any, addr); if (!area || addr != area->addr || addr < 0x30000000 || addr >= 0xC0000000) { return CELL_EINVAL; } const auto mem = idm::select<lv2_memory>([&](u32 id, lv2_memory& mem) { if (mem.addr == addr) { *mem_id = id; return true; } return false; }); if (!mem) { return CELL_EINVAL; } verify(HERE), area->dealloc(addr), mem->addr.exchange(0) == addr; return CELL_OK; }
s32 sceNpTrophyUnlockTrophy(u32 context, u32 handle, s32 trophyId, vm::ptr<u32> platinumId) { sceNpTrophy.error("sceNpTrophyUnlockTrophy(context=0x%x, handle=0x%x, trophyId=%d, platinumId=*0x%x)", context, handle, trophyId, platinumId); const auto ctxt = idm::get<trophy_context_t>(context); if (!ctxt) { return SCE_NP_TROPHY_ERROR_UNKNOWN_CONTEXT; } const auto hndl = idm::get<trophy_handle_t>(handle); if (!hndl) { return SCE_NP_TROPHY_ERROR_UNKNOWN_HANDLE; } 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; ctxt->tropusr->UnlockTrophy(trophyId, 0, 0); // TODO 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; }
s32 cellSaveDataUserListAutoLoad(ppu_thread& ppu, u32 version, u32 userId, u32 errDialog, PSetList setList, PSetBuf setBuf, PFuncFixed funcFixed, PFuncStat funcStat, PFuncFile funcFile, u32 container, vm::ptr<void> userdata) { cellSaveData.error("cellSaveDataUserListAutoLoad(version=%d, userId=%d, errDialog=%d, setList=*0x%x, setBuf=*0x%x, funcFixed=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x, userdata=*0x%x)", version, userId, errDialog, setList, setBuf, funcFixed, funcStat, funcFile, container, userdata); return savedata_op(ppu, SAVEDATA_OP_LIST_AUTO_LOAD, version, vm::null, errDialog, setList, setBuf, vm::null, funcFixed, funcStat, funcFile, container, 6, userdata, userId, vm::null); }
s32 sys_spu_thread_disconnect_event(u32 id, u32 et, u8 spup) { sys_spu.warning("sys_spu_thread_disconnect_event(id=0x%x, et=%d, spup=%d)", id, et, spup); LV2_LOCK; const auto thread = idm::get<SPUThread>(id); if (!thread) { return CELL_ESRCH; } if (et != SYS_SPU_THREAD_EVENT_USER || spup > 63) { sys_spu.error("sys_spu_thread_disconnect_event(): invalid arguments (et=%d, spup=%d)", et, spup); return CELL_EINVAL; } auto& port = thread->spup[spup]; if (port.expired()) { return CELL_ENOTCONN; } port.reset(); return CELL_OK; }
s32 cellSaveDataUserFixedSave(ppu_thread& ppu, u32 version, u32 userId, PSetList setList, PSetBuf setBuf, PFuncFixed funcFixed, PFuncStat funcStat, PFuncFile funcFile, u32 container, vm::ptr<void> userdata) { cellSaveData.error("cellSaveDataUserFixedSave(version=%d, userId=%d, setList=*0x%x, setBuf=*0x%x, funcFixed=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x, userdata=*0x%x)", version, userId, setList, setBuf, funcFixed, funcStat, funcFile, container, userdata); return savedata_op(ppu, SAVEDATA_OP_FIXED_SAVE, version, vm::null, 0, setList, setBuf, vm::null, funcFixed, funcStat, funcFile, container, 6, userdata, userId, vm::null); }
s32 sys_spu_thread_connect_event(u32 id, u32 eq, u32 et, u8 spup) { sys_spu.warning("sys_spu_thread_connect_event(id=0x%x, eq=0x%x, et=%d, spup=%d)", id, eq, et, spup); LV2_LOCK; const auto thread = idm::get<SPUThread>(id); const auto queue = idm::get<lv2_event_queue_t>(eq); if (!thread || !queue) { return CELL_ESRCH; } if (et != SYS_SPU_THREAD_EVENT_USER || spup > 63 || queue->type != SYS_PPU_QUEUE) { sys_spu.error("sys_spu_thread_connect_event(): invalid arguments (et=%d, spup=%d, queue->type=%d)", et, spup, queue->type); return CELL_EINVAL; } auto& port = thread->spup[spup]; if (!port.expired()) { return CELL_EISCONN; } port = queue; return CELL_OK; }
s32 sys_spu_image_open(vm::ptr<sys_spu_image_t> img, vm::cptr<char> path) { sys_spu.warning("sys_spu_image_open(img=*0x%x, path=*0x%x)", img, path); const fs::file f(vfs::get(path.get_ptr())); if (!f) { sys_spu.error("sys_spu_image_open() error: '%s' not found!", path.get_ptr()); return CELL_ENOENT; } SceHeader hdr; hdr.Load(f); if (hdr.CheckMagic()) { throw fmt::exception("sys_spu_image_open() error: '%s' is encrypted! Try to decrypt it manually and try again.", path.get_ptr()); } f.seek(0); u32 entry; u32 offset = LoadSpuImage(f, entry); img->type = SYS_SPU_IMAGE_TYPE_USER; img->entry_point = entry; img->segs.set(offset); // TODO: writing actual segment info img->nsegs = 1; // wrong value return CELL_OK; }
std::string getCert(const std::string certPath, const int certID, const bool isNormalCert) { int newID = certID; // The 'normal' certs have some special rules for loading. if (isNormalCert && certID >= BaltimoreCert && certID <= GTECyberTrustGlobalCert) { if (certID == BaltimoreCert) newID = GTECyberTrustGlobalCert; else if (certID == Class3G2V2Cert) newID = BaltimoreCert; else if (certID == EntrustNetCert) newID = ClassSSV4Cert; else newID = certID - 1; } std::string filePath = fmt::format("%sCA%02d.cer", certPath, newID); if (!fs::exists(filePath)) { cellSsl.error("Can't find certificate file %s, do you have the PS3 firmware installed?", filePath); return ""; } return fs::file(filePath).to_string(); }
error_code sys_mmapper_allocate_shared_memory_from_container(u64 unk, u32 size, u32 cid, u64 flags, vm::ptr<u32> mem_id) { sys_mmapper.error("sys_mmapper_allocate_shared_memory_from_container(0x%llx, size=0x%x, cid=0x%x, flags=0x%llx, mem_id=*0x%x)", unk, size, cid, flags, mem_id); // Check page granularity. switch (flags & SYS_MEMORY_PAGE_SIZE_MASK) { case SYS_MEMORY_PAGE_SIZE_1M: { if (size % 0x100000) { return CELL_EALIGN; } break; } case SYS_MEMORY_PAGE_SIZE_64K: { if (size % 0x10000) { return CELL_EALIGN; } break; } default: { return CELL_EINVAL; } } const auto ct = idm::get<lv2_memory_container>(cid, [&](lv2_memory_container& ct) -> CellError { // Try to get "physical memory" if (!ct.take(size)) { return CELL_ENOMEM; } return {}; }); if (!ct) { return CELL_ESRCH; } if (ct.value) { return ct.value; } // Generate a new mem ID *mem_id = idm::make<lv2_memory>(size, flags & SYS_MEMORY_PAGE_SIZE_1M ? 0x100000 : 0x10000, flags, ct.ptr); return CELL_OK; }
error_code cellGameCreateGameData(vm::ptr<CellGameSetInitParams> init, vm::ptr<char[CELL_GAME_PATH_MAX]> tmp_contentInfoPath, vm::ptr<char[CELL_GAME_PATH_MAX]> tmp_usrdirPath) { cellGame.error("cellGameCreateGameData(init=*0x%x, tmp_contentInfoPath=*0x%x, tmp_usrdirPath=*0x%x)", init, tmp_contentInfoPath, tmp_usrdirPath); const auto prm = fxm::get<content_permission>(); if (!prm || prm->dir.empty()) { return CELL_GAME_ERROR_FAILURE; } std::string tmp_contentInfo = "/dev_hdd1/game/" + prm->dir; std::string tmp_usrdir = "/dev_hdd1/game/" + prm->dir + "/USRDIR"; if (!fs::create_dir(vfs::get(tmp_contentInfo))) { cellGame.error("cellGameCreateGameData(): failed to create directory '%s'", tmp_contentInfo); return CELL_GAME_ERROR_ACCESS_ERROR; // ??? } if (!fs::create_dir(vfs::get(tmp_usrdir))) { cellGame.error("cellGameCreateGameData(): failed to create directory '%s'", tmp_usrdir); return CELL_GAME_ERROR_ACCESS_ERROR; // ??? } // cellGameContentPermit should then move files in non-temporary location and return their non-temporary displacement strcpy_trunc(*tmp_contentInfoPath, tmp_contentInfo); strcpy_trunc(*tmp_usrdirPath, tmp_usrdir); prm->temp = vfs::get(tmp_contentInfo); cellGame.success("cellGameCreateGameData(): temporary directory '%s' has been created", tmp_contentInfo); // Initial PARAM.SFO parameters (overwrite) prm->sfo = { { "CATEGORY", psf::string(3, "GD") }, { "TITLE_ID", psf::string(CELL_GAME_SYSP_TITLEID_SIZE, init->titleId) }, { "TITLE", psf::string(CELL_GAME_SYSP_TITLE_SIZE, init->title) }, { "VERSION", psf::string(CELL_GAME_SYSP_VERSION_SIZE, init->version) }, }; return CELL_OK; }
error_code sys_lwmutex_create(vm::ptr<sys_lwmutex_t> lwmutex, vm::ptr<sys_lwmutex_attribute_t> attr) { sysPrxForUser.trace("sys_lwmutex_create(lwmutex=*0x%x, attr=*0x%x)", lwmutex, attr); const u32 recursive = attr->recursive; if (recursive != SYS_SYNC_RECURSIVE && recursive != SYS_SYNC_NOT_RECURSIVE) { sysPrxForUser.error("sys_lwmutex_create(): invalid recursive attribute (0x%x)", recursive); return CELL_EINVAL; } const u32 protocol = attr->protocol; switch (protocol) { case SYS_SYNC_FIFO: break; case SYS_SYNC_RETRY: break; case SYS_SYNC_PRIORITY: break; default: sysPrxForUser.error("sys_lwmutex_create(): invalid protocol (0x%x)", protocol); return CELL_EINVAL; } vm::var<u32> out_id; vm::var<sys_mutex_attribute_t> attrs; attrs->protocol = protocol == SYS_SYNC_FIFO ? SYS_SYNC_FIFO : SYS_SYNC_PRIORITY; attrs->recursive = attr->recursive; attrs->pshared = SYS_SYNC_NOT_PROCESS_SHARED; attrs->adaptive = SYS_SYNC_NOT_ADAPTIVE; attrs->ipc_key = 0; attrs->flags = 0; attrs->name_u64 = attr->name_u64; if (error_code res = g_cfg.core.hle_lwmutex ? sys_mutex_create(out_id, attrs) : _sys_lwmutex_create(out_id, protocol, lwmutex, 0x80000001, attr->name_u64)) { return res; } lwmutex->lock_var.store({ lwmutex_free, 0 }); lwmutex->attribute = attr->recursive | attr->protocol; lwmutex->recursive_count = 0; lwmutex->sleep_queue = *out_id; return CELL_OK; }
s32 sys_spu_thread_group_connect_event(u32 id, u32 eq, u32 et) { sys_spu.warning("sys_spu_thread_group_connect_event(id=0x%x, eq=0x%x, et=%d)", id, eq, et); LV2_LOCK; const auto group = idm::get<lv2_spu_group_t>(id); const auto queue = idm::get<lv2_event_queue_t>(eq); if (!group || !queue) { return CELL_ESRCH; } switch (et) { case SYS_SPU_THREAD_GROUP_EVENT_RUN: { if (!group->ep_run.expired()) { return CELL_EBUSY; } group->ep_run = queue; break; } case SYS_SPU_THREAD_GROUP_EVENT_EXCEPTION: { if (!group->ep_exception.expired()) { return CELL_EBUSY; } group->ep_exception = queue; break; } case SYS_SPU_THREAD_GROUP_EVENT_SYSTEM_MODULE: { if (!group->ep_sysmodule.expired()) { return CELL_EBUSY; } group->ep_sysmodule = queue; break; } default: { sys_spu.error("sys_spu_thread_group_connect_event(): unknown event type (%d)", et); return CELL_EINVAL; } } return CELL_OK; }
error_code sys_mmapper_allocate_fixed_address() { sys_mmapper.error("sys_mmapper_allocate_fixed_address()"); if (!vm::map(0xB0000000, 0x10000000)) // TODO: set correct flags (they aren't used currently though) { return CELL_EEXIST; } return CELL_OK; }
error_code sys_mmapper_allocate_fixed_address() { sys_mmapper.error("sys_mmapper_allocate_fixed_address()"); if (!vm::map(0xB0000000, 0x10000000, SYS_MEMORY_PAGE_SIZE_1M)) { return CELL_EEXIST; } return CELL_OK; }
s32 cellSailPlayerGetParameter(vm::ptr<CellSailPlayer> pSelf, s32 parameterType, vm::ptr<u64> pParam0, vm::ptr<u64> pParam1) { cellSail.todo("cellSailPlayerGetParameter(pSelf=*0x%x, parameterType=0x%x, param0=*0x%x, param1=*0x%x)", pSelf, parameterType, pParam0, pParam1); switch (parameterType) { default: cellSail.error("cellSailPlayerGetParameter(): unimplemented parameter %s", ParameterCodeToName(parameterType)); } return CELL_OK; }
s32 pngDecDestroy(PPUThread& ppu, PHandle handle) { // Deallocate the decoder handle memory if (handle->free(ppu, handle, handle->free_arg) != 0) { cellPngDec.error("PNG decoder deallocation failed."); return CELL_PNGDEC_ERROR_FATAL; } return CELL_OK; }
error_code sys_fs_opendir(vm::cptr<char> path, vm::ptr<u32> fd) { sys_fs.warning("sys_fs_opendir(path=%s, fd=*0x%x)", path, fd); const std::string& local_path = vfs::get(path.get_ptr()); if (local_path.empty()) { sys_fs.error("sys_fs_opendir(%s) failed: device not mounted", path); return CELL_ENOTMOUNTED; } // TODO: other checks for path if (fs::is_file(local_path)) { sys_fs.error("sys_fs_opendir(%s) failed: path is a file", path); return CELL_ENOTDIR; } fs::dir dir(local_path); if (!dir) { sys_fs.error("sys_fs_opendir(%s): failed to open directory", path); return CELL_ENOENT; } const auto _dir = idm::make_ptr<lv2_dir>(path.get_ptr(), std::move(dir)); if (!_dir) { // out of file descriptors return CELL_EMFILE; } *fd = _dir->id; sys_fs.notice("sys_fs_opendir(%s) -> lv2_fs_id %d", path, _dir->id); return CELL_OK; }