From adee775f443abfc17c0fe78a7487346e00b13ebc Mon Sep 17 00:00:00 2001
From: Yuri Kunde Schlesner <yuriks@yuriks.net>
Date: Sat, 20 Dec 2014 03:04:36 -0200
Subject: [PATCH] Kernel: Implement support for current thread pseudo-handle

This boots a few (mostly Nintendo 1st party) games further.
---
 src/core/hle/kernel/kernel.h   | 12 ++++++++++++
 src/core/hle/kernel/thread.cpp |  3 +--
 src/core/hle/kernel/thread.h   |  3 +++
 3 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 7e0f15c840..861a8e69aa 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -14,6 +14,10 @@ typedef s32 Result;
 
 namespace Kernel {
 
+// From kernel.h. Declarations duplicated here to avoid a circular header dependency.
+class Thread;
+Thread* GetCurrentThread();
+
 enum KernelHandle {
     CurrentThread   = 0xFFFF8000,
     CurrentProcess  = 0xFFFF8001,
@@ -81,6 +85,10 @@ public:
 
     template <class T>
     T* Get(Handle handle) {
+        if (handle == CurrentThread) {
+            return reinterpret_cast<T*>(GetCurrentThread());
+        }
+
         if (handle < HANDLE_OFFSET || handle >= HANDLE_OFFSET + MAX_COUNT || !occupied[handle - HANDLE_OFFSET]) {
             if (handle != 0) {
                 LOG_ERROR(Kernel, "Bad object handle %08x", handle);
@@ -99,6 +107,10 @@ public:
     // ONLY use this when you know the handle is valid.
     template <class T>
     T *GetFast(Handle handle) {
+        if (handle == CurrentThread) {
+            return reinterpret_cast<T*>(GetCurrentThread());
+        }
+
         const Handle realHandle = handle - HANDLE_OFFSET;
         _dbg_assert_(Kernel, realHandle >= 0 && realHandle < MAX_COUNT && occupied[realHandle]);
         return static_cast<T*>(pool[realHandle]);
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 1c04701de5..47be22653a 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -83,8 +83,7 @@ static Thread* current_thread;
 static const u32 INITIAL_THREAD_ID = 1; ///< The first available thread id at startup
 static u32 next_thread_id; ///< The next available thread id
 
-/// Gets the current thread
-inline Thread* GetCurrentThread() {
+Thread* GetCurrentThread() {
     return current_thread;
 }
 
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index be7adface8..ec3b887d43 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -78,6 +78,9 @@ Handle ArbitrateHighestPriorityThread(u32 arbiter, u32 address);
 /// Arbitrate all threads currently waiting...
 void ArbitrateAllThreads(u32 arbiter, u32 address);
 
+/// Gets the current thread
+Thread* GetCurrentThread();
+
 /// Gets the current thread handle
 Handle GetCurrentThreadHandle();