Esempio n. 1
0
int cellSpursSetGlobalExceptionEventHandler(mem_ptr_t<CellSpurs> spurs, 
											mem_func_ptr_t<CellSpursGlobalExceptionEventHandler> eaHandler, mem_ptr_t<void> arg)
{
	cellSpurs.Error("cellSpursEnableExceptionEventHandler(spurs_addr=0x%x, eaHandler_addr=0x%x, arg_addr=0x%x,)", 
		spurs.GetAddr(), eaHandler.GetAddr(), arg.GetAddr());
	
	if(!spurs.IsGood() || eaHandler.IsGood())
		return CELL_SPURS_CORE_ERROR_NULL_POINTER;

	return CELL_OK;
}
Esempio n. 2
0
int cellSaveDataAutoSave2(u32 version, u32 dirName_addr, u32 errDialog, mem_ptr_t<CellSaveDataSetBuf> setBuf,
						  mem_func_ptr_t<CellSaveDataStatCallback> funcStat, mem_func_ptr_t<CellSaveDataFileCallback> funcFile,
						  u32 container, u32 userdata_addr)
{
	cellSysutil->Warning("cellSaveDataAutoSave2(version=%d, dirName_addr=0x%x, errDialog=%d, setBuf=0x%x, funcList=0x%x, funcStat=0x%x, funcFile=0x%x, container=%d, userdata_addr=0x%x)",
		version, dirName_addr, errDialog, setBuf.GetAddr(), funcStat.GetAddr(), funcFile.GetAddr(), container, userdata_addr);

	MemoryAllocator<CellSaveDataCBResult> result;
	MemoryAllocator<CellSaveDataStatGet> statGet;
	MemoryAllocator<CellSaveDataStatSet> statSet;

	std::string saveBaseDir = "/dev_hdd0/home/00000001/savedata/"; // TODO: Get the path of the current user
	vfsDir dir(saveBaseDir);
	if (!dir.IsOpened())
		return CELL_SAVEDATA_ERROR_INTERNAL;

	std::string dirName = Memory.ReadString(dirName_addr);
	std::vector<SaveDataEntry> saveEntries;
	for (const DirEntryInfo* entry = dir.Read(); entry; entry = dir.Read())
	{
		if (entry->flags & DirEntry_TypeDir && entry->name == dirName) {
			addSaveDataEntry(saveEntries, saveBaseDir+dirName);
		}
	}

	// The target entry does not exist
	if (saveEntries.size() == 0) {
		SaveDataEntry entry;
		entry.dirName = dirName;
		entry.sizeKB = 0;
		entry.isNew = true;
		saveEntries.push_back(entry);
	}

	getSaveDataStat(saveEntries[0], statGet.GetAddr()); // There should be only one element in this list
	result->userdata_addr = userdata_addr;
	funcStat(result.GetAddr(), statGet.GetAddr(), statSet.GetAddr());

	Memory.Free(statGet->fileList.GetAddr());
	if (result->result < 0)	{
		LOG_ERROR(HLE, "cellSaveDataAutoSave2: CellSaveDataStatCallback failed."); // TODO: Once we verify that the entire SysCall is working, delete this debug error message.
		return CELL_SAVEDATA_ERROR_CBRESULT;
	}
	/*if (statSet->setParam.GetAddr())
		// TODO: Write PARAM.SFO file
	*/

	// Enter the loop where the save files are read/created/deleted.
	s32 ret = modifySaveDataFiles(funcFile, result.GetAddr(), saveBaseDir + (char*)statGet->dir.dirName);

	return CELL_SAVEDATA_RET_OK;
}
Esempio n. 3
0
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;
}
Esempio n. 4
0
int cellFsStReadWaitCallback(u32 fd, u64 size, mem_func_ptr_t<void (*)(int xfd, u64 xsize)> func)
{
	sys_fs.Warning("TODO: cellFsStReadWaitCallback(fd=%d, size = 0x%llx, func_addr = 0x%x)", fd, size, func.GetAddr());

	if (!func.IsGood())
		return CELL_EFAULT;

	vfsStream* file;
	if(!sys_fs.CheckId(fd, file)) return CELL_ESRCH;
	
	return CELL_OK;
}
Esempio n. 5
0
void fsAioRead(u32 fd, mem_ptr_t<CellFsAio> aio, int xid, mem_func_ptr_t<void (*)(mem_ptr_t<CellFsAio> xaio, int error, int xid, u64 size)> func)
{
	while (g_FsAioReadCur != xid)
	{
		std::this_thread::sleep_for(std::chrono::milliseconds(1));
		if (Emu.IsStopped())
		{
			LOG_WARNING(HLE, "fsAioRead() aborted");
			return;
		}
	}

	vfsFileBase* orig_file;
	if(!sys_fs->CheckId(fd, orig_file)) return;

	u64 nbytes = aio->size;
	u32 buf_addr = aio->buf_addr;

	u32 error = CELL_OK;

	vfsStream& file = *(vfsStream*)orig_file;
	const u64 old_pos = file.Tell();
	file.Seek((u64)aio->offset);

	// TODO: use code from cellFsRead or something

	u64 res = 0;
	if (nbytes != (u32)nbytes)
	{
		error = CELL_ENOMEM;
	}
	else
	{
		res = nbytes ? file.Read(Memory.GetMemFromAddr(buf_addr), nbytes) : 0;
	}

	file.Seek(old_pos);

	if (Ini.HLELogging.GetValue())
		LOG_NOTICE(HLE, "*** fsAioRead(fd=%d, offset=0x%llx, buf_addr=0x%x, size=0x%x, error=0x%x, res=0x%x, xid=0x%x [%s])",
			fd, (u64)aio->offset, buf_addr, (u64)aio->size, error, res, xid, orig_file->GetPath().c_str());

	if (func) // start callback thread
	{
		func.async(aio, error, xid, res);
	}

	g_FsAioReadCur++;
}
Esempio n. 6
0
int cellSpursSetGlobalExceptionEventHandler(mem_ptr_t<CellSpurs> spurs, mem_func_ptr_t<CellSpursGlobalExceptionEventHandler> eaHandler, mem_ptr_t<void> arg)
{
	cellSpurs->Todo("cellSpursSetGlobalExceptionEventHandler(spurs_addr=0x%x, eaHandler_addr=0x%x, arg_addr=0x%x,)", spurs.GetAddr(), eaHandler.GetAddr(), arg.GetAddr());

	if (spurs.GetAddr() % 128 != 0)
	{
		cellSpurs->Error("cellSpursSetGlobalExceptionEventHandler : CELL_SPURS_CORE_ERROR_ALIGN");
		return CELL_SPURS_CORE_ERROR_ALIGN;
	}

	if (!spurs.IsGood() || eaHandler.IsGood())
	{
		cellSpurs->Error("cellSpursSetGlobalExceptionEventHandler : CELL_SPURS_CORE_ERROR_NULL_POINTER");
		return CELL_SPURS_CORE_ERROR_NULL_POINTER;
	}

	return CELL_OK;
}
Esempio n. 7
0
int cellSaveDataFixedLoad2(u32 version,  mem_ptr_t<CellSaveDataSetList> setList, mem_ptr_t<CellSaveDataSetBuf> setBuf,
						   mem_func_ptr_t<CellSaveDataFixedCallback> funcFixed, mem_func_ptr_t<CellSaveDataStatCallback> funcStat, mem_func_ptr_t<CellSaveDataFileCallback> funcFile,
						   u32 container, u32 userdata_addr)
{
	cellSysutil->Warning("cellSaveDataFixedLoad2(version=%d, setList_addr=0x%x, setBuf=0x%x, funcList=0x%x, funcStat=0x%x, funcFile=0x%x, container=%d, userdata_addr=0x%x)",
		version, setList.GetAddr(), setBuf.GetAddr(), funcFixed.GetAddr(), funcStat.GetAddr(), funcFile.GetAddr(), container, userdata_addr);

	MemoryAllocator<CellSaveDataCBResult> result;
	MemoryAllocator<CellSaveDataListGet> listGet;
	MemoryAllocator<CellSaveDataFixedSet> fixedSet;
	MemoryAllocator<CellSaveDataStatGet> statGet;
	MemoryAllocator<CellSaveDataStatSet> statSet;

	std::string saveBaseDir = "/dev_hdd0/home/00000001/savedata/"; // TODO: Get the path of the current user
	vfsDir dir(saveBaseDir);
	if (!dir.IsOpened())
		return CELL_SAVEDATA_ERROR_INTERNAL;

	std::string dirNamePrefix = Memory.ReadString(setList->dirNamePrefix_addr);
	std::vector<SaveDataEntry> saveEntries;
	for (const DirEntryInfo* entry = dir.Read(); entry; entry = dir.Read())
	{
		if (entry->flags & DirEntry_TypeDir && entry->name.substr(0, dirNamePrefix.size()) == dirNamePrefix)
		{
			// Count the amount of matches and the amount of listed directories
			listGet->dirListNum++;
			if (listGet->dirListNum > setBuf->dirListMax)
				continue;
			listGet->dirNum++;

			std::string saveDir = saveBaseDir + entry->name;
			addSaveDataEntry(saveEntries, saveDir);
		}
	}

	// Sort the entries and fill the listGet->dirList array
	std::sort(saveEntries.begin(), saveEntries.end(), sortSaveDataEntry(setList->sortType, setList->sortOrder));
	listGet->dirList.SetAddr(setBuf->buf_addr);
	CellSaveDataDirList* dirList = (CellSaveDataDirList*)Memory.VirtualToRealAddr(listGet->dirList.GetAddr());
	for (u32 i = 0; i<saveEntries.size(); i++) {
		memcpy(dirList[i].dirName, saveEntries[i].dirName.c_str(), CELL_SAVEDATA_DIRNAME_SIZE);
		memcpy(dirList[i].listParam, saveEntries[i].listParam.c_str(), CELL_SAVEDATA_SYSP_LPARAM_SIZE);
	}
	funcFixed(result.GetAddr(), listGet.GetAddr(), fixedSet.GetAddr());
	if (result->result < 0)	{
		LOG_ERROR(HLE, "cellSaveDataFixedLoad2: CellSaveDataFixedCallback failed."); // TODO: Once we verify that the entire SysCall is working, delete this debug error message.
		return CELL_SAVEDATA_ERROR_CBRESULT;
	}
	setSaveDataFixed(saveEntries, fixedSet.GetAddr());
	getSaveDataStat(saveEntries[0], statGet.GetAddr()); // There should be only one element in this list
	// TODO: Display the Yes|No dialog here
	result->userdata_addr = userdata_addr;

	funcStat(result.GetAddr(), statGet.GetAddr(), statSet.GetAddr());
	Memory.Free(statGet->fileList.GetAddr());
	if (result->result < 0)	{
		LOG_ERROR(HLE, "cellSaveDataFixedLoad2: CellSaveDataStatCallback failed."); // TODO: Once we verify that the entire SysCall is working, delete this debug error message.
		return CELL_SAVEDATA_ERROR_CBRESULT;
	}
	/*if (statSet->setParam.GetAddr())
		// TODO: Write PARAM.SFO file
	*/

	// Enter the loop where the save files are read/created/deleted.
	s32 ret = modifySaveDataFiles(funcFile, result.GetAddr(), saveBaseDir + (char*)statGet->dir.dirName);

	return ret;
}
Esempio n. 8
0
int cellMsgDialogOpenErrorCode(u32 errorCode, mem_func_ptr_t<CellMsgDialogCallback> callback, mem_ptr_t<void> userData, u32 extParam)
{
	cellSysutil.Warning("cellMsgDialogOpenErrorCode(errorCode=0x%x, callback_addr=0x%x, userData=%d, extParam=%d)",
		errorCode, callback.GetAddr(), userData, extParam);

	std::string errorMessage;
	switch(errorCode)
	{
	// Generic errors
	case 0x80010001: errorMessage = "The resource is temporarily unavailable."; break;
	case 0x80010002: errorMessage = "Invalid argument or flag."; break;
	case 0x80010003: errorMessage = "The feature is not yet implemented."; break;
	case 0x80010004: errorMessage = "Memory allocation failed."; break;
	case 0x80010005: errorMessage = "The resource with the specified identifier does not exist."; break;
	case 0x80010006: errorMessage = "The file does not exist."; break;
	case 0x80010007: errorMessage = "The file is in unrecognized format / The file is not a valid ELF file."; break;
	case 0x80010008: errorMessage = "Resource deadlock is avoided."; break;
	case 0x80010009: errorMessage = "Operation not permitted."; break;
	case 0x8001000A: errorMessage = "The device or resource is bus."; break;
	case 0x8001000B: errorMessage = "The operation is timed ou."; break;
	case 0x8001000C: errorMessage = "The operation is aborte."; break;
	case 0x8001000D: errorMessage = "Invalid memory access."; break;
	case 0x8001000F: errorMessage = "State of the target thread is invalid."; break;
	case 0x80010010: errorMessage = "Alignment is invalid."; break;
	case 0x80010011: errorMessage = "Shortage of the kernel resources."; break;
	case 0x80010012: errorMessage = "The file is a directory."; break;
	case 0x80010013: errorMessage = "Operation canceled."; break;
	case 0x80010014: errorMessage = "Entry already exists."; break;
	case 0x80010015: errorMessage = "Port is already connected."; break;
	case 0x80010016: errorMessage = "Port is not connected."; break;
	case 0x80010017: errorMessage = "Failure in authorizing SELF. Program authentication fail."; break;
	case 0x80010018: errorMessage = "The file is not MSELF."; break;
	case 0x80010019: errorMessage = "System version error."; break;
	case 0x8001001A: errorMessage = "Fatal system error occurred while authorizing SELF. SELF auth failure."; break;
	case 0x8001001B: errorMessage = "Math domain violation."; break;
	case 0x8001001C: errorMessage = "Math range violation."; break;
	case 0x8001001D: errorMessage = "Illegal multi-byte sequence in input."; break;
	case 0x8001001E: errorMessage = "File position error."; break;
	case 0x8001001F: errorMessage = "Syscall was interrupted."; break;
	case 0x80010020: errorMessage = "File too large."; break;
	case 0x80010021: errorMessage = "Too many links."; break;
	case 0x80010022: errorMessage = "File table overflow."; break;
	case 0x80010023: errorMessage = "No space left on device."; break;
	case 0x80010024: errorMessage = "Not a TTY."; break;
	case 0x80010025: errorMessage = "Broken pipe."; break;
	case 0x80010026: errorMessage = "Read-only filesystem."; break;
	case 0x80010027: errorMessage = "Illegal seek."; break;
	case 0x80010028: errorMessage = "Arg list too long."; break;
	case 0x80010029: errorMessage = "Access violation."; break;
	case 0x8001002A: errorMessage = "Invalid file descriptor."; break;
	case 0x8001002B: errorMessage = "Filesystem mounting failed."; break;
	case 0x8001002C: errorMessage = "Too many files open."; break;
	case 0x8001002D: errorMessage = "No device."; break;
	case 0x8001002E: errorMessage = "Not a directory."; break;
	case 0x8001002F: errorMessage = "No such device or IO."; break;
	case 0x80010030: errorMessage = "Cross-device link error."; break;
	case 0x80010031: errorMessage = "Bad Message."; break;
	case 0x80010032: errorMessage = "In progress."; break;
	case 0x80010033: errorMessage = "Message size error."; break;
	case 0x80010034: errorMessage = "Name too long."; break;
	case 0x80010035: errorMessage = "No lock."; break;
	case 0x80010036: errorMessage = "Not empty."; break;
	case 0x80010037: errorMessage = "Not supported."; break;
	case 0x80010038: errorMessage = "File-system specific error."; break;
	case 0x80010039: errorMessage = "Overflow occured."; break;
	case 0x8001003A: errorMessage = "Filesystem not mounted."; break;
	case 0x8001003B: errorMessage = "Not SData."; break;
	case 0x8001003C: errorMessage = "Incorrect version in sys_load_param."; break;
	case 0x8001003D: errorMessage = "Pointer is null."; break;
	case 0x8001003E: errorMessage = "Pointer is null."; break;
	default: errorMessage = "An error has occurred."; break;
	}

	char errorCodeHex [9];
	sprintf(errorCodeHex, "%08x", errorCode);
	errorMessage.append("\n(");
	errorMessage.append(errorCodeHex);
	errorMessage.append(")\n");

	u64 status;
	int res = wxMessageBox(errorMessage, wxGetApp().GetAppName(), wxICON_ERROR | wxOK);
	switch(res)
	{
	case wxOK: status = CELL_MSGDIALOG_BUTTON_OK; break;
	default:
		if(res)
		{
			status = CELL_MSGDIALOG_BUTTON_INVALID;
			break;
		}

		status = CELL_MSGDIALOG_BUTTON_NONE;
	break;
	}

	if(callback)
		callback(status, userData);

	return CELL_OK;
}
Esempio n. 9
0
int cellHddGameCheck(u32 version, u32 dirName_addr, u32 errDialog, mem_func_ptr_t<CellHddGameStatCallback> funcStat, u32 container)
{
	cellSysutil.Warning("cellHddGameCheck(version=%d, dirName_addr=0x%xx, errDialog=%d, funcStat_addr=0x%x, container=%d)",
		version, dirName_addr, errDialog, funcStat, container);

	if (!Memory.IsGoodAddr(dirName_addr) || !funcStat.IsGood())
		return CELL_HDDGAME_ERROR_PARAM;

	std::string dirName = Memory.ReadString(dirName_addr).ToStdString();
	if (dirName.size() != 9)
		return CELL_HDDGAME_ERROR_PARAM;

	MemoryAllocator<CellHddGameSystemFileParam> param;
	MemoryAllocator<CellHddGameCBResult> result;
	MemoryAllocator<CellHddGameStatGet> get;
	MemoryAllocator<CellHddGameStatSet> set;

	get->hddFreeSizeKB = 40000000; // 40 GB, TODO: Use the free space of the computer's HDD where RPCS3 is being run.
	get->isNewData = CELL_HDDGAME_ISNEWDATA_EXIST;
	get->sysSizeKB = 0; // TODO
	get->st_atime__  = 0; // TODO
	get->st_ctime__  = 0; // TODO
	get->st_mtime__  = 0; // TODO
	get->sizeKB = CELL_HDDGAME_SIZEKB_NOTCALC;
	memcpy(get->contentInfoPath, ("/dev_hdd0/game/"+dirName).c_str(), CELL_HDDGAME_PATH_MAX);
	memcpy(get->hddGamePath, ("/dev_hdd0/game/"+dirName+"/USRDIR").c_str(), CELL_HDDGAME_PATH_MAX);

	if (!Emu.GetVFS().ExistsDir(("/dev_hdd0/game/"+dirName).c_str()))
	{
		get->isNewData = CELL_HDDGAME_ISNEWDATA_NODIR;
	}
	else
	{
		// TODO: Is cellHddGameCheck really responsible for writing the information in get->getParam ? (If not, delete this else)

		vfsFile f(("/dev_hdd0/game/"+dirName+"/PARAM.SFO").c_str());
		PSFLoader psf(f);
		if (!psf.Load(false)) {
			return CELL_HDDGAME_ERROR_BROKEN;
		}

		get->getParam.parentalLevel = psf.m_info.parental_lvl;
		get->getParam.attribute = psf.m_info.attr;
		get->getParam.resolution = psf.m_info.resolution;
		get->getParam.soundFormat = psf.m_info.sound_format;
		memcpy(get->getParam.title, psf.m_info.name.mb_str(), CELL_HDDGAME_SYSP_TITLE_SIZE);
		memcpy(get->getParam.dataVersion, psf.m_info.app_ver.mb_str(), CELL_HDDGAME_SYSP_VERSION_SIZE);
		memcpy(get->getParam.titleId, dirName.c_str(), CELL_HDDGAME_SYSP_TITLEID_SIZE);

		for (u32 i=0; i<CELL_HDDGAME_SYSP_LANGUAGE_NUM; i++) {
			memcpy(get->getParam.titleLang[i], psf.m_info.name.mb_str(), CELL_HDDGAME_SYSP_TITLE_SIZE); // TODO: Get real titleLang name
		}
	}

	// TODO ?

	funcStat(result.GetAddr(), get.GetAddr(), set.GetAddr());
	if (result->result != CELL_HDDGAME_CBRESULT_OK &&
		result->result != CELL_HDDGAME_CBRESULT_OK_CANCEL)
		return CELL_HDDGAME_ERROR_CBRESULT;

	// TODO ?

	return CELL_OK;
}
Esempio n. 10
0
void fsAioRead(u32 fd, mem_ptr_t<CellFsAio> aio, int xid, mem_func_ptr_t<void (*)(mem_ptr_t<CellFsAio> xaio, int error, int xid, u64 size)> func)
{
	while (g_FsAioReadCur != xid)
	{
		Sleep(1);
		if (Emu.IsStopped())
		{
			ConLog.Warning("fsAioRead() aborted");
			return;
		}
	}

	vfsFileBase* orig_file;
	if(!sys_fs.CheckId(fd, orig_file)) return;

	std::string path = orig_file->GetPath();
	std::string::size_type first_slash = path.find('/');
	if (first_slash == std::string::npos)
	{
		path = "";
	}
	else
	{
		path = path.substr(first_slash+1,std::string::npos);
	}

	u64 nbytes = aio->size;
	u32 buf_addr = aio->buf_addr;

	u32 res = 0;
	u32 error = CELL_OK;

	vfsStream& file = *(vfsStream*)orig_file;
	const u64 old_pos = file.Tell();
	file.Seek((u64)aio->offset);

	u32 count = nbytes;
	if (nbytes != (u64)count)
	{
		error = CELL_ENOMEM;
		goto fin;
	}

	if (!Memory.IsGoodAddr(buf_addr))
	{
		error = CELL_EFAULT;
		goto fin;
	}

	if (count) if (u32 frag = buf_addr & 4095) // memory page fragment
	{
		u32 req = min(count, 4096 - frag);
		u32 read = file.Read(Memory + buf_addr, req);
		buf_addr += req;
		res += read;
		count -= req;
		if (read < req) goto fin;
	}

	for (u32 pages = count / 4096; pages > 0; pages--) // full pages
	{
		if (!Memory.IsGoodAddr(buf_addr)) goto fin; // ??? (probably EFAULT)
		u32 read = file.Read(Memory + buf_addr, 4096);
		buf_addr += 4096;
		res += read;
		count -= 4096;
		if (read < 4096) goto fin;
	}

	if (count) // last fragment
	{
		if (!Memory.IsGoodAddr(buf_addr)) goto fin;
		res += file.Read(Memory + buf_addr, count);
	}

fin:
	file.Seek(old_pos);

	ConLog.Warning("*** fsAioRead(fd=%d, offset=0x%llx, buf_addr=0x%x, size=0x%x, error=0x%x, res=0x%x, xid=0x%x [%s])",
		fd, (u64)aio->offset, buf_addr, (u64)aio->size, error, res, xid, path.c_str());

	if (func) // start callback thread
	{
		func.async(aio, error, xid, res);
	}

	/*CPUThread& thr = Emu.GetCallbackThread();
	while (thr.IsAlive())
	{
		Sleep(1);
		if (Emu.IsStopped())
		{
			ConLog.Warning("fsAioRead() aborted");
			break;
		}
	}*/

	g_FsAioReadCur++;
}
Esempio n. 11
0
int cellSaveDataListLoad2(u32 version, mem_ptr_t<CellSaveDataSetList> setList, mem_ptr_t<CellSaveDataSetBuf> setBuf,
						  mem_func_ptr_t<CellSaveDataListCallback> funcList, mem_func_ptr_t<CellSaveDataStatCallback> funcStat, mem_func_ptr_t<CellSaveDataFileCallback> funcFile,
						  u32 container, u32 userdata_addr)
{
	cellSysutil.Warning("cellSaveDataListLoad2(version=%d, setList_addr=0x%x, setBuf_addr=0x%x, funcList_addr=0x%x, funcStat_addr=0x%x, funcFile_addr=0x%x, container=%d, userdata_addr=0x%x)",
		version, setList.GetAddr(), setBuf.GetAddr(), funcList.GetAddr(), funcStat.GetAddr(), funcFile.GetAddr(), container, userdata_addr);
	
	if (!setList.IsGood() || !setBuf.IsGood() || !funcList.IsGood() || !funcStat.IsGood() || !funcFile.IsGood())
		return CELL_SAVEDATA_ERROR_PARAM;

	MemoryAllocator<CellSaveDataCBResult> result;
	MemoryAllocator<CellSaveDataListGet> listGet;
	MemoryAllocator<CellSaveDataListSet> listSet;
	MemoryAllocator<CellSaveDataStatGet> statGet;
	MemoryAllocator<CellSaveDataStatSet> statSet;

	std::string saveBaseDir = "/dev_hdd0/home/00000001/savedata/"; // TODO: Get the path of the current user
	vfsDir dir(saveBaseDir);
	if(!dir.IsOpened())
		return CELL_SAVEDATA_ERROR_INTERNAL;

	std::string dirNamePrefix = Memory.ReadString(setList->dirNamePrefix_addr);
	std::vector<SaveDataEntry> saveEntries;
	for(const DirEntryInfo* entry = dir.Read(); entry; entry = dir.Read())
	{
		if (entry->flags & DirEntry_TypeDir && entry->name.substr(0,dirNamePrefix.size()) == dirNamePrefix)
		{
			// Count the amount of matches and the amount of listed directories
			listGet->dirListNum++;
			if (listGet->dirListNum > setBuf->dirListMax)
				continue;
			listGet->dirNum++;

			std::string saveDir = saveBaseDir + entry->name;
			addSaveDataEntry(saveEntries, saveDir);
		}
	}

	// Sort the entries and fill the listGet->dirList array
	std::sort(saveEntries.begin(), saveEntries.end(), sortSaveDataEntry(setList->sortType, setList->sortOrder));
	listGet->dirList.SetAddr(setBuf->buf_addr);
	CellSaveDataDirList* dirList = (CellSaveDataDirList*)Memory.VirtualToRealAddr(listGet->dirList.GetAddr());
	for (u32 i=0; i<saveEntries.size(); i++) {
		memcpy(dirList[i].dirName, saveEntries[i].dirName.c_str(), CELL_SAVEDATA_DIRNAME_SIZE);
		memcpy(dirList[i].listParam, saveEntries[i].listParam.c_str(), CELL_SAVEDATA_SYSP_LPARAM_SIZE);
	}

	funcList(result.GetAddr(), listGet.GetAddr(), listSet.GetAddr());
	if (result->result < 0)	{
		ConLog.Error("cellSaveDataListLoad2: CellSaveDataListCallback failed."); // TODO: Once we verify that the entire SysCall is working, delete this debug error message.
		return CELL_SAVEDATA_ERROR_CBRESULT;
	}
	if (!listSet->fixedList.IsGood())
		return CELL_SAVEDATA_ERROR_PARAM;

	setSaveDataList(saveEntries, (u32)listSet->fixedList.GetAddr(), listSet->fixedListNum);
	if (listSet->newData.IsGood())
		addNewSaveDataEntry(saveEntries, (u32)listSet->newData.GetAddr());
	if (saveEntries.size() == 0) {
		ConLog.Warning("cellSaveDataListLoad2: No save entries found!"); // TODO: Find a better way to handle this error
		return CELL_SAVEDATA_RET_OK;
	}

	u32 focusIndex = focusSaveDataEntry(saveEntries, listSet->focusPosition);
	// TODO: Display the dialog here
	u32 selectedIndex = focusIndex; // TODO: Until the dialog is implemented, select always the focused entry
	getSaveDataStat(saveEntries[selectedIndex], statGet.GetAddr());
	result->userdata_addr = userdata_addr;

	funcStat(result.GetAddr(), statGet.GetAddr(), statSet.GetAddr());
	Memory.Free(statGet->fileList.GetAddr());
	if (result->result < 0)	{
		ConLog.Error("cellSaveDataListLoad2: CellSaveDataStatCallback failed."); // TODO: Once we verify that the entire SysCall is working, delete this debug error message.
		return CELL_SAVEDATA_ERROR_CBRESULT;
	}
	/*if (statSet->setParam.IsGood())
		// TODO: Write PARAM.SFO file
	*/

	// Enter the loop where the save files are read/created/deleted.
	s32 ret = modifySaveDataFiles(funcFile, result.GetAddr(), saveBaseDir + (char*)statGet->dir.dirName);

	// TODO: There are other returns in this function that doesn't free the memory. Fix it (without using goto's, please).
	for (auto& entry : saveEntries) {
		delete[] entry.iconBuf;
		entry.iconBuf = nullptr;
	}

	return ret;
}
Esempio n. 12
0
int cellSaveDataFixedLoad2(u32 version,  mem_ptr_t<CellSaveDataSetList> setList, mem_ptr_t<CellSaveDataSetBuf> setBuf,
						   mem_func_ptr_t<CellSaveDataFixedCallback> funcFixed, mem_func_ptr_t<CellSaveDataStatCallback> funcStat, mem_func_ptr_t<CellSaveDataFileCallback> funcFile,
						   u32 container, u32 userdata_addr)
{
	cellSysutil.Warning("cellSaveDataFixedLoad2(version=%d, setList_addr=0x%x, setBuf=0x%x, funcList=0x%x, funcStat=0x%x, funcFile=0x%x, container=%d, userdata_addr=0x%x)",
		version, setList.GetAddr(), setBuf.GetAddr(), funcFixed.GetAddr(), funcStat.GetAddr(), funcFile.GetAddr(), container, userdata_addr);

	if (!setList.IsGood() || !setBuf.IsGood() || !funcFixed.IsGood() || !funcStat.IsGood() || !funcFile.IsGood())
		return CELL_SAVEDATA_ERROR_PARAM;

	MemoryAllocator<CellSaveDataCBResult> result;
	MemoryAllocator<CellSaveDataListGet> listGet;
	MemoryAllocator<CellSaveDataFixedSet> fixedSet;
	MemoryAllocator<CellSaveDataStatGet> statGet;
	MemoryAllocator<CellSaveDataStatSet> statSet;
	MemoryAllocator<CellSaveDataFileGet> fileGet;
	MemoryAllocator<CellSaveDataFileSet> fileSet;

	std::string saveBaseDir = "/dev_hdd0/home/00000001/savedata/"; // TODO: Get the path of the current user
	vfsDir dir(saveBaseDir);
	if (!dir.IsOpened())
		return CELL_SAVEDATA_ERROR_INTERNAL;

	std::string dirNamePrefix = Memory.ReadString(setList->dirNamePrefix_addr);
	std::vector<SaveDataEntry> saveEntries;
	for (const DirEntryInfo* entry = dir.Read(); entry; entry = dir.Read())
	{
		if (entry->flags & DirEntry_TypeDir && entry->name.substr(0, dirNamePrefix.size()) == dirNamePrefix)
		{
			// Count the amount of matches and the amount of listed directories
			listGet->dirListNum++;
			if (listGet->dirListNum > setBuf->dirListMax)
				continue;
			listGet->dirNum++;

			std::string saveDir = saveBaseDir + entry->name;
			addSaveDataEntry(saveEntries, saveDir);
		}
	}

	// Sort the entries and fill the listGet->dirList array
	std::sort(saveEntries.begin(), saveEntries.end(), sortSaveDataEntry(setList->sortType, setList->sortOrder));
	listGet->dirList.SetAddr(setBuf->buf_addr);
	CellSaveDataDirList* dirList = (CellSaveDataDirList*)Memory.VirtualToRealAddr(listGet->dirList.GetAddr());
	for (u32 i = 0; i<saveEntries.size(); i++) {
		memcpy(dirList[i].dirName, saveEntries[i].dirName.c_str(), CELL_SAVEDATA_DIRNAME_SIZE);
		memcpy(dirList[i].listParam, saveEntries[i].listParam.c_str(), CELL_SAVEDATA_SYSP_LPARAM_SIZE);
	}
	funcFixed(result.GetAddr(), listGet.GetAddr(), fixedSet.GetAddr());
	if (result->result < 0)	{
		ConLog.Error("cellSaveDataFixedLoad2: CellSaveDataFixedCallback failed."); // TODO: Once we verify that the entire SysCall is working, delete this debug error message.
		return CELL_SAVEDATA_ERROR_CBRESULT;
	}
	setSaveDataFixed(saveEntries, fixedSet.GetAddr());
	getSaveDataStat(saveEntries[0], statGet.GetAddr()); // There should be only one element in this list
	// TODO: Display the Yes|No dialog here
	result->userdata_addr = userdata_addr;

	funcStat(result.GetAddr(), statGet.GetAddr(), statSet.GetAddr());
	Memory.Free(statGet->fileList.GetAddr());
	if (result->result < 0)	{
		ConLog.Error("cellSaveDataFixedLoad2: CellSaveDataStatCallback failed."); // TODO: Once we verify that the entire SysCall is working, delete this debug error message.
		return CELL_SAVEDATA_ERROR_CBRESULT;
	}
	/*if (statSet->setParam.IsGood())
		// TODO: Write PARAM.SFO file
	*/

	fileGet->excSize = 0;
	while (true)
	{
		funcFile(result.GetAddr(), fileGet.GetAddr(), fileSet.GetAddr());
		if (result->result < 0)	{
			ConLog.Error("cellSaveDataFixedLoad2: CellSaveDataStatCallback failed."); // TODO: Once we verify that the entire SysCall is working, delete this debug error message.
			return CELL_SAVEDATA_ERROR_CBRESULT;
		}
		if (result->result == CELL_SAVEDATA_CBRESULT_OK_LAST)
			break;
		switch (fileSet->fileOperation)
		{
		case CELL_SAVEDATA_FILEOP_READ:
			fileGet->excSize = readSaveDataFile(fileSet.GetAddr(), saveBaseDir + (char*)statGet->dir.dirName);
			break;
		case CELL_SAVEDATA_FILEOP_WRITE:
			fileGet->excSize = writeSaveDataFile(fileSet.GetAddr(), saveBaseDir + (char*)statGet->dir.dirName);
			break;
		case CELL_SAVEDATA_FILEOP_DELETE:
		case CELL_SAVEDATA_FILEOP_WRITE_NOTRUNC:
			ConLog.Warning("cellSaveDataFixedLoad2: TODO: fileSet->fileOperation not yet implemented");
			break;
		}
	}

	// TODO: There are other returns in this function that doesn't free the memory. Fix it (without using goto's, please).
	for (auto& entry : saveEntries) {
		delete[] entry.iconBuf;
		entry.iconBuf = nullptr;
	}

	return CELL_SAVEDATA_RET_OK;
}
Esempio n. 13
0
File: lv2Fs.cpp Progetto: Subv/rpcs3
s32 cellFsStReadWaitCallback(u32 fd, u64 size, mem_func_ptr_t<void (*)(int xfd, u64 xsize)> func)
{
	sys_fs->Todo("cellFsStReadWaitCallback(fd=%d, size = 0x%llx, func_addr = 0x%x)", fd, size, func.GetAddr());

	vfsStream* file;
	if(!sys_fs->CheckId(fd, file)) return CELL_ESRCH;
	
	return CELL_OK;
}
Esempio n. 14
0
int sceNpTrophyRegisterContext(u32 context, u32 handle, mem_func_ptr_t<SceNpTrophyStatusCallback> statusCb, u32 arg_addr, u64 options)
{
	sceNpTrophy->Warning("sceNpTrophyRegisterContext(context=%d, handle=%d, statusCb_addr=0x%x, arg_addr=0x%x, options=0x%llx)",
		context, handle, statusCb.GetAddr(), arg_addr, options);

	if (!(s_npTrophyInstance.m_bInitialized))
		return SCE_NP_TROPHY_ERROR_NOT_INITIALIZED;
	if (options & (~(u64)1))
		return SCE_NP_TROPHY_ERROR_NOT_SUPPORTED;
	if (context >= s_npTrophyInstance.contexts.size())
		return SCE_NP_TROPHY_ERROR_UNKNOWN_CONTEXT;
	// TODO: There are other possible errors

	sceNpTrophyInternalContext& ctxt = s_npTrophyInstance.contexts[context];
	if (!ctxt.trp_stream)
		return SCE_NP_TROPHY_ERROR_CONF_DOES_NOT_EXIST;

	TRPLoader trp(*(ctxt.trp_stream));
	if (!trp.LoadHeader())
		return SCE_NP_TROPHY_ERROR_ILLEGAL_UPDATE;

	// Rename or discard certain entries based on the files found
	const size_t kTargetBufferLength = 31;
	char target[kTargetBufferLength+1];
	target[kTargetBufferLength] = 0;
	snprintf(target, kTargetBufferLength, "TROP_%02d.SFM", Ini.SysLanguage.GetValue());

	if (trp.ContainsEntry(target)) {
		trp.RemoveEntry("TROPCONF.SFM");
		trp.RemoveEntry("TROP.SFM");
		trp.RenameEntry(target, "TROPCONF.SFM");
	}
	else if (trp.ContainsEntry("TROP.SFM")) {
		trp.RemoveEntry("TROPCONF.SFM");
		trp.RenameEntry("TROP.SFM", "TROPCONF.SFM");
	}
	else if (!trp.ContainsEntry("TROPCONF.SFM")) {
		return SCE_NP_TROPHY_ERROR_ILLEGAL_UPDATE;
	}

	// Discard unnecessary TROP_XX.SFM files
	for (int i=0; i<=18; i++) {
		snprintf(target, kTargetBufferLength, "TROP_%02d.SFM", i);
		if (i != Ini.SysLanguage.GetValue())
			trp.RemoveEntry(target);
	}

	// TODO: Get the path of the current user
	std::string trophyPath = "/dev_hdd0/home/00000001/trophy/" + ctxt.trp_name;
	if (!trp.Install(trophyPath))
		return SCE_NP_TROPHY_ERROR_ILLEGAL_UPDATE;
	
	TROPUSRLoader* tropusr = new TROPUSRLoader();
	std::string trophyUsrPath = trophyPath + "/TROPUSR.DAT";
	std::string trophyConfPath = trophyPath + "/TROPCONF.SFM";
	tropusr->Load(trophyUsrPath, trophyConfPath);
	ctxt.tropusr.reset(tropusr);

	// TODO: Callbacks
	statusCb(context, SCE_NP_TROPHY_STATUS_INSTALLED, 100, 100, arg_addr);
	statusCb(context, SCE_NP_TROPHY_STATUS_PROCESSING_COMPLETE, 100, 100, arg_addr);
	
	return CELL_OK;
}
Esempio n. 15
0
int cellMsgDialogOpen2(u32 type, mem_list_ptr_t<u8> msgString, mem_func_ptr_t<CellMsgDialogCallback> callback, u32 userData, u32 extParam)
{
	cellSysutil->Warning("cellMsgDialogOpen2(type=0x%x, msgString_addr=0x%x, callback_addr=0x%x, userData=0x%x, extParam=0x%x)",
		type, msgString.GetAddr(), callback.GetAddr(), userData, extParam);
	
	if (!msgString.IsGood() || !callback.IsGood())
	{
		return CELL_EFAULT;
	}

	//type |= CELL_MSGDIALOG_TYPE_PROGRESSBAR_SINGLE;
	//type |= CELL_MSGDIALOG_TYPE_BUTTON_TYPE_YESNO;

	MsgDialogState old = msgDialogNone;
	if (!g_msg_dialog_state.compare_exchange_strong(old, msgDialogOpen))
	{
		return CELL_SYSUTIL_ERROR_BUSY;
	}

	thread t("MsgDialog thread", [=]()
	{
		switch (type & CELL_MSGDIALOG_TYPE_SE_TYPE)
		{
		case CELL_MSGDIALOG_TYPE_SE_TYPE_NORMAL: LOG_WARNING(Log::HLE, "%s", msgString.GetString()); break;
		case CELL_MSGDIALOG_TYPE_SE_TYPE_ERROR: LOG_ERROR(Log::HLE, "%s", msgString.GetString()); break;
		}

		switch (type & CELL_MSGDIALOG_TYPE_SE_MUTE) // TODO
		{
		case CELL_MSGDIALOG_TYPE_SE_MUTE_OFF: break;
		case CELL_MSGDIALOG_TYPE_SE_MUTE_ON: break;
		}

		switch (type & CELL_MSGDIALOG_TYPE_BG) // TODO
		{
		case CELL_MSGDIALOG_TYPE_BG_INVISIBLE: break; 
		case CELL_MSGDIALOG_TYPE_BG_VISIBLE: break;
		}

		switch (type & CELL_MSGDIALOG_TYPE_DEFAULT_CURSOR) // TODO
		{
		case CELL_MSGDIALOG_TYPE_DEFAULT_CURSOR_NO: break;
		default: break;
		}

		u64 status = CELL_MSGDIALOG_BUTTON_NONE;

		volatile bool m_signal = false;
		wxGetApp().CallAfter([&]()
		{
			wxWindow* parent = nullptr; // TODO: align it better

			m_gauge1 = nullptr;
			m_gauge2 = nullptr;
			m_text1 = nullptr;
			m_text2 = nullptr;
			wxButton* m_button_ok = nullptr;
			wxButton* m_button_yes = nullptr;
			wxButton* m_button_no = nullptr;

			g_msg_dialog = new wxDialog(parent, wxID_ANY, type & CELL_MSGDIALOG_TYPE_SE_TYPE ? "" : "Error", wxDefaultPosition, wxDefaultSize);

			g_msg_dialog->SetExtraStyle(g_msg_dialog->GetExtraStyle() | wxWS_EX_TRANSIENT);

			wxSizer* sizer1 = new wxBoxSizer(wxVERTICAL);

			wxStaticText* m_text = new wxStaticText(g_msg_dialog, wxID_ANY, wxString(msgString.GetString(), wxConvUTF8));
			sizer1->Add(m_text, 0, wxALIGN_CENTER_HORIZONTAL | wxLEFT | wxRIGHT | wxTOP, 16);

			switch (type & CELL_MSGDIALOG_TYPE_PROGRESSBAR)
			{
			case CELL_MSGDIALOG_TYPE_PROGRESSBAR_DOUBLE:
				m_gauge2 = new wxGauge(g_msg_dialog, wxID_ANY, 100, wxDefaultPosition, wxSize(300, -1), wxGA_HORIZONTAL | wxGA_SMOOTH);
				m_text2 = new wxStaticText(g_msg_dialog, wxID_ANY, "");
				m_text2->SetAutoLayout(true);
				
			case CELL_MSGDIALOG_TYPE_PROGRESSBAR_SINGLE:
				m_gauge1 = new wxGauge(g_msg_dialog, wxID_ANY, 100, wxDefaultPosition, wxSize(300, -1), wxGA_HORIZONTAL | wxGA_SMOOTH);
				m_text1 = new wxStaticText(g_msg_dialog, wxID_ANY, "");
				m_text1->SetAutoLayout(true);
				
			case CELL_MSGDIALOG_TYPE_PROGRESSBAR_NONE:
				break;
			}

			if (m_gauge1)
			{
				sizer1->Add(m_text1, 0, wxALIGN_CENTER_HORIZONTAL | wxLEFT | wxRIGHT | wxTOP, 8);
				sizer1->Add(m_gauge1, 0, wxALIGN_CENTER_HORIZONTAL | wxLEFT | wxRIGHT, 16);
				m_gauge1->SetValue(0);
			}
			if (m_gauge2)
			{
				sizer1->Add(m_text2, 0, wxALIGN_CENTER_HORIZONTAL | wxLEFT | wxRIGHT | wxTOP, 8);
				sizer1->Add(m_gauge2, 0, wxALIGN_CENTER_HORIZONTAL | wxLEFT | wxRIGHT, 16);
				m_gauge2->SetValue(0);
			}
				
			wxBoxSizer* buttons = new wxBoxSizer(wxHORIZONTAL);

			switch (type & CELL_MSGDIALOG_TYPE_BUTTON_TYPE)
			{
			case CELL_MSGDIALOG_TYPE_BUTTON_TYPE_NONE:
				break;

			case CELL_MSGDIALOG_TYPE_BUTTON_TYPE_YESNO:
				m_button_yes = new wxButton(g_msg_dialog, wxID_YES);
				buttons->Add(m_button_yes, 0, wxALIGN_CENTER_HORIZONTAL | wxRIGHT, 8);
				m_button_no = new wxButton(g_msg_dialog, wxID_NO);
				buttons->Add(m_button_no, 0, wxALIGN_CENTER_HORIZONTAL, 16);

				sizer1->Add(buttons, 0, wxALIGN_CENTER_HORIZONTAL | wxLEFT | wxRIGHT | wxTOP, 16);
				break;

			case CELL_MSGDIALOG_TYPE_BUTTON_TYPE_OK:
				m_button_ok = new wxButton(g_msg_dialog, wxID_OK);
				buttons->Add(m_button_ok, 0, wxALIGN_CENTER_HORIZONTAL, 16);

				sizer1->Add(buttons, 0, wxALIGN_CENTER_HORIZONTAL | wxLEFT | wxRIGHT | wxTOP, 16);
				break;
			}

			sizer1->AddSpacer(16);

			g_msg_dialog->SetSizerAndFit(sizer1);
			g_msg_dialog->Centre(wxBOTH);
			g_msg_dialog->Show();
			g_msg_dialog->Enable();

			g_msg_dialog->Bind(wxEVT_BUTTON, [&](wxCommandEvent& event)
			{
				status = (event.GetId() == wxID_NO) ? CELL_MSGDIALOG_BUTTON_NO : CELL_MSGDIALOG_BUTTON_YES /* OK */;
				g_msg_dialog->Hide();
				m_wait_until = get_system_time();
				g_msg_dialog_state = msgDialogClose;
			});


			g_msg_dialog->Bind(wxEVT_CLOSE_WINDOW, [&](wxCloseEvent& event)
			{
				if (type & CELL_MSGDIALOG_TYPE_DISABLE_CANCEL)
				{
				}
				else
				{
					status = CELL_MSGDIALOG_BUTTON_ESCAPE;
					g_msg_dialog->Hide();
					m_wait_until = get_system_time();
					g_msg_dialog_state = msgDialogClose;
				}
			});

			m_signal = true;
		});

		while (!m_signal)
		{
			std::this_thread::sleep_for(std::chrono::milliseconds(1));
		}

		while (g_msg_dialog_state == msgDialogOpen || get_system_time() < m_wait_until)
		{
			if (Emu.IsStopped())
			{
				g_msg_dialog_state = msgDialogAbort;
				break;
			}
			std::this_thread::sleep_for(std::chrono::milliseconds(1));
		}

		if (callback && (g_msg_dialog_state != msgDialogAbort))
			callback.async(status, userData);

		wxGetApp().CallAfter([&]()
		{
			delete g_msg_dialog;
			g_msg_dialog = nullptr;
		});

		g_msg_dialog_state = msgDialogNone;
	});
	t.detach();

	return CELL_OK;
}
Esempio n. 16
0
int cellHddGameCheck(u32 version, u32 dirName_addr, u32 errDialog, mem_func_ptr_t<CellHddGameStatCallback> funcStat, u32 container)
{
	cellSysutil.Warning("cellHddGameCheck(version=%d, dirName_addr=0x%xx, errDialog=%d, funcStat_addr=0x%x, container=%d)",
		version, dirName_addr, errDialog, funcStat, container);

	if (!Memory.IsGoodAddr(dirName_addr) || !funcStat.IsGood())
		return CELL_HDDGAME_ERROR_PARAM;

	std::string dirName = Memory.ReadString(dirName_addr);
	if (dirName.size() != 9)
		return CELL_HDDGAME_ERROR_PARAM;

	MemoryAllocator<CellHddGameSystemFileParam> param;
	MemoryAllocator<CellHddGameCBResult> result;
	MemoryAllocator<CellHddGameStatGet> get;
	MemoryAllocator<CellHddGameStatSet> set;

	get->hddFreeSizeKB = 40 * 1024 * 1024; // 40 GB, TODO: Use the free space of the computer's HDD where RPCS3 is being run.
	get->isNewData = CELL_HDDGAME_ISNEWDATA_EXIST;
	get->sysSizeKB = 0; // TODO
	get->st_atime__  = 0; // TODO
	get->st_ctime__  = 0; // TODO
	get->st_mtime__  = 0; // TODO
	get->sizeKB = CELL_HDDGAME_SIZEKB_NOTCALC;
	memcpy(get->contentInfoPath, ("/dev_hdd0/game/"+dirName).c_str(), CELL_HDDGAME_PATH_MAX);
	memcpy(get->hddGamePath, ("/dev_hdd0/game/"+dirName+"/USRDIR").c_str(), CELL_HDDGAME_PATH_MAX);

	if (!Emu.GetVFS().ExistsDir(("/dev_hdd0/game/"+dirName).c_str()))
	{
		get->isNewData = CELL_HDDGAME_ISNEWDATA_NODIR;
	}
	else
	{
		// TODO: Is cellHddGameCheck really responsible for writing the information in get->getParam ? (If not, delete this else)

		vfsFile f(("/dev_hdd0/game/"+dirName+"/PARAM.SFO").c_str());
		PSFLoader psf(f);
		if (!psf.Load(false)) {
			return CELL_HDDGAME_ERROR_BROKEN;
		}

		get->getParam.parentalLevel = psf.GetInteger("PARENTAL_LEVEL");
		get->getParam.attribute = psf.GetInteger("ATTRIBUTE");
		get->getParam.resolution = psf.GetInteger("RESOLUTION");
		get->getParam.soundFormat = psf.GetInteger("SOUND_FORMAT");
		std::string title = psf.GetString("TITLE");
		memcpy(get->getParam.title, title.c_str(), min<size_t>(CELL_HDDGAME_SYSP_TITLE_SIZE,title.length()+1));
		std::string app_ver = psf.GetString("APP_VER");
		memcpy(get->getParam.dataVersion, app_ver.c_str(), min<size_t>(CELL_HDDGAME_SYSP_VERSION_SIZE,app_ver.length()+1));
		memcpy(get->getParam.titleId, dirName.c_str(), min<size_t>(CELL_HDDGAME_SYSP_TITLEID_SIZE,dirName.length()+1));

		for (u32 i=0; i<CELL_HDDGAME_SYSP_LANGUAGE_NUM; i++) {
			char key [16];
			sprintf(key, "TITLE_%02d", i);
			title = psf.GetString(key);
			memcpy(get->getParam.titleLang[i], title.c_str(), min<size_t>(CELL_HDDGAME_SYSP_TITLE_SIZE, title.length() + 1));
		}
	}

	// TODO ?

	funcStat(result.GetAddr(), get.GetAddr(), set.GetAddr());
	if (result->result != CELL_HDDGAME_CBRESULT_OK &&
		result->result != CELL_HDDGAME_CBRESULT_OK_CANCEL)
		return CELL_HDDGAME_ERROR_CBRESULT;

	// TODO ?

	return CELL_OK;
}