Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions app/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,10 @@ add_subdirectory("libraries/tzcode")
target_compile_options(tzcode PRIVATE -Wno-everything)

# Oboe
add_subdirectory("libraries/oboe")
include_directories(SYSTEM "libraries/oboe/include")
if (CMAKE_SYSTEM_NAME STREQUAL "Android")
add_subdirectory("libraries/oboe")
include_directories(SYSTEM "libraries/oboe/include")
endif()

# LZ4
set(LZ4_BUILD_CLI OFF CACHE BOOL "Build LZ4 CLI" FORCE)
Expand Down Expand Up @@ -103,7 +105,9 @@ add_subdirectory("libraries/range")
add_subdirectory("libraries/sirit")

# libadrenotools
add_subdirectory("libraries/adrenotools")
if (CMAKE_SYSTEM_NAME STREQUAL "Android")
add_subdirectory("libraries/adrenotools")
endif()

# Build Skyline with full debugging data and -Og for debug builds
set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g3 -glldb -gdwarf-5 -fno-omit-frame-pointer")
Expand Down Expand Up @@ -338,4 +342,8 @@ target_include_directories(skyline PRIVATE ${source_DIR}/skyline)
target_compile_options(skyline PRIVATE -Wall -Wno-unknown-attributes -Wno-c++20-extensions -Wno-c++17-extensions -Wno-c99-designator -Wno-reorder -Wno-missing-braces -Wno-unused-variable -Wno-unused-private-field -Wno-dangling-else -Wconversion -fsigned-bitfields)

target_link_libraries(skyline PRIVATE shader_recompiler)
target_link_libraries_system(skyline android perfetto fmt lz4_static tzcode oboe vkma mbedcrypto opus Boost::intrusive Boost::container range-v3 adrenotools)
if (CMAKE_SYSTEM_NAME STREQUAL "Android")
target_link_libraries_system(skyline android perfetto fmt lz4_static tzcode oboe vkma mbedcrypto opus Boost::intrusive Boost::container range-v3 adrenotools)
else()
target_link_libraries_system(skyline fmt lz4_static tzcode vkma mbedcrypto opus Boost::intrusive Boost::container range-v3)
endif()
2 changes: 2 additions & 0 deletions app/src/main/cpp/emu_jni.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: MPL-2.0
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)

#ifdef __ANDROID__ // FIX_LINUX jni
#include <csignal>
#include <pthread.h>
#include <android/asset_manager_jni.h>
Expand Down Expand Up @@ -241,3 +242,4 @@ extern "C" JNIEXPORT void JNICALL Java_emu_skyline_utils_NativeSettings_updateNa
extern "C" JNIEXPORT void JNICALL Java_emu_skyline_utils_NativeSettings_00024Companion_setLogLevel(JNIEnv *, jobject, jint logLevel) {
skyline::Logger::configLevel = static_cast<skyline::Logger::LogLevel>(logLevel);
}
#endif
2 changes: 2 additions & 0 deletions app/src/main/cpp/loader_jni.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: MPL-2.0
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)

