mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30:04 +00:00 
			
		
		
		
	Applets: Reworked how the Applet update event is handled.
Applets are now cleaned up in AppletUpdateEvent after calling their respective Update method.
This commit is contained in:
		
							parent
							
								
									621ee10eae
								
							
						
					
					
						commit
						725d5eea78
					
				
					 7 changed files with 61 additions and 35 deletions
				
			
		|  | @ -31,9 +31,8 @@ namespace Applets { | ||||||
| 
 | 
 | ||||||
| static std::unordered_map<Service::APT::AppletId, std::shared_ptr<Applet>> applets; | static std::unordered_map<Service::APT::AppletId, std::shared_ptr<Applet>> applets; | ||||||
| static u32 applet_update_event = -1; ///< The CoreTiming event identifier for the Applet update callback.
 | static u32 applet_update_event = -1; ///< The CoreTiming event identifier for the Applet update callback.
 | ||||||
| /// The interval at which the Applet update callback will be called.
 | /// The interval at which the Applet update callback will be called, 16.6ms
 | ||||||
| static const u64 applet_update_interval_microseconds = 16666; | static const u64 applet_update_interval_us = 16666; | ||||||
| std::shared_ptr<Applet> g_current_applet = nullptr; ///< The applet that is currently executing
 |  | ||||||
| 
 | 
 | ||||||
| ResultCode Applet::Create(Service::APT::AppletId id) { | ResultCode Applet::Create(Service::APT::AppletId id) { | ||||||
|     switch (id) { |     switch (id) { | ||||||
|  | @ -57,21 +56,38 @@ std::shared_ptr<Applet> Applet::Get(Service::APT::AppletId id) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// Handles updating the current Applet every time it's called.
 | /// Handles updating the current Applet every time it's called.
 | ||||||
| static void AppletUpdateEvent(u64, int cycles_late) { | static void AppletUpdateEvent(u64 applet_id, int cycles_late) { | ||||||
|     if (g_current_applet && g_current_applet->IsRunning()) |     Service::APT::AppletId id = static_cast<Service::APT::AppletId>(applet_id); | ||||||
|         g_current_applet->Update(); |     std::shared_ptr<Applet> applet = Applet::Get(id); | ||||||
|  |     ASSERT_MSG(applet != nullptr, "Applet doesn't exist! applet_id=%08X", id); | ||||||
| 
 | 
 | ||||||
|     CoreTiming::ScheduleEvent(usToCycles(applet_update_interval) - cycles_late, |     applet->Update(); | ||||||
|         applet_update_event); | 
 | ||||||
|  |     // If the applet is still running after the last update, reschedule the event
 | ||||||
|  |     if (applet->IsRunning()) { | ||||||
|  |         CoreTiming::ScheduleEvent(usToCycles(applet_update_interval_us) - cycles_late, | ||||||
|  |             applet_update_event, applet_id); | ||||||
|  |     } else { | ||||||
|  |         // Otherwise the applet has terminated, in which case we should clean it up
 | ||||||
|  |         applets[id] = nullptr; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ResultCode Applet::Start(const Service::APT::AppletStartupParameter& parameter) { | ||||||
|  |     ResultCode result = StartImpl(parameter); | ||||||
|  |     if (result.IsError()) | ||||||
|  |         return result; | ||||||
|  |     // Schedule the update event
 | ||||||
|  |     CoreTiming::ScheduleEvent(usToCycles(applet_update_interval_us), applet_update_event, static_cast<u64>(id)); | ||||||
|  |     return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Init() { | void Init() { | ||||||
|  |     // Register the applet update callback
 | ||||||
|     applet_update_event = CoreTiming::RegisterEvent("HLE Applet Update Event", AppletUpdateEvent); |     applet_update_event = CoreTiming::RegisterEvent("HLE Applet Update Event", AppletUpdateEvent); | ||||||
|     CoreTiming::ScheduleEvent(usToCycles(applet_update_interval), applet_update_event); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Shutdown() { | void Shutdown() { | ||||||
|     CoreTiming::UnscheduleEvent(applet_update_event, 0); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -12,10 +12,10 @@ | ||||||
| namespace HLE { | namespace HLE { | ||||||
| namespace Applets { | namespace Applets { | ||||||
| 
 | 
 | ||||||
| class Applet : public std::enable_shared_from_this<Applet> { | class Applet { | ||||||
| public: | public: | ||||||
|     virtual ~Applet() {}; |     virtual ~Applet() { } | ||||||
|     Applet(Service::APT::AppletId id) : id(id) {}; |     Applet(Service::APT::AppletId id) : id(id) { } | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * Creates an instance of the Applet subclass identified by the parameter. |      * Creates an instance of the Applet subclass identified by the parameter. | ||||||
|  | @ -37,25 +37,33 @@ public: | ||||||
|      * @param parameter Parameter data to handle. |      * @param parameter Parameter data to handle. | ||||||
|      * @returns ResultCode Whether the operation was successful or not. |      * @returns ResultCode Whether the operation was successful or not. | ||||||
|      */ |      */ | ||||||
|     virtual ResultCode ReceiveParameter(Service::APT::MessageParameter const& parameter) = 0; |     virtual ResultCode ReceiveParameter(const Service::APT::MessageParameter& parameter) = 0; | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * Handles the Applet start event, triggered from the application. |      * Handles the Applet start event, triggered from the application. | ||||||
|      * @param parameter Parameter data to handle. |      * @param parameter Parameter data to handle. | ||||||
|      * @returns ResultCode Whether the operation was successful or not. |      * @returns ResultCode Whether the operation was successful or not. | ||||||
|      */ |      */ | ||||||
|     virtual ResultCode Start(Service::APT::AppletStartupParameter const& parameter) = 0; |     ResultCode Start(const Service::APT::AppletStartupParameter& parameter); | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * Whether the applet is currently executing instead of the host application or not. |      * Whether the applet is currently executing instead of the host application or not. | ||||||
|      */ |      */ | ||||||
|     virtual bool IsRunning() = 0; |     virtual bool IsRunning() const = 0; | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * Handles an update tick for the Applet, lets it update the screen, send commands, etc. |      * Handles an update tick for the Applet, lets it update the screen, send commands, etc. | ||||||
|      */ |      */ | ||||||
|     virtual void Update() = 0; |     virtual void Update() = 0; | ||||||
| 
 | 
 | ||||||
|  | protected: | ||||||
|  |     /**
 | ||||||
|  |      * Handles the Applet start event, triggered from the application. | ||||||
|  |      * @param parameter Parameter data to handle. | ||||||
|  |      * @returns ResultCode Whether the operation was successful or not. | ||||||
|  |      */ | ||||||
|  |     virtual ResultCode StartImpl(const Service::APT::AppletStartupParameter& parameter) = 0; | ||||||
|  | 
 | ||||||
|     Service::APT::AppletId id; ///< Id of this Applet
 |     Service::APT::AppletId id; ///< Id of this Applet
 | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | @ -65,6 +73,5 @@ void Init(); | ||||||
| /// Shuts down the HLE applets
 | /// Shuts down the HLE applets
 | ||||||
| void Shutdown(); | void Shutdown(); | ||||||
| 
 | 
 | ||||||
| extern std::shared_ptr<Applet> g_current_applet; ///< Applet that is currently executing
 |  | ||||||
| } | } | ||||||
| } // namespace
 | } // namespace
 | ||||||
|  |  | ||||||
|  | @ -4,6 +4,7 @@ | ||||||
| 
 | 
 | ||||||
| #include "common/assert.h" | #include "common/assert.h" | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
|  | #include "common/string_util.h" | ||||||
| 
 | 
 | ||||||
| #include "core/hle/applets/swkbd.h" | #include "core/hle/applets/swkbd.h" | ||||||
| #include "core/hle/service/hid/hid.h" | #include "core/hle/service/hid/hid.h" | ||||||
|  | @ -43,7 +44,9 @@ ResultCode SoftwareKeyboard::ReceiveParameter(Service::APT::MessageParameter con | ||||||
|     return RESULT_SUCCESS; |     return RESULT_SUCCESS; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ResultCode SoftwareKeyboard::Start(Service::APT::AppletStartupParameter const& parameter) { | ResultCode SoftwareKeyboard::StartImpl(Service::APT::AppletStartupParameter const& parameter) { | ||||||
|  |     ASSERT_MSG(parameter.buffer_size == sizeof(config), "The size of the parameter (SoftwareKeyboardConfig) is wrong"); | ||||||
|  | 
 | ||||||
|     memcpy(&config, parameter.data, parameter.buffer_size); |     memcpy(&config, parameter.data, parameter.buffer_size); | ||||||
|     text_memory = boost::static_pointer_cast<Kernel::SharedMemory, Kernel::Object>(parameter.object); |     text_memory = boost::static_pointer_cast<Kernel::SharedMemory, Kernel::Object>(parameter.object); | ||||||
| 
 | 
 | ||||||
|  | @ -52,9 +55,7 @@ ResultCode SoftwareKeyboard::Start(Service::APT::AppletStartupParameter const& p | ||||||
| 
 | 
 | ||||||
|     DrawScreenKeyboard(); |     DrawScreenKeyboard(); | ||||||
| 
 | 
 | ||||||
|     // Update the current applet so we can get update events
 |  | ||||||
|     started = true; |     started = true; | ||||||
|     g_current_applet = shared_from_this(); |  | ||||||
|     return RESULT_SUCCESS; |     return RESULT_SUCCESS; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -98,8 +99,6 @@ void SoftwareKeyboard::Finalize() { | ||||||
|     Service::APT::SendParameter(message); |     Service::APT::SendParameter(message); | ||||||
| 
 | 
 | ||||||
|     started = false; |     started = false; | ||||||
|     // Unset the current applet, we are not running anymore
 |  | ||||||
|     g_current_applet = nullptr; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -42,17 +42,21 @@ struct SoftwareKeyboardConfig { | ||||||
|     INSERT_PADDING_BYTES(0x2B6); |     INSERT_PADDING_BYTES(0x2B6); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | /**
 | ||||||
|  |  * The size of this structure (0x400) has been verified via reverse engineering of multiple games | ||||||
|  |  * that use the software keyboard. | ||||||
|  |  */ | ||||||
| static_assert(sizeof(SoftwareKeyboardConfig) == 0x400, "Software Keyboard Config size is wrong"); | static_assert(sizeof(SoftwareKeyboardConfig) == 0x400, "Software Keyboard Config size is wrong"); | ||||||
| 
 | 
 | ||||||
| class SoftwareKeyboard : public Applet { | class SoftwareKeyboard final : public Applet { | ||||||
| public: | public: | ||||||
|     SoftwareKeyboard(Service::APT::AppletId id); |     SoftwareKeyboard(Service::APT::AppletId id); | ||||||
|     ~SoftwareKeyboard() {} |     ~SoftwareKeyboard() {} | ||||||
| 
 | 
 | ||||||
|     ResultCode ReceiveParameter(Service::APT::MessageParameter const& parameter) override; |     ResultCode ReceiveParameter(const Service::APT::MessageParameter& parameter) override; | ||||||
|     ResultCode Start(Service::APT::AppletStartupParameter const& parameter) override; |     ResultCode StartImpl(const Service::APT::AppletStartupParameter& parameter) override; | ||||||
|     void Update() override; |     void Update() override; | ||||||
|     bool IsRunning() override { return started; } |     bool IsRunning() const override { return started; } | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * Draws a keyboard to the current bottom screen framebuffer. |      * Draws a keyboard to the current bottom screen framebuffer. | ||||||
|  | @ -66,7 +70,7 @@ public: | ||||||
|     void Finalize(); |     void Finalize(); | ||||||
| 
 | 
 | ||||||
|     /// TODO(Subv): Find out what this is actually used for.
 |     /// TODO(Subv): Find out what this is actually used for.
 | ||||||
|     // It is believed that the application stores the current screen image here.
 |     /// It is believed that the application stores the current screen image here.
 | ||||||
|     Kernel::SharedPtr<Kernel::SharedMemory> framebuffer_memory; |     Kernel::SharedPtr<Kernel::SharedMemory> framebuffer_memory; | ||||||
| 
 | 
 | ||||||
|     /// SharedMemory where the output text will be stored
 |     /// SharedMemory where the output text will be stored
 | ||||||
|  |  | ||||||
|  | @ -44,7 +44,7 @@ static u32 cpu_percent; ///< CPU time available to the running application | ||||||
| /// Parameter data to be returned in the next call to Glance/ReceiveParameter
 | /// Parameter data to be returned in the next call to Glance/ReceiveParameter
 | ||||||
| static MessageParameter next_parameter; | static MessageParameter next_parameter; | ||||||
| 
 | 
 | ||||||
| void SendParameter(MessageParameter const& parameter) { | void SendParameter(const MessageParameter& parameter) { | ||||||
|     next_parameter = parameter; |     next_parameter = parameter; | ||||||
|     // Signal the event to let the application know that a new parameter is ready to be read
 |     // Signal the event to let the application know that a new parameter is ready to be read
 | ||||||
|     parameter_event->Signal(); |     parameter_event->Signal(); | ||||||
|  |  | ||||||
|  | @ -63,7 +63,7 @@ enum class AppletId : u32 { | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /// Send a parameter to the currently-running application, which will read it via ReceiveParameter
 | /// Send a parameter to the currently-running application, which will read it via ReceiveParameter
 | ||||||
| void SendParameter(MessageParameter const& parameter); | void SendParameter(const MessageParameter& parameter); | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * APT::Initialize service function |  * APT::Initialize service function | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue