//190 int sys_spu_thread_write_spu_mb(u32 id, u32 value) { sc_spu.Warning("sys_spu_thread_write_spu_mb(id=%d, value=0x%x)", id, value); CPUThread* thr = Emu.GetCPU().GetThread(id); if(!thr || (thr->GetType() != CPU_THREAD_SPU && thr->GetType() != CPU_THREAD_RAW_SPU)) { return CELL_ESRCH; } (*(SPUThread*)thr).SPU.In_MBox.PushUncond(value); return CELL_OK; }
//188 int sys_spu_thread_get_spu_cfg(u32 id, mem64_t value) { sc_spu.Warning("sys_spu_thread_get_spu_cfg(id=0x%x, 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; }
//181 int sys_spu_thread_write_ls(u32 id, u32 address, u64 value, u32 type) { sc_spu.Warning("sys_spu_thread_write_ls(id=0x%x, address=0x%x, value=0x%llx, type=0x%x)", id, address, value, type); CPUThread* thr = Emu.GetCPU().GetThread(id); if(!thr || (thr->GetType() != CPU_THREAD_SPU && thr->GetType() != CPU_THREAD_RAW_SPU)) { return CELL_ESRCH; } (*(SPUThread*)thr).WriteLS64(address, value); return CELL_OK; }
s32 sys_spu_thread_connect_event(u32 id, u32 eq_id, u32 et, u8 spup) { sc_spu.Warning("sys_spu_thread_connect_event(id=%d, eq_id=%d, event_type=0x%x, spup=%d)", id, eq_id, et, spup); CPUThread* thr = Emu.GetCPU().GetThread(id); if(!thr || (thr->GetType() != CPU_THREAD_SPU && thr->GetType() != CPU_THREAD_RAW_SPU)) { return CELL_ESRCH; } EventQueue* eq; if (!Emu.GetIdManager().GetIDData(eq_id, eq)) { return CELL_ESRCH; } if (spup > 63) { sc_spu.Error("sys_spu_thread_connect_event: invalid spup (%d)", spup); return CELL_EINVAL; } if (et != SYS_SPU_THREAD_EVENT_USER) { sc_spu.Error("sys_spu_thread_connect_event: unsupported event type (0x%x)", et); return CELL_EINVAL; } // TODO: check if can receive these events SPUThread& spu = *(SPUThread*)thr; EventPort& port = spu.SPUPs[spup]; std::lock_guard<std::mutex> lock(port.m_mutex); if (port.eq) { return CELL_EISCONN; } eq->ports.add(&port); port.eq = eq; 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; } }
s32 sys_spu_thread_unbind_queue(u32 id, u32 spuq_num) { sc_spu.Warning("sys_spu_thread_unbind_queue(id=0x%x, spuq_num=0x%x)", id, spuq_num); CPUThread* thr = Emu.GetCPU().GetThread(id); if(!thr || (thr->GetType() != CPU_THREAD_SPU && thr->GetType() != CPU_THREAD_RAW_SPU)) { return CELL_ESRCH; } if (!(*(SPUThread*)thr).SPUQs.UnregisterKey(FIX_SPUQ(spuq_num))) { return CELL_ESRCH; // may be CELL_EINVAL } return CELL_OK; }
//184 s32 sys_spu_thread_write_snr(u32 id, u32 number, u32 value) { sc_spu.Log("sys_spu_thread_write_snr(id=%d, number=%d, value=0x%x)", id, number, value); CPUThread* thr = Emu.GetCPU().GetThread(id); if(!thr || (thr->GetType() != CPU_THREAD_SPU && thr->GetType() != CPU_THREAD_RAW_SPU)) { return CELL_ESRCH; } if (number > 1) { return CELL_EINVAL; } (*(SPUThread*)thr).WriteSNR(number, value); return CELL_OK; }
//190 int sys_spu_thread_write_spu_mb(u32 id, u32 value) { sc_spu.Warning("sys_spu_thread_write_spu_mb(id=0x%x, value=0x%x)", id, value); CPUThread* thr = Emu.GetCPU().GetThread(id); if(!thr || (thr->GetType() != CPU_THREAD_SPU && thr->GetType() != CPU_THREAD_RAW_SPU)) { return CELL_ESRCH; } if(!(*(SPUThread*)thr).SPU.In_MBox.Push(value)) { ConLog.Warning("sys_spu_thread_write_spu_mb(id=0x%x, value=0x%x): used all mbox items."); return CELL_EBUSY; //? } return CELL_OK; }
//187 s32 sys_spu_thread_set_spu_cfg(u32 id, u64 value) { sc_spu.Warning("sys_spu_thread_set_spu_cfg(id=%d, value=0x%x)", id, value); CPUThread* thr = Emu.GetCPU().GetThread(id); if(!thr || (thr->GetType() != CPU_THREAD_SPU && thr->GetType() != CPU_THREAD_RAW_SPU)) { return CELL_ESRCH; } if (value > 3) { return CELL_EINVAL; } (*(SPUThread*)thr).cfg.value = value; 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; }
//181 int sys_spu_thread_write_ls(u32 id, u32 address, u64 value, u32 type) { sc_spu.Log("sys_spu_thread_write_ls(id=%d, address=0x%x, value=0x%llx, type=0x%x)", id, address, value, 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 (!(*(SPUThread*)thr).IsGoodLSA(address) || (address % type)) // +check alignment { return CELL_EINVAL; } switch (type) { case 1: (*(SPUThread*)thr).WriteLS8(address, value); return CELL_OK; case 2: (*(SPUThread*)thr).WriteLS16(address, value); return CELL_OK; case 4: (*(SPUThread*)thr).WriteLS32(address, value); return CELL_OK; case 8: (*(SPUThread*)thr).WriteLS64(address, value); return CELL_OK; default: return CELL_EINVAL; } }
s32 sys_spu_thread_disconnect_event(u32 id, u32 et, u8 spup) { sc_spu.Warning("sys_spu_thread_disconnect_event(id=%d, event_type=0x%x, spup=%d)", id, et, spup); CPUThread* thr = Emu.GetCPU().GetThread(id); if(!thr || (thr->GetType() != CPU_THREAD_SPU && thr->GetType() != CPU_THREAD_RAW_SPU)) { return CELL_ESRCH; } if (spup > 63) { sc_spu.Error("sys_spu_thread_connect_event: invalid spup (%d)", spup); return CELL_EINVAL; } if (et != SYS_SPU_THREAD_EVENT_USER) { sc_spu.Error("sys_spu_thread_connect_event: unsupported event type (0x%x)", et); return CELL_EINVAL; } SPUThread& spu = *(SPUThread*)thr; EventPort& port = spu.SPUPs[spup]; std::lock_guard<std::mutex> lock(port.m_mutex); if (!port.eq) { return CELL_ENOTCONN; } port.eq->ports.remove(&port); port.eq = nullptr; return CELL_OK; }
//166 s32 sys_spu_thread_set_argument(u32 id, mem_ptr_t<sys_spu_thread_argument> arg) { sc_spu.Warning("sys_spu_thread_set_argument(id=%d, arg_addr=0x%x)", id, arg.GetAddr()); CPUThread* thr = Emu.GetCPU().GetThread(id); if(!thr || (thr->GetType() != CPU_THREAD_SPU && thr->GetType() != CPU_THREAD_RAW_SPU)) { return CELL_ESRCH; } if(!arg.IsGood()) { return CELL_EFAULT; } thr->SetArg(0, arg->arg1); thr->SetArg(1, arg->arg2); thr->SetArg(2, arg->arg3); thr->SetArg(3, arg->arg4); return CELL_OK; }
s32 sys_spu_thread_group_connect_event_all_threads(u32 id, u32 eq_id, u64 req, mem8_t spup) { sc_spu.Warning("sys_spu_thread_group_connect_event_all_threads(id=%d, eq_id=%d, req=0x%llx, spup_addr=0x%x)", id, eq_id, req, spup.GetAddr()); if (!spup.IsGood()) { return CELL_EFAULT; } EventQueue* eq; if (!Emu.GetIdManager().GetIDData(eq_id, eq)) { return CELL_ESRCH; } if (!req) { return CELL_EINVAL; } SpuGroupInfo* group; if (!Emu.GetIdManager().GetIDData(id, group)) { return CELL_ESRCH; } std::vector<SPUThread*> threads; for (auto& v : group->list) { if (!v) continue; CPUThread* thr = Emu.GetCPU().GetThread(v); if (thr->GetType() != CPU_THREAD_SPU) { sc_spu.Error("sys_spu_thread_group_connect_event_all_threads(): CELL_ESTAT (wrong thread type)"); return CELL_ESTAT; } threads.push_back((SPUThread*)thr); } if (threads.size() != group->m_count) { sc_spu.Error("sys_spu_thread_group_connect_event_all_threads(): CELL_ESTAT (%d from %d)", (u32)threads.size(), group->m_count); return CELL_ESTAT; } for (u32 i = 0; i < 64; i++) // port number { bool found = true; if (req & (1ull << i)) { for (auto& t : threads) t->SPUPs[i].m_mutex.lock(); for (auto& t : threads) if (t->SPUPs[i].eq) found = false; if (found) { for (auto& t : threads) { eq->ports.add(&(t->SPUPs[i])); t->SPUPs[i].eq = eq; } spup = (u8)i; } for (auto& t : threads) t->SPUPs[i].m_mutex.unlock(); } else { found = false; } if (found) return CELL_OK; } return CELL_EISCONN; }