#ifdef __ANDROID__ // FIX_LINUX jni
#include "skyline/common/logger.h"
#include "skyline/crypto/key_store.h"
#include "skyline/vfs/nca.h"
Expand Down Expand Up @@ -70,3 +71,4 @@ extern "C" JNIEXPORT jint JNICALL Java_emu_skyline_loader_RomFile_populate(JNIEn

return static_cast<jint>(skyline::loader::LoaderResult::Success);
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,10 @@ namespace skyline::applet::swkbd {
}

void SoftwareKeyboardApplet::SendResult() {
#ifdef __ANDROID__ // FIX_LINUX jni
if (dialog)
state.jvm->CloseKeyboard(dialog);
#endif
PushNormalDataAndSignal(std::make_shared<service::am::ObjIStorage<OutputResult>>(state, manager, OutputResult{currentResult, currentText, config.commonConfig.isUseUtf8}));
onAppletStateChanged->Signal();
}
Expand Down Expand Up @@ -111,6 +113,7 @@ namespace skyline::applet::swkbd {
if (!normalInputData.empty() && config.commonConfig.initialStringLength > 0)
currentText = std::u16string(normalInputData.front()->GetSpan().subspan(config.commonConfig.initialStringOffset).cast<char16_t>().data(), config.commonConfig.initialStringLength);

#ifdef __ANDROID__ // FIX_LINUX jni
dialog = state.jvm->ShowKeyboard(*reinterpret_cast<JvmManager::KeyboardConfig *>(&config), currentText);
if (!dialog) {
Logger::Warn("Couldn't show keyboard dialog, using default text");
Expand All @@ -121,6 +124,7 @@ namespace skyline::applet::swkbd {
currentResult = static_cast<CloseResult>(result.first);
currentText = result.second;
}
#endif
if (config.commonConfig.isUseTextCheck && currentResult == CloseResult::Enter) {
PushInteractiveDataAndSignal(std::make_shared<service::am::ObjIStorage<ValidationRequest>>(state, manager, ValidationRequest{currentText, config.commonConfig.isUseUtf8}));
validationPending = true;
Expand All @@ -146,6 +150,7 @@ namespace skyline::applet::swkbd {
validationPending = false;
SendResult();
} else {
#ifdef __ANDROID__ // FIX_LINUX jni
if (dialog) {
if (static_cast<CloseResult>(state.jvm->ShowValidationResult(dialog, static_cast<JvmManager::KeyboardTextCheckResult>(validationResult.result), std::u16string(validationResult.chars.data()))) == CloseResult::Enter) {
// Accepted on confirmation dialog
Expand All @@ -172,6 +177,7 @@ namespace skyline::applet::swkbd {
Logger::Debug("Guest asked to confirm default text with message: \"{}\"", message);
PushNormalDataAndSignal(std::make_shared<service::am::ObjIStorage<OutputResult>>(state, manager, OutputResult{CloseResult::Enter, currentText, config.commonConfig.isUseUtf8}));
}
#endif
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
#include "software_keyboard_config.h"

namespace skyline::applet::swkbd {
#ifdef __ANDROID__ // FIX_LINUX jvm
static_assert(sizeof(KeyboardConfigVB) == sizeof(JvmManager::KeyboardConfig));
#endif

/**
* @url https://switchbrew.org/wiki/Software_Keyboard
Expand Down Expand Up @@ -78,7 +80,9 @@ namespace skyline::applet::swkbd {
std::u16string currentText{};
CloseResult currentResult{};

#ifdef __ANDROID__ // FIX_LINUX jni
jobject dialog{};
#endif

void SendResult();

Expand Down
7 changes: 7 additions & 0 deletions app/src/main/cpp/skyline/audio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "audio.h"

namespace skyline::audio {
#ifdef __ANDROID__ // FIX_LINUX oboe
Audio::Audio(const DeviceState &state) : oboe::AudioStreamCallback() {
builder.setChannelCount(constant::StereoChannelCount);
builder.setSampleRate(constant::SampleRate);
Expand All @@ -21,6 +22,10 @@ namespace skyline::audio {
Audio::~Audio() {
outputStream->requestStop();
}
#else
Audio::Audio(const DeviceState &state) {}
Audio::~Audio() {}
#endif

std::shared_ptr<AudioTrack> Audio::OpenTrack(u8 channelCount, u32 sampleRate, const std::function<void()> &releaseCallback) {
std::scoped_lock trackGuard{trackLock};
Expand All @@ -37,6 +42,7 @@ namespace skyline::audio {
audioTracks.erase(std::remove(audioTracks.begin(), audioTracks.end(), track), audioTracks.end());
}

#ifdef __ANDROID__ // FIX_LINUX oboe
oboe::DataCallbackResult Audio::onAudioReady(oboe::AudioStream *audioStream, void *audioData, int32_t numFrames) {
auto destBuffer{static_cast<i16 *>(audioData)};
auto streamSamples{static_cast<size_t>(numFrames) * static_cast<size_t>(audioStream->getChannelCount())};
Expand Down Expand Up @@ -74,4 +80,5 @@ namespace skyline::audio {
outputStream->requestStart();
}
}
#endif
}
11 changes: 11 additions & 0 deletions app/src/main/cpp/skyline/audio.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,15 @@ namespace skyline::audio {
/**
* @brief The Audio class is used to mix audio from all tracks
*/
#ifdef __ANDROID__ // FIX_LINUX oboe
class Audio : public oboe::AudioStreamCallback {
private:
oboe::AudioStreamBuilder builder;
oboe::ManagedStream outputStream;
#else
class Audio {
private:
#endif
std::vector<std::shared_ptr<AudioTrack>> audioTracks;
std::mutex trackLock; //!< Synchronizes modifications to the audio tracks

Expand All @@ -22,11 +27,15 @@ namespace skyline::audio {
~Audio();

void Pause() {
#ifdef __ANDROID__ // FIX_LINUX oboe
outputStream->requestPause();
#endif
}

void Resume() {
#ifdef __ANDROID__ // FIX_LINUX oboe
outputStream->requestStart();
#endif
}

/**
Expand All @@ -43,6 +52,7 @@ namespace skyline::audio {
*/
void CloseTrack(std::shared_ptr<AudioTrack> &track);

#ifdef __ANDROID__ // FIX_LINUX oboe
/**
* @brief The callback oboe uses to get audio sample data
* @param audioStream The audio stream we are being called by
Expand All @@ -57,5 +67,6 @@ namespace skyline::audio {
* @param error The error due to which the stream is being closed
*/
void onErrorAfterClose(oboe::AudioStream *audioStream, oboe::Result error);
#endif
};
}
4 changes: 4 additions & 0 deletions app/src/main/cpp/skyline/audio/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@

#pragma once

#ifdef __ANDROID__ // FIX_LINUX oboe
#include <oboe/Oboe.h>
#endif
#include <common.h>

namespace skyline {
Expand All @@ -12,7 +14,9 @@ namespace skyline {
constexpr u8 StereoChannelCount{2}; //!< Channels to use for stereo audio output
constexpr u8 SurroundChannelCount{6}; //!< Channels to use for surround audio output (downsampled by backend)
constexpr u16 MixBufferSize{960}; //!< Default size of the audren mix buffer
#ifdef __ANDROID__ // FIX_LINUX oboe
constexpr auto PcmFormat{oboe::AudioFormat::I16}; //!< PCM data format to use for audio output
#endif
}

namespace audio {
Expand Down
5 changes: 5 additions & 0 deletions app/src/main/cpp/skyline/common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,13 @@
#include "kernel/types/KProcess.h"

namespace skyline {
#ifdef __ANDROID__ // FIX_LINUX jvm
DeviceState::DeviceState(kernel::OS *os, std::shared_ptr<JvmManager> jvmManager, std::shared_ptr<Settings> settings)
: os(os), jvm(std::move(jvmManager)), settings(std::move(settings)) {
#else
DeviceState::DeviceState(kernel::OS *os, std::shared_ptr<Settings> settings)
: os(os), settings(std::move(settings)) {
#endif
// We assign these later as they use the state in their constructor and we don't want null pointers
gpu = std::make_shared<gpu::GPU>(*this);
soc = std::make_shared<soc::SOC>(*this);
Expand Down
11 changes: 11 additions & 0 deletions app/src/main/cpp/skyline/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,19 @@
#include <common/span.h>
#include <common/result.h>
#include <common/logger.h>
#ifndef __ANDROID__
#include <signal.h>
#endif

namespace skyline {
class Settings;
namespace nce {
class NCE;
struct ThreadContext;
}
#ifdef __ANDROID__ // FIX_LINUX jvm
class JvmManager;
#endif
namespace gpu {
class GPU;
}
Expand Down Expand Up @@ -56,12 +61,18 @@ namespace skyline {
* @brief The state of the entire emulator is contained within this class, all objects related to emulation are tied into it
*/
struct DeviceState {
#ifdef __ANDROID__ // FIX_LINUX jvm
DeviceState(kernel::OS *os, std::shared_ptr<JvmManager> jvmManager, std::shared_ptr<Settings> settings);
#else
DeviceState(kernel::OS *os, std::shared_ptr<Settings> settings);
#endif

~DeviceState();

kernel::OS *os;
#ifdef __ANDROID__ // FIX_LINUX jvm
std::shared_ptr<JvmManager> jvm;
#endif
std::shared_ptr<Settings> settings;
std::shared_ptr<loader::Loader> loader;
std::shared_ptr<nce::NCE> nce;
Expand Down
6 changes: 6 additions & 0 deletions app/src/main/cpp/skyline/common/logger.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
// SPDX-License-Identifier: MPL-2.0
// Copyright © 2021 Skyline Team and Contributors (https://github.com/skyline-emu/)

#ifdef __ANDROID__ // FIX_LINUX logging
#include <android/log.h>
#endif
#include "utils.h"
#include "logger.h"

Expand Down Expand Up @@ -47,17 +49,21 @@ namespace skyline {
context = pContext;
}

#ifdef __ANDROID__ // FIX_LINUX logging
void Logger::WriteAndroid(LogLevel level, const std::string &str) {
constexpr std::array<int, 5> levelAlog{ANDROID_LOG_ERROR, ANDROID_LOG_WARN, ANDROID_LOG_INFO, ANDROID_LOG_DEBUG, ANDROID_LOG_VERBOSE}; // This corresponds to LogLevel and provides its equivalent for NDK Logging
if (logTag.empty())
UpdateTag();

__android_log_write(levelAlog[static_cast<u8>(level)], logTag.c_str(), str.c_str());
}
#endif

void Logger::Write(LogLevel level, const std::string &str) {
constexpr std::array<char, 5> levelCharacter{'E', 'W', 'I', 'D', 'V'}; // The LogLevel as written out to a file
#ifdef __ANDROID__ // FIX_LINUX logging
WriteAndroid(level, str);
#endif

if (context)
// We use RS (\036) and GS (\035) as our delimiters
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/cpp/skyline/common/logger.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,9 @@ namespace skyline {

static void SetContext(LoggerContext *context);

#ifdef __ANDROID__ // FIX_LINUX logging
static void WriteAndroid(LogLevel level, const std::string &str);
#endif

static void Write(LogLevel level, const std::string &str);

Expand Down
26 changes: 19 additions & 7 deletions app/src/main/cpp/skyline/common/signal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,10 @@ namespace skyline::signal {
}
}

void ExceptionalSignalHandler(int signal, siginfo *info, ucontext *context) {
void ExceptionalSignalHandler(int signal, siginfo_t *info, ucontext_t *context) {
SignalException signalException;
signalException.signal = signal;
#ifdef __ANDROID__ // FIX_LINUX uc_mcontext .pc and .regs
signalException.pc = reinterpret_cast<void *>(context->uc_mcontext.pc);
if (signal == SIGSEGV)
signalException.fault = info->si_addr;
Expand All @@ -98,6 +99,7 @@ namespace skyline::signal {

SignalExceptionPtr = std::make_exception_ptr(signalException);
context->uc_mcontext.pc = reinterpret_cast<u64>(&ExceptionThrow);
#endif

std::set_terminate(TerminateHandler);

Expand Down Expand Up @@ -130,7 +132,7 @@ namespace skyline::signal {
}

struct DefaultSignalHandler {
void (*function)(int, struct siginfo *, void *){};
void (*function)(int, siginfo_t *, void *){};

~DefaultSignalHandler();
};
Expand All @@ -155,7 +157,7 @@ namespace skyline::signal {
thread_local std::array<SignalHandler, NSIG> ThreadSignalHandlers{};

__attribute__((no_stack_protector)) // Stack protector stores data in TLS at the function epilogue and verifies it at the prolog, we cannot allow writes to guest TLS and may switch to an alternative TLS during the signal handler and have disabled the stack protector as a result
void ThreadSignalHandler(int signal, siginfo *info, ucontext *context) {
void ThreadSignalHandler(int signal, siginfo_t *info, ucontext_t *context) {
void *tls{}; // The TLS value prior to being restored if it is
if (TlsRestorer)
tls = TlsRestorer();
Expand All @@ -177,22 +179,32 @@ namespace skyline::signal {
static std::array<std::once_flag, NSIG> signalHandlerOnce{};

struct sigaction action{
.sa_sigaction = reinterpret_cast<void (*)(int, siginfo *, void *)>(ThreadSignalHandler),
.sa_flags = SA_SIGINFO | SA_EXPOSE_TAGBITS | (syscallRestart ? SA_RESTART : 0) | SA_ONSTACK,
.sa_sigaction = reinterpret_cast<void (*)(int, siginfo_t *, void *)>(ThreadSignalHandler),
.sa_flags = SA_SIGINFO
#ifdef __ANDROID__ // FIX_LINUX
| SA_EXPOSE_TAGBITS
#endif
| (syscallRestart ? SA_RESTART : 0) | SA_ONSTACK,
};

for (int signal : signals) {
std::call_once(signalHandlerOnce[static_cast<size_t>(signal)], [signal, &action]() {
struct sigaction oldAction;
Sigaction(signal, &action, &oldAction);
if (oldAction.sa_flags) {
#ifdef __ANDROID__ // FIX_LINUX
oldAction.sa_flags &= ~SA_UNSUPPORTED; // Mask out kernel not supporting old sigaction() bits
oldAction.sa_flags |= SA_SIGINFO | SA_EXPOSE_TAGBITS | SA_RESTART | SA_ONSTACK; // Intentionally ignore these flags for the comparison
#endif
oldAction.sa_flags |= SA_SIGINFO
#ifdef __ANDROID__ // FIX_LINUX
| SA_EXPOSE_TAGBITS
#endif
| SA_RESTART | SA_ONSTACK; // Intentionally ignore these flags for the comparison
if (oldAction.sa_flags != (action.sa_flags | SA_RESTART))
throw exception("Old sigaction flags aren't equivalent to the replaced signal: {:#b} | {:#b}", oldAction.sa_flags, action.sa_flags);
}

DefaultSignalHandlers.at(static_cast<size_t>(signal)).function = (oldAction.sa_flags & SA_SIGINFO) ? oldAction.sa_sigaction : reinterpret_cast<void (*)(int, struct siginfo *, void *)>(oldAction.sa_handler);
DefaultSignalHandlers.at(static_cast<size_t>(signal)).function = (oldAction.sa_flags & SA_SIGINFO) ? oldAction.sa_sigaction : reinterpret_cast<void (*)(int, siginfo_t *, void *)>(oldAction.sa_handler);
});
ThreadSignalHandlers.at(static_cast<size_t>(signal)) = function;
}
Expand Down
Loading