diff --git a/Common/MemoryUtil.cpp b/Common/MemoryUtil.cpp index 36c7c74088..4fef8c6f3e 100644 --- a/Common/MemoryUtil.cpp +++ b/Common/MemoryUtil.cpp @@ -117,7 +117,6 @@ static void *SearchForFreeMem(size_t size) { // This is purposely not a full wrapper for virtualalloc/mmap, but it // provides exactly the primitive operations that PPSSPP needs. - void *AllocateExecutableMemory(size_t size) { #if defined(_WIN32) void *ptr = nullptr; @@ -157,7 +156,7 @@ void *AllocateExecutableMemory(size_t size) { } #else static char *map_hint = 0; -#if defined(_M_X64) && !defined(MAP_32BIT) +#if defined(_M_X64) // Try to request one that is close to our memory location if we're in high memory. // We use a dummy global variable to give us a good location to start from. if (!map_hint) { @@ -165,9 +164,7 @@ void *AllocateExecutableMemory(size_t size) { map_hint = (char*)round_page(&hint_location) - 0x20000000; // 0.5gb lower than our approximate location else map_hint = (char*)0x20000000; // 0.5GB mark in memory - } - else if ((uintptr_t) map_hint > 0xFFFFFFFFULL) - { + } else if ((uintptr_t) map_hint > 0xFFFFFFFFULL) { map_hint -= round_page(size); /* round down to the next page if we're in high memory */ } #endif @@ -176,13 +173,7 @@ void *AllocateExecutableMemory(size_t size) { if (PlatformIsWXExclusive()) prot = PROT_READ | PROT_WRITE; // POST_EXEC is added later in this case. - void* ptr = mmap(map_hint, size, prot, - MAP_ANON | MAP_PRIVATE -#if defined(_M_X64) && defined(MAP_32BIT) - | MAP_32BIT -#endif - , -1, 0); - + void* ptr = mmap(map_hint, size, prot, MAP_ANON | MAP_PRIVATE, -1, 0); #endif /* defined(_WIN32) */ #if !defined(_WIN32) @@ -193,10 +184,11 @@ void *AllocateExecutableMemory(size_t size) { if (ptr == failed_result) { ptr = nullptr; - ERROR_LOG(MEMMAP, "Failed to allocate executable memory (%d)", (int)size); + ERROR_LOG(MEMMAP, "Failed to allocate executable memory (%d) errno=%d", (int)size, errno); PanicAlert("Failed to allocate executable memory\n%s", GetLastErrorMsg()); } -#if defined(_M_X64) && !defined(_WIN32) && !defined(MAP_32BIT) + +#if defined(_M_X64) && !defined(_WIN32) else if ((uintptr_t)map_hint <= 0xFFFFFFFF) { // Round up if we're below 32-bit mark, probably allocating sequentially. map_hint += round_page(size); diff --git a/Core/Compatibility.cpp b/Core/Compatibility.cpp index 49c5527a08..d98611bcc8 100644 --- a/Core/Compatibility.cpp +++ b/Core/Compatibility.cpp @@ -68,7 +68,6 @@ void Compatibility::CheckSettings(IniFile &iniFile, const std::string &gameID) { CheckSetting(iniFile, gameID, "DisableAccurateDepth", &flags_.DisableAccurateDepth); CheckSetting(iniFile, gameID, "MGS2AcidHack", &flags_.MGS2AcidHack); CheckSetting(iniFile, gameID, "SonicRivalsHack", &flags_.SonicRivalsHack); - CheckSetting(iniFile, gameID, "RenderPassMerge", &flags_.RenderPassMerge); CheckSetting(iniFile, gameID, "AdhocHackDisableNBSwitch", &flags_.AdhocHackDisableNBSwitch); CheckSetting(iniFile, gameID, "AdhocHackStopFriendClear", &flags_.AdhocHackStopFriendClear); CheckSetting(iniFile, gameID, "AdhocHackPhantasyStarOffset", &flags_.AdhocHackPhantasyStarOffset); diff --git a/Core/Compatibility.h b/Core/Compatibility.h index a13ffddcda..0b9a3403f1 100644 --- a/Core/Compatibility.h +++ b/Core/Compatibility.h @@ -68,7 +68,6 @@ struct CompatFlags { bool DisableAccurateDepth; bool MGS2AcidHack; bool SonicRivalsHack; - bool RenderPassMerge; bool AdhocHackDisableNBSwitch; bool AdhocHackStopFriendClear; bool AdhocHackPhantasyStarOffset; diff --git a/Core/Config.cpp b/Core/Config.cpp index aac5b2fa72..4d09454d5f 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -870,6 +870,10 @@ static ConfigSetting controlSettings[] = { ConfigSetting("TouchButtonHideSeconds", &g_Config.iTouchButtonHideSeconds, 20, true, true), ConfigSetting("AutoCenterTouchAnalog", &g_Config.bAutoCenterTouchAnalog, false, true, true), + // Snap touch control position + ConfigSetting("TouchSnapToGrid", &g_Config.bTouchSnapToGrid, false, true, true), + ConfigSetting("TouchSnapGridSize", &g_Config.iTouchSnapGridSize, 64, true, true), + // -1.0f means uninitialized, set in GamepadEmu::CreatePadLayout(). ConfigSetting("ActionButtonSpacing2", &g_Config.fActionButtonSpacing, 1.0f, true, true), ConfigSetting("ActionButtonCenterX", "ActionButtonCenterY", "ActionButtonScale", nullptr, &g_Config.touchActionButtonCenter, defaultTouchPosShow, true, true), diff --git a/Core/Config.h b/Core/Config.h index 92f66d3bad..e33eb7ad1d 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -285,6 +285,11 @@ public: int iTouchButtonStyle; int iTouchButtonOpacity; int iTouchButtonHideSeconds; + + // Snap touch control position + bool bTouchSnapToGrid; + int iTouchSnapGridSize; + // Floating analog stick (recenters on thumb on press). bool bAutoCenterTouchAnalog; diff --git a/Core/FileSystems/MetaFileSystem.cpp b/Core/FileSystems/MetaFileSystem.cpp index 933f56f5b1..19bddf251e 100644 --- a/Core/FileSystems/MetaFileSystem.cpp +++ b/Core/FileSystems/MetaFileSystem.cpp @@ -226,7 +226,7 @@ int MetaFileSystem::MapFilePath(const std::string &_inpath, std::string &outpath currentDirectory = &(it->second); } - if ( RealPath(*currentDirectory, inpath, realpath) ) + if (RealPath(*currentDirectory, inpath, realpath)) { std::string prefix = realpath; size_t prefixPos = realpath.find(':'); @@ -243,7 +243,7 @@ int MetaFileSystem::MapFilePath(const std::string &_inpath, std::string &outpath VERBOSE_LOG(FILESYS, "MapFilePath: mapped \"%s\" to prefix: \"%s\", path: \"%s\"", inpath.c_str(), fileSystems[i].prefix.c_str(), outpath.c_str()); - return 0; + return error == SCE_KERNEL_ERROR_NOCWD ? error : 0; } } } @@ -270,8 +270,7 @@ std::string MetaFileSystem::NormalizePrefix(std::string prefix) const { return prefix; } -void MetaFileSystem::Mount(std::string prefix, IFileSystem *system) -{ +void MetaFileSystem::Mount(std::string prefix, IFileSystem *system) { std::lock_guard guard(lock); MountPoint x; x.prefix = prefix; @@ -279,8 +278,7 @@ void MetaFileSystem::Mount(std::string prefix, IFileSystem *system) fileSystems.push_back(x); } -void MetaFileSystem::Unmount(std::string prefix, IFileSystem *system) -{ +void MetaFileSystem::Unmount(std::string prefix, IFileSystem *system) { std::lock_guard guard(lock); MountPoint x; x.prefix = prefix; @@ -288,12 +286,25 @@ void MetaFileSystem::Unmount(std::string prefix, IFileSystem *system) fileSystems.erase(std::remove(fileSystems.begin(), fileSystems.end(), x), fileSystems.end()); } -void MetaFileSystem::Remount(IFileSystem *oldSystem, IFileSystem *newSystem) { - for (auto it = fileSystems.begin(); it != fileSystems.end(); ++it) { - if (it->system == oldSystem) { - it->system = newSystem; +void MetaFileSystem::Remount(std::string prefix, IFileSystem *newSystem) { + std::lock_guard guard(lock); + IFileSystem *oldSystem = nullptr; + for (auto &it : fileSystems) { + if (it.prefix == prefix) { + oldSystem = it.system; + it.system = newSystem; } } + + bool delOldSystem = true; + for (auto &it : fileSystems) { + if (it.system == oldSystem) { + delOldSystem = false; + } + } + + if (delOldSystem) + delete oldSystem; } IFileSystem *MetaFileSystem::GetSystemFromFilename(const std::string &filename) { @@ -350,7 +361,8 @@ PSPFileInfo MetaFileSystem::GetFileInfo(std::string filename) std::lock_guard guard(lock); std::string of; IFileSystem *system; - if (MapFilePath(filename, of, &system) == 0) + int error = MapFilePath(filename, of, &system); + if (error == 0) { return system->GetFileInfo(of); } @@ -366,7 +378,8 @@ bool MetaFileSystem::GetHostPath(const std::string &inpath, std::string &outpath std::lock_guard guard(lock); std::string of; IFileSystem *system; - if (MapFilePath(inpath, of, &system) == 0) { + int error = MapFilePath(inpath, of, &system); + if (error == 0) { return system->GetHostPath(of, outpath); } else { return false; @@ -378,7 +391,8 @@ std::vector MetaFileSystem::GetDirListing(std::string path) std::lock_guard guard(lock); std::string of; IFileSystem *system; - if (MapFilePath(path, of, &system) == 0) + int error = MapFilePath(path, of, &system); + if (error == 0) { return system->GetDirListing(of); } @@ -406,7 +420,8 @@ int MetaFileSystem::ChDir(const std::string &dir) std::string of; MountPoint *mountPoint; - if (MapFilePath(dir, of, &mountPoint) == 0) + int error = MapFilePath(dir, of, &mountPoint); + if (error == 0) { currentDir[curThread] = mountPoint->prefix + of; return 0; @@ -435,7 +450,8 @@ bool MetaFileSystem::MkDir(const std::string &dirname) std::lock_guard guard(lock); std::string of; IFileSystem *system; - if (MapFilePath(dirname, of, &system) == 0) + int error = MapFilePath(dirname, of, &system); + if (error == 0) { return system->MkDir(of); } @@ -450,7 +466,8 @@ bool MetaFileSystem::RmDir(const std::string &dirname) std::lock_guard guard(lock); std::string of; IFileSystem *system; - if (MapFilePath(dirname, of, &system) == 0) + int error = MapFilePath(dirname, of, &system); + if (error == 0) { return system->RmDir(of); } @@ -467,12 +484,14 @@ int MetaFileSystem::RenameFile(const std::string &from, const std::string &to) std::string rf; IFileSystem *osystem; IFileSystem *rsystem = NULL; - if (MapFilePath(from, of, &osystem) == 0) + int error = MapFilePath(from, of, &osystem); + if (error == 0) { // If it's a relative path, it seems to always use from's filesystem. if (to.find(":/") != to.npos) { - if (!MapFilePath(to, rf, &rsystem)) + error = MapFilePath(to, rf, &rsystem); + if (error < 0) return -1; } else @@ -497,7 +516,8 @@ bool MetaFileSystem::RemoveFile(const std::string &filename) std::lock_guard guard(lock); std::string of; IFileSystem *system; - if (MapFilePath(filename, of, &system) == 0) + int error = MapFilePath(filename, of, &system); + if (error == 0) { return system->RemoveFile(of); } @@ -604,7 +624,8 @@ u64 MetaFileSystem::FreeSpace(const std::string &path) std::lock_guard guard(lock); std::string of; IFileSystem *system; - if (MapFilePath(path, of, &system) == 0) + int error = MapFilePath(path, of, &system); + if (error == 0) return system->FreeSpace(of); else return 0; diff --git a/Core/FileSystems/MetaFileSystem.h b/Core/FileSystems/MetaFileSystem.h index cfc202b0d1..c4bfd8d37f 100644 --- a/Core/FileSystems/MetaFileSystem.h +++ b/Core/FileSystems/MetaFileSystem.h @@ -52,7 +52,7 @@ public: void Mount(std::string prefix, IFileSystem *system); void Unmount(std::string prefix, IFileSystem *system); - void Remount(IFileSystem *oldSystem, IFileSystem *newSystem); + void Remount(std::string prefix, IFileSystem *newSystem); IFileSystem *GetSystem(const std::string &prefix); IFileSystem *GetSystemFromFilename(const std::string &filename); diff --git a/Core/HLE/HLEHelperThread.cpp b/Core/HLE/HLEHelperThread.cpp index 7f932c4a9c..36f9166813 100644 --- a/Core/HLE/HLEHelperThread.cpp +++ b/Core/HLE/HLEHelperThread.cpp @@ -16,9 +16,11 @@ // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. #include "Common/ChunkFile.h" +#include "Core/CoreTiming.h" #include "Core/MemMapHelpers.h" #include "Core/HLE/HLE.h" #include "Core/HLE/HLEHelperThread.h" +#include "Core/HLE/KernelWaitHelpers.h" #include "Core/HLE/sceKernelThread.h" #include "Core/HLE/sceKernelMemory.h" #include "Core/MIPS/MIPSCodeUtils.h" @@ -91,6 +93,13 @@ void HLEHelperThread::ChangePriority(u32 prio) { KernelChangeThreadPriority(id_, prio); } +void HLEHelperThread::Resume(WaitType waitType, SceUID uid, int result) { + bool res = HLEKernel::ResumeFromWait(id_, waitType, uid, result); + if (!res) { + ERROR_LOG(HLE, "Failed to wake helper thread from wait"); + } +} + void HLEHelperThread::Forget() { id_ = 0; entry_ = 0; diff --git a/Core/HLE/HLEHelperThread.h b/Core/HLE/HLEHelperThread.h index 1868d309b0..39df4c7402 100644 --- a/Core/HLE/HLEHelperThread.h +++ b/Core/HLE/HLEHelperThread.h @@ -19,6 +19,7 @@ #include "Core/HLE/sceKernel.h" class PointerWrap; +enum WaitType : int; class HLEHelperThread { public: @@ -33,10 +34,15 @@ public: void Terminate(); bool Stopped(); void ChangePriority(u32 prio); + void Resume(WaitType waitType, SceUID uid, int result); // For savestates. void Forget(); + u32 Entry() { + return entry_; + } + private: void AllocEntry(u32 size); void Create(const char *threadName, u32 prio, int stacksize); diff --git a/Core/HLE/sceIo.cpp b/Core/HLE/sceIo.cpp index d81740095e..f1de847b12 100644 --- a/Core/HLE/sceIo.cpp +++ b/Core/HLE/sceIo.cpp @@ -199,6 +199,7 @@ struct IoAsyncParams { static IoAsyncParams asyncParams[PSP_COUNT_FDS]; static HLEHelperThread *asyncThreads[PSP_COUNT_FDS]{}; +static int asyncDefaultPriority = -1; class FileNode : public KernelObject { public: @@ -294,8 +295,11 @@ public: u64 __IoCompleteAsyncIO(FileNode *f); -static void IoAsyncCleanupThread(int fd, bool force = false) { - if (asyncThreads[fd] && (asyncThreads[fd]->Stopped() || force)) { +static void IoAsyncCleanupThread(int fd) { + if (asyncThreads[fd]) { + if (!asyncThreads[fd]->Stopped()) { + asyncThreads[fd]->Terminate(); + } delete asyncThreads[fd]; asyncThreads[fd] = nullptr; } @@ -437,8 +441,6 @@ static void __IoAsyncNotify(u64 userdata, int cyclesLate) { if (f->closePending) { __IoFreeFd(fd, error); } - - IoAsyncCleanupThread(fd); } } @@ -487,8 +489,6 @@ static void __IoSyncNotify(u64 userdata, int cyclesLate) { HLEKernel::ResumeFromWait(threadID, WAITTYPE_IO, fd, result); f->waitingSyncThreads.erase(std::remove(f->waitingSyncThreads.begin(), f->waitingSyncThreads.end(), threadID), f->waitingSyncThreads.end()); - - IoAsyncCleanupThread(fd); } static void __IoAsyncBeginCallback(SceUID threadID, SceUID prevCallbackId) { @@ -662,7 +662,7 @@ void __IoInit() { } void __IoDoState(PointerWrap &p) { - auto s = p.Section("sceIo", 1, 4); + auto s = p.Section("sceIo", 1, 5); if (!s) return; @@ -697,31 +697,36 @@ void __IoDoState(PointerWrap &p) { } for (int i = 0; i < PSP_COUNT_FDS; ++i) { + auto clearThread = [&]() { + if (asyncThreads[i]) + asyncThreads[i]->Forget(); + delete asyncThreads[i]; + asyncThreads[i] = nullptr; + }; + if (s >= 4) { p.DoVoid(&asyncParams[i], (int)sizeof(IoAsyncParams)); bool hasThread = asyncThreads[i] != nullptr; p.Do(hasThread); if (hasThread) { - if (asyncThreads[i]) - asyncThreads[i]->Forget(); - delete asyncThreads[i]; - asyncThreads[i] = nullptr; + if (p.GetMode() == p.MODE_READ) + clearThread(); p.DoClass(asyncThreads[i]); } else if (!hasThread) { - if (asyncThreads[i]) - asyncThreads[i]->Forget(); - delete asyncThreads[i]; - asyncThreads[i] = nullptr; + clearThread(); } } else { asyncParams[i].op = IoAsyncOp::NONE; asyncParams[i].priority = -1; - if (asyncThreads[i]) - asyncThreads[i]->Forget(); - delete asyncThreads[i]; - asyncThreads[i] = nullptr; + clearThread(); } } + + if (s >= 5) { + p.Do(asyncDefaultPriority); + } else { + asyncDefaultPriority = -1; + } } void __IoShutdown() { @@ -739,6 +744,7 @@ void __IoShutdown() { delete asyncThreads[i]; asyncThreads[i] = nullptr; } + asyncDefaultPriority = -1; pspFileSystem.Unmount("ms0:", memstickSystem); pspFileSystem.Unmount("fatms0:", memstickSystem); @@ -771,10 +777,20 @@ u32 __IoGetFileHandleFromId(u32 id, u32 &outError) } static void IoStartAsyncThread(int id, FileNode *f) { - IoAsyncCleanupThread(id, true); - int priority = asyncParams[id].priority == -1 ? KernelCurThreadPriority() : asyncParams[id].priority; - asyncThreads[id] = new HLEHelperThread("SceIoAsync", "IoFileMgrForUser", "__IoAsyncFinish", priority, 0x200); - asyncThreads[id]->Start(id, 0); + if (asyncThreads[id] && !asyncThreads[id]->Stopped()) { + // Wake the thread up. + if (asyncParams[id].priority == -1 && sceKernelGetCompiledSdkVersion() >= 0x04020000) { + asyncThreads[id]->ChangePriority(KernelCurThreadPriority()); + } + asyncThreads[id]->Resume(WAITTYPE_ASYNCIO, id, 0); + } else { + IoAsyncCleanupThread(id); + int priority = asyncParams[id].priority; + if (priority == -1) + priority = KernelCurThreadPriority(); + asyncThreads[id] = new HLEHelperThread("SceIoAsync", "IoFileMgrForUser", "__IoAsyncFinish", priority, 0x200); + asyncThreads[id]->Start(id, 0); + } f->pendingAsyncResult = true; } @@ -1249,17 +1265,14 @@ static u32 sceIoGetDevType(int id) { static u32 sceIoCancel(int id) { - ERROR_LOG_REPORT(SCEIO, "UNIMPL sceIoCancel(%d)", id); u32 error; FileNode *f = __IoGetFd(id, error); if (f) { - // TODO: Cancel the async operation if possible? + // It seems like this is unsupported for UMDs and memory sticks, based on tests. + return hleReportError(SCEIO, SCE_KERNEL_ERROR_UNSUP, "unimplemented or unsupported"); } else { - ERROR_LOG(SCEIO, "sceIoCancel: unknown id %d", id); - error = SCE_KERNEL_ERROR_BADF; + return hleLogError(SCEIO, SCE_KERNEL_ERROR_BADF, "invalid fd"); } - - return error; } static u32 npdrmLseek(FileNode *f, s32 where, FileMove whence) @@ -1482,7 +1495,7 @@ static u32 sceIoOpen(const char *filename, int flags, int mode) { return id; } else { DEBUG_LOG(SCEIO, "%i=sceIoOpen(%s, %08x, %08x)", id, filename, flags, mode); - asyncParams[id].priority = -1; + asyncParams[id].priority = asyncDefaultPriority; // Timing is not accurate, aiming low for now. return hleDelayResult(id, "file opened", 100); } @@ -1958,11 +1971,16 @@ static u32 sceIoChdir(const char *dirname) { } static int sceIoChangeAsyncPriority(int id, int priority) { - // priority = -1 is valid + // priority = -1 is valid,means the current thread'priority if (priority != -1 && (priority < 0x08 || priority > 0x77)) { return hleLogError(SCEIO, SCE_KERNEL_ERROR_ILLEGAL_PRIORITY, "illegal priority %d", priority); } + if (id == -1) { + asyncDefaultPriority = priority; + return hleLogSuccessI(SCEIO, 0); + } + u32 error; FileNode *f = __IoGetFd(id, error); if (!f) { @@ -1970,6 +1988,9 @@ static int sceIoChangeAsyncPriority(int id, int priority) { } if (asyncThreads[id] && !asyncThreads[id]->Stopped()) { + if (priority == -1) { + priority = KernelCurThreadPriority(); + } asyncThreads[id]->ChangePriority(priority); } @@ -2041,7 +2062,7 @@ static u32 sceIoOpenAsync(const char *filename, int flags, int mode) auto ¶ms = asyncParams[fd]; params.op = IoAsyncOp::OPEN; - params.priority = -1; + params.priority = asyncDefaultPriority; params.open.filenameAddr = PARAM(0); params.open.flags = flags; params.open.mode = mode; @@ -2087,7 +2108,6 @@ static u32 sceIoGetAsyncStat(int id, u32 poll, u32 address) { DEBUG_LOG(SCEIO, "%lli = sceIoGetAsyncStat(%i, %i, %08x)", f->asyncResult, id, poll, address); Memory::Write_U64((u64) f->asyncResult, address); f->hasAsyncResult = false; - IoAsyncCleanupThread(id); if (f->closePending) { __IoFreeFd(id, error); @@ -2125,7 +2145,6 @@ static int sceIoWaitAsync(int id, u32 address) { } Memory::Write_U64((u64) f->asyncResult, address); f->hasAsyncResult = false; - IoAsyncCleanupThread(id); if (f->closePending) { __IoFreeFd(id, error); @@ -2159,7 +2178,6 @@ static int sceIoWaitAsyncCB(int id, u32 address) { } else if (f->hasAsyncResult) { Memory::Write_U64((u64) f->asyncResult, address); f->hasAsyncResult = false; - IoAsyncCleanupThread(id); if (f->closePending) { __IoFreeFd(id, error); @@ -2183,7 +2201,6 @@ static u32 sceIoPollAsync(int id, u32 address) { } else if (f->hasAsyncResult) { Memory::Write_U64((u64) f->asyncResult, address); f->hasAsyncResult = false; - IoAsyncCleanupThread(id); if (f->closePending) { __IoFreeFd(id, error); @@ -2531,6 +2548,10 @@ static int __IoIoctl(u32 id, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, // 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 (GetIOTimingMethod() == IOTIMING_REALISTIC) // Need a check for io timing method? + usec = 15000;// Fantasy Golf Pangya Portable(KS) needs a delay over 15000us. + if (Memory::IsValidAddress(indataPtr) && inlen >= 4) { struct SeekInfo { u64 offset; @@ -2653,6 +2674,8 @@ static int IoAsyncFinish(int id) { if (f) { // Reset this so the Io funcs don't reject the request. f->pendingAsyncResult = false; + // Reset the PC back so we will run again on resume. + currentMIPS->pc = asyncThreads[id]->Entry(); auto ¶ms = asyncParams[id]; @@ -2714,6 +2737,7 @@ static int IoAsyncFinish(int id) { __IoSchedAsync(f, id, us); __KernelWaitCurThread(WAITTYPE_ASYNCIO, id, 0, 0, false, "async io"); + hleSkipDeadbeef(); params.op = IoAsyncOp::NONE; return 0; diff --git a/Core/HLE/sceKernelThread.h b/Core/HLE/sceKernelThread.h index c89a373ee9..8b95396b97 100644 --- a/Core/HLE/sceKernelThread.h +++ b/Core/HLE/sceKernelThread.h @@ -80,7 +80,7 @@ struct SceKernelSysClock { // TODO: Map these to PSP wait types. Most of these are wrong. // remember to update the waitTypeNames array in sceKernelThread.cpp when changing these -enum WaitType +enum WaitType : int { WAITTYPE_NONE = 0, WAITTYPE_SLEEP = 1, diff --git a/Core/HLE/sceMpeg.cpp b/Core/HLE/sceMpeg.cpp index 43f30b9ce6..5243c76f03 100644 --- a/Core/HLE/sceMpeg.cpp +++ b/Core/HLE/sceMpeg.cpp @@ -1898,6 +1898,11 @@ static u32 sceMpegAtracDecode(u32 mpeg, u32 auAddr, u32 bufferAddr, int init) return -1; } + if (!Memory::IsValidAddress(bufferAddr)) { + WARN_LOG(ME, "sceMpegAtracDecode(%08x, %08x, %08x, %i): invalid addresses", mpeg, auAddr, bufferAddr, init); + return -1; + } + DEBUG_LOG(ME, "sceMpegAtracDecode(%08x, %08x, %08x, %i)", mpeg, auAddr, bufferAddr, init); SceMpegAu atracAu; diff --git a/Core/HLE/sceUmd.cpp b/Core/HLE/sceUmd.cpp index bd4cb56d7b..ab2d62a490 100644 --- a/Core/HLE/sceUmd.cpp +++ b/Core/HLE/sceUmd.cpp @@ -425,7 +425,7 @@ static int sceUmdWaitDriveStatWithTimer(u32 stat, u32 timeout) DEBUG_LOG(SCEIO, "sceUmdWaitDriveStatWithTimer(stat = %08x, timeout = %d): waiting", stat, timeout); __UmdWaitStat(timeout); umdWaitingThreads.push_back(__KernelGetCurThread()); - __KernelWaitCurThread(WAITTYPE_UMD, 1, stat, 0, 0, "umd stat waited with timer"); + __KernelWaitCurThread(WAITTYPE_UMD, 1, stat, 0, false, "umd stat waited with timer"); return 0; } else { hleReSchedule("umd stat checked"); @@ -495,45 +495,17 @@ static u32 sceUmdGetErrorStat() } void __UmdReplace(std::string filepath) { - // TODO: This should really go through Loaders, no? What if it's an invalid file? - - // Only get system from disc0 seems have been enough. - IFileSystem* currentUMD = pspFileSystem.GetSystem("disc0:"); - IFileSystem* currentISOBlock = pspFileSystem.GetSystem("umd0:"); - if (!currentUMD) - return; - - FileLoader *loadedFile = ConstructFileLoader(filepath); - - IFileSystem* umd2; - if (!loadedFile->Exists()) { - delete loadedFile; + std::string error = ""; + if (!UmdReplace(filepath, error)) { + ERROR_LOG(SCEIO, "UMD Replace failed: %s", error.c_str()); return; } - UpdateLoadedFile(loadedFile); - if (loadedFile->IsDirectory()) { - umd2 = new VirtualDiscFileSystem(&pspFileSystem, filepath); - } else { - auto bd = constructBlockDevice(loadedFile); - if (!bd) - return; - umd2 = new ISOFileSystem(&pspFileSystem, bd); - pspFileSystem.Remount(currentUMD, umd2); - - if (currentUMD != currentISOBlock) { - // We mounted an ISO block system separately. - IFileSystem *iso = new ISOBlockSystem(static_cast(umd2)); - pspFileSystem.Remount(currentISOBlock, iso); - delete currentISOBlock; - } - } - delete currentUMD; UMDInserted = false; CoreTiming::ScheduleEvent(usToCycles(200*1000), umdInsertChangeEvent, 0); // Wait sceUmdCheckMedium call // TODO Is this always correct if UMD was not activated? u32 notifyArg = PSP_UMD_PRESENT | PSP_UMD_READABLE | PSP_UMD_CHANGED; - if (driveCBId != -1) + if (driveCBId != 0) __KernelNotifyCallback(driveCBId, notifyArg); } diff --git a/Core/Loaders.cpp b/Core/Loaders.cpp index 14bc31973d..a4d102e122 100644 --- a/Core/Loaders.cpp +++ b/Core/Loaders.cpp @@ -355,3 +355,41 @@ bool LoadFile(FileLoader **fileLoaderPtr, std::string *error_string) { coreState = CORE_ERROR; return false; } + +bool UmdReplace(std::string filepath, std::string &error) { + IFileSystem* currentUMD = pspFileSystem.GetSystem("disc0:"); + + if (!currentUMD) { + error = "has no disc"; + return false; + } + + FileLoader *loadedFile = ConstructFileLoader(filepath); + + if (!loadedFile->Exists()) { + delete loadedFile; + error = loadedFile->Path() + " doesn't exist"; + return false; + } + UpdateLoadedFile(loadedFile); + + loadedFile = ResolveFileLoaderTarget(loadedFile); + IdentifiedFileType type = Identify_File(loadedFile); + + switch (type) { + case IdentifiedFileType::PSP_ISO: + case IdentifiedFileType::PSP_ISO_NP: + case IdentifiedFileType::PSP_DISC_DIRECTORY: + if (!ReInitMemoryForGameISO(loadedFile)) { + error = "reinit memory failed"; + return false; + } + + break; + default: + error = "Unsupported file type:" + std::to_string((int)type); + return false; + break; + } + return true; +} diff --git a/Core/Loaders.h b/Core/Loaders.h index 690376c73b..a076cfa675 100644 --- a/Core/Loaders.h +++ b/Core/Loaders.h @@ -158,3 +158,5 @@ void RegisterFileLoaderFactory(std::string name, std::unique_ptrIsDirectory()) { fileSystem = new VirtualDiscFileSystem(&pspFileSystem, fileLoader->Path()); blockSystem = fileSystem; @@ -144,6 +144,35 @@ void InitMemoryForGameISO(FileLoader *fileLoader) { } } +bool ReInitMemoryForGameISO(FileLoader *fileLoader) { + if (!fileLoader->Exists()) { + return false; + } + + IFileSystem *fileSystem = nullptr; + IFileSystem *blockSystem = nullptr; + + if (fileLoader->IsDirectory()) { + fileSystem = new VirtualDiscFileSystem(&pspFileSystem, fileLoader->Path()); + blockSystem = fileSystem; + } else { + auto bd = constructBlockDevice(fileLoader); + if (!bd) + return false; + + ISOFileSystem *iso = new ISOFileSystem(&pspFileSystem, bd); + fileSystem = iso; + blockSystem = new ISOBlockSystem(iso); + } + + pspFileSystem.Remount("umd0:", blockSystem); + pspFileSystem.Remount("umd1:", blockSystem); + pspFileSystem.Remount("umd:", blockSystem); + pspFileSystem.Remount("disc0:", fileSystem); + + return true; +} + void InitMemoryForGamePBP(FileLoader *fileLoader) { if (!fileLoader->Exists()) { return; diff --git a/Core/PSPLoaders.h b/Core/PSPLoaders.h index f344008460..e9c089494e 100644 --- a/Core/PSPLoaders.h +++ b/Core/PSPLoaders.h @@ -25,5 +25,6 @@ bool Load_PSP_ISO(FileLoader *fileLoader, std::string *error_string); bool Load_PSP_ELF_PBP(FileLoader *fileLoader, std::string *error_string); bool Load_PSP_GE_Dump(FileLoader *fileLoader, std::string *error_string); void InitMemoryForGameISO(FileLoader *fileLoader); +bool ReInitMemoryForGameISO(FileLoader *fileLoader); void InitMemoryForGamePBP(FileLoader *fileLoader); void PSPLoaders_Shutdown(); diff --git a/GPU/Software/SoftGpu.cpp b/GPU/Software/SoftGpu.cpp index 7254c2ce11..691a8756aa 100644 --- a/GPU/Software/SoftGpu.cpp +++ b/GPU/Software/SoftGpu.cpp @@ -158,6 +158,38 @@ void SoftGPU::SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat for bool g_DarkStalkerStretch; +void SoftGPU::ConvertTextureDescFrom16(Draw::TextureDesc &desc, int srcwidth, int srcheight) { + // TODO: This should probably be converted in a shader instead.. + fbTexBuffer_.resize(srcwidth * srcheight); + FormatBuffer displayBuffer; + displayBuffer.data = Memory::GetPointer(displayFramebuf_); + for (int y = 0; y < srcheight; ++y) { + u32 *buf_line = &fbTexBuffer_[y * srcwidth]; + const u16 *fb_line = &displayBuffer.as16[y * displayStride_]; + + switch (displayFormat_) { + case GE_FORMAT_565: + ConvertRGBA565ToRGBA8888(buf_line, fb_line, srcwidth); + break; + + case GE_FORMAT_5551: + ConvertRGBA5551ToRGBA8888(buf_line, fb_line, srcwidth); + break; + + case GE_FORMAT_4444: + ConvertRGBA4444ToRGBA8888(buf_line, fb_line, srcwidth); + break; + + default: + ERROR_LOG_REPORT(G3D, "Software: Unexpected framebuffer format: %d", displayFormat_); + } + } + + desc.width = srcwidth; + desc.height = srcheight; + desc.initData.push_back((uint8_t *)fbTexBuffer_.data()); +} + // Copies RGBA8 data from RAM to the currently bound render target. void SoftGPU::CopyToCurrentFboFromDisplayRam(int srcwidth, int srcheight) { if (!draw_) @@ -191,6 +223,7 @@ void SoftGPU::CopyToCurrentFboFromDisplayRam(int srcwidth, int srcheight) { Draw::Pipeline *pipeline = texColor; if (PSP_CoreParameter().compat.flags().DarkStalkersPresentHack && displayFormat_ == GE_FORMAT_5551 && g_DarkStalkerStretch) { u8 *data = Memory::GetPointer(0x04088000); + bool fillDesc = true; if (draw_->GetDataFormatSupport(Draw::DataFormat::A1B5G5R5_UNORM_PACK16) & Draw::FMT_TEXTURE) { // The perfect one. desc.format = Draw::DataFormat::A1B5G5R5_UNORM_PACK16; @@ -198,10 +231,15 @@ void SoftGPU::CopyToCurrentFboFromDisplayRam(int srcwidth, int srcheight) { // RB swapped, compensate with a shader. desc.format = Draw::DataFormat::A1R5G5B5_UNORM_PACK16; pipeline = texColorRBSwizzle; + } else { + ConvertTextureDescFrom16(desc, srcwidth, srcheight); + fillDesc = false; + } + if (fillDesc) { + desc.width = displayStride_ == 0 ? srcwidth : displayStride_; + desc.height = srcheight; + desc.initData.push_back(data); } - desc.width = displayStride_ == 0 ? srcwidth : displayStride_; - desc.height = srcheight; - desc.initData.push_back(data); u0 = 64.5f / 512.0f; u1 = 447.5f / 512.0f; v1 = 16.0f / 272.0f; @@ -217,6 +255,7 @@ void SoftGPU::CopyToCurrentFboFromDisplayRam(int srcwidth, int srcheight) { desc.format = Draw::DataFormat::R8G8B8A8_UNORM; } else if (displayFormat_ == GE_FORMAT_5551) { u8 *data = Memory::GetPointer(displayFramebuf_); + bool fillDesc = true; desc.format = Draw::DataFormat::A1R5G5B5_UNORM_PACK16; if (draw_->GetDataFormatSupport(Draw::DataFormat::A1B5G5R5_UNORM_PACK16) & Draw::FMT_TEXTURE) { // The perfect one. @@ -225,40 +264,17 @@ void SoftGPU::CopyToCurrentFboFromDisplayRam(int srcwidth, int srcheight) { // RB swapped, compensate with a shader. desc.format = Draw::DataFormat::A1R5G5B5_UNORM_PACK16; pipeline = texColorRBSwizzle; + } else { + ConvertTextureDescFrom16(desc, srcwidth, srcheight); + fillDesc = false; + } + if (fillDesc) { + desc.width = displayStride_ == 0 ? srcwidth : displayStride_; + desc.height = srcheight; + desc.initData.push_back(data); } - desc.width = displayStride_ == 0 ? srcwidth : displayStride_; - desc.height = srcheight; - desc.initData.push_back(data); } else { - // TODO: This should probably be converted in a shader instead.. - fbTexBuffer.resize(srcwidth * srcheight); - FormatBuffer displayBuffer; - displayBuffer.data = Memory::GetPointer(displayFramebuf_); - for (int y = 0; y < srcheight; ++y) { - u32 *buf_line = &fbTexBuffer[y * srcwidth]; - const u16 *fb_line = &displayBuffer.as16[y * displayStride_]; - - switch (displayFormat_) { - case GE_FORMAT_565: - ConvertRGBA565ToRGBA8888(buf_line, fb_line, srcwidth); - break; - - case GE_FORMAT_5551: - ConvertRGBA5551ToRGBA8888(buf_line, fb_line, srcwidth); - break; - - case GE_FORMAT_4444: - ConvertRGBA4444ToRGBA8888(buf_line, fb_line, srcwidth); - break; - - default: - ERROR_LOG_REPORT(G3D, "Software: Unexpected framebuffer format: %d", displayFormat_); - } - } - - desc.width = srcwidth; - desc.height = srcheight; - desc.initData.push_back((uint8_t *)fbTexBuffer.data()); + ConvertTextureDescFrom16(desc, srcwidth, srcheight); u1 = 1.0f; } if (!hasImage) { diff --git a/GPU/Software/SoftGpu.h b/GPU/Software/SoftGpu.h index 02660b5576..84626b31c2 100644 --- a/GPU/Software/SoftGpu.h +++ b/GPU/Software/SoftGpu.h @@ -101,6 +101,7 @@ public: protected: void FastRunLoop(DisplayList &list) override; void CopyToCurrentFboFromDisplayRam(int srcwidth, int srcheight); + void ConvertTextureDescFrom16(Draw::TextureDesc &desc, int srcwidth, int srcheight); private: bool framebufferDirty_; @@ -113,7 +114,7 @@ private: Draw::Texture *fbTex; Draw::Pipeline *texColor; Draw::Pipeline *texColorRBSwizzle; - std::vector fbTexBuffer; + std::vector fbTexBuffer_; Draw::SamplerState *samplerNearest = nullptr; Draw::SamplerState *samplerLinear = nullptr; diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index 1a5e254e27..3f20ec0642 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -485,8 +485,9 @@ void GPU_Vulkan::InitDeviceObjects() { hacks |= QUEUE_HACK_MGS2_ACID; if (PSP_CoreParameter().compat.flags().SonicRivalsHack) hacks |= QUEUE_HACK_SONIC; - if (PSP_CoreParameter().compat.flags().RenderPassMerge) - hacks |= QUEUE_HACK_RENDERPASS_MERGE; + + // Always on. + hacks |= QUEUE_HACK_RENDERPASS_MERGE; if (hacks) { rm->GetQueueRunner()->EnableHacks(hacks); diff --git a/Qt/QtHost.cpp b/Qt/QtHost.cpp index c2ef7d2eac..e13f916c69 100644 --- a/Qt/QtHost.cpp +++ b/Qt/QtHost.cpp @@ -18,12 +18,12 @@ #include #include "Qt/QtHost.h" -const char* QtHost::SymbolMapFilename(std::string currentFilename) { - std::string result = currentFilename; - size_t dot = result.rfind('.'); - if (dot == result.npos) - return (result + ".map").c_str(); +std::string QtHost::SymbolMapFilename(std::string currentFilename) { + size_t dot = currentFilename.rfind('.'); + if (dot == std::string::npos) + currentFilename.append(".map"); + else + currentFilename.replace(dot, -1, ".map"); - result.replace(dot, result.npos, ".map"); - return result.c_str(); + return currentFilename; } diff --git a/Qt/QtHost.h b/Qt/QtHost.h index 846da1058f..1a15740806 100644 --- a/Qt/QtHost.h +++ b/Qt/QtHost.h @@ -64,13 +64,12 @@ public: #endif } virtual bool AttemptLoadSymbolMap() override { - return false; - // TODO: Make this work with Qt and threaded GL... not sure what's so broken. - // auto fn = SymbolMapFilename(PSP_CoreParameter().fileToStart); - // return g_symbolMap->LoadSymbolMap(fn); + auto fn = SymbolMapFilename(PSP_CoreParameter().fileToStart); + return g_symbolMap->LoadSymbolMap(fn.c_str()); } void PrepareShutdown() { - g_symbolMap->SaveSymbolMap(SymbolMapFilename(PSP_CoreParameter().fileToStart)); + auto fn = SymbolMapFilename(PSP_CoreParameter().fileToStart); + g_symbolMap->SaveSymbolMap(fn.c_str()); } void SetWindowTitle(const char *message) override { std::string title = std::string("PPSSPP ") + PPSSPP_GIT_VERSION; @@ -91,6 +90,6 @@ public: } private: - const char* SymbolMapFilename(std::string currentFilename); + std::string SymbolMapFilename(std::string currentFilename); MainWindow* mainWindow; }; diff --git a/Qt/mainwindow.cpp b/Qt/mainwindow.cpp index 502e22a0fd..4b4a6aaaf7 100644 --- a/Qt/mainwindow.cpp +++ b/Qt/mainwindow.cpp @@ -29,6 +29,8 @@ MainWindow::MainWindow(QWidget *parent, bool fullscreen) : QRect rect = desktop->screenGeometry(screenNum); move((rect.width()-frameGeometry().width()) / 4, (rect.height()-frameGeometry().height()) / 4); + setWindowIcon(QIcon(qApp->applicationDirPath() + "/assets/icon_regular_72.png")); + SetGameTitle(""); emugl = new MainUI(this); diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp index f868592bd2..90db5d4195 100644 --- a/SDL/SDLMain.cpp +++ b/SDL/SDLMain.cpp @@ -910,7 +910,9 @@ int main(int argc, char *argv[]) { if (!name) { break; } - if (g_Config.bAutoAudioDevice || g_Config.sAudioDevice == name) { + // Don't start auto switching for a second, because some devices init on start. + bool doAutoSwitch = g_Config.bAutoAudioDevice && framecount > 60; + if (doAutoSwitch || g_Config.sAudioDevice == name) { StopSDLAudioDevice(); InitSDLAudioDevice(name ? name : ""); } diff --git a/UI/DiscordIntegration.cpp b/UI/DiscordIntegration.cpp index fea814924d..b88680f048 100644 --- a/UI/DiscordIntegration.cpp +++ b/UI/DiscordIntegration.cpp @@ -64,11 +64,12 @@ void Discord::Init() { } void Discord::Shutdown() { - assert(initialized_); + if (initialized_) { #ifdef ENABLE_DISCORD - Discord_Shutdown(); + Discord_Shutdown(); #endif - initialized_ = false; + initialized_ = false; + } } void Discord::Update() { diff --git a/UI/TouchControlLayoutScreen.cpp b/UI/TouchControlLayoutScreen.cpp index 24574ed951..65ebb654cf 100644 --- a/UI/TouchControlLayoutScreen.cpp +++ b/UI/TouchControlLayoutScreen.cpp @@ -243,9 +243,15 @@ bool TouchControlLayoutScreen::touch(const TouchInput &touch) { // if the leftmost point of the control is ahead of the margin, // move it. Otherwise, don't. newX = touch.x; + // Snap to grid + if (g_Config.bTouchSnapToGrid) + newX -= (int)(touch.x - bounds.w) % g_Config.iTouchSnapGridSize; } if (touch.y > minTouchY && touch.y < maxTouchY) { newY = touch.y; + // Snap to grid + if (g_Config.bTouchSnapToGrid) + newY -= (int)(touch.y - bounds.h) % g_Config.iTouchSnapGridSize; } pickedControl_->ReplaceLayoutParams(new UI::AnchorLayoutParams(newX, newY, NONE, NONE, true)); } else if (mode == 1) { @@ -324,11 +330,15 @@ void TouchControlLayoutScreen::CreateViews() { Choice *reset = new Choice(di->T("Reset"), "", false, new AnchorLayoutParams(leftColumnWidth, WRAP_CONTENT, 10, NONE, NONE, 84)); Choice *back = new Choice(di->T("Back"), "", false, new AnchorLayoutParams(leftColumnWidth, WRAP_CONTENT, 10, NONE, NONE, 10)); - Choice *visibility = new Choice(co->T("Visibility"), "", false, new AnchorLayoutParams(leftColumnWidth, WRAP_CONTENT, 10, NONE, NONE, 158)); + Choice *visibility = new Choice(co->T("Visibility"), "", false, new AnchorLayoutParams(leftColumnWidth, WRAP_CONTENT, 10, NONE, NONE, 298)); // controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fButtonScale, 0.80, 2.0, co->T("Button Scaling"), screenManager())) // ->OnChange.Handle(this, &GameSettingsScreen::OnChangeControlScaling); - mode_ = new ChoiceStrip(ORIENT_VERTICAL, new AnchorLayoutParams(leftColumnWidth, WRAP_CONTENT, 10, NONE, NONE, 158 + 64 + 10)); + CheckBox *snap = new CheckBox(&g_Config.bTouchSnapToGrid, di->T("Snap"), "", new AnchorLayoutParams(leftColumnWidth, WRAP_CONTENT, 10, NONE, NONE, 228)); + PopupSliderChoice *gridSize = new PopupSliderChoice(&g_Config.iTouchSnapGridSize, 1, 256, di->T("Grid"), screenManager(), "", new AnchorLayoutParams(leftColumnWidth, WRAP_CONTENT, 10, NONE, NONE, 158)); + gridSize->SetEnabledPtr(&g_Config.bTouchSnapToGrid); + + mode_ = new ChoiceStrip(ORIENT_VERTICAL, new AnchorLayoutParams(leftColumnWidth, WRAP_CONTENT, 10, NONE, NONE, 140 + 158 + 64 + 10)); mode_->AddChoice(di->T("Move")); mode_->AddChoice(di->T("Resize")); mode_->SetSelection(0); @@ -338,6 +348,8 @@ void TouchControlLayoutScreen::CreateViews() { visibility->OnClick.Handle(this, &TouchControlLayoutScreen::OnVisibility); root_->Add(mode_); root_->Add(visibility); + root_->Add(snap); + root_->Add(gridSize); root_->Add(reset); root_->Add(back); @@ -352,7 +364,7 @@ void TouchControlLayoutScreen::CreateViews() { I18NCategory *ms = GetI18NCategory("MainSettings"); - tabHolder->AddTab(ms->T("Controls"), controlsHolder); + //tabHolder->AddTab(ms->T("Controls"), controlsHolder); if (!g_Config.bShowTouchControls) { // Shouldn't even be able to get here as the way into this dialog should be closed. diff --git a/assets/compat.ini b/assets/compat.ini index 4d97b71450..df1bea3498 100644 --- a/assets/compat.ini +++ b/assets/compat.ini @@ -764,48 +764,14 @@ ULAS42214 = true ULJS19054 = true NPJH50184 = true -[RenderPassMerge] -UCJS10114 = true -UCKS45084 = true -# GOW : Ghost of Sparta -UCUS98737 = true -UCAS40323 = true -NPHG00092 = true -NPEG00044 = true -NPEG00045 = true -NPJG00120 = true -NPUG80508 = true -UCJS10114 = true -UCES01401 = true -UCES01473 = true -# GOW : Ghost of Sparta Demo -NPEG90035 = true -NPUG70125 = true -NPJG90095 = true -# GOW : Chains Of Olympus -UCAS40198 = true -UCUS98653 = true -UCES00842 = true -ULJM05438 = true -ULJM05348 = true -UCKS45084 = true -NPUG80325 = true -NPEG00023 = true -NPHG00027 = true -NPHG00028 = true -NPJH50170 = true -UCET00844 = true -# GOW: Chains of Olympus Demo -UCUS98705 = true -UCED00971 = true -UCUS98713 = true - [ForceSoftwareRenderer] # Darkstalkers ULES00016 = true ULUS10005 = true +ULJM05005 = true [DarkStalkersPresentHack] # Darkstalkers ULES00016 = true ULUS10005 = true +ULJM05005 = true diff --git a/assets/lang b/assets/lang index a95fd4974c..6189eb455e 160000 --- a/assets/lang +++ b/assets/lang @@ -1 +1 @@ -Subproject commit a95fd4974c436a1a07455c5beef4a12f9f47b811 +Subproject commit 6189eb455e4b184ede558f7354e6ba31b485fd58 diff --git a/build.gradle b/build.gradle index c651082644..a9deb8ae96 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.5.2' + classpath 'com.android.tools.build:gradle:3.5.3' } } diff --git a/ext/native/gfx_es2/draw_buffer.cpp b/ext/native/gfx_es2/draw_buffer.cpp index 5d1bb88153..b329534a93 100644 --- a/ext/native/gfx_es2/draw_buffer.cpp +++ b/ext/native/gfx_es2/draw_buffer.cpp @@ -495,8 +495,12 @@ void DrawBuffer::DrawTextRect(int font, const char *text, float x, float y, floa // ROTATE_* doesn't yet work right. void DrawBuffer::DrawText(int font, const char *text, float x, float y, Color color, int align) { // rough estimate - if (count_ + strlen(text) * 6 > MAX_VERTS) { + size_t textLen = strlen(text); + if (count_ + textLen * 6 > MAX_VERTS) { Flush(true); + if (textLen * 6 >= MAX_VERTS) { + textLen = std::min(MAX_VERTS / 6 - 10, (int)textLen); + } } const AtlasFont &atlasfont = *atlas->fonts[font]; @@ -508,14 +512,14 @@ void DrawBuffer::DrawText(int font, const char *text, float x, float y, Color co } if (align & ROTATE_90DEG_LEFT) { - x -= atlasfont.ascend*fontscaley; + x -= atlasfont.ascend * fontscaley; // y += h; + } else { + y += atlasfont.ascend * fontscaley; } - else - y += atlasfont.ascend*fontscaley; float sx = x; UTF8 utf(text); - while (true) { + for (size_t i = 0; i < textLen; i++) { if (utf.end()) break; cval = utf.next(); diff --git a/ext/native/thin3d/VulkanQueueRunner.cpp b/ext/native/thin3d/VulkanQueueRunner.cpp index 3785b7d9b9..8a7dcd8f4a 100644 --- a/ext/native/thin3d/VulkanQueueRunner.cpp +++ b/ext/native/thin3d/VulkanQueueRunner.cpp @@ -469,7 +469,7 @@ void VulkanQueueRunner::RunSteps(VkCommandBuffer cmd, std::vector &st break; } - if (profile) { + if (profile && profile->timestampDescriptions.size() + 1 < MAX_TIMESTAMP_QUERIES) { vkCmdWriteTimestamp(cmd, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, profile->queryPool, (uint32_t)profile->timestampDescriptions.size()); profile->timestampDescriptions.push_back(StepToString(step)); } @@ -789,11 +789,13 @@ void VulkanQueueRunner::ApplyRenderPassMerge(std::vector &steps) { if (steps[j]->copy.src == fb || steps[j]->copy.dst == fb) { goto done_fb; } + touchedFramebuffers.insert(steps[j]->copy.dst); break; case VKRStepType::BLIT: if (steps[j]->blit.src == fb || steps[j]->blit.dst == fb) { goto done_fb; } + touchedFramebuffers.insert(steps[j]->blit.dst); break; case VKRStepType::READBACK: // Not sure this has much effect, when executed READBACK is always the last step diff --git a/ext/native/thin3d/VulkanRenderManager.h b/ext/native/thin3d/VulkanRenderManager.h index 4201d912ad..c14c894a72 100644 --- a/ext/native/thin3d/VulkanRenderManager.h +++ b/ext/native/thin3d/VulkanRenderManager.h @@ -85,6 +85,10 @@ enum class VKRRunType { SYNC, }; +enum { + MAX_TIMESTAMP_QUERIES = 128, +}; + class VulkanRenderManager { public: VulkanRenderManager(VulkanContext *vulkan); @@ -299,10 +303,6 @@ private: FrameData frameData_[VulkanContext::MAX_INFLIGHT_FRAMES]; - enum { - MAX_TIMESTAMP_QUERIES = 256, - }; - // Submission time state int curWidth_ = -1; int curHeight_ = -1; diff --git a/ffmpeg b/ffmpeg index 90701640c7..55147e5f33 160000 --- a/ffmpeg +++ b/ffmpeg @@ -1 +1 @@ -Subproject commit 90701640c7f458461310b54e7d4041230e2d5d5a +Subproject commit 55147e5f33f5ae4904f75ec082af809267122b94