diff --git a/src/citra_qt/debugger/disassembler.cpp b/src/citra_qt/debugger/disassembler.cpp
index ccc83abf25..4e8f841f4a 100644
--- a/src/citra_qt/debugger/disassembler.cpp
+++ b/src/citra_qt/debugger/disassembler.cpp
@@ -48,7 +48,7 @@ void DisassemblerWidget::Init()
     unsigned int curInstAddr = base_addr;
     char result[255];
 
-    for (int i = 0; i < 10000; i++) // fixed for now
+    for (int i = 0; i < 20000; i++) // fixed for now
     {
         disasm->disasm(curInstAddr, Memory::Read32(curInstAddr), result);
         model->setItem(i, 0, new QStandardItem(QString("0x%1").arg((uint)(curInstAddr), 8, 16, QLatin1Char('0'))));
diff --git a/src/common/console_listener.cpp b/src/common/console_listener.cpp
index b5f32d1bd9..db48abbf67 100644
--- a/src/common/console_listener.cpp
+++ b/src/common/console_listener.cpp
@@ -259,14 +259,17 @@ void ConsoleListener::Log(LogTypes::LOG_LEVELS Level, const char *Text)
 
     switch (Level)
     {
+    case OS_LEVEL: // light yellow
+        Color = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY;
+        break;
     case NOTICE_LEVEL: // light green
         Color = FOREGROUND_GREEN | FOREGROUND_INTENSITY;
         break;
     case ERROR_LEVEL: // light red
         Color = FOREGROUND_RED | FOREGROUND_INTENSITY;
         break;
-    case WARNING_LEVEL: // light yellow
-        Color = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY;
+    case WARNING_LEVEL: // light purple
+        Color = FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY;
         break;
     case INFO_LEVEL: // cyan
         Color = FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY;
@@ -278,15 +281,8 @@ void ConsoleListener::Log(LogTypes::LOG_LEVELS Level, const char *Text)
         Color = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
         break;
     }
-    if (strlen(Text) > 10)
-    {
-        // First 10 chars white
-        SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
-        WriteConsole(hConsole, Text, 10, &cCharsWritten, NULL);
-        Text += 10;
-    }
     SetConsoleTextAttribute(hConsole, Color);
-    WriteConsole(hConsole, Text, (DWORD)strlen(Text), &cCharsWritten, NULL);
+    printf(Text);
 #else
     char ColorAttr[16] = "";
     char ResetAttr[16] = "";
diff --git a/src/common/log.h b/src/common/log.h
index d0da68aad7..e923224eda 100644
--- a/src/common/log.h
+++ b/src/common/log.h
@@ -7,11 +7,14 @@
 
 #define LOGGING
 
-#define    NOTICE_LEVEL  1  // VERY important information that is NOT errors. Like startup and OSReports.
-#define    ERROR_LEVEL   2  // Critical errors 
-#define    WARNING_LEVEL 3  // Something is suspicious.
-#define    INFO_LEVEL    4  // General information.
-#define    DEBUG_LEVEL   5  // Detailed debugging - might make things slow.
+enum {
+    OS_LEVEL,       // Printed by the emulated operating system
+    NOTICE_LEVEL,   // VERY important information that is NOT errors. Like startup and OSReports.
+    ERROR_LEVEL,    // Critical errors 
+    WARNING_LEVEL,  // Something is suspicious.
+    INFO_LEVEL,     // General information.
+    DEBUG_LEVEL,    // Detailed debugging - might make things slow.
+};
 
 namespace LogTypes
 {
@@ -70,6 +73,7 @@ enum LOG_TYPE {
 
 // FIXME: should this be removed?
 enum LOG_LEVELS {
+    LOS = OS_LEVEL,
     LNOTICE = NOTICE_LEVEL,
     LERROR = ERROR_LEVEL,
     LWARNING = WARNING_LEVEL,
@@ -82,31 +86,34 @@ enum LOG_LEVELS {
 
 }  // namespace
 
-void GenericLog(LOGTYPES_LEVELS level, LOGTYPES_TYPE type,
-        const char *file, int line, const char *fmt, ...)
+void GenericLog(LOGTYPES_LEVELS level, LOGTYPES_TYPE type, const char*file, int line, 
+    const char* function, const char* fmt, ...)
 #ifdef __GNUC__
-        __attribute__((format(printf, 5, 6)))
+        __attribute__((format(printf, 6, 7)))
 #endif
         ;
 
 #if defined LOGGING || defined _DEBUG || defined DEBUGFAST
-#define MAX_LOGLEVEL DEBUG_LEVEL
+#define MAX_LOGLEVEL LDEBUG
 #else
 #ifndef MAX_LOGLEVEL
-#define MAX_LOGLEVEL WARNING_LEVEL
+#define MAX_LOGLEVEL LWARNING
 #endif // loglevel
 #endif // logging
 
-#ifdef GEKKO
-#define GENERIC_LOG(t, v, ...)
-#else
-// Let the compiler optimize this out
-#define GENERIC_LOG(t, v, ...) { \
-    if (v <= MAX_LOGLEVEL) \
-        GenericLog(v, t, __FILE__, __LINE__, __VA_ARGS__); \
-    }
+#ifdef _WIN32
+#ifndef __func__
+#define __func__ __FUNCTION__
+#endif
 #endif
 
+// Let the compiler optimize this out
+#define GENERIC_LOG(t, v, ...) { \
+    if (v <= LogTypes::MAX_LOGLEVEL) \
+        GenericLog(v, t, __FILE__, __LINE__, __func__, __VA_ARGS__); \
+    }
+
+#define OS_LOG(t,...) do { GENERIC_LOG(LogTypes::t, LogTypes::LOS, __VA_ARGS__) } while (0)
 #define ERROR_LOG(t,...) do { GENERIC_LOG(LogTypes::t, LogTypes::LERROR, __VA_ARGS__) } while (0)
 #define WARN_LOG(t,...) do { GENERIC_LOG(LogTypes::t, LogTypes::LWARNING, __VA_ARGS__) } while (0)
 #define NOTICE_LOG(t,...) do { GENERIC_LOG(LogTypes::t, LogTypes::LNOTICE, __VA_ARGS__) } while (0)
diff --git a/src/common/log_manager.cpp b/src/common/log_manager.cpp
index b4a761c75f..4e1cb60bda 100644
--- a/src/common/log_manager.cpp
+++ b/src/common/log_manager.cpp
@@ -10,14 +10,16 @@
 #include "common/thread.h"
 #include "common/file_util.h"
 
-void GenericLog(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, 
-        const char *file, int line, const char* fmt, ...)
+void GenericLog(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const char* file, int line, 
+    const char* function, const char* fmt, ...)
 {
     va_list args;
     va_start(args, fmt);
-    if (LogManager::GetInstance())
+
+    if (LogManager::GetInstance()) {
         LogManager::GetInstance()->Log(level, type,
-            file, line, fmt, args);
+            file, line, function, fmt, args);
+    }
     va_end(args);
 }
 
@@ -88,6 +90,8 @@ LogManager::LogManager()
             m_Log[i]->AddListener(m_debuggerLog);
 #endif
     }
+
+    m_consoleLog->Open();
 }
 
 LogManager::~LogManager()
@@ -107,8 +111,8 @@ LogManager::~LogManager()
     delete m_debuggerLog;
 }
 
-void LogManager::Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, 
-    const char *file, int line, const char *format, va_list args)
+void LogManager::Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const char* file, 
+    int line, const char* function, const char *fmt, va_list args)
 {
     char temp[MAX_MSGLEN];
     char msg[MAX_MSGLEN * 2];
@@ -117,17 +121,15 @@ void LogManager::Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type,
     if (!log->IsEnabled() || level > log->GetLevel() || ! log->HasListeners())
         return;
 
-    CharArrayFromFormatV(temp, MAX_MSGLEN, format, args);
+    CharArrayFromFormatV(temp, MAX_MSGLEN, fmt, args);
 
-    static const char level_to_char[7] = "-NEWID";
-    sprintf(msg, "%s %s:%u %c[%s]: %s\n",
-        Common::Timer::GetTimeFormatted().c_str(),
-        file, line, level_to_char[(int)level],
-        log->GetShortName(), temp);
+    static const char level_to_char[7] = "ONEWID";
+    sprintf(msg, "%s %s:%u %c[%s] %s: %s\n", Common::Timer::GetTimeFormatted().c_str(), file, line, 
+        level_to_char[(int)level], log->GetShortName(), function, temp);
+    
 #ifdef ANDROID
     Host_SysMessage(msg);    
 #endif
-    printf(msg); // TODO(ShizZy): RemoveMe when I no longer need this
     log->Trigger(level, msg);
 }
 
