diff --git a/src/core/arm/interpreter/armsupp.cpp b/src/core/arm/interpreter/armsupp.cpp
index a0c866c15..101b9807a 100644
--- a/src/core/arm/interpreter/armsupp.cpp
+++ b/src/core/arm/interpreter/armsupp.cpp
@@ -19,6 +19,8 @@
#include "armemu.h"
//#include "ansidecl.h"
#include "skyeye_defs.h"
+#include "core/hle/hle.h"
+
unsigned xscale_cp15_cp_access_allowed (ARMul_State * state, unsigned reg,
unsigned cpnum);
//extern int skyeye_instr_debug;
@@ -734,39 +736,39 @@ ARMword
ARMul_MRC (ARMul_State * state, ARMword instr)
{
unsigned cpab;
- ARMword result = 0;
+ ARMword result = HLE::CallGetThreadCommandBuffer();
- //printf("SKYEYE ARMul_MRC, CPnum is %x, instr %x\n",CPNum, instr);
- if (!CP_ACCESS_ALLOWED (state, CPNum)) {
- //chy 2004-07-19 should fix in the future????!!!!
- //printf("SKYEYE ARMul_MRC,NOT ALLOWed UndefInstr CPnum is %x, instr %x\n",CPNum, instr);
- ARMul_UndefInstr (state, instr);
- return -1;
- }
+ ////printf("SKYEYE ARMul_MRC, CPnum is %x, instr %x\n",CPNum, instr);
+ //if (!CP_ACCESS_ALLOWED (state, CPNum)) {
+ // //chy 2004-07-19 should fix in the future????!!!!
+ // //printf("SKYEYE ARMul_MRC,NOT ALLOWed UndefInstr CPnum is %x, instr %x\n",CPNum, instr);
+ // ARMul_UndefInstr (state, instr);
+ // return -1;
+ //}
- cpab = (state->MRC[CPNum]) (state, ARMul_FIRST, instr, &result);
- while (cpab == ARMul_BUSY) {
- ARMul_Icycles (state, 1, 0);
- if (IntPending (state)) {
- cpab = (state->MRC[CPNum]) (state, ARMul_INTERRUPT,
- instr, 0);
- return (0);
- }
- else
- cpab = (state->MRC[CPNum]) (state, ARMul_BUSY, instr,
- &result);
- }
- if (cpab == ARMul_CANT) {
- printf ("SKYEYE ARMul_MRC,CANT UndefInstr CPnum is %x, instr %x\n", CPNum, instr);
- ARMul_Abort (state, ARMul_UndefinedInstrV);
- /* Parent will destroy the flags otherwise. */
- result = ECC;
- }
- else {
- BUSUSEDINCPCN;
- ARMul_Ccycles (state, 1, 0);
- ARMul_Icycles (state, 1, 0);
- }
+ //cpab = (state->MRC[CPNum]) (state, ARMul_FIRST, instr, &result);
+ //while (cpab == ARMul_BUSY) {
+ // ARMul_Icycles (state, 1, 0);
+ // if (IntPending (state)) {
+ // cpab = (state->MRC[CPNum]) (state, ARMul_INTERRUPT,
+ // instr, 0);
+ // return (0);
+ // }
+ // else
+ // cpab = (state->MRC[CPNum]) (state, ARMul_BUSY, instr,
+ // &result);
+ //}
+ //if (cpab == ARMul_CANT) {
+ // printf ("SKYEYE ARMul_MRC,CANT UndefInstr CPnum is %x, instr %x\n", CPNum, instr);
+ // ARMul_Abort (state, ARMul_UndefinedInstrV);
+ // /* Parent will destroy the flags otherwise. */
+ // result = ECC;
+ //}
+ //else {
+ // BUSUSEDINCPCN;
+ // ARMul_Ccycles (state, 1, 0);
+ // ARMul_Icycles (state, 1, 0);
+ //}
return result;
}
diff --git a/src/core/core.vcxproj b/src/core/core.vcxproj
index 10ecca596..b10ae8684 100644
--- a/src/core/core.vcxproj
+++ b/src/core/core.vcxproj
@@ -153,6 +153,7 @@
+
diff --git a/src/core/core.vcxproj.filters b/src/core/core.vcxproj.filters
index d450224a4..4844e78b8 100644
--- a/src/core/core.vcxproj.filters
+++ b/src/core/core.vcxproj.filters
@@ -87,6 +87,9 @@
hle
+
+ hle\service
+
diff --git a/src/core/hle/hle.cpp b/src/core/hle/hle.cpp
index 32aff0eb5..3d2c53954 100644
--- a/src/core/hle/hle.cpp
+++ b/src/core/hle/hle.cpp
@@ -4,8 +4,10 @@
#include
+#include "core/mem_map.h"
#include "core/hle/hle.h"
#include "core/hle/syscall.h"
+#include "core/hle/service/service.h"
////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -35,6 +37,14 @@ void CallSyscall(u32 opcode) {
}
}
+/// Returns the coprocessor (in this case, syscore) command buffer pointer
+Addr CallGetThreadCommandBuffer() {
+ // Called on insruction: mrc p15, 0, r0, c13, c0, 3
+ // Returns an address in OSHLE memory for the CPU to read/write to
+ RETURN(OS_THREAD_COMMAND_BUFFER_ADDR);
+ return OS_THREAD_COMMAND_BUFFER_ADDR;
+}
+
void RegisterModule(std::string name, int num_functions, const FunctionDef* func_table) {
ModuleDef module = {name, num_functions, func_table};
g_module_db.push_back(module);
@@ -45,7 +55,10 @@ void RegisterAllModules() {
}
void Init() {
+ Service::Init();
+
RegisterAllModules();
+
NOTICE_LOG(HLE, "initialized OK");
}
diff --git a/src/core/hle/hle.h b/src/core/hle/hle.h
index 9466be540..2bd1f99a2 100644
--- a/src/core/hle/hle.h
+++ b/src/core/hle/hle.h
@@ -16,6 +16,11 @@
namespace HLE {
+enum {
+ OS_THREAD_COMMAND_BUFFER_ADDR = 0xA0004000,
+};
+
+typedef u32 Addr;
typedef void (*Func)();
struct FunctionDef {
@@ -34,6 +39,8 @@ void RegisterModule(std::string name, int num_functions, const FunctionDef *func
void CallSyscall(u32 opcode);
+Addr CallGetThreadCommandBuffer();
+
void Init();
void Shutdown();
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
new file mode 100644
index 000000000..4bc96cc18
--- /dev/null
+++ b/src/core/hle/service/service.cpp
@@ -0,0 +1,115 @@
+// Copyright 2014 Citra Emulator Project
+// Licensed under GPLv2
+// Refer to the license.txt file included.
+
+#include "common/common.h"
+#include "common/log.h"
+
+#include "core/hle/service/service.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Namespace Service
+
+namespace Service {
+
+Manager* g_manager = NULL; ///< Service manager
+
+Manager::Manager() {
+}
+
+Manager::~Manager() {
+ for(Interface* service : m_services) {
+ DeleteService(service->GetPortName());
+ }
+}
+
+/// Add a service to the manager (does not create it though)
+void Manager::AddService(Interface* service) {
+ int index = m_services.size();
+ u32 new_uid = GetUIDFromIndex(index);
+
+ m_services.push_back(service);
+
+ m_port_map[service->GetPortName()] = new_uid;
+ service->m_uid = new_uid;
+}
+
+/// Removes a service from the manager, also frees memory
+void Manager::DeleteService(std::string port_name) {
+ auto service = FetchFromPortName(port_name);
+
+ m_services.erase(m_services.begin() + GetIndexFromUID(service->m_uid));
+ m_port_map.erase(port_name);
+
+ delete service;
+}
+
+/// Get a Service Interface from its UID
+Interface* Manager::FetchFromUID(u32 uid) {
+ int index = GetIndexFromUID(uid);
+ if (index < (int)m_services.size()) {
+ return m_services[index];
+ }
+ return NULL;
+}
+
+/// Get a Service Interface from its port
+Interface* Manager::FetchFromPortName(std::string port_name) {
+ auto itr = m_port_map.find(port_name);
+ if (itr == m_port_map.end()) {
+ return NULL;
+ }
+ return FetchFromUID(itr->second);
+}
+
+class Interface_SRV : public Interface {
+public:
+
+ Interface_SRV() {
+ }
+
+ ~Interface_SRV() {
+ }
+
+ /**
+ * Gets the string name used by CTROS for a service
+ * @return String name of service
+ */
+ std::string GetName() {
+ return "ServiceManager";
+ }
+
+ /**
+ * Gets the string name used by CTROS for a service
+ * @return Port name of service
+ */
+ std::string GetPortName() {
+ return "srv:";
+ }
+
+ /**
+ * Called when svcSendSyncRequest is called, loads command buffer and executes comand
+ * @return Return result of svcSendSyncRequest passed back to user app
+ */
+ Syscall::Result Sync() {
+ ERROR_LOG(HLE, "Unimplemented function ServiceManager::Sync");
+ return -1;
+ }
+
+};
+
+/// Initialize ServiceManager
+void Init() {
+ g_manager = new Manager;
+ g_manager->AddService(new Interface_SRV);
+ NOTICE_LOG(HLE, "ServiceManager initialized OK");
+}
+
+/// Shutdown ServiceManager
+void Shutdown() {
+ delete g_manager;
+ NOTICE_LOG(HLE, "ServiceManager shutdown OK");
+}
+
+
+}
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h
index f15099982..3fd855dee 100644
--- a/src/core/hle/service/service.h
+++ b/src/core/hle/service/service.h
@@ -4,6 +4,8 @@
#pragma once
+#include
+#include