forked from eden-emu/eden
		
	Merge pull request #10508 from yuzu-emu/lime
Project Lime - yuzu Android Port
This commit is contained in:
		
						commit
						31ad92b287
					
				
					 339 changed files with 21731 additions and 188 deletions
				
			
		|  | @ -142,6 +142,7 @@ add_library(core STATIC | |||
|     frontend/emu_window.h | ||||
|     frontend/framebuffer_layout.cpp | ||||
|     frontend/framebuffer_layout.h | ||||
|     frontend/graphics_context.h | ||||
|     hid/emulated_console.cpp | ||||
|     hid/emulated_console.h | ||||
|     hid/emulated_controller.cpp | ||||
|  |  | |||
|  | @ -569,6 +569,10 @@ std::optional<std::pair<Key128, Key128>> ParseTicket(const Ticket& ticket, | |||
| } | ||||
| 
 | ||||
| KeyManager::KeyManager() { | ||||
|     ReloadKeys(); | ||||
| } | ||||
| 
 | ||||
| void KeyManager::ReloadKeys() { | ||||
|     // Initialize keys
 | ||||
|     const auto yuzu_keys_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::KeysDir); | ||||
| 
 | ||||
|  | @ -702,6 +706,10 @@ void KeyManager::LoadFromFile(const std::filesystem::path& file_path, bool is_ti | |||
|     } | ||||
| } | ||||
| 
 | ||||
| bool KeyManager::AreKeysLoaded() const { | ||||
|     return !s128_keys.empty() && !s256_keys.empty(); | ||||
| } | ||||
| 
 | ||||