@@ -147,7 +149,7 @@ LogContainer::LogContainer(const char* shortName, const char* fullName, bool ena
 {
     strncpy(m_fullName, fullName, 128);
     strncpy(m_shortName, shortName, 32);
-    m_level = (LogTypes::LOG_LEVELS)MAX_LOGLEVEL;
+    m_level = LogTypes::MAX_LOGLEVEL;
 }
 
 // LogContainer
diff --git a/src/common/log_manager.h b/src/common/log_manager.h
index 580860b4d6..6d3d7c7ff8 100644
--- a/src/common/log_manager.h
+++ b/src/common/log_manager.h
@@ -97,10 +97,10 @@ private:
     ~LogManager();
 public:
 
-    static u32 GetMaxLevel() { return MAX_LOGLEVEL;    }
+    static u32 GetMaxLevel() { return LogTypes::MAX_LOGLEVEL;    }
 
-    void Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, 
-             const char *file, int line, const char *fmt, va_list args);
+    void Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const char* file, int line, 
+        const char* function, const char *fmt, va_list args);
 
     void SetLogLevel(LogTypes::LOG_TYPE type, LogTypes::LOG_LEVELS level)
     {
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 1c1a2eeb39..7116b88e90 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -34,12 +34,14 @@ set(SRCS    core.cpp
             hle/config_mem.cpp
             hle/coprocessor.cpp
             hle/svc.cpp
+            hle/kernel/event.cpp
             hle/kernel/kernel.cpp
             hle/kernel/mutex.cpp
             hle/kernel/thread.cpp
             hle/service/apt.cpp
             hle/service/gsp.cpp
             hle/service/hid.cpp
+            hle/service/ndm.cpp
             hle/service/service.cpp
             hle/service/srv.cpp
             hw/gpu.cpp
diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h
index 34a2eba1ba..be677ae203 100644
--- a/src/core/arm/arm_interface.h
+++ b/src/core/arm/arm_interface.h
@@ -89,6 +89,9 @@ public:
      */
     virtual void LoadContext(const ThreadContext& ctx) = 0;
 
+    /// Prepare core for thread reschedule (if needed to correctly handle state)
+    virtual void PrepareReschedule() = 0;
+
     /// Getter for num_instructions
     u64 GetNumInstructions() {
         return num_instructions;
diff --git a/src/core/arm/interpreter/arm_interpreter.cpp b/src/core/arm/interpreter/arm_interpreter.cpp
index 17f787b862..0e893f1821 100644
--- a/src/core/arm/interpreter/arm_interpreter.cpp
+++ b/src/core/arm/interpreter/arm_interpreter.cpp
@@ -98,7 +98,7 @@ u64 ARM_Interpreter::GetTicks() const {
  * @param num_instructions Number of instructions to executes
  */
 void ARM_Interpreter::ExecuteInstructions(int num_instructions) {
-    state->NumInstrsToExecute = num_instructions;
+    state->NumInstrsToExecute = num_instructions - 1;
     ARMul_Emulate32(state);
 }
 
@@ -118,6 +118,9 @@ void ARM_Interpreter::SaveContext(ThreadContext& ctx) {
 
     ctx.fpscr = state->VFP[1];
     ctx.fpexc = state->VFP[2];
+
+    ctx.reg_15 = state->Reg[15];
+    ctx.mode = state->NextInstr;
 }
 
 /**
@@ -137,6 +140,11 @@ void ARM_Interpreter::LoadContext(const ThreadContext& ctx) {
     state->VFP[1] = ctx.fpscr;
     state->VFP[2] = ctx.fpexc;
 
-    state->Reg[15] = ctx.pc;
-    state->NextInstr = RESUME;
+    state->Reg[15] = ctx.reg_15;
+    state->NextInstr = ctx.mode;
+}
+
+/// Prepare core for thread reschedule (if needed to correctly handle state)
+void ARM_Interpreter::PrepareReschedule() {
+    state->NumInstrsToExecute = 0;
 }
diff --git a/src/core/arm/interpreter/arm_interpreter.h b/src/core/arm/interpreter/arm_interpreter.h
index 6a531e4979..1e82883a22 100644
--- a/src/core/arm/interpreter/arm_interpreter.h
+++ b/src/core/arm/interpreter/arm_interpreter.h
@@ -72,6 +72,9 @@ public:
      */
     void LoadContext(const ThreadContext& ctx);
 
+    /// Prepare core for thread reschedule (if needed to correctly handle state)
+    void PrepareReschedule();
+
 protected:
 
     /**
diff --git a/src/core/arm/interpreter/armemu.cpp b/src/core/arm/interpreter/armemu.cpp
index e5dc7bd44f..f3c14e608b 100644
--- a/src/core/arm/interpreter/armemu.cpp
+++ b/src/core/arm/interpreter/armemu.cpp
@@ -4456,6 +4456,7 @@ ARMul_Emulate26 (ARMul_State * state)
                     }
                 /* Drop through.  */
 
+            case 0xe0:
             case 0xe4:
             case 0xe6:
             case 0xe8:
@@ -4489,7 +4490,6 @@ ARMul_Emulate26 (ARMul_State * state)
 
 
                 /* Co-Processor Register Transfers (MRC) and Data Ops.  */
-            case 0xe0:
             case 0xe1:
             case 0xe3:
             case 0xe5:
@@ -4533,23 +4533,7 @@ ARMul_Emulate26 (ARMul_State * state)
             case 0xfd:
             case 0xfe:
             case 0xff:
-                if (instr == ARMul_ABORTWORD
-                    && state->AbortAddr == pc) {
-                    /* A prefetch abort.  */
-                    XScale_set_fsr_far (state,
-                                ARMul_CP15_R5_MMU_EXCPT,
-                                pc);
-                    ARMul_Abort (state,
-                             ARMul_PrefetchAbortV);
-                    break;
-                }
-                //sky_pref_t* pref = get_skyeye_pref();
-                //if(pref->user_mode_sim){
-                //    ARMul_OSHandleSWI (state, BITS (0, 23));
-                //    break;
-                //}
                 HLE::CallSVC(instr);
-                ARMul_Abort (state, ARMul_SWIV);
                 break;
             }
         }
diff --git a/src/core/core.cpp b/src/core/core.cpp
index f88bcd704e..7dc0809d05 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -9,21 +9,24 @@
 #include "core/core.h"
 #include "core/mem_map.h"
 #include "core/hw/hw.h"
+#include "core/hw/gpu.h"
 #include "core/arm/disassembler/arm_disasm.h"
 #include "core/arm/interpreter/arm_interpreter.h"
 
+#include "core/hle/hle.h"
 #include "core/hle/kernel/thread.h"
 
 namespace Core {
 
-ARM_Disasm*     g_disasm    = NULL; ///< ARM disassembler
-ARM_Interface*  g_app_core  = NULL; ///< ARM11 application core
-ARM_Interface*  g_sys_core  = NULL; ///< ARM11 system (OS) core
+u64             g_last_ticks    = 0;        ///< Last CPU ticks
+ARM_Disasm*     g_disasm        = nullptr;  ///< ARM disassembler
+ARM_Interface*  g_app_core      = nullptr;  ///< ARM11 application core
+ARM_Interface*  g_sys_core      = nullptr;  ///< ARM11 system (OS) core
 
 /// Run the core CPU loop
 void RunLoop() {
     for (;;){
-        g_app_core->Run(100);
+        g_app_core->Run(GPU::kFrameTicks);
         HW::Update();
         Kernel::Reschedule();
     }
@@ -32,8 +35,14 @@ void RunLoop() {
 /// Step the CPU one instruction
 void SingleStep() {
     g_app_core->Step();
-    HW::Update();
-    Kernel::Reschedule();
+
+    // Update and reschedule after approx. 1 frame
+    u64 current_ticks = Core::g_app_core->GetTicks();
+    if ((current_ticks - g_last_ticks) >= GPU::kFrameTicks || HLE::g_reschedule) {
+        g_last_ticks = current_ticks;
+        HW::Update();
+        Kernel::Reschedule();
+    }
 }
 
 /// Halt the core
@@ -54,6 +63,8 @@ int Init() {
     g_app_core = new ARM_Interpreter();
     g_sys_core = new ARM_Interpreter();
 
+    g_last_ticks = Core::g_app_core->GetTicks();
+
     return 0;
 }
 
diff --git a/src/core/core.vcxproj b/src/core/core.vcxproj
index 8a3ad83ea2..8eb189a8b5 100644
--- a/src/core/core.vcxproj
+++ b/src/core/core.vcxproj
@@ -168,12 +168,14 @@
     <ClCompile Include="hle\config_mem.cpp" />
     <ClCompile Include="hle\coprocessor.cpp" />
     <ClCompile Include="hle\hle.cpp" />
+    <ClCompile Include="hle\kernel\event.cpp" />
     <ClCompile Include="hle\kernel\kernel.cpp" />
     <ClCompile Include="hle\kernel\mutex.cpp" />
     <ClCompile Include="hle\kernel\thread.cpp" />
     <ClCompile Include="hle\service\apt.cpp" />
     <ClCompile Include="hle\service\gsp.cpp" />
     <ClCompile Include="hle\service\hid.cpp" />
+    <ClCompile Include="hle\service\ndm.cpp" />
     <ClCompile Include="hle\service\service.cpp" />
     <ClCompile Include="hle\service\srv.cpp" />
     <ClCompile Include="hle\svc.cpp" />
@@ -217,12 +219,14 @@
     <ClInclude Include="hle\coprocessor.h" />
     <ClInclude Include="hle\function_wrappers.h" />
     <ClInclude Include="hle\hle.h" />
+    <ClInclude Include="hle\kernel\event.h" />
     <ClInclude Include="hle\kernel\kernel.h" />
     <ClInclude Include="hle\kernel\mutex.h" />
     <ClInclude Include="hle\kernel\thread.h" />
     <ClInclude Include="hle\service\apt.h" />
     <ClInclude Include="hle\service\gsp.h" />
     <ClInclude Include="hle\service\hid.h" />
+    <ClInclude Include="hle\service\ndm.h" />
     <ClInclude Include="hle\service\service.h" />
     <ClInclude Include="hle\service\srv.h" />
     <ClInclude Include="hle\svc.h" />
diff --git a/src/core/core.vcxproj.filters b/src/core/core.vcxproj.filters
index f7b342f98d..da781f8163 100644
--- a/src/core/core.vcxproj.filters
+++ b/src/core/core.vcxproj.filters
@@ -165,6 +165,12 @@
     <ClCompile Include="arm\interpreter\armcopro.cpp">
       <Filter>arm\interpreter</Filter>
     </ClCompile>
+    <ClCompile Include="hle\kernel\event.cpp">
+      <Filter>hle\kernel</Filter>
+    </ClCompile>
+    <ClCompile Include="hle\service\ndm.cpp">
+      <Filter>hle\service</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="arm\disassembler\arm_disasm.h">
@@ -295,6 +301,12 @@
     <ClInclude Include="hle\kernel\mutex.h">
       <Filter>hle\kernel</Filter>
     </ClInclude>
+    <ClInclude Include="hle\kernel\event.h">
+      <Filter>hle\kernel</Filter>
+    </ClInclude>
+    <ClInclude Include="hle\service\ndm.h">
+      <Filter>hle\service</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <Text Include="CMakeLists.txt" />
diff --git a/src/core/hle/config_mem.cpp b/src/core/hle/config_mem.cpp
index 48aa878cc1..8c898b2653 100644
--- a/src/core/hle/config_mem.cpp
+++ b/src/core/hle/config_mem.cpp
@@ -55,7 +55,7 @@ inline void Read(T &var, const u32 addr) {
         break;
 
     default:
-        ERROR_LOG(HLE, "unknown ConfigMem::Read%d @ 0x%08X", sizeof(var) * 8, addr);
+        ERROR_LOG(HLE, "unknown addr=0x%08X", addr);
     }
 }
 
diff --git a/src/core/hle/coprocessor.cpp b/src/core/hle/coprocessor.cpp
index 39674ee644..9a5b0dedaa 100644
--- a/src/core/hle/coprocessor.cpp
+++ b/src/core/hle/coprocessor.cpp
@@ -25,7 +25,7 @@ s32 CallMRC(u32 instruction) {
         return GetThreadCommandBuffer();
 
     default:
-        //DEBUG_LOG(OSHLE, "unknown MRC call 0x%08X", instruction);
+        DEBUG_LOG(OSHLE, "unknown MRC call 0x%08X", instruction);
         break;
     }
     return -1;
diff --git a/src/core/hle/function_wrappers.h b/src/core/hle/function_wrappers.h
index 801865d493..0bed78653d 100644
--- a/src/core/hle/function_wrappers.h
+++ b/src/core/hle/function_wrappers.h
@@ -1,19 +1,6 @@
-// Copyright (c) 2012- PPSSPP Project.
-
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, version 2.0 or later versions.
-
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License 2.0 for more details.
-
-// A copy of the GPL 2.0 should have been included with the program.
-// If not, see http://www.gnu.org/licenses/
-
-// Official git repository and contact information can be found at
-// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
+// Copyright 2014 Citra Emulator Project
+// Licensed under GPLv2
+// Refer to the license.txt file included.
 
 #pragma once
 
@@ -21,725 +8,107 @@
 #include "core/mem_map.h"
 #include "core/hle/hle.h"
 
-// For easy parameter parsing and return value processing.
+namespace HLE {
 
-//32bit wrappers
-template<void func()> void WrapV_V() {
-    func();
+#define PARAM(n)    Core::g_app_core->GetReg(n)
+#define RETURN(n)   Core::g_app_core->SetReg(0, n)
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Function wrappers that return type s32
+
+template<s32 func(u32, u32, u32, u32)> void Wrap() {
+    RETURN(func(PARAM(0), PARAM(1), PARAM(2), PARAM(3)));
 }
 
-template<u32 func()> void WrapU_V() {
+template<s32 func(u32, u32, u32, u32, u32)> void Wrap() {
+    RETURN(func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)));
+}
+
+template<s32 func(u32*, u32, u32, u32, u32, u32)> void Wrap(){
+    u32 param_1 = 0;
+    u32 retval = func(&param_1, PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4));
+    Core::g_app_core->SetReg(1, param_1);
+    RETURN(retval);
+}
+
+template<s32 func(s32*, u32*, s32, bool, s64)> void Wrap() {
+    s32 param_1 = 0;
+    s32 retval = func(&param_1, (Handle*)Memory::GetPointer(PARAM(1)), (s32)PARAM(2), 
+        (PARAM(3) != 0), (((s64)PARAM(4) << 32) | PARAM(0)));
+    Core::g_app_core->SetReg(1, (u32)param_1);
+    RETURN(retval);
+}
+
+// TODO(bunnei): Is this correct? Probably not
+template<s32 func(u32, u32, u32, u32, s64)> void Wrap() {
+    RETURN(func(PARAM(5), PARAM(1), PARAM(2), PARAM(3), (((s64)PARAM(4) << 32) | PARAM(0))));
+}
+
+template<s32 func(u32, s64)> void Wrap() {
+    RETURN(func(PARAM(0), (((s64)PARAM(3) << 32) | PARAM(2))));
+}
+
+template<s32 func(void*, void*, u32)> void Wrap(){
+    RETURN(func(Memory::GetPointer(PARAM(0)), Memory::GetPointer(PARAM(1)), PARAM(2)));
+}
+
+template<s32 func(s32*, u32)> void Wrap(){
+    s32 param_1 = 0;
+    u32 retval = func(&param_1, PARAM(1));
+    Core::g_app_core->SetReg(1, param_1);
+    RETURN(retval);
+}
+
+template<s32 func(u32, s32)> void Wrap() {
+    RETURN(func(PARAM(0), (s32)PARAM(1)));
+}
+
+template<s32 func(u32*, u32)> void Wrap(){
+    u32 param_1 = 0;
+    u32 retval = func(&param_1, PARAM(1));
+    Core::g_app_core->SetReg(1, param_1);
+    RETURN(retval);
+}
+
+template<s32 func(u32)> void Wrap() {
+    RETURN(func(PARAM(0)));
+}
+
+template<s32 func(void*)> void Wrap() {
+    RETURN(func(Memory::GetPointer(PARAM(0))));
+}
+
+template<s32 func(s64*, u32, void*, s32)> void Wrap(){
+    RETURN(func((s64*)Memory::GetPointer(PARAM(0)), PARAM(1), Memory::GetPointer(PARAM(2)), 
+        (s32)PARAM(3)));
+}
+
+template<s32 func(u32*, const char*)> void Wrap() {
+    u32 param_1 = 0;
+    u32 retval = func(&param_1, Memory::GetCharPointer(PARAM(1)));
+    Core::g_app_core->SetReg(1, param_1);
+    RETURN(retval);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Function wrappers that return type u32
+
+template<u32 func()> void Wrap() {
     RETURN(func());
 }
 
-template<int func(void *, const char *)> void WrapI_VC() {
-    u32 retval = func(Memory::GetPointer(PARAM(0)), Memory::GetCharPointer(PARAM(1)));
-    RETURN(retval);
-}
-
-template<u32 func(int, void *, int)> void WrapU_IVI() {
-    u32 retval = func(PARAM(0), Memory::GetPointer(PARAM(1)), PARAM(2));
-    RETURN(retval);
-}
-
-template<int func(const char *, int, int, u32)> void WrapI_CIIU() {
-    u32 retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2), PARAM(3));
-    RETURN(retval);
-}
-
-template<int func(int, const char *, u32, void *, void *, u32, int)> void WrapI_ICUVVUI() {
-    u32 retval = func(PARAM(0), Memory::GetCharPointer(PARAM(1)), PARAM(2), Memory::GetPointer(PARAM(3)),Memory::GetPointer(PARAM(4)), PARAM(5), PARAM(6) );
-    RETURN(retval);
-}
-
-// Hm, do so many params get passed in registers?
-template<int func(const char *, int, const char *, int, int, int, int, int)> void WrapI_CICIIIII() {
-    u32 retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1), Memory::GetCharPointer(PARAM(2)),
-        PARAM(3), PARAM(4), PARAM(5), PARAM(6), PARAM(7));
-    RETURN(retval);
-}
-
-// Hm, do so many params get passed in registers?
-template<int func(const char *, int, int, int, int, int, int)> void WrapI_CIIIIII() {
-    u32 retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2),
-        PARAM(3), PARAM(4), PARAM(5), PARAM(6));
-    RETURN(retval);
-}
-
-// Hm, do so many params get passed in registers?
-template<int func(int, int, int, int, int, int, u32)> void WrapI_IIIIIIU() {
-    u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4), PARAM(5), PARAM(6));
-    RETURN(retval);
-}
-
-// Hm, do so many params get passed in registers?
-template<int func(int, int, int, int, int, int, int, int, u32)> void WrapI_IIIIIIIIU() {
-    u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4), PARAM(5), PARAM(6), PARAM(7), PARAM(8));
-    RETURN(retval);
-}
-
-template<u32 func(int, void *)> void WrapU_IV() {
-    u32 retval = func(PARAM(0), Memory::GetPointer(PARAM(1)));
-    RETURN(retval);
-}
-
-template<u32 func(u32)> void WrapU_U() {
-    u32 retval = func(PARAM(0));
-    RETURN(retval);
-}
-
-template<u32 func(u32, int)> void WrapU_UI() {
-    u32 retval = func(PARAM(0), PARAM(1));
-    RETURN(retval);
-}
-
-template<int func(u32)> void WrapI_U() {
-    int retval = func(PARAM(0));
-    RETURN(retval);
-}
-
-template<int func(u32, int)> void WrapI_UI() {
-    int retval = func(PARAM(0), PARAM(1));
-    RETURN(retval);
-}
-
-template<int func(u32, int, int, u32)> void WrapI_UIIU() {
-    int retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3));
-    RETURN(retval);
-}
-
-template<u32 func(int, u32, int)> void WrapU_IUI() {
-    u32 retval = func(PARAM(0), PARAM(1), PARAM(2));
-    RETURN(retval);
-}
-
-template<int func(u32, u32)> void WrapI_UU() {
-    int retval = func(PARAM(0), PARAM(1));
-    RETURN(retval);
-}
-
-template<int func(u32, u32, u32)> void WrapI_UUU() {
-    int retval = func(PARAM(0), PARAM(1), PARAM(2));
-    RETURN(retval);
-}
-
-template<int func(u32, u32, u32, int)> void WrapI_UUUI() {
-    int retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3));
-    RETURN(retval);
-}
-
-template<int func(u32, u32, u32, int, int, int,int )> void WrapI_UUUIIII() {
-    int retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4), PARAM(5), PARAM(6));
-    RETURN(retval);
-}
-
-template<int func(u32, u32, u32, u32)> void WrapI_UUUU() {
-    int retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3));
-    RETURN(retval);
-}
-
-template<int func(u32, u32, u32, u32, u32)> void WrapI_UUUUU() {
-    int retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4));
-    RETURN(retval);
-}
-
-template<int func(void*)> void WrapI_V() {
-    u32 retval = func(Memory::GetPointer(PARAM(0)));
-    RETURN(retval);
-}
-
-template<u32 func(int)> void WrapU_I() {
-    u32 retval = func(PARAM(0));
-    RETURN(retval);
-}
-
-template<u32 func(int, int, u32)> void WrapU_IIU() {
-    u32 retval = func(PARAM(0), PARAM(1), PARAM(2));
-    RETURN(retval);
-}
-
-template<int func(int)> void WrapI_I() {
-    int retval = func(PARAM(0));
-    RETURN(retval);
-}
-
-template<void func(u32)> void WrapV_U() {
-    func(PARAM(0));
-}
-
-template<void func(int)> void WrapV_I() {
-    func(PARAM(0));
-}
-
-template<void func(u32, u32)> void WrapV_UU() {
-    func(PARAM(0), PARAM(1));
-}
-
-template<void func(int, int)> void WrapV_II() {
-    func(PARAM(0), PARAM(1));
-}
-
-template<void func(u32, const char *)> void WrapV_UC() {
-    func(PARAM(0), Memory::GetCharPointer(PARAM(1)));
-}
-
-template<int func(u32, const char *)> void WrapI_UC() {
-    int retval = func(PARAM(0), Memory::GetCharPointer(PARAM(1)));
-    RETURN(retval);
-}
-
-template<int func(u32, const char *, int)> void WrapI_UCI() {
-    int retval = func(PARAM(0), Memory::GetCharPointer(PARAM(1)), PARAM(2));
-    RETURN(retval);
-}
-
-template<u32 func(u32, int , int , int, int, int)> void WrapU_UIIIII() {
-    u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4), PARAM(5));
-    RETURN(retval);
-}
-
-template<u32 func(u32, int , int , int, u32)> void WrapU_UIIIU() {
-    u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4));
-    RETURN(retval);
-}
-
-template<u32 func(u32, int , int , int, int, int, int)> void WrapU_UIIIIII() {
-    u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4), PARAM(5), PARAM(6));
-    RETURN(retval);
-}
-
-template<u32 func(u32, u32)> void WrapU_UU() {
-    u32 retval = func(PARAM(0), PARAM(1));
-    RETURN(retval);
-}
-
-template<u32 func(u32, u32, int)> void WrapU_UUI() {
-    u32 retval = func(PARAM(0), PARAM(1), PARAM(2));
-    RETURN(retval);
-}
-
-template<u32 func(u32, u32, int, int)> void WrapU_UUII() {
-    u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3));
-    RETURN(retval);
-}
-
-template<u32 func(const char *, u32, u32, u32)> void WrapU_CUUU() {
-    u32 retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2), PARAM(3));
-    RETURN(retval);
-}
-
-template<void func(u32, int, u32, int, int)> void WrapV_UIUII() {
-    func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4));
-}
-
-template<u32 func(u32, int, u32, int, int)> void WrapU_UIUII() {
-    u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4));
-    RETURN(retval);
-}
-
-template<int func(u32, int, u32, int, int)> void WrapI_UIUII() {
-    int retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4));
-    RETURN(retval);
-}
-
-template<u32 func(u32, int, u32, int)> void WrapU_UIUI() {
-    u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3));
-    RETURN(retval);
-}
-
-template<int func(u32, int, u32, int)> void WrapI_UIUI() {
-    u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3));
-    RETURN(retval);
-}
-
-template<u32 func(u32, int, u32)> void WrapU_UIU() {
-    u32 retval = func(PARAM(0), PARAM(1), PARAM(2));
-    RETURN(retval);
-}
-
-template<u32 func(u32, int, u32, u32)> void WrapU_UIUU() {
-    u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3));
-    RETURN(retval);
-}
-
-template<u32 func(u32, int, int)> void WrapU_UII() {
-    u32 retval = func(PARAM(0), PARAM(1), PARAM(2));
-    RETURN(retval);
-}
-
-template<u32 func(u32, int, int, u32)> void WrapU_UIIU() {
-    u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3));
-    RETURN(retval);
-}
-
-template<int func(u32, int, int, u32, u32)> void WrapI_UIIUU() {
-    u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4));
-    RETURN(retval);
-}
-
-template<int func(u32, u32, int, int)> void WrapI_UUII() {
-    int retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3));
-    RETURN(retval);
-}
-
-template<int func(u32, u32, int, int, int)> void WrapI_UUIII() {
-    int retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4));
-    RETURN(retval);
-}
-
-template<void func(u32, int, int, int)> void WrapV_UIII() {
-    func(PARAM(0), PARAM(1), PARAM(2), PARAM(3));
-}
-
-template<void func(u32, int, int, int, int, int)> void WrapV_UIIIII() {
-    func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4), PARAM(5));
-}
-
-template<void func(u32, int, int)> void WrapV_UII() {
-    func(PARAM(0), PARAM(1), PARAM(2));
-}
-
-template<u32 func(int, u32)> void WrapU_IU() {
-    int retval = func(PARAM(0), PARAM(1));
-    RETURN(retval);
-}
-
-template<int func(int, u32)> void WrapI_IU() {
-    int retval = func(PARAM(0), PARAM(1));
-    RETURN(retval);
-}
-
-template<int func(u32, u32, int)> void WrapI_UUI() {
-    int retval = func(PARAM(0), PARAM(1), PARAM(2));
-    RETURN(retval);
-}
-
-template<int func(u32, u32, int, u32)> void WrapI_UUIU() {
-    int retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3));
-    RETURN(retval);
-}
-
-template<int func(int, int)> void WrapI_II() {
-    int retval = func(PARAM(0), PARAM(1));
-    RETURN(retval);
-}
-
-template<int func(int, int, int)> void WrapI_III() {
-    int retval = func(PARAM(0), PARAM(1), PARAM(2));
-    RETURN(retval);
-}
-
-template<int func(int, u32, int)> void WrapI_IUI() {
-    int retval = func(PARAM(0), PARAM(1), PARAM(2));
-    RETURN(retval);
-}
-
-template<int func(int, int, int, int)> void WrapI_IIII() {
-    int retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3));
-    RETURN(retval);
-}
-
-template<int func(u32, int, int, int)> void WrapI_UIII() {
-    int retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3));
-    RETURN(retval);
-}
-
-template<int func(int, int, int, u32, int)> void WrapI_IIIUI() {
-    int retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4));
-    RETURN(retval);
-}
-
-template<int func(int, u32, u32, int, int)> void WrapI_IUUII() {
-    int retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4));
-    RETURN(retval);
-}
-
-template<int func(int, const char *, int, u32, u32)> void WrapI_ICIUU() {
-    int retval = func(PARAM(0), Memory::GetCharPointer(PARAM(1)), PARAM(2), PARAM(3), PARAM(4));
-    RETURN(retval);
-}
-
-template<int func(int, int, u32)> void WrapI_IIU() {
-    int retval = func(PARAM(0), PARAM(1), PARAM(2));
-    RETURN(retval);
-}
-
-template<void func(int, u32)> void WrapV_IU() {
-    func(PARAM(0), PARAM(1));
-}
-
-template<void func(u32, int)> void WrapV_UI() {
-    func(PARAM(0), PARAM(1));
-}
-
-template<u32 func(const char *)> void WrapU_C() {
-    u32 retval = func(Memory::GetCharPointer(PARAM(0)));
-    RETURN(retval);
-}
-
-template<u32 func(const char *, const char *, const char *, u32)> void WrapU_CCCU() {
-    u32 retval = func(Memory::GetCharPointer(PARAM(0)),
-            Memory::GetCharPointer(PARAM(1)), Memory::GetCharPointer(PARAM(2)),
-            PARAM(3));
-    RETURN(retval);
-}
-
-template<int func(const char *)> void WrapI_C() {
-    int retval = func(Memory::GetCharPointer(PARAM(0)));
-    RETURN(retval);
-}
-
-template<int func(const char *, u32)> void WrapI_CU() {
-    int retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1));
-    RETURN(retval);
-}
-
-template<int func(const char *, u32, int)> void WrapI_CUI() {
-    int retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2));
-    RETURN(retval);
-}
-
-template<int func(int, const char *, int, u32)> void WrapI_ICIU() {
-    int retval = func(PARAM(0), Memory::GetCharPointer(PARAM(1)), PARAM(2), PARAM(3));
-    RETURN(retval);
-}
-
-template<int func(const char *, int, u32)> void WrapI_CIU() {
-    int retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2));
-    RETURN(retval);
-}
-
-template<int func(const char *, u32, u32)> void WrapI_CUU() {
-    int retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2));
-    RETURN(retval);
-}
-
-template<int func(const char *, u32, u32, u32)> void WrapI_CUUU() {
-    int retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2),
-            PARAM(3));
-    RETURN(retval);
-}
-
-template<int func(const char *, const char*, int, int)> void WrapI_CCII() {
-    int retval = func(Memory::GetCharPointer(PARAM(0)), Memory::GetCharPointer(PARAM(1)), PARAM(2), PARAM(3));
-    RETURN(retval);
-}
-
-template<int func(const char *, u32, u32, int, u32, u32)> void WrapI_CUUIUU() {
-    int retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2),
-            PARAM(3), PARAM(4), PARAM(5));
-    RETURN(retval);
-}
-
-template<int func(const char *, int, int, u32, int, int)> void WrapI_CIIUII() {
-    int retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2),
-        PARAM(3), PARAM(4), PARAM(5));
-    RETURN(retval);
-}
-
-template<int func(const char *, int, u32, u32, u32)> void WrapI_CIUUU() {
-    int retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2),
-            PARAM(3), PARAM(4));
-    RETURN(retval);
-}
-
-template<int func(const char *, u32, u32, u32, u32, u32)> void WrapI_CUUUUU() {
-    int retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2),
-            PARAM(3), PARAM(4), PARAM(5));
-    RETURN(retval);
-}
-
-template<u32 func(const char *, u32)> void WrapU_CU() {
-    u32 retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1));
-    RETURN((u32) retval);
-}
-
-template<u32 func(u32, const char *)> void WrapU_UC() {
-    u32 retval = func(PARAM(0), Memory::GetCharPointer(PARAM(1)));
-    RETURN(retval);
-}
-
-template<u32 func(const char *, u32, u32)> void WrapU_CUU() {
-    u32 retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2));
-    RETURN((u32) retval);
-}
-
-template<u32 func(int, int, int)> void WrapU_III() {
-    u32 retval = func(PARAM(0), PARAM(1), PARAM(2));
-    RETURN(retval);
-}
-
-template<u32 func(int, int)> void WrapU_II() {
-    u32 retval = func(PARAM(0), PARAM(1));
-    RETURN(retval);
-}
-
-template<u32 func(int, int, int, int)> void WrapU_IIII() {
-    u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3));
-    RETURN(retval);
-}
-
-template<u32 func(int, u32, u32)> void WrapU_IUU() {
-    u32 retval = func(PARAM(0), PARAM(1), PARAM(2));
-    RETURN(retval);
-}
-
-template<u32 func(int, u32, u32, u32)> void WrapU_IUUU() {
-    u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3));
-    RETURN(retval);
-}
-
-template<u32 func(int, u32, u32, u32, u32)> void WrapU_IUUUU() {
-    u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4));
-    RETURN(retval);
-}
-
-template<u32 func(u32, u32, u32)> void WrapU_UUU() {
-    u32 retval = func(PARAM(0), PARAM(1), PARAM(2));
-    RETURN(retval);
-}
-
-template<void func(int, u32, u32)> void WrapV_IUU() {
-    func(PARAM(0), PARAM(1), PARAM(2));
-}
-
-template<void func(int, int, u32)> void WrapV_IIU() {
-    func(PARAM(0), PARAM(1), PARAM(2));
-}
-
-template<void func(u32, int, u32)> void WrapV_UIU() {
-    func(PARAM(0), PARAM(1), PARAM(2));
-}
-
-template<int func(u32, int, u32)> void WrapI_UIU() {
-    int retval = func(PARAM(0), PARAM(1), PARAM(2));
-    RETURN(retval);
-}
-
-template<void func(int, u32, u32, u32, u32)> void WrapV_IUUUU() {
-    func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4));
-}
-
-template<void func(u32, u32, u32)> void WrapV_UUU() {
-    func(PARAM(0), PARAM(1), PARAM(2));
-}
-
-template<void func(u32, u32, u32, u32)> void WrapV_UUUU() {
-    func(PARAM(0), PARAM(1), PARAM(2), PARAM(3));
-}
-
-template<void func(const char *, u32, int, u32)> void WrapV_CUIU() {
-    func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2), PARAM(3));
-}
-
-template<int func(const char *, u32, int, u32)> void WrapI_CUIU() {
-    int retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2), PARAM(3));
-    RETURN(retval);
-}
-
-template<void func(u32, const char *, u32, int, u32)> void WrapV_UCUIU() {
-    func(PARAM(0), Memory::GetCharPointer(PARAM(1)), PARAM(2), PARAM(3),
-            PARAM(4));
-}
-
-template<int func(u32, const char *, u32, int, u32)> void WrapI_UCUIU() {
-    int retval = func(PARAM(0), Memory::GetCharPointer(PARAM(1)), PARAM(2),
-            PARAM(3), PARAM(4));
-    RETURN(retval);
-}
-
-template<void func(const char *, u32, int, int, u32)> void WrapV_CUIIU() {
-    func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2), PARAM(3),
-            PARAM(4));
-}
-
-template<int func(const char *, u32, int, int, u32)> void WrapI_CUIIU() {
-    int retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2),
-            PARAM(3), PARAM(4));
-    RETURN(retval);
-}
-
-template<u32 func(u32, u32, u32, u32)> void WrapU_UUUU() {
-    u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3));
-    RETURN(retval);
-}
-
-template<u32 func(u32, const char *, u32, u32)> void WrapU_UCUU() {
-    u32 retval = func(PARAM(0), Memory::GetCharPointer(PARAM(1)), PARAM(2), PARAM(3));
-    RETURN(retval);
-}
-
-template<u32 func(u32, u32, u32, int)> void WrapU_UUUI() {
-    u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3));
-    RETURN(retval);
-}
-
-template<u32 func(u32, u32, u32, int, u32)> void WrapU_UUUIU() {
-    u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4));
-    RETURN(retval);
-}
-
-template<u32 func(u32, u32, u32, int, u32, int)> void WrapU_UUUIUI() {
-    u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4), PARAM(5));
-    RETURN(retval);
-}
-
-template<u32 func(u32, u32, int, u32)> void WrapU_UUIU() {
-    u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3));
-    RETURN(retval);
-}
-
-template<u32 func(u32, int, int, int)> void WrapU_UIII() {
-    u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3));
-    RETURN(retval);
-}
-
-template<int func(int, u32, u32, u32, u32)> void WrapI_IUUUU() {
-    int retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4));
-    RETURN(retval);
-}
-
-template<int func(int, u32, u32, u32, u32, u32)> void WrapI_IUUUUU() {
-    int retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4), PARAM(5));
-    RETURN(retval);
-}
-
-template<int func(int, u32, int, int)> void WrapI_IUII() {
-    int retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3));
-    RETURN(retval);
-}
-template<u32 func(u32, u32, u32, u32, u32)> void WrapU_UUUUU() {
-    u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4));
-    RETURN(retval);
-}
-
-template<void func(u32, u32, u32, u32, u32)> void WrapV_UUUUU() {
-    func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4));
-}
+////////////////////////////////////////////////////////////////////////////////////////////////////
+/// Function wrappers that return type void
 
