From b3e811d488878b23630417d2194cb7bae0c255ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=97=B1=20PixelyIon?= Date: Mon, 2 Dec 2019 23:10:53 +0530 Subject: [PATCH] Adapt C++ backend to changes This commit adapts the C++ backend to the Kotlin frontend by moving to usage of file descriptors and, provides an interface to access frontend code via JNI which is used to check the state of the activity and catch events such as surface destruction. In addition, this commit fixes some minor linting errors and changes the CMake version to 3.10.2+. --- app/build.gradle | 2 +- app/src/main/cpp/main.cpp | 126 +++++------------- app/src/main/cpp/skyline/common.cpp | 25 +++- app/src/main/cpp/skyline/common.h | 84 +++++++++++- app/src/main/cpp/skyline/gpu.cpp | 15 ++- app/src/main/cpp/skyline/gpu.h | 2 +- app/src/main/cpp/skyline/loader/loader.h | 11 +- app/src/main/cpp/skyline/loader/nro.cpp | 2 +- app/src/main/cpp/skyline/loader/nro.h | 2 +- app/src/main/cpp/skyline/nce.cpp | 3 +- app/src/main/cpp/skyline/os.cpp | 10 +- app/src/main/cpp/skyline/os.h | 7 +- app/src/main/java/emu/skyline/GameActivity.kt | 2 +- .../java/emu/skyline/adapter/LogAdapter.kt | 2 +- .../java/emu/skyline/loader/BaseLoader.kt | 2 +- app/src/main/res/values/array.xml | 10 +- app/src/main/res/values/strings.xml | 2 - 17 files changed, 163 insertions(+), 144 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index a8968dfe..c699b886 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -39,7 +39,7 @@ android { } externalNativeBuild { cmake { - version "3.8.0+" + version "3.10.2+" path "CMakeLists.txt" } } diff --git a/app/src/main/cpp/main.cpp b/app/src/main/cpp/main.cpp index 2b279cc4..c4579be9 100644 --- a/app/src/main/cpp/main.cpp +++ b/app/src/main/cpp/main.cpp @@ -1,115 +1,51 @@ #include "skyline/common.h" #include "skyline/os.h" #include -#include #include -#include #include bool Halt{}; -uint faultCount{}; -ANativeActivity *Activity{}; -ANativeWindow *Window{}; -AInputQueue *Queue{}; -std::thread *uiThread{}; - -void GameThread(const std::string &prefPath, const std::string &logPath, const std::string &romPath) { - while (!Window) - sched_yield(); - setpriority(PRIO_PROCESS, static_cast(getpid()), skyline::constant::PriorityAn.second); - auto settings = std::make_shared(prefPath); - auto logger = std::make_shared(logPath, static_cast(std::stoi(settings->GetString("log_level")))); - //settings->List(logger); // (Uncomment when you want to print out all settings strings) - auto start = std::chrono::steady_clock::now(); - try { - skyline::kernel::OS os(logger, settings, Window); - logger->Info("Launching ROM {}", romPath); - os.Execute(romPath); - logger->Info("Emulation has ended"); - } catch (std::exception &e) { - logger->Error(e.what()); - } catch (...) { - logger->Error("An unknown exception has occurred"); - } - auto end = std::chrono::steady_clock::now(); - logger->Info("Done in: {} ms", (std::chrono::duration_cast(end - start).count())); - Window = nullptr; - Halt = true; -} - -void UIThread(const std::string &prefPath, const std::string &logPath, const std::string &romPath) { - while (!Queue) - sched_yield(); - std::thread gameThread(GameThread, std::string(prefPath), std::string(logPath), std::string(romPath)); - AInputEvent *event{}; - while (!Halt) { - if (AInputQueue_getEvent(Queue, &event) >= -1) { - if (AKeyEvent_getKeyCode(event) == AKEYCODE_BACK) - Halt = true; - AInputQueue_finishEvent(Queue, event, true); - } - } - Queue = nullptr; - gameThread.join(); - Halt = false; - ANativeActivity_finish(Activity); -} - -void onNativeWindowCreated(ANativeActivity *activity, ANativeWindow *window) { - Window = window; -} - -void onInputQueueCreated(ANativeActivity *activity, AInputQueue *queue) { - Queue = queue; -} - -void onNativeWindowDestroyed(ANativeActivity *activity, ANativeWindow *window) { - Halt = true; - while (Window) - sched_yield(); -} - -void onInputQueueDestroyed(ANativeActivity *activity, AInputQueue *queue) { - Halt = true; - while (Queue) - sched_yield(); -} +uint FaultCount{}; void signalHandler(int signal) { syslog(LOG_ERR, "Halting program due to signal: %s", strsignal(signal)); - if (faultCount > 2) - pthread_kill(uiThread->native_handle(), SIGKILL); + if (FaultCount > 2) + exit(SIGKILL); else - ANativeActivity_finish(Activity); - faultCount++; + Halt = true; + FaultCount++; } -JNIEXPORT void ANativeActivity_onCreate(ANativeActivity *activity, void *savedState, size_t savedStateSize) { - Activity = activity; - Halt = false; - faultCount = 0; - JNIEnv *env = activity->env; - jobject intent = env->CallObjectMethod(activity->clazz, env->GetMethodID(env->GetObjectClass(activity->clazz), "getIntent", "()Landroid/content/Intent;")); - jclass icl = env->GetObjectClass(intent); - jmethodID gse = env->GetMethodID(icl, "getStringExtra", "(Ljava/lang/String;)Ljava/lang/String;"); - auto jsRom = reinterpret_cast(env->CallObjectMethod(intent, gse, env->NewStringUTF("rom"))); - auto jsPrefs = reinterpret_cast(env->CallObjectMethod(intent, gse, env->NewStringUTF("prefs"))); - auto jsLog = reinterpret_cast(env->CallObjectMethod(intent, gse, env->NewStringUTF("log"))); - const char *romPath = env->GetStringUTFChars(jsRom, nullptr); - const char *prefPath = env->GetStringUTFChars(jsPrefs, nullptr); - const char *logPath = env->GetStringUTFChars(jsLog, nullptr); +extern "C" JNIEXPORT void Java_emu_skyline_GameActivity_executeRom(JNIEnv *env, jobject instance, jstring romJstring, jint romType, jint romFd, jint preferenceFd, jint logFd) { std::signal(SIGTERM, signalHandler); std::signal(SIGSEGV, signalHandler); std::signal(SIGINT, signalHandler); std::signal(SIGILL, signalHandler); std::signal(SIGABRT, signalHandler); std::signal(SIGFPE, signalHandler); - activity->callbacks->onNativeWindowCreated = onNativeWindowCreated; - activity->callbacks->onInputQueueCreated = onInputQueueCreated; - activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed; - activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed; - uiThread = new std::thread(UIThread, std::string(prefPath), std::string(logPath), std::string(romPath)); - env->ReleaseStringUTFChars(jsRom, romPath); - env->ReleaseStringUTFChars(jsPrefs, prefPath); - env->ReleaseStringUTFChars(jsLog, logPath); + + setpriority(PRIO_PROCESS, static_cast(getpid()), skyline::constant::PriorityAn.second); + + auto jvmManager = std::make_shared(env, instance); + auto settings = std::make_shared(preferenceFd); + auto logger = std::make_shared(logFd, static_cast(std::stoi(settings->GetString("log_level")))); + //settings->List(logger); // (Uncomment when you want to print out all settings strings) + + auto start = std::chrono::steady_clock::now(); + + try { + skyline::kernel::OS os(jvmManager, logger, settings); + const char *romString = env->GetStringUTFChars(romJstring, nullptr); + logger->Info("Launching ROM {}", romString); + env->ReleaseStringUTFChars(romJstring, romString); + os.Execute(romFd, static_cast(romType)); + logger->Info("Emulation has ended"); + } catch (std::exception &e) { + logger->Error(e.what()); + } catch (...) { + logger->Error("An unknown exception has occurred"); + } + + auto end = std::chrono::steady_clock::now(); + logger->Info("Done in: {} ms", (std::chrono::duration_cast(end - start).count())); } diff --git a/app/src/main/cpp/skyline/common.cpp b/app/src/main/cpp/skyline/common.cpp index 96b64a1a..fca451e6 100644 --- a/app/src/main/cpp/skyline/common.cpp +++ b/app/src/main/cpp/skyline/common.cpp @@ -4,9 +4,9 @@ #include namespace skyline { - Settings::Settings(const std::string &prefXml) { + Settings::Settings(const int preferenceFd) { tinyxml2::XMLDocument pref; - if (pref.LoadFile(prefXml.c_str())) + if (pref.LoadFile(fdopen(preferenceFd, "r"))) throw exception("TinyXML2 Error: " + std::string(pref.ErrorStr())); tinyxml2::XMLElement *elem = pref.LastChild()->FirstChild()->ToElement(); while (elem) { @@ -51,8 +51,8 @@ namespace skyline { logger->Info("Key: {}, Value: {}, Type: Bool", iter.first, GetBool(iter.first)); } - Logger::Logger(const std::string &logPath, LogLevel configLevel) : configLevel(configLevel) { - logFile.open(logPath, std::ios::app); + Logger::Logger(const int logFd, LogLevel configLevel) : configLevel(configLevel) { + logFile.__open(logFd, std::ios::app); WriteHeader("Logging started"); } @@ -75,9 +75,20 @@ namespace skyline { logFile.flush(); } - DeviceState::DeviceState(kernel::OS *os, std::shared_ptr &thisProcess, std::shared_ptr &thisThread, ANativeWindow *window, std::shared_ptr settings, std::shared_ptr logger) : os(os), settings(std::move(settings)), logger(std::move(logger)), thisProcess(thisProcess), thisThread(thisThread) { - // We assign these later as they may use the state in their constructor and we don't want null pointers + JvmManager::JvmManager(JNIEnv *env, jobject instance) : env(env), instance(instance), instanceClass(env->GetObjectClass(instance)) {} + + jobject JvmManager::GetField(const char *key, const char *signature) { + return env->GetObjectField(instance, env->GetFieldID(instanceClass, key, signature)); + } + + bool JvmManager::CheckNull(const char *key, const char *signature) { + return env->IsSameObject(env->GetObjectField(instance, env->GetFieldID(instanceClass, key, signature)), nullptr); + } + + DeviceState::DeviceState(kernel::OS *os, std::shared_ptr &thisProcess, std::shared_ptr &thisThread, std::shared_ptr jvmManager, std::shared_ptr settings, std::shared_ptr logger) + : os(os), jvmManager(std::move(jvmManager)), settings(std::move(settings)), logger(std::move(logger)), thisProcess(thisProcess), thisThread(thisThread) { + // We assign these later as they use the state in their constructor and we don't want null pointers nce = std::move(std::make_shared(*this)); - gpu = std::move(std::make_shared(*this, window)); + gpu = std::move(std::make_shared(*this)); } } diff --git a/app/src/main/cpp/skyline/common.h b/app/src/main/cpp/skyline/common.h index c8796105..4b23a7cf 100644 --- a/app/src/main/cpp/skyline/common.h +++ b/app/src/main/cpp/skyline/common.h @@ -15,6 +15,7 @@ #include #include #include +#include namespace skyline { using u128 = __uint128_t; //!< Unsigned 128-bit integer @@ -94,6 +95,16 @@ namespace skyline { } }; + /** + * @brief This enumerates the types of the ROM + * @note This needs to be synchronized with emu.skyline.loader.BaseLoader.TitleFormat + */ + enum class TitleFormat { + NRO, //!< The NRO format: https://switchbrew.org/wiki/NRO + XCI, //!< The XCI format: https://switchbrew.org/wiki/XCI + NSP, //!< The NSP format from "nspwn" exploit: https://switchbrew.org/wiki/Switch_System_Flaws + }; + namespace instr { /** * @brief A bit-field struct that encapsulates a BRK instruction. See https://developer.arm.com/docs/ddi0596/latest/base-instructions-alphabetic-order/brk-breakpoint-instruction. @@ -182,7 +193,7 @@ namespace skyline { enum class Sreg { Sp, Pc, PState }; /** - * @brief The Logger class is to generate a log of the program + * @brief The Logger class is to write log output */ class Logger { private: @@ -195,13 +206,13 @@ namespace skyline { LogLevel configLevel; //!< The level of logs to write /** - * @param logPath The path to the log file + * @param logFd A FD to the log file * @param configLevel The minimum level of logs to write */ - Logger(const std::string &logPath, LogLevel configLevel); + Logger(const int logFd, LogLevel configLevel); /** - * Writes "Logging ended" as a header + * @brief Writes the termination message to the log file */ ~Logger(); @@ -278,9 +289,9 @@ namespace skyline { public: /** - * @param prefXml The path to the preference XML file + * @param preferenceFd An FD to the preference XML file */ - Settings(const std::string &prefXml); + Settings(const int preferenceFd); /** * @brief Retrieves a particular setting as a string @@ -322,6 +333,64 @@ namespace skyline { inline exception(const S &formatStr, Args &&... args) : runtime_error(fmt::format(formatStr, args...)) {} }; + /** + * @brief The JvmManager class is used to simplify transactions with the Java component + */ + class JvmManager { + public: + JNIEnv *env; //!< A pointer to the JNI environment + jobject instance; //!< A reference to the activity + jclass instanceClass; //!< The class of the activity + + /** + * @param env A pointer to the JNI environment + * @param instance A reference to the activity + */ + JvmManager(JNIEnv *env, jobject instance); + + /** + * @brief Retrieves a specific field of the given type from the activity + * @tparam objectType The type of the object in the field + * @param key The name of the field in the activity class + * @return The contents of the field as objectType + */ + template + objectType GetField(const char *key) { + if constexpr(std::is_same()) + return env->GetBooleanField(instance, env->GetFieldID(instanceClass, key, "Z")); + else if constexpr(std::is_same()) + return env->GetByteField(instance, env->GetFieldID(instanceClass, key, "B")); + else if constexpr(std::is_same()) + return env->GetCharField(instance, env->GetFieldID(instanceClass, key, "C")); + else if constexpr(std::is_same()) + return env->GetShortField(instance, env->GetFieldID(instanceClass, key, "S")); + else if constexpr(std::is_same()) + return env->GetIntField(instance, env->GetFieldID(instanceClass, key, "I")); + else if constexpr(std::is_same()) + return env->GetLongField(instance, env->GetFieldID(instanceClass, key, "J")); + else if constexpr(std::is_same()) + return env->GetFloatField(instance, env->GetFieldID(instanceClass, key, "F")); + else if constexpr(std::is_same()) + return env->GetDoubleField(instance, env->GetFieldID(instanceClass, key, "D")); + } + + /** + * @brief Retrieves a specific field from the activity as a jobject + * @param key The name of the field in the activity class + * @param signature The signature of the field + * @return A jobject of the contents of the field + */ + jobject GetField(const char *key, const char *signature); + + /** + * @brief Checks if a specific field from the activity is null or not + * @param key The name of the field in the activity class + * @param signature The signature of the field + * @return If the field is null or not + */ + bool CheckNull(const char *key, const char *signature); + }; + /** * @brief Returns the current time in nanoseconds * @return The current time in nanoseconds @@ -346,13 +415,14 @@ namespace skyline { * @brief This struct is used to hold the state of a device */ struct DeviceState { - DeviceState(kernel::OS *os, std::shared_ptr &thisProcess, std::shared_ptr &thisThread, ANativeWindow *window, std::shared_ptr settings, std::shared_ptr logger); + DeviceState(kernel::OS *os, std::shared_ptr &thisProcess, std::shared_ptr &thisThread, std::shared_ptr jvmManager, std::shared_ptr settings, std::shared_ptr logger); kernel::OS *os; //!< This holds a reference to the OS class std::shared_ptr &thisProcess; //!< This holds a reference to the current process object std::shared_ptr &thisThread; //!< This holds a reference to the current thread object std::shared_ptr nce; //!< This holds a reference to the NCE class std::shared_ptr gpu; //!< This holds a reference to the GPU class + std::shared_ptr jvmManager; //!< This holds a reference to the JvmManager class std::shared_ptr settings; //!< This holds a reference to the Settings class std::shared_ptr logger; //!< This holds a reference to the Logger class }; diff --git a/app/src/main/cpp/skyline/gpu.cpp b/app/src/main/cpp/skyline/gpu.cpp index 69a2e04d..48501918 100644 --- a/app/src/main/cpp/skyline/gpu.cpp +++ b/app/src/main/cpp/skyline/gpu.cpp @@ -4,11 +4,12 @@ #include "gpu/devices/nvhost_channel.h" #include "gpu/devices/nvhost_as_gpu.h" #include +#include extern bool Halt; namespace skyline::gpu { - GPU::GPU(const DeviceState &state, ANativeWindow *window) : state(state), window(window), bufferQueue(state), vsyncEvent(std::make_shared(state)), bufferEvent(std::make_shared(state)) { + GPU::GPU(const DeviceState &state) : state(state), window(ANativeWindow_fromSurface(state.jvmManager->env, state.jvmManager->GetField("surface", "Landroid/view/Surface;"))), bufferQueue(state), vsyncEvent(std::make_shared(state)), bufferEvent(std::make_shared(state)) { ANativeWindow_acquire(window); resolution.width = static_cast(ANativeWindow_getWidth(window)); resolution.height = static_cast(ANativeWindow_getHeight(window)); @@ -20,6 +21,18 @@ namespace skyline::gpu { } void GPU::Loop() { + if(state.jvmManager->CheckNull("surface", "Landroid/view/Surface;")) { + while (state.jvmManager->CheckNull("surface", "Landroid/view/Surface;")) { + if(state.jvmManager->GetField("halt")) + return; + sched_yield(); + } + window = ANativeWindow_fromSurface(state.jvmManager->env, state.jvmManager->GetField("surface", "Landroid/view/Surface;")); + ANativeWindow_acquire(window); + resolution.width = static_cast(ANativeWindow_getWidth(window)); + resolution.height = static_cast(ANativeWindow_getHeight(window)); + format = ANativeWindow_getFormat(window); + } if (!bufferQueue.displayQueue.empty()) { auto &buffer = bufferQueue.displayQueue.front(); bufferQueue.displayQueue.pop(); diff --git a/app/src/main/cpp/skyline/gpu.h b/app/src/main/cpp/skyline/gpu.h index 318442f9..aa7b9ada 100644 --- a/app/src/main/cpp/skyline/gpu.h +++ b/app/src/main/cpp/skyline/gpu.h @@ -31,7 +31,7 @@ namespace skyline::gpu { /** * @param window The ANativeWindow to render to */ - GPU(const DeviceState &state, ANativeWindow *window); + GPU(const DeviceState &state); /** * @brief The destructor for the GPU class diff --git a/app/src/main/cpp/skyline/loader/loader.h b/app/src/main/cpp/skyline/loader/loader.h index 20d6500b..41f91463 100644 --- a/app/src/main/cpp/skyline/loader/loader.h +++ b/app/src/main/cpp/skyline/loader/loader.h @@ -2,12 +2,12 @@ #include #include +#include namespace skyline::loader { class Loader { protected: - std::string filePath; //!< The path to the ROM file - std::ifstream file; //!< An input stream from the file + const int romFd; //!< An FD to the ROM file /** * @brief Read the file at a particular offset @@ -17,9 +17,8 @@ namespace skyline::loader { * @param size The amount to read in bytes */ template - void ReadOffset(T *output, u32 offset, size_t size) { - file.seekg(offset, std::ios_base::beg); - file.read(reinterpret_cast(output), size); + void ReadOffset(T *output, u64 offset, size_t size) { + pread64(romFd, output, size, offset); } /** @@ -52,7 +51,7 @@ namespace skyline::loader { /** * @param filePath The path to the ROM file */ - Loader(std::string &filePath) : filePath(filePath), file(filePath, std::ios::binary | std::ios::beg) {} + Loader(const int romFd) : romFd(romFd) {} /** * This loads in the data of the main process diff --git a/app/src/main/cpp/skyline/loader/nro.cpp b/app/src/main/cpp/skyline/loader/nro.cpp index 8d58e511..4d645dde 100644 --- a/app/src/main/cpp/skyline/loader/nro.cpp +++ b/app/src/main/cpp/skyline/loader/nro.cpp @@ -2,7 +2,7 @@ #include "nro.h" namespace skyline::loader { - NroLoader::NroLoader(std::string filePath) : Loader(filePath) { + NroLoader::NroLoader(const int romFd) : Loader(romFd) { ReadOffset((u32 *) &header, 0x0, sizeof(NroHeader)); if (header.magic != constant::NroMagic) throw exception("Invalid NRO magic! 0x{0:X}", header.magic); diff --git a/app/src/main/cpp/skyline/loader/nro.h b/app/src/main/cpp/skyline/loader/nro.h index c49037a2..60f57115 100644 --- a/app/src/main/cpp/skyline/loader/nro.h +++ b/app/src/main/cpp/skyline/loader/nro.h @@ -45,7 +45,7 @@ namespace skyline::loader { /** * @param filePath The path to the ROM file */ - NroLoader(std::string filePath); + NroLoader(const int romFd); /** * This loads in the data of the main process diff --git a/app/src/main/cpp/skyline/nce.cpp b/app/src/main/cpp/skyline/nce.cpp index 0d5d3069..d2a97691 100644 --- a/app/src/main/cpp/skyline/nce.cpp +++ b/app/src/main/cpp/skyline/nce.cpp @@ -32,7 +32,7 @@ namespace skyline { void NCE::Execute() { int status = 0; while (!Halt && !state.os->processMap.empty()) { - for (const auto &process : state.os->processMap) { // NOLINT(performance-for-range-copy) + for (const auto &process : state.os->processMap) { state.os->thisProcess = process.second; state.os->thisThread = process.second->threadMap.at(process.first); currPid = process.first; @@ -87,6 +87,7 @@ namespace skyline { } state.os->serviceManager.Loop(); state.gpu->Loop(); + Halt = state.jvmManager->GetField("halt"); } for (const auto &process : state.os->processMap) { state.os->KillThread(process.first); diff --git a/app/src/main/cpp/skyline/os.cpp b/app/src/main/cpp/skyline/os.cpp index 98918899..c1c46dde 100644 --- a/app/src/main/cpp/skyline/os.cpp +++ b/app/src/main/cpp/skyline/os.cpp @@ -3,14 +3,12 @@ #include "loader/nro.h" namespace skyline::kernel { - OS::OS(std::shared_ptr &logger, std::shared_ptr &settings, ANativeWindow *window) : state(this, thisProcess, thisThread, window, settings, logger), serviceManager(state) {} + OS::OS(std::shared_ptr& jvmManager, std::shared_ptr &logger, std::shared_ptr &settings) : state(this, thisProcess, thisThread, jvmManager, settings, logger), serviceManager(state) {} - void OS::Execute(const std::string &romFile) { - std::string romExt = romFile.substr(romFile.find_last_of('.') + 1); - std::transform(romExt.begin(), romExt.end(), romExt.begin(), [](unsigned char c) { return std::tolower(c); }); + void OS::Execute(const int romFd, const TitleFormat romType) { auto process = CreateProcess(constant::BaseAddr, constant::DefStackSize); - if (romExt == "nro") { - loader::NroLoader loader(romFile); + if (romType == TitleFormat::NRO) { + loader::NroLoader loader(romFd); loader.LoadProcessData(process, state); } else throw exception("Unsupported ROM extension."); diff --git a/app/src/main/cpp/skyline/os.h b/app/src/main/cpp/skyline/os.h index 9add81ce..fe3f8780 100644 --- a/app/src/main/cpp/skyline/os.h +++ b/app/src/main/cpp/skyline/os.h @@ -30,13 +30,14 @@ namespace skyline::kernel { * @param settings An instance of the Settings class * @param window The ANativeWindow object to draw the screen to */ - OS(std::shared_ptr &logger, std::shared_ptr &settings, ANativeWindow *window); + OS(std::shared_ptr& jvmManager, std::shared_ptr &logger, std::shared_ptr &settings); /** * @brief Execute a particular ROM file. This launches the main process and calls the NCE class to handle execution. - * @param romFile The path to the ROM file to execute + * @param romFd A FD to the ROM file to execute + * @param romType The type of the ROM file */ - void Execute(const std::string &romFile); + void Execute(const int romFd, const TitleFormat romType); /** * @brief Creates a new process diff --git a/app/src/main/java/emu/skyline/GameActivity.kt b/app/src/main/java/emu/skyline/GameActivity.kt index 717cb784..478fa0b2 100644 --- a/app/src/main/java/emu/skyline/GameActivity.kt +++ b/app/src/main/java/emu/skyline/GameActivity.kt @@ -38,7 +38,7 @@ class GameActivity : AppCompatActivity(), SurfaceHolder.Callback, InputQueue.Cal val preference = File("${applicationInfo.dataDir}/shared_prefs/${applicationInfo.packageName}_preferences.xml") preferenceFd = ParcelFileDescriptor.open(preference, ParcelFileDescriptor.MODE_READ_WRITE) val log = File("${applicationInfo.dataDir}/skyline.log") - logFd = ParcelFileDescriptor.open(log, ParcelFileDescriptor.MODE_READ_WRITE) + logFd = ParcelFileDescriptor.open(log, ParcelFileDescriptor.MODE_CREATE or ParcelFileDescriptor.MODE_READ_WRITE) window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN) game_view.holder.addCallback(this) //window.takeInputQueue(this) diff --git a/app/src/main/java/emu/skyline/adapter/LogAdapter.kt b/app/src/main/java/emu/skyline/adapter/LogAdapter.kt index 32791cde..43762c3a 100644 --- a/app/src/main/java/emu/skyline/adapter/LogAdapter.kt +++ b/app/src/main/java/emu/skyline/adapter/LogAdapter.kt @@ -73,7 +73,7 @@ internal class LogAdapter internal constructor(val context: Context, val compact viewHolder.txtTitle!!.text = item.title } viewHolder.position = position - return view!! + return view } private class ViewHolder { diff --git a/app/src/main/java/emu/skyline/loader/BaseLoader.kt b/app/src/main/java/emu/skyline/loader/BaseLoader.kt index 890888e8..3fa08d5f 100644 --- a/app/src/main/java/emu/skyline/loader/BaseLoader.kt +++ b/app/src/main/java/emu/skyline/loader/BaseLoader.kt @@ -19,7 +19,7 @@ enum class TitleFormat { internal class TitleEntry(var name: String, var author: String, var romType: TitleFormat, var valid: Boolean, @Transient var uri: Uri, @Transient var icon: Bitmap) : Serializable { constructor(context: Context, author: String, romType: TitleFormat, valid: Boolean, uri: Uri) : this("", author, romType, valid, uri, context.resources.getDrawable(R.drawable.ic_missing_icon, context.theme).toBitmap(256, 256)) { - context.contentResolver.query(uri, null, null, null, null)!!.use { cursor -> + context.contentResolver.query(uri, null, null, null, null)?.use { cursor -> val nameIndex: Int = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME) cursor.moveToFirst() name = cursor.getString(nameIndex) diff --git a/app/src/main/res/values/array.xml b/app/src/main/res/values/array.xml index ba489324..4449f71b 100644 --- a/app/src/main/res/values/array.xml +++ b/app/src/main/res/values/array.xml @@ -12,12 +12,4 @@ 2 3 - - System Language - English - - - sys - en - - \ No newline at end of file + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index cdbc8ed5..6837e093 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -27,8 +27,6 @@ Compact Logs Logs will be displayed in a compact form factor The logs will be displayed in a verbose form factor - Localization - Language System Use Docked Mode The system will emulate being in handheld mode