mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-11-22 20:09:17 +01:00
Add AndroidAsset{Backing,FileSystem} for accessing built-in assets
These only implement the subset of VFS needed for time, implementing more is difficult due to some issues in the AAsset API which make support quite ugly. The abstract asset filesystem can be accessed by services through the OS class allowing other implementations to be used in the future.
This commit is contained in:
parent
a0f6cc161c
commit
63c54207d2
@ -75,11 +75,13 @@ add_library(skyline SHARED
|
|||||||
${source_DIR}/skyline/loader/nca.cpp
|
${source_DIR}/skyline/loader/nca.cpp
|
||||||
${source_DIR}/skyline/loader/xci.cpp
|
${source_DIR}/skyline/loader/xci.cpp
|
||||||
${source_DIR}/skyline/loader/nsp.cpp
|
${source_DIR}/skyline/loader/nsp.cpp
|
||||||
${source_DIR}/skyline/vfs/os_filesystem.cpp
|
|
||||||
${source_DIR}/skyline/vfs/partition_filesystem.cpp
|
${source_DIR}/skyline/vfs/partition_filesystem.cpp
|
||||||
${source_DIR}/skyline/vfs/ctr_encrypted_backing.cpp
|
${source_DIR}/skyline/vfs/ctr_encrypted_backing.cpp
|
||||||
${source_DIR}/skyline/vfs/rom_filesystem.cpp
|
${source_DIR}/skyline/vfs/rom_filesystem.cpp
|
||||||
|
${source_DIR}/skyline/vfs/os_filesystem.cpp
|
||||||
${source_DIR}/skyline/vfs/os_backing.cpp
|
${source_DIR}/skyline/vfs/os_backing.cpp
|
||||||
|
${source_DIR}/skyline/vfs/android_asset_filesystem.cpp
|
||||||
|
${source_DIR}/skyline/vfs/android_asset_backing.cpp
|
||||||
${source_DIR}/skyline/vfs/nacp.cpp
|
${source_DIR}/skyline/vfs/nacp.cpp
|
||||||
${source_DIR}/skyline/vfs/npdm.cpp
|
${source_DIR}/skyline/vfs/npdm.cpp
|
||||||
${source_DIR}/skyline/vfs/nca.cpp
|
${source_DIR}/skyline/vfs/nca.cpp
|
||||||
|
@ -5,10 +5,12 @@
|
|||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <android/log.h>
|
#include <android/log.h>
|
||||||
|
#include <android/asset_manager_jni.h>
|
||||||
#include "skyline/common.h"
|
#include "skyline/common.h"
|
||||||
#include "skyline/common/signal.h"
|
#include "skyline/common/signal.h"
|
||||||
#include "skyline/common/settings.h"
|
#include "skyline/common/settings.h"
|
||||||
#include "skyline/loader/loader.h"
|
#include "skyline/loader/loader.h"
|
||||||
|
#include "skyline/vfs/android_asset_filesystem.h"
|
||||||
#include "skyline/os.h"
|
#include "skyline/os.h"
|
||||||
#include "skyline/jvm.h"
|
#include "skyline/jvm.h"
|
||||||
#include "skyline/gpu.h"
|
#include "skyline/gpu.h"
|
||||||
@ -21,7 +23,7 @@ std::weak_ptr<skyline::kernel::OS> OsWeak;
|
|||||||
std::weak_ptr<skyline::gpu::GPU> GpuWeak;
|
std::weak_ptr<skyline::gpu::GPU> GpuWeak;
|
||||||
std::weak_ptr<skyline::input::Input> InputWeak;
|
std::weak_ptr<skyline::input::Input> InputWeak;
|
||||||
|
|
||||||
extern "C" JNIEXPORT void Java_emu_skyline_EmulationActivity_executeApplication(JNIEnv *env, jobject instance, jstring romUriJstring, jint romType, jint romFd, jint preferenceFd, jstring appFilesPathJstring) {
|
extern "C" JNIEXPORT void Java_emu_skyline_EmulationActivity_executeApplication(JNIEnv *env, jobject instance, jstring romUriJstring, jint romType, jint romFd, jint preferenceFd, jstring appFilesPathJstring, jobject assetManager) {
|
||||||
skyline::signal::ScopedStackBlocker stackBlocker; // We do not want anything to unwind past JNI code as there are invalid stack frames which can lead to a segmentation fault
|
skyline::signal::ScopedStackBlocker stackBlocker; // We do not want anything to unwind past JNI code as there are invalid stack frames which can lead to a segmentation fault
|
||||||
Fps = FrameTime = 0;
|
Fps = FrameTime = 0;
|
||||||
|
|
||||||
@ -37,7 +39,7 @@ extern "C" JNIEXPORT void Java_emu_skyline_EmulationActivity_executeApplication(
|
|||||||
auto start{std::chrono::steady_clock::now()};
|
auto start{std::chrono::steady_clock::now()};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
auto os{std::make_shared<skyline::kernel::OS>(jvmManager, logger, settings, std::string(appFilesPath))};
|
auto os{std::make_shared<skyline::kernel::OS>(jvmManager, logger, settings, std::string(appFilesPath), std::make_shared<skyline::vfs::AndroidAssetFileSystem>(AAssetManager_fromJava(env, assetManager)))};
|
||||||
OsWeak = os;
|
OsWeak = os;
|
||||||
GpuWeak = os->state.gpu;
|
GpuWeak = os->state.gpu;
|
||||||
InputWeak = os->state.input;
|
InputWeak = os->state.input;
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
#include "os.h"
|
#include "os.h"
|
||||||
|
|
||||||
namespace skyline::kernel {
|
namespace skyline::kernel {
|
||||||
OS::OS(std::shared_ptr<JvmManager> &jvmManager, std::shared_ptr<Logger> &logger, std::shared_ptr<Settings> &settings, std::string appFilesPath) : state(this, jvmManager, settings, logger), serviceManager(state), appFilesPath(std::move(appFilesPath)) {}
|
OS::OS(std::shared_ptr<JvmManager> &jvmManager, std::shared_ptr<Logger> &logger, std::shared_ptr<Settings> &settings, std::string appFilesPath, std::shared_ptr<vfs::FileSystem> assetFileSystem) : state(this, jvmManager, settings, logger), appFilesPath(std::move(appFilesPath)), assetFileSystem(std::move(assetFileSystem)), serviceManager(state) {}
|
||||||
|
|
||||||
void OS::Execute(int romFd, loader::RomFormat romType) {
|
void OS::Execute(int romFd, loader::RomFormat romType) {
|
||||||
auto romFile{std::make_shared<vfs::OsBacking>(romFd)};
|
auto romFile{std::make_shared<vfs::OsBacking>(romFd)};
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "vfs/filesystem.h"
|
||||||
#include "loader/loader.h"
|
#include "loader/loader.h"
|
||||||
#include "services/serviceman.h"
|
#include "services/serviceman.h"
|
||||||
|
|
||||||
@ -13,15 +14,16 @@ namespace skyline::kernel {
|
|||||||
class OS {
|
class OS {
|
||||||
public:
|
public:
|
||||||
DeviceState state;
|
DeviceState state;
|
||||||
service::ServiceManager serviceManager;
|
|
||||||
std::string appFilesPath; //!< The full path to the app's files directory
|
std::string appFilesPath; //!< The full path to the app's files directory
|
||||||
|
std::shared_ptr<vfs::FileSystem> assetFileSystem; //!< A filesystem to be used for accessing emulator assets (like tzdata)
|
||||||
|
service::ServiceManager serviceManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param logger An instance of the Logger class
|
* @param logger An instance of the Logger class
|
||||||
* @param settings An instance of the Settings class
|
* @param settings An instance of the Settings class
|
||||||
* @param window The ANativeWindow object to draw the screen to
|
* @param window The ANativeWindow object to draw the screen to
|
||||||
*/
|
*/
|
||||||
OS(std::shared_ptr<JvmManager> &jvmManager, std::shared_ptr<Logger> &logger, std::shared_ptr<Settings> &settings, std::string appFilesPath);
|
OS(std::shared_ptr<JvmManager> &jvmManager, std::shared_ptr<Logger> &logger, std::shared_ptr<Settings> &settings, std::string appFilesPath, std::shared_ptr<vfs::FileSystem>);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Execute a particular ROM file
|
* @brief Execute a particular ROM file
|
||||||
|
30
app/src/main/cpp/skyline/vfs/android_asset_backing.cpp
Normal file
30
app/src/main/cpp/skyline/vfs/android_asset_backing.cpp
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
// Copyright © 2021 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <android/asset_manager.h>
|
||||||
|
#include "android_asset_backing.h"
|
||||||
|
|
||||||
|
namespace skyline::vfs {
|
||||||
|
AndroidAssetBacking::AndroidAssetBacking(AAsset *backing, Mode mode) : Backing(mode), backing(backing) {
|
||||||
|
if (mode.write || mode.append)
|
||||||
|
throw exception("AndroidAssetBacking doesn't support writing");
|
||||||
|
|
||||||
|
size = AAsset_getLength64(backing);
|
||||||
|
}
|
||||||
|
|
||||||
|
AndroidAssetBacking::~AndroidAssetBacking() {
|
||||||
|
AAsset_close(backing);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t AndroidAssetBacking::ReadImpl(span<u8> output, size_t offset) {
|
||||||
|
if (AAsset_seek64(backing, offset, SEEK_SET) != offset)
|
||||||
|
throw exception("Failed to seek asset position");
|
||||||
|
|
||||||
|
auto ret{AAsset_read(backing, output.data(), output.size())};
|
||||||
|
if (ret < 0)
|
||||||
|
throw exception("Failed to read from fd: {}", strerror(errno));
|
||||||
|
|
||||||
|
return static_cast<size_t>(ret);
|
||||||
|
}
|
||||||
|
}
|
28
app/src/main/cpp/skyline/vfs/android_asset_backing.h
Normal file
28
app/src/main/cpp/skyline/vfs/android_asset_backing.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
// Copyright © 2021 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "backing.h"
|
||||||
|
|
||||||
|
struct AAsset;
|
||||||
|
|
||||||
|
namespace skyline::vfs {
|
||||||
|
/**
|
||||||
|
* @brief The AndroidAssetBacking class provides the backing abstractions for the AAsset Android API
|
||||||
|
* @note This is NOT thread safe NOR should it be shared across threads.
|
||||||
|
* @note This will take ownership of the backing asset passed into it
|
||||||
|
*/
|
||||||
|
class AndroidAssetBacking : public Backing {
|
||||||
|
private:
|
||||||
|
AAsset *backing; //!< The backing AAsset object we abstract
|
||||||
|
|
||||||
|
protected:
|
||||||
|
size_t ReadImpl(span<u8> output, size_t offset) override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
AndroidAssetBacking(AAsset *backing, Mode mode = {true, false, false});
|
||||||
|
|
||||||
|
virtual ~AndroidAssetBacking();
|
||||||
|
};
|
||||||
|
}
|
35
app/src/main/cpp/skyline/vfs/android_asset_filesystem.cpp
Normal file
35
app/src/main/cpp/skyline/vfs/android_asset_filesystem.cpp
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
// Copyright © 2021 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
||||||
|
|
||||||
|
#include <android/asset_manager.h>
|
||||||
|
#include "android_asset_backing.h"
|
||||||
|
#include "android_asset_filesystem.h"
|
||||||
|
|
||||||
|
namespace skyline::vfs {
|
||||||
|
AndroidAssetFileSystem::AndroidAssetFileSystem(AAssetManager *backing) : FileSystem(), backing(backing) {}
|
||||||
|
|
||||||
|
std::shared_ptr<Backing> AndroidAssetFileSystem::OpenFileImpl(const std::string &path, Backing::Mode mode) {
|
||||||
|
auto file{AAssetManager_open(backing, path.c_str(), AASSET_MODE_RANDOM)};
|
||||||
|
if (file == nullptr)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return std::make_shared<AndroidAssetBacking>(file, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<Directory::EntryType> AndroidAssetFileSystem::GetEntryTypeImpl(const std::string &path) {
|
||||||
|
// Tries to open as a file then as a directory in order to check the type
|
||||||
|
// This is really hacky but it at least it works
|
||||||
|
if (AAssetManager_open(backing, path.c_str(), AASSET_MODE_RANDOM) != nullptr)
|
||||||
|
return Directory::EntryType::File;
|
||||||
|
|
||||||
|
if (AAssetManager_openDir(backing, path.c_str()) != nullptr)
|
||||||
|
return Directory::EntryType::Directory;
|
||||||
|
|
||||||
|
// Doesn't exit
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Directory> AndroidAssetFileSystem::OpenDirectoryImpl(const std::string &path, Directory::ListMode listMode) {
|
||||||
|
throw exception("AndroidAssetFileSystem directories are unimplemented");
|
||||||
|
}
|
||||||
|
}
|
28
app/src/main/cpp/skyline/vfs/android_asset_filesystem.h
Normal file
28
app/src/main/cpp/skyline/vfs/android_asset_filesystem.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
// Copyright © 2021 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "filesystem.h"
|
||||||
|
|
||||||
|
struct AAssetManager;
|
||||||
|
|
||||||
|
namespace skyline::vfs {
|
||||||
|
/**
|
||||||
|
* @brief The AndroidAssetFileSystem class provides the filesystem backing abstractions for the AAsset Android API
|
||||||
|
*/
|
||||||
|
class AndroidAssetFileSystem : public FileSystem {
|
||||||
|
private:
|
||||||
|
AAssetManager *backing; //!< The backing manager of the filesystem
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::shared_ptr<Backing> OpenFileImpl(const std::string &path, Backing::Mode mode) override;
|
||||||
|
|
||||||
|
std::optional<Directory::EntryType> GetEntryTypeImpl(const std::string &path) override;
|
||||||
|
|
||||||
|
std::shared_ptr<Directory> OpenDirectoryImpl(const std::string &path, Directory::ListMode listMode) override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
AndroidAssetFileSystem(AAssetManager *backing);
|
||||||
|
};
|
||||||
|
}
|
@ -8,6 +8,7 @@ package emu.skyline
|
|||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.content.res.AssetManager
|
||||||
import android.graphics.PointF
|
import android.graphics.PointF
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.*
|
import android.os.*
|
||||||
@ -64,8 +65,9 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
|
|||||||
* @param romFd The file descriptor of the ROM object
|
* @param romFd The file descriptor of the ROM object
|
||||||
* @param preferenceFd The file descriptor of the Preference XML
|
* @param preferenceFd The file descriptor of the Preference XML
|
||||||
* @param appFilesPath The full path to the app files directory
|
* @param appFilesPath The full path to the app files directory
|
||||||
|
* @param assetManager The asset manager used for accessing app assets
|
||||||
*/
|
*/
|
||||||
private external fun executeApplication(romUri : String, romType : Int, romFd : Int, preferenceFd : Int, appFilesPath : String)
|
private external fun executeApplication(romUri : String, romType : Int, romFd : Int, preferenceFd : Int, appFilesPath : String, assetManager : AssetManager)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return If it successfully caused the [emulationThread] to gracefully stop
|
* @return If it successfully caused the [emulationThread] to gracefully stop
|
||||||
@ -167,7 +169,7 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
|
|||||||
val preferenceFd = ParcelFileDescriptor.open(File("${applicationInfo.dataDir}/shared_prefs/${applicationInfo.packageName}_preferences.xml"), ParcelFileDescriptor.MODE_READ_WRITE)
|
val preferenceFd = ParcelFileDescriptor.open(File("${applicationInfo.dataDir}/shared_prefs/${applicationInfo.packageName}_preferences.xml"), ParcelFileDescriptor.MODE_READ_WRITE)
|
||||||
|
|
||||||
emulationThread = Thread {
|
emulationThread = Thread {
|
||||||
executeApplication(rom.toString(), romType, romFd.detachFd(), preferenceFd.detachFd(), applicationContext.filesDir.canonicalPath + "/")
|
executeApplication(rom.toString(), romType, romFd.detachFd(), preferenceFd.detachFd(), applicationContext.filesDir.canonicalPath + "/", assets)
|
||||||
if (shouldFinish)
|
if (shouldFinish)
|
||||||
runOnUiThread {
|
runOnUiThread {
|
||||||
emulationThread.join()
|
emulationThread.join()
|
||||||
|
Loading…
Reference in New Issue
Block a user