diff options
author | Jesse Talavera-Greenberg <jesse@jesse.tg> | 2023-08-18 16:50:57 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-08-18 22:50:57 +0200 |
commit | ee5567708630441d8d3210e81d6e03d028fb7bbd (patch) | |
tree | ab92234123b16ec414d6c0da9bb0716c1b798229 /src/frontend/qt_sdl/Platform.cpp | |
parent | f454eba3c3243b095f0e6b9ddde3e68b095c5d8d (diff) |
Assorted portability enhancements (#1800)
* Introduce some Platform calls for managing dynamic libraries
* Add Platform::WriteFATSectors
* Introduce some Platform calls for managing dynamic libraries
* Add Platform::WriteFATSectors
* Change includes of "../types.h" to "types.h"
- Makes it easier to directly include these headers in downstream projects
* Change an include of "../Wifi.h" to "Wifi.h"
* Allow CommonFuncs.cpp to compile on Android
* Tidy up some logging calls
- Use Platform::Log in LAN_Socket.cpp
- Soften some warnings to Debug logs (since they don't necessarily represent problems)
* Add Platform::EnterGBAMode
- Gracefully stop the emulator if trying to enter GBA mode
* Soften some logs that most players won't care about
* Soften some more logs
* Introduce Platform wrappers for file operations
* Fix pointer spacing
* Fix more style nits
* Log the errno when ftruncate fails
* Fix FileSeek offset argument
- With an s32 offset, we couldn't access files larger than 2GB
* Revise Platform::StopEmu to address feedback
- Remove Platform::EnterGBAMode in favor of adding a reason to Platform::StopEmu
- Also rename Platform::StopEmu to Platform::SignalStop
- Add an optional argument to NDS::Stop
- Use the new argument everywhere that the console stops itself
* Rename FileGetString to FileReadLine
- It conveys the meaning better
* Rename FileSeekOrigin::Set to Start
- It conveys the meaning better
* Change definition of FileGetString to FileReadLine
- Oops, almost forgot it
* Rename FlushFile to FileFlush
- To remain consistent with the other File functions
* Add a FileType usage
* Fix line break in FileSeekOrigin
* Document Platform::DeInit
* Clarify that StopReason::Unknown doesn't always mean an error
* Move and document FileType::HostFile
* Remove Platform::OpenDataFile
- Nothing currently uses it
* Refactor Platform::OpenFile and Platform::OpenLocalFile to accept a FileMode enum instead of a string
- The enum is converted to fopen flags under the hood
- The file type is used to decide whether to add the "b" flag
- Some helper functions are exposed for the benefit of consistent behavior among frontends
- Equivalent behavior is maintained
* Fix a tab that should be spaces
* Use Windows' 64-bit implementations of fseek/ftell
* Move Platform::IsBinaryFile to Platform.cpp
- It could vary by frontend
* Remove an unused FileType
* Rename an enum constant
* Document various Platform items
* Use Platform::DynamicLibrary to load libandroid
- And clean it up at the end
* Fix a typo
* Pass the correct filetype to FATStorage
- Since it can be used for DSI NAND images or for SD cards
* Remove Platform::FileType
Diffstat (limited to 'src/frontend/qt_sdl/Platform.cpp')
-rw-r--r-- | src/frontend/qt_sdl/Platform.cpp | 203 |
1 files changed, 176 insertions, 27 deletions
diff --git a/src/frontend/qt_sdl/Platform.cpp b/src/frontend/qt_sdl/Platform.cpp index eef9934..5263377 100644 --- a/src/frontend/qt_sdl/Platform.cpp +++ b/src/frontend/qt_sdl/Platform.cpp @@ -29,6 +29,7 @@ #include <QMutex> #include <QOpenGLContext> #include <QSharedMemory> +#include <SDL_loadso.h> #include "Platform.h" #include "Config.h" @@ -37,7 +38,12 @@ #include "LAN_Socket.h" #include "LAN_PCap.h" #include "LocalMP.h" +#include "OSD.h" +#ifdef __WIN32__ +#define fseek _fseeki64 +#define ftell _ftelli64 +#endif // __WIN32__ std::string EmuDirectory; @@ -149,10 +155,24 @@ void DeInit() IPCDeInit(); } - -void StopEmu() +void SignalStop(StopReason reason) { emuStop(); + switch (reason) + { + case StopReason::GBAModeNotSupported: + Log(LogLevel::Error, "!! GBA MODE NOT SUPPORTED\n"); + OSD::AddMessage(0xFFA0A0, "GBA mode not supported."); + break; + case StopReason::BadExceptionRegion: + OSD::AddMessage(0xFFA0A0, "Internal error."); + break; + case StopReason::PowerOff: + case StopReason::External: + OSD::AddMessage(0xFFC040, "Shutdown"); + default: + break; + } } @@ -246,6 +266,7 @@ std::string GetConfigString(ConfigEntry entry) case Firm_Username: return Config::FirmwareUsername; case Firm_Message: return Config::FirmwareMessage; + case WifiSettingsPath: return Config::WifiSettingsPath; } return ""; @@ -288,45 +309,72 @@ bool GetConfigArray(ConfigEntry entry, void* data) return false; } +constexpr char AccessMode(FileMode mode, bool file_exists) +{ + if (!(mode & FileMode::Write)) + // If we're only opening the file for reading... + return 'r'; + + if (mode & (FileMode::NoCreate)) + // If we're not allowed to create a new file... + return 'r'; // Open in "r+" mode (IsExtended will add the "+") + + if ((mode & FileMode::Preserve) && file_exists) + // If we're not allowed to overwrite a file that already exists... + return 'r'; // Open in "r+" mode (IsExtended will add the "+") + + return 'w'; +} -FILE* OpenFile(const std::string& path, const std::string& mode, bool mustexist) +constexpr bool IsExtended(FileMode mode) { - QFile f(QString::fromStdString(path)); + // fopen's "+" flag always opens the file for read/write + return (mode & FileMode::ReadWrite) == FileMode::ReadWrite; +} - if (mustexist && !f.exists()) - { +static std::string GetModeString(FileMode mode, bool file_exists) +{ + std::string modeString; + + modeString += AccessMode(mode, file_exists); + + if (IsExtended(mode)) + modeString += '+'; + + if (!(mode & FileMode::Text)) + modeString += 'b'; + + return modeString; +} + +FileHandle* OpenFile(const std::string& path, FileMode mode) +{ + if ((mode & FileMode::ReadWrite) == FileMode::None) + { // If we aren't reading or writing, then we can't open the file + Log(LogLevel::Error, "Attempted to open \"%s\" in neither read nor write mode (FileMode 0x%x)\n", path.c_str(), mode); return nullptr; } - QIODevice::OpenMode qmode; - if (mode.length() > 1 && mode[0] == 'r' && mode[1] == '+') - { - qmode = QIODevice::OpenModeFlag::ReadWrite; - } - else if (mode.length() > 1 && mode[0] == 'w' && mode[1] == '+') - { - qmode = QIODevice::OpenModeFlag::Truncate | QIODevice::OpenModeFlag::ReadWrite; - } - else if (mode[0] == 'w') + bool file_exists = QFile::exists(QString::fromStdString(path)); + std::string modeString = GetModeString(mode, file_exists); + + FILE* file = fopen(path.c_str(), modeString.c_str()); + if (file) { - qmode = QIODevice::OpenModeFlag::Truncate | QIODevice::OpenModeFlag::WriteOnly; + Log(LogLevel::Debug, "Opened \"%s\" with FileMode 0x%x (effective mode \"%s\")\n", path.c_str(), mode, modeString.c_str()); + return reinterpret_cast<FileHandle *>(file); } else { - qmode = QIODevice::OpenModeFlag::ReadOnly; + Log(LogLevel::Warn, "Failed to open \"%s\" with FileMode 0x%x (effective mode \"%s\")\n", path.c_str(), mode, modeString.c_str()); + return nullptr; } - - f.open(qmode); - FILE* file = fdopen(dup(f.handle()), mode.c_str()); - f.close(); - - return file; } -FILE* OpenLocalFile(const std::string& path, const std::string& mode) +FileHandle* OpenLocalFile(const std::string& path, FileMode mode) { QString qpath = QString::fromStdString(path); - QDir dir(qpath); + QDir dir(qpath); QString fullpath; if (dir.isAbsolute()) @@ -347,7 +395,93 @@ FILE* OpenLocalFile(const std::string& path, const std::string& mode) #endif } - return OpenFile(fullpath.toStdString(), mode, mode[0] != 'w'); + return OpenFile(fullpath.toStdString(), mode); +} + +bool CloseFile(FileHandle* file) +{ + return fclose(reinterpret_cast<FILE *>(file)) == 0; +} + +bool IsEndOfFile(FileHandle* file) +{ + return feof(reinterpret_cast<FILE *>(file)) != 0; +} + +bool FileReadLine(char* str, int count, FileHandle* file) +{ + return fgets(str, count, reinterpret_cast<FILE *>(file)) != nullptr; +} + +bool FileExists(const std::string& name) +{ + FileHandle* f = OpenFile(name, FileMode::Read); + if (!f) return false; + CloseFile(f); + return true; +} + +bool LocalFileExists(const std::string& name) +{ + FileHandle* f = OpenLocalFile(name, FileMode::Read); + if (!f) return false; + CloseFile(f); + return true; +} + +bool FileSeek(FileHandle* file, s64 offset, FileSeekOrigin origin) +{ + int stdorigin; + switch (origin) + { + case FileSeekOrigin::Start: stdorigin = SEEK_SET; break; + case FileSeekOrigin::Current: stdorigin = SEEK_CUR; break; + case FileSeekOrigin::End: stdorigin = SEEK_END; break; + } + + return fseek(reinterpret_cast<FILE *>(file), offset, stdorigin) == 0; +} + +void FileRewind(FileHandle* file) +{ + rewind(reinterpret_cast<FILE *>(file)); +} + +u64 FileRead(void* data, u64 size, u64 count, FileHandle* file) +{ + return fread(data, size, count, reinterpret_cast<FILE *>(file)); +} + +bool FileFlush(FileHandle* file) +{ + return fflush(reinterpret_cast<FILE *>(file)) == 0; +} + +u64 FileWrite(const void* data, u64 size, u64 count, FileHandle* file) +{ + return fwrite(data, size, count, reinterpret_cast<FILE *>(file)); +} + +u64 FileWriteFormatted(FileHandle* file, const char* fmt, ...) +{ + if (fmt == nullptr) + return 0; + + va_list args; + va_start(args, fmt); + u64 ret = vfprintf(reinterpret_cast<FILE *>(file), fmt, args); + va_end(args); + return ret; +} + +u64 FileLength(FileHandle* file) +{ + FILE* stdfile = reinterpret_cast<FILE *>(file); + long pos = ftell(stdfile); + fseek(stdfile, 0, SEEK_END); + long len = ftell(stdfile); + fseek(stdfile, pos, SEEK_SET); + return len; } void Log(LogLevel level, const char* fmt, ...) @@ -566,4 +700,19 @@ void Camera_CaptureFrame(int num, u32* frame, int width, int height, bool yuv) return camManager[num]->captureFrame(frame, width, height, yuv); } +DynamicLibrary* DynamicLibrary_Load(const char* lib) +{ + return (DynamicLibrary*) SDL_LoadObject(lib); +} + +void DynamicLibrary_Unload(DynamicLibrary* lib) +{ + SDL_UnloadObject(lib); +} + +void* DynamicLibrary_LoadFunction(DynamicLibrary* lib, const char* name) +{ + return SDL_LoadFunction(lib, name); +} + } |