diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj
index 1c53cd4d33..f5afe70279 100644
--- a/Core/Core.vcxproj
+++ b/Core/Core.vcxproj
@@ -182,6 +182,7 @@
+
@@ -522,6 +523,7 @@
+
@@ -759,4 +761,4 @@
-
\ No newline at end of file
+
diff --git a/Core/Core.vcxproj.filters b/Core/Core.vcxproj.filters
index c3fb351a71..234ff2172a 100644
--- a/Core/Core.vcxproj.filters
+++ b/Core/Core.vcxproj.filters
@@ -677,6 +677,9 @@
Core
+
+ HLE\Libraries
+
@@ -1244,10 +1247,13 @@
Core
+
+ HLE\Libraries
+
-
\ No newline at end of file
+
diff --git a/Core/HLE/HLETables.cpp b/Core/HLE/HLETables.cpp
index a7b0ea8cc4..b3efc7faac 100644
--- a/Core/HLE/HLETables.cpp
+++ b/Core/HLE/HLETables.cpp
@@ -74,6 +74,7 @@
#include "sceAdler.h"
#include "sceSfmt19937.h"
#include "sceG729.h"
+#include "KUBridge.h"
#define N(s) s
@@ -266,12 +267,12 @@ void RegisterAllModules() {
Register_sceAudiocodec();
Register_sceHeap();
- for (int i = 0; i < numModules; i++)
- {
+ for (int i = 0; i < numModules; i++) {
RegisterModule(moduleList[i].name, moduleList[i].numFunctions, moduleList[i].funcTable);
}
- // New modules have to be added at the end, or they will break savestates.
+ // IMPORTANT: New modules have to be added at the end, or they will break savestates.
+
Register_StdioForKernel();
RegisterModule("LoadCoreForKernel", ARRAY_SIZE(LoadCoreForKernel), LoadCoreForKernel);
Register_IoFileMgrForKernel();
@@ -292,5 +293,8 @@ void RegisterAllModules() {
Register_sceG729();
Register_sceNetUpnp();
Register_sceNetIfhandle();
+ Register_KUBridge();
+
+ // add new modules here.
}
diff --git a/Core/HLE/KUBridge.cpp b/Core/HLE/KUBridge.cpp
new file mode 100644
index 0000000000..ddfe46504e
--- /dev/null
+++ b/Core/HLE/KUBridge.cpp
@@ -0,0 +1,47 @@
+// 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/.
+
+// KUBridge seems to be some utility module that comes with some custom firmware for PSP,
+// providing the ability to call some kernel-only functions from user mode.
+// A few homebrew applications use this. We only simulate a small subset of the functionality for now.
+
+#include "Core/HLE/HLE.h"
+#include "Core/HLE/FunctionWrappers.h"
+#include "Core/HLE/KUBridge.h"
+#include "Core/HLE/sceKernelModule.h"
+#include "Core/Config.h"
+
+static int kuKernelLoadModule(const char *path, uint32_t flags, uint32_t lmOptionAddr) {
+ INFO_LOG(HLE, "kuKernelLoadModule - forwarding to sceKernelLoadModule");
+ // Simply forward the call, like JPSCP does.
+ return sceKernelLoadModule(path, flags, lmOptionAddr);
+}
+
+static int kuKernelGetModel() {
+ INFO_LOG(HLE, "kuKernelGetModel()");
+ return g_Config.iPSPModel;
+}
+
+const HLEFunction KUBridge[] =
+{
+ { 0x4C25EA72, &WrapI_CUU, "kuKernelLoadModule", 'i', "cuu" },
+ { 0x24331850, &WrapI_V, "kuKernelGetModel", 'i', "" },
+};
+
+void Register_KUBridge() {
+ RegisterModule("KUBridge", ARRAY_SIZE(KUBridge), KUBridge);
+}
diff --git a/Core/HLE/KUBridge.h b/Core/HLE/KUBridge.h
new file mode 100644
index 0000000000..d9337cb45e
--- /dev/null
+++ b/Core/HLE/KUBridge.h
@@ -0,0 +1,20 @@
+// 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/.
+
+#pragma once
+
+void Register_KUBridge();
diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp
index 81a13f8f65..5298ab9dba 100644
--- a/Core/HLE/sceKernelModule.cpp
+++ b/Core/HLE/sceKernelModule.cpp
@@ -1678,8 +1678,7 @@ int sceKernelLoadExec(const char *filename, u32 paramPtr)
return 0;
}
-
-static u32 sceKernelLoadModule(const char *name, u32 flags, u32 optionAddr) {
+u32 sceKernelLoadModule(const char *name, u32 flags, u32 optionAddr) {
if (!name) {
return hleLogError(LOADER, SCE_KERNEL_ERROR_ILLEGAL_ADDR, "bad filename");
}
diff --git a/Core/HLE/sceKernelModule.h b/Core/HLE/sceKernelModule.h
index ee56d1203d..70509d9f22 100644
--- a/Core/HLE/sceKernelModule.h
+++ b/Core/HLE/sceKernelModule.h
@@ -44,4 +44,7 @@ void __KernelReturnFromModuleFunc();
u32 hleKernelStopUnloadSelfModuleWithOrWithoutStatus(u32 exitCode, u32 argSize, u32 argp, u32 statusAddr, u32 optionAddr, bool WithStatus);
void Register_ModuleMgrForUser();
-void Register_ModuleMgrForKernel();
\ No newline at end of file
+void Register_ModuleMgrForKernel();
+
+// Expose for use by KUBridge.
+u32 sceKernelLoadModule(const char *name, u32 flags, u32 optionAddr);