-template<u32 func(const char *, const char *)> void WrapU_CC() {
-    int retval = func(Memory::GetCharPointer(PARAM(0)),
-            Memory::GetCharPointer(PARAM(1)));
-    RETURN(retval);
+template<void func(s64)> void Wrap() {
+    func(((s64)PARAM(1) << 32) | PARAM(0));
 }
 
-template<void func(const char*)> void WrapV_C() {
+template<void func(const char*)> void Wrap() {
     func(Memory::GetCharPointer(PARAM(0)));
 }
 
-template<void func(const char *, int)> void WrapV_CI() {
-    func(Memory::GetCharPointer(PARAM(0)), PARAM(1));
-}
+#undef PARAM
+#undef RETURN
 
-template<u32 func(const char *, int)> void WrapU_CI() {
-    int retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1));
-    RETURN(retval);
-}
-
-template<u32 func(const char *, int, int)> void WrapU_CII() {
-    int retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2));
-    RETURN(retval);
-}
-
-template<int func(const char *, int, u32, int, u32)> void WrapU_CIUIU() {
-    int retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2),
-            PARAM(3), PARAM(4));
-    RETURN(retval);
-}
-
-template<u32 func(const char *, int, u32, int, u32, int)> void WrapU_CIUIUI() {
-    u32 retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2),
-            PARAM(3), PARAM(4), PARAM(5));
-    RETURN(retval);
-}
-
-template<u32 func(u32, u32, u32, u32, u32, u32)> void WrapU_UUUUUU() {
-    u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4),
-            PARAM(5));
-    RETURN(retval);
-}
-
-template<int func(int, u32, u32, u32)> void WrapI_IUUU() {
-    int retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3));
-    RETURN(retval);
-}
-
-template<int func(int, u32, u32)> void WrapI_IUU() {
-    int retval = func(PARAM(0), PARAM(1), PARAM(2));
-    RETURN(retval);
-}
-
-template<u32 func(u32, u32, u32, u32, u32, u32, u32)> void WrapU_UUUUUUU() {
-  u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4), PARAM(5), PARAM(6));
-  RETURN(retval);
-}
-
-template<int func(u32, int, u32, u32)> void WrapI_UIUU() {
-    u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3));
-    RETURN(retval);
-}
-
-template<int func(int, const char *)> void WrapI_IC() {
-    int retval = func(PARAM(0), Memory::GetCharPointer(PARAM(1)));
-    RETURN(retval);
-}
-
-template <int func(int, const char *, const char *, u32, int)> void WrapI_ICCUI() {
-    int retval = func(PARAM(0), Memory::GetCharPointer(PARAM(1)), Memory::GetCharPointer(PARAM(2)), PARAM(3), PARAM(4));
-    RETURN(retval);
-}
-
-template <int func(int, const char *, const char *, int)> void WrapI_ICCI() {
-    int retval = func(PARAM(0), Memory::GetCharPointer(PARAM(1)), Memory::GetCharPointer(PARAM(2)), PARAM(3));
-    RETURN(retval);
-}
-
-template <int func(const char *, int, int)> void WrapI_CII() {
-    int retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2));
-    RETURN(retval);
-}
-
-template <int func(int, const char *, int)> void WrapI_ICI() {
-    int retval = func(PARAM(0), Memory::GetCharPointer(PARAM(1)), PARAM(2));
-    RETURN(retval);
-}
-
-template<int func(int, void *, void *, void *, void *, u32, int)> void WrapI_IVVVVUI(){
-    u32 retval = func(PARAM(0), Memory::GetPointer(PARAM(1)), Memory::GetPointer(PARAM(2)), Memory::GetPointer(PARAM(3)), Memory::GetPointer(PARAM(4)), PARAM(5), PARAM(6) );
-    RETURN(retval);
-}
-
-template<int func(int, const char *, u32, void *, int, int, int)> void WrapI_ICUVIII(){
-    u32 retval = func(PARAM(0), Memory::GetCharPointer(PARAM(1)), PARAM(2), Memory::GetPointer(PARAM(3)), PARAM(4), PARAM(5), PARAM(6));
-    RETURN(retval);
-}
-
-template<int func(void*, u32)> void WrapI_VU(){
-    u32 retval = func(Memory::GetPointer(PARAM(0)), PARAM(1));
-    RETURN(retval);
-}
-
-template<int func(void*, void*, u32)> void WrapI_VVU(){
-    u32 retval = func(Memory::GetPointer(PARAM(0)), Memory::GetPointer(PARAM(1)), PARAM(2));
-    RETURN(retval);
-}
-
-template<int func(void*, u32, void*, int)> void WrapI_VUVI(){
-    u32 retval = func(Memory::GetPointer(PARAM(0)), PARAM(1), Memory::GetPointer(PARAM(2)), PARAM(3));
-    RETURN(retval);
-}
-
-template<int func(void*, u32, u32, u32, u32, u32)> void WrapI_VUUUUU(){
-    u32 retval = func(NULL, PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4));
-    RETURN(retval);
-}
-
-template<int func(u32, s64)> void WrapI_US64() {
-    int retval = func(PARAM(0), PARAM64(1));
-    RETURN(retval);
-}
-
-template<int func(void*, void*, u32, u32, s64)> void WrapI_VVUUS64() {
-    int retval = func(Memory::GetPointer(PARAM(0)), Memory::GetPointer(PARAM(1)), PARAM(2), PARAM(3), PARAM(4));
-    RETURN(retval);
-}
+} // namespace HLE
diff --git a/src/core/hle/hle.cpp b/src/core/hle/hle.cpp
index 080c36abf4..53cda4a61b 100644
--- a/src/core/hle/hle.cpp
+++ b/src/core/hle/hle.cpp
@@ -7,6 +7,7 @@
 #include "core/mem_map.h"
 #include "core/hle/hle.h"
 #include "core/hle/svc.h"
