Merge pull request #4887 from unknownbrackets/io-minor

Implement a few more ioctl commands
This commit is contained in:
Henrik Rydgård 2013-12-28 00:17:37 -08:00
commit ff10d0b0f2
10 changed files with 232 additions and 76 deletions

View File

@ -489,6 +489,14 @@ bool DirectoryFileSystem::OwnsHandle(u32 handle) {
return (iter != entries.end());
}
int DirectoryFileSystem::Ioctl(u32 handle, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 outlen, int &usec) {
return SCE_KERNEL_ERROR_ERRNO_FUNCTION_NOT_SUPPORTED;
}
int DirectoryFileSystem::DevType(u32 handle) {
return PSP_DEV_TYPE_FILE;
}
size_t DirectoryFileSystem::ReadFile(u32 handle, u8 *pointer, s64 size) {
EntryMap::iterator iter = entries.find(handle);
if (iter != entries.end())
@ -767,6 +775,14 @@ bool VFSFileSystem::OwnsHandle(u32 handle) {
return (iter != entries.end());
}
int VFSFileSystem::Ioctl(u32 handle, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 outlen, int &usec) {
return SCE_KERNEL_ERROR_ERRNO_FUNCTION_NOT_SUPPORTED;
}
int VFSFileSystem::DevType(u32 handle) {
return PSP_DEV_TYPE_FILE;
}
size_t VFSFileSystem::ReadFile(u32 handle, u8 *pointer, s64 size) {
INFO_LOG(FILESYS,"VFSFileSystem::ReadFile %08x %p %i", handle, pointer, (u32)size);
EntryMap::iterator iter = entries.find(handle);

View File

@ -95,6 +95,8 @@ public:
size_t SeekFile(u32 handle, s32 position, FileMove type);
PSPFileInfo GetFileInfo(std::string filename);
bool OwnsHandle(u32 handle);
int Ioctl(u32 handle, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 outlen, int &usec);
int DevType(u32 handle);
bool MkDir(const std::string &dirname);
bool RmDir(const std::string &dirname);
@ -132,6 +134,8 @@ public:
size_t SeekFile(u32 handle, s32 position, FileMove type);
PSPFileInfo GetFileInfo(std::string filename);
bool OwnsHandle(u32 handle);
int Ioctl(u32 handle, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 outlen, int &usec);
int DevType(u32 handle);
bool MkDir(const std::string &dirname);
bool RmDir(const std::string &dirname);

View File

@ -18,7 +18,8 @@
#pragma once
#include "../../Globals.h"
#include "ChunkFile.h"
#include "Common/ChunkFile.h"
#include "Core/HLE/sceKernel.h"
enum FileAccess
{
@ -42,6 +43,13 @@ enum FileType
FILETYPE_DIRECTORY=2
};
enum DevType
{
PSP_DEV_TYPE_BLOCK = 0x04,
PSP_DEV_TYPE_FILE = 0x10,
PSP_DEV_TYPE_ALIAS = 0x20,
};
class IHandleAllocator {
public:
@ -120,6 +128,8 @@ public:
virtual int RenameFile(const std::string &from, const std::string &to) = 0;
virtual bool RemoveFile(const std::string &filename) = 0;
virtual bool GetHostPath(const std::string &inpath, std::string &outpath) = 0;
virtual int Ioctl(u32 handle, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 outlen, int &usec) = 0;
virtual int DevType(u32 handle) = 0;
};
@ -140,6 +150,8 @@ public:
virtual int RenameFile(const std::string &from, const std::string &to) {return -1;}
virtual bool RemoveFile(const std::string &filename) {return false;}
virtual bool GetHostPath(const std::string &inpath, std::string &outpath) {return false;}
virtual int Ioctl(u32 handle, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 outlen, int &usec) {return SCE_KERNEL_ERROR_ERRNO_FUNCTION_NOT_SUPPORTED; }
virtual int DevType(u32 handle) {return 0;}
};

View File

@ -18,6 +18,8 @@
#include "Globals.h"
#include "Common/Common.h"
#include "Core/FileSystems/ISOFileSystem.h"
#include "Core/HLE/sceKernel.h"
#include "Core/MemMap.h"
#include "Core/Reporting.h"
#include <cstring>
#include <cstdio>
@ -452,6 +454,71 @@ bool ISOFileSystem::OwnsHandle(u32 handle)
return (iter != entries.end());
}
int ISOFileSystem::Ioctl(u32 handle, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 outlen, int &usec) {
EntryMap::iterator iter = entries.find(handle);
if (iter == entries.end()) {
ERROR_LOG(FILESYS, "Ioctl on a bad file handle");
return SCE_KERNEL_ERROR_BADF;
}
OpenFileEntry &e = iter->second;
switch (cmd) {
// Get ISO9660 volume descriptor (from open ISO9660 file.)
case 0x01020001:
if (e.isBlockSectorMode) {
ERROR_LOG(FILESYS, "Unsupported read volume descriptor command on a umd block device");
return SCE_KERNEL_ERROR_ERRNO_FUNCTION_NOT_SUPPORTED;
}
if (!Memory::IsValidAddress(outdataPtr) || outlen < 0x800) {
WARN_LOG_REPORT(FILESYS, "sceIoIoctl: Invalid out pointer while reading ISO9660 volume descriptor");
return SCE_KERNEL_ERROR_ERRNO_INVALID_ARGUMENT;
}
INFO_LOG(SCEIO, "sceIoIoctl: reading ISO9660 volume descriptor read");
blockDevice->ReadBlock(16, Memory::GetPointer(outdataPtr));
return 0;
// Get ISO9660 path table (from open ISO9660 file.)
case 0x01020002:
if (e.isBlockSectorMode) {
ERROR_LOG(FILESYS, "Unsupported read path table command on a umd block device");
return SCE_KERNEL_ERROR_ERRNO_FUNCTION_NOT_SUPPORTED;
}
VolDescriptor desc;
blockDevice->ReadBlock(16, (u8 *)&desc);
if (outlen < (u32)desc.pathTableLengthLE) {
return SCE_KERNEL_ERROR_ERRNO_INVALID_ARGUMENT;
} else {
int block = (u16)desc.firstLETableSectorLE;
u32 size = (u32)desc.pathTableLengthLE;
u8 *out = Memory::GetPointer(outdataPtr);
while (size >= 2048) {
blockDevice->ReadBlock(block++, out);
out += 2048;
}
// The remaining (or, usually, only) partial sector.
if (size > 0) {
u8 temp[2048];
blockDevice->ReadBlock(block, temp);
memcpy(out, temp, size);
}
return 0;
}
}
return SCE_KERNEL_ERROR_ERRNO_FUNCTION_NOT_SUPPORTED;
}
int ISOFileSystem::DevType(u32 handle)
{
EntryMap::iterator iter = entries.find(handle);
return iter->second.isBlockSectorMode ? PSP_DEV_TYPE_BLOCK : PSP_DEV_TYPE_FILE;
}
size_t ISOFileSystem::ReadFile(u32 handle, u8 *pointer, s64 size)
{
EntryMap::iterator iter = entries.find(handle);

View File

@ -39,6 +39,8 @@ public:
size_t SeekFile(u32 handle, s32 position, FileMove type);
PSPFileInfo GetFileInfo(std::string filename);
bool OwnsHandle(u32 handle);
int Ioctl(u32 handle, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 outlen, int &usec);
int DevType(u32 handle);
size_t WriteFile(u32 handle, const u8 *pointer, s64 size);
bool GetHostPath(const std::string &inpath, std::string &outpath) {return false;}

View File

@ -479,6 +479,24 @@ bool MetaFileSystem::RemoveFile(const std::string &filename)
}
}
int MetaFileSystem::Ioctl(u32 handle, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 outlen, int &usec)
{
lock_guard guard(lock);
IFileSystem *sys = GetHandleOwner(handle);
if (sys)
return sys->Ioctl(handle, cmd, indataPtr, inlen, outdataPtr, outlen, usec);
return SCE_KERNEL_ERROR_ERROR;
}
int MetaFileSystem::DevType(u32 handle)
{
lock_guard guard(lock);
IFileSystem *sys = GetHandleOwner(handle);
if (sys)
return sys->DevType(handle);
return SCE_KERNEL_ERROR_ERROR;
}
void MetaFileSystem::CloseFile(u32 handle)
{
lock_guard guard(lock);

View File

@ -102,8 +102,8 @@ public:
virtual bool RmDir(const std::string &dirname);
virtual int RenameFile(const std::string &from, const std::string &to);
virtual bool RemoveFile(const std::string &filename);
// TODO: void IoCtl(...)
virtual int Ioctl(u32 handle, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 outlen, int &usec);
virtual int DevType(u32 handle);
// Convenience helper - returns < 0 on failure.
int ReadEntireFile(const std::string &filename, std::vector<u8> &data);

View File

@ -498,6 +498,16 @@ bool VirtualDiscFileSystem::OwnsHandle(u32 handle) {
return (iter != entries.end());
}
int VirtualDiscFileSystem::Ioctl(u32 handle, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 outlen, int &usec) {
// TODO: How to support these?
return SCE_KERNEL_ERROR_ERRNO_FUNCTION_NOT_SUPPORTED;
}
int VirtualDiscFileSystem::DevType(u32 handle) {
EntryMap::iterator iter = entries.find(handle);
return iter->second.type == VFILETYPE_ISO ? PSP_DEV_TYPE_BLOCK : PSP_DEV_TYPE_FILE;
}
PSPFileInfo VirtualDiscFileSystem::GetFileInfo(std::string filename) {
PSPFileInfo x;
x.name = filename;

View File

@ -36,6 +36,8 @@ public:
void CloseFile(u32 handle);
PSPFileInfo GetFileInfo(std::string filename);
bool OwnsHandle(u32 handle);
int Ioctl(u32 handle, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 outlen, int &usec);
int DevType(u32 handle);
bool GetHostPath(const std::string &inpath, std::string &outpath);
std::vector<PSPFileInfo> GetDirListing(std::string path);

View File

@ -59,8 +59,6 @@ const int ERROR_KERNEL_BAD_FILE_DESCRIPTOR = 0x80020323;
const int ERROR_PGD_INVALID_HEADER = 0x80510204;
#define PSP_DEV_TYPE_ALIAS 0x20
/*
TODO: async io is missing features!
@ -107,6 +105,9 @@ typedef u64 SceIores;
const int PSP_COUNT_FDS = 64;
// TODO: Should be 3, and stdin/stdout/stderr are special values aliased to 0?
const int PSP_MIN_FD = 4;
const int PSP_STDOUT = 1;
const int PSP_STDERR = 2;
const int PSP_STDIN = 3;
static int asyncNotifyEvent = -1;
static int syncNotifyEvent = -1;
static SceUID fds[PSP_COUNT_FDS];
@ -553,22 +554,22 @@ u32 sceIoUnassign(const char *alias)
u32 sceKernelStdin() {
// fix Buzz Ultimate Music Quiz Crash Sporadically,issue#4497
hleEatCycles(1);
DEBUG_LOG(SCEIO, "3=sceKernelStdin()");
return 3;
DEBUG_LOG(SCEIO, "%d=sceKernelStdin()", PSP_STDIN);
return PSP_STDIN;
}
u32 sceKernelStdout() {
// fix Buzz Ultimate Music Quiz Crash Sporadically,issue#4497
hleEatCycles(1);
DEBUG_LOG(SCEIO, "1=sceKernelStdout()");
return 1;
DEBUG_LOG(SCEIO, "%d=sceKernelStdout()", PSP_STDOUT);
return PSP_STDOUT;
}
u32 sceKernelStderr() {
// fix Buzz Ultimate Music Quiz Crash Sporadically,issue#4497
hleEatCycles(1);
DEBUG_LOG(SCEIO, "2=sceKernelStderr()");
return 2;
DEBUG_LOG(SCEIO, "%d=sceKernelStderr()", PSP_STDERR);
return PSP_STDERR;
}
void __IoCompleteAsyncIO(int fd) {
@ -714,7 +715,7 @@ u32 npdrmRead(FileNode *f, u8 *data, int size) {
}
bool __IoRead(int &result, int id, u32 data_addr, int size) {
if (id == 3) {
if (id == PSP_STDIN) {
DEBUG_LOG(SCEIO, "sceIoRead STDIN");
return 0; //stdin
}
@ -828,7 +829,7 @@ u32 sceIoReadAsync(int id, u32 data_addr, int size) {
bool __IoWrite(int &result, int id, u32 data_addr, int size) {
const void *data_ptr = Memory::GetPointer(data_addr);
// Let's handle stdout/stderr specially.
if (id == 1 || id == 2) {
if (id == PSP_STDOUT || id == PSP_STDERR) {
const char *str = (const char *) data_ptr;
const int str_size = size == 0 ? 0 : (str[size - 1] == '\n' ? size - 1 : size);
INFO_LOG(SCEIO, "%s: %.*s", id == 1 ? "stdout" : "stderr", str_size, str);
@ -935,15 +936,20 @@ u32 sceIoWriteAsync(int id, u32 data_addr, int size) {
}
}
u32 sceIoGetDevType(int id)
{
ERROR_LOG_REPORT(SCEIO, "UNIMPL sceIoGetDevType(%d)", id);
u32 sceIoGetDevType(int id) {
if (id == PSP_STDOUT || id == PSP_STDERR || id == PSP_STDIN) {
DEBUG_LOG(SCEIO, "sceIoGetDevType(%d)", id);
return PSP_DEV_TYPE_FILE;
}
u32 error;
FileNode *f = __IoGetFd(id, error);
int result;
if (f)
result = PSP_DEV_TYPE_ALIAS;
else {
if (f) {
// TODO: When would this return PSP_DEV_TYPE_ALIAS?
WARN_LOG(SCEIO, "sceIoGetDevType(%d - %s)", id, f->fullpath.c_str());
result = pspFileSystem.DevType(f->handle);
} else {
ERROR_LOG(SCEIO, "sceIoGetDevType: unknown id %d", id);
result = ERROR_KERNEL_BAD_FILE_DESCRIPTOR;
}
@ -1906,8 +1912,7 @@ u32 sceIoDclose(int id) {
return kernelObjects.Destroy<DirListing>(id);
}
int __IoIoctl(u32 id, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 outlen)
{
int __IoIoctl(u32 id, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 outlen, int &usec) {
u32 error;
FileNode *f = __IoGetFd(id, error);
if (error) {
@ -1919,6 +1924,9 @@ int __IoIoctl(u32 id, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 out
return SCE_KERNEL_ERROR_ASYNC_BUSY;
}
// TODO: Move this into each command, probably?
usec = 100;
//KD Hearts:
//56:46:434 HLE\sceIo.cpp:886 E[HLE]: UNIMPL 0=sceIoIoctrl id: 0000011f, cmd 04100001, indataPtr 08b313d8, inlen 00000010, outdataPtr 00000000, outLen 0
// 0000000
@ -1977,40 +1985,6 @@ int __IoIoctl(u32 id, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 out
return (int)f->info.size;
break;
// Get ISO9660 volume descriptor (from open ISO9660 file.)
case 0x01020001:
// TODO: Should not work for umd0:/, ms0:/, etc.
// TODO: Should probably move this to something common between ISOFileSystem and VirtualDiscSystem.
if (!Memory::IsValidAddress(outdataPtr) || outlen < 0x800) {
WARN_LOG_REPORT(SCEIO, "sceIoIoctl: Invalid out pointer while reading ISO9660 volume descriptor");
return SCE_KERNEL_ERROR_ERRNO_INVALID_ARGUMENT;
} else {
INFO_LOG(SCEIO, "sceIoIoctl: reading ISO9660 volume descriptor read");
u32 descFd = pspFileSystem.OpenFile("disc0:/sce_lbn0x10_size0x800", FILEACCESS_READ);
if (descFd == 0) {
return SCE_KERNEL_ERROR_ERRNO_INVALID_ARGUMENT;
}
pspFileSystem.ReadFile(descFd, Memory::GetPointer(outdataPtr), 0x800);
pspFileSystem.CloseFile(descFd);
return 0;
}
break;
// Get ISO9660 path table (from open ISO9660 file.)
case 0x01020002:
// TODO: Should not work for umd0:/, ms0:/, etc.
// Seems like it will accept an out size > path table size, but only write path table bytes.
// If not big enough, returns SCE_KERNEL_ERROR_ERRNO_INVALID_ARGUMENT.
// Probably only the LE version.
{
char temp[256];
// We want the reported message to include the cmd, so it's unique.
sprintf(temp, "sceIoIoctl(%%s, %08x, %%08x, %%x, %%08x, %%x)", cmd);
Reporting::ReportMessage(temp, f->fullpath.c_str(), indataPtr, inlen, outdataPtr, outlen);
ERROR_LOG(SCEIO, "UNIMPL 0=sceIoIoctl id: %08x, cmd %08x, indataPtr %08x, inlen %08x, outdataPtr %08x, outLen %08x", id,cmd,indataPtr,inlen,outdataPtr,outlen);
}
break;
// Get UMD sector size
case 0x01020003:
// TODO: Should not work for umd0:/, ms0:/, etc.
@ -2093,6 +2067,8 @@ int __IoIoctl(u32 id, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 out
if (Memory::IsValidAddress(indataPtr) && inlen >= 4) {
u32 size = Memory::Read_U32(indataPtr);
if (Memory::IsValidAddress(outdataPtr) && size <= outlen) {
// sceIoRead does its own delaying (and deferring.)
usec = 0;
return sceIoRead(id, outdataPtr, size);
} else {
return SCE_KERNEL_ERROR_ERRNO_INVALID_ARGUMENT;
@ -2102,26 +2078,75 @@ int __IoIoctl(u32 id, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 out
}
break;
// Unknown command, always expects return value of 1 according to JPCSP, used by Pangya Fantasy Golf.
// TODO: This is unsupported on ms0:/ (SCE_KERNEL_ERROR_UNSUP.)
// Get current sector seek pos from UMD device file.
case 0x01d20001:
// TODO: Should work only for umd0:/, etc. not for ms0:/ or disc0:/.
// TODO: Should probably move this to something common between ISOFileSystem and VirtualDiscSystem.
INFO_LOG(SCEIO, "sceIoIoctl: Sector tell from file %i", id);
if (Memory::IsValidAddress(outdataPtr) && outlen >= 4) {
Memory::Write_U32((u32)pspFileSystem.GetSeekPos(f->handle), outdataPtr);
} else {
return SCE_KERNEL_ERROR_ERRNO_INVALID_ARGUMENT;
}
break;
// Read raw sectors from UMD device file.
case 0x01f30003:
INFO_LOG(SCEIO, "sceIoIoctl: Unknown cmd %08x always returns 1", cmd);
if(inlen != 4 || outlen != 1 || Memory::Read_U32(indataPtr) != outlen) {
INFO_LOG(SCEIO, "sceIoIoctl id: %08x, cmd %08x, indataPtr %08x, inlen %08x, outdataPtr %08x, outlen %08x has invalid parameters", id, cmd, indataPtr, inlen, outdataPtr, outlen);
return SCE_KERNEL_ERROR_INVALID_ARGUMENT;
// TODO: Should work only for umd0:/, etc. not for ms0:/ or disc0:/.
// TODO: Should probably move this to something common between ISOFileSystem and VirtualDiscSystem.
INFO_LOG(SCEIO, "sceIoIoctl: Sector read from file %i", id);
if (Memory::IsValidAddress(indataPtr) && inlen >= 4) {
u32 size = Memory::Read_U32(indataPtr);
// Note that size is specified in sectors, not bytes.
if (size > 0 && Memory::IsValidAddress(outdataPtr) && size <= outlen) {
// sceIoRead does its own delaying (and deferring.)
usec = 0;
return sceIoRead(id, outdataPtr, size);
} else {
return SCE_KERNEL_ERROR_ERRNO_INVALID_ARGUMENT;
}
} else {
return SCE_KERNEL_ERROR_ERRNO_INVALID_ARGUMENT;
}
else {
return 1;
break;
// Seek by sector in UMD device file.
case 0x01f100a6:
// TODO: Should work only for umd0:/, etc. not for ms0:/ or disc0:/.
// TODO: Should probably move this to something common between ISOFileSystem and VirtualDiscSystem.
INFO_LOG(SCEIO, "sceIoIoctl: Sector seek for file %i", id);
// Even if the size is 4, it still actually reads a 16 byte struct, it seems.
if (Memory::IsValidAddress(indataPtr) && inlen >= 4) {
struct SeekInfo {
u64 offset;
u32 unk;
u32 whence;
};
const auto seekInfo = PSPPointer<SeekInfo>::Create(indataPtr);
FileMove seek;
s64 newPos = __IoLseekDest(f, seekInfo->offset, seekInfo->whence, seek);
// Position is in sectors, don't forget.
if (newPos < 0 || newPos > f->info.size / 0x800) {
// Not allowed to seek past the end of the file with this API.
return SCE_KERNEL_ERROR_ERRNO_INVALID_FILE_SIZE;
}
pspFileSystem.SeekFile(f->handle, (s32)seekInfo->offset, seek);
} else {
return SCE_KERNEL_ERROR_ERRNO_INVALID_ARGUMENT;
}
break;
default:
{
char temp[256];
// We want the reported message to include the cmd, so it's unique.
sprintf(temp, "sceIoIoctl(%%s, %08x, %%08x, %%x, %%08x, %%x)", cmd);
Reporting::ReportMessage(temp, f->fullpath.c_str(), indataPtr, inlen, outdataPtr, outlen);
ERROR_LOG(SCEIO, "UNIMPL 0=sceIoIoctl id: %08x, cmd %08x, indataPtr %08x, inlen %08x, outdataPtr %08x, outLen %08x", id,cmd,indataPtr,inlen,outdataPtr,outlen);
// TODO: return SCE_KERNEL_ERROR_ERRNO_FUNCTION_NOT_SUPPORTED;
int result = pspFileSystem.Ioctl(f->handle, cmd, indataPtr, inlen, outdataPtr, outlen, usec);
if (result == SCE_KERNEL_ERROR_ERRNO_FUNCTION_NOT_SUPPORTED) {
char temp[256];
// We want the reported message to include the cmd, so it's unique.
sprintf(temp, "sceIoIoctl(%%s, %08x, %%08x, %%x, %%08x, %%x)", cmd);
Reporting::ReportMessage(temp, f->fullpath.c_str(), indataPtr, inlen, outdataPtr, outlen);
ERROR_LOG(SCEIO, "UNIMPL 0=sceIoIoctl id: %08x, cmd %08x, indataPtr %08x, inlen %08x, outdataPtr %08x, outLen %08x", id,cmd,indataPtr,inlen,outdataPtr,outlen);
}
return result;
}
break;
}
@ -2131,11 +2156,10 @@ int __IoIoctl(u32 id, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 out
u32 sceIoIoctl(u32 id, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 outlen)
{
int result = __IoIoctl(id, cmd, indataPtr, inlen, outdataPtr, outlen);
// Just a low estimate on timing.
// TODO: What errors are delayed?
if (result != (int)SCE_KERNEL_ERROR_ASYNC_BUSY && result != (int)SCE_KERNEL_ERROR_UNSUP) {
return hleDelayResult(result, "io ctrl command", 100);
int usec = 0;
int result = __IoIoctl(id, cmd, indataPtr, inlen, outdataPtr, outlen, usec);
if (usec != 0) {
return hleDelayResult(result, "io ctrl command", usec);
}
return result;
}
@ -2150,8 +2174,9 @@ u32 sceIoIoctlAsync(u32 id, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u
return SCE_KERNEL_ERROR_ASYNC_BUSY;
}
DEBUG_LOG(SCEIO, "sceIoIoctlAsync(%08x, %08x, %08x, %08x, %08x, %08x)", id, cmd, indataPtr, inlen, outdataPtr, outlen);
f->asyncResult = __IoIoctl(id, cmd, indataPtr, inlen, outdataPtr, outlen);
__IoSchedAsync(f, id, 100);
int usec = 100;
f->asyncResult = __IoIoctl(id, cmd, indataPtr, inlen, outdataPtr, outlen, usec);
__IoSchedAsync(f, id, usec);
return 0;
} else {
ERROR_LOG(SCEIO, "UNIMPL %08x=sceIoIoctlAsync id: %08x, cmd %08x, bad file", error, id, cmd);