mirror of
https://github.com/Vita3K/Vita3K.git
synced 2026-07-11 01:34:23 +02:00
207 lines
7.7 KiB
C++
207 lines
7.7 KiB
C++
// Vita3K emulator project
|
|
// Copyright (C) 2026 Vita3K team
|
|
//
|
|
// This program is free software; you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation; either version 2 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License along
|
|
// with this program; if not, write to the Free Software Foundation, Inc.,
|
|
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
|
#include "android_state.h"
|
|
|
|
#include <app/functions.h>
|
|
#include <compat/functions.h>
|
|
#include <config/settings.h>
|
|
#include <io/state.h>
|
|
#include <util/log.h>
|
|
|
|
extern "C" {
|
|
|
|
JNIEXPORT jobjectArray JNICALL
|
|
Java_org_vita3k_emulator_NativeLib_getAppListDetailed(JNIEnv *env, jclass) {
|
|
jclass app_info_class = env->FindClass("org/vita3k/emulator/data/NativeAppInfo");
|
|
if (!app_info_class)
|
|
return nullptr;
|
|
|
|
jmethodID ctor = env->GetMethodID(app_info_class, "<init>", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZIJJ)V");
|
|
if (!ctor)
|
|
return env->NewObjectArray(0, app_info_class, nullptr);
|
|
|
|
auto *emuenv = get_emuenv();
|
|
if (!emuenv)
|
|
return env->NewObjectArray(0, app_info_class, nullptr);
|
|
|
|
const auto apps = app::get_apps(*emuenv);
|
|
const auto app_times = app::get_user_app_times(*emuenv);
|
|
jobjectArray result = env->NewObjectArray(static_cast<jsize>(apps.size()), app_info_class, nullptr);
|
|
|
|
for (jsize i = 0; i < static_cast<jsize>(apps.size()); ++i) {
|
|
const auto &app = apps[static_cast<size_t>(i)];
|
|
const int compat_state = static_cast<int>(compat::get_app_compat(emuenv->compat, app.title_id));
|
|
const bool has_custom_config = config::has_custom_config(emuenv->config_path, app.path);
|
|
|
|
int64_t last_played = 0;
|
|
int64_t playtime = 0;
|
|
const auto time_it = app_times.find(app.path);
|
|
if (time_it != app_times.end()) {
|
|
last_played = static_cast<int64_t>(time_it->second.last_time_used);
|
|
playtime = time_it->second.time_used;
|
|
}
|
|
|
|
const fs::path icon_path = app.icon_path;
|
|
const std::string icon_full = app.icon_path.empty()
|
|
? std::string()
|
|
: (icon_path.is_absolute() ? icon_path.generic_string() : (emuenv->vita_fs_path / icon_path).generic_string());
|
|
|
|
jstring title_id = env->NewStringUTF(app.title_id.c_str());
|
|
jstring title = env->NewStringUTF(app.title.c_str());
|
|
jstring category = env->NewStringUTF(app.category.c_str());
|
|
jstring app_ver = env->NewStringUTF(app.app_ver.c_str());
|
|
jstring icon_path_str = env->NewStringUTF(icon_full.c_str());
|
|
|
|
jobject app_info = env->NewObject(app_info_class, ctor,
|
|
title_id,
|
|
title,
|
|
category,
|
|
app_ver,
|
|
icon_path_str,
|
|
static_cast<jboolean>(has_custom_config),
|
|
static_cast<jint>(compat_state),
|
|
static_cast<jlong>(last_played),
|
|
static_cast<jlong>(playtime));
|
|
|
|
env->SetObjectArrayElement(result, i, app_info);
|
|
env->DeleteLocalRef(app_info);
|
|
env->DeleteLocalRef(title_id);
|
|
env->DeleteLocalRef(title);
|
|
env->DeleteLocalRef(category);
|
|
env->DeleteLocalRef(app_ver);
|
|
env->DeleteLocalRef(icon_path_str);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
JNIEXPORT jboolean JNICALL
|
|
Java_org_vita3k_emulator_NativeLib_performAppAction(JNIEnv *env, jclass, jstring title_id_str, jint action_bit) {
|
|
auto *emuenv = get_emuenv();
|
|
auto *controller = get_app_session_controller();
|
|
if (!emuenv)
|
|
return JNI_FALSE;
|
|
|
|
const std::string title_id = jstring_to_string(env, title_id_str);
|
|
|
|
switch (static_cast<uint32_t>(action_bit)) {
|
|
case ACTION_DELETE_APPLICATION: {
|
|
if (controller && controller->has_active_session())
|
|
return JNI_FALSE;
|
|
const auto app = find_app_by_title_id(title_id);
|
|
if (!app.has_value())
|
|
return JNI_FALSE;
|
|
app::delete_app(*emuenv, app->path);
|
|
return JNI_TRUE;
|
|
}
|
|
case ACTION_DELETE_SAVE_DATA: {
|
|
const auto app = find_app_by_title_id(title_id);
|
|
if (!app.has_value())
|
|
return JNI_FALSE;
|
|
return remove_path_if_exists(emuenv->vita_fs_path / "ux0/user" / emuenv->io.user_id / "savedata" / app->savedata)
|
|
? JNI_TRUE
|
|
: JNI_FALSE;
|
|
}
|
|
case ACTION_DELETE_PATCH: {
|
|
bool removed = false;
|
|
removed |= remove_path_if_exists(emuenv->vita_fs_path / "ux0/patch" / title_id);
|
|
removed |= remove_path_if_exists(emuenv->shared_path / "patch" / title_id);
|
|
return removed ? JNI_TRUE : JNI_FALSE;
|
|
}
|
|
case ACTION_DELETE_DLC: {
|
|
const auto app = find_app_by_title_id(title_id);
|
|
if (!app.has_value())
|
|
return JNI_FALSE;
|
|
return remove_path_if_exists(emuenv->vita_fs_path / "ux0/addcont" / app->addcont)
|
|
? JNI_TRUE
|
|
: JNI_FALSE;
|
|
}
|
|
case ACTION_DELETE_LICENSE:
|
|
return remove_path_if_exists(emuenv->vita_fs_path / "ux0/license" / title_id)
|
|
? JNI_TRUE
|
|
: JNI_FALSE;
|
|
case ACTION_DELETE_SHADER_CACHE:
|
|
return remove_path_if_exists(emuenv->cache_path / "shaders" / title_id)
|
|
? JNI_TRUE
|
|
: JNI_FALSE;
|
|
case ACTION_DELETE_SHADER_LOG: {
|
|
bool removed = false;
|
|
removed |= remove_path_if_exists(emuenv->cache_path / "shaderlog" / title_id);
|
|
removed |= remove_path_if_exists(emuenv->log_path / "shaderlog" / title_id);
|
|
return removed ? JNI_TRUE : JNI_FALSE;
|
|
}
|
|
case ACTION_DELETE_EXPORT_TEXTURES:
|
|
return remove_path_if_exists(emuenv->shared_path / "textures/export" / title_id)
|
|
? JNI_TRUE
|
|
: JNI_FALSE;
|
|
case ACTION_DELETE_IMPORT_TEXTURES:
|
|
return remove_path_if_exists(emuenv->shared_path / "textures/import" / title_id)
|
|
? JNI_TRUE
|
|
: JNI_FALSE;
|
|
case ACTION_RESET_LAST_PLAYED: {
|
|
const auto app = find_app_by_title_id(title_id);
|
|
if (!app.has_value())
|
|
return JNI_FALSE;
|
|
app::reset_last_time_app_used(*emuenv, app->path);
|
|
return JNI_TRUE;
|
|
}
|
|
default:
|
|
return JNI_FALSE;
|
|
}
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL
|
|
Java_org_vita3k_emulator_NativeLib_getAppActionAvailabilityMask(JNIEnv *env, jclass, jstring title_id_str) {
|
|
auto *emuenv = get_emuenv();
|
|
if (!emuenv)
|
|
return static_cast<jint>(0);
|
|
|
|
const std::string title_id = jstring_to_string(env, title_id_str);
|
|
return static_cast<jint>(get_app_action_availability_mask(title_id));
|
|
}
|
|
|
|
JNIEXPORT jlong JNICALL
|
|
Java_org_vita3k_emulator_NativeLib_getAppInstallSize(JNIEnv *env, jclass, jstring title_id_str) {
|
|
auto *emuenv = get_emuenv();
|
|
if (!emuenv)
|
|
return 0L;
|
|
|
|
const std::string title_id = jstring_to_string(env, title_id_str);
|
|
const auto app = find_app_by_title_id(title_id);
|
|
if (!app.has_value())
|
|
return 0L;
|
|
|
|
const auto app_path = emuenv->vita_fs_path / "ux0/app" / app->path;
|
|
if (!fs::exists(app_path))
|
|
return 0L;
|
|
|
|
try {
|
|
uintmax_t size = 0;
|
|
for (const auto &entry : fs::recursive_directory_iterator(app_path, fs::directory_options::skip_permission_denied)) {
|
|
if (entry.is_regular_file())
|
|
size += fs::file_size(entry.path());
|
|
}
|
|
return static_cast<jlong>(size);
|
|
} catch (const std::exception &error) {
|
|
LOG_WARN("Failed to compute install size for {}: {}", title_id, error.what());
|
|
return 0L;
|
|
}
|
|
}
|
|
|
|
} // extern "C"
|