+#include "core/hle/kernel/thread.h"
 #include "core/hle/service/service.h"
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -15,11 +16,13 @@ namespace HLE {
 
 static std::vector<ModuleDef> g_module_db;
 
+bool g_reschedule = false;  ///< If true, immediately reschedules the CPU to a new thread
+
 const FunctionDef* GetSVCInfo(u32 opcode) {
     u32 func_num = opcode & 0xFFFFFF; // 8 bits
     if (func_num > 0xFF) {
-        ERROR_LOG(HLE,"Unknown SVC: 0x%02X", func_num); 
-        return NULL;
+        ERROR_LOG(HLE,"unknown svc=0x%02X", func_num); 
+        return nullptr;
     }
     return &g_module_db[0].func_table[func_num];
 }
@@ -33,19 +36,16 @@ void CallSVC(u32 opcode) {
     if (info->func) {
         info->func();
     } else {
-        ERROR_LOG(HLE, "Unimplemented SVC function %s(..)", info->name.c_str());
+        ERROR_LOG(HLE, "unimplemented SVC function %s(..)", info->name.c_str());
     }
 }
 
-void EatCycles(u32 cycles) {
-    // TODO: ImplementMe
-}
-
-void ReSchedule(const char *reason) {
+void Reschedule(const char *reason) {
 #ifdef _DEBUG
-    _dbg_assert_msg_(HLE, reason != 0 && strlen(reason) < 256, "ReSchedule: Invalid or too long reason.");
+    _dbg_assert_msg_(HLE, reason != 0 && strlen(reason) < 256, "Reschedule: Invalid or too long reason.");
 #endif
-    // TODO: ImplementMe
+    Core::g_app_core->PrepareReschedule();
+    g_reschedule = true;
 }
 
 void RegisterModule(std::string name, int num_functions, const FunctionDef* func_table) {
diff --git a/src/core/hle/hle.h b/src/core/hle/hle.h
index c075147c39..bf4d84575c 100644
--- a/src/core/hle/hle.h
+++ b/src/core/hle/hle.h
@@ -9,14 +9,10 @@
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 
-#define PARAM(n)        Core::g_app_core->GetReg(n)
-#define PARAM64(n)      (Core::g_app_core->GetReg(n) | ((u64)Core::g_app_core->GetReg(n + 1) << 32))
-#define RETURN(n)       Core::g_app_core->SetReg(0, n)
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
 namespace HLE {
 
+extern bool g_reschedule;   ///< If true, immediately reschedules the CPU to a new thread
+
 typedef u32 Addr;
 typedef void (*Func)();
 
@@ -36,9 +32,7 @@ void RegisterModule(std::string name, int num_functions, const FunctionDef *func
 
 void CallSVC(u32 opcode);
 
-void EatCycles(u32 cycles);
-
-void ReSchedule(const char *reason);
+void Reschedule(const char *reason);
 
 void Init();
 
diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp
new file mode 100644
index 0000000000..127c0cfc6c
--- /dev/null
+++ b/src/core/hle/kernel/event.cpp
@@ -0,0 +1,159 @@
+// Copyright 2014 Citra Emulator Project
+// Licensed under GPLv2
+// Refer to the license.txt file included.  
+
+#include <map>
+#include <algorithm>
+#include <vector>
+
+#include "common/common.h"
+
+#include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/event.h"
+#include "core/hle/kernel/thread.h"
+
+namespace Kernel {
+
+class Event : public Object {
+public:
+    const char* GetTypeName() const { return "Event"; }
+    const char* GetName() const { return name.c_str(); }
+
+    static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Event; }
+    Kernel::HandleType GetHandleType() const { return Kernel::HandleType::Event; }
+
+    ResetType intitial_reset_type;          ///< ResetType specified at Event initialization
+    ResetType reset_type;                   ///< Current ResetType
+
+    bool locked;                            ///< Event signal wait
+    bool permanent_locked;                  ///< Hack - to set event permanent state (for easy passthrough)
+    std::vector<Handle> waiting_threads;    ///< Threads that are waiting for the event
+    std::string name;                       ///< Name of event (optional)
+
+    /**
+     * Wait for kernel object to synchronize
+     * @param wait Boolean wait set if current thread should wait as a result of sync operation
+     * @return Result of operation, 0 on success, otherwise error code
+     */
+    Result WaitSynchronization(bool* wait) {
+        *wait = locked;
+        if (locked) {
+            Handle thread = GetCurrentThreadHandle();
+            if (std::find(waiting_threads.begin(), waiting_threads.end(), thread) == waiting_threads.end()) {
+                waiting_threads.push_back(thread);
+            }
+            Kernel::WaitCurrentThread(WAITTYPE_EVENT);
+        }
+        if (reset_type != RESETTYPE_STICKY && !permanent_locked) {
+            locked = true;
+        }
+        return 0;
+    }
+};
+
+/**
+ * Hackish function to set an events permanent lock state, used to pass through synch blocks
+ * @param handle Handle to event to change
+ * @param permanent_locked Boolean permanent locked value to set event
+ * @return Result of operation, 0 on success, otherwise error code
+ */
+Result SetPermanentLock(Handle handle, const bool permanent_locked) {
+    Event* evt = g_object_pool.GetFast<Event>(handle);
+    _assert_msg_(KERNEL, (evt != nullptr), "called, but event is nullptr!");
+
+    evt->permanent_locked = permanent_locked;
+    return 0;
+}
+
+/**
+ * Changes whether an event is locked or not
+ * @param handle Handle to event to change
+ * @param locked Boolean locked value to set event
+ * @return Result of operation, 0 on success, otherwise error code
+ */
+Result SetEventLocked(const Handle handle, const bool locked) {
+    Event* evt = g_object_pool.GetFast<Event>(handle);
+    _assert_msg_(KERNEL, (evt != nullptr), "called, but event is nullptr!");
+
+    if (!evt->permanent_locked) {
+        evt->locked = locked;
+    }
+    return 0;
+}
+
+/**
+ * Signals an event
+ * @param handle Handle to event to signal
+ * @return Result of operation, 0 on success, otherwise error code
+ */
+Result SignalEvent(const Handle handle) {
+    Event* evt = g_object_pool.GetFast<Event>(handle);
+    _assert_msg_(KERNEL, (evt != nullptr), "called, but event is nullptr!");
+
+    // Resume threads waiting for event to signal
+    bool event_caught = false;
+    for (size_t i = 0; i < evt->waiting_threads.size(); ++i) {
+        ResumeThreadFromWait( evt->waiting_threads[i]);
+
+        // If any thread is signalled awake by this event, assume the event was "caught" and reset 
+        // the event. This will result in the next thread waiting on the event to block. Otherwise,
+        // the event will not be reset, and the next thread to call WaitSynchronization on it will
+        // not block. Not sure if this is correct behavior, but it seems to work.
+        event_caught = true;
+    }
+    evt->waiting_threads.clear();
+
+    if (!evt->permanent_locked) {
+        evt->locked = event_caught;
+    }
+    return 0;
+}
+
+/**
+ * Clears an event
+ * @param handle Handle to event to clear
+ * @return Result of operation, 0 on success, otherwise error code
+ */
+Result ClearEvent(Handle handle) {
+    Event* evt = g_object_pool.GetFast<Event>(handle);
+    _assert_msg_(KERNEL, (evt != nullptr), "called, but event is nullptr!");
+
+    if (!evt->permanent_locked) {
+        evt->locked = true;
+    }
+    return 0;
+}
+
+/**
+ * Creates an event
+ * @param handle Reference to handle for the newly created mutex
+ * @param reset_type ResetType describing how to create event
+ * @param name Optional name of event
+ * @return Newly created Event object
+ */
+Event* CreateEvent(Handle& handle, const ResetType reset_type, const std::string& name) {
+    Event* evt = new Event;
+
+    handle = Kernel::g_object_pool.Create(evt);
+
+    evt->locked = true;
+    evt->permanent_locked = false;
+    evt->reset_type = evt->intitial_reset_type = reset_type;
+    evt->name = name;
+
+    return evt;
+}
+
+/**
+ * Creates an event
+ * @param reset_type ResetType describing how to create event
+ * @param name Optional name of event
+ * @return Handle to newly created Event object
+ */
+Handle CreateEvent(const ResetType reset_type, const std::string& name) {
+    Handle handle;
+    Event* evt = CreateEvent(handle, reset_type, name);
+    return handle;
+}
+
+} // namespace
diff --git a/src/core/hle/kernel/event.h b/src/core/hle/kernel/event.h
new file mode 100644
index 0000000000..c39b33180d
--- /dev/null
+++ b/src/core/hle/kernel/event.h
@@ -0,0 +1,52 @@
+// Copyright 2014 Citra Emulator Project
+// Licensed under GPLv2
+// Refer to the license.txt file included.  
+
+#pragma once
+
+#include "common/common_types.h"
+
+#include "core/hle/kernel/kernel.h"
+#include "core/hle/svc.h"
+
+namespace Kernel {
+
+/**
+ * Changes whether an event is locked or not
+ * @param handle Handle to event to change
+ * @param locked Boolean locked value to set event
+ * @return Result of operation, 0 on success, otherwise error code
+ */
+Result SetEventLocked(const Handle handle, const bool locked);
+
+/**
+ * Hackish function to set an events permanent lock state, used to pass through synch blocks
+ * @param handle Handle to event to change
+ * @param permanent_locked Boolean permanent locked value to set event
+ * @return Result of operation, 0 on success, otherwise error code
+ */
+Result SetPermanentLock(Handle handle, const bool permanent_locked);
+
+/**
+ * Signals an event
+ * @param handle Handle to event to signal
+ * @return Result of operation, 0 on success, otherwise error code
+ */
+Result SignalEvent(const Handle handle);
+
+/**
+ * Clears an event
+ * @param handle Handle to event to clear
+ * @return Result of operation, 0 on success, otherwise error code
+ */
+Result ClearEvent(Handle handle);
+
+/**
+ * Creates an event
+ * @param reset_type ResetType describing how to create event
+ * @param name Optional name of event
+ * @return Handle to newly created Event object
+ */
+Handle CreateEvent(const ResetType reset_type, const std::string& name="Unknown");
+
+} // namespace
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index de80de8937..cda183add7 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -2,8 +2,6 @@
 // Licensed under GPLv2
 // Refer to the license.txt file included.  
 
-#pragma once
-
 #include <string.h>
 
 #include "common/common.h"
@@ -14,6 +12,7 @@
 
 namespace Kernel {
 
+Handle g_main_thread = 0;
 ObjectPool g_object_pool;
 
 ObjectPool::ObjectPool() {
@@ -127,16 +126,20 @@ Object* ObjectPool::CreateByIDType(int type) {
 
     default:
         ERROR_LOG(COMMON, "Unable to load state: could not find object type %d.", type);
-        return NULL;
+        return nullptr;
     }
 }
 
+/// Initialize the kernel
 void Init() {
     Kernel::ThreadingInit();
 }
 
+/// Shutdown the kernel
 void Shutdown() {
     Kernel::ThreadingShutdown();
+
+    g_object_pool.Clear(); // Free all kernel objects
 }
 
 /**
@@ -150,7 +153,7 @@ bool LoadExec(u32 entry_point) {
     Core::g_app_core->SetPC(entry_point);
 
     // 0x30 is the typical main thread priority I've seen used so far
-    Handle thread = Kernel::SetupMainThread(0x30);
+    g_main_thread = Kernel::SetupMainThread(0x30);
 
     return true;
 }
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 7cd79c2c41..3f15da0ace 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -11,6 +11,11 @@ typedef s32 Result;
 
 namespace Kernel {
 
+enum KernelHandle {
+    CurrentThread   = 0xFFFF8000,
+    CurrentProcess  = 0xFFFF8001,
+};
+
 enum class HandleType : u32 {
     Unknown         = 0,
     Port            = 1,
@@ -39,9 +44,26 @@ class Object : NonCopyable {
 public:
     virtual ~Object() {}
     Handle GetHandle() const { return handle; }
-    virtual const char *GetTypeName() { return "[BAD KERNEL OBJECT TYPE]"; }
-    virtual const char *GetName() { return "[UNKNOWN KERNEL OBJECT]"; }
+    virtual const char* GetTypeName() const { return "[BAD KERNEL OBJECT TYPE]"; }
+    virtual const char* GetName() const { return "[UNKNOWN KERNEL OBJECT]"; }
     virtual Kernel::HandleType GetHandleType() const = 0;
+
+    /**
+     * Synchronize kernel object 
+     * @param wait Boolean wait set if current thread should wait as a result of sync operation
+     * @return Result of operation, 0 on success, otherwise error code
+     */
+    virtual Result SyncRequest(bool* wait) {
+        ERROR_LOG(KERNEL, "(UNIMPLEMENTED)");
+        return -1;
+    }
+
+    /**
+     * Wait for kernel object to synchronize
+     * @param wait Boolean wait set if current thread should wait as a result of sync operation
+     * @return Result of operation, 0 on success, otherwise error code
+     */
+    virtual Result WaitSynchronization(bool* wait) = 0;
 };
 
 class ObjectPool : NonCopyable {
@@ -143,6 +165,13 @@ private:
 };
 
 extern ObjectPool g_object_pool;
+extern Handle g_main_thread;
+
+/// Initialize the kernel
+void Init();
+
+/// Shutdown the kernel
+void Shutdown();
 
 /**
  * Loads executable stored at specified address
diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp
index 019efbc785..1ccf1eb730 100644
--- a/src/core/hle/kernel/mutex.cpp
+++ b/src/core/hle/kernel/mutex.cpp
@@ -8,21 +8,51 @@
 #include "common/common.h"
 
 #include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/mutex.h"
 #include "core/hle/kernel/thread.h"
 
 namespace Kernel {
 
 class Mutex : public Object {
 public:
-    const char* GetTypeName() { return "Mutex"; }
+    const char* GetTypeName() const { return "Mutex"; }
+    const char* GetName() const { return name.c_str(); }
 
-    static Kernel::HandleType GetStaticHandleType() {  return Kernel::HandleType::Mutex; }
+    static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Mutex; }
     Kernel::HandleType GetHandleType() const { return Kernel::HandleType::Mutex; }
 
     bool initial_locked;                        ///< Initial lock state when mutex was created
     bool locked;                                ///< Current locked state
     Handle lock_thread;                         ///< Handle to thread that currently has mutex
     std::vector<Handle> waiting_threads;        ///< Threads that are waiting for the mutex
+    std::string name;                           ///< Name of mutex (optional)
+
+    /**
+     * Synchronize kernel object 
+     * @param wait Boolean wait set if current thread should wait as a result of sync operation
+     * @return Result of operation, 0 on success, otherwise error code
+     */
+    Result SyncRequest(bool* wait) {
+        // TODO(bunnei): ImplementMe
+        locked = true;
+        return 0;
+    }
+
+    /**
+     * Wait for kernel object to synchronize
+     * @param wait Boolean wait set if current thread should wait as a result of sync operation
+     * @return Result of operation, 0 on success, otherwise error code
+     */
+    Result WaitSynchronization(bool* wait) {
+        // TODO(bunnei): ImplementMe
+        *wait = locked;
+
+        if (locked) {
+            Kernel::WaitCurrentThread(WAITTYPE_MUTEX);
+        }
+
+        return 0;
+    }
 };
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -70,10 +100,10 @@ bool ReleaseMutexForThread(Mutex* mutex, Handle thread) {
 bool ReleaseMutex(Mutex* mutex) {
     MutexEraseLock(mutex);
     bool woke_threads = false;
-    auto iter = mutex->waiting_threads.begin();
 
     // Find the next waiting thread for the mutex...
     while (!woke_threads && !mutex->waiting_threads.empty()) {
+        std::vector<Handle>::iterator iter = mutex->waiting_threads.begin();
         woke_threads |= ReleaseMutexForThread(mutex, *iter);
         mutex->waiting_threads.erase(iter);
     }
@@ -91,6 +121,9 @@ bool ReleaseMutex(Mutex* mutex) {
  */
 Result ReleaseMutex(Handle handle) {
     Mutex* mutex = Kernel::g_object_pool.GetFast<Mutex>(handle);
+
+    _assert_msg_(KERNEL, (mutex != nullptr), "ReleaseMutex tried to release a nullptr mutex!");
+
     if (!ReleaseMutex(mutex)) {
         return -1;
     }
@@ -101,12 +134,15 @@ Result ReleaseMutex(Handle handle) {
  * Creates a mutex
  * @param handle Reference to handle for the newly created mutex
  * @param initial_locked Specifies if the mutex should be locked initially
+ * @param name Optional name of mutex
+ * @return Pointer to new Mutex object
  */
-Mutex* CreateMutex(Handle& handle, bool initial_locked) {
+Mutex* CreateMutex(Handle& handle, bool initial_locked, const std::string& name) {
     Mutex* mutex = new Mutex;
     handle = Kernel::g_object_pool.Create(mutex);
 
     mutex->locked = mutex->initial_locked = initial_locked;
+    mutex->name = name;
 
     // Acquire mutex with current thread if initialized as locked...
     if (mutex->locked) {
@@ -122,10 +158,12 @@ Mutex* CreateMutex(Handle& handle, bool initial_locked) {
 /**
  * Creates a mutex
  * @param initial_locked Specifies if the mutex should be locked initially
+ * @param name Optional name of mutex
+ * @return Handle to newly created object
  */
-Handle CreateMutex(bool initial_locked) {
+Handle CreateMutex(bool initial_locked, const std::string& name) {
     Handle handle;
-    Mutex* mutex = CreateMutex(handle, initial_locked);
+    Mutex* mutex = CreateMutex(handle, initial_locked, name);
     return handle;
 }
 
diff --git a/src/core/hle/kernel/mutex.h b/src/core/hle/kernel/mutex.h
index 871e2e5626..7d7b5137e2 100644
--- a/src/core/hle/kernel/mutex.h
+++ b/src/core/hle/kernel/mutex.h
@@ -13,14 +13,16 @@ namespace Kernel {
 /**
  * Releases a mutex
  * @param handle Handle to mutex to release
+ * @return Result of operation, 0 on success, otherwise error code
  */
 Result ReleaseMutex(Handle handle);
 
 /**
  * Creates a mutex
- * @param handle Reference to handle for the newly created mutex
  * @param initial_locked Specifies if the mutex should be locked initially
+ * @param name Optional name of mutex
+ * @return Handle to newly created object
  */
-Handle CreateMutex(bool initial_locked);
+Handle CreateMutex(bool initial_locked, const std::string& name="Unknown");
 
 } // namespace
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index bf4c8353ce..ab5a5559e3 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -5,6 +5,7 @@
 #include <stdio.h>
 
 #include <list>
+#include <algorithm>
 #include <vector>
 #include <map>
 #include <string>
@@ -24,10 +25,10 @@ namespace Kernel {
 class Thread : public Kernel::Object {
 public:
 
-    const char* GetName() { return name; }
-    const char* GetTypeName() { return "Thread"; }
+    const char* GetName() const { return name; }
+    const char* GetTypeName() const { return "Thread"; }
 
-    static Kernel::HandleType GetStaticHandleType() {  return Kernel::HandleType::Thread; }
+    static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Thread; }
     Kernel::HandleType GetHandleType() const { return Kernel::HandleType::Thread; }
 
     inline bool IsRunning() const { return (status & THREADSTATUS_RUNNING) != 0; }
@@ -36,6 +37,23 @@ public:
     inline bool IsWaiting() const { return (status & THREADSTATUS_WAIT) != 0; }
     inline bool IsSuspended() const { return (status & THREADSTATUS_SUSPEND) != 0; }
 
+    /**
+     * Wait for kernel object to synchronize
+     * @param wait Boolean wait set if current thread should wait as a result of sync operation
+     * @return Result of operation, 0 on success, otherwise error code
+     */
+    Result WaitSynchronization(bool* wait) {
+        if (status != THREADSTATUS_DORMANT) {
+            Handle thread = GetCurrentThreadHandle();
+            if (std::find(waiting_threads.begin(), waiting_threads.end(), thread) == waiting_threads.end()) {
+                waiting_threads.push_back(thread);
+            }
+            WaitCurrentThread(WAITTYPE_THREADEND, this->GetHandle());
+            *wait = true;
+        }
+        return 0;
+    }
+
     ThreadContext context;
 
     u32 status;
@@ -49,6 +67,9 @@ public:
     s32 processor_id;
 
     WaitType wait_type;
+    Handle wait_handle;
+
+    std::vector<Handle> waiting_threads;
 
     char name[Kernel::MAX_NAME_LENGTH + 1];
 };
@@ -62,7 +83,6 @@ Common::ThreadQueueList<Handle> g_thread_ready_queue;
 Handle g_current_thread_handle;
 Thread* g_current_thread;
 
-
 /// Gets the current thread
 inline Thread* GetCurrentThread() {
     return g_current_thread;
@@ -94,15 +114,15 @@ void ResetThread(Thread* t, u32 arg, s32 lowest_priority) {
     memset(&t->context, 0, sizeof(ThreadContext));
 
     t->context.cpu_registers[0] = arg;
-    t->context.pc = t->entry_point;
+    t->context.pc = t->context.reg_15 = t->entry_point;
     t->context.sp = t->stack_top;
     t->context.cpsr = 0x1F; // Usermode
     
     if (t->current_priority < lowest_priority) {
         t->current_priority = t->initial_priority;
     }
-        
     t->wait_type = WAITTYPE_NONE;
+    t->wait_handle = 0;
 }
 
 /// Change a thread to "ready" state
@@ -122,6 +142,37 @@ void ChangeReadyState(Thread* t, bool ready) {
     }
 }
 
+/// Verify that a thread has not been released from waiting
+inline bool VerifyWait(const Handle& handle, WaitType type, Handle wait_handle) {
+    Thread* thread = g_object_pool.GetFast<Thread>(handle);
+    _assert_msg_(KERNEL, (thread != nullptr), "called, but thread is nullptr!");
+
+    if (type != thread->wait_type || wait_handle != thread->wait_handle) 
+        return false;
+
+    return true;
+}
+
+/// Stops the current thread
+void StopThread(Handle handle, const char* reason) {
+    Thread* thread = g_object_pool.GetFast<Thread>(handle);
+    _assert_msg_(KERNEL, (thread != nullptr), "called, but thread is nullptr!");
+    
+    ChangeReadyState(thread, false);
+    thread->status = THREADSTATUS_DORMANT;
+    for (size_t i = 0; i < thread->waiting_threads.size(); ++i) {
+        const Handle waiting_thread = thread->waiting_threads[i];
+        if (VerifyWait(waiting_thread, WAITTYPE_THREADEND, handle)) {
+            ResumeThreadFromWait(waiting_thread);
+        }
+    }
+    thread->waiting_threads.clear();
+
+    // Stopped threads are never waiting.
+    thread->wait_type = WAITTYPE_NONE;
+    thread->wait_handle = 0;
+}
+
 /// Changes a threads state
 void ChangeThreadState(Thread* t, ThreadStatus new_status) {
     if (!t || t->status == new_status) {
@@ -132,7 +183,7 @@ void ChangeThreadState(Thread* t, ThreadStatus new_status) {
     
     if (new_status == THREADSTATUS_WAIT) {
         if (t->wait_type == WAITTYPE_NONE) {
-            printf("ERROR: Waittype none not allowed here\n");
+            ERROR_LOG(KERNEL, "Waittype none not allowed");
         }
     }
 }
@@ -166,7 +217,7 @@ void SwitchContext(Thread* t) {
         t->wait_type = WAITTYPE_NONE;
         LoadContext(t->context);
     } else {
-        SetCurrentThread(NULL);
+        SetCurrentThread(nullptr);
     }
 }
 
@@ -181,26 +232,43 @@ Thread* NextThread() {
         next = g_thread_ready_queue.pop_first();
     }
     if (next == 0) {
-        return NULL;
+        return nullptr;
     }
     return Kernel::g_object_pool.GetFast<Thread>(next);
 }
 
 /// Puts the current thread in the wait state for the given type
-void WaitCurrentThread(WaitType wait_type) {
-    Thread* t = GetCurrentThread();
-    t->wait_type = wait_type;
-    ChangeThreadState(t, ThreadStatus(THREADSTATUS_WAIT | (t->status & THREADSTATUS_SUSPEND)));
+void WaitCurrentThread(WaitType wait_type, Handle wait_handle) {
+    Thread* thread = GetCurrentThread();
+    thread->wait_type = wait_type;
+    thread->wait_handle = wait_handle;
+    ChangeThreadState(thread, ThreadStatus(THREADSTATUS_WAIT | (thread->status & THREADSTATUS_SUSPEND)));
 }
 
 /// Resumes a thread from waiting by marking it as "ready"
 void ResumeThreadFromWait(Handle handle) {
     u32 error;
-    Thread* t = Kernel::g_object_pool.Get<Thread>(handle, error);
-    if (t) {
-        t->status &= ~THREADSTATUS_WAIT;
-        if (!(t->status & (THREADSTATUS_WAITSUSPEND | THREADSTATUS_DORMANT | THREADSTATUS_DEAD))) {
-            ChangeReadyState(t, true);
+    Thread* thread = Kernel::g_object_pool.Get<Thread>(handle, error);
+    if (thread) {
+        thread->status &= ~THREADSTATUS_WAIT;
+        if (!(thread->status & (THREADSTATUS_WAITSUSPEND | THREADSTATUS_DORMANT | THREADSTATUS_DEAD))) {
+            ChangeReadyState(thread, true);
+        }
+    }
+}
+
+/// Prints the thread queue for debugging purposes
+void DebugThreadQueue() {
+    Thread* thread = GetCurrentThread();
+    if (!thread) {
+        return;
+    }
+    INFO_LOG(KERNEL, "0x%02X 0x%08X (current)", thread->current_priority, GetCurrentThreadHandle());
+    for (u32 i = 0; i < g_thread_queue.size(); i++) {
+        Handle handle = g_thread_queue[i];
+        s32 priority = g_thread_ready_queue.contains(handle);
+        if (priority != -1) {
+            INFO_LOG(KERNEL, "0x%02X 0x%08X", priority, handle);
         }
     }
 }
@@ -212,32 +280,34 @@ Thread* CreateThread(Handle& handle, const char* name, u32 entry_point, s32 prio
     _assert_msg_(KERNEL, (priority >= THREADPRIO_HIGHEST && priority <= THREADPRIO_LOWEST), 
         "CreateThread priority=%d, outside of allowable range!", priority)
 
-    Thread* t = new Thread;
-    
-    handle = Kernel::g_object_pool.Create(t);
-    
+    Thread* thread = new Thread;
+
+    handle = Kernel::g_object_pool.Create(thread);
+
     g_thread_queue.push_back(handle);
     g_thread_ready_queue.prepare(priority);
-    
-    t->status = THREADSTATUS_DORMANT;
-    t->entry_point = entry_point;
-    t->stack_top = stack_top;
-    t->stack_size = stack_size;
-    t->initial_priority = t->current_priority = priority;
-    t->processor_id = processor_id;
-    t->wait_type = WAITTYPE_NONE;
-    
-    strncpy(t->name, name, Kernel::MAX_NAME_LENGTH);
-    t->name[Kernel::MAX_NAME_LENGTH] = '\0';
-    
-    return t;
+
+    thread->status = THREADSTATUS_DORMANT;
+    thread->entry_point = entry_point;
+    thread->stack_top = stack_top;
+    thread->stack_size = stack_size;
+    thread->initial_priority = thread->current_priority = priority;
+    thread->processor_id = processor_id;
+    thread->wait_type = WAITTYPE_NONE;
+    thread->wait_handle = 0;
+
+    strncpy(thread->name, name, Kernel::MAX_NAME_LENGTH);
+    thread->name[Kernel::MAX_NAME_LENGTH] = '\0';
+
+    return thread;
 }
 
 /// Creates a new thread - wrapper for external user
 Handle CreateThread(const char* name, u32 entry_point, s32 priority, u32 arg, s32 processor_id,
     u32 stack_top, int stack_size) {
-    if (name == NULL) {
-        ERROR_LOG(KERNEL, "CreateThread(): NULL name");
+
+    if (name == nullptr) {
+        ERROR_LOG(KERNEL, "CreateThread(): nullptr name");
         return -1;
     }
     if ((u32)stack_size < 0x200) {
@@ -258,31 +328,67 @@ Handle CreateThread(const char* name, u32 entry_point, s32 priority, u32 arg, s3
         return -1;
     }
     Handle handle;
-    Thread* t = CreateThread(handle, name, entry_point, priority, processor_id, stack_top, 
+    Thread* thread = CreateThread(handle, name, entry_point, priority, processor_id, stack_top, 
         stack_size);
 
-    ResetThread(t, arg, 0);
+    ResetThread(thread, arg, 0);
+    CallThread(thread);
 
-    HLE::EatCycles(32000);
-
-    // This won't schedule to the new thread, but it may to one woken from eating cycles.
-    // Technically, this should not eat all at once, and reschedule in the middle, but that's hard.
-    HLE::ReSchedule("thread created");
-
-    CallThread(t);
-    
     return handle;
 }
 
+/// Get the priority of the thread specified by handle
+u32 GetThreadPriority(const Handle handle) {
+    Thread* thread = g_object_pool.GetFast<Thread>(handle);
+    _assert_msg_(KERNEL, (thread != nullptr), "called, but thread is nullptr!");
+    return thread->current_priority;
+}
+
+/// Set the priority of the thread specified by handle
+Result SetThreadPriority(Handle handle, s32 priority) {
+    Thread* thread = nullptr;
+    if (!handle) {
+        thread = GetCurrentThread(); // TODO(bunnei): Is this correct behavior?
+    } else {
+        thread = g_object_pool.GetFast<Thread>(handle);
+    }
+    _assert_msg_(KERNEL, (thread != nullptr), "called, but thread is nullptr!");
+
+    // If priority is invalid, clamp to valid range
+    if (priority < THREADPRIO_HIGHEST || priority > THREADPRIO_LOWEST) {
+        s32 new_priority = CLAMP(priority, THREADPRIO_HIGHEST, THREADPRIO_LOWEST);
+        WARN_LOG(KERNEL, "invalid priority=0x%08X, clamping to %08X", priority, new_priority);
+        // TODO(bunnei): Clamping to a valid priority is not necessarily correct behavior... Confirm
+        // validity of this
+        priority = new_priority;
+    }
+
+    // Change thread priority
+    s32 old = thread->current_priority;
+    g_thread_ready_queue.remove(old, handle);
+    thread->current_priority = priority;
+    g_thread_ready_queue.prepare(thread->current_priority);
+
+    // Change thread status to "ready" and push to ready queue
+    if (thread->IsRunning()) {
+        thread->status = (thread->status & ~THREADSTATUS_RUNNING) | THREADSTATUS_READY;
+    }
+    if (thread->IsReady()) {
+        g_thread_ready_queue.push_back(thread->current_priority, handle);
+    }
+
+    return 0;
+}
+
 /// Sets up the primary application thread
 Handle SetupMainThread(s32 priority, int stack_size) {
     Handle handle;
     
     // Initialize new "main" thread
-    Thread* t = CreateThread(handle, "main", Core::g_app_core->GetPC(), priority, 
+    Thread* thread = CreateThread(handle, "main", Core::g_app_core->GetPC(), priority, 
         THREADPROCESSORID_0, Memory::SCRATCHPAD_VADDR_END, stack_size);
     
-    ResetThread(t, 0, 0);
+    ResetThread(thread, 0, 0);
     
     // If running another thread already, set it to "ready" state
     Thread* cur = GetCurrentThread();
@@ -291,24 +397,31 @@ Handle SetupMainThread(s32 priority, int stack_size) {
     }
     
     // Run new "main" thread
-    SetCurrentThread(t);
-    t->status = THREADSTATUS_RUNNING;
-    LoadContext(t->context);
+    SetCurrentThread(thread);
+    thread->status = THREADSTATUS_RUNNING;
+    LoadContext(thread->context);
 
     return handle;
 }
 
+
 /// Reschedules to the next available thread (call after current thread is suspended)
 void Reschedule() {
     Thread* prev = GetCurrentThread();
     Thread* next = NextThread();
+    HLE::g_reschedule = false;
     if (next > 0) {
+        INFO_LOG(KERNEL, "context switch 0x%08X -> 0x%08X", prev->GetHandle(), next->GetHandle());
+        
         SwitchContext(next);
 
-        // Hack - automatically change previous thread (which would have been in "wait" state) to
-        // "ready" state, so that we can immediately resume to it when new thread yields. FixMe to
-        // actually wait for whatever event it is supposed to be waiting on.
-        ChangeReadyState(prev, true);
+        // Hack - There is no mechanism yet to waken the primary thread if it has been put to sleep
+        // by a simulated VBLANK thread switch. So, we'll just immediately set it to "ready" again.
+        // This results in the current thread yielding on a VBLANK once, and then it will be 
+        // immediately placed back in the queue for execution.
+        if (prev->wait_type == WAITTYPE_VBLANK) {
+            ResumeThreadFromWait(prev->GetHandle());
+        }
     }
 }
 
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index 9628f165d6..04914ba900 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -34,7 +34,7 @@ enum WaitType {
     WAITTYPE_NONE,
     WAITTYPE_SLEEP,
     WAITTYPE_SEMA,
-    WAITTYPE_EVENTFLAG,
+    WAITTYPE_EVENT,
     WAITTYPE_THREADEND,
     WAITTYPE_VBLANK,
     WAITTYPE_MUTEX,
@@ -53,8 +53,8 @@ Handle SetupMainThread(s32 priority, int stack_size=Kernel::DEFAULT_STACK_SIZE);
 /// Reschedules to the next available thread (call after current thread is suspended)
 void Reschedule();
 
-/// Puts the current thread in the wait state for the given type
-void WaitCurrentThread(WaitType wait_type);
+/// Stops the current thread
+void StopThread(Handle thread, const char* reason);
 
 /// Resumes a thread from waiting by marking it as "ready"
 void ResumeThreadFromWait(Handle handle);
@@ -62,9 +62,18 @@ void ResumeThreadFromWait(Handle handle);
 /// Gets the current thread handle
 Handle GetCurrentThreadHandle();
 
+/// Puts the current thread in the wait state for the given type
+void WaitCurrentThread(WaitType wait_type, Handle wait_handle=GetCurrentThreadHandle());
+
 /// Put current thread in a wait state - on WaitSynchronization
 void WaitThread_Synchronization();
 
+/// Get the priority of the thread specified by handle
+u32 GetThreadPriority(const Handle handle);
+
+/// Set the priority of the thread specified by handle
+Result SetThreadPriority(Handle handle, s32 priority);
+
 /// Initialize threading
 void ThreadingInit();
 
diff --git a/src/core/hle/service/apt.cpp b/src/core/hle/service/apt.cpp
index 32759a0874..a0012b5ddf 100644
--- a/src/core/hle/service/apt.cpp
+++ b/src/core/hle/service/apt.cpp
@@ -6,6 +6,7 @@
 #include "common/common.h"
 
 #include "core/hle/hle.h"
+#include "core/hle/kernel/event.h"
 #include "core/hle/kernel/mutex.h"
 #include "core/hle/service/apt.h"
 
@@ -15,96 +16,120 @@
 namespace APT_U {
 
 void Initialize(Service::Interface* self) {
-    NOTICE_LOG(OSHLE, "APT_U::Sync - Initialize");
+    u32* cmd_buff = Service::GetCommandBuffer();
+    DEBUG_LOG(KERNEL, "called");
+    
+    cmd_buff[3] = Kernel::CreateEvent(RESETTYPE_ONESHOT, "APT_U:Menu");  // APT menu event handle
+    cmd_buff[4] = Kernel::CreateEvent(RESETTYPE_ONESHOT, "APT_U:Pause"); // APT pause event handle
+
+    Kernel::SetEventLocked(cmd_buff[3], true);
+    Kernel::SetEventLocked(cmd_buff[4], false); // Fire start event
+
+    cmd_buff[1] = 0; // No error
 }
 
 void GetLockHandle(Service::Interface* self) {
     u32* cmd_buff = Service::GetCommandBuffer();
     u32 flags = cmd_buff[1]; // TODO(bunnei): Figure out the purpose of the flag field
     cmd_buff[1] = 0; // No error
-    cmd_buff[5] = Kernel::CreateMutex(false);
-    DEBUG_LOG(KERNEL, "APT_U::GetLockHandle called : created handle 0x%08X", cmd_buff[5]);
+    cmd_buff[5] = Kernel::CreateMutex(false, "APT_U:Lock");
+    DEBUG_LOG(KERNEL, "called handle=0x%08X", cmd_buff[5]);
+}
+
+void Enable(Service::Interface* self) {
+    u32* cmd_buff = Service::GetCommandBuffer();
+    u32 unk = cmd_buff[1]; // TODO(bunnei): What is this field used for?
+    cmd_buff[1] = 0; // No error
+    ERROR_LOG(KERNEL, "(UNIMPEMENTED) called unk=0x%08X", unk);
+}
+
+void InquireNotification(Service::Interface* self) {
+    u32* cmd_buff = Service::GetCommandBuffer();
+    u32 app_id = cmd_buff[2];
+    cmd_buff[1] = 0; // No error
+    cmd_buff[3] = 0; // Signal type
+    ERROR_LOG(KERNEL, "(UNIMPEMENTED) called app_id=0x%08X", app_id);
 }
 
 const Interface::FunctionInfo FunctionTable[] = {
-    {0x00010040, GetLockHandle, "GetLockHandle"},
-    {0x00020080, Initialize,    "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"},
+    {0x00010040, GetLockHandle,         "GetLockHandle"},
+    {0x00020080, Initialize,            "Initialize"},
+    {0x00030040, Enable,                "Enable"},
+    {0x00040040, nullptr,               "Finalize"},
+    {0x00050040, nullptr,               "GetAppletManInfo"},
+    {0x00060040, nullptr,               "GetAppletInfo"},
+    {0x00070000, nullptr,               "GetLastSignaledAppletId"},
+    {0x00080000, nullptr,               "CountRegisteredApplet"},
+    {0x00090040, nullptr,               "IsRegistered"},
+    {0x000A0040, nullptr,               "GetAttribute"},
+    {0x000B0040, InquireNotification,   "InquireNotification"},
+    {0x000C0104, nullptr,                "SendParameter"},
+    {0x000D0080, nullptr,                "ReceiveParameter"},
+    {0x000E0080, nullptr,                "GlanceParameter"},
+    {0x000F0100, nullptr,                "CancelParameter"},
+    {0x001000C2, nullptr,                "DebugFunc"},
+    {0x001100C0, nullptr,                "MapProgramIdForDebug"},
+    {0x00120040, nullptr,                "SetHomeMenuAppletIdForDebug"},
+    {0x00130000, nullptr,                "GetPreparationState"},
+    {0x00140040, nullptr,                "SetPreparationState"},
+    {0x00150140, nullptr,                "PrepareToStartApplication"},
+    {0x00160040, nullptr,                "PreloadLibraryApplet"},
+    {0x00170040, nullptr,                "FinishPreloadingLibraryApplet"},
+    {0x00180040, nullptr,                "PrepareToStartLibraryApplet"},
+    {0x00190040, nullptr,                "PrepareToStartSystemApplet"},
+    {0x001A0000, nullptr,                "PrepareToStartNewestHomeMenu"},
+    {0x001B00C4, nullptr,                "StartApplication"},
+    {0x001C0000, nullptr,                "WakeupApplication"},
+    {0x001D0000, nullptr,                "CancelApplication"},
+    {0x001E0084, nullptr,                "StartLibraryApplet"},
+    {0x001F0084, nullptr,                "StartSystemApplet"},
+    {0x00200044, nullptr,                "StartNewestHomeMenu"},
+    {0x00210000, nullptr,                "OrderToCloseApplication"},
+    {0x00220040, nullptr,                "PrepareToCloseApplication"},
+    {0x00230040, nullptr,                "PrepareToJumpToApplication"},
+    {0x00240044, nullptr,                "JumpToApplication"},
+    {0x002500C0, nullptr,                "PrepareToCloseLibraryApplet"},
+    {0x00260000, nullptr,                "PrepareToCloseSystemApplet"},
+    {0x00270044, nullptr,                "CloseApplication"},
+    {0x00280044, nullptr,                "CloseLibraryApplet"},
+    {0x00290044, nullptr,                "CloseSystemApplet"},
+    {0x002A0000, nullptr,                "OrderToCloseSystemApplet"},
+    {0x002B0000, nullptr,                "PrepareToJumpToHomeMenu"},
+    {0x002C0044, nullptr,                "JumpToHomeMenu"},
+    {0x002D0000, nullptr,                "PrepareToLeaveHomeMenu"},
+    {0x002E0044, nullptr,                "LeaveHomeMenu"},
+    {0x002F0040, nullptr,                "PrepareToLeaveResidentApplet"},
+    {0x00300044, nullptr,                "LeaveResidentApplet"},
+    {0x00310100, nullptr,                "PrepareToDoApplicationJump"},
+    {0x00320084, nullptr,                "DoApplicationJump"},
+    {0x00330000, nullptr,                "GetProgramIdOnApplicationJump"},
+    {0x00340084, nullptr,                "SendDeliverArg"},
+    {0x00350080, nullptr,                "ReceiveDeliverArg"},
+    {0x00360040, nullptr,                "LoadSysMenuArg"},
+    {0x00370042, nullptr,                "StoreSysMenuArg"},
+    {0x00380040, nullptr,                "PreloadResidentApplet"},
+    {0x00390040, nullptr,                "PrepareToStartResidentApplet"},
+    {0x003A0044, nullptr,                "StartResidentApplet"},
+    {0x003B0040, nullptr,                "CancelLibraryApplet"},
+    {0x003C0042, nullptr,                "SendDspSleep"},
+    {0x003D0042, nullptr,                "SendDspWakeUp"},
+    {0x003E0080, nullptr,                "ReplySleepQuery"},
+    {0x003F0040, nullptr,                "ReplySleepNotificationComplete"},
+    {0x00400042, nullptr,                "SendCaptureBufferInfo"},
+    {0x00410040, nullptr,                "ReceiveCaptureBufferInfo"},
+    {0x00420080, nullptr,                "SleepSystem"},
+    {0x00430040, nullptr,                "NotifyToWait"},
+    {0x00440000, nullptr,                "GetSharedFont"},
+    {0x00450040, nullptr,                "GetWirelessRebootInfo"},
+    {0x00460104, nullptr,                "Wrap"},
+    {0x00470104, nullptr,                "Unwrap"},
+    {0x00480100, nullptr,                "GetProgramInfo"},
+    {0x00490180, nullptr,                "Reboot"},
+    {0x004A0040, nullptr,                "GetCaptureInfo"},
+    {0x004B00C2, nullptr,                "AppletUtility"},
+    {0x004C0000, nullptr,                "SetFatalErrDispMode"},
+    {0x004D0080, nullptr,                "GetAppletProgramInfo"},
+    {0x004E0000, nullptr,                "HardwareResetAsync"},
 };
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/service/gsp.cpp b/src/core/hle/service/gsp.cpp
index aabcb48db8..f75ba75c28 100644
--- a/src/core/hle/service/gsp.cpp
+++ b/src/core/hle/service/gsp.cpp
@@ -8,6 +8,7 @@
 
 #include "core/mem_map.h"
 #include "core/hle/hle.h"
+#include "core/hle/kernel/event.h"
 #include "core/hle/service/gsp.h"
 
 #include "core/hw/gpu.h"
@@ -60,6 +61,7 @@ void GX_FinishCommand(u32 thread_id) {
 
 namespace GSP_GPU {
 
+Handle g_event_handle = 0;
 u32 g_thread_id = 0;
 
 enum {
@@ -96,7 +98,7 @@ void ReadHWRegs(Service::Interface* self) {
         break;
 
     default:
-        ERROR_LOG(GSP, "ReadHWRegs unknown register read at address %08X", reg_addr);
+        ERROR_LOG(GSP, "unknown register read at address %08X", reg_addr);
     }
 
 }
@@ -104,7 +106,19 @@ void ReadHWRegs(Service::Interface* self) {
 void RegisterInterruptRelayQueue(Service::Interface* self) {
     u32* cmd_buff = Service::GetCommandBuffer();
     u32 flags = cmd_buff[1];
-    u32 event_handle = cmd_buff[3]; // TODO(bunnei): Implement event handling
+    u32 event_handle = cmd_buff[3];
+
+    _assert_msg_(GSP, (event_handle != 0), "called, but event is nullptr!");
+
+    g_event_handle = event_handle;
+
+    Kernel::SetEventLocked(event_handle, false);
+
+    // Hack - This function will permanently set the state of the GSP event such that GPU command 
+    // synchronization barriers always passthrough. Correct solution would be to set this after the 
+    // GPU as processed all queued up commands, but due to the emulator being single-threaded they
+    // will always be ready.
+    Kernel::SetPermanentLock(event_handle, true);
 
     cmd_buff[2] = g_thread_id;          // ThreadID
 }
@@ -150,43 +164,43 @@ void TriggerCmdReqQueue(Service::Interface* self) {
     }
 
     default:
-        ERROR_LOG(GSP, "TriggerCmdReqQueue unknown command 0x%08X", cmd_buff[0]);
+        ERROR_LOG(GSP, "unknown command 0x%08X", cmd_buff[0]);
     }
 
     GX_FinishCommand(g_thread_id);
 }
 
 const Interface::FunctionInfo FunctionTable[] = {
-    {0x00010082, NULL,                          "WriteHWRegs"},
-    {0x00020084, NULL,                          "WriteHWRegsWithMask"},
-    {0x00030082, NULL,                          "WriteHWRegRepeat"},
+    {0x00010082, nullptr,                       "WriteHWRegs"},
+    {0x00020084, nullptr,                       "WriteHWRegsWithMask"},
+    {0x00030082, nullptr,                       "WriteHWRegRepeat"},
     {0x00040080, ReadHWRegs,                    "ReadHWRegs"},
-    {0x00050200, NULL,                          "SetBufferSwap"},
-    {0x00060082, NULL,                          "SetCommandList"},
-    {0x000700C2, NULL,                          "RequestDma"},
-    {0x00080082, NULL,                          "FlushDataCache"},
-    {0x00090082, NULL,                          "InvalidateDataCache"},
-    {0x000A0044, NULL,                          "RegisterInterruptEvents"},
-    {0x000B0040, NULL,                          "SetLcdForceBlack"},
+    {0x00050200, nullptr,                       "SetBufferSwap"},
+    {0x00060082, nullptr,                       "SetCommandList"},
+    {0x000700C2, nullptr,                       "RequestDma"},
+    {0x00080082, nullptr,                       "FlushDataCache"},
+    {0x00090082, nullptr,                       "InvalidateDataCache"},
+    {0x000A0044, nullptr,                       "RegisterInterruptEvents"},
+    {0x000B0040, nullptr,                       "SetLcdForceBlack"},
     {0x000C0000, TriggerCmdReqQueue,            "TriggerCmdReqQueue"},
-    {0x000D0140, NULL,                          "SetDisplayTransfer"},
-    {0x000E0180, NULL,                          "SetTextureCopy"},
-    {0x000F0200, NULL,                          "SetMemoryFill"},
-    {0x00100040, NULL,                          "SetAxiConfigQoSMode"},
-    {0x00110040, NULL,                          "SetPerfLogMode"},
-    {0x00120000, NULL,                          "GetPerfLog"},
+    {0x000D0140, nullptr,                       "SetDisplayTransfer"},
+    {0x000E0180, nullptr,                       "SetTextureCopy"},
+    {0x000F0200, nullptr,                       "SetMemoryFill"},
+    {0x00100040, nullptr,                       "SetAxiConfigQoSMode"},
+    {0x00110040, nullptr,                       "SetPerfLogMode"},
+    {0x00120000, nullptr,                       "GetPerfLog"},
     {0x00130042, RegisterInterruptRelayQueue,   "RegisterInterruptRelayQueue"},
-    {0x00140000, NULL,                          "UnregisterInterruptRelayQueue"},
-    {0x00150002, NULL,                          "TryAcquireRight"},
-    {0x00160042, NULL,                          "AcquireRight"},
-    {0x00170000, NULL,                          "ReleaseRight"},
-    {0x00180000, NULL,                          "ImportDisplayCaptureInfo"},
-    {0x00190000, NULL,                          "SaveVramSysArea"},
-    {0x001A0000, NULL,                          "RestoreVramSysArea"},
-    {0x001B0000, NULL,                          "ResetGpuCore"},
-    {0x001C0040, NULL,                          "SetLedForceOff"},
-    {0x001D0040, NULL,                          "SetTestCommand"},
-    {0x001E0080, NULL,                          "SetInternalPriorities"},
+    {0x00140000, nullptr,                       "UnregisterInterruptRelayQueue"},
+    {0x00150002, nullptr,                       "TryAcquireRight"},
+    {0x00160042, nullptr,                       "AcquireRight"},
+    {0x00170000, nullptr,                       "ReleaseRight"},
+    {0x00180000, nullptr,                       "ImportDisplayCaptureInfo"},
+    {0x00190000, nullptr,                       "SaveVramSysArea"},
+    {0x001A0000, nullptr,                       "RestoreVramSysArea"},
+    {0x001B0000, nullptr,                       "ResetGpuCore"},
+    {0x001C0040, nullptr,                       "SetLedForceOff"},
+    {0x001D0040, nullptr,                       "SetTestCommand"},
+    {0x001E0080, nullptr,                       "SetInternalPriorities"},
 };
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/service/hid.cpp b/src/core/hle/service/hid.cpp
index 5542e5bf2f..ab78f47d7f 100644
--- a/src/core/hle/service/hid.cpp
+++ b/src/core/hle/service/hid.cpp
@@ -13,11 +13,11 @@
 namespace HID_User {
 
 const Interface::FunctionInfo FunctionTable[] = {
-    {0x000A0000, NULL, "GetIPCHandles"},
-    {0x00110000, NULL, "EnableAccelerometer"},
-    {0x00130000, NULL, "EnableGyroscopeLow"},
-    {0x00150000, NULL, "GetGyroscopeLowRawToDpsCoefficient"},
-    {0x00160000, NULL, "GetGyroscopeLowCalibrateParam"},
+    {0x000A0000, nullptr, "GetIPCHandles"},
+    {0x00110000, nullptr, "EnableAccelerometer"},
+    {0x00130000, nullptr, "EnableGyroscopeLow"},
+    {0x00150000, nullptr, "GetGyroscopeLowRawToDpsCoefficient"},
+    {0x00160000, nullptr, "GetGyroscopeLowCalibrateParam"},
 };
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/service/ndm.cpp b/src/core/hle/service/ndm.cpp
new file mode 100644
index 0000000000..48755b6a74
--- /dev/null
+++ b/src/core/hle/service/ndm.cpp
@@ -0,0 +1,32 @@
+// Copyright 2014 Citra Emulator Project
+// Licensed under GPLv2
+// Refer to the license.txt file included.
+
+#include "common/log.h"
+
+#include "core/hle/hle.h"
+#include "core/hle/service/ndm.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Namespace NDM_U
+
+namespace NDM_U {
+
+const Interface::FunctionInfo FunctionTable[] = {
+    {0x00060040, nullptr, "SuspendDaemons"},
+    {0x00080040, nullptr, "DisableWifiUsage"},
+    {0x00090000, nullptr, "EnableWifiUsage"},
+    {0x00140040, nullptr, "OverrideDefaultDaemons"},
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Interface class
+
+Interface::Interface() {
+    Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+}
+
+Interface::~Interface() {
+}
+
+} // namespace
diff --git a/src/core/hle/service/ndm.h b/src/core/hle/service/ndm.h
new file mode 100644
index 0000000000..fbe88fb8f7
--- /dev/null
+++ b/src/core/hle/service/ndm.h
@@ -0,0 +1,33 @@
+// Copyright 2014 Citra Emulator Project
+// Licensed under GPLv2
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Namespace NDM
+
+// No idea what this is
+
+namespace NDM_U {
+
+class Interface : public Service::Interface {
+public:
+
+    Interface();
+
+    ~Interface();
+
+    /**
+     * Gets the string port name used by CTROS for the service
+     * @return Port name of service
+     */
+    const char *GetPortName() const {
+        return "ndm:u";
+    }
+
+};
+
+} // namespace
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index 08d0c43ff5..4a1ac857e5 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -12,13 +12,14 @@
 #include "core/hle/service/apt.h"
 #include "core/hle/service/gsp.h"
 #include "core/hle/service/hid.h"
+#include "core/hle/service/ndm.h"
 #include "core/hle/service/srv.h"
 
 #include "core/hle/kernel/kernel.h"
 
 namespace Service {
 
-Manager* g_manager = NULL;  ///< Service manager
+Manager* g_manager = nullptr;  ///< Service manager
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 // Service Manager class
@@ -55,7 +56,7 @@ Interface* Manager::FetchFromHandle(Handle handle) {
 Interface* Manager::FetchFromPortName(std::string port_name) {
     auto itr = m_port_map.find(port_name);
     if (itr == m_port_map.end()) {
-        return NULL;
+        return nullptr;
     }
     return FetchFromHandle(itr->second);
 }
@@ -72,14 +73,15 @@ void Init() {
     g_manager->AddService(new APT_U::Interface);
     g_manager->AddService(new GSP_GPU::Interface);
     g_manager->AddService(new HID_User::Interface);
+    g_manager->AddService(new NDM_U::Interface);
 
-    NOTICE_LOG(HLE, "Services initialized OK");
+    NOTICE_LOG(HLE, "initialized OK");
 }
 
 /// Shutdown ServiceManager
 void Shutdown() {
     delete g_manager;
-    NOTICE_LOG(HLE, "Services shutdown OK");
+    NOTICE_LOG(HLE, "shutdown OK");
 }
 
 
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h
index fab51753f9..dcd5257271 100644
--- a/src/core/hle/service/service.h
+++ b/src/core/hle/service/service.h
@@ -39,8 +39,8 @@ class Interface  : public Kernel::Object {
     friend class Manager;
 public:
     
-    const char *GetName() { return GetPortName(); }
-    const char *GetTypeName() { return GetPortName(); }
+    const char *GetName() const { return GetPortName(); }
+    const char *GetTypeName() const { return GetPortName(); }
 
     static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Service; }
     Kernel::HandleType GetHandleType() const { return Kernel::HandleType::Service; }
@@ -76,22 +76,31 @@ public:
     }
 
     /**
-     * Called when svcSendSyncRequest is called, loads command buffer and executes comand
-     * @return Return result of svcSendSyncRequest passed back to user app
+     * Synchronize kernel object 
+     * @param wait Boolean wait set if current thread should wait as a result of sync operation
+     * @return Result of operation, 0 on success, otherwise error code
      */
-    Result Sync() {
+    Result SyncRequest(bool* wait) {
         u32* cmd_buff = GetCommandBuffer();
         auto itr = m_functions.find(cmd_buff[0]);
 
         if (itr == m_functions.end()) {
-            ERROR_LOG(OSHLE, "Unknown/unimplemented function: port = %s, command = 0x%08X!", 
+            ERROR_LOG(OSHLE, "unknown/unimplemented function: port=%s, command=0x%08X", 
                 GetPortName(), cmd_buff[0]);
-            return -1;
+
+            // TODO(bunnei): Hack - ignore error
+            u32* cmd_buff = Service::GetCommandBuffer();
+            cmd_buff[1] = 0;
+            return 0; 
         }
-        if (itr->second.func == NULL) {
-            ERROR_LOG(OSHLE, "Unimplemented function: port = %s, name = %s!", 
+        if (itr->second.func == nullptr) {
+            ERROR_LOG(OSHLE, "unimplemented function: port=%s, name=%s", 
                 GetPortName(), itr->second.name.c_str());
-            return -1;
+
+            // TODO(bunnei): Hack - ignore error
+            u32* cmd_buff = Service::GetCommandBuffer();
+            cmd_buff[1] = 0;
+            return 0; 
         } 
 
         itr->second.func(this);
@@ -99,6 +108,17 @@ public:
         return 0; // TODO: Implement return from actual function
     }
 
+    /**
+     * Wait for kernel object to synchronize
+     * @param wait Boolean wait set if current thread should wait as a result of sync operation
+     * @return Result of operation, 0 on success, otherwise error code
+     */
+    Result WaitSynchronization(bool* wait) {
+        // TODO(bunnei): ImplementMe
+        ERROR_LOG(OSHLE, "unimplemented function");
+        return 0;
+    }
+
 protected:
 
     /**
diff --git a/src/core/hle/service/srv.cpp b/src/core/hle/service/srv.cpp
index ff6da8f1cd..f45c0efc27 100644
--- a/src/core/hle/service/srv.cpp
+++ b/src/core/hle/service/srv.cpp
@@ -5,21 +5,28 @@
 #include "core/hle/hle.h"
 #include "core/hle/service/srv.h"
 #include "core/hle/service/service.h"
-
+#include "core/hle/kernel/mutex.h"
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 // Namespace SRV
 
 namespace SRV {
 
+Handle g_mutex = 0;
+
 void Initialize(Service::Interface* self) {
-    NOTICE_LOG(OSHLE, "SRV::Sync - Initialize");
+    DEBUG_LOG(OSHLE, "called");
+    if (!g_mutex) {
+        g_mutex = Kernel::CreateMutex(true, "SRV:Lock");
+    }
 }
 
 void GetProcSemaphore(Service::Interface* self) {
+    DEBUG_LOG(OSHLE, "called");
     // Get process semaphore?
     u32* cmd_buff = Service::GetCommandBuffer();
-    cmd_buff[3] = 0xDEADBEEF; // Return something... 0 == NULL, raises an exception
+    cmd_buff[1] = 0;        // No error
+    cmd_buff[3] = g_mutex;  // Return something... 0 == nullptr, raises an exception
 }
 
 void GetServiceHandle(Service::Interface* self) {
@@ -29,25 +36,21 @@ void GetServiceHandle(Service::Interface* self) {
     std::string port_name = std::string((const char*)&cmd_buff[1], 0, Service::kMaxPortSize);
     Service::Interface* service = Service::g_manager->FetchFromPortName(port_name);
 
-    NOTICE_LOG(OSHLE, "SRV::Sync - GetHandle - port: %s, handle: 0x%08X", port_name.c_str(), 
-        service->GetHandle());
-
-    if (NULL != service) {
+    if (nullptr != service) {
         cmd_buff[3] = service->GetHandle();
+        DEBUG_LOG(OSHLE, "called port=%s, handle=0x%08X", port_name.c_str(), cmd_buff[3]);
     } else {
-        ERROR_LOG(OSHLE, "Service %s does not exist", port_name.c_str());
+        ERROR_LOG(OSHLE, "(UNIMPLEMENTED) called port=%s", port_name.c_str());
         res = -1;
     }
     cmd_buff[1] = res;
-
-    //return res;
 }
 
 const Interface::FunctionInfo FunctionTable[] = {
     {0x00010002, Initialize,        "Initialize"},
     {0x00020000, GetProcSemaphore,  "GetProcSemaphore"},
-    {0x00030100, NULL,              "RegisterService"},
-    {0x000400C0, NULL,              "UnregisterService"},
+    {0x00030100, nullptr,           "RegisterService"},
+    {0x000400C0, nullptr,           "UnregisterService"},
     {0x00050100, GetServiceHandle,  "GetServiceHandle"},
 };
 
diff --git a/src/core/hle/service/srv.h b/src/core/hle/service/srv.h
index 1e35032ba5..81109a2a84 100644
--- a/src/core/hle/service/srv.h
+++ b/src/core/hle/service/srv.h
@@ -26,12 +26,6 @@ public:
         return "srv:";
     }
 
-    /**
-     * Called when svcSendSyncRequest is called, loads command buffer and executes comand
-     * @return Return result of svcSendSyncRequest passed back to user app
-     */
-    Result Sync();
-
 };
 
 } // namespace
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp
index 90c05cb74d..441d8ce8d1 100644
--- a/src/core/hle/svc.cpp
+++ b/src/core/hle/svc.cpp
@@ -9,6 +9,7 @@
 
 #include "core/mem_map.h"
 
+#include "core/hle/kernel/event.h"
 #include "core/hle/kernel/kernel.h"
 #include "core/hle/kernel/mutex.h"
 #include "core/hle/kernel/thread.h"
@@ -16,7 +17,6 @@
 #include "core/hle/function_wrappers.h"
 #include "core/hle/svc.h"
 #include "core/hle/service/service.h"
-#include "core/hle/kernel/thread.h"
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 // Namespace SVC
@@ -34,40 +34,32 @@ enum MapMemoryPermission {
 };
 
 /// Map application or GSP heap memory
-Result ControlMemory(void* _outaddr, u32 operation, u32 addr0, u32 addr1, u32 size, u32 permissions) {
-    u32* outaddr = (u32*)_outaddr;
-    u32 virtual_address = 0x00000000;
-
-    DEBUG_LOG(SVC, "ControlMemory called operation=0x%08X, addr0=0x%08X, addr1=0x%08X, size=%08X, permissions=0x%08X", 
+Result ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 addr1, u32 size, u32 permissions) {
+    DEBUG_LOG(SVC,"called operation=0x%08X, addr0=0x%08X, addr1=0x%08X, size=%08X, permissions=0x%08X", 
         operation, addr0, addr1, size, permissions);
 
     switch (operation) {
 
     // Map normal heap memory
     case MEMORY_OPERATION_HEAP:
-        virtual_address = Memory::MapBlock_Heap(size, operation, permissions);
+        *out_addr = Memory::MapBlock_Heap(size, operation, permissions);
         break;
 
     // Map GSP heap memory
     case MEMORY_OPERATION_GSP_HEAP:
-        virtual_address = Memory::MapBlock_HeapGSP(size, operation, permissions);
+        *out_addr = Memory::MapBlock_HeapGSP(size, operation, permissions);
         break;
 
     // Unknown ControlMemory operation
     default:
-        ERROR_LOG(SVC, "ControlMemory unknown operation=0x%08X", operation);
+        ERROR_LOG(SVC, "unknown operation=0x%08X", operation);
     }
-    if (NULL != outaddr) {
-        *outaddr = virtual_address;
-    }
-    Core::g_app_core->SetReg(1, virtual_address);
-
     return 0;
 }
 
 /// Maps a memory block to specified address
 Result MapMemoryBlock(Handle memblock, u32 addr, u32 mypermissions, u32 otherpermission) {
-    DEBUG_LOG(SVC, "MapMemoryBlock called memblock=0x08X, addr=0x%08X, mypermissions=0x%08X, otherpermission=%d", 
+    DEBUG_LOG(SVC, "called memblock=0x08X, addr=0x%08X, mypermissions=0x%08X, otherpermission=%d", 
         memblock, addr, mypermissions, otherpermission);
     switch (mypermissions) {
     case MEMORY_PERMISSION_NORMAL:
@@ -76,88 +68,146 @@ Result MapMemoryBlock(Handle memblock, u32 addr, u32 mypermissions, u32 otherper
         Memory::MapBlock_Shared(memblock, addr, mypermissions);
         break;
     default:
-        ERROR_LOG(OSHLE, "MapMemoryBlock unknown permissions=0x%08X", mypermissions);
+        ERROR_LOG(OSHLE, "unknown permissions=0x%08X", mypermissions);
     }
     return 0;
 }
 
 /// Connect to an OS service given the port name, returns the handle to the port to out
-Result ConnectToPort(void* out, const char* port_name) {
+Result ConnectToPort(Handle* out, const char* port_name) {
     Service::Interface* service = Service::g_manager->FetchFromPortName(port_name);
-    if (service) {
-        Core::g_app_core->SetReg(1, service->GetHandle());
-    } else {
-        PanicYesNo("ConnectToPort called port_name=%s, but it is not implemented!", port_name);
-    }
-    DEBUG_LOG(SVC, "ConnectToPort called port_name=%s", port_name);
+
+    DEBUG_LOG(SVC, "called port_name=%s", port_name);
+    _assert_msg_(KERNEL, (service != nullptr), "called, but service is not implemented!");
+
+    *out = service->GetHandle();
+
     return 0;
 }
 
 /// Synchronize to an OS service
 Result SendSyncRequest(Handle handle) {
-    DEBUG_LOG(SVC, "SendSyncRequest called handle=0x%08X");
-    Service::Interface* service = Service::g_manager->FetchFromHandle(handle);
-    service->Sync();
-    return 0;
+    Kernel::Object* object = Kernel::g_object_pool.GetFast<Kernel::Object>(handle);
+
+    _assert_msg_(KERNEL, (object != nullptr), "called, but kernel object is nullptr!");
+    DEBUG_LOG(SVC, "called handle=0x%08X(%s)", handle, object->GetTypeName());
+
+    bool wait = false;
+    Result res = object->SyncRequest(&wait);
+    if (wait) {
+        Kernel::WaitCurrentThread(WAITTYPE_SYNCH); // TODO(bunnei): Is this correct?
+    }
+
+    return res;
 }
 
 /// Close a handle
 Result CloseHandle(Handle handle) {
     // ImplementMe
-    DEBUG_LOG(SVC, "(UNIMPLEMENTED) CloseHandle called handle=0x%08X", handle);
+    ERROR_LOG(SVC, "(UNIMPLEMENTED) called handle=0x%08X", handle);
     return 0;
 }
 
 /// Wait for a handle to synchronize, timeout after the specified nanoseconds
 Result WaitSynchronization1(Handle handle, s64 nano_seconds) {
-    DEBUG_LOG(SVC, "(UNIMPLEMENTED) WaitSynchronization1 called handle=0x%08X, nanoseconds=%d", 
-        handle, nano_seconds);
-    Kernel::WaitCurrentThread(WAITTYPE_SYNCH); // TODO(bunnei): Is this correct?
-    return 0;
+    // TODO(bunnei): Do something with nano_seconds, currently ignoring this
+    bool wait = false;
+    bool wait_infinite = (nano_seconds == -1); // Used to wait until a thread has terminated
+
+    Kernel::Object* object = Kernel::g_object_pool.GetFast<Kernel::Object>(handle);
+
+    DEBUG_LOG(SVC, "called handle=0x%08X(%s:%s), nanoseconds=%d", handle, object->GetTypeName(), 
+            object->GetName(), nano_seconds);
+
+    _assert_msg_(KERNEL, (object != nullptr), "called, but kernel object is nullptr!");
+
+    Result res = object->WaitSynchronization(&wait);
+
+    // Check for next thread to schedule
+    if (wait) {
+        HLE::Reschedule(__func__);
+        return 0;
+    }
+
+    return res;
 }
 
 /// Wait for the given handles to synchronize, timeout after the specified nanoseconds
-Result WaitSynchronizationN(void* _out, void* _handles, u32 handle_count, u32 wait_all, s64 nano_seconds) {
-    s32* out = (s32*)_out;
-    Handle* handles = (Handle*)_handles;
+Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, bool wait_all, 
+    s64 nano_seconds) {
+    // TODO(bunnei): Do something with nano_seconds, currently ignoring this
+    bool unlock_all = true;
+    bool wait_infinite = (nano_seconds == -1); // Used to wait until a thread has terminated
 
-    DEBUG_LOG(SVC, "(UNIMPLEMENTED) WaitSynchronizationN called handle_count=%d, wait_all=%s, nanoseconds=%d %s", 
+    DEBUG_LOG(SVC, "called handle_count=%d, wait_all=%s, nanoseconds=%d", 
         handle_count, (wait_all ? "true" : "false"), nano_seconds);
 
-    for (u32 i = 0; i < handle_count; i++) {
-        DEBUG_LOG(SVC, "\thandle[%d]=0x%08X", i, handles[i]);
+    // Iterate through each handle, synchronize kernel object
+    for (s32 i = 0; i < handle_count; i++) {
+        bool wait = false;
+        Kernel::Object* object = Kernel::g_object_pool.GetFast<Kernel::Object>(handles[i]);
+
+        _assert_msg_(KERNEL, (object != nullptr), "called handle=0x%08X, but kernel object "
+            "is nullptr!", handles[i]);
+
+        DEBUG_LOG(SVC, "\thandle[%d] = 0x%08X(%s:%s)", i, handles[i], object->GetTypeName(), 
+            object->GetName());
+
+        Result res = object->WaitSynchronization(&wait);
+
+        if (!wait && !wait_all) {
+            *out = i;
+            return 0;
+        } else {
+            unlock_all = false;
+        }
     }
-    Kernel::WaitCurrentThread(WAITTYPE_SYNCH); // TODO(bunnei): Is this correct?
+
+    if (wait_all && unlock_all) {
+        *out = handle_count;
+        return 0;
+    }
+
+    // Check for next thread to schedule
+    HLE::Reschedule(__func__);
+
     return 0;
 }
 
 /// Create an address arbiter (to allocate access to shared resources)
 Result CreateAddressArbiter(void* arbiter) {
-    // ImplementMe
-    DEBUG_LOG(SVC, "(UNIMPLEMENTED) CreateAddressArbiter called");
+    ERROR_LOG(SVC, "(UNIMPLEMENTED) called");
     Core::g_app_core->SetReg(1, 0xFABBDADD);
     return 0;
 }
 
+/// Arbitrate address
+Result ArbitrateAddress(Handle arbiter, u32 addr, u32 _type, u32 value, s64 nanoseconds) {
+    ERROR_LOG(SVC, "(UNIMPLEMENTED) called");
+    ArbitrationType type = (ArbitrationType)_type;
+    Memory::Write32(addr, type);
+    return 0;
+}
+
 /// Used to output a message on a debug hardware unit - does nothing on a retail unit
 void OutputDebugString(const char* string) {
-    NOTICE_LOG(SVC, "## OSDEBUG: %08X %s", Core::g_app_core->GetPC(), string);
+    OS_LOG(SVC, "%s", string);
 }
 
 /// Get resource limit
-Result GetResourceLimit(void* resource_limit, Handle process) {
+Result GetResourceLimit(Handle* resource_limit, Handle process) {
     // With regards to proceess values:
     // 0xFFFF8001 is a handle alias for the current KProcess, and 0xFFFF8000 is a handle alias for 
     // the current KThread.
-    DEBUG_LOG(SVC, "(UNIMPLEMENTED) GetResourceLimit called process=0x%08X", process);
-    Core::g_app_core->SetReg(1, 0xDEADBEEF);
+    *resource_limit = 0xDEADBEEF;
+    ERROR_LOG(SVC, "(UNIMPLEMENTED) called process=0x%08X", process);
     return 0;
 }
 
 /// Get resource limit current values
-Result GetResourceLimitCurrentValues(void* _values, Handle resource_limit, void* names, s32 name_count) {
-    //s64* values = (s64*)_values;
-    DEBUG_LOG(SVC, "(UNIMPLEMENTED) GetResourceLimitCurrentValues called resource_limit=%08X, names=%s, name_count=%d",
+Result GetResourceLimitCurrentValues(s64* values, Handle resource_limit, void* names, 
+    s32 name_count) {
+    ERROR_LOG(SVC, "(UNIMPLEMENTED) called resource_limit=%08X, names=%s, name_count=%d",
         resource_limit, names, name_count);
     Memory::Write32(Core::g_app_core->GetReg(0), 0); // Normmatt: Set used memory to 0 for now
     return 0;
@@ -180,179 +230,234 @@ Result CreateThread(u32 priority, u32 entry_point, u32 arg, u32 stack_top, u32 p
 
     Core::g_app_core->SetReg(1, thread);
 
-    DEBUG_LOG(SVC, "CreateThread called entrypoint=0x%08X (%s), arg=0x%08X, stacktop=0x%08X, "
-        "threadpriority=0x%08X, processorid=0x%08X : created handle 0x%08X", entry_point, 
+    DEBUG_LOG(SVC, "called entrypoint=0x%08X (%s), arg=0x%08X, stacktop=0x%08X, "
+        "threadpriority=0x%08X, processorid=0x%08X : created handle=0x%08X", entry_point, 
         name.c_str(), arg, stack_top, priority, processor_id, thread);
     
     return 0;
 }
 
+/// Called when a thread exits
+u32 ExitThread() {
+    Handle thread = Kernel::GetCurrentThreadHandle();
+
+    DEBUG_LOG(SVC, "called, pc=0x%08X", Core::g_app_core->GetPC()); // PC = 0x0010545C
+
+    Kernel::StopThread(thread, __func__);
+    HLE::Reschedule(__func__);
+    return 0;
+}
+
+/// Gets the priority for the specified thread
+Result GetThreadPriority(s32* priority, Handle handle) {
+    *priority = Kernel::GetThreadPriority(handle);
+    return 0;
+}
+
+/// Sets the priority for the specified thread
+Result SetThreadPriority(Handle handle, s32 priority) {
+    return Kernel::SetThreadPriority(handle, priority);
+}
+
 /// Create a mutex
-Result CreateMutex(void* _mutex, u32 initial_locked) {
-    Handle* mutex = (Handle*)_mutex;
+Result CreateMutex(Handle* mutex, u32 initial_locked) {
     *mutex = Kernel::CreateMutex((initial_locked != 0));
-    Core::g_app_core->SetReg(1, *mutex);
-    DEBUG_LOG(SVC, "CreateMutex called initial_locked=%s : created handle 0x%08X", 
+    DEBUG_LOG(SVC, "called initial_locked=%s : created handle=0x%08X", 
         initial_locked ? "true" : "false", *mutex);
     return 0;
 }
 
 /// Release a mutex
 Result ReleaseMutex(Handle handle) {
-    DEBUG_LOG(SVC, "ReleaseMutex called handle=0x%08X", handle);
+    DEBUG_LOG(SVC, "called handle=0x%08X", handle);
+    _assert_msg_(KERNEL, (handle != 0), "called, but handle is nullptr!");
     Kernel::ReleaseMutex(handle);
     return 0;
 }
 
 /// Get current thread ID
-Result GetThreadId(void* thread_id, u32 thread) {
-    DEBUG_LOG(SVC, "(UNIMPLEMENTED) GetThreadId called thread=0x%08X", thread);
+Result GetThreadId(u32* thread_id, Handle thread) {
+    ERROR_LOG(SVC, "(UNIMPLEMENTED) called thread=0x%08X", thread);
     return 0;
 }
 
 /// Query memory
-Result QueryMemory(void *_info, void *_out, u32 addr) {
-    MemoryInfo* info = (MemoryInfo*) _info;
-    PageInfo* out = (PageInfo*) _out;
-    DEBUG_LOG(SVC, "(UNIMPLEMENTED) QueryMemory called addr=0x%08X", addr);
+Result QueryMemory(void* info, void* out, u32 addr) {
+    ERROR_LOG(SVC, "(UNIMPLEMENTED) called addr=0x%08X", addr);
     return 0;
 }
 
 /// Create an event
-Result CreateEvent(void* _event, u32 reset_type) {
-    Handle* event = (Handle*)_event;
-    DEBUG_LOG(SVC, "(UNIMPLEMENTED) CreateEvent called reset_type=0x%08X", reset_type);
-    Core::g_app_core->SetReg(1, 0xBADC0DE0);
+Result CreateEvent(Handle* evt, u32 reset_type) {
+    *evt = Kernel::CreateEvent((ResetType)reset_type);
+    DEBUG_LOG(SVC, "called reset_type=0x%08X : created handle=0x%08X", 
+        reset_type, *evt);
     return 0;
 }
 
+/// Duplicates a kernel handle
+Result DuplicateHandle(Handle* out, Handle handle) {
+    DEBUG_LOG(SVC, "called handle=0x%08X", handle);
+
+    // Translate kernel handles -> real handles
+    if (handle == Kernel::CurrentThread) {
+        handle = Kernel::GetCurrentThreadHandle();
+    }
+    _assert_msg_(KERNEL, (handle != Kernel::CurrentProcess),
+        "(UNIMPLEMENTED) process handle duplication!");
+    
+    // TODO(bunnei): FixMe - This is a hack to return the handle that we were asked to duplicate.
+    *out = handle;
+
+    return 0;
+}
+
+/// Signals an event
+Result SignalEvent(Handle evt) {
+    Result res = Kernel::SignalEvent(evt);
+    DEBUG_LOG(SVC, "called event=0x%08X", evt);
+    return res;
+}
+
+/// Clears an event
+Result ClearEvent(Handle evt) {
+    Result res = Kernel::ClearEvent(evt);
+    DEBUG_LOG(SVC, "called event=0x%08X", evt);
+    return res;
+}
+
+/// Sleep the current thread
+void SleepThread(s64 nanoseconds) {
+    DEBUG_LOG(SVC, "called nanoseconds=%d", nanoseconds);
+}
+
 const HLE::FunctionDef SVC_Table[] = {
-    {0x00,  NULL,                                       "Unknown"},
-    {0x01,  WrapI_VUUUUU<ControlMemory>,                "ControlMemory"},
-    {0x02,  WrapI_VVU<QueryMemory>,                     "QueryMemory"},
-    {0x03,  NULL,                                       "ExitProcess"},
-    {0x04,  NULL,                                       "GetProcessAffinityMask"},
-    {0x05,  NULL,                                       "SetProcessAffinityMask"},
-    {0x06,  NULL,                                       "GetProcessIdealProcessor"},
-    {0x07,  NULL,                                       "SetProcessIdealProcessor"},
-    {0x08,  WrapI_UUUUU<CreateThread>,                  "CreateThread"},
-    {0x09,  NULL,                                       "ExitThread"},
-    {0x0A,  NULL,                                       "SleepThread"},
-    {0x0B,  NULL,                                       "GetThreadPriority"},
-    {0x0C,  NULL,                                       "SetThreadPriority"},
-    {0x0D,  NULL,                                       "GetThreadAffinityMask"},
-    {0x0E,  NULL,                                       "SetThreadAffinityMask"},
-    {0x0F,  NULL,                                       "GetThreadIdealProcessor"},
-    {0x10,  NULL,                                       "SetThreadIdealProcessor"},
-    {0x11,  NULL,                                       "GetCurrentProcessorNumber"},
-    {0x12,  NULL,                                       "Run"},
-    {0x13,  WrapI_VU<CreateMutex>,                      "CreateMutex"},
-    {0x14,  WrapI_U<ReleaseMutex>,                      "ReleaseMutex"},
-    {0x15,  NULL,                                       "CreateSemaphore"},
-    {0x16,  NULL,                                       "ReleaseSemaphore"},
-    {0x17,  WrapI_VU<CreateEvent>,                      "CreateEvent"},
-    {0x18,  NULL,                                       "SignalEvent"},
-    {0x19,  NULL,                                       "ClearEvent"},
-    {0x1A,  NULL,                                       "CreateTimer"},
-    {0x1B,  NULL,                                       "SetTimer"},
-    {0x1C,  NULL,                                       "CancelTimer"},
-    {0x1D,  NULL,                                       "ClearTimer"},
-    {0x1E,  NULL,                                       "CreateMemoryBlock"},
-    {0x1F,  WrapI_UUUU<MapMemoryBlock>,                 "MapMemoryBlock"},
-    {0x20,  NULL,                                       "UnmapMemoryBlock"},
-    {0x21,  WrapI_V<CreateAddressArbiter>,              "CreateAddressArbiter"},
-    {0x22,  NULL,                                       "ArbitrateAddress"},
-    {0x23,  WrapI_U<CloseHandle>,                       "CloseHandle"},
-    {0x24,  WrapI_US64<WaitSynchronization1>,           "WaitSynchronization1"},
-    {0x25,  WrapI_VVUUS64<WaitSynchronizationN>,        "WaitSynchronizationN"},
-    {0x26,  NULL,                                       "SignalAndWait"},
-    {0x27,  NULL,                                       "DuplicateHandle"},
-    {0x28,  NULL,                                       "GetSystemTick"},
-    {0x29,  NULL,                                       "GetHandleInfo"},
-    {0x2A,  NULL,                                       "GetSystemInfo"},
-    {0x2B,  NULL,                                       "GetProcessInfo"},
-    {0x2C,  NULL,                                       "GetThreadInfo"},
-    {0x2D,  WrapI_VC<ConnectToPort>,                    "ConnectToPort"},
-    {0x2E,  NULL,                                       "SendSyncRequest1"},
-    {0x2F,  NULL,                                       "SendSyncRequest2"},
-    {0x30,  NULL,                                       "SendSyncRequest3"},
-    {0x31,  NULL,                                       "SendSyncRequest4"},
-    {0x32,  WrapI_U<SendSyncRequest>,                   "SendSyncRequest"},
-    {0x33,  NULL,                                       "OpenProcess"},
-    {0x34,  NULL,                                       "OpenThread"},
-    {0x35,  NULL,                                       "GetProcessId"},
-    {0x36,  NULL,                                       "GetProcessIdOfThread"},
-    {0x37,  WrapI_VU<GetThreadId>,                      "GetThreadId"},
-    {0x38,  WrapI_VU<GetResourceLimit>,                 "GetResourceLimit"},
-    {0x39,  NULL,                                       "GetResourceLimitLimitValues"},
-    {0x3A,  WrapI_VUVI<GetResourceLimitCurrentValues>,  "GetResourceLimitCurrentValues"},
-    {0x3B,  NULL,                                       "GetThreadContext"},
-    {0x3C,  NULL,                                       "Break"},
-    {0x3D,  WrapV_C<OutputDebugString>,                 "OutputDebugString"},
-    {0x3E,  NULL,                                       "ControlPerformanceCounter"},
-    {0x3F,  NULL,                                       "Unknown"},
-    {0x40,  NULL,                                       "Unknown"},
-    {0x41,  NULL,                                       "Unknown"},
-    {0x42,  NULL,                                       "Unknown"},
-    {0x43,  NULL,                                       "Unknown"},
-    {0x44,  NULL,                                       "Unknown"},
-    {0x45,  NULL,                                       "Unknown"},
-    {0x46,  NULL,                                       "Unknown"},
-    {0x47,  NULL,                                       "CreatePort"},
-    {0x48,  NULL,                                       "CreateSessionToPort"},
-    {0x49,  NULL,                                       "CreateSession"},
-    {0x4A,  NULL,                                       "AcceptSession"},
-    {0x4B,  NULL,                                       "ReplyAndReceive1"},
-    {0x4C,  NULL,                                       "ReplyAndReceive2"},
-    {0x4D,  NULL,                                       "ReplyAndReceive3"},
-    {0x4E,  NULL,                                       "ReplyAndReceive4"},
-    {0x4F,  NULL,                                       "ReplyAndReceive"},
-    {0x50,  NULL,                                       "BindInterrupt"},
-    {0x51,  NULL,                                       "UnbindInterrupt"},
-    {0x52,  NULL,                                       "InvalidateProcessDataCache"},
-    {0x53,  NULL,                                       "StoreProcessDataCache"},
-    {0x54,  NULL,                                       "FlushProcessDataCache"},
-    {0x55,  NULL,                                       "StartInterProcessDma"},
-    {0x56,  NULL,                                       "StopDma"},
-    {0x57,  NULL,                                       "GetDmaState"},
-    {0x58,  NULL,                                       "RestartDma"},
-    {0x59,  NULL,                                       "Unknown"},
-    {0x5A,  NULL,                                       "Unknown"},
-    {0x5B,  NULL,                                       "Unknown"},
-    {0x5C,  NULL,                                       "Unknown"},
-    {0x5D,  NULL,                                       "Unknown"},
-    {0x5E,  NULL,                                       "Unknown"},
-    {0x5F,  NULL,                                       "Unknown"},
-    {0x60,  NULL,                                       "DebugActiveProcess"},
-    {0x61,  NULL,                                       "BreakDebugProcess"},
-    {0x62,  NULL,                                       "TerminateDebugProcess"},
-    {0x63,  NULL,                                       "GetProcessDebugEvent"},
-    {0x64,  NULL,                                       "ContinueDebugEvent"},
-    {0x65,  NULL,                                       "GetProcessList"},
-    {0x66,  NULL,                                       "GetThreadList"},
-    {0x67,  NULL,                                       "GetDebugThreadContext"},
-    {0x68,  NULL,                                       "SetDebugThreadContext"},
-    {0x69,  NULL,                                       "QueryDebugProcessMemory"},
-    {0x6A,  NULL,                                       "ReadProcessMemory"},
-    {0x6B,  NULL,                                       "WriteProcessMemory"},
-    {0x6C,  NULL,                                       "SetHardwareBreakPoint"},
-    {0x6D,  NULL,                                       "GetDebugThreadParam"},
-    {0x6E,  NULL,                                       "Unknown"},
-    {0x6F,  NULL,                                       "Unknown"},
-    {0x70,  NULL,                                       "ControlProcessMemory"},
-    {0x71,  NULL,                                       "MapProcessMemory"},
-    {0x72,  NULL,                                       "UnmapProcessMemory"},
-    {0x73,  NULL,                                       "Unknown"},
-    {0x74,  NULL,                                       "Unknown"},
-    {0x75,  NULL,                                       "Unknown"},
-    {0x76,  NULL,                                       "TerminateProcess"},
-    {0x77,  NULL,                                       "Unknown"},
-    {0x78,  NULL,                                       "CreateResourceLimit"},
-    {0x79,  NULL,                                       "Unknown"},
-    {0x7A,  NULL,                                       "Unknown"},
-    {0x7B,  NULL,                                       "Unknown"},
-    {0x7C,  NULL,                                       "KernelSetState"},
-    {0x7D,  NULL,                                       "QueryProcessMemory"},
+    {0x00, nullptr,                         "Unknown"},
+    {0x01, HLE::Wrap<ControlMemory>,        "ControlMemory"},
+    {0x02, HLE::Wrap<QueryMemory>,          "QueryMemory"},
+    {0x03, nullptr,                         "ExitProcess"},
+    {0x04, nullptr,                         "GetProcessAffinityMask"},
+    {0x05, nullptr,                         "SetProcessAffinityMask"},
+    {0x06, nullptr,                         "GetProcessIdealProcessor"},
+    {0x07, nullptr,                         "SetProcessIdealProcessor"},
+    {0x08, HLE::Wrap<CreateThread>,         "CreateThread"},
+    {0x09, HLE::Wrap<ExitThread>,           "ExitThread"},
+    {0x0A, HLE::Wrap<SleepThread>,          "SleepThread"},
+    {0x0B, HLE::Wrap<GetThreadPriority>,    "GetThreadPriority"},
+    {0x0C, HLE::Wrap<SetThreadPriority>,    "SetThreadPriority"},
+    {0x0D, nullptr,                         "GetThreadAffinityMask"},
+    {0x0E, nullptr,                         "SetThreadAffinityMask"},
+    {0x0F, nullptr,                         "GetThreadIdealProcessor"},
+    {0x10, nullptr,                         "SetThreadIdealProcessor"},
+    {0x11, nullptr,                         "GetCurrentProcessorNumber"},
+    {0x12, nullptr,                         "Run"},
+    {0x13, HLE::Wrap<CreateMutex>,          "CreateMutex"},
+    {0x14, HLE::Wrap<ReleaseMutex>,         "ReleaseMutex"},
+    {0x15, nullptr,                         "CreateSemaphore"},
+    {0x16, nullptr,                         "ReleaseSemaphore"},
+    {0x17, HLE::Wrap<CreateEvent>,          "CreateEvent"},
+    {0x18, HLE::Wrap<SignalEvent>,          "SignalEvent"},
+    {0x19, HLE::Wrap<ClearEvent>,           "ClearEvent"},
+    {0x1A, nullptr,                         "CreateTimer"},
+    {0x1B, nullptr,                         "SetTimer"},
+    {0x1C, nullptr,                         "CancelTimer"},
+    {0x1D, nullptr,                         "ClearTimer"},
+    {0x1E, nullptr,                         "CreateMemoryBlock"},
+    {0x1F, HLE::Wrap<MapMemoryBlock>,       "MapMemoryBlock"},
+    {0x20, nullptr,                         "UnmapMemoryBlock"},
+    {0x21, HLE::Wrap<CreateAddressArbiter>, "CreateAddressArbiter"},
+    {0x22, HLE::Wrap<ArbitrateAddress>,     "ArbitrateAddress"},
+    {0x23, HLE::Wrap<CloseHandle>,          "CloseHandle"},
+    {0x24, HLE::Wrap<WaitSynchronization1>, "WaitSynchronization1"},
+    {0x25, HLE::Wrap<WaitSynchronizationN>, "WaitSynchronizationN"},
+    {0x26, nullptr,                         "SignalAndWait"},
+    {0x27, HLE::Wrap<DuplicateHandle>,      "DuplicateHandle"},
+    {0x28, nullptr,                         "GetSystemTick"},
+    {0x29, nullptr,                         "GetHandleInfo"},
+    {0x2A, nullptr,                         "GetSystemInfo"},
+    {0x2B, nullptr,                         "GetProcessInfo"},
+    {0x2C, nullptr,                         "GetThreadInfo"},
+    {0x2D, HLE::Wrap<ConnectToPort>,        "ConnectToPort"},
+    {0x2E, nullptr,                         "SendSyncRequest1"},
+    {0x2F, nullptr,                         "SendSyncRequest2"},
+    {0x30, nullptr,                         "SendSyncRequest3"},
+    {0x31, nullptr,                         "SendSyncRequest4"},
+    {0x32, HLE::Wrap<SendSyncRequest>,      "SendSyncRequest"},
+    {0x33, nullptr,                         "OpenProcess"},
+    {0x34, nullptr,                         "OpenThread"},
+    {0x35, nullptr,                         "GetProcessId"},
+    {0x36, nullptr,                         "GetProcessIdOfThread"},
+    {0x37, HLE::Wrap<GetThreadId>,          "GetThreadId"},
+    {0x38, HLE::Wrap<GetResourceLimit>,     "GetResourceLimit"},
+    {0x39, nullptr,                         "GetResourceLimitLimitValues"},
+    {0x3A, HLE::Wrap<GetResourceLimitCurrentValues>, "GetResourceLimitCurrentValues"},
+    {0x3B, nullptr,                         "GetThreadContext"},
+    {0x3C, nullptr,                         "Break"},
+    {0x3D, HLE::Wrap<OutputDebugString>,    "OutputDebugString"},
+    {0x3E, nullptr,                         "ControlPerformanceCounter"},
+    {0x3F, nullptr,                         "Unknown"},
+    {0x40, nullptr,                         "Unknown"},
+    {0x41, nullptr,                         "Unknown"},
+    {0x42, nullptr,                         "Unknown"},
+    {0x43, nullptr,                         "Unknown"},
+    {0x44, nullptr,                         "Unknown"},
+    {0x45, nullptr,                         "Unknown"},
+    {0x46, nullptr,                         "Unknown"},
+    {0x47, nullptr,                         "CreatePort"},
+    {0x48, nullptr,                         "CreateSessionToPort"},
+    {0x49, nullptr,                         "CreateSession"},
+    {0x4A, nullptr,                         "AcceptSession"},
+    {0x4B, nullptr,                         "ReplyAndReceive1"},
+    {0x4C, nullptr,                         "ReplyAndReceive2"},
+    {0x4D, nullptr,                         "ReplyAndReceive3"},
+    {0x4E, nullptr,                         "ReplyAndReceive4"},
+    {0x4F, nullptr,                         "ReplyAndReceive"},
+    {0x50, nullptr,                         "BindInterrupt"},
+    {0x51, nullptr,                         "UnbindInterrupt"},
+    {0x52, nullptr,                         "InvalidateProcessDataCache"},
+    {0x53, nullptr,                         "StoreProcessDataCache"},
+    {0x54, nullptr,                         "FlushProcessDataCache"},
+    {0x55, nullptr,                         "StartInterProcessDma"},
+    {0x56, nullptr,                         "StopDma"},
+    {0x57, nullptr,                         "GetDmaState"},
+    {0x58, nullptr,                         "RestartDma"},
+    {0x59, nullptr,                         "Unknown"},
+    {0x5A, nullptr,                         "Unknown"},
+    {0x5B, nullptr,                         "Unknown"},
+    {0x5C, nullptr,                         "Unknown"},
+    {0x5D, nullptr,                         "Unknown"},
+    {0x5E, nullptr,                         "Unknown"},
+    {0x5F, nullptr,                         "Unknown"},
+    {0x60, nullptr,                         "DebugActiveProcess"},
+    {0x61, nullptr,                         "BreakDebugProcess"},
+    {0x62, nullptr,                         "TerminateDebugProcess"},
+    {0x63, nullptr,                         "GetProcessDebugEvent"},
+    {0x64, nullptr,                         "ContinueDebugEvent"},
+    {0x65, nullptr,                         "GetProcessList"},
+    {0x66, nullptr,                         "GetThreadList"},
+    {0x67, nullptr,                         "GetDebugThreadContext"},
+    {0x68, nullptr,                         "SetDebugThreadContext"},
+    {0x69, nullptr,                         "QueryDebugProcessMemory"},
+    {0x6A, nullptr,                         "ReadProcessMemory"},
+    {0x6B, nullptr,                         "WriteProcessMemory"},
+    {0x6C, nullptr,                         "SetHardwareBreakPoint"},
+    {0x6D, nullptr,                         "GetDebugThreadParam"},
+    {0x6E, nullptr,                         "Unknown"},
+    {0x6F, nullptr,                         "Unknown"},
+    {0x70, nullptr,                         "ControlProcessMemory"},
+    {0x71, nullptr,                         "MapProcessMemory"},
+    {0x72, nullptr,                         "UnmapProcessMemory"},
+    {0x73, nullptr,                         "Unknown"},
+    {0x74, nullptr,                         "Unknown"},
+    {0x75, nullptr,                         "Unknown"},
+    {0x76, nullptr,                         "TerminateProcess"},
+    {0x77, nullptr,                         "Unknown"},
+    {0x78, nullptr,                         "CreateResourceLimit"},
+    {0x79, nullptr,                         "Unknown"},
+    {0x7A, nullptr,                         "Unknown"},
+    {0x7B, nullptr,                         "Unknown"},
+    {0x7C, nullptr,                         "KernelSetState"},
+    {0x7D, nullptr,                         "QueryProcessMemory"},
 };
 
 void Register() {
diff --git a/src/core/hle/svc.h b/src/core/hle/svc.h
index 5c35977d13..1d125faf62 100644
--- a/src/core/hle/svc.h
+++ b/src/core/hle/svc.h
@@ -29,6 +29,10 @@ struct ThreadContext {
     u32 fpu_registers[32];
     u32 fpscr;
     u32 fpexc;
+
+    // These are not part of native ThreadContext, but needed by emu
+    u32 reg_15;
+    u32 mode;
 };
 
 enum ResetType {
@@ -38,6 +42,15 @@ enum ResetType {
     RESETTYPE_MAX_BIT = (1u << 31),
 };
 
+enum ArbitrationType {
+    ARBITRATIONTYPE_SIGNAL,
+    ARBITRATIONTYPE_WAIT_IF_LESS_THAN,
+    ARBITRATIONTYPE_DECREMENT_AND_WAIT_IF_LESS_THAN,
+    ARBITRATIONTYPE_WAIT_IF_LESS_THAN_WITH_TIMEOUT,
+    ARBITRATIONTYPE_DECREMENT_AND_WAIT_IF_LESS_THAN_WITH_TIMEOUT,
+    ARBITRATIONTYPE_MAX_BIT = (1u << 31)
+};
+
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 // Namespace SVC
 
diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp
index ec2d0e1569..f0ca4eadad 100644
--- a/src/core/hw/gpu.cpp
+++ b/src/core/hw/gpu.cpp
@@ -17,8 +17,6 @@ namespace GPU {
 
 Registers g_regs;
 
-static const u32 kFrameTicks = 268123480 / 60;  ///< 268MHz / 60 frames per second
-
 u64 g_last_ticks = 0; ///< Last CPU ticks
 
 /**
diff --git a/src/core/hw/gpu.h b/src/core/hw/gpu.h
index f26f25e988..3314ba9892 100644
--- a/src/core/hw/gpu.h
+++ b/src/core/hw/gpu.h
@@ -8,6 +8,9 @@
 
 namespace GPU {
 
+static const u32 kFrameCycles   = 268123480 / 60;   ///< 268MHz / 60 frames per second
+static const u32 kFrameTicks    = kFrameCycles / 3; ///< Approximate number of instructions/frame
+
 struct Registers {
     enum Id : u32 {
         FramebufferTopLeft1     = 0x1EF00468,   // Main LCD, first framebuffer for 3D left
diff --git a/src/core/mem_map_funcs.cpp b/src/core/mem_map_funcs.cpp
index 86e9eaa203..ab014a5965 100644
--- a/src/core/mem_map_funcs.cpp
+++ b/src/core/mem_map_funcs.cpp
@@ -86,7 +86,7 @@ inline void _Read(T &var, const u32 addr) {
         var = *((const T*)&g_vram[vaddr & VRAM_MASK]);
 
     } else {
-        //_assert_msg_(MEMMAP, false, "unknown Read%d @ 0x%08X", sizeof(var) * 8, vaddr);
+        ERROR_LOG(MEMMAP, "unknown Read%d @ 0x%08X", sizeof(var) * 8, vaddr);
     }
 }
 
@@ -136,8 +136,7 @@ inline void _Write(u32 addr, const T data) {
     
     // Error out...
     } else {
-        _assert_msg_(MEMMAP, false, "unknown Write%d 0x%08X @ 0x%08X", sizeof(data) * 8,
-            data, vaddr);
+        ERROR_LOG(MEMMAP, "unknown Write%d 0x%08X @ 0x%08X", sizeof(data) * 8, data, vaddr);
     }
 }
 
diff --git a/src/core/system.cpp b/src/core/system.cpp
index c77092327b..9b1e96888a 100644
--- a/src/core/system.cpp
+++ b/src/core/system.cpp
@@ -8,6 +8,7 @@
 #include "core/system.h"
 #include "core/hw/hw.h"
 #include "core/hle/hle.h"
+#include "core/hle/kernel/kernel.h"
 
 #include "video_core/video_core.h"
 
@@ -26,6 +27,7 @@ void Init(EmuWindow* emu_window) {
     HLE::Init();
     CoreTiming::Init();
     VideoCore::Init(emu_window);
+    Kernel::Init();
 }
 
 void RunLoopFor(int cycles) {
@@ -42,6 +44,7 @@ void Shutdown() {
     HLE::Shutdown();
     CoreTiming::Shutdown();
     VideoCore::Shutdown();
+    Kernel::Shutdown();
     g_ctr_file_system.Shutdown();
 }