diff --git a/src/core/core.vcxproj b/src/core/core.vcxproj
index be750b24fbf5206610b582806d2d15d1d4ad0c1f..da3cc7a2662dbee087ef1372406fbeb9ca40797a 100644
--- a/src/core/core.vcxproj
+++ b/src/core/core.vcxproj
@@ -155,6 +155,7 @@
     <ClCompile Include="hle\hle.cpp" />
     <ClCompile Include="hle\service\apt.cpp" />
     <ClCompile Include="hle\service\service.cpp" />
+    <ClCompile Include="hle\service\srv.cpp" />
     <ClCompile Include="hle\syscall.cpp" />
     <ClCompile Include="hw\hw.cpp" />
     <ClCompile Include="hw\hw_lcd.cpp" />
@@ -190,6 +191,7 @@
     <ClInclude Include="hle\hle.h" />
     <ClInclude Include="hle\service\apt.h" />
     <ClInclude Include="hle\service\service.h" />
+    <ClInclude Include="hle\service\srv.h" />
     <ClInclude Include="hle\syscall.h" />
     <ClInclude Include="hw\hw.h" />
     <ClInclude Include="hw\hw_lcd.h" />
diff --git a/src/core/core.vcxproj.filters b/src/core/core.vcxproj.filters
index 29d680935fa959e40805b32a643347c1f7ef79c1..fa20ab68674a85800f6b8885bdc3e5da00bc00ff 100644
--- a/src/core/core.vcxproj.filters
+++ b/src/core/core.vcxproj.filters
@@ -93,6 +93,9 @@
     <ClCompile Include="hle\service\apt.cpp">
       <Filter>hle\service</Filter>
     </ClCompile>
+    <ClCompile Include="hle\service\srv.cpp">
+      <Filter>hle\service</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="arm\disassembler\arm_disasm.h">
@@ -181,6 +184,9 @@
     <ClInclude Include="hle\service\apt.h">
       <Filter>hle\service</Filter>
     </ClInclude>
