diff --git a/Common/FileUtil.cpp b/Common/FileUtil.cpp index 8ba82fa901..638f278b0f 100644 --- a/Common/FileUtil.cpp +++ b/Common/FileUtil.cpp @@ -70,15 +70,6 @@ static inline int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **res } #endif -// No thread safe -#ifdef _WIN32 -inline struct tm* localtime_r (const time_t *clock, struct tm *result) { - if (!clock || !result) return NULL; - memcpy(result,localtime(clock),sizeof(*result)); - return result; -} -#endif - // This namespace has various generic functions related to files and paths. // The code still needs a ton of cleanup. diff --git a/Common/FileUtil.h b/Common/FileUtil.h index 4c9a86f5cf..a9e410d6ba 100644 --- a/Common/FileUtil.h +++ b/Common/FileUtil.h @@ -37,6 +37,15 @@ enum { NUM_PATH_INDICES }; +// No thread safe +#ifdef _WIN32 +inline struct tm* localtime_r (const time_t *clock, struct tm *result) { + if (!clock || !result) return NULL; + memcpy(result,localtime(clock),sizeof(*result)); + return result; +} +#endif + namespace File { diff --git a/Core/FileSystems/DirectoryFileSystem.cpp b/Core/FileSystems/DirectoryFileSystem.cpp index 7cc5957254..15b38175ce 100644 --- a/Core/FileSystems/DirectoryFileSystem.cpp +++ b/Core/FileSystems/DirectoryFileSystem.cpp @@ -203,13 +203,9 @@ bool DirectoryFileSystem::RmDir(const std::string &dirname) { bool DirectoryFileSystem::RenameFile(const std::string &from, const std::string &to) { std::string fullTo = to; - // TO filename may not include path. Intention is that it uses FROM's path - if (to.find("/") != std::string::npos) { - size_t offset = from.find_last_of("/"); - if (offset != std::string::npos) { - fullTo = from.substr(0, offset + 1) + to; - } - } + + // Rename only work for filename in current directory + std::string fullFrom = GetLocalPath(from); #if HOST_IS_CASE_SENSITIVE @@ -495,16 +491,20 @@ PSPFileInfo DirectoryFileSystem::GetFileInfo(std::string filename) { if (x.type != FILETYPE_DIRECTORY) { + struct stat64 s; + stat64(fullName.c_str(), &s); #ifdef _WIN32 WIN32_FILE_ATTRIBUTE_DATA data; GetFileAttributesEx(fullName.c_str(), GetFileExInfoStandard, &data); x.size = data.nFileSizeLow | ((u64)data.nFileSizeHigh<<32); #else - x.size = File::GetSize(fullName); - //TODO + x.size = s.st_size; #endif - x.mtime = File::GetModifTime(fullName); + x.access = s.st_mode & 0x1FF; + localtime_r((time_t*)&s.st_atime,&x.atime); + localtime_r((time_t*)&s.st_ctime,&x.ctime); + localtime_r((time_t*)&s.st_mtime,&x.mtime); } return x; @@ -559,12 +559,18 @@ std::vector DirectoryFileSystem::GetDirListing(std::string path) { while ((dirp = readdir(dp)) != NULL) { PSPFileInfo entry; struct stat s; - stat(dirp->d_name, &s); + std::string fullName = GetLocalPath(path) + "/"+dirp->d_name; + stat(fullName.c_str(), &s); if (S_ISDIR(s.st_mode)) entry.type = FILETYPE_DIRECTORY; else entry.type = FILETYPE_NORMAL; + entry.access = s.st_mode & 0x1FF; entry.name = dirp->d_name; + entry.size = s.st_size; + localtime_r((time_t*)&s.st_atime,&entry.atime); + localtime_r((time_t*)&s.st_ctime,&entry.ctime); + localtime_r((time_t*)&s.st_mtime,&entry.mtime); myVector.push_back(entry); } closedir(dp); diff --git a/Core/FileSystems/FileSystem.h b/Core/FileSystems/FileSystem.h index ff09dfd70c..f57ecdff40 100644 --- a/Core/FileSystems/FileSystem.h +++ b/Core/FileSystems/FileSystem.h @@ -64,6 +64,8 @@ struct PSPFileInfo p.Do(access); p.Do(exists); p.Do(type); + p.Do(atime); + p.Do(ctime); p.Do(mtime); p.Do(isOnSectorSystem); p.Do(startSector); @@ -79,6 +81,8 @@ struct PSPFileInfo bool exists; FileType type; + tm atime; + tm ctime; tm mtime; bool isOnSectorSystem; diff --git a/Core/FileSystems/MetaFileSystem.cpp b/Core/FileSystems/MetaFileSystem.cpp index ae3db8de1d..f4221fbd9e 100644 --- a/Core/FileSystems/MetaFileSystem.cpp +++ b/Core/FileSystems/MetaFileSystem.cpp @@ -71,8 +71,9 @@ static bool RealPath(const std::string ¤tDirectory, const std::string &inP size_t inLen = inPath.length(); if (inLen == 0) { - ERROR_LOG(HLE, "RealPath: inPath is empty"); - return false; + WARN_LOG(HLE, "RealPath: inPath is empty"); + outPath = currentDirectory; + return true; } size_t inColon = inPath.find(':'); diff --git a/Core/HLE/sceIo.cpp b/Core/HLE/sceIo.cpp index bf776ad224..a9f6362691 100644 --- a/Core/HLE/sceIo.cpp +++ b/Core/HLE/sceIo.cpp @@ -147,6 +147,7 @@ public: p.Do(closePending); p.Do(pendingAsyncResult); p.Do(sectorBlockMode); + p.Do(openMode); p.DoMarker("File"); } @@ -163,6 +164,7 @@ public: bool closePending; PSPFileInfo info; + u32 openMode; }; static void TellFsThreadEnded (SceUID threadID) { @@ -288,6 +290,17 @@ void __IoCompleteAsyncIO(SceUID id) { } } +void __IoCopyDate(ScePspDateTime& date_out, const tm& date_in) +{ + date_out.year = date_in.tm_year+1900; + date_out.month = date_in.tm_mon+1; + date_out.day = date_in.tm_mday; + date_out.hour = date_in.tm_hour; + date_out.minute = date_in.tm_min; + date_out.second = date_in.tm_sec; + date_out.microsecond = 0; +} + void __IoGetStat(SceIoStat *stat, PSPFileInfo &info) { memset(stat, 0xfe, sizeof(SceIoStat)); stat->st_size = (s64) info.size; @@ -298,9 +311,12 @@ void __IoGetStat(SceIoStat *stat, PSPFileInfo &info) { else type = SCE_STM_FREG, attr = TYPE_FILE; - stat->st_mode = type; //0777 | type; + stat->st_mode = type | info.access; stat->st_attr = attr; stat->st_size = info.size; + __IoCopyDate(stat->st_atime, info.atime); + __IoCopyDate(stat->st_ctime, info.ctime); + __IoCopyDate(stat->st_mtime, info.mtime); stat->st_private[0] = info.startSector; } @@ -319,7 +335,7 @@ u32 sceIoGetstat(const char *filename, u32 addr) { } } else { DEBUG_LOG(HLE, "sceIoGetstat(%s, %08x) : FILE NOT FOUND", filename, addr); - return SCE_KERNEL_ERROR_NOFILE; + return ERROR_ERRNO_FILE_NOT_FOUND; } } @@ -333,7 +349,11 @@ u32 sceIoRead(int id, u32 data_addr, int size) { u32 error; FileNode *f = kernelObjects.Get < FileNode > (id, error); if (f) { - if (Memory::IsValidAddress(data_addr)) { + if(!(f->openMode & FILEACCESS_READ)) + { + return ERROR_KERNEL_BAD_FILE_DESCRIPTOR; + } + else if (Memory::IsValidAddress(data_addr)) { u8 *data = (u8*) Memory::GetPointer(data_addr); f->asyncResult = (u32) pspFileSystem.ReadFile(f->handle, data, size); DEBUG_LOG(HLE, "%i=sceIoRead(%d, %08x , %i)", f->asyncResult, id, data_addr, size); @@ -367,9 +387,16 @@ u32 sceIoWrite(int id, void *data_ptr, int size) u32 error; FileNode *f = kernelObjects.Get < FileNode > (id, error); if (f) { - u8 *data = (u8*) data_ptr; - f->asyncResult = (u32) pspFileSystem.WriteFile(f->handle, data, size); - return f->asyncResult; + if(!(f->openMode & FILEACCESS_WRITE)) + { + return ERROR_KERNEL_BAD_FILE_DESCRIPTOR; + } + else + { + u8 *data = (u8*) data_ptr; + f->asyncResult = (u32) pspFileSystem.WriteFile(f->handle, data, size); + return f->asyncResult; + } } else { ERROR_LOG(HLE, "sceIoWrite ERROR: no file open"); return error; @@ -421,16 +448,23 @@ s64 sceIoLseek(int id, s64 offset, int whence) { FileNode *f = kernelObjects.Get < FileNode > (id, error); if (f) { FileMove seek = FILEMOVE_BEGIN; + bool outOfBound = false; + int newPos = 0; switch (whence) { case 0: + newPos = offset; break; case 1: + newPos = pspFileSystem.GetSeekPos(f->handle) + offset; seek = FILEMOVE_CURRENT; break; case 2: + newPos = f->info.size + offset; seek = FILEMOVE_END; break; } + if(newPos < 0 || newPos > f->info.size) + return -1; f->asyncResult = (u32) pspFileSystem.SeekFile(f->handle, (s32) offset, seek); DEBUG_LOG(HLE, "%i = sceIoLseek(%d,%i,%i)", f->asyncResult, id, (int) offset, whence); @@ -448,16 +482,23 @@ u32 sceIoLseek32(int id, int offset, int whence) { DEBUG_LOG(HLE, "sceIoLseek32(%d,%08x,%i)", id, (int) offset, whence); FileMove seek = FILEMOVE_BEGIN; + bool outOfBound = false; + int newPos = 0; switch (whence) { case 0: + newPos = offset; break; case 1: + newPos = pspFileSystem.GetSeekPos(f->handle) + offset; seek = FILEMOVE_CURRENT; break; case 2: + newPos = f->info.size + offset; seek = FILEMOVE_END; break; } + if(newPos < 0 || newPos > f->info.size) + return -1; f->asyncResult = (u32) pspFileSystem.SeekFile(f->handle, (s32) offset, seek); return f->asyncResult; @@ -494,6 +535,7 @@ u32 sceIoOpen(const char* filename, int flags, int mode) { f->fullpath = filename; f->asyncResult = id; f->info = info; + f->openMode = access; DEBUG_LOG(HLE, "%i=sceIoOpen(%s, %08x, %08x)", id, filename, flags, mode); return id; } @@ -505,10 +547,12 @@ u32 sceIoClose(int id) { u32 sceIoRemove(const char *filename) { DEBUG_LOG(HLE, "sceIoRemove(%s)", filename); - if (pspFileSystem.DeleteFile(filename)) - return 0; - else - return -1; + + if(!pspFileSystem.GetFileInfo(filename).exists) + return ERROR_ERRNO_FILE_NOT_FOUND; + + pspFileSystem.DeleteFile(filename); + return 0; } u32 sceIoMkdir(const char *dirname, int mode) { @@ -760,16 +804,19 @@ u32 sceIoDevctl(const char *name, int cmd, u32 argAddr, int argLen, u32 outPtr, u32 sceIoRename(const char *from, const char *to) { DEBUG_LOG(HLE, "sceIoRename(%s, %s)", from, to); - if (pspFileSystem.RenameFile(from, to)) - return 0; - else - return -1; + + if(!pspFileSystem.GetFileInfo(from).exists) + return ERROR_ERRNO_FILE_NOT_FOUND; + + if(!pspFileSystem.RenameFile(from, to)) + WARN_LOG(HLE, "Could not move %s to %s\n",from, to); + return 0; } u32 sceIoChdir(const char *dirname) { - pspFileSystem.ChDir(dirname); DEBUG_LOG(HLE, "sceIoChdir(%s)", dirname); - return 1; + pspFileSystem.ChDir(dirname); + return 0; } int sceIoChangeAsyncPriority(int id, int priority) @@ -954,11 +1001,15 @@ public: u32 sceIoDopen(const char *path) { DEBUG_LOG(HLE, "sceIoDopen(\"%s\")", path); + + if(!pspFileSystem.GetFileInfo(path).exists) + { + return ERROR_ERRNO_FILE_NOT_FOUND; + } + DirListing *dir = new DirListing(); SceUID id = kernelObjects.Create(dir); - // TODO: ERROR_ERRNO_FILE_NOT_FOUND - dir->listing = pspFileSystem.GetDirListing(path); dir->index = 0; dir->name = std::string(path); diff --git a/Core/PSPLoaders.cpp b/Core/PSPLoaders.cpp index d55d237659..e73ec60564 100644 --- a/Core/PSPLoaders.cpp +++ b/Core/PSPLoaders.cpp @@ -129,7 +129,7 @@ bool Load_PSP_ELF_PBP(const char *filename, std::string *error_string) path = ReplaceAll(path, "/", "\\"); #endif DirectoryFileSystem *fs = new DirectoryFileSystem(&pspFileSystem, path); - pspFileSystem.Mount("umd0:/", fs); + pspFileSystem.Mount("umd0:", fs); std::string finalName = "umd0:/" + file + extension; return __KernelLoadExec(finalName.c_str(), 0, error_string); diff --git a/GPU/GLES/TransformPipeline.cpp b/GPU/GLES/TransformPipeline.cpp index 7ed920f368..36a0d8fec6 100644 --- a/GPU/GLES/TransformPipeline.cpp +++ b/GPU/GLES/TransformPipeline.cpp @@ -783,9 +783,9 @@ u32 TransformDrawEngine::ComputeHash() { u32 TransformDrawEngine::ComputeFastDCID() { u32 hash = 0; for (int i = 0; i < numDrawCalls; i++) { - hash ^= (u32)drawCalls[i].verts; + hash ^= *(u32*)&drawCalls[i].verts; hash = _rotl(hash, 13); - hash ^= (u32)drawCalls[i].inds; + hash ^= *(u32*)&drawCalls[i].inds; hash = _rotl(hash, 13); hash ^= (u32)drawCalls[i].vertType; hash = _rotl(hash, 13); diff --git a/headless/Headless.cpp b/headless/Headless.cpp index 92dced788b..b260dca2cd 100644 --- a/headless/Headless.cpp +++ b/headless/Headless.cpp @@ -157,6 +157,13 @@ int main(int argc, const char* argv[]) g_Config.bFirstRun = false; g_Config.bIgnoreBadMemAccess = true; +#if defined(ANDROID) +#elif defined(BLACKBERRY) || defined(__SYMBIAN32__) +#else + g_Config.memCardDirectory = std::string(getenv("HOME"))+"/.ppsspp/"; + g_Config.flashDirectory = g_Config.memCardDirectory+"/flash/"; +#endif + std::string error_string; if (!PSP_Init(coreParameter, &error_string)) { diff --git a/native b/native index b5037341aa..464240f703 160000 --- a/native +++ b/native @@ -1 +1 @@ -Subproject commit b5037341aaca775e806be4b6a7bf109a47e0c655 +Subproject commit 464240f7034b8defe5a60513c1e88bf6dc1c94c2 diff --git a/pspautotests b/pspautotests index 3e830600f6..31e3915d4e 160000 --- a/pspautotests +++ b/pspautotests @@ -1 +1 @@ -Subproject commit 3e830600f66d1f5235ff5b7cad4e2346af66445a +Subproject commit 31e3915d4e4302e5e7dc2f6c2a4f191c420f38f9