mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-11-22 20:39:20 +01:00
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+.
This commit is contained in:
parent
e4dc602f4d
commit
b3e811d488
@ -39,7 +39,7 @@ android {
|
||||
}
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
version "3.8.0+"
|
||||
version "3.10.2+"
|
||||
path "CMakeLists.txt"
|
||||
}
|
||||
}
|
||||
|
@ -1,115 +1,51 @@
|
||||
#include "skyline/common.h"
|
||||
#include "skyline/os.h"
|
||||
#include <unistd.h>
|
||||
#include <jni.h>
|
||||
#include <android/native_window_jni.h>
|
||||
#include <android/native_activity.h>
|
||||
#include <csignal>
|
||||
|
||||
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<id_t>(getpid()), skyline::constant::PriorityAn.second);
|
||||
auto settings = std::make_shared<skyline::Settings>(prefPath);
|
||||
auto logger = std::make_shared<skyline::Logger>(logPath, static_cast<skyline::Logger::LogLevel>(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<std::chrono::milliseconds>(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<jstring>(env->CallObjectMethod(intent, gse, env->NewStringUTF("rom")));
|
||||
auto jsPrefs = reinterpret_cast<jstring>(env->CallObjectMethod(intent, gse, env->NewStringUTF("prefs")));
|
||||
auto jsLog = reinterpret_cast<jstring>(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<id_t>(getpid()), skyline::constant::PriorityAn.second);
|
||||
|
||||
auto jvmManager = std::make_shared<skyline::JvmManager>(env, instance);
|
||||
auto settings = std::make_shared<skyline::Settings>(preferenceFd);
|
||||
auto logger = std::make_shared<skyline::Logger>(logFd, static_cast<skyline::Logger::LogLevel>(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<skyline::TitleFormat>(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<std::chrono::milliseconds>(end - start).count()));
|
||||
}
|
||||
|
@ -4,9 +4,9 @@
|
||||
#include <tinyxml2.h>
|
||||
|
||||
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<kernel::type::KProcess> &thisProcess, std::shared_ptr<kernel::type::KThread> &thisThread, ANativeWindow *window, std::shared_ptr<Settings> settings, std::shared_ptr<Logger> 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<kernel::type::KProcess> &thisProcess, std::shared_ptr<kernel::type::KThread> &thisThread, std::shared_ptr<JvmManager> jvmManager, std::shared_ptr<Settings> settings, std::shared_ptr<Logger> 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<NCE>(*this));
|
||||
gpu = std::move(std::make_shared<gpu::GPU>(*this, window));
|
||||
gpu = std::move(std::make_shared<gpu::GPU>(*this));
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <android/native_window.h>
|
||||
#include <jni.h>
|
||||
|
||||
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<typename objectType>
|
||||
objectType GetField(const char *key) {
|
||||
if constexpr(std::is_same<objectType, jboolean>())
|
||||
return env->GetBooleanField(instance, env->GetFieldID(instanceClass, key, "Z"));
|
||||
else if constexpr(std::is_same<objectType, jbyte>())
|
||||
return env->GetByteField(instance, env->GetFieldID(instanceClass, key, "B"));
|
||||
else if constexpr(std::is_same<objectType, jchar>())
|
||||
return env->GetCharField(instance, env->GetFieldID(instanceClass, key, "C"));
|
||||
else if constexpr(std::is_same<objectType, jshort>())
|
||||
return env->GetShortField(instance, env->GetFieldID(instanceClass, key, "S"));
|
||||
else if constexpr(std::is_same<objectType, jint>())
|
||||
return env->GetIntField(instance, env->GetFieldID(instanceClass, key, "I"));
|
||||
else if constexpr(std::is_same<objectType, jlong>())
|
||||
return env->GetLongField(instance, env->GetFieldID(instanceClass, key, "J"));
|
||||
else if constexpr(std::is_same<objectType, jfloat>())
|
||||
return env->GetFloatField(instance, env->GetFieldID(instanceClass, key, "F"));
|
||||
else if constexpr(std::is_same<objectType, jdouble>())
|
||||
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<kernel::type::KProcess> &thisProcess, std::shared_ptr<kernel::type::KThread> &thisThread, ANativeWindow *window, std::shared_ptr<Settings> settings, std::shared_ptr<Logger> logger);
|
||||
DeviceState(kernel::OS *os, std::shared_ptr<kernel::type::KProcess> &thisProcess, std::shared_ptr<kernel::type::KThread> &thisThread, std::shared_ptr<JvmManager> jvmManager, std::shared_ptr<Settings> settings, std::shared_ptr<Logger> logger);
|
||||
|
||||
kernel::OS *os; //!< This holds a reference to the OS class
|
||||
std::shared_ptr<kernel::type::KProcess> &thisProcess; //!< This holds a reference to the current process object
|
||||
std::shared_ptr<kernel::type::KThread> &thisThread; //!< This holds a reference to the current thread object
|
||||
std::shared_ptr<NCE> nce; //!< This holds a reference to the NCE class
|
||||
std::shared_ptr<gpu::GPU> gpu; //!< This holds a reference to the GPU class
|
||||
std::shared_ptr<JvmManager> jvmManager; //!< This holds a reference to the JvmManager class
|
||||
std::shared_ptr<Settings> settings; //!< This holds a reference to the Settings class
|
||||
std::shared_ptr<Logger> logger; //!< This holds a reference to the Logger class
|
||||
};
|
||||
|
@ -4,11 +4,12 @@
|
||||
#include "gpu/devices/nvhost_channel.h"
|
||||
#include "gpu/devices/nvhost_as_gpu.h"
|
||||
#include <kernel/types/KProcess.h>
|
||||
#include <android/native_window_jni.h>
|
||||
|
||||
extern bool Halt;
|
||||
|
||||
namespace skyline::gpu {
|
||||
GPU::GPU(const DeviceState &state, ANativeWindow *window) : state(state), window(window), bufferQueue(state), vsyncEvent(std::make_shared<kernel::type::KEvent>(state)), bufferEvent(std::make_shared<kernel::type::KEvent>(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<kernel::type::KEvent>(state)), bufferEvent(std::make_shared<kernel::type::KEvent>(state)) {
|
||||
ANativeWindow_acquire(window);
|
||||
resolution.width = static_cast<u32>(ANativeWindow_getWidth(window));
|
||||
resolution.height = static_cast<u32>(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<jboolean>("halt"))
|
||||
return;
|
||||
sched_yield();
|
||||
}
|
||||
window = ANativeWindow_fromSurface(state.jvmManager->env, state.jvmManager->GetField("surface", "Landroid/view/Surface;"));
|
||||
ANativeWindow_acquire(window);
|
||||
resolution.width = static_cast<u32>(ANativeWindow_getWidth(window));
|
||||
resolution.height = static_cast<u32>(ANativeWindow_getHeight(window));
|
||||
format = ANativeWindow_getFormat(window);
|
||||
}
|
||||
if (!bufferQueue.displayQueue.empty()) {
|
||||
auto &buffer = bufferQueue.displayQueue.front();
|
||||
bufferQueue.displayQueue.pop();
|
||||
|
@ -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
|
||||
|
@ -2,12 +2,12 @@
|
||||
|
||||
#include <os.h>
|
||||
#include <kernel/types/KProcess.h>
|
||||
#include <unistd.h>
|
||||
|
||||
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<typename T>
|
||||
void ReadOffset(T *output, u32 offset, size_t size) {
|
||||
file.seekg(offset, std::ios_base::beg);
|
||||
file.read(reinterpret_cast<char *>(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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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<jboolean>("halt");
|
||||
}
|
||||
for (const auto &process : state.os->processMap) {
|
||||
state.os->KillThread(process.first);
|
||||
|
@ -3,14 +3,12 @@
|
||||
#include "loader/nro.h"
|
||||
|
||||
namespace skyline::kernel {
|
||||
OS::OS(std::shared_ptr<Logger> &logger, std::shared_ptr<Settings> &settings, ANativeWindow *window) : state(this, thisProcess, thisThread, window, settings, logger), serviceManager(state) {}
|
||||
OS::OS(std::shared_ptr<JvmManager>& jvmManager, std::shared_ptr<Logger> &logger, std::shared_ptr<Settings> &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.");
|
||||
|
@ -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> &logger, std::shared_ptr<Settings> &settings, ANativeWindow *window);
|
||||
OS(std::shared_ptr<JvmManager>& jvmManager, std::shared_ptr<Logger> &logger, std::shared_ptr<Settings> &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
|
||||
|
@ -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)
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
|
@ -12,12 +12,4 @@
|
||||
<item>2</item>
|
||||
<item>3</item>
|
||||
</string-array>
|
||||
<string-array name="language_names">
|
||||
<item>System Language</item>
|
||||
<item>English</item>
|
||||
</string-array>
|
||||
<string-array name="language_values">
|
||||
<item>sys</item>
|
||||
<item>en</item>
|
||||
</string-array>
|
||||
</resources>
|
||||
</resources>
|
||||
|
@ -27,8 +27,6 @@
|
||||
<string name="log_compact">Compact Logs</string>
|
||||
<string name="log_compact_desc_on">Logs will be displayed in a compact form factor</string>
|
||||
<string name="log_compact_desc_off">The logs will be displayed in a verbose form factor</string>
|
||||
<string name="localization">Localization</string>
|
||||
<string name="localization_language">Language</string>
|
||||
<string name="system">System</string>
|
||||
<string name="use_docked">Use Docked Mode</string>
|
||||
<string name="handheld_enabled">The system will emulate being in handheld mode</string>
|
||||
|
Loading…
Reference in New Issue
Block a user