+    <ClInclude Include="hle\service\srv.h">
+      <Filter>hle\service</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <Text Include="CMakeLists.txt" />
diff --git a/src/core/hle/service/apt.cpp b/src/core/hle/service/apt.cpp
index 5e37b838ac235b41a5c3200fe8fc8a15eb21ba7e..b1e49db97af69a7cf679fc9af8643ca9c3222c34 100644
--- a/src/core/hle/service/apt.cpp
+++ b/src/core/hle/service/apt.cpp
@@ -10,8 +10,89 @@
 
 namespace Service {
 
+const HLE::FunctionDef APT_U_Table[] = {
+    {0x00010040, NULL,      "GetLockHandle"},
+    {0x00020080, NULL,      "Initialize"},
+    {0x00030040, NULL,      "Enable"},
+    {0x00040040, NULL,      "Finalize"},
+    {0x00050040, NULL,      "GetAppletManInfo"},
+    {0x00060040, NULL,      "GetAppletInfo"},
+    {0x00070000, NULL,      "GetLastSignaledAppletId"},
+    {0x00080000, NULL,      "CountRegisteredApplet"},
+    {0x00090040, NULL,      "IsRegistered"},
+    {0x000A0040, NULL,      "GetAttribute"},
+    {0x000B0040, NULL,      "InquireNotification"},
+    {0x000C0104, NULL,      "SendParameter"},
+    {0x000D0080, NULL,      "ReceiveParameter"},
+    {0x000E0080, NULL,      "GlanceParameter"},
+    {0x000F0100, NULL,      "CancelParameter"},
+    {0x001000C2, NULL,      "DebugFunc"},
+    {0x001100C0, NULL,      "MapProgramIdForDebug"},
+    {0x00120040, NULL,      "SetHomeMenuAppletIdForDebug"},
+    {0x00130000, NULL,      "GetPreparationState"},
+    {0x00140040, NULL,      "SetPreparationState"},
+    {0x00150140, NULL,      "PrepareToStartApplication"},
+    {0x00160040, NULL,      "PreloadLibraryApplet"},
+    {0x00170040, NULL,      "FinishPreloadingLibraryApplet"},
+    {0x00180040, NULL,      "PrepareToStartLibraryApplet"},
+    {0x00190040, NULL,      "PrepareToStartSystemApplet"},
+    {0x001A0000, NULL,      "PrepareToStartNewestHomeMenu"},
+    {0x001B00C4, NULL,      "StartApplication"},
+    {0x001C0000, NULL,      "WakeupApplication"},
+    {0x001D0000, NULL,      "CancelApplication"},
+    {0x001E0084, NULL,      "StartLibraryApplet"},
+    {0x001F0084, NULL,      "StartSystemApplet"},
+    {0x00200044, NULL,      "StartNewestHomeMenu"},
+    {0x00210000, NULL,      "OrderToCloseApplication"},
+    {0x00220040, NULL,      "PrepareToCloseApplication"},
+    {0x00230040, NULL,      "PrepareToJumpToApplication"},
+    {0x00240044, NULL,      "JumpToApplication"},
+    {0x002500C0, NULL,      "PrepareToCloseLibraryApplet"},
+    {0x00260000, NULL,      "PrepareToCloseSystemApplet"},
+    {0x00270044, NULL,      "CloseApplication"},
+    {0x00280044, NULL,      "CloseLibraryApplet"},
+    {0x00290044, NULL,      "CloseSystemApplet"},
+    {0x002A0000, NULL,      "OrderToCloseSystemApplet"},
+    {0x002B0000, NULL,      "PrepareToJumpToHomeMenu"},
+    {0x002C0044, NULL,      "JumpToHomeMenu"},
+    {0x002D0000, NULL,      "PrepareToLeaveHomeMenu"},
+    {0x002E0044, NULL,      "LeaveHomeMenu"},
+    {0x002F0040, NULL,      "PrepareToLeaveResidentApplet"},
+    {0x00300044, NULL,      "LeaveResidentApplet"},
+    {0x00310100, NULL,      "PrepareToDoApplicationJump"},
+    {0x00320084, NULL,      "DoApplicationJump"},
+    {0x00330000, NULL,      "GetProgramIdOnApplicationJump"},
+    {0x00340084, NULL,      "SendDeliverArg"},
+    {0x00350080, NULL,      "ReceiveDeliverArg"},
+    {0x00360040, NULL,      "LoadSysMenuArg"},
+    {0x00370042, NULL,      "StoreSysMenuArg"},
+    {0x00380040, NULL,      "PreloadResidentApplet"},
+    {0x00390040, NULL,      "PrepareToStartResidentApplet"},
+    {0x003A0044, NULL,      "StartResidentApplet"},
+    {0x003B0040, NULL,      "CancelLibraryApplet"},
+    {0x003C0042, NULL,      "SendDspSleep"},
+    {0x003D0042, NULL,      "SendDspWakeUp"},
+    {0x003E0080, NULL,      "ReplySleepQuery"},
+    {0x003F0040, NULL,      "ReplySleepNotificationComplete"},
+    {0x00400042, NULL,      "SendCaptureBufferInfo"},
+    {0x00410040, NULL,      "ReceiveCaptureBufferInfo"},
+    {0x00420080, NULL,      "SleepSystem"},
+    {0x00430040, NULL,      "NotifyToWait"},
+    {0x00440000, NULL,      "GetSharedFont"},
+    {0x00450040, NULL,      "GetWirelessRebootInfo"},
+    {0x00460104, NULL,      "Wrap"},
+    {0x00470104, NULL,      "Unwrap"},
+    {0x00480100, NULL,      "GetProgramInfo"},
+    {0x00490180, NULL,      "Reboot"},
+    {0x004A0040, NULL,      "GetCaptureInfo"},
+    {0x004B00C2, NULL,      "AppletUtility"},
+    {0x004C0000, NULL,      "SetFatalErrDispMode"},
+    {0x004D0080, NULL,      "GetAppletProgramInfo"},
+    {0x004E0000, NULL,      "HardwareResetAsync"},
+};
+
 // Returns handle to APT Mutex. Not imlemented.
-Syscall::Result APT::GetLockHandle() {
+Syscall::Result APT_U::GetLockHandle() {
     return 0x00000000;
 }
 
@@ -19,22 +100,22 @@ Syscall::Result APT::GetLockHandle() {
  * Called when svcSendSyncRequest is called, loads command buffer and executes comand
  * @return Return result of svcSendSyncRequest passed back to user app
  */
-Syscall::Result APT::Sync() {
+Syscall::Result APT_U::Sync() {
     Syscall::Result res = 0;
     u32* cmd_buff = (u32*)HLE::GetPointer(HLE::CMD_BUFFER_ADDR + CMD_OFFSET);
 
     switch(cmd_buff[0]) {
     case CMD_HEADER_INIT:
-        NOTICE_LOG(OSHLE, "APT::Sync - Initialize");
+        NOTICE_LOG(OSHLE, "APT_U::Sync - Initialize");
         break;
 
     case CMD_HEADER_GET_LOCK_HANDLE:
-        NOTICE_LOG(OSHLE, "APT::Sync - GetLockHandle");
+        NOTICE_LOG(OSHLE, "APT_U::Sync - GetLockHandle");
         cmd_buff[5] = GetLockHandle();
         break;
 
     default:
-        ERROR_LOG(OSHLE, "APT::Sync - Unknown command 0x%08X", cmd_buff[0]);
+        ERROR_LOG(OSHLE, "APT_U::Sync - Unknown command 0x%08X", cmd_buff[0]);
         res = -1;
         break;
     }
diff --git a/src/core/hle/service/apt.h b/src/core/hle/service/apt.h
index 3730bc30e21b5a10c319aeb77b29d1d77151e2c7..0e1f205c726ee3327a85521ede11f1e6cfe726b2 100644
--- a/src/core/hle/service/apt.h
+++ b/src/core/hle/service/apt.h
@@ -17,13 +17,13 @@ namespace Service {
 // exactly the same, however certain commands are only accessible with APT:S(NS module will call 
 // svcBreak when the command isn't accessible). See http://3dbrew.org/wiki/NS#APT_Services.
 
-class APT : public Interface {
+class APT_U : public Interface {
 public:
 
-    APT() {
+    APT_U() {
     }
 
-    ~APT() {
+    ~APT_U() {
     }
 
     enum {
@@ -44,14 +44,6 @@ public:
         CMD_HEADER_CLOSE_APP                    = 0x00270044,   ///< Close application
     };
 
-    /**
-     * Gets the string name used by CTROS for the APT service
-     * @return String name of service
-     */
-    std::string GetName() const {
-        return "APT";
-    }
-
     /**
      * Gets the string port name used by CTROS for the APT service
      * @return Port name of service
@@ -68,10 +60,9 @@ public:
 
 private:
 
-
     Syscall::Result GetLockHandle();
 
-
+    DISALLOW_COPY_AND_ASSIGN(APT_U);
 };
 
 } // namespace
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index 44c7c8627c4433200e3bb35da8cc44be147b90c6..799dbe90e78ccd925c49be3f2dbfec77a69b1b1f 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -4,10 +4,12 @@
 
 #include "common/common.h"
 #include "common/log.h"
+#include "common/string_util.h"
 
 #include "core/hle/hle.h"
 #include "core/hle/service/service.h"
 #include "core/hle/service/apt.h"
+#include "core/hle/service/srv.h"
 
 namespace Service {
 
@@ -64,84 +66,6 @@ Interface* Manager::FetchFromPortName(std::string port_name) {
     return FetchFromUID(itr->second);
 }
 
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Interface to "SRV" service
-
-class SRV : public Interface {
-
-public:
-
-    SRV() {
-    }
-
-    ~SRV() {
-    }
-
-    enum {
-        CMD_OFFSET              = 0x80,
-        CMD_HEADER_INIT         = 0x10002,  ///< Command header to initialize SRV service
-        CMD_HEADER_GET_HANDLE   = 0x50100,  ///< Command header to get handle of other services
-    };
-
-    /**
-     * Gets the string name used by CTROS for a service
-     * @return String name of service
-     */
-    std::string GetName() const {
-        return "ServiceManager";
-    }
-
-    /**
-     * Gets the string name used by CTROS for a service
-     * @return Port name of service
-     */
-    std::string GetPortName() const {
-        return "srv:";
-    }
-
-    /**
-     * Called when svcSendSyncRequest is called, loads command buffer and executes comand
-     * @return Return result of svcSendSyncRequest passed back to user app
-     */
-    Syscall::Result Sync() {
-        Syscall::Result res = 0;
-        u32* cmd_buff = (u32*)HLE::GetPointer(HLE::CMD_BUFFER_ADDR + CMD_OFFSET);
-
-        switch (cmd_buff[0]) {
-
-        case CMD_HEADER_INIT:
-            NOTICE_LOG(OSHLE, "SRV::Sync - Initialize");
-            break;
-
-        case CMD_HEADER_GET_HANDLE:
-        {
-            const char* port_name = (const char*)&cmd_buff[1];
-            Interface* service = g_manager->FetchFromPortName(port_name);
-
-            NOTICE_LOG(OSHLE, "SRV::Sync - GetHandle - port: %s, handle: 0x%08X", port_name, 
-                service->GetUID());
-
-            if (NULL != service) {
-                cmd_buff[3] = service->GetUID();
-            } else {
-                ERROR_LOG(OSHLE, "Service %s does not exist", port_name);
-                res = -1;
-            }
-            break;
-        }
-
-        default:
-            ERROR_LOG(OSHLE, "SRV::Sync - Unknown command 0x%08X", cmd_buff[0]);
-            res = -1;
-            break;
-        }
-
-        cmd_buff[1] = res;
-
-        return res;
-    }
-     
-};
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 // Module interface
@@ -149,8 +73,8 @@ public:
 /// Initialize ServiceManager
 void Init() {
     g_manager = new Manager;
-    g_manager->AddService(new SRV);
-    g_manager->AddService(new APT);
+    g_manager->AddService(new SRV::Interface);
+    g_manager->AddService(new APT_U);
     NOTICE_LOG(HLE, "Services initialized OK");
 }
 
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h
index 365583ed23c22531be3aadb6a2cc9096db35ed8f..9368a9f0f5ec4206bd47f139e0174783ab4c34b9 100644
--- a/src/core/hle/service/service.h
+++ b/src/core/hle/service/service.h
@@ -37,14 +37,6 @@ public:
         return (NativeUID)m_uid;
     }
 
-    /**
-     * Gets the string name used by CTROS for a service
-     * @return String name of service
-     */
-    virtual std::string GetName() const {
-        return "[UNKNOWN SERVICE NAME]";
-    }
-
     /**
      * Gets the string name used by CTROS for a service
      * @return Port name of service
@@ -59,8 +51,19 @@ public:
      */
     virtual Syscall::Result Sync() = 0;
 
+protected:
+    /**
+     * Registers the functions in the service
+     */
+    void Register(const HLE::FunctionDef* functions, int len) {
+        for (int i = 0; i < len; i++) {
+            m_functions[functions[i].id] = functions[i];
+        }
+    }
+
 private:
     u32 m_uid;
+    std::map<u32, HLE::FunctionDef> m_functions;
 };
 
 /// Simple class to manage accessing services from ports and UID handles