diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 2e32ff35b6fd562ae39ae281c652a33863d60612..848b17b180230b3eeb95369ce293ae933ba2ffd1 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -84,6 +84,8 @@ add_library(core STATIC
     hle/service/acc/acc_u0.h
     hle/service/am/am.cpp
     hle/service/am/am.h
+    hle/service/am/applet_ae.cpp
+    hle/service/am/applet_ae.h
     hle/service/am/applet_oe.cpp
     hle/service/am/applet_oe.h
     hle/service/aoc/aoc_u.cpp
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index b6896852efa2b98ee2a401f8913bb8acd3e29d1e..2825abd1a581eba6f281fb664ab3da008719ac11 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -2,14 +2,347 @@
 // Licensed under GPLv2 or any later version
 // Refer to the license.txt file included.
 
+#include "core/hle/ipc_helpers.h"
+#include "core/hle/kernel/event.h"
 #include "core/hle/service/am/am.h"
+#include "core/hle/service/am/applet_ae.h"
 #include "core/hle/service/am/applet_oe.h"
+#include "core/hle/service/apm/apm.h"
+#include "core/hle/service/nvflinger/nvflinger.h"
 
 namespace Service {
 namespace AM {
 
+IWindowController::IWindowController() : ServiceFramework("IWindowController") {
+    static const FunctionInfo functions[] = {
+        {1, &IWindowController::GetAppletResourceUserId, "GetAppletResourceUserId"},
+        {10, &IWindowController::AcquireForegroundRights, "AcquireForegroundRights"},
+    };
+    RegisterHandlers(functions);
+}
+
+void IWindowController::GetAppletResourceUserId(Kernel::HLERequestContext& ctx) {
+    LOG_WARNING(Service, "(STUBBED) called");
+    IPC::ResponseBuilder rb{ctx, 4};
+    rb.Push(RESULT_SUCCESS);
+    rb.Push<u64>(0);
+}
+
+void IWindowController::AcquireForegroundRights(Kernel::HLERequestContext& ctx) {
+    LOG_WARNING(Service, "(STUBBED) called");
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(RESULT_SUCCESS);
+}
+
+IAudioController::IAudioController() : ServiceFramework("IAudioController") {}
+
+IDisplayController::IDisplayController() : ServiceFramework("IDisplayController") {}
+
+IDebugFunctions::IDebugFunctions() : ServiceFramework("IDebugFunctions") {}
+
+ISelfController::ISelfController(std::shared_ptr<NVFlinger::NVFlinger> nvflinger)
+    : ServiceFramework("ISelfController"), nvflinger(std::move(nvflinger)) {
+    static const FunctionInfo functions[] = {
+        {1, &ISelfController::LockExit, "LockExit"},
+        {2, &ISelfController::UnlockExit, "UnlockExit"},
+        {11, &ISelfController::SetOperationModeChangedNotification,
+         "SetOperationModeChangedNotification"},
+        {12, &ISelfController::SetPerformanceModeChangedNotification,
+         "SetPerformanceModeChangedNotification"},
+        {13, &ISelfController::SetFocusHandlingMode, "SetFocusHandlingMode"},
+        {14, &ISelfController::SetRestartMessageEnabled, "SetRestartMessageEnabled"},
+        {16, &ISelfController::SetOutOfFocusSuspendingEnabled, "SetOutOfFocusSuspendingEnabled"},
+        {40, &ISelfController::CreateManagedDisplayLayer, "CreateManagedDisplayLayer"},
+    };
+    RegisterHandlers(functions);
+}
+
+void ISelfController::SetFocusHandlingMode(Kernel::HLERequestContext& ctx) {
+    // Takes 3 input u8s with each field located immediately after the previous u8, these are
+    // bool flags. No output.
+
+    IPC::RequestParser rp{ctx};
+
+    struct FocusHandlingModeParams {
+        u8 unknown0;
+        u8 unknown1;
+        u8 unknown2;
+    };
+    auto flags = rp.PopRaw<FocusHandlingModeParams>();
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(RESULT_SUCCESS);
+
+    LOG_WARNING(Service, "(STUBBED) called");
+}
+
+void ISelfController::SetRestartMessageEnabled(Kernel::HLERequestContext& ctx) {
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(RESULT_SUCCESS);
+
+    LOG_WARNING(Service, "(STUBBED) called");
+}
+
+void ISelfController::SetPerformanceModeChangedNotification(Kernel::HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+
+    bool flag = rp.Pop<bool>();
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(RESULT_SUCCESS);
+
+    LOG_WARNING(Service, "(STUBBED) called flag=%u", static_cast<u32>(flag));
+}
+
+void ISelfController::SetOperationModeChangedNotification(Kernel::HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+
+    bool flag = rp.Pop<bool>();
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(RESULT_SUCCESS);
+
+    LOG_WARNING(Service, "(STUBBED) called flag=%u", static_cast<u32>(flag));
+}
+
+void ISelfController::SetOutOfFocusSuspendingEnabled(Kernel::HLERequestContext& ctx) {
+    // Takes 3 input u8s with each field located immediately after the previous u8, these are
+    // bool flags. No output.
+    IPC::RequestParser rp{ctx};
+
+    bool enabled = rp.Pop<bool>();
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(RESULT_SUCCESS);
+
+    LOG_WARNING(Service, "(STUBBED) called enabled=%u", static_cast<u32>(enabled));
+}
+
+void ISelfController::LockExit(Kernel::HLERequestContext& ctx) {
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(RESULT_SUCCESS);
+
+    LOG_WARNING(Service, "(STUBBED) called");
+}
+
+void ISelfController::UnlockExit(Kernel::HLERequestContext& ctx) {
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(RESULT_SUCCESS);
+
+    LOG_WARNING(Service, "(STUBBED) called");
+}
+
+void ISelfController::CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx) {
+    // TODO(Subv): Find out how AM determines the display to use, for now just create the layer
+    // in the Default display.
+    u64 display_id = nvflinger->OpenDisplay("Default");
+    u64 layer_id = nvflinger->CreateLayer(display_id);
+
+    IPC::ResponseBuilder rb{ctx, 4};
+    rb.Push(RESULT_SUCCESS);
+    rb.Push(layer_id);
+
+    LOG_WARNING(Service, "(STUBBED) called");
+}
+
+ICommonStateGetter::ICommonStateGetter() : ServiceFramework("ICommonStateGetter") {
+    static const FunctionInfo functions[] = {
+        {0, &ICommonStateGetter::GetEventHandle, "GetEventHandle"},
+        {1, &ICommonStateGetter::ReceiveMessage, "ReceiveMessage"},
+        {5, &ICommonStateGetter::GetOperationMode, "GetOperationMode"},
+        {6, &ICommonStateGetter::GetPerformanceMode, "GetPerformanceMode"},
+        {9, &ICommonStateGetter::GetCurrentFocusState, "GetCurrentFocusState"},
+    };
+    RegisterHandlers(functions);
+
+    event = Kernel::Event::Create(Kernel::ResetType::OneShot, "ICommonStateGetter:Event");
+}
+
+void ICommonStateGetter::GetEventHandle(Kernel::HLERequestContext& ctx) {
+    event->Signal();
+
+    IPC::ResponseBuilder rb{ctx, 2, 1};
+    rb.Push(RESULT_SUCCESS);
+    rb.PushCopyObjects(event);
+
+    LOG_WARNING(Service, "(STUBBED) called");
+}
+
+void ICommonStateGetter::ReceiveMessage(Kernel::HLERequestContext& ctx) {
+    IPC::ResponseBuilder rb{ctx, 3};
+    rb.Push(RESULT_SUCCESS);
+    rb.Push<u32>(15);
+
+    LOG_WARNING(Service, "(STUBBED) called");
+}
+
+void ICommonStateGetter::GetCurrentFocusState(Kernel::HLERequestContext& ctx) {
+    IPC::ResponseBuilder rb{ctx, 3};
+    rb.Push(RESULT_SUCCESS);
+    rb.Push(static_cast<u8>(FocusState::InFocus));
+
+    LOG_WARNING(Service, "(STUBBED) called");
+}
+
+void ICommonStateGetter::GetOperationMode(Kernel::HLERequestContext& ctx) {
+    IPC::ResponseBuilder rb{ctx, 3};
+    rb.Push(RESULT_SUCCESS);
+    rb.Push(static_cast<u8>(OperationMode::Handheld));
+
+    LOG_WARNING(Service, "(STUBBED) called");
+}
+
+void ICommonStateGetter::GetPerformanceMode(Kernel::HLERequestContext& ctx) {
+    IPC::ResponseBuilder rb{ctx, 3};
+    rb.Push(RESULT_SUCCESS);
+    rb.Push(static_cast<u32>(APM::PerformanceMode::Handheld));
+
+    LOG_WARNING(Service, "(STUBBED) called");
+}
+
+ILibraryAppletCreator::ILibraryAppletCreator() : ServiceFramework("ILibraryAppletCreator") {}
+
+class IStorageAccessor final : public ServiceFramework<IStorageAccessor> {
+public:
+    explicit IStorageAccessor(std::vector<u8> buffer)
+        : ServiceFramework("IStorageAccessor"), buffer(std::move(buffer)) {
+        static const FunctionInfo functions[] = {
+            {0, &IStorageAccessor::GetSize, "GetSize"},
+            {11, &IStorageAccessor::Read, "Read"},
+        };
+        RegisterHandlers(functions);
+    }
+
+private:
+    std::vector<u8> buffer;
+
+    void GetSize(Kernel::HLERequestContext& ctx) {
+        IPC::ResponseBuilder rb{ctx, 4};
+
+        rb.Push(RESULT_SUCCESS);
+        rb.Push(static_cast<u64>(buffer.size()));
+
+        LOG_DEBUG(Service, "called");
+    }
+
+    void Read(Kernel::HLERequestContext& ctx) {
+        IPC::RequestParser rp{ctx};
+
+        u64 offset = rp.Pop<u64>();
+
+        const auto& output_buffer = ctx.BufferDescriptorC()[0];
+
+        ASSERT(offset + output_buffer.Size() <= buffer.size());
+
+        Memory::WriteBlock(output_buffer.Address(), buffer.data() + offset, output_buffer.Size());
+
+        IPC::ResponseBuilder rb{ctx, 2};
+
+        rb.Push(RESULT_SUCCESS);
+
+        LOG_DEBUG(Service, "called");
+    }
+};
+
+class IStorage final : public ServiceFramework<IStorage> {
+public:
+    explicit IStorage(std::vector<u8> buffer)
+        : ServiceFramework("IStorage"), buffer(std::move(buffer)) {
+        static const FunctionInfo functions[] = {
+            {0, &IStorage::Open, "Open"},
+        };
+        RegisterHandlers(functions);
+    }
+
+private:
+    std::vector<u8> buffer;
+
+    void Open(Kernel::HLERequestContext& ctx) {
+        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+
+        rb.Push(RESULT_SUCCESS);
+        rb.PushIpcInterface<AM::IStorageAccessor>(buffer);
+
+        LOG_DEBUG(Service, "called");
+    }
+};
+
+IApplicationFunctions::IApplicationFunctions() : ServiceFramework("IApplicationFunctions") {
+    static const FunctionInfo functions[] = {
+        {1, &IApplicationFunctions::PopLaunchParameter, "PopLaunchParameter"},
+        {21, &IApplicationFunctions::GetDesiredLanguage, "GetDesiredLanguage"},
+        {22, &IApplicationFunctions::SetTerminateResult, "SetTerminateResult"},
+        {66, &IApplicationFunctions::InitializeGamePlayRecording, "InitializeGamePlayRecording"},
+        {67, &IApplicationFunctions::SetGamePlayRecordingState, "SetGamePlayRecordingState"},
+        {40, &IApplicationFunctions::NotifyRunning, "NotifyRunning"},
+    };
+    RegisterHandlers(functions);
+}
+
+void IApplicationFunctions::PopLaunchParameter(Kernel::HLERequestContext& ctx) {
+    constexpr u8 data[0x88] = {
+        0xca, 0x97, 0x94, 0xc7, // Magic
+        1,    0,    0,    0,    // IsAccountSelected (bool)
+        1,    0,    0,    0,    // User Id (word 0)
+        0,    0,    0,    0,    // User Id (word 1)
+        0,    0,    0,    0,    // User Id (word 2)
+        0,    0,    0,    0     // User Id (word 3)
+    };
+
+    std::vector<u8> buffer(data, data + sizeof(data));
+
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+
+    rb.Push(RESULT_SUCCESS);
+    rb.PushIpcInterface<AM::IStorage>(buffer);
+
+    LOG_DEBUG(Service, "called");
+}
+
+void IApplicationFunctions::SetTerminateResult(Kernel::HLERequestContext& ctx) {
+    // Takes an input u32 Result, no output.
+    // For example, in some cases official apps use this with error 0x2A2 then uses svcBreak.
+
+    IPC::RequestParser rp{ctx};
+    u32 result = rp.Pop<u32>();
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(RESULT_SUCCESS);
+
+    LOG_WARNING(Service, "(STUBBED) called, result=0x%08X", result);
+}
+
+void IApplicationFunctions::GetDesiredLanguage(Kernel::HLERequestContext& ctx) {
+    IPC::ResponseBuilder rb{ctx, 4};
+    rb.Push(RESULT_SUCCESS);
+    rb.Push<u64>(SystemLanguage::English);
+    LOG_WARNING(Service, "(STUBBED) called");
+}
+
+void IApplicationFunctions::InitializeGamePlayRecording(Kernel::HLERequestContext& ctx) {
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(RESULT_SUCCESS);
+    LOG_WARNING(Service, "(STUBBED) called");
+}
+
+void IApplicationFunctions::SetGamePlayRecordingState(Kernel::HLERequestContext& ctx) {
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(RESULT_SUCCESS);
+
+    LOG_WARNING(Service, "(STUBBED) called");
+}
+
+void IApplicationFunctions::NotifyRunning(Kernel::HLERequestContext& ctx) {
+    IPC::ResponseBuilder rb{ctx, 3};
+    rb.Push(RESULT_SUCCESS);
+    rb.Push<u8>(0); // Unknown, seems to be ignored by official processes
+
+    LOG_WARNING(Service, "(STUBBED) called");
+}
+
 void InstallInterfaces(SM::ServiceManager& service_manager,
                        std::shared_ptr<NVFlinger::NVFlinger> nvflinger) {
+    std::make_shared<AppletAE>(nvflinger)->InstallAsService(service_manager);
     std::make_shared<AppletOE>(nvflinger)->InstallAsService(service_manager);
 }
 
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h
index 3b8a06c1dc619151eb0b9a3e74c82981ab7b1697..b603c17ddd52f2539e463c13de741ece2fdbfa9c 100644
--- a/src/core/hle/service/am/am.h
+++ b/src/core/hle/service/am/am.h
@@ -7,6 +7,10 @@
 #include <memory>
 #include "core/hle/service/service.h"
 
+namespace Kernel {
+class Event;
+}
+
 namespace Service {
 namespace NVFlinger {
 class NVFlinger;
@@ -14,6 +18,95 @@ class NVFlinger;
 
 namespace AM {
 
+// TODO: Add more languages
+enum SystemLanguage {
+    Japanese = 0,
+    English = 1,
+};
+
+class IWindowController final : public ServiceFramework<IWindowController> {
+public:
+    IWindowController();
+
+private:
+    void GetAppletResourceUserId(Kernel::HLERequestContext& ctx);
+    void AcquireForegroundRights(Kernel::HLERequestContext& ctx);
+};
+
+class IAudioController final : public ServiceFramework<IAudioController> {
+public:
+    IAudioController();
+};
+
+class IDisplayController final : public ServiceFramework<IDisplayController> {
+public:
+    IDisplayController();
+};
+
+class IDebugFunctions final : public ServiceFramework<IDebugFunctions> {
+public:
+    IDebugFunctions();
+};
+
+class ISelfController final : public ServiceFramework<ISelfController> {
+public:
+    ISelfController(std::shared_ptr<NVFlinger::NVFlinger> nvflinger);
+
+private:
+    void SetFocusHandlingMode(Kernel::HLERequestContext& ctx);
+    void SetRestartMessageEnabled(Kernel::HLERequestContext& ctx);
+    void SetPerformanceModeChangedNotification(Kernel::HLERequestContext& ctx);
+    void SetOperationModeChangedNotification(Kernel::HLERequestContext& ctx);
+    void SetOutOfFocusSuspendingEnabled(Kernel::HLERequestContext& ctx);
+    void LockExit(Kernel::HLERequestContext& ctx);
+    void UnlockExit(Kernel::HLERequestContext& ctx);
+    void CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx);
+
+    std::shared_ptr<NVFlinger::NVFlinger> nvflinger;
+};
+
+class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> {
+public:
+    ICommonStateGetter();
+
+private:
+    enum class FocusState : u8 {
+        InFocus = 1,
+        NotInFocus = 2,
+    };
+
+    enum class OperationMode : u8 {
+        Handheld = 0,
+        Docked = 1,
+    };
+
+    void GetEventHandle(Kernel::HLERequestContext& ctx);
+    void ReceiveMessage(Kernel::HLERequestContext& ctx);
+    void GetCurrentFocusState(Kernel::HLERequestContext& ctx);
+    void GetOperationMode(Kernel::HLERequestContext& ctx);
+    void GetPerformanceMode(Kernel::HLERequestContext& ctx);
+
+    Kernel::SharedPtr<Kernel::Event> event;
+};
+
+class ILibraryAppletCreator final : public ServiceFramework<ILibraryAppletCreator> {
+public:
+    ILibraryAppletCreator();
+};
+
+class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> {
+public:
+    IApplicationFunctions();
+
+private:
+    void PopLaunchParameter(Kernel::HLERequestContext& ctx);
+    void SetTerminateResult(Kernel::HLERequestContext& ctx);
+    void GetDesiredLanguage(Kernel::HLERequestContext& ctx);
+    void InitializeGamePlayRecording(Kernel::HLERequestContext& ctx);
+    void SetGamePlayRecordingState(Kernel::HLERequestContext& ctx);
+    void NotifyRunning(Kernel::HLERequestContext& ctx);
+};
+
 /// Registers all AM services with the specified service manager.
 void InstallInterfaces(SM::ServiceManager& service_manager,
                        std::shared_ptr<NVFlinger::NVFlinger> nvflinger);
diff --git a/src/core/hle/service/am/applet_ae.cpp b/src/core/hle/service/am/applet_ae.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a63fb62103e8a834b0f87b77327dc9a8a05cdc71
--- /dev/null
+++ b/src/core/hle/service/am/applet_ae.cpp
@@ -0,0 +1,112 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "common/logging/log.h"
+#include "core/hle/ipc_helpers.h"
+#include "core/hle/service/am/am.h"
+#include "core/hle/service/am/applet_ae.h"
+#include "core/hle/service/nvflinger/nvflinger.h"
+
+namespace Service {
+namespace AM {
+
+class ILibraryAppletProxy final : public ServiceFramework<ILibraryAppletProxy> {
+public:
+    ILibraryAppletProxy(std::shared_ptr<NVFlinger::NVFlinger> nvflinger)
+        : ServiceFramework("ILibraryAppletProxy"), nvflinger(std::move(nvflinger)) {
+        static const FunctionInfo functions[] = {
+            {0, &ILibraryAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"},
+            {1, &ILibraryAppletProxy::GetSelfController, "GetSelfController"},
+            {2, &ILibraryAppletProxy::GetWindowController, "GetWindowController"},
+            {3, &ILibraryAppletProxy::GetAudioController, "GetAudioController"},
+            {4, &ILibraryAppletProxy::GetDisplayController, "GetDisplayController"},
+            {11, &ILibraryAppletProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"},
+            {20, &ILibraryAppletProxy::GetApplicationFunctions, "GetApplicationFunctions"},
+            {1000, &ILibraryAppletProxy::GetDebugFunctions, "GetDebugFunctions"},
+        };
+        RegisterHandlers(functions);
+    }
+
+private:
+    void GetCommonStateGetter(Kernel::HLERequestContext& ctx) {
+        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+        rb.Push(RESULT_SUCCESS);
+        rb.PushIpcInterface<ICommonStateGetter>();
+        LOG_DEBUG(Service, "called");
+    }
+
+    void GetSelfController(Kernel::HLERequestContext& ctx) {
+        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+        rb.Push(RESULT_SUCCESS);
+        rb.PushIpcInterface<ISelfController>(nvflinger);
+        LOG_DEBUG(Service, "called");
+    }
+
+    void GetWindowController(Kernel::HLERequestContext& ctx) {
+        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+        rb.Push(RESULT_SUCCESS);
+        rb.PushIpcInterface<IWindowController>();
+        LOG_DEBUG(Service, "called");
+    }
+
+    void GetAudioController(Kernel::HLERequestContext& ctx) {
+        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+        rb.Push(RESULT_SUCCESS);
+        rb.PushIpcInterface<IAudioController>();
+        LOG_DEBUG(Service, "called");
+    }
+
+    void GetDisplayController(Kernel::HLERequestContext& ctx) {
+        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+        rb.Push(RESULT_SUCCESS);
+        rb.PushIpcInterface<IDisplayController>();
+        LOG_DEBUG(Service, "called");
+    }
+
+    void GetDebugFunctions(Kernel::HLERequestContext& ctx) {
+        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+        rb.Push(RESULT_SUCCESS);
+        rb.PushIpcInterface<IDebugFunctions>();
+        LOG_DEBUG(Service, "called");
+    }
+
+    void GetLibraryAppletCreator(Kernel::HLERequestContext& ctx) {
+        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+        rb.Push(RESULT_SUCCESS);
+        rb.PushIpcInterface<ILibraryAppletCreator>();
+        LOG_DEBUG(Service, "called");
+    }
+
+    void GetApplicationFunctions(Kernel::HLERequestContext& ctx) {
+        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+        rb.Push(RESULT_SUCCESS);
+        rb.PushIpcInterface<IApplicationFunctions>();
+        LOG_DEBUG(Service, "called");
+    }
+
+    std::shared_ptr<NVFlinger::NVFlinger> nvflinger;
+};
+
+void AppletAE::OpenLibraryAppletProxyOld(Kernel::HLERequestContext& ctx) {
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+    rb.Push(RESULT_SUCCESS);
+    rb.PushIpcInterface<ILibraryAppletProxy>(nvflinger);
+    LOG_DEBUG(Service, "called");
+}
+
+AppletAE::AppletAE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger)
+    : ServiceFramework("appletAE"), nvflinger(std::move(nvflinger)) {
+    static const FunctionInfo functions[] = {
+        {100, nullptr, "OpenSystemAppletProxy"},
+        {200, &AppletAE::OpenLibraryAppletProxyOld, "OpenLibraryAppletProxyOld"},
+        {201, nullptr, "OpenLibraryAppletProxy"},
+        {300, nullptr, "OpenOverlayAppletProxy"},
+        {350, nullptr, "OpenSystemApplicationProxy"},
+        {400, nullptr, "CreateSelfLibraryAppletCreatorForDevelop"},
+    };
+    RegisterHandlers(functions);
+}
+
+} // namespace AM
+} // namespace Service
diff --git a/src/core/hle/service/am/applet_ae.h b/src/core/hle/service/am/applet_ae.h
new file mode 100644
index 0000000000000000000000000000000000000000..38fc428fb15b8e618cf0372eb9218cec10ad0526
--- /dev/null
+++ b/src/core/hle/service/am/applet_ae.h
@@ -0,0 +1,30 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <memory>
+#include "core/hle/kernel/hle_ipc.h"
+#include "core/hle/service/service.h"
+
+namespace Service {
+namespace NVFlinger {
+class NVFlinger;
+}
+
+namespace AM {
+
+class AppletAE final : public ServiceFramework<AppletAE> {
+public:
+    AppletAE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger);
+    ~AppletAE() = default;
+
+private:
+    void OpenLibraryAppletProxyOld(Kernel::HLERequestContext& ctx);
+
+    std::shared_ptr<NVFlinger::NVFlinger> nvflinger;
+};
+
+} // namespace AM
+} // namespace Service
diff --git a/src/core/hle/service/am/applet_oe.cpp b/src/core/hle/service/am/applet_oe.cpp
index 15b7701e023f7cecc83506786b34fd7171974e1b..5aa76577015fa126d620bcaeb9cf3debe13ac673 100644
--- a/src/core/hle/service/am/applet_oe.cpp
+++ b/src/core/hle/service/am/applet_oe.cpp
@@ -4,385 +4,13 @@
 
 #include "common/logging/log.h"
 #include "core/hle/ipc_helpers.h"
-#include "core/hle/kernel/event.h"
+#include "core/hle/service/am/am.h"
 #include "core/hle/service/am/applet_oe.h"
-#include "core/hle/service/apm/apm.h"
 #include "core/hle/service/nvflinger/nvflinger.h"
 
 namespace Service {
 namespace AM {
 
-class IWindowController final : public ServiceFramework<IWindowController> {
-public:
-    IWindowController() : ServiceFramework("IWindowController") {
-        static const FunctionInfo functions[] = {
-            {1, &IWindowController::GetAppletResourceUserId, "GetAppletResourceUserId"},
-            {10, &IWindowController::AcquireForegroundRights, "AcquireForegroundRights"},
-        };
-        RegisterHandlers(functions);
-    }
-
-private:
-    void GetAppletResourceUserId(Kernel::HLERequestContext& ctx) {
-        LOG_WARNING(Service, "(STUBBED) called");
-        IPC::ResponseBuilder rb{ctx, 4};
-        rb.Push(RESULT_SUCCESS);
-        rb.Push<u64>(0);
-    }
-
-    void AcquireForegroundRights(Kernel::HLERequestContext& ctx) {
-        LOG_WARNING(Service, "(STUBBED) called");
-        IPC::ResponseBuilder rb{ctx, 2};
-        rb.Push(RESULT_SUCCESS);
-    }
-};
-
-class IAudioController final : public ServiceFramework<IAudioController> {
-public:
-    IAudioController() : ServiceFramework("IAudioController") {}
-};
-
-class IDisplayController final : public ServiceFramework<IDisplayController> {
-public:
-    IDisplayController() : ServiceFramework("IDisplayController") {}
-};
-
-class IDebugFunctions final : public ServiceFramework<IDebugFunctions> {
-public:
-    IDebugFunctions() : ServiceFramework("IDebugFunctions") {}
-};
-
-class ISelfController final : public ServiceFramework<ISelfController> {
-public:
-    ISelfController(std::shared_ptr<NVFlinger::NVFlinger> nvflinger)
-        : ServiceFramework("ISelfController"), nvflinger(std::move(nvflinger)) {
-        static const FunctionInfo functions[] = {
-            {1, &ISelfController::LockExit, "LockExit"},
-            {2, &ISelfController::UnlockExit, "UnlockExit"},
-            {11, &ISelfController::SetOperationModeChangedNotification,
-             "SetOperationModeChangedNotification"},
-            {12, &ISelfController::SetPerformanceModeChangedNotification,
-             "SetPerformanceModeChangedNotification"},
-            {13, &ISelfController::SetFocusHandlingMode, "SetFocusHandlingMode"},
-            {14, &ISelfController::SetRestartMessageEnabled, "SetRestartMessageEnabled"},
-            {16, &ISelfController::SetOutOfFocusSuspendingEnabled,
-             "SetOutOfFocusSuspendingEnabled"},
-            {40, &ISelfController::CreateManagedDisplayLayer, "CreateManagedDisplayLayer"},
-        };
-        RegisterHandlers(functions);
-    }
-
-private:
-    void SetFocusHandlingMode(Kernel::HLERequestContext& ctx) {
-        // Takes 3 input u8s with each field located immediately after the previous u8, these are
-        // bool flags. No output.
-
-        IPC::RequestParser rp{ctx};
-
-        struct FocusHandlingModeParams {
-            u8 unknown0;
-            u8 unknown1;
-            u8 unknown2;
-        };
-        auto flags = rp.PopRaw<FocusHandlingModeParams>();
-
-        IPC::ResponseBuilder rb{ctx, 2};
-        rb.Push(RESULT_SUCCESS);
-
-        LOG_WARNING(Service, "(STUBBED) called");
-    }
-
-    void SetRestartMessageEnabled(Kernel::HLERequestContext& ctx) {
-        IPC::ResponseBuilder rb{ctx, 2};
-        rb.Push(RESULT_SUCCESS);
-
-        LOG_WARNING(Service, "(STUBBED) called");
-    }
-
-    void SetPerformanceModeChangedNotification(Kernel::HLERequestContext& ctx) {
-        IPC::RequestParser rp{ctx};
-
-        bool flag = rp.Pop<bool>();
-
-        IPC::ResponseBuilder rb{ctx, 2};
-        rb.Push(RESULT_SUCCESS);
-
-        LOG_WARNING(Service, "(STUBBED) called flag=%u", static_cast<u32>(flag));
-    }
-
-    void SetOperationModeChangedNotification(Kernel::HLERequestContext& ctx) {
-        IPC::RequestParser rp{ctx};
-
-        bool flag = rp.Pop<bool>();
-
-        IPC::ResponseBuilder rb{ctx, 2};
-        rb.Push(RESULT_SUCCESS);
-
-        LOG_WARNING(Service, "(STUBBED) called flag=%u", static_cast<u32>(flag));
-    }
-
-    void SetOutOfFocusSuspendingEnabled(Kernel::HLERequestContext& ctx) {
-        // Takes 3 input u8s with each field located immediately after the previous u8, these are
-        // bool flags. No output.
-        IPC::RequestParser rp{ctx};
-
-        bool enabled = rp.Pop<bool>();
-
-        IPC::ResponseBuilder rb{ctx, 2};
-        rb.Push(RESULT_SUCCESS);
-
-        LOG_WARNING(Service, "(STUBBED) called enabled=%u", static_cast<u32>(enabled));
-    }
-
-    void LockExit(Kernel::HLERequestContext& ctx) {
-        IPC::ResponseBuilder rb{ctx, 2};
-        rb.Push(RESULT_SUCCESS);
-
-        LOG_WARNING(Service, "(STUBBED) called");
-    }
-
-    void UnlockExit(Kernel::HLERequestContext& ctx) {
-        IPC::ResponseBuilder rb{ctx, 2};
-        rb.Push(RESULT_SUCCESS);
-
-        LOG_WARNING(Service, "(STUBBED) called");
-    }
-
-    void CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx) {
-        // TODO(Subv): Find out how AM determines the display to use, for now just create the layer
-        // in the Default display.
-        u64 display_id = nvflinger->OpenDisplay("Default");
-        u64 layer_id = nvflinger->CreateLayer(display_id);
-
-        IPC::ResponseBuilder rb{ctx, 4};
-        rb.Push(RESULT_SUCCESS);
-        rb.Push(layer_id);
-
-        LOG_WARNING(Service, "(STUBBED) called");
-    }
-
-    std::shared_ptr<NVFlinger::NVFlinger> nvflinger;
-};
-
-class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> {
-public:
-    ICommonStateGetter() : ServiceFramework("ICommonStateGetter") {
-        static const FunctionInfo functions[] = {
-            {0, &ICommonStateGetter::GetEventHandle, "GetEventHandle"},
-            {1, &ICommonStateGetter::ReceiveMessage, "ReceiveMessage"},
-            {5, &ICommonStateGetter::GetOperationMode, "GetOperationMode"},
-            {6, &ICommonStateGetter::GetPerformanceMode, "GetPerformanceMode"},
-            {9, &ICommonStateGetter::GetCurrentFocusState, "GetCurrentFocusState"},
-        };
-        RegisterHandlers(functions);
-
-        event = Kernel::Event::Create(Kernel::ResetType::OneShot, "ICommonStateGetter:Event");
-    }
-
-private:
-    enum class FocusState : u8 {
-        InFocus = 1,
-        NotInFocus = 2,
-    };
-
-    enum class OperationMode : u8 {
-        Handheld = 0,
-        Docked = 1,
-    };
-
-    void GetEventHandle(Kernel::HLERequestContext& ctx) {
-        event->Signal();
-
-        IPC::ResponseBuilder rb{ctx, 2, 1};
-        rb.Push(RESULT_SUCCESS);
-        rb.PushCopyObjects(event);
-
-        LOG_WARNING(Service, "(STUBBED) called");
-    }
-
-    void ReceiveMessage(Kernel::HLERequestContext& ctx) {
-        IPC::ResponseBuilder rb{ctx, 3};
-        rb.Push(RESULT_SUCCESS);
-        rb.Push<u32>(15);
-
-        LOG_WARNING(Service, "(STUBBED) called");
-    }
-
-    void GetCurrentFocusState(Kernel::HLERequestContext& ctx) {
-        IPC::ResponseBuilder rb{ctx, 3};
-        rb.Push(RESULT_SUCCESS);
-        rb.Push(static_cast<u8>(FocusState::InFocus));
-
-        LOG_WARNING(Service, "(STUBBED) called");
-    }
-
-    void GetOperationMode(Kernel::HLERequestContext& ctx) {
-        IPC::ResponseBuilder rb{ctx, 3};
-        rb.Push(RESULT_SUCCESS);
-        rb.Push(static_cast<u8>(OperationMode::Handheld));
-
-        LOG_WARNING(Service, "(STUBBED) called");
-    }
-
-    void GetPerformanceMode(Kernel::HLERequestContext& ctx) {
-        IPC::ResponseBuilder rb{ctx, 3};
-        rb.Push(RESULT_SUCCESS);
-        rb.Push(static_cast<u32>(APM::PerformanceMode::Handheld));
-
-        LOG_WARNING(Service, "(STUBBED) called");
-    }
-
-    Kernel::SharedPtr<Kernel::Event> event;
-};
-
-class IStorageAccessor final : public ServiceFramework<IStorageAccessor> {
-public:
-    explicit IStorageAccessor(std::vector<u8> buffer)
-        : ServiceFramework("IStorageAccessor"), buffer(std::move(buffer)) {
-        static const FunctionInfo functions[] = {
-            {0, &IStorageAccessor::GetSize, "GetSize"},
-            {11, &IStorageAccessor::Read, "Read"},
-        };
-        RegisterHandlers(functions);
-    }
-
-private:
-    std::vector<u8> buffer;
-
-    void GetSize(Kernel::HLERequestContext& ctx) {
-        IPC::ResponseBuilder rb{ctx, 4};
-
-        rb.Push(RESULT_SUCCESS);
-        rb.Push(static_cast<u64>(buffer.size()));
-
-        LOG_DEBUG(Service, "called");
-    }
-
-    void Read(Kernel::HLERequestContext& ctx) {
-        IPC::RequestParser rp{ctx};
-
-        u64 offset = rp.Pop<u64>();
-
-        const auto& output_buffer = ctx.BufferDescriptorC()[0];
-
-        ASSERT(offset + output_buffer.Size() <= buffer.size());
-
-        Memory::WriteBlock(output_buffer.Address(), buffer.data() + offset, output_buffer.Size());
-
-        IPC::ResponseBuilder rb{ctx, 2};
-
-        rb.Push(RESULT_SUCCESS);
-
-        LOG_DEBUG(Service, "called");
-    }
-};
-
-class IStorage final : public ServiceFramework<IStorage> {
-public:
-    explicit IStorage(std::vector<u8> buffer)
-        : ServiceFramework("IStorage"), buffer(std::move(buffer)) {
-        static const FunctionInfo functions[] = {
-            {0, &IStorage::Open, "Open"},
-        };
-        RegisterHandlers(functions);
-    }
-
-private:
-    std::vector<u8> buffer;
-
-    void Open(Kernel::HLERequestContext& ctx) {
-        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-
-        rb.Push(RESULT_SUCCESS);
-        rb.PushIpcInterface<AM::IStorageAccessor>(buffer);
-
-        LOG_DEBUG(Service, "called");
-    }
-};
-
-class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> {
-public:
-    IApplicationFunctions() : ServiceFramework("IApplicationFunctions") {
-        static const FunctionInfo functions[] = {
-            {1, &IApplicationFunctions::PopLaunchParameter, "PopLaunchParameter"},
-            {21, &IApplicationFunctions::GetDesiredLanguage, "GetDesiredLanguage"},
-            {22, &IApplicationFunctions::SetTerminateResult, "SetTerminateResult"},
-            {66, &IApplicationFunctions::InitializeGamePlayRecording,
-             "InitializeGamePlayRecording"},
-            {67, &IApplicationFunctions::SetGamePlayRecordingState, "SetGamePlayRecordingState"},
-            {40, &IApplicationFunctions::NotifyRunning, "NotifyRunning"},
-        };
-        RegisterHandlers(functions);
-    }
-
-private:
-    void PopLaunchParameter(Kernel::HLERequestContext& ctx) {
-        constexpr u8 data[0x88] = {
-            0xca, 0x97, 0x94, 0xc7, // Magic
-            1,    0,    0,    0,    // IsAccountSelected (bool)
-            1,    0,    0,    0,    // User Id (word 0)
-            0,    0,    0,    0,    // User Id (word 1)
-            0,    0,    0,    0,    // User Id (word 2)
-            0,    0,    0,    0     // User Id (word 3)
-        };
-
-        std::vector<u8> buffer(data, data + sizeof(data));
-
-        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-
-        rb.Push(RESULT_SUCCESS);
-        rb.PushIpcInterface<AM::IStorage>(buffer);
-
-        LOG_DEBUG(Service, "called");
-    }
-
-    void SetTerminateResult(Kernel::HLERequestContext& ctx) {
-        // Takes an input u32 Result, no output.
-        // For example, in some cases official apps use this with error 0x2A2 then uses svcBreak.
-
-        IPC::RequestParser rp{ctx};
-        u32 result = rp.Pop<u32>();
-
-        IPC::ResponseBuilder rb{ctx, 2};
-        rb.Push(RESULT_SUCCESS);
-
-        LOG_WARNING(Service, "(STUBBED) called, result=0x%08X", result);
-    }
-
-    void GetDesiredLanguage(Kernel::HLERequestContext& ctx) {
-        IPC::ResponseBuilder rb{ctx, 4};
-        rb.Push(RESULT_SUCCESS);
-        rb.Push<u64>(SystemLanguage::English);
-        LOG_WARNING(Service, "(STUBBED) called");
-    }
-
-    void InitializeGamePlayRecording(Kernel::HLERequestContext& ctx) {
-        IPC::ResponseBuilder rb{ctx, 2};
-        rb.Push(RESULT_SUCCESS);
-        LOG_WARNING(Service, "(STUBBED) called");
-    }
-
-    void SetGamePlayRecordingState(Kernel::HLERequestContext& ctx) {
-        IPC::ResponseBuilder rb{ctx, 2};
-        rb.Push(RESULT_SUCCESS);
-
-        LOG_WARNING(Service, "(STUBBED) called");
-    }
-
-    void NotifyRunning(Kernel::HLERequestContext& ctx) {
-        IPC::ResponseBuilder rb{ctx, 3};
-        rb.Push(RESULT_SUCCESS);
-        rb.Push<u8>(0); // Unknown, seems to be ignored by official processes
-
-        LOG_WARNING(Service, "(STUBBED) called");
-    }
-};
-
-class ILibraryAppletCreator final : public ServiceFramework<ILibraryAppletCreator> {
-public:
-    ILibraryAppletCreator() : ServiceFramework("ILibraryAppletCreator") {}
-};
-
 class IApplicationProxy final : public ServiceFramework<IApplicationProxy> {
 public:
     IApplicationProxy(std::shared_ptr<NVFlinger::NVFlinger> nvflinger)
diff --git a/src/core/hle/service/am/applet_oe.h b/src/core/hle/service/am/applet_oe.h
index 8083135c339d6ef0a9009de1dc684fffab8d6142..d2ab44c674b82320dbf81f77d8aad2599954fc1a 100644
--- a/src/core/hle/service/am/applet_oe.h
+++ b/src/core/hle/service/am/applet_oe.h
@@ -15,12 +15,6 @@ class NVFlinger;
 
 namespace AM {
 
-// TODO: Add more languages
-enum SystemLanguage {
-    Japanese = 0,
-    English = 1,
-};
-
 class AppletOE final : public ServiceFramework<AppletOE> {
 public:
     AppletOE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger);