diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index b3807c2040b935e689b6e5404747237c7b7051ca..f4be926e4db4543e7a000187e1ddaa04e40d5588 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -181,10 +181,10 @@ add_library(core STATIC
     hle/service/nvflinger/buffer_queue.h
     hle/service/nvflinger/nvflinger.cpp
     hle/service/nvflinger/nvflinger.h
+    hle/service/pctl/module.cpp
+    hle/service/pctl/module.h
     hle/service/pctl/pctl.cpp
     hle/service/pctl/pctl.h
-    hle/service/pctl/pctl_a.cpp
-    hle/service/pctl/pctl_a.h
     hle/service/service.cpp
     hle/service/service.h
     hle/service/set/set.cpp
diff --git a/src/core/hle/service/pctl/pctl_a.cpp b/src/core/hle/service/pctl/module.cpp
similarity index 83%
rename from src/core/hle/service/pctl/pctl_a.cpp
rename to src/core/hle/service/pctl/module.cpp
index 24a6cf3103e021b8e88fe05228819c3d71265b53..dd20d5ae79603c0e757973a4f71e3909ab8d3907 100644
--- a/src/core/hle/service/pctl/pctl_a.cpp
+++ b/src/core/hle/service/pctl/module.cpp
@@ -4,7 +4,8 @@
 
 #include "common/logging/log.h"
 #include "core/hle/ipc_helpers.h"
-#include "core/hle/service/pctl/pctl_a.h"
+#include "core/hle/service/pctl/module.h"
+#include "core/hle/service/pctl/pctl.h"
 
 namespace Service::PCTL {
 
@@ -12,7 +13,7 @@ class IParentalControlService final : public ServiceFramework<IParentalControlSe
 public:
     IParentalControlService() : ServiceFramework("IParentalControlService") {
         static const FunctionInfo functions[] = {
-            {1, nullptr, "Initialize"},
+            {1, &IParentalControlService::Initialize, "Initialize"},
             {1001, nullptr, "CheckFreeCommunicationPermission"},
             {1002, nullptr, "ConfirmLaunchApplicationPermission"},
             {1003, nullptr, "ConfirmResumeApplicationPermission"},
@@ -108,20 +109,38 @@ public:
         };
         RegisterHandlers(functions);
     }
+
+private:
+    void Initialize(Kernel::HLERequestContext& ctx) {
+        NGLOG_WARNING(Service_PCTL, "(STUBBED) called");
+        IPC::ResponseBuilder rb{ctx, 2, 0, 0};
+        rb.Push(RESULT_SUCCESS);
+    }
 };
-void PCTL_A::CreateService(Kernel::HLERequestContext& ctx) {
+
+void Module::Interface::CreateService(Kernel::HLERequestContext& ctx) {
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+    rb.Push(RESULT_SUCCESS);
+    rb.PushIpcInterface<IParentalControlService>();
+    NGLOG_DEBUG(Service_PCTL, "called");
+}
+
+void Module::Interface::CreateServiceWithoutInitialize(Kernel::HLERequestContext& ctx) {
     IPC::ResponseBuilder rb{ctx, 2, 0, 1};
     rb.Push(RESULT_SUCCESS);
     rb.PushIpcInterface<IParentalControlService>();
     NGLOG_DEBUG(Service_PCTL, "called");
 }
 
-PCTL_A::PCTL_A() : ServiceFramework("pctl:a") {
-    static const FunctionInfo functions[] = {
-        {0, &PCTL_A::CreateService, "CreateService"},
-        {1, nullptr, "CreateServiceWithoutInitialize"},
-    };
-    RegisterHandlers(functions);
+Module::Interface::Interface(std::shared_ptr<Module> module, const char* name)
+    : ServiceFramework(name), module(std::move(module)) {}
+
+void InstallInterfaces(SM::ServiceManager& service_manager) {
+    auto module = std::make_shared<Module>();
+    std::make_shared<PCTL>(module, "pctl")->InstallAsService(service_manager);
+    std::make_shared<PCTL>(module, "pctl:a")->InstallAsService(service_manager);
+    std::make_shared<PCTL>(module, "pctl:r")->InstallAsService(service_manager);
+    std::make_shared<PCTL>(module, "pctl:s")->InstallAsService(service_manager);
 }
 
 } // namespace Service::PCTL
diff --git a/src/core/hle/service/pctl/module.h b/src/core/hle/service/pctl/module.h
new file mode 100644
index 0000000000000000000000000000000000000000..68da628a838dfaafd6b39216398fa21776908439
--- /dev/null
+++ b/src/core/hle/service/pctl/module.h
@@ -0,0 +1,28 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service::PCTL {
+
+class Module final {
+public:
+    class Interface : public ServiceFramework<Interface> {
+    public:
+        Interface(std::shared_ptr<Module> module, const char* name);
+
+        void CreateService(Kernel::HLERequestContext& ctx);
+        void CreateServiceWithoutInitialize(Kernel::HLERequestContext& ctx);
+
+    protected:
+        std::shared_ptr<Module> module;
+    };
+};
+
+/// Registers all PCTL services with the specified service manager.
+void InstallInterfaces(SM::ServiceManager& service_manager);
+
+} // namespace Service::PCTL
diff --git a/src/core/hle/service/pctl/pctl.cpp b/src/core/hle/service/pctl/pctl.cpp
index 6ee81866d4893e9a061f6cb0c316401e32ea6b16..de2741d66af21210967ac429c4a85d32cf10d6bd 100644
--- a/src/core/hle/service/pctl/pctl.cpp
+++ b/src/core/hle/service/pctl/pctl.cpp
@@ -3,12 +3,15 @@
 // Refer to the license.txt file included.
 
 #include "core/hle/service/pctl/pctl.h"
-#include "core/hle/service/pctl/pctl_a.h"
 
 namespace Service::PCTL {
 
-void InstallInterfaces(SM::ServiceManager& service_manager) {
-    std::make_shared<PCTL_A>()->InstallAsService(service_manager);
+PCTL::PCTL(std::shared_ptr<Module> module, const char* name)
+    : Module::Interface(std::move(module), name) {
+    static const FunctionInfo functions[] = {
+        {0, &PCTL::CreateService, "CreateService"},
+        {1, &PCTL::CreateServiceWithoutInitialize, "CreateServiceWithoutInitialize"},
+    };
+    RegisterHandlers(functions);
 }
-
 } // namespace Service::PCTL
diff --git a/src/core/hle/service/pctl/pctl.h b/src/core/hle/service/pctl/pctl.h
index f0a84b1159a806a768d0eb5263357c3c3e33a434..8ddf691287b40851e5fb7f91c9bd52df62b17fd8 100644
--- a/src/core/hle/service/pctl/pctl.h
+++ b/src/core/hle/service/pctl/pctl.h
@@ -4,11 +4,13 @@
 
 #pragma once
 
-#include "core/hle/service/service.h"
+#include "core/hle/service/pctl/module.h"
 
 namespace Service::PCTL {
 
-/// Registers all PCTL services with the specified service manager.
-void InstallInterfaces(SM::ServiceManager& service_manager);
+class PCTL final : public Module::Interface {
+public:
+    explicit PCTL(std::shared_ptr<Module> module, const char* name);
+};
 
 } // namespace Service::PCTL
diff --git a/src/core/hle/service/pctl/pctl_a.h b/src/core/hle/service/pctl/pctl_a.h
deleted file mode 100644
index 09ed82e1b0871f605bf111066b22724bc10fab16..0000000000000000000000000000000000000000
--- a/src/core/hle/service/pctl/pctl_a.h
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2018 yuzu emulator team
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include "core/hle/service/service.h"
-
-namespace Service::PCTL {
-
-class PCTL_A final : public ServiceFramework<PCTL_A> {
-public:
-    PCTL_A();
-    ~PCTL_A() = default;
-
-private:
-    void CreateService(Kernel::HLERequestContext& ctx);
-};
-
-} // namespace Service::PCTL
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index 5817819fee41178ec79067f324f089d147ec4965..a85c406bebf321468b0bff8cbe35b14e8f4fc0e5 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -29,7 +29,7 @@
 #include "core/hle/service/nifm/nifm.h"
 #include "core/hle/service/ns/ns.h"
 #include "core/hle/service/nvdrv/nvdrv.h"
-#include "core/hle/service/pctl/pctl.h"
+#include "core/hle/service/pctl/module.h"
 #include "core/hle/service/service.h"
 #include "core/hle/service/set/settings.h"
 #include "core/hle/service/sm/controller.h"