diff --git a/Core/Config.h b/Core/Config.h index d1b7da5eeb..ed57ec93fa 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -56,6 +56,7 @@ public: bool bUseVBO; int iWindowZoom; // for Windows bool SSAntiAlaising; //for Windows, too + bool bDisableG3DLog; // Sound bool bEnableSound; diff --git a/Core/FileSystems/MetaFileSystem.cpp b/Core/FileSystems/MetaFileSystem.cpp index fde8036b24..67fdd124b6 100644 --- a/Core/FileSystems/MetaFileSystem.cpp +++ b/Core/FileSystems/MetaFileSystem.cpp @@ -17,6 +17,7 @@ #include #include "Common/StringUtil.h" +#include "../HLE/sceKernelThread.h" #include "MetaFileSystem.h" static bool ApplyPathStringToComponentsVector(std::vector &vector, const std::string &pathString) @@ -163,7 +164,6 @@ IFileSystem *MetaFileSystem::GetHandleOwner(u32 handle) bool MetaFileSystem::MapFilePath(const std::string &_inpath, std::string &outpath, IFileSystem **system) { - //TODO: implement current directory per thread (NOT per drive) std::string realpath; // Special handling: host0:command.txt (as seen in Super Monkey Ball Adventures, for example) @@ -174,7 +174,22 @@ bool MetaFileSystem::MapFilePath(const std::string &_inpath, std::string &outpat inpath = inpath.substr(6); } - if ( RealPath(currentDirectory, inpath, realpath) ) + const std::string *currentDirectory = &startingDirectory; + + int currentThread = __KernelGetCurThread(); + currentDir_t::iterator i = currentDir.find(currentThread); + if (i == currentDir.end()) + { + //TODO: emulate PSP's error 8002032C: "no current working directory" if relative... may break things requiring fixes elsewhere + if (inpath.find(':') == std::string::npos /* means path is relative */) + WARN_LOG(HLE, "Path is relative, but current directory not set for thread %i. Should give error, instead falling back to %s", currentThread, startingDirectory.c_str()); + } + else + { + currentDirectory = &(i->second); + } + + if ( RealPath(*currentDirectory, inpath, realpath) ) { for (size_t i = 0; i < fileSystems.size(); i++) { @@ -203,7 +218,7 @@ void MetaFileSystem::Mount(std::string prefix, IFileSystem *system) fileSystems.push_back(x); } -void MetaFileSystem::UnmountAll() +void MetaFileSystem::Shutdown() { current = 6; @@ -220,7 +235,8 @@ void MetaFileSystem::UnmountAll() } fileSystems.clear(); - currentDirectory = ""; + currentDir.clear(); + startingDirectory = ""; } u32 MetaFileSystem::OpenFile(std::string filename, FileAccess access) @@ -278,6 +294,31 @@ std::vector MetaFileSystem::GetDirListing(std::string path) } } +void MetaFileSystem::ThreadEnded(int threadID) +{ + currentDir.erase(threadID); +} + +void MetaFileSystem::ChDir(const std::string &dir) +{ + int curThread = __KernelGetCurThread(); + + std::string of; + IFileSystem *system; + if (MapFilePath(dir, of, &system)) + { + currentDir[curThread] = of; + //return true; + } + else + { + //TODO: PSP's sceIoChdir seems very forgiving, but does it always accept bad paths and what happens when it does? + WARN_LOG(HLE, "ChDir failed to map path \"%s\", saving as current directory anyway", dir.c_str()); + currentDir[curThread] = dir; + //return false; + } +} + bool MetaFileSystem::MkDir(const std::string &dirname) { std::string of; @@ -372,9 +413,34 @@ size_t MetaFileSystem::SeekFile(u32 handle, s32 position, FileMove type) void MetaFileSystem::DoState(PointerWrap &p) { p.Do(current); - p.Do(currentDirectory); - int n = (int) fileSystems.size(); + // Save/load per-thread current directory map + u32 n = (u32) currentDir.size(); + p.Do(n); + if (p.mode == p.MODE_READ) + { + std::string dir; + currentDir.clear(); + for (u32 i = 0; i < n; ++i) + { + int threadID; + p.Do(threadID); + p.Do(dir); + + currentDir[threadID] = dir; + } + } + else + { + currentDir_t::iterator i = currentDir.begin(), end = currentDir.end(); + for (; i != end; ++i) + { + p.Do(i->first); + p.Do(i->second); + } + } + + n = (u32) fileSystems.size(); p.Do(n); if (n != fileSystems.size()) { @@ -382,7 +448,7 @@ void MetaFileSystem::DoState(PointerWrap &p) return; } - for (int i = 0; i < n; ++i) + for (u32 i = 0; i < n; ++i) fileSystems[i].system->DoState(p); p.DoMarker("MetaFileSystem"); diff --git a/Core/FileSystems/MetaFileSystem.h b/Core/FileSystems/MetaFileSystem.h index 88fc50d23c..17eeb4ca5c 100644 --- a/Core/FileSystems/MetaFileSystem.h +++ b/Core/FileSystems/MetaFileSystem.h @@ -30,8 +30,9 @@ public: void Mount(std::string prefix, IFileSystem *system); void Unmount(IFileSystem *system); - // Effectively "Shutdown". - void UnmountAll(); + void ThreadEnded(int threadID); + + void Shutdown(); u32 GetNewHandle() {return current++;} void FreeHandle(u32 handle) {} @@ -57,7 +58,7 @@ public: return SeekFile(handle, 0, FILEMOVE_CURRENT); } - virtual void ChDir(std::string dir) {currentDirectory = dir;} + virtual void ChDir(const std::string &dir); virtual bool MkDir(const std::string &dirname); virtual bool RmDir(const std::string &dirname); @@ -66,8 +67,8 @@ public: // TODO: void IoCtl(...) - void SetCurrentDirectory(const std::string &dir) { - currentDirectory = dir; + void SetStartingDirectory(const std::string &dir) { + startingDirectory = dir; } private: u32 current; @@ -78,5 +79,8 @@ private: }; std::vector fileSystems; - std::string currentDirectory; + typedef std::map currentDir_t; + currentDir_t currentDir; + + std::string startingDirectory; }; diff --git a/Core/HLE/sceIo.cpp b/Core/HLE/sceIo.cpp index 5910bd31ce..b0bbe4f0bb 100644 --- a/Core/HLE/sceIo.cpp +++ b/Core/HLE/sceIo.cpp @@ -159,6 +159,10 @@ public: PSPFileInfo info; }; +static void TellFsThreadEnded (SceUID threadID) { + pspFileSystem.ThreadEnded(threadID); +} + void __IoInit() { INFO_LOG(HLE, "Starting up I/O..."); @@ -199,6 +203,8 @@ void __IoInit() { pspFileSystem.Mount("fatms:", memstick); pspFileSystem.Mount("flash0:", flash); pspFileSystem.Mount("flash1:", flash); + + __KernelListenThreadEnd(&TellFsThreadEnded); } void __IoDoState(PointerWrap &p) { diff --git a/Core/HLE/sceKernel.h b/Core/HLE/sceKernel.h index 52ad5f8ca2..a461c14bbe 100644 --- a/Core/HLE/sceKernel.h +++ b/Core/HLE/sceKernel.h @@ -423,7 +423,7 @@ extern KernelObjectPool kernelObjects; struct KernelStats { void Reset() { - memset(this, 0, sizeof(this)); + memset(this, 0, sizeof(*this)); } void ResetFrame() { msInSyscalls = 0; diff --git a/Core/HLE/sceMpeg.cpp b/Core/HLE/sceMpeg.cpp index c44f4d1c31..0519e3dc24 100644 --- a/Core/HLE/sceMpeg.cpp +++ b/Core/HLE/sceMpeg.cpp @@ -1022,6 +1022,10 @@ int sceMpegGetAvcAu(u32 mpeg, u32 streamId, u32 auAddr, u32 attrAddr) if (!ctx->mediaengine->readVideoAu(&sceAu) || true) { // Only return this after the video already ended. if (ctx->endOfVideoReached) { + if (mpegRingbuffer.packetsFree < mpegRingbuffer.packets) { + mpegRingbuffer.packetsFree = mpegRingbuffer.packets; + Memory::WriteStruct(ctx->mpegRingbufferAddr, &mpegRingbuffer); + } result = PSP_ERROR_MPEG_NO_DATA; } if (ctx->mpegLastTimestamp < 0 || sceAu.pts >= ctx->mpegLastTimestamp) { diff --git a/Core/HLE/scePower.cpp b/Core/HLE/scePower.cpp index 13fbcaf85a..2113355baf 100644 --- a/Core/HLE/scePower.cpp +++ b/Core/HLE/scePower.cpp @@ -22,8 +22,22 @@ #include "scePower.h" #include "sceKernelThread.h" +const int PSP_POWER_ERROR_TAKEN_SLOT = 0x80000020; +const int PSP_POWER_ERROR_SLOTS_FULL = 0x80000022; +const int PSP_POWER_ERROR_PRIVATE_SLOT = 0x80000023; +const int PSP_POWER_ERROR_EMPTY_SLOT = 0x80000025; +const int PSP_POWER_ERROR_INVALID_CB = 0x80000100; +const int PSP_POWER_ERROR_INVALID_SLOT = 0x80000102; +const int PSP_POWER_ERROR_INVALID_TYPE = 0x80000107; + +const int PSP_POWER_CB_AC_POWER = 0x00001000; +const int PSP_POWER_CB_BATTERY_EXIST = 0x00000080; +const int PSP_POWER_CB_BATTERY_FULL = 0x00000064; + const int POWER_CB_AUTO = -1; + const int numberOfCBPowerSlots = 16; +const int numberOfCBPowerSlotsPrivate = 32; static bool volatileMemLocked; static int powerCbSlots[numberOfCBPowerSlots]; @@ -44,6 +58,12 @@ int scePowerGetBatteryLifePercent() { return 100; } +int scePowerGetBatteryLifeTime() { + DEBUG_LOG(HLE, "0=scePowerGetBatteryLifeTime()"); + // 0 means we're on AC power. + return 0; +} + int scePowerIsPowerOnline() { DEBUG_LOG(HLE, "1=scePowerIsPowerOnline"); return 1; @@ -70,61 +90,90 @@ int scePowerIsLowBattery() { } int scePowerRegisterCallback(int slot, int cbId) { - DEBUG_LOG(HLE,"0=scePowerRegisterCallback(%i, %i)", slot, cbId); - int foundSlot = -1; + DEBUG_LOG(HLE, "0=scePowerRegisterCallback(%i, %i)", slot, cbId); + + if (slot < -1 || slot >= numberOfCBPowerSlotsPrivate) { + return PSP_POWER_ERROR_INVALID_SLOT; + } + if (slot >= numberOfCBPowerSlots) { + return PSP_POWER_ERROR_PRIVATE_SLOT; + } + // TODO: If cbId is invalid return PSP_POWER_ERROR_INVALID_CB. + if (cbId == 0) { + return PSP_POWER_ERROR_INVALID_CB; + } + + int retval = -1; if (slot == POWER_CB_AUTO) { // -1 signifies auto select of bank for (int i=0; i < numberOfCBPowerSlots; i++) { - if ((powerCbSlots[i]==0) && (foundSlot == POWER_CB_AUTO)) { // found an empty slot + if (powerCbSlots[i] == 0 && retval == -1) { // found an empty slot powerCbSlots[i] = cbId; - foundSlot = i; + retval = i; } } + if (retval == -1) { + return PSP_POWER_ERROR_SLOTS_FULL; + } } else { if (powerCbSlots[slot] == 0) { powerCbSlots[slot] = cbId; - foundSlot = 0; + retval = 0; } else { - // slot already in use! - foundSlot = POWER_CB_AUTO; + return PSP_POWER_ERROR_TAKEN_SLOT; } } - if (foundSlot>=0) { + if (retval >= 0) { __KernelRegisterCallback(THREAD_CALLBACK_POWER, cbId); - __KernelNotifyCallbackType(THREAD_CALLBACK_POWER, cbId, 0x185); // TODO: I have no idea what the 0x185 is from the flags, but its needed for the test to pass. Need another example of it being called + + int arg = PSP_POWER_CB_AC_POWER | PSP_POWER_CB_BATTERY_EXIST | PSP_POWER_CB_BATTERY_FULL; + __KernelNotifyCallbackType(THREAD_CALLBACK_POWER, cbId, arg); } - return foundSlot; + return retval; } int scePowerUnregisterCallback(int slotId) { - if (slotId < 0 || slotId >= numberOfCBPowerSlots) { - return -1; + DEBUG_LOG(HLE, "0=scePowerUnregisterCallback(%i)", slotId); + + if (slotId < 0 || slotId >= numberOfCBPowerSlotsPrivate) { + return PSP_POWER_ERROR_INVALID_SLOT; + } + if (slotId >= numberOfCBPowerSlots) { + return PSP_POWER_ERROR_PRIVATE_SLOT; } if (powerCbSlots[slotId] != 0) { int cbId = powerCbSlots[slotId]; - DEBUG_LOG(HLE,"0=scePowerUnregisterCallback(%i) (cbid = %i)", slotId, cbId); + DEBUG_LOG(HLE, "0=scePowerUnregisterCallback(%i) (cbid = %i)", slotId, cbId); __KernelUnregisterCallback(THREAD_CALLBACK_POWER, cbId); powerCbSlots[slotId] = 0; } else { - return 0x80000025; // TODO: docs say a value less than 0, test checks for this specifically. why?? + return PSP_POWER_ERROR_EMPTY_SLOT; } return 0; } int sceKernelPowerLock(int lockType) { - DEBUG_LOG(HLE,"0=sceKernelPowerLock(%i)", lockType); - return 0; + DEBUG_LOG(HLE, "0=sceKernelPowerLock(%i)", lockType); + if (lockType == 0) { + return 0; + } else { + return PSP_POWER_ERROR_INVALID_TYPE; + } } int sceKernelPowerUnlock(int lockType) { - DEBUG_LOG(HLE,"0=sceKernelPowerUnlock(%i)", lockType); - return 0; + DEBUG_LOG(HLE, "0=sceKernelPowerUnlock(%i)", lockType); + if (lockType == 0) { + return 0; + } else { + return PSP_POWER_ERROR_INVALID_TYPE; + } } int sceKernelPowerTick(int flag) { - DEBUG_LOG(HLE,"UNIMPL 0=sceKernelPowerTick(%i)", flag); + DEBUG_LOG(HLE, "UNIMPL 0=sceKernelPowerTick(%i)", flag); return 0; } @@ -217,7 +266,7 @@ static const HLEFunction scePower[] = { {0x94F5A53F,0,"scePowerGetBatteryRemainCapacity"}, {0xFD18A0FF,0,"scePowerGetBatteryFullCapacity"}, {0x2085D15D,&WrapI_V,"scePowerGetBatteryLifePercent"}, - {0x8EFB3FA2,0,"scePowerGetBatteryLifeTime"}, + {0x8EFB3FA2,&WrapI_V,"scePowerGetBatteryLifeTime"}, {0x28E12023,0,"scePowerGetBatteryTemp"}, {0x862AE1A6,0,"scePowerGetBatteryElec"}, {0x483CE86B,0,"scePowerGetBatteryVolt"}, diff --git a/Core/Loaders.cpp b/Core/Loaders.cpp index c51da638a7..7bffa5ecba 100644 --- a/Core/Loaders.cpp +++ b/Core/Loaders.cpp @@ -92,11 +92,11 @@ bool LoadFile(const char *filename, std::string *error_string) // If loading from memstick... size_t pos = path.find("/PSP/GAME/"); if (pos != std::string::npos) - pspFileSystem.SetCurrentDirectory("ms0:" + path.substr(pos)); + pspFileSystem.SetStartingDirectory("ms0:" + path.substr(pos)); return Load_PSP_ELF_PBP(filename, error_string); } case FILETYPE_PSP_ISO: - pspFileSystem.SetCurrentDirectory("disc0:/PSP_GAME/USRDIR"); + pspFileSystem.SetStartingDirectory("disc0:/PSP_GAME/USRDIR"); return Load_PSP_ISO(filename, error_string); case FILETYPE_ERROR: ERROR_LOG(LOADER, "Could not file"); diff --git a/Core/System.cpp b/Core/System.cpp index 67c3b74cd6..1e7e6c8241 100644 --- a/Core/System.cpp +++ b/Core/System.cpp @@ -64,7 +64,7 @@ bool PSP_Init(const CoreParameter &coreParam, std::string *error_string) if (!LoadFile(coreParameter.fileToStart.c_str(), error_string)) { - pspFileSystem.UnmountAll(); + pspFileSystem.Shutdown(); CoreTiming::ClearPendingEvents(); CoreTiming::UnregisterAllEvents(); __KernelShutdown(); @@ -90,7 +90,7 @@ bool PSP_IsInited() void PSP_Shutdown() { - pspFileSystem.UnmountAll(); + pspFileSystem.Shutdown(); TextureCache_Clear(true); diff --git a/GPU/GLES/DisplayListInterpreter.cpp b/GPU/GLES/DisplayListInterpreter.cpp index cb862d3f34..113d1c8ba2 100644 --- a/GPU/GLES/DisplayListInterpreter.cpp +++ b/GPU/GLES/DisplayListInterpreter.cpp @@ -147,6 +147,8 @@ const int flushBeforeCommandList[] = { GLES_GPU::GLES_GPU(int renderWidth, int renderHeight) : interruptsEnabled_(true), displayFramebufPtr_(0), + prevDisplayFramebufPtr_(0), + prevPrevDisplayFramebufPtr_(0), renderWidth_(renderWidth), renderHeight_(renderHeight) { @@ -235,6 +237,8 @@ void GLES_GPU::BeginFrame() { void GLES_GPU::SetDisplayFramebuffer(u32 framebuf, u32 stride, int format) { if (framebuf & 0x04000000) { //DEBUG_LOG(G3D, "Switch display framebuffer %08x", framebuf); + prevPrevDisplayFramebufPtr_ = prevDisplayFramebufPtr_; + prevDisplayFramebufPtr_ = displayFramebufPtr_; displayFramebufPtr_ = framebuf; displayStride_ = stride; displayFormat_ = format; @@ -283,8 +287,20 @@ void GLES_GPU::CopyDisplayToOutput() { BeginDebugDraw(); } +static bool MaskedEqual(u32 addr1, u32 addr2) { + return (addr1 & 0x3FFFFFF) == (addr2 & 0x3FFFFFF); +} + + void GLES_GPU::DecimateFBOs() { for (auto iter = vfbs_.begin(); iter != vfbs_.end();) { + VirtualFramebuffer *v = *iter; + if (MaskedEqual(v->fb_address, displayFramebufPtr_) || + MaskedEqual(v->fb_address, prevDisplayFramebufPtr_) || + MaskedEqual(v->fb_address, prevPrevDisplayFramebufPtr_)) { + ++iter; + continue; + } if ((*iter)->last_frame_used + FBO_OLD_AGE < gpuStats.numFrames) { fbo_destroy((*iter)->fbo); vfbs_.erase(iter++); @@ -296,7 +312,7 @@ void GLES_GPU::DecimateFBOs() { GLES_GPU::VirtualFramebuffer *GLES_GPU::GetDisplayFBO() { for (auto iter = vfbs_.begin(); iter != vfbs_.end(); ++iter) { - if (((*iter)->fb_address & 0x3FFFFFF) == (displayFramebufPtr_ & 0x3FFFFFF)) { + if (MaskedEqual((*iter)->fb_address, displayFramebufPtr_)) { // Could check w to but whatever return *iter; } diff --git a/GPU/GLES/DisplayListInterpreter.h b/GPU/GLES/DisplayListInterpreter.h index 690ca4f5d2..9586acf392 100644 --- a/GPU/GLES/DisplayListInterpreter.h +++ b/GPU/GLES/DisplayListInterpreter.h @@ -73,6 +73,8 @@ private: bool interruptsEnabled_; u32 displayFramebufPtr_; + u32 prevDisplayFramebufPtr_; + u32 prevPrevDisplayFramebufPtr_; u32 displayStride_; int displayFormat_; diff --git a/Qt/Native.pro b/Qt/Native.pro index c0be10d0ce..c08db9b8e2 100755 --- a/Qt/Native.pro +++ b/Qt/Native.pro @@ -54,7 +54,7 @@ INCLUDEPATH += ../ext/snappy # Zlib !symbian: { - SOURCES += ../ext/zlib/adler32.c \ + SOURCES += ../ext/zlib/adler32.c \ ../ext/zlib/compress.c \ ../ext/zlib/crc32.c \ ../ext/zlib/deflate.c \ diff --git a/Qt/Settings.pri b/Qt/Settings.pri index c31a8218aa..4425495b9b 100644 --- a/Qt/Settings.pri +++ b/Qt/Settings.pri @@ -1,3 +1,4 @@ +DEFINES += USING_QT_UI blackberry|symbian|contains(MEEGO_EDITION,harmattan): CONFIG += mobile_platform unix:!blackberry:!symbian:!macx: CONFIG += linux diff --git a/Windows/WndMainWindow.cpp b/Windows/WndMainWindow.cpp index 38eed10d75..3bacff84fc 100644 --- a/Windows/WndMainWindow.cpp +++ b/Windows/WndMainWindow.cpp @@ -507,6 +507,14 @@ namespace MainWindow g_Config.SSAntiAlaising = !g_Config.SSAntiAlaising; UpdateMenus(); break; + case ID_OPTIONS_DISABLEG3DLOG: + g_Config.bDisableG3DLog = !g_Config.bDisableG3DLog; + if (!g_Config.bDisableG3DLog ) + LogManager::GetInstance()->SetEnable(LogTypes::G3D, true); + else + LogManager::GetInstance()->SetEnable(LogTypes::G3D, false); + UpdateMenus(); + break; case ID_OPTIONS_CONTROLS: DialogManager::EnableAll(FALSE); DialogBox(hInst, (LPCTSTR)IDD_CONTROLS, hWnd, (DLGPROC)Controls); @@ -653,6 +661,7 @@ namespace MainWindow CHECKITEM(ID_OPTIONS_SIMPLE2XSSAA, g_Config.SSAntiAlaising); CHECKITEM(ID_EMULATION_RUNONLOAD, g_Config.bAutoRun); CHECKITEM(ID_OPTIONS_USEVBO, g_Config.bUseVBO); + CHECKITEM(ID_OPTIONS_DISABLEG3DLOG, g_Config.bDisableG3DLog); UINT enable = !Core_IsStepping() ? MF_GRAYED : MF_ENABLED; EnableMenuItem(menu,ID_EMULATION_RUN, g_State.bEmuThreadStarted ? enable : MF_GRAYED); diff --git a/Windows/ppsspp.rc b/Windows/ppsspp.rc index b285c94183..c9b36e8724 100644 --- a/Windows/ppsspp.rc +++ b/Windows/ppsspp.rc @@ -261,6 +261,7 @@ BEGIN MENUITEM "&Wireframe (experimental)", ID_OPTIONS_WIREFRAME MENUITEM "&Display Raw Framebuffer", ID_OPTIONS_DISPLAYRAWFRAMEBUFFER MENUITEM "&Show Debug Statistics", ID_OPTIONS_SHOWDEBUGSTATISTICS + MENUITEM "&Disable G3D Log", ID_OPTIONS_DISABLEG3DLOG MENUITEM SEPARATOR MENUITEM "Screen &1x\tCtrl+1", ID_OPTIONS_SCREEN1X MENUITEM "Screen &2x\tCtrl+2", ID_OPTIONS_SCREEN2X diff --git a/Windows/resource.h b/Windows/resource.h index 5fbfb9d2f3..102ce27357 100644 --- a/Windows/resource.h +++ b/Windows/resource.h @@ -256,6 +256,7 @@ #define ID_DEBUG_DUMPNEXTFRAME 40132 #define ID_OPTIONS_SIMPLE2XSSAA 40133 #define ID_OPTIONS_USEVBO 40134 +#define ID_OPTIONS_DISABLEG3DLOG 40135 #define IDC_STATIC -1 // Next default values for new objects diff --git a/android/jni/MenuScreens.cpp b/android/jni/MenuScreens.cpp index 6d5759bdfd..fd61272215 100644 --- a/android/jni/MenuScreens.cpp +++ b/android/jni/MenuScreens.cpp @@ -42,6 +42,12 @@ #include "MenuScreens.h" #include "EmuScreen.h" +#ifdef USING_QT_UI +#include +#include +#include +#endif + // Ugly communication with NativeApp extern std::string game_title; @@ -163,6 +169,15 @@ void MenuScreen::render() { if (UIButton(GEN_ID, vlinear, w, "Load...", ALIGN_RIGHT)) { +#if defined(USING_QT_UI) && defined(__SYMBIAN32__) + QString fileName = QFileDialog::getOpenFileName(NULL, "Load ROM", g_Config.currentDirectory.c_str(), "PSP ROMs (*.iso *.cso *.pbp *.elf)"); + if (QFile::exists(fileName)) { + QDir newPath; + g_Config.currentDirectory = newPath.filePath(fileName).toStdString(); + g_Config.Save(); + screenManager()->switchScreen(new EmuScreen(fileName.toStdString())); + } +#else FileSelectScreenOptions options; options.allowChooseDirectory = true; options.filter = "iso:cso:pbp:elf:prx:"; @@ -172,6 +187,7 @@ void MenuScreen::render() { options.iconMapping["pbp"] = I_ICON_EXE; options.iconMapping["elf"] = I_ICON_EXE; screenManager()->switchScreen(new FileSelectScreen(options)); +#endif UIReset(); } @@ -437,7 +453,7 @@ static const char *credits[] = "Android SDK + NDK", #elif defined(BLACKBERRY) "Blackberry NDK", -#elif defined(__SYMBIAN32__) +#elif defined(USING_QT_UI) "Qt", #else "SDL",