diff options
Diffstat (limited to 'src/core/hle/applets/applet.cpp')
| -rw-r--r-- | src/core/hle/applets/applet.cpp | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/src/core/hle/applets/applet.cpp b/src/core/hle/applets/applet.cpp new file mode 100644 index 000000000..4dcce729a --- /dev/null +++ b/src/core/hle/applets/applet.cpp | |||
| @@ -0,0 +1,94 @@ | |||
| 1 | // Copyright 2015 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/assert.h" | ||
| 6 | #include "common/logging/log.h" | ||
| 7 | |||
| 8 | #include "core/core_timing.h" | ||
| 9 | #include "core/hle/applets/applet.h" | ||
| 10 | #include "core/hle/applets/swkbd.h" | ||
| 11 | |||
| 12 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 13 | |||
| 14 | // Specializes std::hash for AppletId, so that we can use it in std::unordered_map. | ||
| 15 | // Workaround for libstdc++ bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60970 | ||
| 16 | namespace std { | ||
| 17 | template <> | ||
| 18 | struct hash<Service::APT::AppletId> { | ||
| 19 | typedef Service::APT::AppletId argument_type; | ||
| 20 | typedef std::size_t result_type; | ||
| 21 | |||
| 22 | result_type operator()(const argument_type& id_code) const { | ||
| 23 | typedef std::underlying_type<argument_type>::type Type; | ||
| 24 | return std::hash<Type>()(static_cast<Type>(id_code)); | ||
| 25 | } | ||
| 26 | }; | ||
| 27 | } | ||
| 28 | |||
| 29 | namespace HLE { | ||
| 30 | namespace Applets { | ||
| 31 | |||
| 32 | static std::unordered_map<Service::APT::AppletId, std::shared_ptr<Applet>> applets; | ||
| 33 | static u32 applet_update_event = -1; ///< The CoreTiming event identifier for the Applet update callback. | ||
| 34 | /// The interval at which the Applet update callback will be called, 16.6ms | ||
| 35 | static const u64 applet_update_interval_us = 16666; | ||
| 36 | |||
| 37 | ResultCode Applet::Create(Service::APT::AppletId id) { | ||
| 38 | switch (id) { | ||
| 39 | case Service::APT::AppletId::SoftwareKeyboard1: | ||
| 40 | case Service::APT::AppletId::SoftwareKeyboard2: | ||
| 41 | applets[id] = std::make_shared<SoftwareKeyboard>(id); | ||
| 42 | break; | ||
| 43 | default: | ||
| 44 | // TODO(Subv): Find the right error code | ||
| 45 | return ResultCode(ErrorDescription::NotFound, ErrorModule::Applet, ErrorSummary::NotSupported, ErrorLevel::Permanent); | ||
| 46 | } | ||
| 47 | |||
| 48 | return RESULT_SUCCESS; | ||
| 49 | } | ||
| 50 | |||
| 51 | std::shared_ptr<Applet> Applet::Get(Service::APT::AppletId id) { | ||
| 52 | auto itr = applets.find(id); | ||
| 53 | if (itr != applets.end()) | ||
| 54 | return itr->second; | ||
| 55 | return nullptr; | ||
| 56 | } | ||
| 57 | |||
| 58 | /// Handles updating the current Applet every time it's called. | ||
| 59 | static void AppletUpdateEvent(u64 applet_id, int cycles_late) { | ||
| 60 | Service::APT::AppletId id = static_cast<Service::APT::AppletId>(applet_id); | ||
| 61 | std::shared_ptr<Applet> applet = Applet::Get(id); | ||
| 62 | ASSERT_MSG(applet != nullptr, "Applet doesn't exist! applet_id=%08X", id); | ||
| 63 | |||
| 64 | applet->Update(); | ||
| 65 | |||
| 66 | // If the applet is still running after the last update, reschedule the event | ||
| 67 | if (applet->IsRunning()) { | ||
| 68 | CoreTiming::ScheduleEvent(usToCycles(applet_update_interval_us) - cycles_late, | ||
| 69 | applet_update_event, applet_id); | ||
| 70 | } else { | ||
| 71 | // Otherwise the applet has terminated, in which case we should clean it up | ||
| 72 | applets[id] = nullptr; | ||
| 73 | } | ||
| 74 | } | ||
| 75 | |||
| 76 | ResultCode Applet::Start(const Service::APT::AppletStartupParameter& parameter) { | ||
| 77 | ResultCode result = StartImpl(parameter); | ||
| 78 | if (result.IsError()) | ||
| 79 | return result; | ||
| 80 | // Schedule the update event | ||
| 81 | CoreTiming::ScheduleEvent(usToCycles(applet_update_interval_us), applet_update_event, static_cast<u64>(id)); | ||
| 82 | return result; | ||
| 83 | } | ||
| 84 | |||
| 85 | void Init() { | ||
| 86 | // Register the applet update callback | ||
| 87 | applet_update_event = CoreTiming::RegisterEvent("HLE Applet Update Event", AppletUpdateEvent); | ||
| 88 | } | ||
| 89 | |||
| 90 | void Shutdown() { | ||
| 91 | } | ||
| 92 | |||
| 93 | } | ||
| 94 | } // namespace | ||