s32 cellSurMixerGetCurrentBlockTag(vm::ptr<u64> tag) { libmixer.Log("cellSurMixerGetCurrentBlockTag(tag=*0x%x)", tag); *tag = g_surmx.mixcount; return CELL_OK; }
int cellPadEnd() { sys_io.Log("cellPadEnd()"); if(!Emu.GetPadManager().IsInited()) return CELL_PAD_ERROR_UNINITIALIZED; Emu.GetPadManager().Close(); return CELL_OK; }
int cellGcmSetFlip(mem_ptr_t<CellGcmContextData> ctxt, u32 id) { cellGcmSys.Log("cellGcmSetFlip(ctx=0x%x, id=0x%x)", ctxt.GetAddr(), id); int res = cellGcmSetPrepareFlip(ctxt, id); return res < 0 ? CELL_GCM_ERROR_FAILURE : CELL_OK; }
int cellPadGetDataExtra(u32 port_no, u32 device_type_addr, u32 data_addr) { sys_io.Log("cellPadGetDataExtra(port_no=%d, device_type_addr=0x%x, device_type_addr=0x%x)", port_no, device_type_addr, data_addr); if(!Emu.GetPadManager().IsInited()) return CELL_PAD_ERROR_UNINITIALIZED; if(port_no >= Emu.GetPadManager().GetPads().GetCount()) return CELL_PAD_ERROR_INVALID_PARAMETER; return CELL_OK; }
int cellPadGetInfo2(u32 info_addr) { sys_io.Log("cellPadGetInfo2(info_addr=0x%x)", info_addr); if(!Emu.GetPadManager().IsInited()) return CELL_PAD_ERROR_UNINITIALIZED; CellPadInfo2 info; memset(&info, 0, sizeof(CellPadInfo2)); const PadInfo& rinfo = Emu.GetPadManager().GetInfo(); info.max_connect = re(rinfo.max_connect); info.now_connect = re(rinfo.now_connect); info.system_info = re(rinfo.system_info); const Array<Pad>& pads = Emu.GetPadManager().GetPads(); for(u32 i=0; i<CELL_PAD_MAX_PORT_NUM; ++i) { if(i >= pads.GetCount()) break; info.port_status[i] = re(pads[i].m_port_status); info.port_setting[i] = re(pads[i].m_port_setting); info.device_capability[i] = re(pads[i].m_device_capability); info.device_type[i] = re(pads[i].m_device_type); } Memory.WriteData(info_addr, info); return CELL_OK; }
s32 cellPadGetInfo(vm::ptr<CellPadInfo> info) { sys_io.Log("cellPadGetInfo(info=*0x%x)", info); if (!Emu.GetPadManager().IsInited()) return CELL_PAD_ERROR_UNINITIALIZED; const PadInfo& rinfo = Emu.GetPadManager().GetInfo(); info->max_connect = rinfo.max_connect; info->now_connect = rinfo.now_connect; info->system_info = rinfo.system_info; //Can't have this as const, we need to reset Assign Changes Flag here std::vector<Pad>& pads = Emu.GetPadManager().GetPads(); for (u32 i=0; i<CELL_MAX_PADS; ++i) { if (i >= pads.size()) break; info->status[i] = pads[i].m_port_status; pads[i].m_port_status &= ~CELL_PAD_STATUS_ASSIGN_CHANGES; info->product_id[i] = 0x0268; info->vendor_id[i] = 0x054C; } return CELL_OK; }
s32 cellPadClearBuf(u32 port_no) { sys_io.Log("cellPadClearBuf(port_no=%d)", port_no); 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; //Set 'm_buffer_cleared' to force a resend of everything //might as well also reset everything in our pad 'buffer' to nothing as well std::vector<Pad>& pads = Emu.GetPadManager().GetPads(); Pad& pad = pads[port_no]; pad.m_buffer_cleared = true; pad.m_analog_left_x = pad.m_analog_left_y = pad.m_analog_right_x = pad.m_analog_right_y = 128; pad.m_digital_1 = pad.m_digital_2 = 0; pad.m_press_right = pad.m_press_left = pad.m_press_up = pad.m_press_down = 0; pad.m_press_triangle = pad.m_press_circle = pad.m_press_cross = pad.m_press_square = 0; pad.m_press_L1 = pad.m_press_L2 = pad.m_press_R1 = pad.m_press_R2 = 0; //~399 on sensor y is a level non moving controller pad.m_sensor_y = 399; pad.m_sensor_x = pad.m_sensor_z = pad.m_sensor_g = 0; return CELL_OK; }
int cellAudioGetPortTimestamp(u32 portNum, u64 tag, mem64_t stamp) { cellAudio.Log("cellAudioGetPortTimestamp(portNum=0x%x, tag=0x%llx, stamp_addr=0x%x)", portNum, tag, stamp.GetAddr()); if (portNum >= m_config.AUDIO_PORT_COUNT) { return CELL_AUDIO_ERROR_PARAM; } if (!m_config.m_ports[portNum].m_is_audio_port_opened) { return CELL_AUDIO_ERROR_PORT_NOT_OPEN; } if (!m_config.m_ports[portNum].m_is_audio_port_started) { return CELL_AUDIO_ERROR_PORT_NOT_RUN; } AudioPortConfig& port = m_config.m_ports[portNum]; SMutexGeneralLocker lock(port.m_mutex); stamp = m_config.start_time + (port.counter + (tag - port.tag)) * 256000000 / 48000; return CELL_OK; }
int cellSysutilGetSystemParamString(s32 id, mem_list_ptr_t<u8> buf, u32 bufsize) { cellSysutil.Log("cellSysutilGetSystemParamString(id=%d, buf_addr=0x%x, bufsize=%d)", id, buf.GetAddr(), bufsize); if (!buf.IsGood()) return CELL_EFAULT; memset(buf, 0, bufsize); switch(id) { case CELL_SYSUTIL_SYSTEMPARAM_ID_NICKNAME: cellSysutil.Warning("cellSysutilGetSystemParamString: CELL_SYSUTIL_SYSTEMPARAM_ID_NICKNAME"); memcpy(buf, "Unknown", 8); //for example break; case CELL_SYSUTIL_SYSTEMPARAM_ID_CURRENT_USERNAME: cellSysutil.Warning("cellSysutilGetSystemParamString: CELL_SYSUTIL_SYSTEMPARAM_ID_CURRENT_USERNAME"); memcpy(buf, "Unknown", 8); break; default: return CELL_EINVAL; } return CELL_OK; }
int cellFsFtruncate(u32 fd, u64 size) { sys_fs.Log("cellFsFtruncate(fd=%d, size=%lld)", fd, size); u32 attr; vfsStream* file; if(!sys_fs.CheckId(fd, file, attr) || attr != IDFlag_File) return CELL_ESRCH; u64 initialSize = file->GetSize(); if (initialSize < size) { u64 last_pos = file->Tell(); file->Seek(0, vfsSeekEnd); static const char nullbyte = 0; file->Seek(size-initialSize-1, vfsSeekCur); file->Write(&nullbyte, sizeof(char)); file->Seek(last_pos, vfsSeekSet); } if (initialSize > size) { // (TODO) } return CELL_OK; }
int cellFsTruncate(u32 path_addr, u64 size) { const wxString& path = Memory.ReadString(path_addr); sys_fs.Log("cellFsTruncate(path=\"%s\", size=%lld)", path.wx_str(), size); vfsFile f(path, vfsReadWrite); if(!f.IsOpened()) { sys_fs.Warning("cellFsTruncate: \"%s\" not found.", path.wx_str()); return CELL_ENOENT; } u64 initialSize = f.GetSize(); if (initialSize < size) { u64 last_pos = f.Tell(); f.Seek(0, vfsSeekEnd); static const char nullbyte = 0; f.Seek(size-initialSize-1, vfsSeekCur); f.Write(&nullbyte, sizeof(char)); f.Seek(last_pos, vfsSeekSet); } if (initialSize > size) { // (TODO) } return CELL_OK; }
int cellFsReaddir(u32 fd, mem_ptr_t<CellFsDirent> dir, mem64_t nread) { sys_fs.Log("cellFsReaddir(fd=%d, dir_addr=0x%x, nread_addr=0x%x)", fd, dir.GetAddr(), nread.GetAddr()); vfsDirBase* directory; if(!sys_fs.CheckId(fd, directory)) return CELL_ESRCH; if(!dir.IsGood() || !nread.IsGood()) return CELL_EFAULT; const DirEntryInfo* info = directory->Read(); if(info) { nread = 1; Memory.WriteString(dir.GetAddr()+2, info->name.wx_str()); dir->d_namlen = info->name.Length(); dir->d_type = (info->flags & DirEntry_TypeFile) ? CELL_FS_TYPE_REGULAR : CELL_FS_TYPE_DIRECTORY; } else { nread = 0; } return CELL_OK; }
int cellFontGetCharGlyphMetrics(mem_ptr_t<CellFont> font, u32 code, mem_ptr_t<CellFontGlyphMetrics> metrics) { cellFont.Log("cellFontGetCharGlyphMetrics(font_addr=0x%x, code=0x%x, metrics_addr=0x%x", font.GetAddr(), code, metrics.GetAddr()); if (!font.IsGood() || metrics.IsGood()) return CELL_FONT_ERROR_INVALID_PARAMETER; int x0, y0, x1, y1; int advanceWidth, leftSideBearing; float scale = stbtt_ScaleForPixelHeight(&(font->stbfont), font->scale_y); stbtt_GetCodepointBox(&(font->stbfont), code, &x0, &y0, &x1, &y1); stbtt_GetCodepointHMetrics(&(font->stbfont), code, &advanceWidth, &leftSideBearing); // TODO: Add the rest of the information metrics->width = (x1-x0) * scale; metrics->height = (y1-y0) * scale; metrics->Horizontal.bearingX = (float)leftSideBearing * scale; metrics->Horizontal.bearingY = 0; metrics->Horizontal.advance = (float)advanceWidth * scale; metrics->Vertical.bearingX = 0; metrics->Vertical.bearingY = 0; metrics->Vertical.advance = 0; return CELL_FONT_OK; }
s32 cellSurMixerGetTimestamp(u64 tag, vm::ptr<u64> stamp) { libmixer.Log("cellSurMixerGetTimestamp(tag=0x%llx, stamp=*0x%x)", tag, stamp); *stamp = g_audio.start_time + (tag) * 256000000 / 48000; // ??? return CELL_OK; }
int cellJpgDecReadHeader(u32 mainHandle, u32 subHandle, mem_ptr_t<CellJpgDecInfo> info) { cellJpgDec.Log("cellJpgDecReadHeader(mainHandle=0x%x, subHandle=0x%x, info_addr=0x%llx)", mainHandle, subHandle, info.GetAddr()); if (!info.IsGood()) return CELL_JPGDEC_ERROR_ARG; CellJpgDecSubHandle* subHandle_data; if(!cellJpgDec.CheckId(subHandle, subHandle_data)) return CELL_JPGDEC_ERROR_FATAL; const u32& fd = subHandle_data->fd; const u64& fileSize = subHandle_data->fileSize; CellJpgDecInfo& current_info = subHandle_data->info; //Copy the JPG file to a buffer MemoryAllocator<u8> buffer(fileSize); MemoryAllocator<be_t<u64>> pos, nread; cellFsLseek(fd, 0, CELL_SEEK_SET, pos); cellFsRead(fd, buffer.GetAddr(), buffer.GetSize(), nread); if (*buffer.To<u32>(0) != 0xE0FFD8FF || // Error: Not a valid SOI header *buffer.To<u32>(6) != 0x4649464A) // Error: Not a valid JFIF string { return CELL_JPGDEC_ERROR_HEADER; } u32 i = 4; if(i >= fileSize) return CELL_JPGDEC_ERROR_HEADER; u16 block_length = buffer[i] * 0xFF + buffer[i+1]; while(true) { i += block_length; // Increase the file index to get to the next block if (i >= fileSize || // Check to protect against segmentation faults buffer[i] != 0xFF) // Check that we are truly at the start of another block { return CELL_JPGDEC_ERROR_HEADER; } if(buffer[i+1] == 0xC0) break; // 0xFFC0 is the "Start of frame" marker which contains the file size i += 2; // Skip the block marker block_length = buffer[i] * 0xFF + buffer[i+1]; // Go to the next block } current_info.imageWidth = buffer[i+7]*0x100 + buffer[i+8]; current_info.imageHeight = buffer[i+5]*0x100 + buffer[i+6]; current_info.numComponents = 3; // Unimplemented current_info.colorSpace = CELL_JPG_RGB; *info = current_info; return CELL_OK; }
void sys_spinlock_initialize(vm::ptr<atomic_be_t<u32>> lock) { sysPrxForUser.Log("sys_spinlock_initialize(lock=*0x%x)", lock); // prx: set 0 and sync lock->exchange(be_t<u32>::make(0)); }
s32 cellDmuxSetStream(u32 handle, u32 streamAddress, u32 streamSize, bool discontinuity, u64 userData) { cellDmux.Log("cellDmuxSetStream(handle=0x%x, streamAddress=0x%x, streamSize=%d, discontinuity=%d, userData=0x%llx)", handle, streamAddress, streamSize, discontinuity, userData); const auto dmux = Emu.GetIdManager().get<Demuxer>(handle); if (!dmux) { return CELL_DMUX_ERROR_ARG; } if (dmux->is_running.exchange(true)) { //std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack return CELL_DMUX_ERROR_BUSY; } DemuxerTask task(dmuxSetStream); auto& info = task.stream; info.addr = streamAddress; info.size = streamSize; info.discontinuity = discontinuity; info.userdata = userData; dmux->job.push(task, &dmux->is_closed); return CELL_OK; }
s32 sys_lwmutex_destroy(PPUThread& CPU, vm::ptr<sys_lwmutex_t> lwmutex) { sysPrxForUser.Log("sys_lwmutex_destroy(lwmutex=*0x%x)", lwmutex); // check to prevent recursive locking in the next call if (lwmutex->owner.read_relaxed() == CPU.GetId()) { return CELL_EBUSY; } // attempt to lock the mutex if (s32 res = sys_lwmutex_trylock(CPU, lwmutex)) { return res; } // call the syscall if (s32 res = _sys_lwmutex_destroy(lwmutex->sleep_queue)) { // unlock the mutex if failed sys_lwmutex_unlock(CPU, lwmutex); return res; } // deleting succeeded lwmutex->owner.exchange(lwmutex::dead); return CELL_OK; }
s32 cellPadGetInfo2(vm::ptr<CellPadInfo2> info) { sys_io.Log("cellPadGetInfo2(info=*0x%x)", info); if (!Emu.GetPadManager().IsInited()) return CELL_PAD_ERROR_UNINITIALIZED; const PadInfo& rinfo = Emu.GetPadManager().GetInfo(); info->max_connect = rinfo.max_connect; info->now_connect = rinfo.now_connect; info->system_info = rinfo.system_info; std::vector<Pad>& pads = Emu.GetPadManager().GetPads(); for (u32 i=0; i<CELL_PAD_MAX_PORT_NUM; ++i) { if (i >= pads.size()) break; info->port_status[i] = pads[i].m_port_status; pads[i].m_port_status &= ~CELL_PAD_STATUS_ASSIGN_CHANGES; info->port_setting[i] = pads[i].m_port_setting; info->device_capability[i] = pads[i].m_device_capability; info->device_type[i] = pads[i].m_device_type; } return CELL_OK; }
s32 sys_process_is_stack(u32 p) { sysPrxForUser.Log("sys_process_is_stack(p=0x%x)", p); // prx: compare high 4 bits with "0xD" return (p >= Memory.StackMem.GetStartAddr() && p <= Memory.StackMem.GetEndAddr()) ? 1 : 0; }
s32 cellPadSetSensorMode(u32 port_no, u32 mode) { sys_io.Log("cellPadSetSensorMode(port_no=%d, mode=%d)", port_no, mode); if (!Emu.GetPadManager().IsInited()) return CELL_PAD_ERROR_UNINITIALIZED; if (mode != 0 && mode != 1) return CELL_PAD_ERROR_INVALID_PARAMETER; 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; std::vector<Pad>& pads = Emu.GetPadManager().GetPads(); if (mode) pads[port_no].m_port_setting |= CELL_PAD_SETTING_SENSOR_ON; else pads[port_no].m_port_setting &= ~CELL_PAD_SETTING_SENSOR_ON; return CELL_OK; }
int cellPadGetInfo(u32 info_addr) { sys_io.Log("cellPadGetInfo(info_addr=0x%x)", info_addr); if(!Emu.GetPadManager().IsInited()) return CELL_PAD_ERROR_UNINITIALIZED; CellPadInfo info; memset(&info, 0, sizeof(CellPadInfo)); const PadInfo& rinfo = Emu.GetPadManager().GetInfo(); info.max_connect = rinfo.max_connect; info.now_connect = rinfo.now_connect; info.system_info = rinfo.system_info; const std::vector<Pad>& pads = Emu.GetPadManager().GetPads(); for(u32 i=0; i<CELL_MAX_PADS; ++i) { if(i >= pads.size()) break; info.status[i] = pads[i].m_port_status; info.product_id[i] = 0x0268; info.vendor_id[i] = 0x054C; } Memory.WriteData(info_addr, info); return CELL_OK; }
int cellPadSetActDirect(u32 port_no, u32 param_addr) { sys_io.Log("cellPadSetActDirect(port_no=%d, param_addr=0x%x)", port_no, param_addr); if(!Emu.GetPadManager().IsInited()) return CELL_PAD_ERROR_UNINITIALIZED; if(port_no >= Emu.GetPadManager().GetPads().GetCount()) return CELL_PAD_ERROR_INVALID_PARAMETER; return CELL_OK; }
s32 sys_process_is_stack(u32 p) { sysPrxForUser.Log("sys_process_is_stack(p=0x%x)", p); // prx: compare high 4 bits with "0xD" return (p >> 28) == 0xD; }
int cellPadInit(u32 max_connect) { sys_io.Log("cellPadInit(max_connect=%d)", max_connect); if(Emu.GetPadManager().IsInited()) return CELL_PAD_ERROR_ALREADY_INITIALIZED; Emu.GetPadManager().Init(max_connect); return CELL_OK; }
s32 cellKbRead(u32 port_no, vm::ptr<CellKbData> data) { sys_io.Log("cellKbRead(port_no=%d, data=*0x%x)", port_no, data); const std::vector<Keyboard>& keyboards = Emu.GetKeyboardManager().GetKeyboards(); if (!Emu.GetKeyboardManager().IsInited()) return CELL_KB_ERROR_UNINITIALIZED; if (port_no >= keyboards.size()) return CELL_KB_ERROR_INVALID_PARAMETER; KbData& current_data = Emu.GetKeyboardManager().GetData(port_no); data->led = current_data.led; data->mkey = current_data.mkey; data->len = std::min((u32)current_data.len, CELL_KB_MAX_KEYCODES); for (s32 i=0; i<current_data.len; i++) { data->keycode[i] = current_data.keycode[i]; } current_data.len = 0; return CELL_OK; }
int cellGcmSetPrepareFlip(mem_ptr_t<CellGcmContextData> ctxt, u32 id) { cellGcmSys.Log("cellGcmSetPrepareFlip(ctx=0x%x, id=0x%x)", ctxt.GetAddr(), id); if(id >= 8) { return CELL_GCM_ERROR_FAILURE; } GSLockCurrent gslock(GS_LOCK_WAIT_FLUSH); u32 current = re(ctxt->current); u32 end = re(ctxt->end); if(current + 8 >= end) { ConLog.Warning("bad flip!"); cellGcmCallback(ctxt.GetAddr(), current + 8 - end); } current = re(ctxt->current); Memory.Write32(current, 0x3fead | (1 << 18)); Memory.Write32(current + 4, id); re(ctxt->current, current + 8); if(ctxt.GetAddr() == gcm_info.context_addr) { CellGcmControl& ctrl = (CellGcmControl&)Memory[gcm_info.control_addr]; re(ctrl.put, re(ctrl.put) + 8); } return id; }
int cellVideoOutGetResolution(u32 resolutionId, u32 resolution_addr) { cellSysutil.Log("cellVideoOutGetResolution(resolutionId=%d, resolution_addr=0x%x)", resolutionId, resolution_addr); if(!Memory.IsGoodAddr(resolution_addr, sizeof(CellVideoOutResolution))) { return CELL_EFAULT; } u32 num = ResolutionIdToNum(resolutionId); if(!num) { return CELL_EINVAL; } CellVideoOutResolution res; re(res.width, ResolutionTable[num].width); re(res.height, ResolutionTable[num].height); Memory.WriteData(resolution_addr, res); return CELL_VIDEO_OUT_SUCCEEDED; }
int cellGcmSetWaitFlip(mem_ptr_t<CellGcmContextData> ctxt) { cellGcmSys.Log("cellGcmSetWaitFlip(ctx=0x%x)", ctxt.GetAddr()); GSLockCurrent lock(GS_LOCK_WAIT_FLIP); return CELL_OK; }
int cellMouseEnd() { sys_io.Log("cellMouseEnd()"); if(!Emu.GetMouseManager().IsInited()) return CELL_MOUSE_ERROR_UNINITIALIZED; Emu.GetMouseManager().Close(); return CELL_OK; }