| bool KeyManager::BaseDeriveNecessary() const { | ||||
|     const auto check_key_existence = [this](auto key_type, u64 index1 = 0, u64 index2 = 0) { | ||||
|         return !HasKey(key_type, index1, index2); | ||||
|  |  | |||
|  | @ -267,6 +267,9 @@ public: | |||
|     bool AddTicketCommon(Ticket raw); | ||||
|     bool AddTicketPersonalized(Ticket raw); | ||||
| 
 | ||||
|     void ReloadKeys(); | ||||
|     bool AreKeysLoaded() const; | ||||
| 
 | ||||
| private: | ||||
|     KeyManager(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -6,9 +6,15 @@ | |||
| 
 | ||||
| namespace Core { | ||||
| 
 | ||||
| #ifdef ANDROID | ||||
| constexpr size_t VirtualReserveSize = 1ULL << 38; | ||||
| #else | ||||
| constexpr size_t VirtualReserveSize = 1ULL << 39; | ||||
| #endif | ||||
| 
 | ||||
| DeviceMemory::DeviceMemory() | ||||
|     : buffer{Kernel::Board::Nintendo::Nx::KSystemControl::Init::GetIntendedMemorySize(), | ||||
|              1ULL << 39} {} | ||||
|              VirtualReserveSize} {} | ||||
| DeviceMemory::~DeviceMemory() = default; | ||||
| 
 | ||||
| } // namespace Core
 | ||||
|  |  | |||
|  | @ -6,8 +6,6 @@ | |||
| 
 | ||||
| namespace Core::Frontend { | ||||
| 
 | ||||
| GraphicsContext::~GraphicsContext() = default; | ||||
| 
 | ||||
| EmuWindow::EmuWindow() { | ||||
|     // TODO: Find a better place to set this.
 | ||||
|     config.min_client_area_size = | ||||
|  |  | |||
|  | @ -5,11 +5,14 @@ | |||
| 
 | ||||
| #include <memory> | ||||
| #include <utility> | ||||
| 
 | ||||
| #include "common/common_types.h" | ||||
| #include "core/frontend/framebuffer_layout.h" | ||||
| 
 | ||||
| namespace Core::Frontend { | ||||
| 
 | ||||
| class GraphicsContext; | ||||
| 
 | ||||
| /// Information for the Graphics Backends signifying what type of screen pointer is in
 | ||||
| /// WindowInformation
 | ||||
| enum class WindowSystemType { | ||||
|  | @ -21,51 +24,6 @@ enum class WindowSystemType { | |||
|     Android, | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  * Represents a drawing context that supports graphics operations. | ||||
|  */ | ||||
| class GraphicsContext { | ||||
| public: | ||||
|     virtual ~GraphicsContext(); | ||||
| 
 | ||||
|     /// Inform the driver to swap the front/back buffers and present the current image
 | ||||
|     virtual void SwapBuffers() {} | ||||
| 
 | ||||
|     /// Makes the graphics context current for the caller thread
 | ||||
|     virtual void MakeCurrent() {} | ||||
| 
 | ||||
|     /// Releases (dunno if this is the "right" word) the context from the caller thread
 | ||||
|     virtual void DoneCurrent() {} | ||||
| 
 | ||||
|     class Scoped { | ||||
|     public: | ||||
|         [[nodiscard]] explicit Scoped(GraphicsContext& context_) : context(context_) { | ||||
|             context.MakeCurrent(); | ||||
|         } | ||||
|         ~Scoped() { | ||||
|             if (active) { | ||||
|                 context.DoneCurrent(); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         /// In the event that context was destroyed before the Scoped is destroyed, this provides a
 | ||||
|         /// mechanism to prevent calling a destroyed object's method during the deconstructor
 | ||||
|         void Cancel() { | ||||
|             active = false; | ||||
|         } | ||||
| 
 | ||||
|     private: | ||||
|         GraphicsContext& context; | ||||
|         bool active{true}; | ||||
|     }; | ||||
| 
 | ||||
|     /// Calls MakeCurrent on the context and calls DoneCurrent when the scope for the returned value
 | ||||
|     /// ends
 | ||||
|     [[nodiscard]] Scoped Acquire() { | ||||
|         return Scoped{*this}; | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  * Abstraction class used to provide an interface between emulation code and the frontend | ||||
|  * (e.g. SDL, QGLWidget, GLFW, etc...). | ||||
|  |  | |||
							
								
								
									
										62
									
								
								src/core/frontend/graphics_context.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								src/core/frontend/graphics_context.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,62 @@ | |||
| // SPDX-FileCopyrightText: 2023 yuzu Emulator Project
 | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later
 | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <memory> | ||||
| 
 | ||||
| #include "common/dynamic_library.h" | ||||
| 
 | ||||
| namespace Core::Frontend { | ||||
| 
 | ||||
| /**
 | ||||
|  * Represents a drawing context that supports graphics operations. | ||||
|  */ | ||||
| class GraphicsContext { | ||||
| public: | ||||
|     virtual ~GraphicsContext() = default; | ||||
| 
 | ||||
|     /// Inform the driver to swap the front/back buffers and present the current image
 | ||||
|     virtual void SwapBuffers() {} | ||||
| 
 | ||||
|     /// Makes the graphics context current for the caller thread
 | ||||
|     virtual void MakeCurrent() {} | ||||
| 
 | ||||
|     /// Releases (dunno if this is the "right" word) the context from the caller thread
 | ||||
|     virtual void DoneCurrent() {} | ||||
| 
 | ||||
|     /// Gets the GPU driver library (used by Android only)
 | ||||
|     virtual std::shared_ptr<Common::DynamicLibrary> GetDriverLibrary() { | ||||
|         return {}; | ||||
|     } | ||||
| 
 | ||||
|     class Scoped { | ||||
|     public: | ||||
|         [[nodiscard]] explicit Scoped(GraphicsContext& context_) : context(context_) { | ||||
|             context.MakeCurrent(); | ||||
|         } | ||||
|         ~Scoped() { | ||||
|             if (active) { | ||||
|                 context.DoneCurrent(); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         /// In the event that context was destroyed before the Scoped is destroyed, this provides a
 | ||||
|         /// mechanism to prevent calling a destroyed object's method during the deconstructor
 | ||||
|         void Cancel() { | ||||
|             active = false; | ||||
|         } | ||||
| 
 | ||||
|     private: | ||||
|         GraphicsContext& context; | ||||
|         bool active{true}; | ||||
|     }; | ||||
| 
 | ||||
|     /// Calls MakeCurrent on the context and calls DoneCurrent when the scope for the returned value
 | ||||
|     /// ends
 | ||||
|     [[nodiscard]] Scoped Acquire() { | ||||
|         return Scoped{*this}; | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| } // namespace Core::Frontend
 | ||||
|  | @ -13,7 +13,7 @@ EmulatedConsole::~EmulatedConsole() = default; | |||
| void EmulatedConsole::ReloadFromSettings() { | ||||
|     // Using first motion device from player 1. No need to assign any unique config at the moment
 | ||||
|     const auto& player = Settings::values.players.GetValue()[0]; | ||||
|     motion_params = Common::ParamPackage(player.motions[0]); | ||||
|     motion_params[0] = Common::ParamPackage(player.motions[0]); | ||||
| 
 | ||||
|     ReloadInput(); | ||||
| } | ||||
|  | @ -74,14 +74,30 @@ void EmulatedConsole::ReloadInput() { | |||
|     // If you load any device here add the equivalent to the UnloadInput() function
 | ||||
|     SetTouchParams(); | ||||
| 
 | ||||
|     motion_devices = Common::Input::CreateInputDevice(motion_params); | ||||
|     if (motion_devices) { | ||||
|         motion_devices->SetCallback({ | ||||
|     motion_params[1] = Common::ParamPackage{"engine:virtual_gamepad,port:8,motion:0"}; | ||||
| 
 | ||||
|     for (std::size_t index = 0; index < motion_devices.size(); ++index) { | ||||
|         motion_devices[index] = Common::Input::CreateInputDevice(motion_params[index]); | ||||
|         if (!motion_devices[index]) { | ||||
|             continue; | ||||
|         } | ||||
|         motion_devices[index]->SetCallback({ | ||||
|             .on_change = | ||||
|                 [this](const Common::Input::CallbackStatus& callback) { SetMotion(callback); }, | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     // Restore motion state
 | ||||
|     auto& emulated_motion = console.motion_values.emulated; | ||||
|     auto& motion = console.motion_state; | ||||
|     emulated_motion.ResetRotations(); | ||||
|     emulated_motion.ResetQuaternion(); | ||||
|     motion.accel = emulated_motion.GetAcceleration(); | ||||
|     motion.gyro = emulated_motion.GetGyroscope(); | ||||
|     motion.rotation = emulated_motion.GetRotations(); | ||||
|     motion.orientation = emulated_motion.GetOrientation(); | ||||
|     motion.is_at_rest = !emulated_motion.IsMoving(motion_sensitivity); | ||||
| 
 | ||||
|     // Unique index for identifying touch device source
 | ||||
|     std::size_t index = 0; | ||||
|     for (auto& touch_device : touch_devices) { | ||||
|  | @ -100,7 +116,9 @@ void EmulatedConsole::ReloadInput() { | |||
| } | ||||
| 
 | ||||
| void EmulatedConsole::UnloadInput() { | ||||
|     motion_devices.reset(); | ||||
|     for (auto& motion : motion_devices) { | ||||
|         motion.reset(); | ||||
|     } | ||||
|     for (auto& touch : touch_devices) { | ||||
|         touch.reset(); | ||||
|     } | ||||
|  | @ -133,11 +151,11 @@ void EmulatedConsole::RestoreConfig() { | |||
| } | ||||
| 
 | ||||
| Common::ParamPackage EmulatedConsole::GetMotionParam() const { | ||||
|     return motion_params; | ||||
|     return motion_params[0]; | ||||
| } | ||||
| 
 | ||||
| void EmulatedConsole::SetMotionParam(Common::ParamPackage param) { | ||||
|     motion_params = std::move(param); | ||||
|     motion_params[0] = std::move(param); | ||||
|     ReloadInput(); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -29,10 +29,10 @@ struct ConsoleMotionInfo { | |||
|     MotionInput emulated{}; | ||||
| }; | ||||
| 
 | ||||
| using ConsoleMotionDevices = std::unique_ptr<Common::Input::InputDevice>; | ||||
| using ConsoleMotionDevices = std::array<std::unique_ptr<Common::Input::InputDevice>, 2>; | ||||
| using TouchDevices = std::array<std::unique_ptr<Common::Input::InputDevice>, MaxTouchDevices>; | ||||
| 
 | ||||
| using ConsoleMotionParams = Common::ParamPackage; | ||||
| using ConsoleMotionParams = std::array<Common::ParamPackage, 2>; | ||||
| using TouchParams = std::array<Common::ParamPackage, MaxTouchDevices>; | ||||
| 
 | ||||
| using ConsoleMotionValues = ConsoleMotionInfo; | ||||
|  |  | |||
|  | @ -193,6 +193,8 @@ void EmulatedController::LoadDevices() { | |||
|                            Common::Input::CreateInputDevice); | ||||
|     std::ranges::transform(virtual_stick_params, virtual_stick_devices.begin(), | ||||
|                            Common::Input::CreateInputDevice); | ||||
|     std::ranges::transform(virtual_motion_params, virtual_motion_devices.begin(), | ||||
|                            Common::Input::CreateInputDevice); | ||||
| } | ||||
| 
 | ||||
| void EmulatedController::LoadTASParams() { | ||||
|  | @ -253,6 +255,12 @@ void EmulatedController::LoadVirtualGamepadParams() { | |||
|     for (auto& param : virtual_stick_params) { | ||||
|         param = common_params; | ||||
|     } | ||||
|     for (auto& param : virtual_stick_params) { | ||||
|         param = common_params; | ||||
|     } | ||||
|     for (auto& param : virtual_motion_params) { | ||||
|         param = common_params; | ||||
|     } | ||||
| 
 | ||||
|     // TODO(german77): Replace this with an input profile or something better
 | ||||
|     virtual_button_params[Settings::NativeButton::A].Set("button", 0); | ||||
|  | @ -284,6 +292,9 @@ void EmulatedController::LoadVirtualGamepadParams() { | |||
|     virtual_stick_params[Settings::NativeAnalog::LStick].Set("range", 1.0f); | ||||
|     virtual_stick_params[Settings::NativeAnalog::RStick].Set("deadzone", 0.0f); | ||||
|     virtual_stick_params[Settings::NativeAnalog::RStick].Set("range", 1.0f); | ||||
| 
 | ||||
|     virtual_motion_params[Settings::NativeMotion::MotionLeft].Set("motion", 0); | ||||
|     virtual_motion_params[Settings::NativeMotion::MotionRight].Set("motion", 0); | ||||
| } | ||||
| 
 | ||||
| void EmulatedController::ReloadInput() { | ||||
|  | @ -463,6 +474,18 @@ void EmulatedController::ReloadInput() { | |||
|                 }, | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     for (std::size_t index = 0; index < virtual_motion_devices.size(); ++index) { | ||||
|         if (!virtual_motion_devices[index]) { | ||||
|             continue; | ||||
|         } | ||||
|         virtual_motion_devices[index]->SetCallback({ | ||||
|             .on_change = | ||||
|                 [this, index](const Common::Input::CallbackStatus& callback) { | ||||
|                     SetMotion(callback, index); | ||||
|                 }, | ||||
|         }); | ||||
|     } | ||||
|     turbo_button_state = 0; | ||||
| } | ||||
| 
 | ||||
|  | @ -500,6 +523,9 @@ void EmulatedController::UnloadInput() { | |||
|     for (auto& stick : virtual_stick_devices) { | ||||
|         stick.reset(); | ||||
|     } | ||||
|     for (auto& motion : virtual_motion_devices) { | ||||
|         motion.reset(); | ||||
|     } | ||||
|     for (auto& camera : camera_devices) { | ||||
|         camera.reset(); | ||||
|     } | ||||
|  |  | |||
|  | @ -568,8 +568,10 @@ private: | |||
|     // Virtual gamepad related variables
 | ||||
|     ButtonParams virtual_button_params; | ||||
|     StickParams virtual_stick_params; | ||||
|     ControllerMotionParams virtual_motion_params; | ||||
|     ButtonDevices virtual_button_devices; | ||||
|     StickDevices virtual_stick_devices; | ||||
|     ControllerMotionDevices virtual_motion_devices; | ||||
| 
 | ||||
|     mutable std::mutex mutex; | ||||
|     mutable std::mutex callback_mutex; | ||||
|  |  | |||
|  | @ -25,7 +25,12 @@ constexpr std::array<KAddressSpaceInfo, 13> AddressSpaceInfos{{ | |||
|    { .bit_width = 36, .address = 2_GiB       , .size = 64_GiB  - 2_GiB  , .type = KAddressSpaceInfo::Type::MapLarge, }, | ||||
|    { .bit_width = 36, .address = Size_Invalid, .size = 8_GiB            , .type = KAddressSpaceInfo::Type::Heap,     }, | ||||
|    { .bit_width = 36, .address = Size_Invalid, .size = 6_GiB            , .type = KAddressSpaceInfo::Type::Alias,    }, | ||||
| #ifdef ANDROID | ||||
|    // With Android, we use a 38-bit address space due to memory limitations. This should (safely) truncate ASLR region.
 | ||||
|    { .bit_width = 39, .address = 128_MiB     , .size = 256_GiB - 128_MiB, .type = KAddressSpaceInfo::Type::Map39Bit, }, | ||||
| #else | ||||
|    { .bit_width = 39, .address = 128_MiB     , .size = 512_GiB - 128_MiB, .type = KAddressSpaceInfo::Type::Map39Bit, }, | ||||
| #endif | ||||
|    { .bit_width = 39, .address = Size_Invalid, .size = 64_GiB           , .type = KAddressSpaceInfo::Type::MapSmall  }, | ||||
|    { .bit_width = 39, .address = Size_Invalid, .size = 8_GiB            , .type = KAddressSpaceInfo::Type::Heap,     }, | ||||
|    { .bit_width = 39, .address = Size_Invalid, .size = 64_GiB           , .type = KAddressSpaceInfo::Type::Alias,    }, | ||||
|  |  | |||
|  | @ -46,6 +46,7 @@ ProfileManager::ProfileManager() { | |||
|     // Create an user if none are present
 | ||||
|     if (user_count == 0) { | ||||
|         CreateNewUser(UUID::MakeRandom(), "yuzu"); | ||||
|         WriteUserSaveFile(); | ||||
|     } | ||||
| 
 | ||||
|     auto current = | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 bunnei
						bunnei