mirror of
https://github.com/libretro/ppsspp.git
synced 2025-01-07 17:10:21 +00:00
Merge pull request #4887 from unknownbrackets/io-minor
Implement a few more ioctl commands
This commit is contained in:
commit
ff10d0b0f2
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;}
|
||||
};
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user