diff --git a/src/android/app/src/main/cpp/AndroidFilesystemCallbacks.h b/src/android/app/src/main/cpp/AndroidFilesystemCallbacks.h index f28413fb..468c2f09 100644 --- a/src/android/app/src/main/cpp/AndroidFilesystemCallbacks.h +++ b/src/android/app/src/main/cpp/AndroidFilesystemCallbacks.h @@ -27,7 +27,7 @@ class AndroidFilesystemCallbacks : public FilesystemAndroid::FilesystemCallbacks AndroidFilesystemCallbacks() { JNIUtils::ScopedJNIENV env; - m_fileUtilClass = JNIUtils::Scopedjclass("info/cemu/Cemu/utils/FileUtil"); + m_fileUtilClass = JNIUtils::Scopedjclass("info/cemu/Cemu/nativeinterface/FileCallbacks"); m_openContentUriMid = env->GetStaticMethodID(*m_fileUtilClass, "openContentUri", "(Ljava/lang/String;)I"); m_listFilesMid = env->GetStaticMethodID(*m_fileUtilClass, "listFiles", "(Ljava/lang/String;)[Ljava/lang/String;"); m_isDirectoryMid = env->GetStaticMethodID(*m_fileUtilClass, "isDirectory", "(Ljava/lang/String;)Z"); diff --git a/src/android/app/src/main/cpp/CMakeLists.txt b/src/android/app/src/main/cpp/CMakeLists.txt index 916bf599..890fe7b0 100644 --- a/src/android/app/src/main/cpp/CMakeLists.txt +++ b/src/android/app/src/main/cpp/CMakeLists.txt @@ -1,24 +1,16 @@ add_library(CemuAndroid SHARED AndroidAudio.cpp - AndroidAudio.h AndroidEmulatedController.cpp - AndroidEmulatedController.h - AndroidFilesystemCallbacks.h - AndroidGameTitleLoadedCallback.h CMakeLists.txt - CafeSystemUtils.cpp - CafeSystemUtils.h - EmulationState.h GameTitleLoader.cpp - GameTitleLoader.h Image.cpp - Image.h JNIUtils.cpp - JNIUtils.h - Utils.cpp - Utils.h - native-lib.cpp - stb_image.h + NativeEmulation.cpp + NativeGameTitles.cpp + NativeGraphicPacks.cpp + NativeInput.cpp + NativeLib.cpp + NativeSettings.cpp ) target_link_libraries(CemuAndroid PRIVATE diff --git a/src/android/app/src/main/cpp/CafeSystemUtils.cpp b/src/android/app/src/main/cpp/CafeSystemUtils.cpp deleted file mode 100644 index 4c4b55c7..00000000 --- a/src/android/app/src/main/cpp/CafeSystemUtils.cpp +++ /dev/null @@ -1,55 +0,0 @@ -#include "CafeSystemUtils.h" - -#include "Cafe/CafeSystem.h" -#include "Cafe/TitleList/TitleList.h" - -namespace CafeSystemUtils -{ - void startGame(const fs::path& launchPath) - { - TitleInfo launchTitle{launchPath}; - if (launchTitle.IsValid()) - { - // the title might not be in the TitleList, so we add it as a temporary entry - CafeTitleList::AddTitleFromPath(launchPath); - // title is valid, launch from TitleId - TitleId baseTitleId; - if (!CafeTitleList::FindBaseTitleId(launchTitle.GetAppTitleId(), baseTitleId)) - { - throw GameBaseFilesNotFoundException(); - } - CafeSystem::STATUS_CODE r = CafeSystem::PrepareForegroundTitle(baseTitleId); - if (r != CafeSystem::STATUS_CODE::SUCCESS) - { - throw UnknownGameFilesException(); - } - } - else // if (launchTitle.GetFormat() == TitleInfo::TitleDataFormat::INVALID_STRUCTURE ) - { - // title is invalid, if it's an RPX/ELF we can launch it directly - // otherwise it's an error - CafeTitleFileType fileType = DetermineCafeSystemFileType(launchPath); - if (fileType == CafeTitleFileType::RPX || fileType == CafeTitleFileType::ELF) - { - CafeSystem::STATUS_CODE r = CafeSystem::PrepareForegroundTitleFromStandaloneRPX(launchPath); - if (r != CafeSystem::STATUS_CODE::SUCCESS) - { - throw UnknownGameFilesException(); - } - } - else if (launchTitle.GetInvalidReason() == TitleInfo::InvalidReason::NO_DISC_KEY) - { - throw NoDiscKeyException(); - } - else if (launchTitle.GetInvalidReason() == TitleInfo::InvalidReason::NO_TITLE_TIK) - { - throw NoTitleTikException(); - } - else - { - throw UnknownGameFilesException(); - } - } - CafeSystem::LaunchForegroundTitle(); - } -}; // namespace CafeSystemUtils \ No newline at end of file diff --git a/src/android/app/src/main/cpp/CafeSystemUtils.h b/src/android/app/src/main/cpp/CafeSystemUtils.h deleted file mode 100644 index 8cdaed43..00000000 --- a/src/android/app/src/main/cpp/CafeSystemUtils.h +++ /dev/null @@ -1,51 +0,0 @@ -#pragma once - -#include "Cafe/TitleList/TitleId.h" - -namespace CafeSystemUtils -{ - class GameFilesException : public std::exception - { - public: - explicit GameFilesException(const std::string& message) - : m_message(message) {} - - const char* what() const noexcept override - { - return m_message.c_str(); - } - - private: - std::string m_message; - }; - - class GameBaseFilesNotFoundException : public GameFilesException - { - public: - GameBaseFilesNotFoundException() - : GameFilesException("Game base files not found.") {} - }; - - class NoDiscKeyException : public GameFilesException - { - public: - NoDiscKeyException() - : GameFilesException("No disc key found.") {} - }; - - class NoTitleTikException : public GameFilesException - { - public: - NoTitleTikException() - : GameFilesException("No title ticket found.") {} - }; - - class UnknownGameFilesException : public GameFilesException - { - public: - UnknownGameFilesException() - : GameFilesException("Unknown error occurred during game launch.") {} - }; - - void startGame(const fs::path& launchPath); -}; // namespace CafeSystemUtils \ No newline at end of file diff --git a/src/android/app/src/main/cpp/EmulationState.h b/src/android/app/src/main/cpp/EmulationState.h deleted file mode 100644 index 91815538..00000000 --- a/src/android/app/src/main/cpp/EmulationState.h +++ /dev/null @@ -1,360 +0,0 @@ -#pragma once - -#include - -#include "AndroidAudio.h" -#include "AndroidEmulatedController.h" -#include "AndroidFilesystemCallbacks.h" -#include "Cafe/HW/Latte/Core/LatteOverlay.h" -#include "Cafe/HW/Latte/Renderer/Vulkan/VulkanAPI.h" -#include "Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h" -#include "CafeSystemUtils.h" -#include "Cafe/CafeSystem.h" -#include "Cemu/GuiSystem/GuiSystem.h" -#include "GameTitleLoader.h" -#include "Utils.h" -#include "input/ControllerFactory.h" -#include "input/InputManager.h" -#include "input/api/Android/AndroidController.h" -#include "input/api/Android/AndroidControllerProvider.h" - -void CemuCommonInit(); - -class EmulationState -{ - GameTitleLoader m_gameTitleLoader; - std::unordered_map m_graphicPacks; - void fillGraphicPacks() - { - m_graphicPacks.clear(); - auto graphicPacks = GraphicPack2::GetGraphicPacks(); - for (auto&& graphicPack : graphicPacks) - { - m_graphicPacks[reinterpret_cast(graphicPack.get())] = graphicPack; - } - } - void onTouchEvent(sint32 x, sint32 y, bool isTV, std::optional status = {}) - { - auto& instance = InputManager::instance(); - auto& touchInfo = isTV ? instance.m_main_mouse : instance.m_pad_mouse; - std::scoped_lock lock(touchInfo.m_mutex); - touchInfo.position = {x, y}; - if (status.has_value()) - touchInfo.left_down = touchInfo.left_down_toggle = status.value(); - } - WiiUMotionHandler m_wiiUMotionHandler{}; - long m_lastMotionTimestamp; - - public: - void initializeEmulation() - { - g_config.SetFilename(ActiveSettings::GetConfigPath("settings.xml").generic_wstring()); - g_config.Load(); - FilesystemAndroid::setFilesystemCallbacks(std::make_shared()); - NetworkConfig::LoadOnce(); - InputManager::instance().load(); - auto& instance = InputManager::instance(); - InitializeGlobalVulkan(); - createCemuDirectories(); - LatteOverlay_init(); - CemuCommonInit(); - fillGraphicPacks(); - } - - void initializeActiveSettings(const fs::path& dataPath, const fs::path& cachePath) - { - std::set failedWriteAccess; - ActiveSettings::SetPaths(false, {}, dataPath, dataPath, cachePath, dataPath, failedWriteAccess); - } - - void clearSurface(bool isMainCanvas) - { - if (!isMainCanvas) - { - auto renderer = static_cast(g_renderer.get()); - if (renderer) - renderer->StopUsingPadAndWait(); - } - } - - void notifySurfaceChanged(bool isMainCanvas) - { - } - - void setSurface(JNIEnv* env, jobject surface, bool isMainCanvas) - { - cemu_assert_debug(surface != nullptr); - auto& windowHandleInfo = isMainCanvas ? GuiSystem::getWindowInfo().canvas_main : GuiSystem::getWindowInfo().canvas_pad; - if (windowHandleInfo.surface) - { - ANativeWindow_release(static_cast(windowHandleInfo.surface)); - windowHandleInfo.surface = nullptr; - } - windowHandleInfo.surface = ANativeWindow_fromSurface(env, surface); - int width, height; - if (isMainCanvas) - GuiSystem::getWindowPhysSize(width, height); - else - GuiSystem::getPadWindowPhysSize(width, height); - VulkanRenderer::GetInstance()->InitializeSurface({width, height}, isMainCanvas); - } - - void setSurfaceSize(int width, int height, bool isMainCanvas) - { - auto& windowInfo = GuiSystem::getWindowInfo(); - if (isMainCanvas) - { - windowInfo.width = windowInfo.phys_width = width; - windowInfo.height = windowInfo.phys_height = height; - } - else - { - windowInfo.pad_width = windowInfo.phys_pad_width = width; - windowInfo.pad_height = windowInfo.phys_pad_height = height; - } - } - - void onKeyEvent(const std::string& deviceDescriptor, const std::string& deviceName, int keyCode, bool isPressed) - { - auto apiProvider = InputManager::instance().get_api_provider(InputAPI::Android); - auto androidControllerProvider = dynamic_cast(apiProvider.get()); - androidControllerProvider->on_key_event(deviceDescriptor, deviceName, keyCode, isPressed); - } - - void onAxisEvent(const std::string& deviceDescriptor, const std::string& deviceName, int axisCode, float value) - { - auto apiProvider = InputManager::instance().get_api_provider(InputAPI::Android); - auto androidControllerProvider = dynamic_cast(apiProvider.get()); - androidControllerProvider->on_axis_event(deviceDescriptor, deviceName, axisCode, value); - } - - std::optional getEmulatedControllerMapping(size_t index, uint64 mappingId) - { - return AndroidEmulatedController::getAndroidEmulatedController(index).getMapping(mappingId); - } - - AndroidEmulatedController& getEmulatedController(size_t index) - { - return AndroidEmulatedController::getAndroidEmulatedController(index); - } - - int getVPADControllersCount() - { - int vpadCount = 0; - for (int i = 0; i < InputManager::kMaxController; i++) - { - auto emulatedController = AndroidEmulatedController::getAndroidEmulatedController(i).getEmulatedController(); - if (!emulatedController) - continue; - if (emulatedController->type() == EmulatedController::Type::VPAD) - ++vpadCount; - } - return vpadCount; - } - - int getWPADControllersCount() - { - int wpadCount = 0; - for (int i = 0; i < InputManager::kMaxController; i++) - { - auto emulatedController = AndroidEmulatedController::getAndroidEmulatedController( - i) - .getEmulatedController(); - if (!emulatedController) - continue; - if (emulatedController->type() != EmulatedController::Type::VPAD) - ++wpadCount; - } - return wpadCount; - } - - EmulatedController::Type getEmulatedControllerType(size_t index) - { - auto emulatedController = AndroidEmulatedController::getAndroidEmulatedController(index).getEmulatedController(); - if (emulatedController) - return emulatedController->type(); - throw std::runtime_error(fmt::format("can't get type for emulated controller {}", index)); - } - - void clearEmulatedControllerMapping(size_t index, uint64 mapping) - { - AndroidEmulatedController::getAndroidEmulatedController(index).clearMapping(mapping); - } - - void setEmulatedControllerType(size_t index, EmulatedController::Type type) - { - auto& androidEmulatedController = AndroidEmulatedController::getAndroidEmulatedController(index); - if (EmulatedController::Type::VPAD <= type && type < EmulatedController::Type::MAX) - androidEmulatedController.setType(type); - else - androidEmulatedController.setDisabled(); - } - - void initializeRenderer(JNIEnv* env, jobject testSurface) - { - cemu_assert_debug(testSurface != nullptr); - // TODO: cleanup surface - GuiSystem::getWindowInfo().window_main.surface = ANativeWindow_fromSurface(env, testSurface); - g_renderer = std::make_unique(); - } - void setReplaceTVWithPadView(bool showDRC) - { - // Emulate pressing the TAB key for showing DRC instead of TV - GuiSystem::getWindowInfo().set_keystate(GuiSystem::PlatformKeyCodes::TAB, showDRC); - } - void setDPI(float dpi) - { - auto& windowInfo = GuiSystem::getWindowInfo(); - windowInfo.dpi_scale = windowInfo.pad_dpi_scale = dpi; - } - - bool isEmulatedControllerDisabled(size_t index) - { - return AndroidEmulatedController::getAndroidEmulatedController(index).getEmulatedController() == nullptr; - } - - std::map getEmulatedControllerMappings(size_t index) - { - return AndroidEmulatedController::getAndroidEmulatedController(index).getMappings(); - } - - void setControllerMapping(const std::string& deviceDescriptor, const std::string& deviceName, size_t index, uint64 mappingId, uint64 buttonId) - { - auto apiProvider = InputManager::instance().get_api_provider(InputAPI::Android); - auto controller = ControllerFactory::CreateController(InputAPI::Android, deviceDescriptor, deviceName); - AndroidEmulatedController::getAndroidEmulatedController(index).setMapping(mappingId, controller, buttonId); - } - void initializeAudioDevices() - { - auto& config = g_config.data(); - if (!config.tv_device.empty()) - AndroidAudio::createAudioDevice(IAudioAPI::AudioAPI::Cubeb, config.tv_channels, config.tv_volume, true); - - if (!config.pad_device.empty()) - AndroidAudio::createAudioDevice(IAudioAPI::AudioAPI::Cubeb, config.pad_channels, config.pad_volume, false); - } - - void setOnGameTitleLoaded(const std::shared_ptr& onGameTitleLoaded) - { - m_gameTitleLoader.setOnTitleLoaded(onGameTitleLoaded); - } - - void addGamesPath(const std::string& gamePath) - { - auto& gamePaths = g_config.data().game_paths; - if (std::any_of(gamePaths.begin(), gamePaths.end(), [&](auto path) { return path == gamePath; })) - return; - gamePaths.push_back(gamePath); - g_config.Save(); - CafeTitleList::ClearScanPaths(); - for (auto& it : gamePaths) - CafeTitleList::AddScanPath(it); - CafeTitleList::Refresh(); - } - - void removeGamesPath(const std::string& gamePath) - { - auto& gamePaths = g_config.data().game_paths; - std::erase_if(gamePaths, [&](auto path) { return path == gamePath; }); - g_config.Save(); - CafeTitleList::ClearScanPaths(); - for (auto& it : gamePaths) - CafeTitleList::AddScanPath(it); - CafeTitleList::Refresh(); - } - - void reloadGameTitles() - { - m_gameTitleLoader.reloadGameTitles(); - } - - void startGame(const fs::path& gamePath) - { - GuiSystem::getWindowInfo().set_keystates_up(); - initializeAudioDevices(); - CafeSystemUtils::startGame(gamePath); - } - - void refreshGraphicPacks() - { - if (!CafeSystem::IsTitleRunning()) - { - GraphicPack2::ClearGraphicPacks(); - GraphicPack2::LoadAll(); - fillGraphicPacks(); - } - } - - const std::unordered_map& getGraphicPacks() const - { - return m_graphicPacks; - } - - void setEnabledStateForGraphicPack(int64_t id, bool state) - { - auto graphicPack = m_graphicPacks.at(id); - graphicPack->SetEnabled(state); - saveGraphicPackStateToConfig(graphicPack); - } - - GraphicPackPtr getGraphicPack(int64_t id) const - { - return m_graphicPacks.at(id); - } - void setGraphicPackActivePreset(int64_t id, const std::string& presetCategory, const std::string& preset) const - { - auto graphicPack = m_graphicPacks.at(id); - graphicPack->SetActivePreset(presetCategory, preset); - saveGraphicPackStateToConfig(graphicPack); - } - void saveGraphicPackStateToConfig(GraphicPackPtr graphicPack) const - { - auto& data = g_config.data(); - auto filename = _utf8ToPath(graphicPack->GetNormalizedPathString()); - if (data.graphic_pack_entries.contains(filename)) - data.graphic_pack_entries.erase(filename); - if (graphicPack->IsEnabled()) - { - data.graphic_pack_entries.try_emplace(filename); - auto& it = data.graphic_pack_entries[filename]; - // otherwise store all selected presets - for (const auto& preset : graphicPack->GetActivePresets()) - it.try_emplace(preset->category, preset->name); - } - else if (graphicPack->IsDefaultEnabled()) - { - // save that its disabled - data.graphic_pack_entries.try_emplace(filename); - auto& it = data.graphic_pack_entries[filename]; - it.try_emplace("_disabled", "false"); - } - g_config.Save(); - } - void onTouchMove(sint32 x, sint32 y, bool isTV) - { - onTouchEvent(x, y, isTV); - } - void onTouchUp(sint32 x, sint32 y, bool isTV) - { - onTouchEvent(x, y, isTV, false); - } - void onTouchDown(sint32 x, sint32 y, bool isTV) - { - onTouchEvent(x, y, isTV, true); - } - void onMotion(long timestamp, float gyroX, float gyroY, float gyroZ, float accelX, float accelY, float accelZ) - { - float deltaTime = (timestamp - m_lastMotionTimestamp) * 1e-9f; - m_wiiUMotionHandler.processMotionSample(deltaTime, gyroX, gyroY, gyroZ, accelX * 0.098066f, -accelY * 0.098066f, -accelZ * 0.098066f); - m_lastMotionTimestamp = timestamp; - auto& deviceMotion = InputManager::instance().m_device_motion; - std::scoped_lock lock{deviceMotion.m_mutex}; - deviceMotion.m_motion_sample = m_wiiUMotionHandler.getMotionSample(); - } - void setMotionEnabled(bool enabled) - { - auto& deviceMotion = InputManager::instance().m_device_motion; - std::scoped_lock lock{deviceMotion.m_mutex}; - deviceMotion.m_device_motion_enabled = enabled; - } -}; \ No newline at end of file diff --git a/src/android/app/src/main/cpp/NativeEmulation.cpp b/src/android/app/src/main/cpp/NativeEmulation.cpp new file mode 100644 index 00000000..be04690c --- /dev/null +++ b/src/android/app/src/main/cpp/NativeEmulation.cpp @@ -0,0 +1,261 @@ +#include "JNIUtils.h" +#include "AndroidAudio.h" +#include "AndroidEmulatedController.h" +#include "AndroidFilesystemCallbacks.h" +#include "Cafe/HW/Latte/Core/LatteOverlay.h" +#include "Cafe/HW/Latte/Renderer/Vulkan/VulkanAPI.h" +#include "Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h" +#include "Cafe/CafeSystem.h" +#include "Cemu/GuiSystem/GuiSystem.h" +#include "GameTitleLoader.h" +#include "input/ControllerFactory.h" +#include "input/InputManager.h" +#include "input/api/Android/AndroidController.h" +#include "input/api/Android/AndroidControllerProvider.h" +#include "config/ActiveSettings.h" +#include "Cemu/ncrypto/ncrypto.h" + +// forward declaration from main.cpp +void CemuCommonInit(); + +namespace NativeEmulation +{ + void initializeAudioDevices() + { + auto& config = g_config.data(); + if (!config.tv_device.empty()) + AndroidAudio::createAudioDevice(IAudioAPI::AudioAPI::Cubeb, config.tv_channels, config.tv_volume, true); + + if (!config.pad_device.empty()) + AndroidAudio::createAudioDevice(IAudioAPI::AudioAPI::Cubeb, config.pad_channels, config.pad_volume, false); + } + + void createCemuDirectories() + { + std::wstring mlc = ActiveSettings::GetMlcPath().generic_wstring(); + + // create sys/usr folder in mlc01 + const auto sysFolder = fs::path(mlc).append(L"sys"); + fs::create_directories(sysFolder); + + const auto usrFolder = fs::path(mlc).append(L"usr"); + fs::create_directories(usrFolder); + fs::create_directories(fs::path(usrFolder).append("title/00050000")); // base + fs::create_directories(fs::path(usrFolder).append("title/0005000c")); // dlc + fs::create_directories(fs::path(usrFolder).append("title/0005000e")); // update + + // Mii Maker save folders {0x500101004A000, 0x500101004A100, 0x500101004A200}, + fs::create_directories(fs::path(mlc).append(L"usr/save/00050010/1004a000/user/common/db")); + fs::create_directories(fs::path(mlc).append(L"usr/save/00050010/1004a100/user/common/db")); + fs::create_directories(fs::path(mlc).append(L"usr/save/00050010/1004a200/user/common/db")); + + // lang files + auto langDir = fs::path(mlc).append(L"sys/title/0005001b/1005c000/content"); + fs::create_directories(langDir); + + auto langFile = fs::path(langDir).append("language.txt"); + if (!fs::exists(langFile)) + { + std::ofstream file(langFile); + if (file.is_open()) + { + const char* langStrings[] = {"ja", "en", "fr", "de", "it", "es", "zh", "ko", "nl", "pt", "ru", "zh"}; + for (const char* lang : langStrings) + file << fmt::format(R"("{}",)", lang) << std::endl; + + file.flush(); + file.close(); + } + } + + auto countryFile = fs::path(langDir).append("country.txt"); + if (!fs::exists(countryFile)) + { + std::ofstream file(countryFile); + for (sint32 i = 0; i < 201; i++) + { + const char* countryCode = NCrypto::GetCountryAsString(i); + if (boost::iequals(countryCode, "NN")) + file << "NULL," << std::endl; + else + file << fmt::format(R"("{}",)", countryCode) << std::endl; + } + file.flush(); + file.close(); + } + + // cemu directories + const auto controllerProfileFolder = ActiveSettings::GetConfigPath(L"controllerProfiles").generic_wstring(); + if (!fs::exists(controllerProfileFolder)) + fs::create_directories(controllerProfileFolder); + + const auto memorySearcherFolder = ActiveSettings::GetUserDataPath(L"memorySearcher").generic_wstring(); + if (!fs::exists(memorySearcherFolder)) + fs::create_directories(memorySearcherFolder); + } + enum StartGameResult : sint32 + { + SUCCESSFUL = 0, + ERROR_GAME_BASE_FILES_NOT_FOUND = 1, + ERROR_NO_DISC_KEY = 2, + ERROR_NO_TITLE_TIK = 3, + ERROR_UNKNOWN = 4, + }; + StartGameResult startGame(const fs::path& launchPath) + { + TitleInfo launchTitle{launchPath}; + if (launchTitle.IsValid()) + { + // the title might not be in the TitleList, so we add it as a temporary entry + CafeTitleList::AddTitleFromPath(launchPath); + // title is valid, launch from TitleId + TitleId baseTitleId; + if (!CafeTitleList::FindBaseTitleId(launchTitle.GetAppTitleId(), baseTitleId)) + { + return ERROR_GAME_BASE_FILES_NOT_FOUND; + } + CafeSystem::STATUS_CODE r = CafeSystem::PrepareForegroundTitle(baseTitleId); + if (r != CafeSystem::STATUS_CODE::SUCCESS) + { + return ERROR_UNKNOWN; + } + } + else // if (launchTitle.GetFormat() == TitleInfo::TitleDataFormat::INVALID_STRUCTURE ) + { + // title is invalid, if it's an RPX/ELF we can launch it directly + // otherwise it's an error + CafeTitleFileType fileType = DetermineCafeSystemFileType(launchPath); + if (fileType == CafeTitleFileType::RPX || fileType == CafeTitleFileType::ELF) + { + CafeSystem::STATUS_CODE r = CafeSystem::PrepareForegroundTitleFromStandaloneRPX(launchPath); + if (r != CafeSystem::STATUS_CODE::SUCCESS) + { + return ERROR_UNKNOWN; + } + } + else if (launchTitle.GetInvalidReason() == TitleInfo::InvalidReason::NO_DISC_KEY) + { + return ERROR_NO_DISC_KEY; + } + else if (launchTitle.GetInvalidReason() == TitleInfo::InvalidReason::NO_TITLE_TIK) + { + return ERROR_NO_TITLE_TIK; + } + else + { + return ERROR_UNKNOWN; + } + } + CafeSystem::LaunchForegroundTitle(); + return SUCCESSFUL; + } +} // namespace NativeEmulation + +extern "C" JNIEXPORT void JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeEmulation_setReplaceTVWithPadView([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jboolean swapped) +{ + // Emulate pressing the TAB key for showing DRC instead of TV + GuiSystem::getWindowInfo().set_keystate(GuiSystem::PlatformKeyCodes::TAB, swapped); +} + +extern "C" [[maybe_unused]] JNIEXPORT void JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeEmulation_initializeActiveSettings(JNIEnv* env, [[maybe_unused]] jclass clazz, jstring data_path, jstring cache_path) +{ + std::string dataPath = JNIUtils::JStringToString(env, data_path); + std::string cachePath = JNIUtils::JStringToString(env, cache_path); + std::set failedWriteAccess; + ActiveSettings::SetPaths(false, {}, dataPath, dataPath, cachePath, dataPath, failedWriteAccess); +} + +extern "C" [[maybe_unused]] JNIEXPORT void JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeEmulation_initializeEmulation([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz) +{ + FilesystemAndroid::setFilesystemCallbacks(std::make_shared()); + g_config.SetFilename(ActiveSettings::GetConfigPath("settings.xml").generic_wstring()); + NativeEmulation::createCemuDirectories(); + NetworkConfig::LoadOnce(); + ActiveSettings::Init(); + LatteOverlay_init(); + CemuCommonInit(); + InitializeGlobalVulkan(); + // TODO: move this + // fillGraphicPacks(); +} +extern "C" [[maybe_unused]] JNIEXPORT void JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeEmulation_initializerRenderer(JNIEnv* env, [[maybe_unused]] jclass clazz, jobject testSurface) +{ + JNIUtils::handleNativeException(env, [&]() { + cemu_assert_debug(testSurface != nullptr); + // TODO: cleanup surface + GuiSystem::getWindowInfo().window_main.surface = ANativeWindow_fromSurface(env, testSurface); + g_renderer = std::make_unique(); + }); +} + +extern "C" [[maybe_unused]] JNIEXPORT void JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeEmulation_setDPI([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jfloat dpi) +{ + auto& windowInfo = GuiSystem::getWindowInfo(); + windowInfo.dpi_scale = windowInfo.pad_dpi_scale = dpi; +} + +extern "C" [[maybe_unused]] JNIEXPORT void JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeEmulation_clearSurface([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jboolean is_main_canvas) +{ + if (!is_main_canvas) + { + auto renderer = static_cast(g_renderer.get()); + if (renderer) + renderer->StopUsingPadAndWait(); + } +} +extern "C" [[maybe_unused]] JNIEXPORT void JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeEmulation_recreateRenderSurface([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jboolean is_main_canvas) +{ + // TODO +} + +extern "C" [[maybe_unused]] JNIEXPORT void JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeEmulation_setSurface(JNIEnv* env, [[maybe_unused]] jclass clazz, jobject surface, jboolean is_main_canvas) +{ + JNIUtils::handleNativeException(env, [&]() { + cemu_assert_debug(surface != nullptr); + auto& windowHandleInfo = is_main_canvas ? GuiSystem::getWindowInfo().canvas_main : GuiSystem::getWindowInfo().canvas_pad; + if (windowHandleInfo.surface) + { + ANativeWindow_release(static_cast(windowHandleInfo.surface)); + windowHandleInfo.surface = nullptr; + } + windowHandleInfo.surface = ANativeWindow_fromSurface(env, surface); + int width, height; + if (is_main_canvas) + GuiSystem::getWindowPhysSize(width, height); + else + GuiSystem::getPadWindowPhysSize(width, height); + VulkanRenderer::GetInstance()->InitializeSurface({width, height}, is_main_canvas); + }); +} + +extern "C" [[maybe_unused]] JNIEXPORT void JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeEmulation_setSurfaceSize([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jint width, jint height, jboolean is_main_canvas) +{ + auto& windowInfo = GuiSystem::getWindowInfo(); + if (is_main_canvas) + { + windowInfo.width = windowInfo.phys_width = width; + windowInfo.height = windowInfo.phys_height = height; + } + else + { + windowInfo.pad_width = windowInfo.phys_pad_width = width; + windowInfo.pad_height = windowInfo.phys_pad_height = height; + } +} + +extern "C" [[maybe_unused]] JNIEXPORT jint JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeEmulation_startGame([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jstring launchPath) +{ + GuiSystem::getWindowInfo().set_keystates_up(); + NativeEmulation::initializeAudioDevices(); + return NativeEmulation::startGame(JNIUtils::JStringToString(env, launchPath)); +} diff --git a/src/android/app/src/main/cpp/NativeGameTitles.cpp b/src/android/app/src/main/cpp/NativeGameTitles.cpp new file mode 100644 index 00000000..d4faba57 --- /dev/null +++ b/src/android/app/src/main/cpp/NativeGameTitles.cpp @@ -0,0 +1,34 @@ +#include "JNIUtils.h" +#include "GameTitleLoader.h" +#include "AndroidGameTitleLoadedCallback.h" + +namespace NativeGameTitles +{ + GameTitleLoader s_gameTitleLoader; +} + +extern "C" [[maybe_unused]] JNIEXPORT void JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeGameTitles_setGameTitleLoadedCallback(JNIEnv* env, [[maybe_unused]] jclass clazz, jobject game_title_loaded_callback) +{ + if (game_title_loaded_callback == nullptr) + { + NativeGameTitles::s_gameTitleLoader.setOnTitleLoaded(nullptr); + return; + } + jclass gameTitleLoadedCallbackClass = env->GetObjectClass(game_title_loaded_callback); + jmethodID onGameTitleLoadedMID = env->GetMethodID(gameTitleLoadedCallbackClass, "onGameTitleLoaded", "(Ljava/lang/String;Ljava/lang/String;[III)V"); + env->DeleteLocalRef(gameTitleLoadedCallbackClass); + NativeGameTitles::s_gameTitleLoader.setOnTitleLoaded(std::make_shared(onGameTitleLoadedMID, game_title_loaded_callback)); +} + +extern "C" [[maybe_unused]] JNIEXPORT void JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeGameTitles_reloadGameTitles([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz) +{ + NativeGameTitles::s_gameTitleLoader.reloadGameTitles(); +} + +extern "C" JNIEXPORT jobject JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeGameTitles_getInstalledGamesTitleIds(JNIEnv* env, [[maybe_unused]] jclass clazz) +{ + return JNIUtils::createJavaLongArrayList(env, CafeTitleList::GetAllTitleIds()); +} diff --git a/src/android/app/src/main/cpp/NativeGraphicPacks.cpp b/src/android/app/src/main/cpp/NativeGraphicPacks.cpp new file mode 100644 index 00000000..3e642beb --- /dev/null +++ b/src/android/app/src/main/cpp/NativeGraphicPacks.cpp @@ -0,0 +1,157 @@ +#include "Cafe/CafeSystem.h" +#include "config/CemuConfig.h" +#include "Cafe/GraphicPack/GraphicPack2.h" +#include "JNIUtils.h" + +namespace NativeGraphicPacks +{ + std::unordered_map s_graphicPacks; + + void fillGraphicPacks() + { + s_graphicPacks.clear(); + auto graphicPacks = GraphicPack2::GetGraphicPacks(); + for (auto&& graphicPack : graphicPacks) + { + s_graphicPacks[reinterpret_cast(graphicPack.get())] = graphicPack; + } + } + + void saveGraphicPackStateToConfig(GraphicPackPtr graphicPack) + { + auto& data = g_config.data(); + auto filename = _utf8ToPath(graphicPack->GetNormalizedPathString()); + if (data.graphic_pack_entries.contains(filename)) + data.graphic_pack_entries.erase(filename); + if (graphicPack->IsEnabled()) + { + data.graphic_pack_entries.try_emplace(filename); + auto& it = data.graphic_pack_entries[filename]; + // otherwise store all selected presets + for (const auto& preset : graphicPack->GetActivePresets()) + it.try_emplace(preset->category, preset->name); + } + else if (graphicPack->IsDefaultEnabled()) + { + // save that its disabled + data.graphic_pack_entries.try_emplace(filename); + auto& it = data.graphic_pack_entries[filename]; + it.try_emplace("_disabled", "false"); + } + g_config.Save(); + } + + jobject getGraphicPresets(JNIEnv* env, GraphicPackPtr graphicPack, sint64 id) + { + auto graphicPackPresetClass = env->FindClass("info/cemu/Cemu/nativeinterface/NativeGraphicPacks$GraphicPackPreset"); + auto graphicPackPresetCtorId = env->GetMethodID(graphicPackPresetClass, "", "(JLjava/lang/String;Ljava/util/ArrayList;Ljava/lang/String;)V"); + + std::vector order; + auto presets = graphicPack->GetCategorizedPresets(order); + + std::vector presetsJobjects; + for (const auto& category : order) + { + const auto& entry = presets[category]; + // test if any preset is visible and update its status + if (std::none_of(entry.cbegin(), entry.cend(), [graphicPack](const auto& p) { return p->visible; })) + { + continue; + } + + jstring categoryJStr = category.empty() ? nullptr : env->NewStringUTF(category.c_str()); + std::vector presetSelections; + std::optional activePreset; + for (auto& pentry : entry) + { + if (!pentry->visible) + continue; + + presetSelections.push_back(pentry->name); + + if (pentry->active) + activePreset = pentry->name; + } + + jstring activePresetJstr = nullptr; + if (activePreset) + activePresetJstr = env->NewStringUTF(activePreset->c_str()); + else if (!presetSelections.empty()) + activePresetJstr = env->NewStringUTF(presetSelections.front().c_str()); + auto presetJObject = env->NewObject(graphicPackPresetClass, graphicPackPresetCtorId, id, categoryJStr, JNIUtils::createJavaStringArrayList(env, presetSelections), activePresetJstr); + presetsJobjects.push_back(presetJObject); + } + return JNIUtils::createArrayList(env, presetsJobjects); + } +} // namespace NativeGraphicPacks + +extern "C" JNIEXPORT void JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeGraphicPacks_refreshGraphicPacks([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz) +{ + if (!CafeSystem::IsTitleRunning()) + { + GraphicPack2::ClearGraphicPacks(); + GraphicPack2::LoadAll(); + NativeGraphicPacks::fillGraphicPacks(); + } +} + +extern "C" JNIEXPORT jobject JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeGraphicPacks_getGraphicPackBasicInfos(JNIEnv* env, [[maybe_unused]] jclass clazz) +{ + auto graphicPackInfoClass = env->FindClass("info/cemu/Cemu/nativeinterface/NativeGraphicPacks$GraphicPackBasicInfo"); + auto graphicPackInfoCtorId = env->GetMethodID(graphicPackInfoClass, "", "(JLjava/lang/String;Ljava/util/ArrayList;)V"); + + std::vector graphicPackInfoJObjects; + for (auto&& graphicPack : NativeGraphicPacks::s_graphicPacks) + { + jstring virtualPath = env->NewStringUTF(graphicPack.second->GetVirtualPath().c_str()); + jlong id = graphicPack.first; + jobject titleIds = JNIUtils::createJavaLongArrayList(env, graphicPack.second->GetTitleIds()); + jobject jGraphicPack = env->NewObject(graphicPackInfoClass, graphicPackInfoCtorId, id, virtualPath, titleIds); + graphicPackInfoJObjects.push_back(jGraphicPack); + } + return JNIUtils::createArrayList(env, graphicPackInfoJObjects); +} + +extern "C" JNIEXPORT jobject JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeGraphicPacks_getGraphicPack(JNIEnv* env, [[maybe_unused]] jclass clazz, jlong id) +{ + auto graphicPackClass = env->FindClass("info/cemu/Cemu/nativeinterface/NativeGraphicPacks$GraphicPack"); + auto graphicPackCtorId = env->GetMethodID(graphicPackClass, "", "(JZLjava/lang/String;Ljava/lang/String;Ljava/util/ArrayList;)V"); + auto graphicPack = NativeGraphicPacks::s_graphicPacks.at(id); + + jstring graphicPackName = env->NewStringUTF(graphicPack->GetName().c_str()); + jstring graphicPackDescription = env->NewStringUTF(graphicPack->GetDescription().c_str()); + return env->NewObject( + graphicPackClass, + graphicPackCtorId, + id, + graphicPack->IsEnabled(), + graphicPackName, + graphicPackDescription, + NativeGraphicPacks::getGraphicPresets(env, graphicPack, id)); +} + +extern "C" JNIEXPORT void JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeGraphicPacks_setGraphicPackActive([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jlong id, jboolean active) +{ + auto graphicPack = NativeGraphicPacks::s_graphicPacks.at(id); + graphicPack->SetEnabled(active); + NativeGraphicPacks::saveGraphicPackStateToConfig(graphicPack); +} + +extern "C" JNIEXPORT void JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeGraphicPacks_setGraphicPackActivePreset([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jlong id, jstring category, jstring preset) +{ + std::string presetCategory = category == nullptr ? "" : JNIUtils::JStringToString(env, category); + auto graphicPack = NativeGraphicPacks::s_graphicPacks.at(id); + graphicPack->SetActivePreset(presetCategory, JNIUtils::JStringToString(env, preset)); + NativeGraphicPacks::saveGraphicPackStateToConfig(graphicPack); +} + +extern "C" JNIEXPORT jobject JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeGraphicPacks_getGraphicPackPresets(JNIEnv* env, [[maybe_unused]] jclass clazz, jlong id) +{ + return NativeGraphicPacks::getGraphicPresets(env, NativeGraphicPacks::s_graphicPacks.at(id), id); +} \ No newline at end of file diff --git a/src/android/app/src/main/cpp/NativeInput.cpp b/src/android/app/src/main/cpp/NativeInput.cpp new file mode 100644 index 00000000..20ea3c66 --- /dev/null +++ b/src/android/app/src/main/cpp/NativeInput.cpp @@ -0,0 +1,190 @@ +#include "JNIUtils.h" +#include "input/ControllerFactory.h" +#include "input/InputManager.h" +#include "input/api/Android/AndroidController.h" +#include "input/api/Android/AndroidControllerProvider.h" +#include "AndroidEmulatedController.h" + +namespace NativeInput +{ + WiiUMotionHandler s_wiiUMotionHandler{}; + long s_lastMotionTimestamp = 0; + + void onTouchEvent(sint32 x, sint32 y, bool isTV, std::optional status = {}) + { + auto& instance = InputManager::instance(); + auto& touchInfo = isTV ? instance.m_main_mouse : instance.m_pad_mouse; + std::scoped_lock lock(touchInfo.m_mutex); + touchInfo.position = {x, y}; + if (status.has_value()) + touchInfo.left_down = touchInfo.left_down_toggle = status.value(); + } +} // namespace NativeInput + +extern "C" [[maybe_unused]] JNIEXPORT void JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeInput_onNativeKey(JNIEnv* env, [[maybe_unused]] jclass clazz, jstring device_descriptor, jstring device_name, jint key, jboolean is_pressed) +{ + auto deviceDescriptor = JNIUtils::JStringToString(env, device_descriptor); + auto deviceName = JNIUtils::JStringToString(env, device_name); + auto apiProvider = InputManager::instance().get_api_provider(InputAPI::Android); + auto androidControllerProvider = dynamic_cast(apiProvider.get()); + androidControllerProvider->on_key_event(deviceDescriptor, deviceName, key, is_pressed); +} + +extern "C" [[maybe_unused]] JNIEXPORT void JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeInput_onNativeAxis(JNIEnv* env, [[maybe_unused]] jclass clazz, jstring device_descriptor, jstring device_name, jint axis, jfloat value) +{ + auto deviceDescriptor = JNIUtils::JStringToString(env, device_descriptor); + auto deviceName = JNIUtils::JStringToString(env, device_name); + auto apiProvider = InputManager::instance().get_api_provider(InputAPI::Android); + auto androidControllerProvider = dynamic_cast(apiProvider.get()); + androidControllerProvider->on_axis_event(deviceDescriptor, deviceName, axis, value); +} + +extern "C" [[maybe_unused]] JNIEXPORT void JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeInput_setControllerType([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jint index, jint emulated_controller_type) +{ + auto type = static_cast(emulated_controller_type); + auto& androidEmulatedController = AndroidEmulatedController::getAndroidEmulatedController(index); + if (EmulatedController::Type::VPAD <= type && type < EmulatedController::Type::MAX) + androidEmulatedController.setType(type); + else + androidEmulatedController.setDisabled(); +} + +extern "C" [[maybe_unused]] JNIEXPORT jint JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeInput_getControllerType([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jint index) +{ + auto emulatedController = AndroidEmulatedController::getAndroidEmulatedController(index).getEmulatedController(); + if (emulatedController) + return emulatedController->type(); + throw std::runtime_error(fmt::format("can't get type for emulated controller {}", index)); +} + +extern "C" [[maybe_unused]] JNIEXPORT jint JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeInput_getWPADControllersCount([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz) +{ + int wpadCount = 0; + for (size_t i = 0; i < InputManager::kMaxController; i++) + { + auto emulatedController = AndroidEmulatedController::getAndroidEmulatedController(i).getEmulatedController(); + if (!emulatedController) + continue; + if (emulatedController->type() != EmulatedController::Type::VPAD) + ++wpadCount; + } + return wpadCount; +} + +extern "C" [[maybe_unused]] JNIEXPORT jint JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeInput_getVPADControllersCount([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz) +{ + int vpadCount = 0; + for (size_t i = 0; i < InputManager::kMaxController; i++) + { + auto emulatedController = AndroidEmulatedController::getAndroidEmulatedController(i).getEmulatedController(); + if (!emulatedController) + continue; + if (emulatedController->type() == EmulatedController::Type::VPAD) + ++vpadCount; + } + return vpadCount; +} + +extern "C" [[maybe_unused]] JNIEXPORT jboolean JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeInput_isControllerDisabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jint index) +{ + return AndroidEmulatedController::getAndroidEmulatedController(index).getEmulatedController() == nullptr; +} + +extern "C" [[maybe_unused]] JNIEXPORT void JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeInput_setControllerMapping(JNIEnv* env, [[maybe_unused]] jclass clazz, jstring device_descriptor, jstring device_name, jint index, jint mapping_id, jint button_id) +{ + auto deviceName = JNIUtils::JStringToString(env, device_name); + auto deviceDescriptor = JNIUtils::JStringToString(env, device_descriptor); + auto apiProvider = InputManager::instance().get_api_provider(InputAPI::Android); + auto controller = ControllerFactory::CreateController(InputAPI::Android, deviceDescriptor, deviceName); + AndroidEmulatedController::getAndroidEmulatedController(index).setMapping(mapping_id, controller, button_id); +} + +extern "C" [[maybe_unused]] JNIEXPORT jstring JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeInput_getControllerMapping(JNIEnv* env, [[maybe_unused]] jclass clazz, jint index, jint mapping_id) +{ + auto mapping = AndroidEmulatedController::getAndroidEmulatedController(index).getMapping(mapping_id); + return env->NewStringUTF(mapping.value_or("").c_str()); +} + +extern "C" [[maybe_unused]] JNIEXPORT void JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeInput_clearControllerMapping([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jint index, jint mapping_id) +{ + AndroidEmulatedController::getAndroidEmulatedController(index).clearMapping(mapping_id); +} + +extern "C" [[maybe_unused]] JNIEXPORT jobject JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeInput_getControllerMappings(JNIEnv* env, [[maybe_unused]] jclass clazz, jint index) +{ + jclass hashMapClass = env->FindClass("java/util/HashMap"); + jmethodID hashMapConstructor = env->GetMethodID(hashMapClass, "", "()V"); + jmethodID hashMapPut = env->GetMethodID(hashMapClass, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); + jclass integerClass = env->FindClass("java/lang/Integer"); + jmethodID integerConstructor = env->GetMethodID(integerClass, "", "(I)V"); + jobject hashMapObj = env->NewObject(hashMapClass, hashMapConstructor); + auto mappings = AndroidEmulatedController::getAndroidEmulatedController(index).getMappings(); + for (const auto& pair : mappings) + { + jint key = pair.first; + jstring buttonName = env->NewStringUTF(pair.second.c_str()); + jobject mappingId = env->NewObject(integerClass, integerConstructor, key); + env->CallObjectMethod(hashMapObj, hashMapPut, mappingId, buttonName); + } + return hashMapObj; +} + +extern "C" JNIEXPORT void JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeInput_onTouchDown([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jint x, jint y, jboolean isTV) +{ + NativeInput::onTouchEvent(x, y, isTV, true); +} + +extern "C" JNIEXPORT void JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeInput_onTouchUp([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jint x, jint y, jboolean isTV) +{ + NativeInput::onTouchEvent(x, y, isTV, false); +} + +extern "C" JNIEXPORT void JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeInput_onTouchMove([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jint x, jint y, jboolean isTV) +{ + NativeInput::onTouchEvent(x, y, isTV); +} + +extern "C" JNIEXPORT void JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeInput_onMotion([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jlong timestamp, jfloat gyroX, jfloat gyroY, jfloat gyroZ, jfloat accelX, jfloat accelY, jfloat accelZ) +{ + float deltaTime = (timestamp - NativeInput::s_lastMotionTimestamp) * 1e-9f; + NativeInput::s_wiiUMotionHandler.processMotionSample(deltaTime, gyroX, gyroY, gyroZ, accelX * 0.098066f, -accelY * 0.098066f, -accelZ * 0.098066f); + NativeInput::s_lastMotionTimestamp = timestamp; + auto& deviceMotion = InputManager::instance().m_device_motion; + std::scoped_lock lock{deviceMotion.m_mutex}; + deviceMotion.m_motion_sample = NativeInput::s_wiiUMotionHandler.getMotionSample(); +} + +extern "C" JNIEXPORT void JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeInput_setMotionEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jboolean motionEnabled) +{ + auto& deviceMotion = InputManager::instance().m_device_motion; + std::scoped_lock lock{deviceMotion.m_mutex}; + deviceMotion.m_device_motion_enabled = motionEnabled; +} + +extern "C" JNIEXPORT void JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeInput_onOverlayButton([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jint controllerIndex, jint mappingId, jboolean state) +{ + AndroidEmulatedController::getAndroidEmulatedController(controllerIndex).setButtonValue(mappingId, state); +} + +extern "C" JNIEXPORT void JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeInput_onOverlayAxis([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jint controllerIndex, jint mappingId, jfloat value) +{ + AndroidEmulatedController::getAndroidEmulatedController(controllerIndex).setAxisValue(mappingId, value); +} \ No newline at end of file diff --git a/src/android/app/src/main/cpp/NativeLib.cpp b/src/android/app/src/main/cpp/NativeLib.cpp new file mode 100644 index 00000000..22c6678f --- /dev/null +++ b/src/android/app/src/main/cpp/NativeLib.cpp @@ -0,0 +1,7 @@ +#include "JNIUtils.h" + +extern "C" [[maybe_unused]] JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, [[maybe_unused]] void* reserved) +{ + JNIUtils::g_jvm = vm; + return JNI_VERSION_1_6; +} diff --git a/src/android/app/src/main/cpp/NativeSettings.cpp b/src/android/app/src/main/cpp/NativeSettings.cpp new file mode 100644 index 00000000..492fe46a --- /dev/null +++ b/src/android/app/src/main/cpp/NativeSettings.cpp @@ -0,0 +1,271 @@ +#include "JNIUtils.h" +#include "config/CemuConfig.h" + +extern "C" JNIEXPORT jint JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeSettings_getOverlayPosition([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz) +{ + return static_cast(g_config.data().overlay.position); +} + +extern "C" JNIEXPORT void JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeSettings_setOverlayPosition([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jint position) +{ + g_config.data().overlay.position = static_cast(position); + g_config.Save(); +} + +extern "C" JNIEXPORT jboolean JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeSettings_isOverlayFPSEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz) +{ + return g_config.data().overlay.fps; +} + +extern "C" JNIEXPORT void JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeSettings_setOverlayFPSEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jboolean enabled) +{ + g_config.data().overlay.fps = enabled; + g_config.Save(); +} + +extern "C" JNIEXPORT jboolean JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeSettings_isOverlayDrawCallsPerFrameEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz) +{ + return g_config.data().overlay.drawcalls; +} + +extern "C" JNIEXPORT void JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeSettings_setOverlayDrawCallsPerFrameEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jboolean enabled) +{ + g_config.data().overlay.drawcalls = enabled; + g_config.Save(); +} + +extern "C" JNIEXPORT jboolean JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeSettings_isOverlayCPUUsageEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz) +{ + return g_config.data().overlay.cpu_usage; +} + +extern "C" JNIEXPORT void JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeSettings_setOverlayCPUUsageEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jboolean enabled) +{ + g_config.data().overlay.cpu_usage = enabled; + g_config.Save(); +} + +extern "C" JNIEXPORT jboolean JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeSettings_isOverlayCPUPerCoreUsageEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz) +{ + return g_config.data().overlay.cpu_per_core_usage; +} + +extern "C" JNIEXPORT void JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeSettings_setOverlayCPUPerCoreUsageEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jboolean enabled) +{ + g_config.data().overlay.cpu_per_core_usage = enabled; + g_config.Save(); +} + +extern "C" JNIEXPORT jboolean JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeSettings_isOverlayRAMUsageEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz) +{ + return g_config.data().overlay.ram_usage; +} + +extern "C" JNIEXPORT void JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeSettings_setOverlayRAMUsageEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jboolean enabled) +{ + g_config.data().overlay.ram_usage = enabled; + g_config.Save(); +} + +extern "C" JNIEXPORT jboolean JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeSettings_isOverlayVRAMUsageEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz) +{ + return g_config.data().overlay.vram_usage; +} + +extern "C" JNIEXPORT void JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeSettings_setOverlayVRAMUsageEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jboolean enabled) +{ + g_config.data().overlay.vram_usage = enabled; + g_config.Save(); +} + +extern "C" JNIEXPORT jboolean JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeSettings_isOverlayDebugEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz) +{ + return g_config.data().overlay.debug; +} + +extern "C" JNIEXPORT void JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeSettings_setOverlayDebugEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jboolean enabled) +{ + g_config.data().overlay.debug = enabled; + g_config.Save(); +} + +extern "C" JNIEXPORT jint JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeSettings_getNotificationsPosition([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz) +{ + return static_cast(g_config.data().notification.position); +} + +extern "C" JNIEXPORT void JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeSettings_setNotificationsPosition([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jint position) +{ + g_config.data().notification.position = static_cast(position); + g_config.Save(); +} + +extern "C" JNIEXPORT jboolean JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeSettings_isNotificationControllerProfilesEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz) +{ + return g_config.data().notification.controller_profiles; +} + +extern "C" JNIEXPORT void JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeSettings_setNotificationControllerProfilesEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jboolean enabled) +{ + g_config.data().notification.controller_profiles = enabled; + g_config.Save(); +} + +extern "C" JNIEXPORT jboolean JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeSettings_isNotificationShaderCompilerEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz) +{ + return g_config.data().notification.shader_compiling; +} + +extern "C" JNIEXPORT void JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeSettings_setNotificationShaderCompilerEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jboolean enabled) +{ + g_config.data().notification.shader_compiling = enabled; + g_config.Save(); +} + +extern "C" JNIEXPORT jboolean JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeSettings_isNotificationFriendListEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz) +{ + return g_config.data().notification.friends; +} + +extern "C" JNIEXPORT void JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeSettings_setNotificationFriendListEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jboolean enabled) +{ + g_config.data().notification.friends = enabled; + g_config.Save(); +} + +extern "C" [[maybe_unused]] JNIEXPORT void JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeSettings_addGamesPath(JNIEnv* env, [[maybe_unused]] jclass clazz, jstring uri) +{ + auto& gamePaths = g_config.data().game_paths; + auto gamePath = JNIUtils::JStringToString(env, uri); + if (std::any_of(gamePaths.begin(), gamePaths.end(), [&](auto path) { return path == gamePath; })) + return; + gamePaths.push_back(gamePath); + g_config.Save(); +} + +extern "C" [[maybe_unused]] JNIEXPORT void JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeSettings_removeGamesPath(JNIEnv* env, [[maybe_unused]] jclass clazz, jstring uri) +{ + auto gamePath = JNIUtils::JStringToString(env, uri); + auto& gamePaths = g_config.data().game_paths; + std::erase_if(gamePaths, [&](auto path) { return path == gamePath; }); + g_config.Save(); +} + +extern "C" [[maybe_unused]] JNIEXPORT jobject JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeSettings_getGamesPaths(JNIEnv* env, [[maybe_unused]] jclass clazz) +{ + return JNIUtils::createJavaStringArrayList(env, g_config.data().game_paths); +} + +extern "C" [[maybe_unused]] JNIEXPORT jboolean JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeSettings_getAsyncShaderCompile([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz) +{ + return g_config.data().async_compile; +} + +extern "C" [[maybe_unused]] JNIEXPORT void JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeSettings_setAsyncShaderCompile([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jboolean enabled) +{ + g_config.data().async_compile = enabled; + g_config.Save(); +} + +extern "C" [[maybe_unused]] JNIEXPORT jint JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeSettings_getVSyncMode([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz) +{ + return g_config.data().vsync; +} + +extern "C" [[maybe_unused]] JNIEXPORT void JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeSettings_setVSyncMode([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jint vsync_mode) +{ + g_config.data().vsync = vsync_mode; + g_config.Save(); +} + +extern "C" [[maybe_unused]] JNIEXPORT jboolean JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeSettings_getAccurateBarriers([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz) +{ + return g_config.data().vk_accurate_barriers; +} + +extern "C" [[maybe_unused]] JNIEXPORT void JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeSettings_setAccurateBarriers([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jboolean enabled) +{ + g_config.data().vk_accurate_barriers = enabled; + g_config.Save(); +} + +extern "C" [[maybe_unused]] JNIEXPORT jboolean JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeSettings_getAudioDeviceEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jboolean tv) +{ + const auto& device = tv ? g_config.data().tv_device : g_config.data().pad_device; + return !device.empty(); +} + +extern "C" [[maybe_unused]] JNIEXPORT void JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeSettings_setAudioDeviceEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jboolean enabled, jboolean tv) +{ + auto& device = tv ? g_config.data().tv_device : g_config.data().pad_device; + if (enabled) + device = L"Default"; + else + device.clear(); + g_config.Save(); +} + +extern "C" [[maybe_unused]] JNIEXPORT jint JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeSettings_getAudioDeviceChannels([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jboolean tv) +{ + const auto& deviceChannels = tv ? g_config.data().tv_channels : g_config.data().pad_channels; + return deviceChannels; +} + +extern "C" [[maybe_unused]] JNIEXPORT void JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeSettings_setAudioDeviceChannels([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jint channels, jboolean tv) +{ + auto& deviceChannels = tv ? g_config.data().tv_channels : g_config.data().pad_channels; + deviceChannels = static_cast(channels); + g_config.Save(); +} + +extern "C" [[maybe_unused]] JNIEXPORT jint JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeSettings_getAudioDeviceVolume([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jboolean tv) +{ + const auto& deviceVolume = tv ? g_config.data().tv_volume : g_config.data().pad_volume; + return deviceVolume; +} + +extern "C" [[maybe_unused]] JNIEXPORT void JNICALL +Java_info_cemu_Cemu_nativeinterface_NativeSettings_setAudioDeviceVolume([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jint volume, jboolean tv) +{ + auto& deviceVolume = tv ? g_config.data().tv_volume : g_config.data().pad_volume; + deviceVolume = volume; + g_config.Save(); +} \ No newline at end of file diff --git a/src/android/app/src/main/cpp/Utils.cpp b/src/android/app/src/main/cpp/Utils.cpp deleted file mode 100644 index 7d1fdb32..00000000 --- a/src/android/app/src/main/cpp/Utils.cpp +++ /dev/null @@ -1,80 +0,0 @@ -#include "Utils.h" - -#include "Cemu/ncrypto/ncrypto.h" -#include "config/ActiveSettings.h" - -void createCemuDirectories() -{ - std::wstring mlc = ActiveSettings::GetMlcPath().generic_wstring(); - - // create sys/usr folder in mlc01 - try - { - const auto sysFolder = fs::path(mlc).append(L"sys"); - fs::create_directories(sysFolder); - - const auto usrFolder = fs::path(mlc).append(L"usr"); - fs::create_directories(usrFolder); - fs::create_directories(fs::path(usrFolder).append("title/00050000")); // base - fs::create_directories(fs::path(usrFolder).append("title/0005000c")); // dlc - fs::create_directories(fs::path(usrFolder).append("title/0005000e")); // update - - // Mii Maker save folders {0x500101004A000, 0x500101004A100, 0x500101004A200}, - fs::create_directories(fs::path(mlc).append(L"usr/save/00050010/1004a000/user/common/db")); - fs::create_directories(fs::path(mlc).append(L"usr/save/00050010/1004a100/user/common/db")); - fs::create_directories(fs::path(mlc).append(L"usr/save/00050010/1004a200/user/common/db")); - - // lang files - auto langDir = fs::path(mlc).append(L"sys/title/0005001b/1005c000/content"); - fs::create_directories(langDir); - - auto langFile = fs::path(langDir).append("language.txt"); - if (!fs::exists(langFile)) - { - std::ofstream file(langFile); - if (file.is_open()) - { - const char* langStrings[] = {"ja", "en", "fr", "de", "it", "es", "zh", "ko", "nl", "pt", "ru", "zh"}; - for (const char* lang : langStrings) - file << fmt::format(R"("{}",)", lang) << std::endl; - - file.flush(); - file.close(); - } - } - - auto countryFile = fs::path(langDir).append("country.txt"); - if (!fs::exists(countryFile)) - { - std::ofstream file(countryFile); - for (sint32 i = 0; i < 201; i++) - { - const char* countryCode = NCrypto::GetCountryAsString(i); - if (boost::iequals(countryCode, "NN")) - file << "NULL," << std::endl; - else - file << fmt::format(R"("{}",)", countryCode) << std::endl; - } - file.flush(); - file.close(); - } - } catch (const std::exception& ex) - { - exit(0); - } - - // cemu directories - try - { - const auto controllerProfileFolder = ActiveSettings::GetConfigPath(L"controllerProfiles").generic_wstring(); - if (!fs::exists(controllerProfileFolder)) - fs::create_directories(controllerProfileFolder); - - const auto memorySearcherFolder = ActiveSettings::GetUserDataPath(L"memorySearcher").generic_wstring(); - if (!fs::exists(memorySearcherFolder)) - fs::create_directories(memorySearcherFolder); - } catch (const std::exception& ex) - { - exit(0); - } -} \ No newline at end of file diff --git a/src/android/app/src/main/cpp/Utils.h b/src/android/app/src/main/cpp/Utils.h deleted file mode 100644 index 1a67e92a..00000000 --- a/src/android/app/src/main/cpp/Utils.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -#include "config/ActiveSettings.h" -#include "Cemu/ncrypto/ncrypto.h" - -void createCemuDirectories(); diff --git a/src/android/app/src/main/cpp/native-lib.cpp b/src/android/app/src/main/cpp/native-lib.cpp deleted file mode 100644 index cf5afd6f..00000000 --- a/src/android/app/src/main/cpp/native-lib.cpp +++ /dev/null @@ -1,638 +0,0 @@ -#include "Cafe/GraphicPack/GraphicPack2.h" -#include "AndroidGameTitleLoadedCallback.h" -#include "EmulationState.h" -#include "JNIUtils.h" - -EmulationState s_emulationState; - -static_assert(sizeof(TitleId) == sizeof(jlong)); - -extern "C" [[maybe_unused]] JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, [[maybe_unused]] void* reserved) -{ - JNIUtils::g_jvm = vm; - return JNI_VERSION_1_6; -} - -extern "C" [[maybe_unused]] JNIEXPORT void JNICALL -Java_info_cemu_Cemu_NativeLibrary_setSurface(JNIEnv* env, [[maybe_unused]] jclass clazz, jobject surface, jboolean is_main_canvas) -{ - JNIUtils::handleNativeException(env, [&]() { - s_emulationState.setSurface(env, surface, is_main_canvas); - }); -} - -extern "C" [[maybe_unused]] JNIEXPORT void JNICALL -Java_info_cemu_Cemu_NativeLibrary_setSurfaceSize([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jint width, jint height, jboolean is_main_canvas) -{ - s_emulationState.setSurfaceSize(width, height, is_main_canvas); -} - -extern "C" [[maybe_unused]] JNIEXPORT void JNICALL -Java_info_cemu_Cemu_NativeLibrary_startGame([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jstring launchPath) -{ - using namespace CafeSystemUtils; - try - { - s_emulationState.startGame(JNIUtils::JStringToString(env, launchPath)); - } catch (const GameBaseFilesNotFoundException& exception) - { - jclass exceptionClass = env->FindClass("info/cemu/Cemu/NativeLibrary$GameBaseFilesNotFoundException"); - env->ThrowNew(exceptionClass, exception.what()); - } catch (const NoDiscKeyException& exception) - { - jclass exceptionClass = env->FindClass("info/cemu/Cemu/NativeLibrary$NoDiscKeyException"); - env->ThrowNew(exceptionClass, exception.what()); - } catch (const NoTitleTikException& exception) - { - jclass exceptionClass = env->FindClass("info/cemu/Cemu/NativeLibrary$NoTitleTikException"); - env->ThrowNew(exceptionClass, exception.what()); - } catch (const std::exception& exception) - { - jclass exceptionClass = env->FindClass("info/cemu/Cemu/NativeLibrary$UnknownGameFilesException"); - env->ThrowNew(exceptionClass, exception.what()); - } -} - -extern "C" [[maybe_unused]] JNIEXPORT void JNICALL -Java_info_cemu_Cemu_NativeLibrary_setGameTitleLoadedCallback(JNIEnv* env, [[maybe_unused]] jclass clazz, jobject game_title_loaded_callback) -{ - if (game_title_loaded_callback == nullptr) - { - s_emulationState.setOnGameTitleLoaded(nullptr); - return; - } - jclass gameTitleLoadedCallbackClass = env->GetObjectClass(game_title_loaded_callback); - jmethodID onGameTitleLoadedMID = env->GetMethodID(gameTitleLoadedCallbackClass, "onGameTitleLoaded", "(Ljava/lang/String;Ljava/lang/String;[III)V"); - env->DeleteLocalRef(gameTitleLoadedCallbackClass); - s_emulationState.setOnGameTitleLoaded(std::make_shared(onGameTitleLoadedMID, game_title_loaded_callback)); -} - -extern "C" [[maybe_unused]] JNIEXPORT void JNICALL -Java_info_cemu_Cemu_NativeLibrary_reloadGameTitles([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz) -{ - s_emulationState.reloadGameTitles(); -} -extern "C" [[maybe_unused]] JNIEXPORT void JNICALL -Java_info_cemu_Cemu_NativeLibrary_initializeActiveSettings(JNIEnv* env, [[maybe_unused]] jclass clazz, jstring data_path, jstring cache_path) -{ - std::string dataPath = JNIUtils::JStringToString(env, data_path); - std::string cachePath = JNIUtils::JStringToString(env, cache_path); - s_emulationState.initializeActiveSettings(dataPath, cachePath); -} - -extern "C" [[maybe_unused]] JNIEXPORT void JNICALL -Java_info_cemu_Cemu_NativeLibrary_initializeEmulation([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz) -{ - s_emulationState.initializeEmulation(); -} -extern "C" [[maybe_unused]] JNIEXPORT void JNICALL -Java_info_cemu_Cemu_NativeLibrary_initializerRenderer(JNIEnv* env, [[maybe_unused]] jclass clazz, jobject testSurface) -{ - JNIUtils::handleNativeException(env, [&]() { - s_emulationState.initializeRenderer(env, testSurface); - }); -} - -extern "C" [[maybe_unused]] JNIEXPORT void JNICALL -Java_info_cemu_Cemu_NativeLibrary_setDPI([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jfloat dpi) -{ - s_emulationState.setDPI(dpi); -} - -extern "C" [[maybe_unused]] JNIEXPORT void JNICALL -Java_info_cemu_Cemu_NativeLibrary_clearSurface([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jboolean is_main_canvas) -{ - s_emulationState.clearSurface(is_main_canvas); -} -extern "C" [[maybe_unused]] JNIEXPORT void JNICALL -Java_info_cemu_Cemu_NativeLibrary_recreateRenderSurface([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jboolean is_main_canvas) -{ - s_emulationState.notifySurfaceChanged(is_main_canvas); -} - -extern "C" [[maybe_unused]] JNIEXPORT void JNICALL -Java_info_cemu_Cemu_NativeLibrary_addGamesPath(JNIEnv* env, [[maybe_unused]] jclass clazz, jstring uri) -{ - s_emulationState.addGamesPath(JNIUtils::JStringToString(env, uri)); -} - -extern "C" [[maybe_unused]] JNIEXPORT void JNICALL -Java_info_cemu_Cemu_NativeLibrary_removeGamesPath(JNIEnv* env, [[maybe_unused]] jclass clazz, jstring uri) -{ - s_emulationState.removeGamesPath(JNIUtils::JStringToString(env, uri)); -} - -extern "C" [[maybe_unused]] JNIEXPORT jobject JNICALL -Java_info_cemu_Cemu_NativeLibrary_getGamesPaths(JNIEnv* env, [[maybe_unused]] jclass clazz) -{ - return JNIUtils::createJavaStringArrayList(env, g_config.data().game_paths); -} - -extern "C" [[maybe_unused]] JNIEXPORT void JNICALL -Java_info_cemu_Cemu_NativeLibrary_onNativeKey(JNIEnv* env, [[maybe_unused]] jclass clazz, jstring device_descriptor, jstring device_name, jint key, jboolean is_pressed) -{ - auto deviceDescriptor = JNIUtils::JStringToString(env, device_descriptor); - auto deviceName = JNIUtils::JStringToString(env, device_name); - s_emulationState.onKeyEvent(deviceDescriptor, deviceName, key, is_pressed); -} - -extern "C" [[maybe_unused]] JNIEXPORT void JNICALL -Java_info_cemu_Cemu_NativeLibrary_onNativeAxis(JNIEnv* env, [[maybe_unused]] jclass clazz, jstring device_descriptor, jstring device_name, jint axis, jfloat value) -{ - auto deviceDescriptor = JNIUtils::JStringToString(env, device_descriptor); - auto deviceName = JNIUtils::JStringToString(env, device_name); - s_emulationState.onAxisEvent(deviceDescriptor, deviceName, axis, value); -} - -extern "C" [[maybe_unused]] JNIEXPORT void JNICALL -Java_info_cemu_Cemu_NativeLibrary_setControllerType([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jint index, jint emulated_controller_type) -{ - s_emulationState.setEmulatedControllerType(index, static_cast(emulated_controller_type)); -} - -extern "C" [[maybe_unused]] JNIEXPORT jint JNICALL -Java_info_cemu_Cemu_NativeLibrary_getControllerType([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jint index) -{ - return s_emulationState.getEmulatedControllerType(index); -} - -extern "C" [[maybe_unused]] JNIEXPORT jint JNICALL -Java_info_cemu_Cemu_NativeLibrary_getWPADControllersCount([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz) -{ - return s_emulationState.getWPADControllersCount(); -} - -extern "C" [[maybe_unused]] JNIEXPORT jint JNICALL -Java_info_cemu_Cemu_NativeLibrary_getVPADControllersCount([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz) -{ - return s_emulationState.getVPADControllersCount(); -} - -extern "C" [[maybe_unused]] JNIEXPORT jboolean JNICALL -Java_info_cemu_Cemu_NativeLibrary_isControllerDisabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jint index) -{ - return s_emulationState.isEmulatedControllerDisabled(index); -} - -extern "C" [[maybe_unused]] JNIEXPORT void JNICALL -Java_info_cemu_Cemu_NativeLibrary_setControllerMapping(JNIEnv* env, [[maybe_unused]] jclass clazz, jstring device_descriptor, jstring device_name, jint index, jint mapping_id, jint button_id) -{ - auto deviceName = JNIUtils::JStringToString(env, device_name); - auto deviceDescriptor = JNIUtils::JStringToString(env, device_descriptor); - s_emulationState.setControllerMapping(deviceDescriptor, deviceName, index, mapping_id, button_id); -} - -extern "C" [[maybe_unused]] JNIEXPORT jstring JNICALL -Java_info_cemu_Cemu_NativeLibrary_getControllerMapping(JNIEnv* env, [[maybe_unused]] jclass clazz, jint index, jint mapping_id) -{ - auto mapping = s_emulationState.getEmulatedControllerMapping(index, mapping_id); - return env->NewStringUTF(mapping.value_or("").c_str()); -} - -extern "C" [[maybe_unused]] JNIEXPORT void JNICALL -Java_info_cemu_Cemu_NativeLibrary_clearControllerMapping([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jint index, jint mapping_id) -{ - s_emulationState.clearEmulatedControllerMapping(index, mapping_id); -} - -extern "C" [[maybe_unused]] JNIEXPORT jobject JNICALL -Java_info_cemu_Cemu_NativeLibrary_getControllerMappings(JNIEnv* env, [[maybe_unused]] jclass clazz, jint index) -{ - jclass hashMapClass = env->FindClass("java/util/HashMap"); - jmethodID hashMapConstructor = env->GetMethodID(hashMapClass, "", "()V"); - jmethodID hashMapPut = env->GetMethodID(hashMapClass, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); - jclass integerClass = env->FindClass("java/lang/Integer"); - jmethodID integerConstructor = env->GetMethodID(integerClass, "", "(I)V"); - jobject hashMapObj = env->NewObject(hashMapClass, hashMapConstructor); - auto mappings = s_emulationState.getEmulatedControllerMappings(index); - for (const auto& pair : mappings) - { - jint key = pair.first; - jstring buttonName = env->NewStringUTF(pair.second.c_str()); - jobject mappingId = env->NewObject(integerClass, integerConstructor, key); - env->CallObjectMethod(hashMapObj, hashMapPut, mappingId, buttonName); - } - return hashMapObj; -} - -extern "C" [[maybe_unused]] JNIEXPORT void JNICALL -Java_info_cemu_Cemu_NativeLibrary_onKeyEvent(JNIEnv* env, [[maybe_unused]] jclass clazz, jstring device_descriptor, jstring device_name, jint key_code, jboolean is_pressed) -{ - auto deviceDescriptor = JNIUtils::JStringToString(env, device_descriptor); - auto deviceName = JNIUtils::JStringToString(env, device_name); - s_emulationState.onKeyEvent(deviceDescriptor, deviceName, key_code, is_pressed); -} - -extern "C" [[maybe_unused]] JNIEXPORT void JNICALL -Java_info_cemu_Cemu_NativeLibrary_onAxisEvent([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jstring device_descriptor, jstring device_name, jint axis_code, jfloat value) -{ - auto deviceDescriptor = JNIUtils::JStringToString(env, device_descriptor); - auto deviceName = JNIUtils::JStringToString(env, device_name); - s_emulationState.onAxisEvent(deviceDescriptor, deviceName, axis_code, value); -} - -extern "C" [[maybe_unused]] JNIEXPORT jboolean JNICALL -Java_info_cemu_Cemu_NativeLibrary_getAsyncShaderCompile([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz) -{ - return g_config.data().async_compile; -} - -extern "C" [[maybe_unused]] JNIEXPORT void JNICALL -Java_info_cemu_Cemu_NativeLibrary_setAsyncShaderCompile([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jboolean enabled) -{ - g_config.data().async_compile = enabled; - g_config.Save(); -} - -extern "C" [[maybe_unused]] JNIEXPORT jint JNICALL -Java_info_cemu_Cemu_NativeLibrary_getVSyncMode([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz) -{ - return g_config.data().vsync; -} - -extern "C" [[maybe_unused]] JNIEXPORT void JNICALL -Java_info_cemu_Cemu_NativeLibrary_setVSyncMode([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jint vsync_mode) -{ - g_config.data().vsync = vsync_mode; - g_config.Save(); -} - -extern "C" [[maybe_unused]] JNIEXPORT jboolean JNICALL -Java_info_cemu_Cemu_NativeLibrary_getAccurateBarriers([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz) -{ - return g_config.data().vk_accurate_barriers; -} - -extern "C" [[maybe_unused]] JNIEXPORT void JNICALL -Java_info_cemu_Cemu_NativeLibrary_setAccurateBarriers([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jboolean enabled) -{ - g_config.data().vk_accurate_barriers = enabled; - g_config.Save(); -} - -extern "C" [[maybe_unused]] JNIEXPORT jboolean JNICALL -Java_info_cemu_Cemu_NativeLibrary_getAudioDeviceEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jboolean tv) -{ - const auto& device = tv ? g_config.data().tv_device : g_config.data().pad_device; - return !device.empty(); -} - -extern "C" [[maybe_unused]] JNIEXPORT void JNICALL -Java_info_cemu_Cemu_NativeLibrary_setAudioDeviceEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jboolean enabled, jboolean tv) -{ - auto& device = tv ? g_config.data().tv_device : g_config.data().pad_device; - if (enabled) - device = L"Default"; - else - device.clear(); - g_config.Save(); -} - -extern "C" [[maybe_unused]] JNIEXPORT jint JNICALL -Java_info_cemu_Cemu_NativeLibrary_getAudioDeviceChannels([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jboolean tv) -{ - const auto& deviceChannels = tv ? g_config.data().tv_channels : g_config.data().pad_channels; - return deviceChannels; -} - -extern "C" [[maybe_unused]] JNIEXPORT void JNICALL -Java_info_cemu_Cemu_NativeLibrary_setAudioDeviceChannels([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jint channels, jboolean tv) -{ - auto& deviceChannels = tv ? g_config.data().tv_channels : g_config.data().pad_channels; - deviceChannels = static_cast(channels); - g_config.Save(); -} - -extern "C" [[maybe_unused]] JNIEXPORT jint JNICALL -Java_info_cemu_Cemu_NativeLibrary_getAudioDeviceVolume([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jboolean tv) -{ - const auto& deviceVolume = tv ? g_config.data().tv_volume : g_config.data().pad_volume; - return deviceVolume; -} - -extern "C" [[maybe_unused]] JNIEXPORT void JNICALL -Java_info_cemu_Cemu_NativeLibrary_setAudioDeviceVolume([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jint volume, jboolean tv) -{ - auto& deviceVolume = tv ? g_config.data().tv_volume : g_config.data().pad_volume; - deviceVolume = volume; - g_config.Save(); -} - -extern "C" JNIEXPORT void JNICALL -Java_info_cemu_Cemu_NativeLibrary_refreshGraphicPacks([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz) -{ - s_emulationState.refreshGraphicPacks(); -} - -extern "C" JNIEXPORT jobject JNICALL -Java_info_cemu_Cemu_NativeLibrary_getGraphicPackBasicInfos(JNIEnv* env, [[maybe_unused]] jclass clazz) -{ - auto graphicPackInfoClass = env->FindClass("info/cemu/Cemu/NativeLibrary$GraphicPackBasicInfo"); - auto graphicPackInfoCtorId = env->GetMethodID(graphicPackInfoClass, "", "(JLjava/lang/String;Ljava/util/ArrayList;)V"); - - auto graphicPacks = s_emulationState.getGraphicPacks(); - std::vector graphicPackInfoJObjects; - for (auto&& graphicPack : graphicPacks) - { - jstring virtualPath = env->NewStringUTF(graphicPack.second->GetVirtualPath().c_str()); - jlong id = graphicPack.first; - jobject titleIds = JNIUtils::createJavaLongArrayList(env, graphicPack.second->GetTitleIds()); - jobject jGraphicPack = env->NewObject(graphicPackInfoClass, graphicPackInfoCtorId, id, virtualPath, titleIds); - graphicPackInfoJObjects.push_back(jGraphicPack); - } - return JNIUtils::createArrayList(env, graphicPackInfoJObjects); -} - -jobject getGraphicPresets(JNIEnv* env, GraphicPackPtr graphicPack, int64_t id) -{ - auto graphicPackPresetClass = env->FindClass("info/cemu/Cemu/NativeLibrary$GraphicPackPreset"); - auto graphicPackPresetCtorId = env->GetMethodID(graphicPackPresetClass, "", "(JLjava/lang/String;Ljava/util/ArrayList;Ljava/lang/String;)V"); - - std::vector order; - auto presets = graphicPack->GetCategorizedPresets(order); - - std::vector presetsJobjects; - for (const auto& category : order) - { - const auto& entry = presets[category]; - // test if any preset is visible and update its status - if (std::none_of(entry.cbegin(), entry.cend(), [graphicPack](const auto& p) { return p->visible; })) - { - continue; - } - - jstring categoryJStr = category.empty() ? nullptr : env->NewStringUTF(category.c_str()); - std::vector presetSelections; - std::optional activePreset; - for (auto& pentry : entry) - { - if (!pentry->visible) - continue; - - presetSelections.push_back(pentry->name); - - if (pentry->active) - activePreset = pentry->name; - } - - jstring activePresetJstr = nullptr; - if (activePreset) - activePresetJstr = env->NewStringUTF(activePreset->c_str()); - else if (!presetSelections.empty()) - activePresetJstr = env->NewStringUTF(presetSelections.front().c_str()); - auto presetJObject = env->NewObject(graphicPackPresetClass, - graphicPackPresetCtorId, - id, - categoryJStr, - JNIUtils::createJavaStringArrayList(env, presetSelections), - activePresetJstr); - presetsJobjects.push_back(presetJObject); - } - return JNIUtils::createArrayList(env, presetsJobjects); -} -extern "C" JNIEXPORT jobject JNICALL -Java_info_cemu_Cemu_NativeLibrary_getGraphicPack(JNIEnv* env, [[maybe_unused]] jclass clazz, jlong id) -{ - auto graphicPackClass = env->FindClass("info/cemu/Cemu/NativeLibrary$GraphicPack"); - auto graphicPackCtorId = env->GetMethodID(graphicPackClass, "", "(JZLjava/lang/String;Ljava/lang/String;Ljava/util/ArrayList;)V"); - auto graphicPack = s_emulationState.getGraphicPack(id); - - jstring graphicPackName = env->NewStringUTF(graphicPack->GetName().c_str()); - jstring graphicPackDescription = env->NewStringUTF(graphicPack->GetDescription().c_str()); - return env->NewObject(graphicPackClass, - graphicPackCtorId, - id, - graphicPack->IsEnabled(), - graphicPackName, - graphicPackDescription, - getGraphicPresets(env, graphicPack, id)); -} - -extern "C" JNIEXPORT void JNICALL -Java_info_cemu_Cemu_NativeLibrary_setGraphicPackActive([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jlong id, jboolean active) -{ - s_emulationState.setEnabledStateForGraphicPack(id, active); -} - -extern "C" JNIEXPORT void JNICALL -Java_info_cemu_Cemu_NativeLibrary_setGraphicPackActivePreset([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jlong id, jstring category, jstring preset) -{ - std::string presetCategory = category == nullptr ? "" : JNIUtils::JStringToString(env, category); - s_emulationState.setGraphicPackActivePreset(id, presetCategory, JNIUtils::JStringToString(env, preset)); -} - -extern "C" JNIEXPORT jobject JNICALL -Java_info_cemu_Cemu_NativeLibrary_getGraphicPackPresets(JNIEnv* env, [[maybe_unused]] jclass clazz, jlong id) -{ - return getGraphicPresets(env, s_emulationState.getGraphicPack(id), id); -} - -extern "C" JNIEXPORT void JNICALL -Java_info_cemu_Cemu_NativeLibrary_onOverlayButton([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jint controllerIndex, jint mappingId, jboolean state) -{ - s_emulationState.getEmulatedController(controllerIndex).setButtonValue(mappingId, state); -} - -extern "C" JNIEXPORT void JNICALL -Java_info_cemu_Cemu_NativeLibrary_onOverlayAxis([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jint controllerIndex, jint mappingId, jfloat value) -{ - s_emulationState.getEmulatedController(controllerIndex).setAxisValue(mappingId, value); -} - -extern "C" JNIEXPORT jint JNICALL -Java_info_cemu_Cemu_NativeLibrary_getOverlayPosition([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz) -{ - return static_cast(g_config.data().overlay.position); -} - -extern "C" JNIEXPORT void JNICALL -Java_info_cemu_Cemu_NativeLibrary_setOverlayPosition([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jint position) -{ - g_config.data().overlay.position = static_cast(position); - g_config.Save(); -} - -extern "C" JNIEXPORT jboolean JNICALL -Java_info_cemu_Cemu_NativeLibrary_isOverlayFPSEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz) -{ - return g_config.data().overlay.fps; -} - -extern "C" JNIEXPORT void JNICALL -Java_info_cemu_Cemu_NativeLibrary_setOverlayFPSEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jboolean enabled) -{ - g_config.data().overlay.fps = enabled; - g_config.Save(); -} - -extern "C" JNIEXPORT jboolean JNICALL -Java_info_cemu_Cemu_NativeLibrary_isOverlayDrawCallsPerFrameEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz) -{ - return g_config.data().overlay.drawcalls; -} - -extern "C" JNIEXPORT void JNICALL -Java_info_cemu_Cemu_NativeLibrary_setOverlayDrawCallsPerFrameEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jboolean enabled) -{ - g_config.data().overlay.drawcalls = enabled; - g_config.Save(); -} - -extern "C" JNIEXPORT jboolean JNICALL -Java_info_cemu_Cemu_NativeLibrary_isOverlayCPUUsageEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz) -{ - return g_config.data().overlay.cpu_usage; -} - -extern "C" JNIEXPORT void JNICALL -Java_info_cemu_Cemu_NativeLibrary_setOverlayCPUUsageEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jboolean enabled) -{ - g_config.data().overlay.cpu_usage = enabled; - g_config.Save(); -} - -extern "C" JNIEXPORT jboolean JNICALL -Java_info_cemu_Cemu_NativeLibrary_isOverlayCPUPerCoreUsageEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz) -{ - return g_config.data().overlay.cpu_per_core_usage; -} - -extern "C" JNIEXPORT void JNICALL -Java_info_cemu_Cemu_NativeLibrary_setOverlayCPUPerCoreUsageEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jboolean enabled) -{ - g_config.data().overlay.cpu_per_core_usage = enabled; - g_config.Save(); -} - -extern "C" JNIEXPORT jboolean JNICALL -Java_info_cemu_Cemu_NativeLibrary_isOverlayRAMUsageEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz) -{ - return g_config.data().overlay.ram_usage; -} - -extern "C" JNIEXPORT void JNICALL -Java_info_cemu_Cemu_NativeLibrary_setOverlayRAMUsageEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jboolean enabled) -{ - g_config.data().overlay.ram_usage = enabled; - g_config.Save(); -} - -extern "C" JNIEXPORT jboolean JNICALL -Java_info_cemu_Cemu_NativeLibrary_isOverlayVRAMUsageEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz) -{ - return g_config.data().overlay.vram_usage; -} - -extern "C" JNIEXPORT void JNICALL -Java_info_cemu_Cemu_NativeLibrary_setOverlayVRAMUsageEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jboolean enabled) -{ - g_config.data().overlay.vram_usage = enabled; - g_config.Save(); -} - -extern "C" JNIEXPORT jboolean JNICALL -Java_info_cemu_Cemu_NativeLibrary_isOverlayDebugEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz) -{ - return g_config.data().overlay.debug; -} - -extern "C" JNIEXPORT void JNICALL -Java_info_cemu_Cemu_NativeLibrary_setOverlayDebugEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jboolean enabled) -{ - g_config.data().overlay.debug = enabled; - g_config.Save(); -} - -extern "C" JNIEXPORT jint JNICALL -Java_info_cemu_Cemu_NativeLibrary_getNotificationsPosition([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz) -{ - return static_cast(g_config.data().notification.position); -} - -extern "C" JNIEXPORT void JNICALL -Java_info_cemu_Cemu_NativeLibrary_setNotificationsPosition([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jint position) -{ - g_config.data().notification.position = static_cast(position); - g_config.Save(); -} - -extern "C" JNIEXPORT jboolean JNICALL -Java_info_cemu_Cemu_NativeLibrary_isNotificationControllerProfilesEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz) -{ - return g_config.data().notification.controller_profiles; -} - -extern "C" JNIEXPORT void JNICALL -Java_info_cemu_Cemu_NativeLibrary_setNotificationControllerProfilesEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jboolean enabled) -{ - g_config.data().notification.controller_profiles = enabled; - g_config.Save(); -} - -extern "C" JNIEXPORT jboolean JNICALL -Java_info_cemu_Cemu_NativeLibrary_isNotificationShaderCompilerEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz) -{ - return g_config.data().notification.shader_compiling; -} - -extern "C" JNIEXPORT void JNICALL -Java_info_cemu_Cemu_NativeLibrary_setNotificationShaderCompilerEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jboolean enabled) -{ - g_config.data().notification.shader_compiling = enabled; - g_config.Save(); -} - -extern "C" JNIEXPORT jboolean JNICALL -Java_info_cemu_Cemu_NativeLibrary_isNotificationFriendListEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz) -{ - return g_config.data().notification.friends; -} - -extern "C" JNIEXPORT void JNICALL -Java_info_cemu_Cemu_NativeLibrary_setNotificationFriendListEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jboolean enabled) -{ - g_config.data().notification.friends = enabled; - g_config.Save(); -} - -extern "C" JNIEXPORT void JNICALL -Java_info_cemu_Cemu_NativeLibrary_setReplaceTVWithPadView([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jboolean swapped) -{ - s_emulationState.setReplaceTVWithPadView(swapped); -} - -extern "C" JNIEXPORT void JNICALL -Java_info_cemu_Cemu_NativeLibrary_onTouchDown([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jint x, jint y, jboolean isTV) -{ - s_emulationState.onTouchDown(x, y, isTV); -} - -extern "C" JNIEXPORT void JNICALL -Java_info_cemu_Cemu_NativeLibrary_onTouchUp([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jint x, jint y, jboolean isTV) -{ - s_emulationState.onTouchUp(x, y, isTV); -} - -extern "C" JNIEXPORT void JNICALL -Java_info_cemu_Cemu_NativeLibrary_onTouchMove([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jint x, jint y, jboolean isTV) -{ - s_emulationState.onTouchMove(x, y, isTV); -} - -extern "C" JNIEXPORT jobject JNICALL -Java_info_cemu_Cemu_NativeLibrary_getInstalledGamesTitleIds(JNIEnv* env, [[maybe_unused]] jclass clazz) -{ - return JNIUtils::createJavaLongArrayList(env, CafeTitleList::GetAllTitleIds()); -} - -extern "C" JNIEXPORT void JNICALL -Java_info_cemu_Cemu_NativeLibrary_onMotion([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jlong timestamp, jfloat gyroX, jfloat gyroY, jfloat gyroZ, jfloat accelX, jfloat accelY, jfloat accelZ) -{ - s_emulationState.onMotion(timestamp, gyroX, gyroY, gyroZ, accelX, accelY, accelZ); -} - -extern "C" JNIEXPORT void JNICALL -Java_info_cemu_Cemu_NativeLibrary_setMotionEnabled([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jboolean motionEnabled) -{ - s_emulationState.setMotionEnabled(motionEnabled); -} \ No newline at end of file diff --git a/src/android/app/src/main/java/info/cemu/Cemu/CemuApplication.java b/src/android/app/src/main/java/info/cemu/Cemu/CemuApplication.java index 3b2bc1f5..45120eec 100644 --- a/src/android/app/src/main/java/info/cemu/Cemu/CemuApplication.java +++ b/src/android/app/src/main/java/info/cemu/Cemu/CemuApplication.java @@ -4,12 +4,15 @@ import android.app.Application; import android.util.DisplayMetrics; import java.io.File; -import java.util.Objects; -import info.cemu.Cemu.NativeLibrary; -import info.cemu.Cemu.utils.FileUtil; +import info.cemu.Cemu.nativeinterface.NativeEmulation; +import info.cemu.Cemu.nativeinterface.NativeGraphicPacks; public class CemuApplication extends Application { + static { + System.loadLibrary("CemuAndroid"); + } + private static CemuApplication application; public CemuApplication() { @@ -31,8 +34,9 @@ public class CemuApplication extends Application { public void onCreate() { super.onCreate(); DisplayMetrics displayMetrics = getResources().getDisplayMetrics(); - NativeLibrary.setDPI(displayMetrics.density); - NativeLibrary.initializeActiveSettings(getInternalFolder().toString(), getInternalFolder().toString()); - NativeLibrary.initializeEmulation(); + NativeEmulation.setDPI(displayMetrics.density); + NativeEmulation.initializeActiveSettings(getInternalFolder().toString(), getInternalFolder().toString()); + NativeEmulation.initializeEmulation(); + NativeGraphicPacks.refreshGraphicPacks(); } } diff --git a/src/android/app/src/main/java/info/cemu/Cemu/NativeLibrary.java b/src/android/app/src/main/java/info/cemu/Cemu/NativeLibrary.java deleted file mode 100644 index 8b02da36..00000000 --- a/src/android/app/src/main/java/info/cemu/Cemu/NativeLibrary.java +++ /dev/null @@ -1,412 +0,0 @@ -package info.cemu.Cemu; - -import android.view.Surface; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Objects; - -public class NativeLibrary { - static { - System.loadLibrary("CemuAndroid"); - } - - public static native void setDPI(float dpi); - - public static native void setSurface(Surface surface, boolean isMainCanvas); - - public static native void clearSurface(boolean isMainCanvas); - - public static native void setSurfaceSize(int width, int height, boolean isMainCanvas); - - public static native void initializerRenderer(Surface surface); - - public static class GameFilesException extends RuntimeException { - } - - public static class GameBaseFilesNotFoundException extends GameFilesException { - } - - public static class NoDiscKeyException extends GameFilesException { - } - - public static class NoTitleTikException extends GameFilesException { - } - - public static class UnknownGameFilesException extends GameFilesException { - } - - public static native void startGame(String launchPath); - - public static native void setReplaceTVWithPadView(boolean swapped); - - public static native void recreateRenderSurface(boolean isMainCanvas); - - public interface GameTitleLoadedCallback { - void onGameTitleLoaded(String path, String title, int[] colors, int width, int height); - } - - public static native void setGameTitleLoadedCallback(GameTitleLoadedCallback gameTitleLoadedCallback); - - public static native void reloadGameTitles(); - - public static native void initializeActiveSettings(String dataPath, String cachePath); - - public static native void initializeEmulation(); - - public static native void addGamesPath(String uri); - - public static native void removeGamesPath(String uri); - - public static native ArrayList getGamesPaths(); - - public static native void onNativeKey(String deviceDescriptor, String deviceName, int key, boolean isPressed); - - public static native void onNativeAxis(String deviceDescriptor, String deviceName, int axis, float value); - - public static final int VPAD_BUTTON_NONE = 0; - public static final int VPAD_BUTTON_A = 1; - public static final int VPAD_BUTTON_B = 2; - public static final int VPAD_BUTTON_X = 3; - public static final int VPAD_BUTTON_Y = 4; - public static final int VPAD_BUTTON_L = 5; - public static final int VPAD_BUTTON_R = 6; - public static final int VPAD_BUTTON_ZL = 7; - public static final int VPAD_BUTTON_ZR = 8; - public static final int VPAD_BUTTON_PLUS = 9; - public static final int VPAD_BUTTON_MINUS = 10; - public static final int VPAD_BUTTON_UP = 11; - public static final int VPAD_BUTTON_DOWN = 12; - public static final int VPAD_BUTTON_LEFT = 13; - public static final int VPAD_BUTTON_RIGHT = 14; - public static final int VPAD_BUTTON_STICKL = 15; - public static final int VPAD_BUTTON_STICKR = 16; - public static final int VPAD_BUTTON_STICKL_UP = 17; - public static final int VPAD_BUTTON_STICKL_DOWN = 18; - public static final int VPAD_BUTTON_STICKL_LEFT = 19; - public static final int VPAD_BUTTON_STICKL_RIGHT = 20; - public static final int VPAD_BUTTON_STICKR_UP = 21; - public static final int VPAD_BUTTON_STICKR_DOWN = 22; - public static final int VPAD_BUTTON_STICKR_LEFT = 23; - public static final int VPAD_BUTTON_STICKR_RIGHT = 24; - public static final int VPAD_BUTTON_MIC = 25; - public static final int VPAD_BUTTON_SCREEN = 26; - public static final int VPAD_BUTTON_HOME = 27; - public static final int VPAD_BUTTON_MAX = 28; - - public static final int PRO_BUTTON_NONE = 0; - public static final int PRO_BUTTON_A = 1; - public static final int PRO_BUTTON_B = 2; - public static final int PRO_BUTTON_X = 3; - public static final int PRO_BUTTON_Y = 4; - public static final int PRO_BUTTON_L = 5; - public static final int PRO_BUTTON_R = 6; - public static final int PRO_BUTTON_ZL = 7; - public static final int PRO_BUTTON_ZR = 8; - public static final int PRO_BUTTON_PLUS = 9; - public static final int PRO_BUTTON_MINUS = 10; - public static final int PRO_BUTTON_HOME = 11; - public static final int PRO_BUTTON_UP = 12; - public static final int PRO_BUTTON_DOWN = 13; - public static final int PRO_BUTTON_LEFT = 14; - public static final int PRO_BUTTON_RIGHT = 15; - public static final int PRO_BUTTON_STICKL = 16; - public static final int PRO_BUTTON_STICKR = 17; - public static final int PRO_BUTTON_STICKL_UP = 18; - public static final int PRO_BUTTON_STICKL_DOWN = 19; - public static final int PRO_BUTTON_STICKL_LEFT = 20; - public static final int PRO_BUTTON_STICKL_RIGHT = 21; - public static final int PRO_BUTTON_STICKR_UP = 22; - public static final int PRO_BUTTON_STICKR_DOWN = 23; - public static final int PRO_BUTTON_STICKR_LEFT = 24; - public static final int PRO_BUTTON_STICKR_RIGHT = 25; - public static final int PRO_BUTTON_MAX = 26; - - public static final int CLASSIC_BUTTON_NONE = 0; - public static final int CLASSIC_BUTTON_A = 1; - public static final int CLASSIC_BUTTON_B = 2; - public static final int CLASSIC_BUTTON_X = 3; - public static final int CLASSIC_BUTTON_Y = 4; - public static final int CLASSIC_BUTTON_L = 5; - public static final int CLASSIC_BUTTON_R = 6; - public static final int CLASSIC_BUTTON_ZL = 7; - public static final int CLASSIC_BUTTON_ZR = 8; - public static final int CLASSIC_BUTTON_PLUS = 9; - public static final int CLASSIC_BUTTON_MINUS = 10; - public static final int CLASSIC_BUTTON_HOME = 11; - public static final int CLASSIC_BUTTON_UP = 12; - public static final int CLASSIC_BUTTON_DOWN = 13; - public static final int CLASSIC_BUTTON_LEFT = 14; - public static final int CLASSIC_BUTTON_RIGHT = 15; - public static final int CLASSIC_BUTTON_STICKL_UP = 16; - public static final int CLASSIC_BUTTON_STICKL_DOWN = 17; - public static final int CLASSIC_BUTTON_STICKL_LEFT = 18; - public static final int CLASSIC_BUTTON_STICKL_RIGHT = 19; - public static final int CLASSIC_BUTTON_STICKR_UP = 20; - public static final int CLASSIC_BUTTON_STICKR_DOWN = 21; - public static final int CLASSIC_BUTTON_STICKR_LEFT = 22; - public static final int CLASSIC_BUTTON_STICKR_RIGHT = 23; - public static final int CLASSIC_BUTTON_MAX = 24; - - public static final int WIIMOTE_BUTTON_NONE = 0; - public static final int WIIMOTE_BUTTON_A = 1; - public static final int WIIMOTE_BUTTON_B = 2; - public static final int WIIMOTE_BUTTON_1 = 3; - public static final int WIIMOTE_BUTTON_2 = 4; - public static final int WIIMOTE_BUTTON_NUNCHUCK_Z = 5; - public static final int WIIMOTE_BUTTON_NUNCHUCK_C = 6; - public static final int WIIMOTE_BUTTON_PLUS = 7; - public static final int WIIMOTE_BUTTON_MINUS = 8; - public static final int WIIMOTE_BUTTON_UP = 9; - public static final int WIIMOTE_BUTTON_DOWN = 10; - public static final int WIIMOTE_BUTTON_LEFT = 11; - public static final int WIIMOTE_BUTTON_RIGHT = 12; - public static final int WIIMOTE_BUTTON_NUNCHUCK_UP = 13; - public static final int WIIMOTE_BUTTON_NUNCHUCK_DOWN = 14; - public static final int WIIMOTE_BUTTON_NUNCHUCK_LEFT = 15; - public static final int WIIMOTE_BUTTON_NUNCHUCK_RIGHT = 16; - public static final int WIIMOTE_BUTTON_HOME = 17; - public static final int WIIMOTE_BUTTON_MAX = 18; - - public static final int EMULATED_CONTROLLER_TYPE_VPAD = 0; - public static final int EMULATED_CONTROLLER_TYPE_PRO = 1; - public static final int EMULATED_CONTROLLER_TYPE_CLASSIC = 2; - public static final int EMULATED_CONTROLLER_TYPE_WIIMOTE = 3; - public static final int EMULATED_CONTROLLER_TYPE_DISABLED = -1; - - public static final int DPAD_UP = 34; - public static final int DPAD_DOWN = 35; - public static final int DPAD_LEFT = 36; - public static final int DPAD_RIGHT = 37; - public static final int AXIS_X_POS = 38; - public static final int AXIS_Y_POS = 39; - public static final int ROTATION_X_POS = 40; - public static final int ROTATION_Y_POS = 41; - public static final int TRIGGER_X_POS = 42; - public static final int TRIGGER_Y_POS = 43; - public static final int AXIS_X_NEG = 44; - public static final int AXIS_Y_NEG = 45; - public static final int ROTATION_X_NEG = 46; - public static final int ROTATION_Y_NEG = 47; - - public static final int MAX_CONTROLLERS = 8; - public static final int MAX_VPAD_CONTROLLERS = 2; - public static final int MAX_WPAD_CONTROLLERS = 7; - - public static native void setControllerType(int index, int emulatedControllerType); - - public static native boolean isControllerDisabled(int index); - - public static native int getControllerType(int index); - - public static native int getWPADControllersCount(); - - public static native int getVPADControllersCount(); - - public static native void setControllerMapping(String deviceDescriptor, String deviceName, int index, int mappingId, int buttonId); - - public static native void clearControllerMapping(int index, int mappingId); - - public static native String getControllerMapping(int index, int mappingId); - - public static native Map getControllerMappings(int index); - - public static native void onKeyEvent(String deviceDescriptor, String deviceName, int keyCode, boolean isPressed); - - public static native void onAxisEvent(String deviceDescriptor, String deviceName, int axisCode, float value); - - public static native boolean getAsyncShaderCompile(); - - public static native void setAsyncShaderCompile(boolean enabled); - - public static final int VSYNC_MODE_OFF = 0; - public static final int VSYNC_MODE_DOUBLE_BUFFERING = 1; - public static final int VSYNC_MODE_TRIPLE_BUFFERING = 2; - - public static native int getVSyncMode(); - - public static native void setVSyncMode(int vsyncMode); - - public static native boolean getAccurateBarriers(); - - public static native void setAccurateBarriers(boolean enabled); - - public static native boolean getAudioDeviceEnabled(boolean tv); - - public static native void setAudioDeviceEnabled(boolean enabled, boolean tv); - - public static final int AUDIO_CHANNELS_MONO = 0; - public static final int AUDIO_CHANNELS_STEREO = 1; - public static final int AUDIO_CHANNELS_SURROUND = 2; - - public static native void setAudioDeviceChannels(int channels, boolean tv); - - public static native int getAudioDeviceChannels(boolean tv); - - public static final int AUDIO_MIN_VOLUME = 0; - public static final int AUDIO_MAX_VOLUME = 100; - - public static native void setAudioDeviceVolume(int volume, boolean tv); - - public static native int getAudioDeviceVolume(boolean tv); - - public record GraphicPackBasicInfo(long id, String virtualPath, ArrayList titleIds) { - } - - public static native ArrayList getInstalledGamesTitleIds(); - - public static native ArrayList getGraphicPackBasicInfos(); - - public static class GraphicPackPreset { - private final long graphicPackId; - private final String category; - private final ArrayList presets; - private String activePreset; - - @Override - public int hashCode() { - return Objects.hash(graphicPackId, category, presets, activePreset); - } - - @Override - public boolean equals(Object object) { - if (object == null) return false; - if (object == this) return true; - if (object instanceof GraphicPackPreset preset) - return this.hashCode() == preset.hashCode(); - return false; - } - - public GraphicPackPreset(long graphicPackId, String category, ArrayList presets, String activePreset) { - this.graphicPackId = graphicPackId; - this.category = category; - this.presets = presets; - this.activePreset = activePreset; - } - - public String getActivePreset() { - return activePreset; - } - - public void setActivePreset(String activePreset) { - if (presets.stream().noneMatch(s -> s.equals(activePreset))) - throw new IllegalArgumentException("Trying to set an invalid preset: " + activePreset); - setGraphicPackActivePreset(graphicPackId, category, activePreset); - this.activePreset = activePreset; - } - - public String getCategory() { - return category; - } - - public ArrayList getPresets() { - return presets; - } - } - - public static class GraphicPack { - public final long id; - protected boolean active; - public final String name; - public final String description; - public List presets; - - public GraphicPack(long id, boolean active, String name, String description, ArrayList presets) { - this.id = id; - this.active = active; - this.name = name; - this.description = description; - this.presets = presets; - } - - public boolean isActive() { - return active; - } - - public void reloadPresets() { - presets = NativeLibrary.getGraphicPackPresets(id); - } - - public void setActive(boolean active) { - this.active = active; - setGraphicPackActive(id, active); - } - } - - public static native void refreshGraphicPacks(); - - public static native GraphicPack getGraphicPack(long id); - - public static native void setGraphicPackActive(long id, boolean active); - - public static native void setGraphicPackActivePreset(long id, String category, String preset); - - public static native ArrayList getGraphicPackPresets(long id); - - public static native void onOverlayButton(int controllerIndex, int mappingId, boolean value); - - public static native void onOverlayAxis(int controllerIndex, int mappingId, float value); - - public static final int OVERLAY_SCREEN_POSITION_DISABLED = 0; - public static final int OVERLAY_SCREEN_POSITION_TOP_LEFT = 1; - public static final int OVERLAY_SCREEN_POSITION_TOP_CENTER = 2; - public static final int OVERLAY_SCREEN_POSITION_TOP_RIGHT = 3; - public static final int OVERLAY_SCREEN_POSITION_BOTTOM_LEFT = 4; - public static final int OVERLAY_SCREEN_POSITION_BOTTOM_CENTER = 5; - public static final int OVERLAY_SCREEN_POSITION_BOTTOM_RIGHT = 6; - - public static native int getOverlayPosition(); - - public static native void setOverlayPosition(int position); - - public static native boolean isOverlayFPSEnabled(); - - public static native void setOverlayFPSEnabled(boolean enabled); - - public static native boolean isOverlayDrawCallsPerFrameEnabled(); - - public static native void setOverlayDrawCallsPerFrameEnabled(boolean enabled); - - public static native boolean isOverlayCPUUsageEnabled(); - - public static native void setOverlayCPUUsageEnabled(boolean enabled); - - public static native boolean isOverlayCPUPerCoreUsageEnabled(); - - public static native void setOverlayCPUPerCoreUsageEnabled(boolean enabled); - - public static native boolean isOverlayRAMUsageEnabled(); - - public static native void setOverlayRAMUsageEnabled(boolean enabled); - - public static native boolean isOverlayDebugEnabled(); - - public static native void setOverlayDebugEnabled(boolean enabled); - - public static native int getNotificationsPosition(); - - public static native void setNotificationsPosition(int position); - - public static native boolean isNotificationControllerProfilesEnabled(); - - public static native void setNotificationControllerProfilesEnabled(boolean enabled); - - public static native boolean isNotificationShaderCompilerEnabled(); - - public static native void setNotificationShaderCompilerEnabled(boolean enabled); - - public static native boolean isNotificationFriendListEnabled(); - - public static native void setNotificationFriendListEnabled(boolean enabled); - - public static native void onTouchDown(int x, int y, boolean isTV); - - public static native void onTouchMove(int x, int y, boolean isTV); - - public static native void onTouchUp(int x, int y, boolean isTV); - - public static native void onMotion(long timestamp, float gyroX, float gyroY, float gyroZ, float accelX, float accelY, float accelZ); - - public static native void setMotionEnabled(boolean motionEnabled); -} diff --git a/src/android/app/src/main/java/info/cemu/Cemu/emulation/EmulationFragment.java b/src/android/app/src/main/java/info/cemu/Cemu/emulation/EmulationFragment.java index 4b79e576..c0d85740 100644 --- a/src/android/app/src/main/java/info/cemu/Cemu/emulation/EmulationFragment.java +++ b/src/android/app/src/main/java/info/cemu/Cemu/emulation/EmulationFragment.java @@ -22,13 +22,14 @@ import androidx.appcompat.widget.PopupMenu; import androidx.fragment.app.Fragment; import androidx.lifecycle.ViewModelProvider; -import info.cemu.Cemu.NativeLibrary; +import info.cemu.Cemu.nativeinterface.NativeEmulation; import info.cemu.Cemu.R; import info.cemu.Cemu.databinding.FragmentEmulationBinding; import info.cemu.Cemu.input.SensorManager; import info.cemu.Cemu.inputoverlay.InputOverlaySettingsProvider; import info.cemu.Cemu.inputoverlay.InputOverlaySurfaceView; import info.cemu.Cemu.nativeinterface.NativeException; +import info.cemu.Cemu.nativeinterface.NativeInput; @SuppressLint("ClickableViewAccessibility") public class EmulationFragment extends Fragment implements PopupMenu.OnMenuItemClickListener { @@ -51,16 +52,16 @@ public class EmulationFragment extends Fragment implements PopupMenu.OnMenuItemC int y = (int) event.getY(pointerIndex); switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN, MotionEvent.ACTION_POINTER_DOWN -> { - NativeLibrary.onTouchDown(x, y, isTV); + NativeInput.onTouchDown(x, y, isTV); return true; } case MotionEvent.ACTION_UP, MotionEvent.ACTION_POINTER_UP -> { currentPointerId = -1; - NativeLibrary.onTouchUp(x, y, isTV); + NativeInput.onTouchUp(x, y, isTV); return true; } case MotionEvent.ACTION_MOVE -> { - NativeLibrary.onTouchMove(x, y, isTV); + NativeInput.onTouchMove(x, y, isTV); return true; } } @@ -83,11 +84,11 @@ public class EmulationFragment extends Fragment implements PopupMenu.OnMenuItemC @Override public void surfaceChanged(@NonNull SurfaceHolder surfaceHolder, int format, int width, int height) { try { - NativeLibrary.setSurfaceSize(width, height, isMainCanvas); + NativeEmulation.setSurfaceSize(width, height, isMainCanvas); if (surfaceSet) { return; } - NativeLibrary.setSurface(surfaceHolder.getSurface(), isMainCanvas); + NativeEmulation.setSurface(surfaceHolder.getSurface(), isMainCanvas); surfaceSet = true; } catch (NativeException exception) { onEmulationError(getString(R.string.failed_create_surface_error, exception.getMessage())); @@ -96,7 +97,7 @@ public class EmulationFragment extends Fragment implements PopupMenu.OnMenuItemC @Override public void surfaceDestroyed(@NonNull SurfaceHolder surfaceHolder) { - NativeLibrary.clearSurface(isMainCanvas); + NativeEmulation.clearSurface(isMainCanvas); surfaceSet = false; } } @@ -212,7 +213,7 @@ public class EmulationFragment extends Fragment implements PopupMenu.OnMenuItemC } if (itemId == R.id.replace_tv_with_pad) { boolean replaceTVWithPad = !item.isChecked(); - NativeLibrary.setReplaceTVWithPadView(replaceTVWithPad); + NativeEmulation.setReplaceTVWithPadView(replaceTVWithPad); item.setChecked(replaceTVWithPad); return true; } @@ -270,7 +271,7 @@ public class EmulationFragment extends Fragment implements PopupMenu.OnMenuItemC } SurfaceView mainCanvas = binding.mainCanvas; try { - NativeLibrary.initializerRenderer(testSurface); + NativeEmulation.initializerRenderer(testSurface); } catch (NativeException exception) { onEmulationError(getString(R.string.failed_initialize_renderer_error, exception.getMessage())); return binding.getRoot(); @@ -302,17 +303,17 @@ public class EmulationFragment extends Fragment implements PopupMenu.OnMenuItemC } private void startGame() { - try { - NativeLibrary.startGame(launchPath); - } catch (NativeLibrary.GameBaseFilesNotFoundException exception) { - onEmulationError(getString(R.string.game_not_found)); - } catch (NativeLibrary.NoDiscKeyException exception) { - onEmulationError(getString(R.string.no_disk_key)); - } catch (NativeLibrary.NoTitleTikException exception) { - onEmulationError(getString(R.string.no_title_tik)); - } catch (NativeLibrary.GameFilesException exception) { - onEmulationError(getString(R.string.game_files_unknown_error, launchPath)); - } + int result = NativeEmulation.startGame(launchPath); + if (result == NativeEmulation.START_GAME_SUCCESSFUL) + return; + int errorMessageId = switch (result) { + case NativeEmulation.START_GAME_ERROR_GAME_BASE_FILES_NOT_FOUND -> + R.string.game_not_found; + case NativeEmulation.START_GAME_ERROR_NO_DISC_KEY -> R.string.no_disk_key; + case NativeEmulation.START_GAME_ERROR_NO_TITLE_TIK -> R.string.no_title_tik; + default -> R.string.game_files_unknown_error; + }; + onEmulationError(getString(errorMessageId)); } private void onEmulationError(String errorMessage) { diff --git a/src/android/app/src/main/java/info/cemu/Cemu/features/DocumentsProvider.java b/src/android/app/src/main/java/info/cemu/Cemu/features/DocumentsProvider.java index 0a4716d7..7ddf8001 100644 --- a/src/android/app/src/main/java/info/cemu/Cemu/features/DocumentsProvider.java +++ b/src/android/app/src/main/java/info/cemu/Cemu/features/DocumentsProvider.java @@ -34,7 +34,6 @@ public class DocumentsProvider extends android.provider.DocumentsProvider { } } - private final String[] DEFAULT_ROOT_PROJECTION = { DocumentsContract.Root.COLUMN_ROOT_ID, DocumentsContract.Root.COLUMN_MIME_TYPES, diff --git a/src/android/app/src/main/java/info/cemu/Cemu/gameview/GameViewModel.java b/src/android/app/src/main/java/info/cemu/Cemu/gameview/GameViewModel.java index 45006439..34422b0f 100644 --- a/src/android/app/src/main/java/info/cemu/Cemu/gameview/GameViewModel.java +++ b/src/android/app/src/main/java/info/cemu/Cemu/gameview/GameViewModel.java @@ -1,7 +1,6 @@ package info.cemu.Cemu.gameview; import android.graphics.Bitmap; -import android.util.Log; import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; @@ -9,10 +8,8 @@ import androidx.lifecycle.ViewModel; import java.util.ArrayList; import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import info.cemu.Cemu.NativeLibrary; +import info.cemu.Cemu.nativeinterface.NativeGameTitles; public class GameViewModel extends ViewModel { private final MutableLiveData> gamesData; @@ -25,7 +22,7 @@ public class GameViewModel extends ViewModel { public GameViewModel() { this.gamesData = new MutableLiveData<>(); - NativeLibrary.setGameTitleLoadedCallback((path, title, colors, width, height) -> { + NativeGameTitles.setGameTitleLoadedCallback((path, title, colors, width, height) -> { Bitmap icon = null; if (colors != null) icon = Bitmap.createBitmap(colors, width, height, Bitmap.Config.ARGB_8888); @@ -39,12 +36,12 @@ public class GameViewModel extends ViewModel { @Override protected void onCleared() { - NativeLibrary.setGameTitleLoadedCallback(null); + NativeGameTitles.setGameTitleLoadedCallback(null); } public void refreshGames() { games.clear(); gamesData.setValue(null); - NativeLibrary.reloadGameTitles(); + NativeGameTitles.reloadGameTitles(); } } diff --git a/src/android/app/src/main/java/info/cemu/Cemu/input/InputManager.java b/src/android/app/src/main/java/info/cemu/Cemu/input/InputManager.java index c537bd1b..29cb72b7 100644 --- a/src/android/app/src/main/java/info/cemu/Cemu/input/InputManager.java +++ b/src/android/app/src/main/java/info/cemu/Cemu/input/InputManager.java @@ -1,11 +1,10 @@ package info.cemu.Cemu.input; -import android.util.Log; import android.view.InputDevice; import android.view.KeyEvent; import android.view.MotionEvent; -import info.cemu.Cemu.NativeLibrary; +import info.cemu.Cemu.nativeinterface.NativeInput; public class InputManager { private static class InvalidAxisException extends Exception { @@ -17,59 +16,60 @@ public class InputManager { private int getNativeAxisKey(int axis, boolean isPositive) throws InvalidAxisException { if (isPositive) { return switch (axis) { - case MotionEvent.AXIS_X -> NativeLibrary.AXIS_X_POS; - case MotionEvent.AXIS_Y -> NativeLibrary.AXIS_Y_POS; - case MotionEvent.AXIS_RX, MotionEvent.AXIS_Z -> NativeLibrary.ROTATION_X_POS; - case MotionEvent.AXIS_RY, MotionEvent.AXIS_RZ -> NativeLibrary.ROTATION_Y_POS; - case MotionEvent.AXIS_LTRIGGER -> NativeLibrary.TRIGGER_X_POS; - case MotionEvent.AXIS_RTRIGGER -> NativeLibrary.TRIGGER_Y_POS; - case MotionEvent.AXIS_HAT_X -> NativeLibrary.DPAD_RIGHT; - case MotionEvent.AXIS_HAT_Y -> NativeLibrary.DPAD_DOWN; + case MotionEvent.AXIS_X -> NativeInput.AXIS_X_POS; + case MotionEvent.AXIS_Y -> NativeInput.AXIS_Y_POS; + case MotionEvent.AXIS_RX, MotionEvent.AXIS_Z -> NativeInput.ROTATION_X_POS; + case MotionEvent.AXIS_RY, MotionEvent.AXIS_RZ -> NativeInput.ROTATION_Y_POS; + case MotionEvent.AXIS_LTRIGGER -> NativeInput.TRIGGER_X_POS; + case MotionEvent.AXIS_RTRIGGER -> NativeInput.TRIGGER_Y_POS; + case MotionEvent.AXIS_HAT_X -> NativeInput.DPAD_RIGHT; + case MotionEvent.AXIS_HAT_Y -> NativeInput.DPAD_DOWN; default -> throw new InvalidAxisException(axis); }; } else { return switch (axis) { - case MotionEvent.AXIS_X -> NativeLibrary.AXIS_X_NEG; - case MotionEvent.AXIS_Y -> NativeLibrary.AXIS_Y_NEG; - case MotionEvent.AXIS_RX, MotionEvent.AXIS_Z -> NativeLibrary.ROTATION_X_NEG; - case MotionEvent.AXIS_RY, MotionEvent.AXIS_RZ -> NativeLibrary.ROTATION_Y_NEG; - case MotionEvent.AXIS_HAT_X -> NativeLibrary.DPAD_LEFT; - case MotionEvent.AXIS_HAT_Y -> NativeLibrary.DPAD_UP; + case MotionEvent.AXIS_X -> NativeInput.AXIS_X_NEG; + case MotionEvent.AXIS_Y -> NativeInput.AXIS_Y_NEG; + case MotionEvent.AXIS_RX, MotionEvent.AXIS_Z -> NativeInput.ROTATION_X_NEG; + case MotionEvent.AXIS_RY, MotionEvent.AXIS_RZ -> NativeInput.ROTATION_Y_NEG; + case MotionEvent.AXIS_HAT_X -> NativeInput.DPAD_LEFT; + case MotionEvent.AXIS_HAT_Y -> NativeInput.DPAD_UP; default -> throw new InvalidAxisException(axis); }; } } - private boolean isMotionEventFromJoystick(MotionEvent event) { - return (event.getSource() & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK && event.getAction() == MotionEvent.ACTION_MOVE; + private boolean isMotionEventFromJoystickOrGamepad(MotionEvent event) { + return (event.getSource() & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK || (event.getSource() & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD; } private static final float MIN_ABS_AXIS_VALUE = 0.33f; public boolean mapMotionEventToMappingId(int controllerIndex, int mappingId, MotionEvent event) { - if (isMotionEventFromJoystick(event)) { - InputDevice device = event.getDevice(); - float maxAbsAxisValue = 0.0f; - int maxAxis = -1; - int actionPointerIndex = event.getActionIndex(); - for (InputDevice.MotionRange motionRange : device.getMotionRanges()) { - float axisValue = event.getAxisValue(motionRange.getAxis(), actionPointerIndex); - int axis; - try { - axis = getNativeAxisKey(motionRange.getAxis(), axisValue > 0); - } catch (InvalidAxisException e) { - continue; - } - if (Math.abs(axisValue) > maxAbsAxisValue) { - maxAxis = axis; - maxAbsAxisValue = Math.abs(axisValue); - } + if (!isMotionEventFromJoystickOrGamepad(event)) { + return false; + } + InputDevice device = event.getDevice(); + float maxAbsAxisValue = 0.0f; + int maxAxis = -1; + int actionPointerIndex = event.getActionIndex(); + for (InputDevice.MotionRange motionRange : device.getMotionRanges()) { + float axisValue = event.getAxisValue(motionRange.getAxis(), actionPointerIndex); + int axis; + try { + axis = getNativeAxisKey(motionRange.getAxis(), axisValue > 0); + } catch (InvalidAxisException e) { + continue; } - if (maxAbsAxisValue > MIN_ABS_AXIS_VALUE) { - NativeLibrary.setControllerMapping(device.getDescriptor(), device.getName(), controllerIndex, mappingId, maxAxis); - return true; + if (Math.abs(axisValue) > maxAbsAxisValue) { + maxAxis = axis; + maxAbsAxisValue = Math.abs(axisValue); } } + if (maxAbsAxisValue > MIN_ABS_AXIS_VALUE) { + NativeInput.setControllerMapping(device.getDescriptor(), device.getName(), controllerIndex, mappingId, maxAxis); + return true; + } return false; } @@ -98,26 +98,26 @@ public class InputManager { InputDevice device = event.getDevice(); if (!isController(device)) return false; - NativeLibrary.onNativeKey(device.getDescriptor(), device.getName(), event.getKeyCode(), event.getAction() == KeyEvent.ACTION_DOWN); + NativeInput.onNativeKey(device.getDescriptor(), device.getName(), event.getKeyCode(), event.getAction() == KeyEvent.ACTION_DOWN); return true; } public boolean onMotionEvent(MotionEvent event) { - if (!isMotionEventFromJoystick(event)) + if (!isMotionEventFromJoystickOrGamepad(event)) return false; InputDevice device = event.getDevice(); int actionPointerIndex = event.getActionIndex(); for (InputDevice.MotionRange motionRange : device.getMotionRanges()) { float axisValue = event.getAxisValue(motionRange.getAxis(), actionPointerIndex); int axis = motionRange.getAxis(); - NativeLibrary.onNativeAxis(device.getDescriptor(), device.getName(), axis, axisValue); + NativeInput.onNativeAxis(device.getDescriptor(), device.getName(), axis, axisValue); } return true; } public boolean mapKeyEventToMappingId(int controllerIndex, int mappingId, KeyEvent event) { InputDevice device = event.getDevice(); - NativeLibrary.setControllerMapping(device.getDescriptor(), device.getName(), controllerIndex, mappingId, event.getKeyCode()); + NativeInput.setControllerMapping(device.getDescriptor(), device.getName(), controllerIndex, mappingId, event.getKeyCode()); return true; } } diff --git a/src/android/app/src/main/java/info/cemu/Cemu/input/SensorManager.java b/src/android/app/src/main/java/info/cemu/Cemu/input/SensorManager.java index 13648e75..6861f2b2 100644 --- a/src/android/app/src/main/java/info/cemu/Cemu/input/SensorManager.java +++ b/src/android/app/src/main/java/info/cemu/Cemu/input/SensorManager.java @@ -5,7 +5,7 @@ import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; -import info.cemu.Cemu.NativeLibrary; +import info.cemu.Cemu.nativeinterface.NativeInput; public class SensorManager implements SensorEventListener { private final android.hardware.SensorManager sensorManager; @@ -28,7 +28,7 @@ public class SensorManager implements SensorEventListener { if (!hasMotionData) { return; } - NativeLibrary.setMotionEnabled(true); + NativeInput.setMotionEnabled(true); sensorManager.registerListener(this, gyroscope, android.hardware.SensorManager.SENSOR_DELAY_GAME); sensorManager.registerListener(this, accelerometer, android.hardware.SensorManager.SENSOR_DELAY_GAME); } @@ -41,7 +41,7 @@ public class SensorManager implements SensorEventListener { if (!hasMotionData) { return; } - NativeLibrary.setMotionEnabled(false); + NativeInput.setMotionEnabled(false); sensorManager.unregisterListener(this); } @@ -65,10 +65,10 @@ public class SensorManager implements SensorEventListener { hasAccelData = false; hasGyroData = false; if (isLandscape) { - NativeLibrary.onMotion(event.timestamp, gyroY, gyroZ, gyroX, accelY, accelZ, accelX); + NativeInput.onMotion(event.timestamp, gyroY, gyroZ, gyroX, accelY, accelZ, accelX); return; } - NativeLibrary.onMotion(event.timestamp, gyroX, gyroY, gyroZ, accelX, accelY, accelZ); + NativeInput.onMotion(event.timestamp, gyroX, gyroY, gyroZ, accelX, accelY, accelZ); } @Override diff --git a/src/android/app/src/main/java/info/cemu/Cemu/inputoverlay/InputOverlaySettingsFragment.java b/src/android/app/src/main/java/info/cemu/Cemu/inputoverlay/InputOverlaySettingsFragment.java index 2b33319e..32b5dfc3 100644 --- a/src/android/app/src/main/java/info/cemu/Cemu/inputoverlay/InputOverlaySettingsFragment.java +++ b/src/android/app/src/main/java/info/cemu/Cemu/inputoverlay/InputOverlaySettingsFragment.java @@ -1,8 +1,6 @@ package info.cemu.Cemu.inputoverlay; -import android.content.Context; -import android.content.Intent; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; @@ -17,13 +15,12 @@ import java.util.stream.IntStream; import info.cemu.Cemu.R; import info.cemu.Cemu.databinding.GenericRecyclerViewLayoutBinding; -import info.cemu.Cemu.guibasecomponents.ButtonRecyclerViewItem; import info.cemu.Cemu.guibasecomponents.CheckboxRecyclerViewItem; import info.cemu.Cemu.guibasecomponents.GenericRecyclerViewAdapter; import info.cemu.Cemu.guibasecomponents.SelectionAdapter; import info.cemu.Cemu.guibasecomponents.SingleSelectionRecyclerViewItem; import info.cemu.Cemu.guibasecomponents.SliderRecyclerViewItem; -import info.cemu.Cemu.NativeLibrary; +import info.cemu.Cemu.nativeinterface.NativeInput; public class InputOverlaySettingsFragment extends Fragment { @@ -75,7 +72,7 @@ public class InputOverlaySettingsFragment extends Fragment { genericRecyclerViewAdapter.addRecyclerViewItem(alphaSlider); SelectionAdapter controllerAdapter = new SelectionAdapter<>( - IntStream.range(0, NativeLibrary.MAX_CONTROLLERS) + IntStream.range(0, NativeInput.MAX_CONTROLLERS) .mapToObj(i -> new SelectionAdapter.ChoiceItem<>(t -> t.setText(getString(R.string.controller_numbered, i + 1)), i)) .collect(Collectors.toList()), overlaySettings.getControllerIndex() diff --git a/src/android/app/src/main/java/info/cemu/Cemu/inputoverlay/InputOverlaySettingsProvider.java b/src/android/app/src/main/java/info/cemu/Cemu/inputoverlay/InputOverlaySettingsProvider.java index 698a6dd9..d9ade8ef 100644 --- a/src/android/app/src/main/java/info/cemu/Cemu/inputoverlay/InputOverlaySettingsProvider.java +++ b/src/android/app/src/main/java/info/cemu/Cemu/inputoverlay/InputOverlaySettingsProvider.java @@ -8,7 +8,7 @@ import android.graphics.Rect; import java.util.Optional; import java.util.function.Consumer; -import info.cemu.Cemu.NativeLibrary; +import info.cemu.Cemu.nativeinterface.NativeInput; public class InputOverlaySettingsProvider { public enum Input { @@ -129,7 +129,7 @@ public class InputOverlaySettingsProvider { int leftJoystickCentreX = (int) (width * 0.25f); int joystickCentreY = (int) (height * 0.55f); int joystickClickRadius = (int) (joystickRadius * 0.7f); - + // TODO: move this to res? return switch (input) { case A -> new Rect(abxyButtonsCentreX + roundButtonRadius, abxyButtonsCentreY - roundButtonRadius, @@ -222,7 +222,7 @@ public class InputOverlaySettingsProvider { } public void setControllerIndex(int controllerIndex) { - this.controllerIndex = Math.min(Math.max(controllerIndex, 0), NativeLibrary.MAX_CONTROLLERS - 1); + this.controllerIndex = Math.min(Math.max(controllerIndex, 0), NativeInput.MAX_CONTROLLERS - 1); } public int getControllerIndex() { diff --git a/src/android/app/src/main/java/info/cemu/Cemu/inputoverlay/InputOverlaySurfaceView.java b/src/android/app/src/main/java/info/cemu/Cemu/inputoverlay/InputOverlaySurfaceView.java index 97232a1d..c4ff440e 100644 --- a/src/android/app/src/main/java/info/cemu/Cemu/inputoverlay/InputOverlaySurfaceView.java +++ b/src/android/app/src/main/java/info/cemu/Cemu/inputoverlay/InputOverlaySurfaceView.java @@ -14,7 +14,7 @@ import java.util.ArrayList; import java.util.List; import info.cemu.Cemu.R; -import info.cemu.Cemu.NativeLibrary; +import info.cemu.Cemu.nativeinterface.NativeInput; public class InputOverlaySurfaceView extends SurfaceView implements View.OnTouchListener { public enum InputMode { @@ -110,94 +110,94 @@ public class InputOverlaySurfaceView extends SurfaceView implements View.OnTouch int overlayButtonToVPADButton(OverlayButton button) { return switch (button) { - case A -> NativeLibrary.VPAD_BUTTON_A; - case B -> NativeLibrary.VPAD_BUTTON_B; - case X -> NativeLibrary.VPAD_BUTTON_X; - case Y -> NativeLibrary.VPAD_BUTTON_Y; - case PLUS -> NativeLibrary.VPAD_BUTTON_PLUS; - case MINUS -> NativeLibrary.VPAD_BUTTON_MINUS; - case DPAD_UP -> NativeLibrary.VPAD_BUTTON_UP; - case DPAD_DOWN -> NativeLibrary.VPAD_BUTTON_DOWN; - case DPAD_LEFT -> NativeLibrary.VPAD_BUTTON_LEFT; - case DPAD_RIGHT -> NativeLibrary.VPAD_BUTTON_RIGHT; - case L_STICK -> NativeLibrary.VPAD_BUTTON_STICKL; - case R_STICK -> NativeLibrary.VPAD_BUTTON_STICKR; - case L -> NativeLibrary.VPAD_BUTTON_L; - case R -> NativeLibrary.VPAD_BUTTON_R; - case ZR -> NativeLibrary.VPAD_BUTTON_ZR; - case ZL -> NativeLibrary.VPAD_BUTTON_ZL; + case A -> NativeInput.VPAD_BUTTON_A; + case B -> NativeInput.VPAD_BUTTON_B; + case X -> NativeInput.VPAD_BUTTON_X; + case Y -> NativeInput.VPAD_BUTTON_Y; + case PLUS -> NativeInput.VPAD_BUTTON_PLUS; + case MINUS -> NativeInput.VPAD_BUTTON_MINUS; + case DPAD_UP -> NativeInput.VPAD_BUTTON_UP; + case DPAD_DOWN -> NativeInput.VPAD_BUTTON_DOWN; + case DPAD_LEFT -> NativeInput.VPAD_BUTTON_LEFT; + case DPAD_RIGHT -> NativeInput.VPAD_BUTTON_RIGHT; + case L_STICK -> NativeInput.VPAD_BUTTON_STICKL; + case R_STICK -> NativeInput.VPAD_BUTTON_STICKR; + case L -> NativeInput.VPAD_BUTTON_L; + case R -> NativeInput.VPAD_BUTTON_R; + case ZR -> NativeInput.VPAD_BUTTON_ZR; + case ZL -> NativeInput.VPAD_BUTTON_ZL; default -> -1; }; } int overlayButtonToClassicButton(OverlayButton button) { return switch (button) { - case A -> NativeLibrary.CLASSIC_BUTTON_A; - case B -> NativeLibrary.CLASSIC_BUTTON_B; - case X -> NativeLibrary.CLASSIC_BUTTON_X; - case Y -> NativeLibrary.CLASSIC_BUTTON_Y; - case PLUS -> NativeLibrary.CLASSIC_BUTTON_PLUS; - case MINUS -> NativeLibrary.CLASSIC_BUTTON_MINUS; - case DPAD_UP -> NativeLibrary.CLASSIC_BUTTON_UP; - case DPAD_DOWN -> NativeLibrary.CLASSIC_BUTTON_DOWN; - case DPAD_LEFT -> NativeLibrary.CLASSIC_BUTTON_LEFT; - case DPAD_RIGHT -> NativeLibrary.CLASSIC_BUTTON_RIGHT; - case L -> NativeLibrary.CLASSIC_BUTTON_L; - case R -> NativeLibrary.CLASSIC_BUTTON_R; - case ZR -> NativeLibrary.CLASSIC_BUTTON_ZR; - case ZL -> NativeLibrary.CLASSIC_BUTTON_ZL; + case A -> NativeInput.CLASSIC_BUTTON_A; + case B -> NativeInput.CLASSIC_BUTTON_B; + case X -> NativeInput.CLASSIC_BUTTON_X; + case Y -> NativeInput.CLASSIC_BUTTON_Y; + case PLUS -> NativeInput.CLASSIC_BUTTON_PLUS; + case MINUS -> NativeInput.CLASSIC_BUTTON_MINUS; + case DPAD_UP -> NativeInput.CLASSIC_BUTTON_UP; + case DPAD_DOWN -> NativeInput.CLASSIC_BUTTON_DOWN; + case DPAD_LEFT -> NativeInput.CLASSIC_BUTTON_LEFT; + case DPAD_RIGHT -> NativeInput.CLASSIC_BUTTON_RIGHT; + case L -> NativeInput.CLASSIC_BUTTON_L; + case R -> NativeInput.CLASSIC_BUTTON_R; + case ZR -> NativeInput.CLASSIC_BUTTON_ZR; + case ZL -> NativeInput.CLASSIC_BUTTON_ZL; default -> -1; }; } int overlayButtonToProButton(OverlayButton button) { return switch (button) { - case A -> NativeLibrary.PRO_BUTTON_A; - case B -> NativeLibrary.PRO_BUTTON_B; - case X -> NativeLibrary.PRO_BUTTON_X; - case Y -> NativeLibrary.PRO_BUTTON_Y; - case PLUS -> NativeLibrary.PRO_BUTTON_PLUS; - case MINUS -> NativeLibrary.PRO_BUTTON_MINUS; - case DPAD_UP -> NativeLibrary.PRO_BUTTON_UP; - case DPAD_DOWN -> NativeLibrary.PRO_BUTTON_DOWN; - case DPAD_LEFT -> NativeLibrary.PRO_BUTTON_LEFT; - case DPAD_RIGHT -> NativeLibrary.PRO_BUTTON_RIGHT; - case L_STICK -> NativeLibrary.PRO_BUTTON_STICKL; - case R_STICK -> NativeLibrary.PRO_BUTTON_STICKR; - case L -> NativeLibrary.PRO_BUTTON_L; - case R -> NativeLibrary.PRO_BUTTON_R; - case ZR -> NativeLibrary.PRO_BUTTON_ZR; - case ZL -> NativeLibrary.PRO_BUTTON_ZL; + case A -> NativeInput.PRO_BUTTON_A; + case B -> NativeInput.PRO_BUTTON_B; + case X -> NativeInput.PRO_BUTTON_X; + case Y -> NativeInput.PRO_BUTTON_Y; + case PLUS -> NativeInput.PRO_BUTTON_PLUS; + case MINUS -> NativeInput.PRO_BUTTON_MINUS; + case DPAD_UP -> NativeInput.PRO_BUTTON_UP; + case DPAD_DOWN -> NativeInput.PRO_BUTTON_DOWN; + case DPAD_LEFT -> NativeInput.PRO_BUTTON_LEFT; + case DPAD_RIGHT -> NativeInput.PRO_BUTTON_RIGHT; + case L_STICK -> NativeInput.PRO_BUTTON_STICKL; + case R_STICK -> NativeInput.PRO_BUTTON_STICKR; + case L -> NativeInput.PRO_BUTTON_L; + case R -> NativeInput.PRO_BUTTON_R; + case ZR -> NativeInput.PRO_BUTTON_ZR; + case ZL -> NativeInput.PRO_BUTTON_ZL; default -> -1; }; } int overlayButtonToWiimoteButton(OverlayButton button) { return switch (button) { - case A -> NativeLibrary.WIIMOTE_BUTTON_A; - case B -> NativeLibrary.WIIMOTE_BUTTON_B; - case ONE -> NativeLibrary.WIIMOTE_BUTTON_1; - case TWO -> NativeLibrary.WIIMOTE_BUTTON_2; - case PLUS -> NativeLibrary.WIIMOTE_BUTTON_PLUS; - case MINUS -> NativeLibrary.WIIMOTE_BUTTON_MINUS; - case HOME -> NativeLibrary.WIIMOTE_BUTTON_HOME; - case DPAD_UP -> NativeLibrary.WIIMOTE_BUTTON_UP; - case DPAD_DOWN -> NativeLibrary.WIIMOTE_BUTTON_DOWN; - case DPAD_LEFT -> NativeLibrary.WIIMOTE_BUTTON_LEFT; - case DPAD_RIGHT -> NativeLibrary.WIIMOTE_BUTTON_RIGHT; - case C -> NativeLibrary.WIIMOTE_BUTTON_NUNCHUCK_C; - case Z -> NativeLibrary.WIIMOTE_BUTTON_NUNCHUCK_Z; + case A -> NativeInput.WIIMOTE_BUTTON_A; + case B -> NativeInput.WIIMOTE_BUTTON_B; + case ONE -> NativeInput.WIIMOTE_BUTTON_1; + case TWO -> NativeInput.WIIMOTE_BUTTON_2; + case PLUS -> NativeInput.WIIMOTE_BUTTON_PLUS; + case MINUS -> NativeInput.WIIMOTE_BUTTON_MINUS; + case HOME -> NativeInput.WIIMOTE_BUTTON_HOME; + case DPAD_UP -> NativeInput.WIIMOTE_BUTTON_UP; + case DPAD_DOWN -> NativeInput.WIIMOTE_BUTTON_DOWN; + case DPAD_LEFT -> NativeInput.WIIMOTE_BUTTON_LEFT; + case DPAD_RIGHT -> NativeInput.WIIMOTE_BUTTON_RIGHT; + case C -> NativeInput.WIIMOTE_BUTTON_NUNCHUCK_C; + case Z -> NativeInput.WIIMOTE_BUTTON_NUNCHUCK_Z; default -> -1; }; } void onButtonStateChange(OverlayButton button, boolean state) { int nativeButtonId = switch (nativeControllerType) { - case NativeLibrary.EMULATED_CONTROLLER_TYPE_VPAD -> overlayButtonToVPADButton(button); - case NativeLibrary.EMULATED_CONTROLLER_TYPE_CLASSIC -> + case NativeInput.EMULATED_CONTROLLER_TYPE_VPAD -> overlayButtonToVPADButton(button); + case NativeInput.EMULATED_CONTROLLER_TYPE_CLASSIC -> overlayButtonToClassicButton(button); - case NativeLibrary.EMULATED_CONTROLLER_TYPE_PRO -> overlayButtonToProButton(button); - case NativeLibrary.EMULATED_CONTROLLER_TYPE_WIIMOTE -> + case NativeInput.EMULATED_CONTROLLER_TYPE_PRO -> overlayButtonToProButton(button); + case NativeInput.EMULATED_CONTROLLER_TYPE_WIIMOTE -> overlayButtonToWiimoteButton(button); default -> -1; }; @@ -207,61 +207,61 @@ public class InputOverlaySurfaceView extends SurfaceView implements View.OnTouch if (vibrateOnTouch && state) { vibrator.vibrate(buttonTouchVibrationEffect); } - NativeLibrary.onOverlayButton(controllerIndex, nativeButtonId, state); + NativeInput.onOverlayButton(controllerIndex, nativeButtonId, state); } void onOverlayAxis(int axis, float value) { - NativeLibrary.onOverlayAxis(controllerIndex, axis, value); + NativeInput.onOverlayAxis(controllerIndex, axis, value); } void onVPADJoystickStateChange(OverlayJoystick joystick, float up, float down, float left, float right) { if (joystick == OverlayJoystick.LEFT) { - onOverlayAxis(NativeLibrary.VPAD_BUTTON_STICKL_UP, up); - onOverlayAxis(NativeLibrary.VPAD_BUTTON_STICKL_DOWN, down); - onOverlayAxis(NativeLibrary.VPAD_BUTTON_STICKL_LEFT, left); - onOverlayAxis(NativeLibrary.VPAD_BUTTON_STICKL_RIGHT, right); + onOverlayAxis(NativeInput.VPAD_BUTTON_STICKL_UP, up); + onOverlayAxis(NativeInput.VPAD_BUTTON_STICKL_DOWN, down); + onOverlayAxis(NativeInput.VPAD_BUTTON_STICKL_LEFT, left); + onOverlayAxis(NativeInput.VPAD_BUTTON_STICKL_RIGHT, right); } else { - onOverlayAxis(NativeLibrary.VPAD_BUTTON_STICKR_UP, up); - onOverlayAxis(NativeLibrary.VPAD_BUTTON_STICKR_DOWN, down); - onOverlayAxis(NativeLibrary.VPAD_BUTTON_STICKR_LEFT, left); - onOverlayAxis(NativeLibrary.VPAD_BUTTON_STICKR_RIGHT, right); + onOverlayAxis(NativeInput.VPAD_BUTTON_STICKR_UP, up); + onOverlayAxis(NativeInput.VPAD_BUTTON_STICKR_DOWN, down); + onOverlayAxis(NativeInput.VPAD_BUTTON_STICKR_LEFT, left); + onOverlayAxis(NativeInput.VPAD_BUTTON_STICKR_RIGHT, right); } } void onProJoystickStateChange(OverlayJoystick joystick, float up, float down, float left, float right) { if (joystick == OverlayJoystick.LEFT) { - onOverlayAxis(NativeLibrary.PRO_BUTTON_STICKL_UP, up); - onOverlayAxis(NativeLibrary.PRO_BUTTON_STICKL_DOWN, down); - onOverlayAxis(NativeLibrary.PRO_BUTTON_STICKL_LEFT, left); - onOverlayAxis(NativeLibrary.PRO_BUTTON_STICKL_RIGHT, right); + onOverlayAxis(NativeInput.PRO_BUTTON_STICKL_UP, up); + onOverlayAxis(NativeInput.PRO_BUTTON_STICKL_DOWN, down); + onOverlayAxis(NativeInput.PRO_BUTTON_STICKL_LEFT, left); + onOverlayAxis(NativeInput.PRO_BUTTON_STICKL_RIGHT, right); } else { - onOverlayAxis(NativeLibrary.PRO_BUTTON_STICKR_UP, up); - onOverlayAxis(NativeLibrary.PRO_BUTTON_STICKR_DOWN, down); - onOverlayAxis(NativeLibrary.PRO_BUTTON_STICKR_LEFT, left); - onOverlayAxis(NativeLibrary.PRO_BUTTON_STICKR_RIGHT, right); + onOverlayAxis(NativeInput.PRO_BUTTON_STICKR_UP, up); + onOverlayAxis(NativeInput.PRO_BUTTON_STICKR_DOWN, down); + onOverlayAxis(NativeInput.PRO_BUTTON_STICKR_LEFT, left); + onOverlayAxis(NativeInput.PRO_BUTTON_STICKR_RIGHT, right); } } void onClassicJoystickStateChange(OverlayJoystick joystick, float up, float down, float left, float right) { if (joystick == OverlayJoystick.LEFT) { - onOverlayAxis(NativeLibrary.CLASSIC_BUTTON_STICKL_UP, up); - onOverlayAxis(NativeLibrary.CLASSIC_BUTTON_STICKL_DOWN, down); - onOverlayAxis(NativeLibrary.CLASSIC_BUTTON_STICKL_LEFT, left); - onOverlayAxis(NativeLibrary.CLASSIC_BUTTON_STICKL_RIGHT, right); + onOverlayAxis(NativeInput.CLASSIC_BUTTON_STICKL_UP, up); + onOverlayAxis(NativeInput.CLASSIC_BUTTON_STICKL_DOWN, down); + onOverlayAxis(NativeInput.CLASSIC_BUTTON_STICKL_LEFT, left); + onOverlayAxis(NativeInput.CLASSIC_BUTTON_STICKL_RIGHT, right); } else { - onOverlayAxis(NativeLibrary.CLASSIC_BUTTON_STICKR_UP, up); - onOverlayAxis(NativeLibrary.CLASSIC_BUTTON_STICKR_DOWN, down); - onOverlayAxis(NativeLibrary.CLASSIC_BUTTON_STICKR_LEFT, left); - onOverlayAxis(NativeLibrary.CLASSIC_BUTTON_STICKR_RIGHT, right); + onOverlayAxis(NativeInput.CLASSIC_BUTTON_STICKR_UP, up); + onOverlayAxis(NativeInput.CLASSIC_BUTTON_STICKR_DOWN, down); + onOverlayAxis(NativeInput.CLASSIC_BUTTON_STICKR_LEFT, left); + onOverlayAxis(NativeInput.CLASSIC_BUTTON_STICKR_RIGHT, right); } } void onWiimoteJoystickStateChange(OverlayJoystick joystick, float up, float down, float left, float right) { if (joystick == OverlayJoystick.LEFT) { - onOverlayAxis(NativeLibrary.WIIMOTE_BUTTON_NUNCHUCK_UP, up); - onOverlayAxis(NativeLibrary.WIIMOTE_BUTTON_NUNCHUCK_DOWN, down); - onOverlayAxis(NativeLibrary.WIIMOTE_BUTTON_NUNCHUCK_LEFT, left); - onOverlayAxis(NativeLibrary.WIIMOTE_BUTTON_NUNCHUCK_RIGHT, right); + onOverlayAxis(NativeInput.WIIMOTE_BUTTON_NUNCHUCK_UP, up); + onOverlayAxis(NativeInput.WIIMOTE_BUTTON_NUNCHUCK_DOWN, down); + onOverlayAxis(NativeInput.WIIMOTE_BUTTON_NUNCHUCK_LEFT, left); + onOverlayAxis(NativeInput.WIIMOTE_BUTTON_NUNCHUCK_RIGHT, right); } } @@ -271,13 +271,13 @@ public class InputOverlaySurfaceView extends SurfaceView implements View.OnTouch float left = x < 0 ? -x : 0; float right = x > 0 ? x : 0; switch (nativeControllerType) { - case NativeLibrary.EMULATED_CONTROLLER_TYPE_VPAD -> + case NativeInput.EMULATED_CONTROLLER_TYPE_VPAD -> onVPADJoystickStateChange(joystick, up, down, left, right); - case NativeLibrary.EMULATED_CONTROLLER_TYPE_PRO -> + case NativeInput.EMULATED_CONTROLLER_TYPE_PRO -> onProJoystickStateChange(joystick, up, down, left, right); - case NativeLibrary.EMULATED_CONTROLLER_TYPE_CLASSIC -> + case NativeInput.EMULATED_CONTROLLER_TYPE_CLASSIC -> onClassicJoystickStateChange(joystick, up, down, left, right); - case NativeLibrary.EMULATED_CONTROLLER_TYPE_WIIMOTE -> + case NativeInput.EMULATED_CONTROLLER_TYPE_WIIMOTE -> onWiimoteJoystickStateChange(joystick, up, down, left, right); } } @@ -291,11 +291,11 @@ public class InputOverlaySurfaceView extends SurfaceView implements View.OnTouch return; } inputs = new ArrayList<>(); - if (NativeLibrary.isControllerDisabled(controllerIndex)) { + if (NativeInput.isControllerDisabled(controllerIndex)) { return; } var resources = getResources(); - nativeControllerType = NativeLibrary.getControllerType(controllerIndex); + nativeControllerType = NativeInput.getControllerType(controllerIndex); inputs.add(new RoundButton( resources, @@ -314,7 +314,7 @@ public class InputOverlaySurfaceView extends SurfaceView implements View.OnTouch getOverlaySettingsForInput(InputOverlaySettingsProvider.Input.B) )); - if (nativeControllerType != NativeLibrary.EMULATED_CONTROLLER_TYPE_WIIMOTE) { + if (nativeControllerType != NativeInput.EMULATED_CONTROLLER_TYPE_WIIMOTE) { inputs.add(new RoundButton( resources, R.drawable.button_x_pressed, @@ -409,7 +409,7 @@ public class InputOverlaySurfaceView extends SurfaceView implements View.OnTouch getOverlaySettingsForInput(InputOverlaySettingsProvider.Input.LEFT_AXIS) )); - if (nativeControllerType == NativeLibrary.EMULATED_CONTROLLER_TYPE_WIIMOTE) { + if (nativeControllerType == NativeInput.EMULATED_CONTROLLER_TYPE_WIIMOTE) { inputs.add(new RoundButton( resources, R.drawable.button_c_pressed, @@ -435,8 +435,8 @@ public class InputOverlaySurfaceView extends SurfaceView implements View.OnTouch getOverlaySettingsForInput(InputOverlaySettingsProvider.Input.HOME) )); } - if (nativeControllerType != NativeLibrary.EMULATED_CONTROLLER_TYPE_CLASSIC - && nativeControllerType != NativeLibrary.EMULATED_CONTROLLER_TYPE_WIIMOTE) { + if (nativeControllerType != NativeInput.EMULATED_CONTROLLER_TYPE_CLASSIC + && nativeControllerType != NativeInput.EMULATED_CONTROLLER_TYPE_WIIMOTE) { inputs.add(new RoundButton( resources, R.drawable.button_stick_pressed, diff --git a/src/android/app/src/main/java/info/cemu/Cemu/utils/FileUtil.java b/src/android/app/src/main/java/info/cemu/Cemu/nativeinterface/FileCallbacks.java similarity index 92% rename from src/android/app/src/main/java/info/cemu/Cemu/utils/FileUtil.java rename to src/android/app/src/main/java/info/cemu/Cemu/nativeinterface/FileCallbacks.java index 91d4f8bc..9132b688 100644 --- a/src/android/app/src/main/java/info/cemu/Cemu/utils/FileUtil.java +++ b/src/android/app/src/main/java/info/cemu/Cemu/nativeinterface/FileCallbacks.java @@ -1,4 +1,4 @@ -package info.cemu.Cemu.utils; +package info.cemu.Cemu.nativeinterface; import android.database.Cursor; import android.net.Uri; @@ -13,7 +13,7 @@ import java.util.ArrayList; import info.cemu.Cemu.CemuApplication; -public class FileUtil { +public class FileCallbacks { private static final String PATH_SEPARATOR_ENCODED = "%2F"; private static final String PATH_SEPARATOR_DECODED = "/"; private static final String COLON_ENCODED = "%3A"; @@ -46,7 +46,7 @@ public class FileUtil { return fd; } } catch (Exception e) { - Log.e("FileUtil", "Cannot open content uri, error: " + e.getMessage()); + Log.e("FileCallbacks", "Cannot open content uri, error: " + e.getMessage()); } return -1; } @@ -62,7 +62,7 @@ public class FileUtil { files.add(toCppPath(documentUri)); } } catch (Exception e) { - Log.e("FileUtil", "Cannot list files: " + e.getMessage()); + Log.e("FileCallbacks", "Cannot list files: " + e.getMessage()); } String[] filesArray = new String[files.size()]; filesArray = files.toArray(filesArray); @@ -82,7 +82,7 @@ public class FileUtil { try (Cursor cursor = CemuApplication.getApplication().getApplicationContext().getContentResolver().query(fromCppPath(uri), null, null, null, null)) { return cursor != null && cursor.moveToFirst(); } catch (Exception e) { - Log.e("FileUtil", "Failed checking if file exists: " + e.getMessage()); + Log.e("FileCallbacks", "Failed checking if file exists: " + e.getMessage()); return false; } } diff --git a/src/android/app/src/main/java/info/cemu/Cemu/nativeinterface/NativeEmulation.java b/src/android/app/src/main/java/info/cemu/Cemu/nativeinterface/NativeEmulation.java new file mode 100644 index 00000000..dd62b07c --- /dev/null +++ b/src/android/app/src/main/java/info/cemu/Cemu/nativeinterface/NativeEmulation.java @@ -0,0 +1,31 @@ +package info.cemu.Cemu.nativeinterface; + +import android.view.Surface; + +public class NativeEmulation { + public static native void initializeActiveSettings(String dataPath, String cachePath); + + public static native void initializeEmulation(); + + public static native void setDPI(float dpi); + + public static native void setSurface(Surface surface, boolean isMainCanvas); + + public static native void clearSurface(boolean isMainCanvas); + + public static native void setSurfaceSize(int width, int height, boolean isMainCanvas); + + public static native void initializerRenderer(Surface surface); + + public static final int START_GAME_SUCCESSFUL = 0; + public static final int START_GAME_ERROR_GAME_BASE_FILES_NOT_FOUND = 1; + public static final int START_GAME_ERROR_NO_DISC_KEY = 2; + public static final int START_GAME_ERROR_NO_TITLE_TIK = 3; + public static final int START_GAME_ERROR_UNKNOWN = 4; + + public static native int startGame(String launchPath); + + public static native void setReplaceTVWithPadView(boolean swapped); + + public static native void recreateRenderSurface(boolean isMainCanvas); +} diff --git a/src/android/app/src/main/java/info/cemu/Cemu/nativeinterface/NativeGameTitles.java b/src/android/app/src/main/java/info/cemu/Cemu/nativeinterface/NativeGameTitles.java new file mode 100644 index 00000000..6272a005 --- /dev/null +++ b/src/android/app/src/main/java/info/cemu/Cemu/nativeinterface/NativeGameTitles.java @@ -0,0 +1,16 @@ +package info.cemu.Cemu.nativeinterface; + +import java.util.ArrayList; + +public class NativeGameTitles { + public interface GameTitleLoadedCallback { + void onGameTitleLoaded(String path, String title, int[] colors, int width, int height); + } + + public static native void setGameTitleLoadedCallback(GameTitleLoadedCallback gameTitleLoadedCallback); + + public static native void reloadGameTitles(); + + public static native ArrayList getInstalledGamesTitleIds(); + +} diff --git a/src/android/app/src/main/java/info/cemu/Cemu/nativeinterface/NativeGraphicPacks.java b/src/android/app/src/main/java/info/cemu/Cemu/nativeinterface/NativeGraphicPacks.java new file mode 100644 index 00000000..485ef335 --- /dev/null +++ b/src/android/app/src/main/java/info/cemu/Cemu/nativeinterface/NativeGraphicPacks.java @@ -0,0 +1,98 @@ +package info.cemu.Cemu.nativeinterface; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +public class NativeGraphicPacks { + public record GraphicPackBasicInfo(long id, String virtualPath, ArrayList titleIds) { + } + + public static native ArrayList getGraphicPackBasicInfos(); + + public static class GraphicPackPreset { + private final long graphicPackId; + private final String category; + private final ArrayList presets; + private String activePreset; + + @Override + public int hashCode() { + return Objects.hash(graphicPackId, category, presets, activePreset); + } + + @Override + public boolean equals(Object object) { + if (object == null) return false; + if (object == this) return true; + if (object instanceof GraphicPackPreset preset) + return this.hashCode() == preset.hashCode(); + return false; + } + + public GraphicPackPreset(long graphicPackId, String category, ArrayList presets, String activePreset) { + this.graphicPackId = graphicPackId; + this.category = category; + this.presets = presets; + this.activePreset = activePreset; + } + + public String getActivePreset() { + return activePreset; + } + + public void setActivePreset(String activePreset) { + if (presets.stream().noneMatch(s -> s.equals(activePreset))) + throw new IllegalArgumentException("Trying to set an invalid preset: " + activePreset); + setGraphicPackActivePreset(graphicPackId, category, activePreset); + this.activePreset = activePreset; + } + + public String getCategory() { + return category; + } + + public ArrayList getPresets() { + return presets; + } + } + + public static class GraphicPack { + public final long id; + protected boolean active; + public final String name; + public final String description; + public List presets; + + public GraphicPack(long id, boolean active, String name, String description, ArrayList presets) { + this.id = id; + this.active = active; + this.name = name; + this.description = description; + this.presets = presets; + } + + public boolean isActive() { + return active; + } + + public void reloadPresets() { + presets = NativeGraphicPacks.getGraphicPackPresets(id); + } + + public void setActive(boolean active) { + this.active = active; + setGraphicPackActive(id, active); + } + } + + public static native void refreshGraphicPacks(); + + public static native GraphicPack getGraphicPack(long id); + + public static native void setGraphicPackActive(long id, boolean active); + + public static native void setGraphicPackActivePreset(long id, String category, String preset); + + public static native ArrayList getGraphicPackPresets(long id); +} diff --git a/src/android/app/src/main/java/info/cemu/Cemu/nativeinterface/NativeInput.java b/src/android/app/src/main/java/info/cemu/Cemu/nativeinterface/NativeInput.java new file mode 100644 index 00000000..a458b52e --- /dev/null +++ b/src/android/app/src/main/java/info/cemu/Cemu/nativeinterface/NativeInput.java @@ -0,0 +1,169 @@ +package info.cemu.Cemu.nativeinterface; + +import java.util.Map; + +public class NativeInput { + public static final int VPAD_BUTTON_NONE = 0; + public static final int VPAD_BUTTON_A = 1; + public static final int VPAD_BUTTON_B = 2; + public static final int VPAD_BUTTON_X = 3; + public static final int VPAD_BUTTON_Y = 4; + public static final int VPAD_BUTTON_L = 5; + public static final int VPAD_BUTTON_R = 6; + public static final int VPAD_BUTTON_ZL = 7; + public static final int VPAD_BUTTON_ZR = 8; + public static final int VPAD_BUTTON_PLUS = 9; + public static final int VPAD_BUTTON_MINUS = 10; + public static final int VPAD_BUTTON_UP = 11; + public static final int VPAD_BUTTON_DOWN = 12; + public static final int VPAD_BUTTON_LEFT = 13; + public static final int VPAD_BUTTON_RIGHT = 14; + public static final int VPAD_BUTTON_STICKL = 15; + public static final int VPAD_BUTTON_STICKR = 16; + public static final int VPAD_BUTTON_STICKL_UP = 17; + public static final int VPAD_BUTTON_STICKL_DOWN = 18; + public static final int VPAD_BUTTON_STICKL_LEFT = 19; + public static final int VPAD_BUTTON_STICKL_RIGHT = 20; + public static final int VPAD_BUTTON_STICKR_UP = 21; + public static final int VPAD_BUTTON_STICKR_DOWN = 22; + public static final int VPAD_BUTTON_STICKR_LEFT = 23; + public static final int VPAD_BUTTON_STICKR_RIGHT = 24; + public static final int VPAD_BUTTON_MIC = 25; + public static final int VPAD_BUTTON_SCREEN = 26; + public static final int VPAD_BUTTON_HOME = 27; + public static final int VPAD_BUTTON_MAX = 28; + + public static final int PRO_BUTTON_NONE = 0; + public static final int PRO_BUTTON_A = 1; + public static final int PRO_BUTTON_B = 2; + public static final int PRO_BUTTON_X = 3; + public static final int PRO_BUTTON_Y = 4; + public static final int PRO_BUTTON_L = 5; + public static final int PRO_BUTTON_R = 6; + public static final int PRO_BUTTON_ZL = 7; + public static final int PRO_BUTTON_ZR = 8; + public static final int PRO_BUTTON_PLUS = 9; + public static final int PRO_BUTTON_MINUS = 10; + public static final int PRO_BUTTON_HOME = 11; + public static final int PRO_BUTTON_UP = 12; + public static final int PRO_BUTTON_DOWN = 13; + public static final int PRO_BUTTON_LEFT = 14; + public static final int PRO_BUTTON_RIGHT = 15; + public static final int PRO_BUTTON_STICKL = 16; + public static final int PRO_BUTTON_STICKR = 17; + public static final int PRO_BUTTON_STICKL_UP = 18; + public static final int PRO_BUTTON_STICKL_DOWN = 19; + public static final int PRO_BUTTON_STICKL_LEFT = 20; + public static final int PRO_BUTTON_STICKL_RIGHT = 21; + public static final int PRO_BUTTON_STICKR_UP = 22; + public static final int PRO_BUTTON_STICKR_DOWN = 23; + public static final int PRO_BUTTON_STICKR_LEFT = 24; + public static final int PRO_BUTTON_STICKR_RIGHT = 25; + public static final int PRO_BUTTON_MAX = 26; + + public static final int CLASSIC_BUTTON_NONE = 0; + public static final int CLASSIC_BUTTON_A = 1; + public static final int CLASSIC_BUTTON_B = 2; + public static final int CLASSIC_BUTTON_X = 3; + public static final int CLASSIC_BUTTON_Y = 4; + public static final int CLASSIC_BUTTON_L = 5; + public static final int CLASSIC_BUTTON_R = 6; + public static final int CLASSIC_BUTTON_ZL = 7; + public static final int CLASSIC_BUTTON_ZR = 8; + public static final int CLASSIC_BUTTON_PLUS = 9; + public static final int CLASSIC_BUTTON_MINUS = 10; + public static final int CLASSIC_BUTTON_HOME = 11; + public static final int CLASSIC_BUTTON_UP = 12; + public static final int CLASSIC_BUTTON_DOWN = 13; + public static final int CLASSIC_BUTTON_LEFT = 14; + public static final int CLASSIC_BUTTON_RIGHT = 15; + public static final int CLASSIC_BUTTON_STICKL_UP = 16; + public static final int CLASSIC_BUTTON_STICKL_DOWN = 17; + public static final int CLASSIC_BUTTON_STICKL_LEFT = 18; + public static final int CLASSIC_BUTTON_STICKL_RIGHT = 19; + public static final int CLASSIC_BUTTON_STICKR_UP = 20; + public static final int CLASSIC_BUTTON_STICKR_DOWN = 21; + public static final int CLASSIC_BUTTON_STICKR_LEFT = 22; + public static final int CLASSIC_BUTTON_STICKR_RIGHT = 23; + public static final int CLASSIC_BUTTON_MAX = 24; + + public static final int WIIMOTE_BUTTON_NONE = 0; + public static final int WIIMOTE_BUTTON_A = 1; + public static final int WIIMOTE_BUTTON_B = 2; + public static final int WIIMOTE_BUTTON_1 = 3; + public static final int WIIMOTE_BUTTON_2 = 4; + public static final int WIIMOTE_BUTTON_NUNCHUCK_Z = 5; + public static final int WIIMOTE_BUTTON_NUNCHUCK_C = 6; + public static final int WIIMOTE_BUTTON_PLUS = 7; + public static final int WIIMOTE_BUTTON_MINUS = 8; + public static final int WIIMOTE_BUTTON_UP = 9; + public static final int WIIMOTE_BUTTON_DOWN = 10; + public static final int WIIMOTE_BUTTON_LEFT = 11; + public static final int WIIMOTE_BUTTON_RIGHT = 12; + public static final int WIIMOTE_BUTTON_NUNCHUCK_UP = 13; + public static final int WIIMOTE_BUTTON_NUNCHUCK_DOWN = 14; + public static final int WIIMOTE_BUTTON_NUNCHUCK_LEFT = 15; + public static final int WIIMOTE_BUTTON_NUNCHUCK_RIGHT = 16; + public static final int WIIMOTE_BUTTON_HOME = 17; + public static final int WIIMOTE_BUTTON_MAX = 18; + + public static final int EMULATED_CONTROLLER_TYPE_VPAD = 0; + public static final int EMULATED_CONTROLLER_TYPE_PRO = 1; + public static final int EMULATED_CONTROLLER_TYPE_CLASSIC = 2; + public static final int EMULATED_CONTROLLER_TYPE_WIIMOTE = 3; + public static final int EMULATED_CONTROLLER_TYPE_DISABLED = -1; + + public static final int DPAD_UP = 34; + public static final int DPAD_DOWN = 35; + public static final int DPAD_LEFT = 36; + public static final int DPAD_RIGHT = 37; + public static final int AXIS_X_POS = 38; + public static final int AXIS_Y_POS = 39; + public static final int ROTATION_X_POS = 40; + public static final int ROTATION_Y_POS = 41; + public static final int TRIGGER_X_POS = 42; + public static final int TRIGGER_Y_POS = 43; + public static final int AXIS_X_NEG = 44; + public static final int AXIS_Y_NEG = 45; + public static final int ROTATION_X_NEG = 46; + public static final int ROTATION_Y_NEG = 47; + + public static final int MAX_CONTROLLERS = 8; + public static final int MAX_VPAD_CONTROLLERS = 2; + public static final int MAX_WPAD_CONTROLLERS = 7; + + public static native void onNativeKey(String deviceDescriptor, String deviceName, int key, boolean isPressed); + + public static native void onNativeAxis(String deviceDescriptor, String deviceName, int axis, float value); + + public static native void setControllerType(int index, int emulatedControllerType); + + public static native boolean isControllerDisabled(int index); + + public static native int getControllerType(int index); + + public static native int getWPADControllersCount(); + + public static native int getVPADControllersCount(); + + public static native void setControllerMapping(String deviceDescriptor, String deviceName, int index, int mappingId, int buttonId); + + public static native void clearControllerMapping(int index, int mappingId); + + public static native String getControllerMapping(int index, int mappingId); + + public static native Map getControllerMappings(int index); + + public static native void onTouchDown(int x, int y, boolean isTV); + + public static native void onTouchMove(int x, int y, boolean isTV); + + public static native void onTouchUp(int x, int y, boolean isTV); + + public static native void onMotion(long timestamp, float gyroX, float gyroY, float gyroZ, float accelX, float accelY, float accelZ); + + public static native void setMotionEnabled(boolean motionEnabled); + public static native void onOverlayButton(int controllerIndex, int mappingId, boolean value); + + public static native void onOverlayAxis(int controllerIndex, int mappingId, float value); +} diff --git a/src/android/app/src/main/java/info/cemu/Cemu/nativeinterface/NativeSettings.java b/src/android/app/src/main/java/info/cemu/Cemu/nativeinterface/NativeSettings.java new file mode 100644 index 00000000..f8921ffd --- /dev/null +++ b/src/android/app/src/main/java/info/cemu/Cemu/nativeinterface/NativeSettings.java @@ -0,0 +1,98 @@ +package info.cemu.Cemu.nativeinterface; + +import java.util.ArrayList; + +public class NativeSettings { + public static native void addGamesPath(String uri); + + public static native void removeGamesPath(String uri); + + public static native ArrayList getGamesPaths(); + + public static native boolean getAsyncShaderCompile(); + + public static native void setAsyncShaderCompile(boolean enabled); + + public static final int VSYNC_MODE_OFF = 0; + public static final int VSYNC_MODE_DOUBLE_BUFFERING = 1; + public static final int VSYNC_MODE_TRIPLE_BUFFERING = 2; + + public static native int getVSyncMode(); + + public static native void setVSyncMode(int vsyncMode); + + public static native boolean getAccurateBarriers(); + + public static native void setAccurateBarriers(boolean enabled); + + public static native boolean getAudioDeviceEnabled(boolean tv); + + public static native void setAudioDeviceEnabled(boolean enabled, boolean tv); + + public static final int AUDIO_CHANNELS_MONO = 0; + public static final int AUDIO_CHANNELS_STEREO = 1; + public static final int AUDIO_CHANNELS_SURROUND = 2; + + public static native void setAudioDeviceChannels(int channels, boolean tv); + + public static native int getAudioDeviceChannels(boolean tv); + + public static final int AUDIO_MIN_VOLUME = 0; + public static final int AUDIO_MAX_VOLUME = 100; + + public static native void setAudioDeviceVolume(int volume, boolean tv); + + public static native int getAudioDeviceVolume(boolean tv); + + public static final int OVERLAY_SCREEN_POSITION_DISABLED = 0; + public static final int OVERLAY_SCREEN_POSITION_TOP_LEFT = 1; + public static final int OVERLAY_SCREEN_POSITION_TOP_CENTER = 2; + public static final int OVERLAY_SCREEN_POSITION_TOP_RIGHT = 3; + public static final int OVERLAY_SCREEN_POSITION_BOTTOM_LEFT = 4; + public static final int OVERLAY_SCREEN_POSITION_BOTTOM_CENTER = 5; + public static final int OVERLAY_SCREEN_POSITION_BOTTOM_RIGHT = 6; + + public static native int getOverlayPosition(); + + public static native void setOverlayPosition(int position); + + public static native boolean isOverlayFPSEnabled(); + + public static native void setOverlayFPSEnabled(boolean enabled); + + public static native boolean isOverlayDrawCallsPerFrameEnabled(); + + public static native void setOverlayDrawCallsPerFrameEnabled(boolean enabled); + + public static native boolean isOverlayCPUUsageEnabled(); + + public static native void setOverlayCPUUsageEnabled(boolean enabled); + + public static native boolean isOverlayCPUPerCoreUsageEnabled(); + + public static native void setOverlayCPUPerCoreUsageEnabled(boolean enabled); + + public static native boolean isOverlayRAMUsageEnabled(); + + public static native void setOverlayRAMUsageEnabled(boolean enabled); + + public static native boolean isOverlayDebugEnabled(); + + public static native void setOverlayDebugEnabled(boolean enabled); + + public static native int getNotificationsPosition(); + + public static native void setNotificationsPosition(int position); + + public static native boolean isNotificationControllerProfilesEnabled(); + + public static native void setNotificationControllerProfilesEnabled(boolean enabled); + + public static native boolean isNotificationShaderCompilerEnabled(); + + public static native void setNotificationShaderCompilerEnabled(boolean enabled); + + public static native boolean isNotificationFriendListEnabled(); + + public static native void setNotificationFriendListEnabled(boolean enabled); +} diff --git a/src/android/app/src/main/java/info/cemu/Cemu/settings/audio/AudioSettingsFragment.java b/src/android/app/src/main/java/info/cemu/Cemu/settings/audio/AudioSettingsFragment.java index d90e8234..edf4212c 100644 --- a/src/android/app/src/main/java/info/cemu/Cemu/settings/audio/AudioSettingsFragment.java +++ b/src/android/app/src/main/java/info/cemu/Cemu/settings/audio/AudioSettingsFragment.java @@ -19,15 +19,15 @@ import info.cemu.Cemu.guibasecomponents.GenericRecyclerViewAdapter; import info.cemu.Cemu.guibasecomponents.SelectionAdapter; import info.cemu.Cemu.guibasecomponents.SingleSelectionRecyclerViewItem; import info.cemu.Cemu.guibasecomponents.SliderRecyclerViewItem; -import info.cemu.Cemu.NativeLibrary; +import info.cemu.Cemu.nativeinterface.NativeSettings; public class AudioSettingsFragment extends Fragment { private static int channelsToResourceNameId(int channels) { return switch (channels) { - case NativeLibrary.AUDIO_CHANNELS_MONO -> R.string.mono; - case NativeLibrary.AUDIO_CHANNELS_STEREO -> R.string.stereo; - case NativeLibrary.AUDIO_CHANNELS_SURROUND -> R.string.surround; + case NativeSettings.AUDIO_CHANNELS_MONO -> R.string.mono; + case NativeSettings.AUDIO_CHANNELS_STEREO -> R.string.stereo; + case NativeSettings.AUDIO_CHANNELS_SURROUND -> R.string.surround; default -> throw new IllegalArgumentException("Invalid channels type: " + channels); }; } @@ -38,52 +38,52 @@ public class AudioSettingsFragment extends Fragment { GenericRecyclerViewAdapter genericRecyclerViewAdapter = new GenericRecyclerViewAdapter(); CheckboxRecyclerViewItem tvDeviceCheckbox = new CheckboxRecyclerViewItem(getString(R.string.tv), - getString(R.string.tv_audio_description), NativeLibrary.getAudioDeviceEnabled(true), - checked -> NativeLibrary.setAudioDeviceEnabled(checked, true)); + getString(R.string.tv_audio_description), NativeSettings.getAudioDeviceEnabled(true), + checked -> NativeSettings.setAudioDeviceEnabled(checked, true)); genericRecyclerViewAdapter.addRecyclerViewItem(tvDeviceCheckbox); - var tvChannelsChoices = Stream.of(NativeLibrary.AUDIO_CHANNELS_MONO, NativeLibrary.AUDIO_CHANNELS_STEREO, NativeLibrary.AUDIO_CHANNELS_SURROUND) + var tvChannelsChoices = Stream.of(NativeSettings.AUDIO_CHANNELS_MONO, NativeSettings.AUDIO_CHANNELS_STEREO, NativeSettings.AUDIO_CHANNELS_SURROUND) .map(channels -> new SelectionAdapter.ChoiceItem<>(t -> t.setText(channelsToResourceNameId(channels)), channels)) .collect(Collectors.toList()); - int tvChannels = NativeLibrary.getAudioDeviceChannels(true); + int tvChannels = NativeSettings.getAudioDeviceChannels(true); SelectionAdapter tvChannelsSelectionAdapter = new SelectionAdapter<>(tvChannelsChoices, tvChannels); SingleSelectionRecyclerViewItem tvChannelsModeSelection = new SingleSelectionRecyclerViewItem<>(getString(R.string.tv_channels), getString(channelsToResourceNameId(tvChannels)), tvChannelsSelectionAdapter, (channels, selectionRecyclerViewItem) -> { - NativeLibrary.setAudioDeviceChannels(channels, true); + NativeSettings.setAudioDeviceChannels(channels, true); selectionRecyclerViewItem.setDescription(getString(channelsToResourceNameId(channels))); }); genericRecyclerViewAdapter.addRecyclerViewItem(tvChannelsModeSelection); SliderRecyclerViewItem tvVolumeSlider = new SliderRecyclerViewItem(getString(R.string.tv_volume), - NativeLibrary.AUDIO_MIN_VOLUME, - NativeLibrary.AUDIO_MAX_VOLUME, - NativeLibrary.getAudioDeviceVolume(true), - value -> NativeLibrary.setAudioDeviceVolume((int) value, true), + NativeSettings.AUDIO_MIN_VOLUME, + NativeSettings.AUDIO_MAX_VOLUME, + NativeSettings.getAudioDeviceVolume(true), + value -> NativeSettings.setAudioDeviceVolume((int) value, true), value -> (int) value + "%"); genericRecyclerViewAdapter.addRecyclerViewItem(tvVolumeSlider); CheckboxRecyclerViewItem padDeviceCheckbox = new CheckboxRecyclerViewItem(getString(R.string.gamepad), - getString(R.string.gamepad_audio_description), NativeLibrary.getAudioDeviceEnabled(false), - checked -> NativeLibrary.setAudioDeviceEnabled(checked, false)); + getString(R.string.gamepad_audio_description), NativeSettings.getAudioDeviceEnabled(false), + checked -> NativeSettings.setAudioDeviceEnabled(checked, false)); genericRecyclerViewAdapter.addRecyclerViewItem(padDeviceCheckbox); - var gamepadChannelsChoices = List.of(new SelectionAdapter.ChoiceItem<>(t -> t.setText(channelsToResourceNameId(NativeLibrary.AUDIO_CHANNELS_STEREO)), NativeLibrary.AUDIO_CHANNELS_STEREO)); - int gamepadChannels = NativeLibrary.getAudioDeviceChannels(false); + var gamepadChannelsChoices = List.of(new SelectionAdapter.ChoiceItem<>(t -> t.setText(channelsToResourceNameId(NativeSettings.AUDIO_CHANNELS_STEREO)), NativeSettings.AUDIO_CHANNELS_STEREO)); + int gamepadChannels = NativeSettings.getAudioDeviceChannels(false); SelectionAdapter gamepadChannelsSelectionAdapter = new SelectionAdapter<>(gamepadChannelsChoices, gamepadChannels); SingleSelectionRecyclerViewItem gamepadChannelsModeSelection = new SingleSelectionRecyclerViewItem<>(getString(R.string.gamepad_channels), getString(channelsToResourceNameId(gamepadChannels)), gamepadChannelsSelectionAdapter, (channels, selectionRecyclerViewItem) -> { - NativeLibrary.setAudioDeviceChannels(channels, false); + NativeSettings.setAudioDeviceChannels(channels, false); selectionRecyclerViewItem.setDescription(getString(channelsToResourceNameId(channels))); }); genericRecyclerViewAdapter.addRecyclerViewItem(gamepadChannelsModeSelection); SliderRecyclerViewItem padVolumeSlider = new SliderRecyclerViewItem(getString(R.string.pad_volume), - NativeLibrary.AUDIO_MIN_VOLUME, - NativeLibrary.AUDIO_MAX_VOLUME, - NativeLibrary.getAudioDeviceVolume(false), - value -> NativeLibrary.setAudioDeviceVolume((int) value, false), + NativeSettings.AUDIO_MIN_VOLUME, + NativeSettings.AUDIO_MAX_VOLUME, + NativeSettings.getAudioDeviceVolume(false), + value -> NativeSettings.setAudioDeviceVolume((int) value, false), value -> (int) value + "%"); genericRecyclerViewAdapter.addRecyclerViewItem(padVolumeSlider); diff --git a/src/android/app/src/main/java/info/cemu/Cemu/settings/gamespath/GamePathsFragment.java b/src/android/app/src/main/java/info/cemu/Cemu/settings/gamespath/GamePathsFragment.java index 98edc1a1..16937882 100644 --- a/src/android/app/src/main/java/info/cemu/Cemu/settings/gamespath/GamePathsFragment.java +++ b/src/android/app/src/main/java/info/cemu/Cemu/settings/gamespath/GamePathsFragment.java @@ -27,7 +27,7 @@ import java.util.Objects; import java.util.stream.Collectors; import java.util.stream.Stream; -import info.cemu.Cemu.NativeLibrary; +import info.cemu.Cemu.nativeinterface.NativeSettings; import info.cemu.Cemu.R; import info.cemu.Cemu.databinding.GenericRecyclerViewLayoutBinding; @@ -56,12 +56,12 @@ public class GamePathsFragment extends Fragment { Toast.makeText(requireContext(), R.string.game_path_already_added, Toast.LENGTH_LONG).show(); return; } - NativeLibrary.addGamesPath(gamesPath); + NativeSettings.addGamesPath(gamesPath); gamesPaths = Stream.concat(Stream.of(gamesPath), gamesPaths.stream()).collect(Collectors.toList()); gamePathAdapter.submitList(gamesPaths); }); gamePathAdapter = new GamePathAdapter(path -> { - NativeLibrary.removeGamesPath(path); + NativeSettings.removeGamesPath(path); gamesPaths = gamesPaths.stream().filter(p -> !p.equals(path)).collect(Collectors.toList()); gamePathAdapter.submitList(gamesPaths); }); @@ -71,7 +71,7 @@ public class GamePathsFragment extends Fragment { public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { GenericRecyclerViewLayoutBinding binding = GenericRecyclerViewLayoutBinding.inflate(inflater, container, false); binding.recyclerView.setAdapter(gamePathAdapter); - gamesPaths = NativeLibrary.getGamesPaths(); + gamesPaths = NativeSettings.getGamesPaths(); gamePathAdapter.submitList(gamesPaths); requireActivity().addMenuProvider(new MenuProvider() { @Override diff --git a/src/android/app/src/main/java/info/cemu/Cemu/settings/graphicpacks/GraphicPackRecyclerViewItem.java b/src/android/app/src/main/java/info/cemu/Cemu/settings/graphicpacks/GraphicPackRecyclerViewItem.java index b3f24af6..3238baa8 100644 --- a/src/android/app/src/main/java/info/cemu/Cemu/settings/graphicpacks/GraphicPackRecyclerViewItem.java +++ b/src/android/app/src/main/java/info/cemu/Cemu/settings/graphicpacks/GraphicPackRecyclerViewItem.java @@ -11,7 +11,7 @@ import com.google.android.material.checkbox.MaterialCheckBox; import info.cemu.Cemu.R; import info.cemu.Cemu.guibasecomponents.RecyclerViewItem; -import info.cemu.Cemu.NativeLibrary; +import info.cemu.Cemu.nativeinterface.NativeGraphicPacks; public class GraphicPackRecyclerViewItem implements RecyclerViewItem { private static class GraphicPackViewHolder extends RecyclerView.ViewHolder { @@ -28,9 +28,9 @@ public class GraphicPackRecyclerViewItem implements RecyclerViewItem { } - private final NativeLibrary.GraphicPack graphicPack; + private final NativeGraphicPacks.GraphicPack graphicPack; - public GraphicPackRecyclerViewItem(NativeLibrary.GraphicPack graphicPack) { + public GraphicPackRecyclerViewItem(NativeGraphicPacks.GraphicPack graphicPack) { this.graphicPack = graphicPack; } diff --git a/src/android/app/src/main/java/info/cemu/Cemu/settings/graphicpacks/GraphicPacksFragment.java b/src/android/app/src/main/java/info/cemu/Cemu/settings/graphicpacks/GraphicPacksFragment.java index 82f13187..0dc789ae 100644 --- a/src/android/app/src/main/java/info/cemu/Cemu/settings/graphicpacks/GraphicPacksFragment.java +++ b/src/android/app/src/main/java/info/cemu/Cemu/settings/graphicpacks/GraphicPacksFragment.java @@ -21,7 +21,7 @@ import info.cemu.Cemu.databinding.GenericRecyclerViewLayoutBinding; import info.cemu.Cemu.guibasecomponents.GenericRecyclerViewAdapter; import info.cemu.Cemu.guibasecomponents.SingleSelectionRecyclerViewItem; import info.cemu.Cemu.guibasecomponents.StringSelectionAdapter; -import info.cemu.Cemu.NativeLibrary; +import info.cemu.Cemu.nativeinterface.NativeGraphicPacks; public class GraphicPacksFragment extends Fragment { private final GenericRecyclerViewAdapter genericRecyclerViewAdapter = new GenericRecyclerViewAdapter(); @@ -78,12 +78,12 @@ public class GraphicPacksFragment extends Fragment { private void fillData(GraphicPacksRootFragment.GraphicPackDataNode graphicPackDataNode) { genericRecyclerViewAdapter.clearRecyclerViewItems(); - var graphicPack = NativeLibrary.getGraphicPack(graphicPackDataNode.getId()); + var graphicPack = NativeGraphicPacks.getGraphicPack(graphicPackDataNode.getId()); genericRecyclerViewAdapter.addRecyclerViewItem(new GraphicPackRecyclerViewItem(graphicPack)); fillPresets(graphicPack); } - private void fillPresets(NativeLibrary.GraphicPack graphicPack) { + private void fillPresets(NativeGraphicPacks.GraphicPack graphicPack) { var recyclerViewItems = new ArrayList>(); IntStream.range(0, graphicPack.presets.size()).forEach(index -> { var graphicPackPreset = graphicPack.presets.get(index); diff --git a/src/android/app/src/main/java/info/cemu/Cemu/settings/graphicpacks/GraphicPacksRootFragment.java b/src/android/app/src/main/java/info/cemu/Cemu/settings/graphicpacks/GraphicPacksRootFragment.java index eb8e5a90..b2d9f093 100644 --- a/src/android/app/src/main/java/info/cemu/Cemu/settings/graphicpacks/GraphicPacksRootFragment.java +++ b/src/android/app/src/main/java/info/cemu/Cemu/settings/graphicpacks/GraphicPacksRootFragment.java @@ -41,10 +41,10 @@ import java.util.Optional; import info.cemu.Cemu.R; import info.cemu.Cemu.databinding.GenericRecyclerViewLayoutBinding; import info.cemu.Cemu.guibasecomponents.FilterableRecyclerViewAdapter; -import info.cemu.Cemu.guibasecomponents.GenericRecyclerViewAdapter; -import info.cemu.Cemu.NativeLibrary; -import info.cemu.Cemu.utils.FileUtil; -import info.cemu.Cemu.utils.ZipUtil; +import info.cemu.Cemu.nativeinterface.FileCallbacks; +import info.cemu.Cemu.nativeinterface.NativeGameTitles; +import info.cemu.Cemu.nativeinterface.NativeGraphicPacks; +import info.cemu.Cemu.zip.Zip; import okhttp3.Call; import okhttp3.Callback; import okhttp3.OkHttpClient; @@ -144,7 +144,7 @@ public class GraphicPacksRootFragment extends Fragment { } } - private final ArrayList installedTitleIds = NativeLibrary.getInstalledGamesTitleIds(); + private final ArrayList installedTitleIds = NativeGameTitles.getInstalledGamesTitleIds(); private final GraphicPackSectionNode graphicPackSectionRootNode = new GraphicPackSectionNode(); private final FilterableRecyclerViewAdapter genericRecyclerViewAdapter = new FilterableRecyclerViewAdapter<>(); private GraphicPackViewModel graphicPackViewModel; @@ -240,7 +240,7 @@ public class GraphicPacksRootFragment extends Fragment { } private void fillGraphicPacks() { - var nativeGraphicPacks = NativeLibrary.getGraphicPackBasicInfos(); + var nativeGraphicPacks = NativeGraphicPacks.getGraphicPackBasicInfos(); graphicPackSectionRootNode.clear(); List graphicPackDataNodes = new ArrayList<>(); nativeGraphicPacks.forEach(graphicPack -> { @@ -329,13 +329,13 @@ public class GraphicPacksRootFragment extends Fragment { public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException { try (ResponseBody responseBody = response.body()) { Path graphicPacksTempDirPath = graphicPacksDirPath.resolve("downloadedGraphicPacksTemp"); - FileUtil.delete(graphicPacksTempDirPath); - ZipUtil.unzip(Objects.requireNonNull(responseBody).byteStream(), graphicPacksTempDirPath.toString()); + FileCallbacks.delete(graphicPacksTempDirPath); + Zip.unzip(Objects.requireNonNull(responseBody).byteStream(), graphicPacksTempDirPath.toString()); Files.write(graphicPacksTempDirPath.resolve("version.txt"), version.getBytes(StandardCharsets.UTF_8)); Path downloadedGraphicPacksDirPath = graphicPacksDirPath.resolve("downloadedGraphicPacks"); - FileUtil.delete(downloadedGraphicPacksDirPath); + FileCallbacks.delete(downloadedGraphicPacksDirPath); Files.move(graphicPacksTempDirPath, downloadedGraphicPacksDirPath); - NativeLibrary.refreshGraphicPacks(); + NativeGraphicPacks.refreshGraphicPacks(); requireActivity().runOnUiThread(() -> fillGraphicPacks()); onDownloadFinish(dialog); } diff --git a/src/android/app/src/main/java/info/cemu/Cemu/settings/graphics/GraphicsSettingsFragment.java b/src/android/app/src/main/java/info/cemu/Cemu/settings/graphics/GraphicsSettingsFragment.java index f1653508..3f0e0921 100644 --- a/src/android/app/src/main/java/info/cemu/Cemu/settings/graphics/GraphicsSettingsFragment.java +++ b/src/android/app/src/main/java/info/cemu/Cemu/settings/graphics/GraphicsSettingsFragment.java @@ -6,7 +6,6 @@ import android.view.View; import android.view.ViewGroup; import androidx.annotation.NonNull; -import androidx.annotation.StringRes; import androidx.fragment.app.Fragment; import java.util.stream.Collectors; @@ -18,14 +17,14 @@ import info.cemu.Cemu.guibasecomponents.CheckboxRecyclerViewItem; import info.cemu.Cemu.guibasecomponents.GenericRecyclerViewAdapter; import info.cemu.Cemu.guibasecomponents.SelectionAdapter; import info.cemu.Cemu.guibasecomponents.SingleSelectionRecyclerViewItem; -import info.cemu.Cemu.NativeLibrary; +import info.cemu.Cemu.nativeinterface.NativeSettings; public class GraphicsSettingsFragment extends Fragment { private static int vsyncModeToResourceNameId(int vsyncMode) { return switch (vsyncMode) { - case NativeLibrary.VSYNC_MODE_OFF -> R.string.off; - case NativeLibrary.VSYNC_MODE_DOUBLE_BUFFERING -> R.string.double_buffering; - case NativeLibrary.VSYNC_MODE_TRIPLE_BUFFERING -> R.string.triple_buffering; + case NativeSettings.VSYNC_MODE_OFF -> R.string.off; + case NativeSettings.VSYNC_MODE_DOUBLE_BUFFERING -> R.string.double_buffering; + case NativeSettings.VSYNC_MODE_TRIPLE_BUFFERING -> R.string.triple_buffering; default -> throw new IllegalArgumentException("Invalid vsync mode: " + vsyncMode); }; } @@ -36,23 +35,23 @@ public class GraphicsSettingsFragment extends Fragment { GenericRecyclerViewAdapter genericRecyclerViewAdapter = new GenericRecyclerViewAdapter(); - CheckboxRecyclerViewItem asyncShaderCheckbox = new CheckboxRecyclerViewItem(getString(R.string.async_shader_compile), getString(R.string.async_shader_compile_description), NativeLibrary.getAsyncShaderCompile(), NativeLibrary::setAsyncShaderCompile); + CheckboxRecyclerViewItem asyncShaderCheckbox = new CheckboxRecyclerViewItem(getString(R.string.async_shader_compile), getString(R.string.async_shader_compile_description), NativeSettings.getAsyncShaderCompile(), NativeSettings::setAsyncShaderCompile); genericRecyclerViewAdapter.addRecyclerViewItem(asyncShaderCheckbox); - int vsyncMode = NativeLibrary.getVSyncMode(); - var vsyncChoices = Stream.of(NativeLibrary.VSYNC_MODE_OFF, NativeLibrary.VSYNC_MODE_DOUBLE_BUFFERING, NativeLibrary.VSYNC_MODE_TRIPLE_BUFFERING) + int vsyncMode = NativeSettings.getVSyncMode(); + var vsyncChoices = Stream.of(NativeSettings.VSYNC_MODE_OFF, NativeSettings.VSYNC_MODE_DOUBLE_BUFFERING, NativeSettings.VSYNC_MODE_TRIPLE_BUFFERING) .map(vsync -> new SelectionAdapter.ChoiceItem<>(t -> t.setText(vsyncModeToResourceNameId(vsync)), vsync)) .collect(Collectors.toList()); SelectionAdapter vsyncSelectionAdapter = new SelectionAdapter<>(vsyncChoices, vsyncMode); SingleSelectionRecyclerViewItem vsyncModeSelection = new SingleSelectionRecyclerViewItem<>(getString(R.string.vsync), getString(vsyncModeToResourceNameId(vsyncMode)), vsyncSelectionAdapter, (vsync, selectionRecyclerViewItem) -> { - NativeLibrary.setVSyncMode(vsync); + NativeSettings.setVSyncMode(vsync); selectionRecyclerViewItem.setDescription(getString(vsyncModeToResourceNameId(vsync))); }); genericRecyclerViewAdapter.addRecyclerViewItem(vsyncModeSelection); - CheckboxRecyclerViewItem accurateBarriersCheckbox = new CheckboxRecyclerViewItem(getString(R.string.accurate_barriers), getString(R.string.accurate_barriers_description), NativeLibrary.getAccurateBarriers(), NativeLibrary::setAccurateBarriers); + CheckboxRecyclerViewItem accurateBarriersCheckbox = new CheckboxRecyclerViewItem(getString(R.string.accurate_barriers), getString(R.string.accurate_barriers_description), NativeSettings.getAccurateBarriers(), NativeSettings::setAccurateBarriers); genericRecyclerViewAdapter.addRecyclerViewItem(accurateBarriersCheckbox); binding.recyclerView.setAdapter(genericRecyclerViewAdapter); diff --git a/src/android/app/src/main/java/info/cemu/Cemu/settings/input/ControllerInputsDataProvider.java b/src/android/app/src/main/java/info/cemu/Cemu/settings/input/ControllerInputsDataProvider.java index e2b7e05d..377be6d3 100644 --- a/src/android/app/src/main/java/info/cemu/Cemu/settings/input/ControllerInputsDataProvider.java +++ b/src/android/app/src/main/java/info/cemu/Cemu/settings/input/ControllerInputsDataProvider.java @@ -6,122 +6,122 @@ import java.util.Map; import java.util.stream.Collectors; import info.cemu.Cemu.R; -import info.cemu.Cemu.NativeLibrary; +import info.cemu.Cemu.nativeinterface.NativeInput; public class ControllerInputsDataProvider { private int getButtonResourceIdName(int controllerType, int buttonId) { - if (controllerType == NativeLibrary.EMULATED_CONTROLLER_TYPE_VPAD) { + if (controllerType == NativeInput.EMULATED_CONTROLLER_TYPE_VPAD) { return switch (buttonId) { - case NativeLibrary.VPAD_BUTTON_A -> R.string.button_a; - case NativeLibrary.VPAD_BUTTON_B -> R.string.button_b; - case NativeLibrary.VPAD_BUTTON_X -> R.string.button_x; - case NativeLibrary.VPAD_BUTTON_Y -> R.string.button_y; - case NativeLibrary.VPAD_BUTTON_L -> R.string.button_l; - case NativeLibrary.VPAD_BUTTON_R -> R.string.button_r; - case NativeLibrary.VPAD_BUTTON_ZL -> R.string.button_zl; - case NativeLibrary.VPAD_BUTTON_ZR -> R.string.button_zr; - case NativeLibrary.VPAD_BUTTON_PLUS -> R.string.button_plus; - case NativeLibrary.VPAD_BUTTON_MINUS -> R.string.button_minus; - case NativeLibrary.VPAD_BUTTON_UP -> R.string.button_up; - case NativeLibrary.VPAD_BUTTON_DOWN -> R.string.button_down; - case NativeLibrary.VPAD_BUTTON_LEFT -> R.string.button_left; - case NativeLibrary.VPAD_BUTTON_RIGHT -> R.string.button_right; - case NativeLibrary.VPAD_BUTTON_STICKL -> R.string.button_stickl; - case NativeLibrary.VPAD_BUTTON_STICKR -> R.string.button_stickr; - case NativeLibrary.VPAD_BUTTON_STICKL_UP -> R.string.button_stickl_up; - case NativeLibrary.VPAD_BUTTON_STICKL_DOWN -> R.string.button_stickl_down; - case NativeLibrary.VPAD_BUTTON_STICKL_LEFT -> R.string.button_stickl_left; - case NativeLibrary.VPAD_BUTTON_STICKL_RIGHT -> R.string.button_stickl_right; - case NativeLibrary.VPAD_BUTTON_STICKR_UP -> R.string.button_stickr_up; - case NativeLibrary.VPAD_BUTTON_STICKR_DOWN -> R.string.button_stickr_down; - case NativeLibrary.VPAD_BUTTON_STICKR_LEFT -> R.string.button_stickr_left; - case NativeLibrary.VPAD_BUTTON_STICKR_RIGHT -> R.string.button_stickr_right; - case NativeLibrary.VPAD_BUTTON_MIC -> R.string.button_mic; - case NativeLibrary.VPAD_BUTTON_SCREEN -> R.string.button_screen; - case NativeLibrary.VPAD_BUTTON_HOME -> R.string.button_home; + case NativeInput.VPAD_BUTTON_A -> R.string.button_a; + case NativeInput.VPAD_BUTTON_B -> R.string.button_b; + case NativeInput.VPAD_BUTTON_X -> R.string.button_x; + case NativeInput.VPAD_BUTTON_Y -> R.string.button_y; + case NativeInput.VPAD_BUTTON_L -> R.string.button_l; + case NativeInput.VPAD_BUTTON_R -> R.string.button_r; + case NativeInput.VPAD_BUTTON_ZL -> R.string.button_zl; + case NativeInput.VPAD_BUTTON_ZR -> R.string.button_zr; + case NativeInput.VPAD_BUTTON_PLUS -> R.string.button_plus; + case NativeInput.VPAD_BUTTON_MINUS -> R.string.button_minus; + case NativeInput.VPAD_BUTTON_UP -> R.string.button_up; + case NativeInput.VPAD_BUTTON_DOWN -> R.string.button_down; + case NativeInput.VPAD_BUTTON_LEFT -> R.string.button_left; + case NativeInput.VPAD_BUTTON_RIGHT -> R.string.button_right; + case NativeInput.VPAD_BUTTON_STICKL -> R.string.button_stickl; + case NativeInput.VPAD_BUTTON_STICKR -> R.string.button_stickr; + case NativeInput.VPAD_BUTTON_STICKL_UP -> R.string.button_stickl_up; + case NativeInput.VPAD_BUTTON_STICKL_DOWN -> R.string.button_stickl_down; + case NativeInput.VPAD_BUTTON_STICKL_LEFT -> R.string.button_stickl_left; + case NativeInput.VPAD_BUTTON_STICKL_RIGHT -> R.string.button_stickl_right; + case NativeInput.VPAD_BUTTON_STICKR_UP -> R.string.button_stickr_up; + case NativeInput.VPAD_BUTTON_STICKR_DOWN -> R.string.button_stickr_down; + case NativeInput.VPAD_BUTTON_STICKR_LEFT -> R.string.button_stickr_left; + case NativeInput.VPAD_BUTTON_STICKR_RIGHT -> R.string.button_stickr_right; + case NativeInput.VPAD_BUTTON_MIC -> R.string.button_mic; + case NativeInput.VPAD_BUTTON_SCREEN -> R.string.button_screen; + case NativeInput.VPAD_BUTTON_HOME -> R.string.button_home; default -> throw new IllegalArgumentException("Invalid buttonId " + buttonId + " for controllerType " + controllerType); }; } - if (controllerType == NativeLibrary.EMULATED_CONTROLLER_TYPE_PRO) { + if (controllerType == NativeInput.EMULATED_CONTROLLER_TYPE_PRO) { return switch (buttonId) { - case NativeLibrary.PRO_BUTTON_A -> R.string.button_a; - case NativeLibrary.PRO_BUTTON_B -> R.string.button_b; - case NativeLibrary.PRO_BUTTON_X -> R.string.button_x; - case NativeLibrary.PRO_BUTTON_Y -> R.string.button_y; - case NativeLibrary.PRO_BUTTON_L -> R.string.button_l; - case NativeLibrary.PRO_BUTTON_R -> R.string.button_r; - case NativeLibrary.PRO_BUTTON_ZL -> R.string.button_zl; - case NativeLibrary.PRO_BUTTON_ZR -> R.string.button_zr; - case NativeLibrary.PRO_BUTTON_PLUS -> R.string.button_plus; - case NativeLibrary.PRO_BUTTON_MINUS -> R.string.button_minus; - case NativeLibrary.PRO_BUTTON_HOME -> R.string.button_home; - case NativeLibrary.PRO_BUTTON_UP -> R.string.button_up; - case NativeLibrary.PRO_BUTTON_DOWN -> R.string.button_down; - case NativeLibrary.PRO_BUTTON_LEFT -> R.string.button_left; - case NativeLibrary.PRO_BUTTON_RIGHT -> R.string.button_right; - case NativeLibrary.PRO_BUTTON_STICKL -> R.string.button_stickl; - case NativeLibrary.PRO_BUTTON_STICKR -> R.string.button_stickr; - case NativeLibrary.PRO_BUTTON_STICKL_UP -> R.string.button_stickl_up; - case NativeLibrary.PRO_BUTTON_STICKL_DOWN -> R.string.button_stickl_down; - case NativeLibrary.PRO_BUTTON_STICKL_LEFT -> R.string.button_stickl_left; - case NativeLibrary.PRO_BUTTON_STICKL_RIGHT -> R.string.button_stickl_right; - case NativeLibrary.PRO_BUTTON_STICKR_UP -> R.string.button_stickr_up; - case NativeLibrary.PRO_BUTTON_STICKR_DOWN -> R.string.button_stickr_down; - case NativeLibrary.PRO_BUTTON_STICKR_LEFT -> R.string.button_stickr_left; - case NativeLibrary.PRO_BUTTON_STICKR_RIGHT -> R.string.button_stickr_right; + case NativeInput.PRO_BUTTON_A -> R.string.button_a; + case NativeInput.PRO_BUTTON_B -> R.string.button_b; + case NativeInput.PRO_BUTTON_X -> R.string.button_x; + case NativeInput.PRO_BUTTON_Y -> R.string.button_y; + case NativeInput.PRO_BUTTON_L -> R.string.button_l; + case NativeInput.PRO_BUTTON_R -> R.string.button_r; + case NativeInput.PRO_BUTTON_ZL -> R.string.button_zl; + case NativeInput.PRO_BUTTON_ZR -> R.string.button_zr; + case NativeInput.PRO_BUTTON_PLUS -> R.string.button_plus; + case NativeInput.PRO_BUTTON_MINUS -> R.string.button_minus; + case NativeInput.PRO_BUTTON_HOME -> R.string.button_home; + case NativeInput.PRO_BUTTON_UP -> R.string.button_up; + case NativeInput.PRO_BUTTON_DOWN -> R.string.button_down; + case NativeInput.PRO_BUTTON_LEFT -> R.string.button_left; + case NativeInput.PRO_BUTTON_RIGHT -> R.string.button_right; + case NativeInput.PRO_BUTTON_STICKL -> R.string.button_stickl; + case NativeInput.PRO_BUTTON_STICKR -> R.string.button_stickr; + case NativeInput.PRO_BUTTON_STICKL_UP -> R.string.button_stickl_up; + case NativeInput.PRO_BUTTON_STICKL_DOWN -> R.string.button_stickl_down; + case NativeInput.PRO_BUTTON_STICKL_LEFT -> R.string.button_stickl_left; + case NativeInput.PRO_BUTTON_STICKL_RIGHT -> R.string.button_stickl_right; + case NativeInput.PRO_BUTTON_STICKR_UP -> R.string.button_stickr_up; + case NativeInput.PRO_BUTTON_STICKR_DOWN -> R.string.button_stickr_down; + case NativeInput.PRO_BUTTON_STICKR_LEFT -> R.string.button_stickr_left; + case NativeInput.PRO_BUTTON_STICKR_RIGHT -> R.string.button_stickr_right; default -> throw new IllegalArgumentException("Invalid buttonId " + buttonId + " for controllerType " + controllerType); }; } - if (controllerType == NativeLibrary.EMULATED_CONTROLLER_TYPE_CLASSIC) { + if (controllerType == NativeInput.EMULATED_CONTROLLER_TYPE_CLASSIC) { return switch (buttonId) { - case NativeLibrary.CLASSIC_BUTTON_A -> R.string.button_a; - case NativeLibrary.CLASSIC_BUTTON_B -> R.string.button_b; - case NativeLibrary.CLASSIC_BUTTON_X -> R.string.button_x; - case NativeLibrary.CLASSIC_BUTTON_Y -> R.string.button_y; - case NativeLibrary.CLASSIC_BUTTON_L -> R.string.button_l; - case NativeLibrary.CLASSIC_BUTTON_R -> R.string.button_r; - case NativeLibrary.CLASSIC_BUTTON_ZL -> R.string.button_zl; - case NativeLibrary.CLASSIC_BUTTON_ZR -> R.string.button_zr; - case NativeLibrary.CLASSIC_BUTTON_PLUS -> R.string.button_plus; - case NativeLibrary.CLASSIC_BUTTON_MINUS -> R.string.button_minus; - case NativeLibrary.CLASSIC_BUTTON_HOME -> R.string.button_home; - case NativeLibrary.CLASSIC_BUTTON_UP -> R.string.button_up; - case NativeLibrary.CLASSIC_BUTTON_DOWN -> R.string.button_down; - case NativeLibrary.CLASSIC_BUTTON_LEFT -> R.string.button_left; - case NativeLibrary.CLASSIC_BUTTON_RIGHT -> R.string.button_right; - case NativeLibrary.CLASSIC_BUTTON_STICKL_UP -> R.string.button_stickl_up; - case NativeLibrary.CLASSIC_BUTTON_STICKL_DOWN -> R.string.button_stickl_down; - case NativeLibrary.CLASSIC_BUTTON_STICKL_LEFT -> R.string.button_stickl_left; - case NativeLibrary.CLASSIC_BUTTON_STICKL_RIGHT -> R.string.button_stickl_right; - case NativeLibrary.CLASSIC_BUTTON_STICKR_UP -> R.string.button_stickr_up; - case NativeLibrary.CLASSIC_BUTTON_STICKR_DOWN -> R.string.button_stickr_down; - case NativeLibrary.CLASSIC_BUTTON_STICKR_LEFT -> R.string.button_stickr_left; - case NativeLibrary.CLASSIC_BUTTON_STICKR_RIGHT -> R.string.button_stickr_right; + case NativeInput.CLASSIC_BUTTON_A -> R.string.button_a; + case NativeInput.CLASSIC_BUTTON_B -> R.string.button_b; + case NativeInput.CLASSIC_BUTTON_X -> R.string.button_x; + case NativeInput.CLASSIC_BUTTON_Y -> R.string.button_y; + case NativeInput.CLASSIC_BUTTON_L -> R.string.button_l; + case NativeInput.CLASSIC_BUTTON_R -> R.string.button_r; + case NativeInput.CLASSIC_BUTTON_ZL -> R.string.button_zl; + case NativeInput.CLASSIC_BUTTON_ZR -> R.string.button_zr; + case NativeInput.CLASSIC_BUTTON_PLUS -> R.string.button_plus; + case NativeInput.CLASSIC_BUTTON_MINUS -> R.string.button_minus; + case NativeInput.CLASSIC_BUTTON_HOME -> R.string.button_home; + case NativeInput.CLASSIC_BUTTON_UP -> R.string.button_up; + case NativeInput.CLASSIC_BUTTON_DOWN -> R.string.button_down; + case NativeInput.CLASSIC_BUTTON_LEFT -> R.string.button_left; + case NativeInput.CLASSIC_BUTTON_RIGHT -> R.string.button_right; + case NativeInput.CLASSIC_BUTTON_STICKL_UP -> R.string.button_stickl_up; + case NativeInput.CLASSIC_BUTTON_STICKL_DOWN -> R.string.button_stickl_down; + case NativeInput.CLASSIC_BUTTON_STICKL_LEFT -> R.string.button_stickl_left; + case NativeInput.CLASSIC_BUTTON_STICKL_RIGHT -> R.string.button_stickl_right; + case NativeInput.CLASSIC_BUTTON_STICKR_UP -> R.string.button_stickr_up; + case NativeInput.CLASSIC_BUTTON_STICKR_DOWN -> R.string.button_stickr_down; + case NativeInput.CLASSIC_BUTTON_STICKR_LEFT -> R.string.button_stickr_left; + case NativeInput.CLASSIC_BUTTON_STICKR_RIGHT -> R.string.button_stickr_right; default -> throw new IllegalArgumentException("Invalid buttonId " + buttonId + " for controllerType " + controllerType); }; } - if (controllerType == NativeLibrary.EMULATED_CONTROLLER_TYPE_WIIMOTE) { + if (controllerType == NativeInput.EMULATED_CONTROLLER_TYPE_WIIMOTE) { return switch (buttonId) { - case NativeLibrary.WIIMOTE_BUTTON_A -> R.string.button_a; - case NativeLibrary.WIIMOTE_BUTTON_B -> R.string.button_b; - case NativeLibrary.WIIMOTE_BUTTON_1 -> R.string.button_1; - case NativeLibrary.WIIMOTE_BUTTON_2 -> R.string.button_2; - case NativeLibrary.WIIMOTE_BUTTON_NUNCHUCK_Z -> R.string.button_nunchuck_z; - case NativeLibrary.WIIMOTE_BUTTON_NUNCHUCK_C -> R.string.button_nunchuck_c; - case NativeLibrary.WIIMOTE_BUTTON_PLUS -> R.string.button_plus; - case NativeLibrary.WIIMOTE_BUTTON_MINUS -> R.string.button_minus; - case NativeLibrary.WIIMOTE_BUTTON_UP -> R.string.button_up; - case NativeLibrary.WIIMOTE_BUTTON_DOWN -> R.string.button_down; - case NativeLibrary.WIIMOTE_BUTTON_LEFT -> R.string.button_left; - case NativeLibrary.WIIMOTE_BUTTON_RIGHT -> R.string.button_right; - case NativeLibrary.WIIMOTE_BUTTON_NUNCHUCK_UP -> R.string.button_nunchuck_up; - case NativeLibrary.WIIMOTE_BUTTON_NUNCHUCK_DOWN -> R.string.button_nunchuck_down; - case NativeLibrary.WIIMOTE_BUTTON_NUNCHUCK_LEFT -> R.string.button_nunchuck_left; - case NativeLibrary.WIIMOTE_BUTTON_NUNCHUCK_RIGHT -> R.string.button_nunchuck_right; - case NativeLibrary.WIIMOTE_BUTTON_HOME -> R.string.button_home; + case NativeInput.WIIMOTE_BUTTON_A -> R.string.button_a; + case NativeInput.WIIMOTE_BUTTON_B -> R.string.button_b; + case NativeInput.WIIMOTE_BUTTON_1 -> R.string.button_1; + case NativeInput.WIIMOTE_BUTTON_2 -> R.string.button_2; + case NativeInput.WIIMOTE_BUTTON_NUNCHUCK_Z -> R.string.button_nunchuck_z; + case NativeInput.WIIMOTE_BUTTON_NUNCHUCK_C -> R.string.button_nunchuck_c; + case NativeInput.WIIMOTE_BUTTON_PLUS -> R.string.button_plus; + case NativeInput.WIIMOTE_BUTTON_MINUS -> R.string.button_minus; + case NativeInput.WIIMOTE_BUTTON_UP -> R.string.button_up; + case NativeInput.WIIMOTE_BUTTON_DOWN -> R.string.button_down; + case NativeInput.WIIMOTE_BUTTON_LEFT -> R.string.button_left; + case NativeInput.WIIMOTE_BUTTON_RIGHT -> R.string.button_right; + case NativeInput.WIIMOTE_BUTTON_NUNCHUCK_UP -> R.string.button_nunchuck_up; + case NativeInput.WIIMOTE_BUTTON_NUNCHUCK_DOWN -> R.string.button_nunchuck_down; + case NativeInput.WIIMOTE_BUTTON_NUNCHUCK_LEFT -> R.string.button_nunchuck_left; + case NativeInput.WIIMOTE_BUTTON_NUNCHUCK_RIGHT -> R.string.button_nunchuck_right; + case NativeInput.WIIMOTE_BUTTON_HOME -> R.string.button_home; default -> throw new IllegalArgumentException("Invalid buttonId " + buttonId + " for controllerType " + controllerType); }; @@ -158,29 +158,29 @@ public class ControllerInputsDataProvider { public List getControllerInputs(int controllerType, Map inputs) { List controllerInputItems = new ArrayList<>(); - if (controllerType == NativeLibrary.EMULATED_CONTROLLER_TYPE_VPAD) { - addControllerInputsGroup(controllerInputItems, R.string.buttons, controllerType, List.of(NativeLibrary.VPAD_BUTTON_A, NativeLibrary.VPAD_BUTTON_B, NativeLibrary.VPAD_BUTTON_X, NativeLibrary.VPAD_BUTTON_Y, NativeLibrary.VPAD_BUTTON_L, NativeLibrary.VPAD_BUTTON_R, NativeLibrary.VPAD_BUTTON_ZL, NativeLibrary.VPAD_BUTTON_ZR, NativeLibrary.VPAD_BUTTON_PLUS, NativeLibrary.VPAD_BUTTON_MINUS), inputs); - addControllerInputsGroup(controllerInputItems, R.string.d_pad, controllerType, List.of(NativeLibrary.VPAD_BUTTON_UP, NativeLibrary.VPAD_BUTTON_DOWN, NativeLibrary.VPAD_BUTTON_LEFT, NativeLibrary.VPAD_BUTTON_RIGHT), inputs); - addControllerInputsGroup(controllerInputItems, R.string.left_axis, controllerType, List.of(NativeLibrary.VPAD_BUTTON_STICKL, NativeLibrary.VPAD_BUTTON_STICKL_UP, NativeLibrary.VPAD_BUTTON_STICKL_DOWN, NativeLibrary.VPAD_BUTTON_STICKL_LEFT, NativeLibrary.VPAD_BUTTON_STICKL_RIGHT), inputs); - addControllerInputsGroup(controllerInputItems, R.string.right_axis, controllerType, List.of(NativeLibrary.VPAD_BUTTON_STICKR, NativeLibrary.VPAD_BUTTON_STICKR_UP, NativeLibrary.VPAD_BUTTON_STICKR_DOWN, NativeLibrary.VPAD_BUTTON_STICKR_LEFT, NativeLibrary.VPAD_BUTTON_STICKR_RIGHT), inputs); - addControllerInputsGroup(controllerInputItems, R.string.extra, controllerType, List.of(NativeLibrary.VPAD_BUTTON_MIC, NativeLibrary.VPAD_BUTTON_SCREEN, NativeLibrary.VPAD_BUTTON_HOME), inputs); + if (controllerType == NativeInput.EMULATED_CONTROLLER_TYPE_VPAD) { + addControllerInputsGroup(controllerInputItems, R.string.buttons, controllerType, List.of(NativeInput.VPAD_BUTTON_A, NativeInput.VPAD_BUTTON_B, NativeInput.VPAD_BUTTON_X, NativeInput.VPAD_BUTTON_Y, NativeInput.VPAD_BUTTON_L, NativeInput.VPAD_BUTTON_R, NativeInput.VPAD_BUTTON_ZL, NativeInput.VPAD_BUTTON_ZR, NativeInput.VPAD_BUTTON_PLUS, NativeInput.VPAD_BUTTON_MINUS), inputs); + addControllerInputsGroup(controllerInputItems, R.string.d_pad, controllerType, List.of(NativeInput.VPAD_BUTTON_UP, NativeInput.VPAD_BUTTON_DOWN, NativeInput.VPAD_BUTTON_LEFT, NativeInput.VPAD_BUTTON_RIGHT), inputs); + addControllerInputsGroup(controllerInputItems, R.string.left_axis, controllerType, List.of(NativeInput.VPAD_BUTTON_STICKL, NativeInput.VPAD_BUTTON_STICKL_UP, NativeInput.VPAD_BUTTON_STICKL_DOWN, NativeInput.VPAD_BUTTON_STICKL_LEFT, NativeInput.VPAD_BUTTON_STICKL_RIGHT), inputs); + addControllerInputsGroup(controllerInputItems, R.string.right_axis, controllerType, List.of(NativeInput.VPAD_BUTTON_STICKR, NativeInput.VPAD_BUTTON_STICKR_UP, NativeInput.VPAD_BUTTON_STICKR_DOWN, NativeInput.VPAD_BUTTON_STICKR_LEFT, NativeInput.VPAD_BUTTON_STICKR_RIGHT), inputs); + addControllerInputsGroup(controllerInputItems, R.string.extra, controllerType, List.of(NativeInput.VPAD_BUTTON_MIC, NativeInput.VPAD_BUTTON_SCREEN, NativeInput.VPAD_BUTTON_HOME), inputs); } - if (controllerType == NativeLibrary.EMULATED_CONTROLLER_TYPE_PRO) { - addControllerInputsGroup(controllerInputItems, R.string.buttons, controllerType, List.of(NativeLibrary.PRO_BUTTON_A, NativeLibrary.PRO_BUTTON_B, NativeLibrary.PRO_BUTTON_X, NativeLibrary.PRO_BUTTON_Y, NativeLibrary.PRO_BUTTON_L, NativeLibrary.PRO_BUTTON_R, NativeLibrary.PRO_BUTTON_ZL, NativeLibrary.PRO_BUTTON_ZR, NativeLibrary.PRO_BUTTON_PLUS, NativeLibrary.PRO_BUTTON_MINUS, NativeLibrary.PRO_BUTTON_HOME), inputs); - addControllerInputsGroup(controllerInputItems, R.string.left_axis, controllerType, List.of(NativeLibrary.PRO_BUTTON_STICKL, NativeLibrary.PRO_BUTTON_STICKL_UP, NativeLibrary.PRO_BUTTON_STICKL_DOWN, NativeLibrary.PRO_BUTTON_STICKL_LEFT, NativeLibrary.PRO_BUTTON_STICKL_RIGHT), inputs); - addControllerInputsGroup(controllerInputItems, R.string.right_axis, controllerType, List.of(NativeLibrary.PRO_BUTTON_STICKR, NativeLibrary.PRO_BUTTON_STICKR_UP, NativeLibrary.PRO_BUTTON_STICKR_DOWN, NativeLibrary.PRO_BUTTON_STICKR_LEFT, NativeLibrary.PRO_BUTTON_STICKR_RIGHT), inputs); - addControllerInputsGroup(controllerInputItems, R.string.d_pad, controllerType, List.of(NativeLibrary.PRO_BUTTON_UP, NativeLibrary.PRO_BUTTON_DOWN, NativeLibrary.PRO_BUTTON_LEFT, NativeLibrary.PRO_BUTTON_RIGHT), inputs); + if (controllerType == NativeInput.EMULATED_CONTROLLER_TYPE_PRO) { + addControllerInputsGroup(controllerInputItems, R.string.buttons, controllerType, List.of(NativeInput.PRO_BUTTON_A, NativeInput.PRO_BUTTON_B, NativeInput.PRO_BUTTON_X, NativeInput.PRO_BUTTON_Y, NativeInput.PRO_BUTTON_L, NativeInput.PRO_BUTTON_R, NativeInput.PRO_BUTTON_ZL, NativeInput.PRO_BUTTON_ZR, NativeInput.PRO_BUTTON_PLUS, NativeInput.PRO_BUTTON_MINUS, NativeInput.PRO_BUTTON_HOME), inputs); + addControllerInputsGroup(controllerInputItems, R.string.left_axis, controllerType, List.of(NativeInput.PRO_BUTTON_STICKL, NativeInput.PRO_BUTTON_STICKL_UP, NativeInput.PRO_BUTTON_STICKL_DOWN, NativeInput.PRO_BUTTON_STICKL_LEFT, NativeInput.PRO_BUTTON_STICKL_RIGHT), inputs); + addControllerInputsGroup(controllerInputItems, R.string.right_axis, controllerType, List.of(NativeInput.PRO_BUTTON_STICKR, NativeInput.PRO_BUTTON_STICKR_UP, NativeInput.PRO_BUTTON_STICKR_DOWN, NativeInput.PRO_BUTTON_STICKR_LEFT, NativeInput.PRO_BUTTON_STICKR_RIGHT), inputs); + addControllerInputsGroup(controllerInputItems, R.string.d_pad, controllerType, List.of(NativeInput.PRO_BUTTON_UP, NativeInput.PRO_BUTTON_DOWN, NativeInput.PRO_BUTTON_LEFT, NativeInput.PRO_BUTTON_RIGHT), inputs); } - if (controllerType == NativeLibrary.EMULATED_CONTROLLER_TYPE_CLASSIC) { - addControllerInputsGroup(controllerInputItems, R.string.buttons, controllerType, List.of(NativeLibrary.CLASSIC_BUTTON_A, NativeLibrary.CLASSIC_BUTTON_B, NativeLibrary.CLASSIC_BUTTON_X, NativeLibrary.CLASSIC_BUTTON_Y, NativeLibrary.CLASSIC_BUTTON_L, NativeLibrary.CLASSIC_BUTTON_R, NativeLibrary.CLASSIC_BUTTON_ZL, NativeLibrary.CLASSIC_BUTTON_ZR, NativeLibrary.CLASSIC_BUTTON_PLUS, NativeLibrary.CLASSIC_BUTTON_MINUS, NativeLibrary.CLASSIC_BUTTON_HOME), inputs); - addControllerInputsGroup(controllerInputItems, R.string.left_axis, controllerType, List.of(NativeLibrary.CLASSIC_BUTTON_STICKL_UP, NativeLibrary.CLASSIC_BUTTON_STICKL_DOWN, NativeLibrary.CLASSIC_BUTTON_STICKL_LEFT, NativeLibrary.CLASSIC_BUTTON_STICKL_RIGHT), inputs); - addControllerInputsGroup(controllerInputItems, R.string.right_axis, controllerType, List.of(NativeLibrary.CLASSIC_BUTTON_STICKR_UP, NativeLibrary.CLASSIC_BUTTON_STICKR_DOWN, NativeLibrary.CLASSIC_BUTTON_STICKR_LEFT, NativeLibrary.CLASSIC_BUTTON_STICKR_RIGHT), inputs); - addControllerInputsGroup(controllerInputItems, R.string.d_pad, controllerType, List.of(NativeLibrary.CLASSIC_BUTTON_UP, NativeLibrary.CLASSIC_BUTTON_DOWN, NativeLibrary.CLASSIC_BUTTON_LEFT, NativeLibrary.CLASSIC_BUTTON_RIGHT), inputs); + if (controllerType == NativeInput.EMULATED_CONTROLLER_TYPE_CLASSIC) { + addControllerInputsGroup(controllerInputItems, R.string.buttons, controllerType, List.of(NativeInput.CLASSIC_BUTTON_A, NativeInput.CLASSIC_BUTTON_B, NativeInput.CLASSIC_BUTTON_X, NativeInput.CLASSIC_BUTTON_Y, NativeInput.CLASSIC_BUTTON_L, NativeInput.CLASSIC_BUTTON_R, NativeInput.CLASSIC_BUTTON_ZL, NativeInput.CLASSIC_BUTTON_ZR, NativeInput.CLASSIC_BUTTON_PLUS, NativeInput.CLASSIC_BUTTON_MINUS, NativeInput.CLASSIC_BUTTON_HOME), inputs); + addControllerInputsGroup(controllerInputItems, R.string.left_axis, controllerType, List.of(NativeInput.CLASSIC_BUTTON_STICKL_UP, NativeInput.CLASSIC_BUTTON_STICKL_DOWN, NativeInput.CLASSIC_BUTTON_STICKL_LEFT, NativeInput.CLASSIC_BUTTON_STICKL_RIGHT), inputs); + addControllerInputsGroup(controllerInputItems, R.string.right_axis, controllerType, List.of(NativeInput.CLASSIC_BUTTON_STICKR_UP, NativeInput.CLASSIC_BUTTON_STICKR_DOWN, NativeInput.CLASSIC_BUTTON_STICKR_LEFT, NativeInput.CLASSIC_BUTTON_STICKR_RIGHT), inputs); + addControllerInputsGroup(controllerInputItems, R.string.d_pad, controllerType, List.of(NativeInput.CLASSIC_BUTTON_UP, NativeInput.CLASSIC_BUTTON_DOWN, NativeInput.CLASSIC_BUTTON_LEFT, NativeInput.CLASSIC_BUTTON_RIGHT), inputs); } - if (controllerType == NativeLibrary.EMULATED_CONTROLLER_TYPE_WIIMOTE) { - addControllerInputsGroup(controllerInputItems, R.string.buttons, controllerType, List.of(NativeLibrary.WIIMOTE_BUTTON_A, NativeLibrary.WIIMOTE_BUTTON_B, NativeLibrary.WIIMOTE_BUTTON_1, NativeLibrary.WIIMOTE_BUTTON_2, NativeLibrary.WIIMOTE_BUTTON_NUNCHUCK_Z, NativeLibrary.WIIMOTE_BUTTON_NUNCHUCK_C, NativeLibrary.WIIMOTE_BUTTON_PLUS, NativeLibrary.WIIMOTE_BUTTON_MINUS, NativeLibrary.WIIMOTE_BUTTON_HOME), inputs); - addControllerInputsGroup(controllerInputItems, R.string.d_pad, controllerType, List.of(NativeLibrary.WIIMOTE_BUTTON_UP, NativeLibrary.WIIMOTE_BUTTON_DOWN, NativeLibrary.WIIMOTE_BUTTON_LEFT, NativeLibrary.WIIMOTE_BUTTON_RIGHT), inputs); - addControllerInputsGroup(controllerInputItems, R.string.nunchuck, controllerType, List.of(NativeLibrary.WIIMOTE_BUTTON_NUNCHUCK_UP, NativeLibrary.WIIMOTE_BUTTON_NUNCHUCK_DOWN, NativeLibrary.WIIMOTE_BUTTON_NUNCHUCK_LEFT, NativeLibrary.WIIMOTE_BUTTON_NUNCHUCK_RIGHT), inputs); + if (controllerType == NativeInput.EMULATED_CONTROLLER_TYPE_WIIMOTE) { + addControllerInputsGroup(controllerInputItems, R.string.buttons, controllerType, List.of(NativeInput.WIIMOTE_BUTTON_A, NativeInput.WIIMOTE_BUTTON_B, NativeInput.WIIMOTE_BUTTON_1, NativeInput.WIIMOTE_BUTTON_2, NativeInput.WIIMOTE_BUTTON_NUNCHUCK_Z, NativeInput.WIIMOTE_BUTTON_NUNCHUCK_C, NativeInput.WIIMOTE_BUTTON_PLUS, NativeInput.WIIMOTE_BUTTON_MINUS, NativeInput.WIIMOTE_BUTTON_HOME), inputs); + addControllerInputsGroup(controllerInputItems, R.string.d_pad, controllerType, List.of(NativeInput.WIIMOTE_BUTTON_UP, NativeInput.WIIMOTE_BUTTON_DOWN, NativeInput.WIIMOTE_BUTTON_LEFT, NativeInput.WIIMOTE_BUTTON_RIGHT), inputs); + addControllerInputsGroup(controllerInputItems, R.string.nunchuck, controllerType, List.of(NativeInput.WIIMOTE_BUTTON_NUNCHUCK_UP, NativeInput.WIIMOTE_BUTTON_NUNCHUCK_DOWN, NativeInput.WIIMOTE_BUTTON_NUNCHUCK_LEFT, NativeInput.WIIMOTE_BUTTON_NUNCHUCK_RIGHT), inputs); } return controllerInputItems; } diff --git a/src/android/app/src/main/java/info/cemu/Cemu/settings/input/ControllerInputsFragment.java b/src/android/app/src/main/java/info/cemu/Cemu/settings/input/ControllerInputsFragment.java index 81fc476a..dbc82171 100644 --- a/src/android/app/src/main/java/info/cemu/Cemu/settings/input/ControllerInputsFragment.java +++ b/src/android/app/src/main/java/info/cemu/Cemu/settings/input/ControllerInputsFragment.java @@ -21,7 +21,7 @@ import info.cemu.Cemu.guibasecomponents.GenericRecyclerViewAdapter; import info.cemu.Cemu.guibasecomponents.HeaderRecyclerViewItem; import info.cemu.Cemu.guibasecomponents.SingleSelectionRecyclerViewItem; import info.cemu.Cemu.input.InputManager; -import info.cemu.Cemu.NativeLibrary; +import info.cemu.Cemu.nativeinterface.NativeInput; public class ControllerInputsFragment extends Fragment { public static final String CONTROLLER_INDEX = "ControllerIndex"; @@ -35,14 +35,14 @@ public class ControllerInputsFragment extends Fragment { private void onTypeChanged(int controllerType) { if (this.controllerType == controllerType) return; this.controllerType = controllerType; - NativeLibrary.setControllerType(controllerIndex, controllerType); + NativeInput.setControllerType(controllerIndex, controllerType); genericRecyclerViewAdapter.clearRecyclerViewItems(); setControllerInputs(new HashMap<>()); } private void setControllerInputs(Map inputs) { emulatedControllerTypeAdapter.setSelectedValue(controllerType); - emulatedControllerTypeAdapter.setControllerTypeCounts(NativeLibrary.getVPADControllersCount(), NativeLibrary.getWPADControllersCount()); + emulatedControllerTypeAdapter.setControllerTypeCounts(NativeInput.getVPADControllersCount(), NativeInput.getWPADControllersCount()); String controllerTypeName = getString(ControllerTypeResourceNameMapper.controllerTypeToResourceNameId(controllerType)); SingleSelectionRecyclerViewItem emulatedControllerSelection = new SingleSelectionRecyclerViewItem<>(getString(R.string.emulated_controller_label), @@ -59,21 +59,21 @@ public class ControllerInputsFragment extends Fragment { MotionDialog inputDialog = new MotionDialog(getContext()); inputDialog.setOnKeyListener((dialog, keyCode, keyEvent) -> { if (inputManager.mapKeyEventToMappingId(controllerIndex, buttonId, keyEvent)) { - inputItem.setBoundInput(NativeLibrary.getControllerMapping(controllerIndex, buttonId)); + inputItem.setBoundInput(NativeInput.getControllerMapping(controllerIndex, buttonId)); inputDialog.dismiss(); } return true; }); inputDialog.setOnMotionListener(motionEvent -> { if (inputManager.mapMotionEventToMappingId(controllerIndex, buttonId, motionEvent)) { - inputItem.setBoundInput(NativeLibrary.getControllerMapping(controllerIndex, buttonId)); + inputItem.setBoundInput(NativeInput.getControllerMapping(controllerIndex, buttonId)); inputDialog.dismiss(); } return true; }); inputDialog.setMessage(getString(R.string.inputBindingDialogMessage, getString(buttonResourceIdName))); inputDialog.setButton(AlertDialog.BUTTON_NEUTRAL, getString(R.string.clear), (dialogInterface, i) -> { - NativeLibrary.clearControllerMapping(controllerIndex, buttonId); + NativeInput.clearControllerMapping(controllerIndex, buttonId); inputItem.clearBoundInput(); dialogInterface.dismiss(); }); @@ -94,11 +94,11 @@ public class ControllerInputsFragment extends Fragment { ActionBar actionBar = ((AppCompatActivity) requireActivity()).getSupportActionBar(); if (actionBar != null) actionBar.setTitle(getString(R.string.controller_numbered, controllerIndex + 1)); - if (NativeLibrary.isControllerDisabled(controllerIndex)) - controllerType = NativeLibrary.EMULATED_CONTROLLER_TYPE_DISABLED; - else controllerType = NativeLibrary.getControllerType(controllerIndex); + if (NativeInput.isControllerDisabled(controllerIndex)) + controllerType = NativeInput.EMULATED_CONTROLLER_TYPE_DISABLED; + else controllerType = NativeInput.getControllerType(controllerIndex); - setControllerInputs(NativeLibrary.getControllerMappings(controllerIndex)); + setControllerInputs(NativeInput.getControllerMappings(controllerIndex)); var binding = GenericRecyclerViewLayoutBinding.inflate(inflater, container, false); binding.recyclerView.setAdapter(genericRecyclerViewAdapter); diff --git a/src/android/app/src/main/java/info/cemu/Cemu/settings/input/ControllerTypeResourceNameMapper.java b/src/android/app/src/main/java/info/cemu/Cemu/settings/input/ControllerTypeResourceNameMapper.java index 8ff92075..4b6df13c 100644 --- a/src/android/app/src/main/java/info/cemu/Cemu/settings/input/ControllerTypeResourceNameMapper.java +++ b/src/android/app/src/main/java/info/cemu/Cemu/settings/input/ControllerTypeResourceNameMapper.java @@ -1,16 +1,16 @@ package info.cemu.Cemu.settings.input; import info.cemu.Cemu.R; -import info.cemu.Cemu.NativeLibrary; +import info.cemu.Cemu.nativeinterface.NativeInput; public class ControllerTypeResourceNameMapper { public static int controllerTypeToResourceNameId(int type) { return switch (type) { - case NativeLibrary.EMULATED_CONTROLLER_TYPE_DISABLED -> R.string.disabled; - case NativeLibrary.EMULATED_CONTROLLER_TYPE_VPAD -> R.string.vpad_controller; - case NativeLibrary.EMULATED_CONTROLLER_TYPE_PRO -> R.string.pro_controller; - case NativeLibrary.EMULATED_CONTROLLER_TYPE_WIIMOTE -> R.string.wiimote_controller; - case NativeLibrary.EMULATED_CONTROLLER_TYPE_CLASSIC -> R.string.classic_controller; + case NativeInput.EMULATED_CONTROLLER_TYPE_DISABLED -> R.string.disabled; + case NativeInput.EMULATED_CONTROLLER_TYPE_VPAD -> R.string.vpad_controller; + case NativeInput.EMULATED_CONTROLLER_TYPE_PRO -> R.string.pro_controller; + case NativeInput.EMULATED_CONTROLLER_TYPE_WIIMOTE -> R.string.wiimote_controller; + case NativeInput.EMULATED_CONTROLLER_TYPE_CLASSIC -> R.string.classic_controller; default -> throw new IllegalArgumentException("Invalid controller type: " + type); }; } diff --git a/src/android/app/src/main/java/info/cemu/Cemu/settings/input/EmulatedControllerTypeAdapter.java b/src/android/app/src/main/java/info/cemu/Cemu/settings/input/EmulatedControllerTypeAdapter.java index e398ea52..22894d76 100644 --- a/src/android/app/src/main/java/info/cemu/Cemu/settings/input/EmulatedControllerTypeAdapter.java +++ b/src/android/app/src/main/java/info/cemu/Cemu/settings/input/EmulatedControllerTypeAdapter.java @@ -5,21 +5,21 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import info.cemu.Cemu.guibasecomponents.SelectionAdapter; -import info.cemu.Cemu.NativeLibrary; +import info.cemu.Cemu.nativeinterface.NativeInput; public class EmulatedControllerTypeAdapter extends SelectionAdapter { private int vpadCount = 0; private int wpadCount = 0; public EmulatedControllerTypeAdapter() { - choiceItems = Stream.of(NativeLibrary.EMULATED_CONTROLLER_TYPE_DISABLED, - NativeLibrary.EMULATED_CONTROLLER_TYPE_VPAD, - NativeLibrary.EMULATED_CONTROLLER_TYPE_PRO, - NativeLibrary.EMULATED_CONTROLLER_TYPE_CLASSIC, - NativeLibrary.EMULATED_CONTROLLER_TYPE_WIIMOTE) + choiceItems = Stream.of(NativeInput.EMULATED_CONTROLLER_TYPE_DISABLED, + NativeInput.EMULATED_CONTROLLER_TYPE_VPAD, + NativeInput.EMULATED_CONTROLLER_TYPE_PRO, + NativeInput.EMULATED_CONTROLLER_TYPE_CLASSIC, + NativeInput.EMULATED_CONTROLLER_TYPE_WIIMOTE) .map(type -> new ChoiceItem<>(t->t.setText(ControllerTypeResourceNameMapper.controllerTypeToResourceNameId(type)), type)) .collect(Collectors.toList()); - setSelectedValue(NativeLibrary.EMULATED_CONTROLLER_TYPE_DISABLED); + setSelectedValue(NativeInput.EMULATED_CONTROLLER_TYPE_DISABLED); } public void setControllerTypeCounts(int vpadCount, int wpadCount) { @@ -32,11 +32,11 @@ public class EmulatedControllerTypeAdapter extends SelectionAdapter { public boolean isEnabled(int position) { int currentControllerType = getItem(selectedPosition); int type = getItem(position); - if (type == NativeLibrary.EMULATED_CONTROLLER_TYPE_DISABLED) + if (type == NativeInput.EMULATED_CONTROLLER_TYPE_DISABLED) return true; - if (type == NativeLibrary.EMULATED_CONTROLLER_TYPE_VPAD) - return currentControllerType == NativeLibrary.EMULATED_CONTROLLER_TYPE_VPAD || vpadCount < NativeLibrary.MAX_VPAD_CONTROLLERS; - boolean isWPAD = currentControllerType != NativeLibrary.EMULATED_CONTROLLER_TYPE_VPAD && currentControllerType != NativeLibrary.EMULATED_CONTROLLER_TYPE_DISABLED; - return isWPAD || wpadCount < NativeLibrary.MAX_WPAD_CONTROLLERS; + if (type == NativeInput.EMULATED_CONTROLLER_TYPE_VPAD) + return currentControllerType == NativeInput.EMULATED_CONTROLLER_TYPE_VPAD || vpadCount < NativeInput.MAX_VPAD_CONTROLLERS; + boolean isWPAD = currentControllerType != NativeInput.EMULATED_CONTROLLER_TYPE_VPAD && currentControllerType != NativeInput.EMULATED_CONTROLLER_TYPE_DISABLED; + return isWPAD || wpadCount < NativeInput.MAX_WPAD_CONTROLLERS; } } diff --git a/src/android/app/src/main/java/info/cemu/Cemu/settings/input/InputSettingsFragment.java b/src/android/app/src/main/java/info/cemu/Cemu/settings/input/InputSettingsFragment.java index 23309db8..5ef769e1 100644 --- a/src/android/app/src/main/java/info/cemu/Cemu/settings/input/InputSettingsFragment.java +++ b/src/android/app/src/main/java/info/cemu/Cemu/settings/input/InputSettingsFragment.java @@ -16,7 +16,7 @@ import info.cemu.Cemu.databinding.GenericRecyclerViewLayoutBinding; import info.cemu.Cemu.guibasecomponents.ButtonRecyclerViewItem; import info.cemu.Cemu.guibasecomponents.GenericRecyclerViewAdapter; import info.cemu.Cemu.guibasecomponents.SimpleButtonRecyclerViewItem; -import info.cemu.Cemu.NativeLibrary; +import info.cemu.Cemu.nativeinterface.NativeInput; public class InputSettingsFragment extends Fragment { @@ -27,9 +27,9 @@ public class InputSettingsFragment extends Fragment { GenericRecyclerViewAdapter genericRecyclerViewAdapter = new GenericRecyclerViewAdapter(); genericRecyclerViewAdapter.addRecyclerViewItem(new SimpleButtonRecyclerViewItem(getString(R.string.input_overlay_settings), () -> NavHostFragment.findNavController(InputSettingsFragment.this).navigate(R.id.action_inputSettingsFragment_to_inputOverlaySettingsFragment))); - for (int index = 0; index < NativeLibrary.MAX_CONTROLLERS; index++) { + for (int index = 0; index < NativeInput.MAX_CONTROLLERS; index++) { int controllerIndex = index; - int controllerType = NativeLibrary.isControllerDisabled(controllerIndex) ? NativeLibrary.EMULATED_CONTROLLER_TYPE_DISABLED : NativeLibrary.getControllerType(controllerIndex); + int controllerType = NativeInput.isControllerDisabled(controllerIndex) ? NativeInput.EMULATED_CONTROLLER_TYPE_DISABLED : NativeInput.getControllerType(controllerIndex); String controllerTypeName = getString(ControllerTypeResourceNameMapper.controllerTypeToResourceNameId(controllerType)); ButtonRecyclerViewItem buttonRecyclerViewItem = new ButtonRecyclerViewItem( getString(R.string.controller_numbered, controllerIndex + 1), diff --git a/src/android/app/src/main/java/info/cemu/Cemu/settings/overlay/OverlaySettingsFragment.java b/src/android/app/src/main/java/info/cemu/Cemu/settings/overlay/OverlaySettingsFragment.java index f5c50e25..6c717559 100644 --- a/src/android/app/src/main/java/info/cemu/Cemu/settings/overlay/OverlaySettingsFragment.java +++ b/src/android/app/src/main/java/info/cemu/Cemu/settings/overlay/OverlaySettingsFragment.java @@ -18,25 +18,25 @@ import info.cemu.Cemu.guibasecomponents.GenericRecyclerViewAdapter; import info.cemu.Cemu.guibasecomponents.HeaderRecyclerViewItem; import info.cemu.Cemu.guibasecomponents.SelectionAdapter; import info.cemu.Cemu.guibasecomponents.SingleSelectionRecyclerViewItem; -import info.cemu.Cemu.NativeLibrary; +import info.cemu.Cemu.nativeinterface.NativeSettings; public class OverlaySettingsFragment extends Fragment { private static int overlayScreenPositionToResourceNameId(int overlayScreenPosition) { return switch (overlayScreenPosition) { - case NativeLibrary.OVERLAY_SCREEN_POSITION_DISABLED -> + case NativeSettings.OVERLAY_SCREEN_POSITION_DISABLED -> R.string.overlay_position_disabled; - case NativeLibrary.OVERLAY_SCREEN_POSITION_TOP_LEFT -> + case NativeSettings.OVERLAY_SCREEN_POSITION_TOP_LEFT -> R.string.overlay_position_top_left; - case NativeLibrary.OVERLAY_SCREEN_POSITION_TOP_CENTER -> + case NativeSettings.OVERLAY_SCREEN_POSITION_TOP_CENTER -> R.string.overlay_position_top_center; - case NativeLibrary.OVERLAY_SCREEN_POSITION_TOP_RIGHT -> + case NativeSettings.OVERLAY_SCREEN_POSITION_TOP_RIGHT -> R.string.overlay_position_top_right; - case NativeLibrary.OVERLAY_SCREEN_POSITION_BOTTOM_LEFT -> + case NativeSettings.OVERLAY_SCREEN_POSITION_BOTTOM_LEFT -> R.string.overlay_position_bottom_left; - case NativeLibrary.OVERLAY_SCREEN_POSITION_BOTTOM_CENTER -> + case NativeSettings.OVERLAY_SCREEN_POSITION_BOTTOM_CENTER -> R.string.overlay_position_bottom_center; - case NativeLibrary.OVERLAY_SCREEN_POSITION_BOTTOM_RIGHT -> + case NativeSettings.OVERLAY_SCREEN_POSITION_BOTTOM_RIGHT -> R.string.overlay_position_bottom_right; default -> throw new IllegalArgumentException("Invalid overlay position: " + overlayScreenPosition); @@ -50,76 +50,76 @@ public class OverlaySettingsFragment extends Fragment { GenericRecyclerViewAdapter genericRecyclerViewAdapter = new GenericRecyclerViewAdapter(); var overlayPositionChoices = Stream.of( - NativeLibrary.OVERLAY_SCREEN_POSITION_DISABLED, - NativeLibrary.OVERLAY_SCREEN_POSITION_TOP_LEFT, - NativeLibrary.OVERLAY_SCREEN_POSITION_TOP_CENTER, - NativeLibrary.OVERLAY_SCREEN_POSITION_TOP_RIGHT, - NativeLibrary.OVERLAY_SCREEN_POSITION_BOTTOM_LEFT, - NativeLibrary.OVERLAY_SCREEN_POSITION_BOTTOM_CENTER, - NativeLibrary.OVERLAY_SCREEN_POSITION_BOTTOM_RIGHT) + NativeSettings.OVERLAY_SCREEN_POSITION_DISABLED, + NativeSettings.OVERLAY_SCREEN_POSITION_TOP_LEFT, + NativeSettings.OVERLAY_SCREEN_POSITION_TOP_CENTER, + NativeSettings.OVERLAY_SCREEN_POSITION_TOP_RIGHT, + NativeSettings.OVERLAY_SCREEN_POSITION_BOTTOM_LEFT, + NativeSettings.OVERLAY_SCREEN_POSITION_BOTTOM_CENTER, + NativeSettings.OVERLAY_SCREEN_POSITION_BOTTOM_RIGHT) .map(position -> new SelectionAdapter.ChoiceItem<>(t -> t.setText(overlayScreenPositionToResourceNameId(position)), position)) .collect(Collectors.toList()); - int overlayPosition = NativeLibrary.getOverlayPosition(); + int overlayPosition = NativeSettings.getOverlayPosition(); genericRecyclerViewAdapter.addRecyclerViewItem(new HeaderRecyclerViewItem(R.string.overlay)); SelectionAdapter overlayPositionSelectionAdapter = new SelectionAdapter<>(overlayPositionChoices, overlayPosition); SingleSelectionRecyclerViewItem overlayPositionSelection = new SingleSelectionRecyclerViewItem<>(getString(R.string.overlay_position), getString(overlayScreenPositionToResourceNameId(overlayPosition)), overlayPositionSelectionAdapter, (position, selectionRecyclerViewItem) -> { - NativeLibrary.setOverlayPosition(position); + NativeSettings.setOverlayPosition(position); selectionRecyclerViewItem.setDescription(getString(overlayScreenPositionToResourceNameId(position))); }); genericRecyclerViewAdapter.addRecyclerViewItem(overlayPositionSelection); CheckboxRecyclerViewItem overlayFps = new CheckboxRecyclerViewItem(getString(R.string.fps), - getString(R.string.fps_overlay_description), NativeLibrary.isOverlayFPSEnabled(), - NativeLibrary::setOverlayFPSEnabled); + getString(R.string.fps_overlay_description), NativeSettings.isOverlayFPSEnabled(), + NativeSettings::setOverlayFPSEnabled); genericRecyclerViewAdapter.addRecyclerViewItem(overlayFps); CheckboxRecyclerViewItem drawCallsCheckbox = new CheckboxRecyclerViewItem(getString(R.string.draw_calls_per_frame), - getString(R.string.draw_calls_per_frame_overlay_description), NativeLibrary.isOverlayDrawCallsPerFrameEnabled(), - NativeLibrary::setOverlayDrawCallsPerFrameEnabled); + getString(R.string.draw_calls_per_frame_overlay_description), NativeSettings.isOverlayDrawCallsPerFrameEnabled(), + NativeSettings::setOverlayDrawCallsPerFrameEnabled); genericRecyclerViewAdapter.addRecyclerViewItem(drawCallsCheckbox); CheckboxRecyclerViewItem cpuUsageCheckbox = new CheckboxRecyclerViewItem(getString(R.string.cpu_usage), - getString(R.string.cpu_usage_overlay_description), NativeLibrary.isOverlayCPUUsageEnabled(), - NativeLibrary::setOverlayCPUUsageEnabled); + getString(R.string.cpu_usage_overlay_description), NativeSettings.isOverlayCPUUsageEnabled(), + NativeSettings::setOverlayCPUUsageEnabled); genericRecyclerViewAdapter.addRecyclerViewItem(cpuUsageCheckbox); CheckboxRecyclerViewItem ramUsageCheckbox = new CheckboxRecyclerViewItem(getString(R.string.ram_usage), - getString(R.string.ram_usage_overlay_description), NativeLibrary.isOverlayRAMUsageEnabled(), - NativeLibrary::setOverlayRAMUsageEnabled); + getString(R.string.ram_usage_overlay_description), NativeSettings.isOverlayRAMUsageEnabled(), + NativeSettings::setOverlayRAMUsageEnabled); genericRecyclerViewAdapter.addRecyclerViewItem(ramUsageCheckbox); CheckboxRecyclerViewItem debugCheckbox = new CheckboxRecyclerViewItem(getString(R.string.debug), - getString(R.string.debug_overlay_description), NativeLibrary.isOverlayDebugEnabled(), - NativeLibrary::setOverlayDebugEnabled); + getString(R.string.debug_overlay_description), NativeSettings.isOverlayDebugEnabled(), + NativeSettings::setOverlayDebugEnabled); genericRecyclerViewAdapter.addRecyclerViewItem(debugCheckbox); genericRecyclerViewAdapter.addRecyclerViewItem(new HeaderRecyclerViewItem(R.string.notifications)); - int notificationsPosition = NativeLibrary.getNotificationsPosition(); + int notificationsPosition = NativeSettings.getNotificationsPosition(); SelectionAdapter notificationsPositionSelectionAdapter = new SelectionAdapter<>(overlayPositionChoices, notificationsPosition); SingleSelectionRecyclerViewItem notificationsPositionSelection = new SingleSelectionRecyclerViewItem<>(getString(R.string.overlay_position), getString(overlayScreenPositionToResourceNameId(notificationsPosition)), notificationsPositionSelectionAdapter, (position, selectionRecyclerViewItem) -> { - NativeLibrary.setNotificationsPosition(position); + NativeSettings.setNotificationsPosition(position); selectionRecyclerViewItem.setDescription(getString(overlayScreenPositionToResourceNameId(position))); }); genericRecyclerViewAdapter.addRecyclerViewItem(notificationsPositionSelection); CheckboxRecyclerViewItem controllerProfiles = new CheckboxRecyclerViewItem(getString(R.string.controller_profiles), - getString(R.string.controller_profiles_notification_description), NativeLibrary.isNotificationControllerProfilesEnabled(), - NativeLibrary::setNotificationControllerProfilesEnabled); + getString(R.string.controller_profiles_notification_description), NativeSettings.isNotificationControllerProfilesEnabled(), + NativeSettings::setNotificationControllerProfilesEnabled); genericRecyclerViewAdapter.addRecyclerViewItem(controllerProfiles); CheckboxRecyclerViewItem shaderCompiler = new CheckboxRecyclerViewItem(getString(R.string.shader_compiler), - getString(R.string.shader_compiler_notification_description), NativeLibrary.isNotificationShaderCompilerEnabled(), - NativeLibrary::setNotificationShaderCompilerEnabled); + getString(R.string.shader_compiler_notification_description), NativeSettings.isNotificationShaderCompilerEnabled(), + NativeSettings::setNotificationShaderCompilerEnabled); genericRecyclerViewAdapter.addRecyclerViewItem(shaderCompiler); CheckboxRecyclerViewItem friendList = new CheckboxRecyclerViewItem(getString(R.string.friend_list), - getString(R.string.friend_list_notification_description), NativeLibrary.isNotificationFriendListEnabled(), - NativeLibrary::setNotificationFriendListEnabled); + getString(R.string.friend_list_notification_description), NativeSettings.isNotificationFriendListEnabled(), + NativeSettings::setNotificationFriendListEnabled); genericRecyclerViewAdapter.addRecyclerViewItem(friendList); binding.recyclerView.setAdapter(genericRecyclerViewAdapter); diff --git a/src/android/app/src/main/java/info/cemu/Cemu/utils/ProgressResponseBody.java b/src/android/app/src/main/java/info/cemu/Cemu/utils/ProgressResponseBody.java deleted file mode 100644 index b70935c0..00000000 --- a/src/android/app/src/main/java/info/cemu/Cemu/utils/ProgressResponseBody.java +++ /dev/null @@ -1,66 +0,0 @@ -package info.cemu.Cemu.utils; - -import androidx.annotation.NonNull; - -import java.io.IOException; - -import okhttp3.MediaType; -import okhttp3.ResponseBody; -import okio.Buffer; -import okio.BufferedSource; -import okio.ForwardingSource; -import okio.Okio; -import okio.Source; - -class ProgressResponseBody extends ResponseBody { - - private final ResponseBody responseBody; - private final ProgressListener progressListener; - private BufferedSource bufferedSource; - - ProgressResponseBody(ResponseBody responseBody, ProgressListener progressListener) { - this.responseBody = responseBody; - this.progressListener = progressListener; - } - - @Override - public MediaType contentType() { - return responseBody.contentType(); - } - - @Override - public long contentLength() { - return responseBody.contentLength(); - } - - @NonNull - @Override - public BufferedSource source() { - if (bufferedSource == null) { - bufferedSource = Okio.buffer(source(responseBody.source())); - } - return bufferedSource; - } - - private Source source(Source source) { - return new ForwardingSource(source) { - long totalBytesRead = 0L; - - @Override - public long read(@NonNull Buffer sink, long byteCount) throws IOException { - long bytesRead = super.read(sink, byteCount); - sink.flush(); - if (bytesRead == -1) - return 100; - totalBytesRead += bytesRead; - progressListener.update((int) (100f * totalBytesRead / responseBody.contentLength())); - return bytesRead; - } - }; - } - - public interface ProgressListener { - void update(int progress); - } -} - diff --git a/src/android/app/src/main/java/info/cemu/Cemu/utils/ZipUtil.java b/src/android/app/src/main/java/info/cemu/Cemu/zip/Zip.java similarity index 93% rename from src/android/app/src/main/java/info/cemu/Cemu/utils/ZipUtil.java rename to src/android/app/src/main/java/info/cemu/Cemu/zip/Zip.java index 6e256d6c..0555bf10 100644 --- a/src/android/app/src/main/java/info/cemu/Cemu/utils/ZipUtil.java +++ b/src/android/app/src/main/java/info/cemu/Cemu/zip/Zip.java @@ -1,4 +1,4 @@ -package info.cemu.Cemu.utils; +package info.cemu.Cemu.zip; import java.io.File; import java.io.FileOutputStream; @@ -8,7 +8,7 @@ import java.nio.file.Paths; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; -public class ZipUtil { +public class Zip { public static void unzip(InputStream stream, String targetDir) throws IOException { try (ZipInputStream zipInputStream = new ZipInputStream(stream)) { @@ -34,7 +34,7 @@ public class ZipUtil { private static void createDir(String dir) { File f = new File(dir); if (!f.isDirectory()) { - f.mkdirs(); + var ignored = f.mkdirs(); } } } diff --git a/src/android/app/src/test/java/info/cemu/Cemu/ExampleUnitTest.java b/src/android/app/src/test/java/info/cemu/Cemu/ExampleUnitTest.java deleted file mode 100644 index a673d6c5..00000000 --- a/src/android/app/src/test/java/info/cemu/Cemu/ExampleUnitTest.java +++ /dev/null @@ -1,17 +0,0 @@ -package info.cemu.Cemu; - -import org.junit.Test; - -import static org.junit.Assert.*; - -/** - * Example local unit test, which will execute on the development machine (host). - * - * @see Testing documentation - */ -public class ExampleUnitTest { - @Test - public void addition_isCorrect() { - assertEquals(4, 2 + 2); - } -} \ No newline at end of file diff --git a/src/input/InputManager.h b/src/input/InputManager.h index 9d016170..a8d4130f 100644 --- a/src/input/InputManager.h +++ b/src/input/InputManager.h @@ -17,7 +17,7 @@ #include "input/api/GameCube/GameCubeControllerProvider.h" #if __ANDROID__ -#include "input/api/Android//AndroidControllerProvider.h" +#include "input/api/Android/AndroidControllerProvider.h" #endif #include "input/emulated/VPADController.h"