mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-15 10:40:01 +01:00
Merge branch 'master' into TemporaryHackishBranch
# Conflicts: # Core/Compatibility.cpp # Core/Compatibility.h
This commit is contained in:
commit
a0306633fc
33 files changed
+327
-215
No files matched your search
+6
-14
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -68,7 +68,6 @@ struct CompatFlags {
|
||||
bool DisableAccurateDepth;
|
||||
bool MGS2AcidHack;
|
||||
bool SonicRivalsHack;
|
||||
bool RenderPassMerge;
|
||||
bool AdhocHackDisableNBSwitch;
|
||||
bool AdhocHackStopFriendClear;
|
||||
bool AdhocHackPhantasyStarOffset;
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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<std::recursive_mutex> 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<std::recursive_mutex> 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<std::recursive_mutex> 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<std::recursive_mutex> 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<std::recursive_mutex> 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<PSPFileInfo> MetaFileSystem::GetDirListing(std::string path)
|
||||
std::lock_guard<std::recursive_mutex> 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<std::recursive_mutex> 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<std::recursive_mutex> 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<std::recursive_mutex> 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<std::recursive_mutex> 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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
+60
-36
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
+5
-33
@@ -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<ISOFileSystem *>(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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -158,3 +158,5 @@ void RegisterFileLoaderFactory(std::string name, std::unique_ptr<FileLoaderFacto
|
||||
|
||||
// Can modify the string filename, as it calls IdentifyFile above.
|
||||
bool LoadFile(FileLoader **fileLoaderPtr, std::string *error_string);
|
||||
|
||||
bool UmdReplace(std::string filepath, std::string &error);
|
||||
+30
-1
@@ -83,7 +83,7 @@ void InitMemoryForGameISO(FileLoader *fileLoader) {
|
||||
|
||||
IFileSystem *fileSystem = nullptr;
|
||||
IFileSystem *blockSystem = nullptr;
|
||||
bool actualIso = false;
|
||||
|
||||
if (fileLoader->IsDirectory()) {
|
||||
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;
|
||||
|
||||
@@ -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();
|
||||
+51
-35
@@ -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) {
|
||||
|
||||
@@ -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<u32> fbTexBuffer;
|
||||
std::vector<u32> fbTexBuffer_;
|
||||
|
||||
Draw::SamplerState *samplerNearest = nullptr;
|
||||
Draw::SamplerState *samplerLinear = nullptr;
|
||||
|
||||
@@ -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);
|
||||
|
||||
+7
-7
@@ -18,12 +18,12 @@
|
||||
#include <string>
|
||||
#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;
|
||||
}
|
||||
+5
-6
@@ -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;
|
||||
};
|
||||
@@ -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);
|
||||
|
||||
|
||||
+3
-1
@@ -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 : "");
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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.
|
||||
|
||||
+2
-36
@@ -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
|
||||
+1
-1
Submodule assets/lang updated: a95fd4974c...6189eb455e.
+1
-1
@@ -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'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -469,7 +469,7 @@ void VulkanQueueRunner::RunSteps(VkCommandBuffer cmd, std::vector<VKRStep *> &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<VKRStep *> &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
|
||||
|
||||
@@ -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;
|
||||
|
||||
+1
-1
Submodule ffmpeg updated: 90701640c7...55147e5f33.
Reference in new issue
Block a user