mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30:04 +00:00 
			
		
		
		
	Merge branch 'hle-interface'
This commit is contained in:
		
						commit
						958bca606e
					
				
					 40 changed files with 2379 additions and 227 deletions
				
			
		|  | @ -55,8 +55,8 @@ enum LOG_TYPE { | ||||||
|     WII_IPC_HID, |     WII_IPC_HID, | ||||||
|     WII_IPC_HLE, |     WII_IPC_HLE, | ||||||
|     WII_IPC_NET, |     WII_IPC_NET, | ||||||
|     WII_IPC_WC24, |     NDMA, | ||||||
|     WII_IPC_SSL, |     HLE, | ||||||
|     RENDER, |     RENDER, | ||||||
|     LCD, |     LCD, | ||||||
|     HW, |     HW, | ||||||
|  |  | ||||||
|  | @ -67,9 +67,9 @@ LogManager::LogManager() | ||||||
|     m_Log[LogTypes::RENDER]             = new LogContainer("RENDER",            "RENDER"); |     m_Log[LogTypes::RENDER]             = new LogContainer("RENDER",            "RENDER"); | ||||||
|     m_Log[LogTypes::LCD]                = new LogContainer("LCD",               "LCD"); |     m_Log[LogTypes::LCD]                = new LogContainer("LCD",               "LCD"); | ||||||
|     m_Log[LogTypes::WII_IPC_NET]        = new LogContainer("WII_IPC_NET",       "WII IPC NET"); |     m_Log[LogTypes::WII_IPC_NET]        = new LogContainer("WII_IPC_NET",       "WII IPC NET"); | ||||||
|     m_Log[LogTypes::WII_IPC_WC24]       = new LogContainer("WII_IPC_WC24",      "WII IPC WC24"); |     m_Log[LogTypes::NDMA]               = new LogContainer("NDMA",              "NDMA"); | ||||||
|     m_Log[LogTypes::WII_IPC_SSL]        = new LogContainer("WII_IPC_SSL",       "WII IPC SSL"); |     m_Log[LogTypes::HLE]                = new LogContainer("HLE",               "High Level Emulation"); | ||||||
|     m_Log[LogTypes::HW]                 = new LogContainer("HARDWARE",          "HARDWARE"); |     m_Log[LogTypes::HW]                 = new LogContainer("HW",                "Hardware"); | ||||||
|     m_Log[LogTypes::ACTIONREPLAY]       = new LogContainer("ActionReplay",      "ActionReplay"); |     m_Log[LogTypes::ACTIONREPLAY]       = new LogContainer("ActionReplay",      "ActionReplay"); | ||||||
|     m_Log[LogTypes::MEMCARD_MANAGER]    = new LogContainer("MemCard Manager",   "MemCard Manager"); |     m_Log[LogTypes::MEMCARD_MANAGER]    = new LogContainer("MemCard Manager",   "MemCard Manager"); | ||||||
|     m_Log[LogTypes::NETPLAY]            = new LogContainer("NETPLAY",           "Netplay"); |     m_Log[LogTypes::NETPLAY]            = new LogContainer("NETPLAY",           "Netplay"); | ||||||
|  |  | ||||||
|  | @ -17,6 +17,22 @@ | ||||||
|     #include <errno.h> |     #include <errno.h> | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  | /// Make a string lowercase
 | ||||||
|  | void LowerStr(char* str) { | ||||||
|  |     for (int i = 0; str[i]; i++) { | ||||||
|  |         str[i] = tolower(str[ i ]); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /// Make a string uppercase
 | ||||||
|  | void UpperStr(char* str) { | ||||||
|  |     for (int i=0; i < strlen(str); i++) { | ||||||
|  |         if(str[i] >= 'a' && str[i] <= 'z') { | ||||||
|  |             str[i] &= 0xDF; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // faster than sscanf
 | // faster than sscanf
 | ||||||
| bool AsciiToHex(const char* _szValue, u32& result) | bool AsciiToHex(const char* _szValue, u32& result) | ||||||
| { | { | ||||||
|  |  | ||||||
|  | @ -14,6 +14,12 @@ | ||||||
| 
 | 
 | ||||||
| #include "common/common.h" | #include "common/common.h" | ||||||
| 
 | 
 | ||||||
|  | /// Make a string lowercase
 | ||||||
|  | void LowerStr(char* str); | ||||||
|  | 
 | ||||||
|  | /// Make a string uppercase
 | ||||||
|  | void UpperStr(char* str); | ||||||
|  | 
 | ||||||
| std::string StringFromFormat(const char* format, ...); | std::string StringFromFormat(const char* format, ...); | ||||||
| // Cheap!
 | // Cheap!
 | ||||||
| bool CharArrayFromFormatV(char* out, int outsize, const char* format, va_list args); | bool CharArrayFromFormatV(char* out, int outsize, const char* format, va_list args); | ||||||
|  |  | ||||||
|  | @ -42,6 +42,13 @@ public: | ||||||
|      */ |      */ | ||||||
|     virtual u32 GetReg(int index) const = 0; |     virtual u32 GetReg(int index) const = 0; | ||||||
| 
 | 
 | ||||||
|  |     /**
 | ||||||
|  |      * Set an ARM register | ||||||
|  |      * @param index Register index (0-15) | ||||||
|  |      * @param value Value to set register to | ||||||
|  |      */ | ||||||
|  |     virtual void SetReg(int index, u32 value) = 0; | ||||||
|  | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * Get the current CPSR register |      * Get the current CPSR register | ||||||
|      * @return Returns the value of the CPSR register |      * @return Returns the value of the CPSR register | ||||||
|  | @ -59,11 +66,13 @@ public: | ||||||
|         return m_num_instructions; |         return m_num_instructions; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| private: | protected: | ||||||
|      |      | ||||||
|     /// Execture next instruction
 |     /// Execture next instruction
 | ||||||
|     virtual void ExecuteInstruction() = 0; |     virtual void ExecuteInstruction() = 0; | ||||||
| 
 | 
 | ||||||
|  | private: | ||||||
|  | 
 | ||||||
|     u64 m_num_instructions;                     ///< Number of instructions executed
 |     u64 m_num_instructions;                     ///< Number of instructions executed
 | ||||||
| 
 | 
 | ||||||
|     DISALLOW_COPY_AND_ASSIGN(ARM_Interface); |     DISALLOW_COPY_AND_ASSIGN(ARM_Interface); | ||||||
|  |  | ||||||
|  | @ -31,30 +31,61 @@ ARM_Interpreter::ARM_Interpreter()  { | ||||||
|     m_state->Reg[13] = 0x10000000; // Set stack pointer to the top of the stack
 |     m_state->Reg[13] = 0x10000000; // Set stack pointer to the top of the stack
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ARM_Interpreter::SetPC(u32 pc) { |  | ||||||
|     m_state->pc = m_state->Reg[15] = pc; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| u32 ARM_Interpreter::GetPC() const { |  | ||||||
|     return m_state->pc; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| u32 ARM_Interpreter::GetReg(int index) const { |  | ||||||
|     return m_state->Reg[index]; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| u32 ARM_Interpreter::GetCPSR() const { |  | ||||||
|     return m_state->Cpsr; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| u64 ARM_Interpreter::GetTicks() const { |  | ||||||
|     return ARMul_Time(m_state); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| ARM_Interpreter::~ARM_Interpreter() { | ARM_Interpreter::~ARM_Interpreter() { | ||||||
|     delete m_state; |     delete m_state; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /**
 | ||||||
|  |  * Set the Program Counter to an address | ||||||
|  |  * @param addr Address to set PC to | ||||||
|  |  */ | ||||||
|  | void ARM_Interpreter::SetPC(u32 pc) { | ||||||
|  |     m_state->pc = m_state->Reg[15] = pc; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Get the current Program Counter | ||||||
|  |  * @return Returns current PC | ||||||
|  |  */ | ||||||
|  | u32 ARM_Interpreter::GetPC() const { | ||||||
|  |     return m_state->pc; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Get an ARM register | ||||||
|  |  * @param index Register index (0-15) | ||||||
|  |  * @return Returns the value in the register | ||||||
|  |  */ | ||||||
|  | u32 ARM_Interpreter::GetReg(int index) const { | ||||||
|  |     return m_state->Reg[index]; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Set an ARM register | ||||||
|  |  * @param index Register index (0-15) | ||||||
|  |  * @param value Value to set register to | ||||||
|  |  */ | ||||||
|  | void ARM_Interpreter::SetReg(int index, u32 value) { | ||||||
|  |     m_state->Reg[index] = value; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Get the current CPSR register | ||||||
|  |  * @return Returns the value of the CPSR register | ||||||
|  |  */ | ||||||
|  | u32 ARM_Interpreter::GetCPSR() const { | ||||||
|  |     return m_state->Cpsr; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Returns the number of clock ticks since the last reset | ||||||
|  |  * @return Returns number of clock ticks | ||||||
|  |  */ | ||||||
|  | u64 ARM_Interpreter::GetTicks() const { | ||||||
|  |     return ARMul_Time(m_state); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /// Execture next instruction
 | ||||||
| void ARM_Interpreter::ExecuteInstruction() { | void ARM_Interpreter::ExecuteInstruction() { | ||||||
|     m_state->step++; |     m_state->step++; | ||||||
|     m_state->cycle++; |     m_state->cycle++; | ||||||
|  |  | ||||||
|  | @ -12,22 +12,55 @@ | ||||||
| 
 | 
 | ||||||
| class ARM_Interpreter : virtual public ARM_Interface { | class ARM_Interpreter : virtual public ARM_Interface { | ||||||
| public: | public: | ||||||
|  | 
 | ||||||
|     ARM_Interpreter(); |     ARM_Interpreter(); | ||||||
|     ~ARM_Interpreter(); |     ~ARM_Interpreter(); | ||||||
| 
 | 
 | ||||||
|     void ExecuteInstruction(); |     /**
 | ||||||
| 
 |      * Set the Program Counter to an address | ||||||
|  |      * @param addr Address to set PC to | ||||||
|  |      */ | ||||||
|     void SetPC(u32 pc); |     void SetPC(u32 pc); | ||||||
| 
 | 
 | ||||||
|  |     /*
 | ||||||
|  |      * Get the current Program Counter | ||||||
|  |      * @return Returns current PC | ||||||
|  |      */ | ||||||
|     u32 GetPC() const; |     u32 GetPC() const; | ||||||
| 
 | 
 | ||||||
|  |     /**
 | ||||||
|  |      * Get an ARM register | ||||||
|  |      * @param index Register index (0-15) | ||||||
|  |      * @return Returns the value in the register | ||||||
|  |      */ | ||||||
|     u32 GetReg(int index) const; |     u32 GetReg(int index) const; | ||||||
| 
 | 
 | ||||||
|  |     /**
 | ||||||
|  |      * Set an ARM register | ||||||
|  |      * @param index Register index (0-15) | ||||||
|  |      * @param value Value to set register to | ||||||
|  |      */ | ||||||
|  |     void SetReg(int index, u32 value); | ||||||
|  | 
 | ||||||
|  |     /**
 | ||||||
|  |      * Get the current CPSR register | ||||||
|  |      * @return Returns the value of the CPSR register | ||||||
|  |      */ | ||||||
|     u32 GetCPSR() const; |     u32 GetCPSR() const; | ||||||
| 
 | 
 | ||||||
|  |     /**
 | ||||||
|  |      * Returns the number of clock ticks since the last reset | ||||||
|  |      * @return Returns number of clock ticks | ||||||
|  |      */ | ||||||
|     u64 GetTicks() const; |     u64 GetTicks() const; | ||||||
| 
 | 
 | ||||||
|  | protected: | ||||||
|  | 
 | ||||||
|  |     /// Execture next instruction
 | ||||||
|  |     void ExecuteInstruction(); | ||||||
|  | 
 | ||||||
| private: | private: | ||||||
|  | 
 | ||||||
|     ARMul_State* m_state; |     ARMul_State* m_state; | ||||||
| 
 | 
 | ||||||
|     DISALLOW_COPY_AND_ASSIGN(ARM_Interpreter); |     DISALLOW_COPY_AND_ASSIGN(ARM_Interpreter); | ||||||
|  |  | ||||||
|  | @ -16,6 +16,8 @@ | ||||||
|     along with this program; if not, write to the Free Software |     along with this program; if not, write to the Free Software | ||||||
|     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */ |     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */ | ||||||
| 
 | 
 | ||||||
|  | #include "core/hle/hle.h" | ||||||
|  | 
 | ||||||
| #include "arm_regformat.h" | #include "arm_regformat.h" | ||||||
| #include "armdefs.h" | #include "armdefs.h" | ||||||
| #include "armemu.h" | #include "armemu.h" | ||||||
|  | @ -4558,6 +4560,7 @@ ARMul_Emulate26 (ARMul_State * state) | ||||||
|                 //    ARMul_OSHandleSWI (state, BITS (0, 23));
 |                 //    ARMul_OSHandleSWI (state, BITS (0, 23));
 | ||||||
|                 //    break;
 |                 //    break;
 | ||||||
|                 //}
 |                 //}
 | ||||||
|  |                 HLE::CallSyscall(instr); | ||||||
|                 ARMul_Abort (state, ARMul_SWIV); |                 ARMul_Abort (state, ARMul_SWIV); | ||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  | @ -229,6 +229,17 @@ extern ARMword isize; | ||||||
|     }									\ |     }									\ | ||||||
|   while (0) |   while (0) | ||||||
| 
 | 
 | ||||||
|  | #define SETABORT_SKIPBRANCH(i, m, d)						\ | ||||||
|  |   do									\ | ||||||
|  |     { 									\ | ||||||
|  |       int SETABORT_mode = (m);						\ | ||||||
|  | 									\ | ||||||
|  |       ARMul_SetSPSR (state, SETABORT_mode, ARMul_GetCPSR (state));	\ | ||||||
|  |       ARMul_SetCPSR (state, ((ARMul_GetCPSR (state) & ~(EMODE | TBIT))	\ | ||||||
|  | 			     | (i) | SETABORT_mode));			\ | ||||||
|  |     }									\ | ||||||
|  |   while (0) | ||||||
|  | 
 | ||||||
| //#ifndef MODE32
 | //#ifndef MODE32
 | ||||||
| #define VECTORS 0x20 | #define VECTORS 0x20 | ||||||
| #define LEGALADDR 0x03ffffff | #define LEGALADDR 0x03ffffff | ||||||
|  |  | ||||||
|  | @ -530,9 +530,13 @@ ARMul_Abort (ARMul_State * state, ARMword vector) | ||||||
| 			  isize); | 			  isize); | ||||||
| 		break; | 		break; | ||||||
| 	case ARMul_SWIV:	/* Software Interrupt */ | 	case ARMul_SWIV:	/* Software Interrupt */ | ||||||
| 		SETABORT (IBIT, state->prog32Sig ? SVC32MODE : SVC26MODE, | 		// Modified SETABORT that doesn't branch to a SVC vector as we are implementing this in HLE
 | ||||||
|  | 		// Instead of doing normal routine, backup R15 by one instruction (this is what PC will get 
 | ||||||
|  | 		// set to, making it the next instruction after the SVC call), and skip setting the LR.
 | ||||||
|  | 		SETABORT_SKIPBRANCH (IBIT, state->prog32Sig ? SVC32MODE : SVC26MODE, | ||||||
| 			  isize); | 			  isize); | ||||||
| 		break; | 		state->Reg[15] -= 4; | ||||||
|  | 		return; | ||||||
| 	case ARMul_PrefetchAbortV:	/* Prefetch Abort */ | 	case ARMul_PrefetchAbortV:	/* Prefetch Abort */ | ||||||
| 		state->AbortAddr = 1; | 		state->AbortAddr = 1; | ||||||
| 		SETABORT (IBIT, state->prog32Sig ? ABORT32MODE : SVC26MODE, | 		SETABORT (IBIT, state->prog32Sig ? ABORT32MODE : SVC26MODE, | ||||||
|  |  | ||||||
|  | @ -19,6 +19,8 @@ | ||||||
| #include "armemu.h" | #include "armemu.h" | ||||||
| //#include "ansidecl.h"
 | //#include "ansidecl.h"
 | ||||||
| #include "skyeye_defs.h" | #include "skyeye_defs.h" | ||||||
|  | #include "core/hle/hle.h" | ||||||
|  | 
 | ||||||
| unsigned xscale_cp15_cp_access_allowed (ARMul_State * state, unsigned reg, | unsigned xscale_cp15_cp_access_allowed (ARMul_State * state, unsigned reg, | ||||||
|                                         unsigned cpnum); |                                         unsigned cpnum); | ||||||
| //extern int skyeye_instr_debug;
 | //extern int skyeye_instr_debug;
 | ||||||
|  | @ -734,39 +736,39 @@ ARMword | ||||||
| ARMul_MRC (ARMul_State * state, ARMword instr) | ARMul_MRC (ARMul_State * state, ARMword instr) | ||||||
| { | { | ||||||
| 	unsigned cpab; | 	unsigned cpab; | ||||||
| 	ARMword result = 0; | 	ARMword result = HLE::CallGetThreadCommandBuffer(); | ||||||
| 
 | 
 | ||||||
| 	//printf("SKYEYE ARMul_MRC, CPnum is %x, instr %x\n",CPNum, instr);
 | 	////printf("SKYEYE ARMul_MRC, CPnum is %x, instr %x\n",CPNum, instr);
 | ||||||
| 	if (!CP_ACCESS_ALLOWED (state, CPNum)) { | 	//if (!CP_ACCESS_ALLOWED (state, CPNum)) {
 | ||||||
| 		//chy 2004-07-19 should fix in the future????!!!!
 | 	//	//chy 2004-07-19 should fix in the future????!!!!
 | ||||||
| 		//printf("SKYEYE ARMul_MRC,NOT ALLOWed UndefInstr  CPnum is %x, instr %x\n",CPNum, instr);
 | 	//	//printf("SKYEYE ARMul_MRC,NOT ALLOWed UndefInstr  CPnum is %x, instr %x\n",CPNum, instr);
 | ||||||
| 		ARMul_UndefInstr (state, instr); | 	//	ARMul_UndefInstr (state, instr);
 | ||||||
| 		return -1; | 	//	return -1;
 | ||||||
| 	} | 	//}
 | ||||||
| 
 | 
 | ||||||
| 	cpab = (state->MRC[CPNum]) (state, ARMul_FIRST, instr, &result); | 	//cpab = (state->MRC[CPNum]) (state, ARMul_FIRST, instr, &result);
 | ||||||
| 	while (cpab == ARMul_BUSY) { | 	//while (cpab == ARMul_BUSY) {
 | ||||||
| 		ARMul_Icycles (state, 1, 0); | 	//	ARMul_Icycles (state, 1, 0);
 | ||||||
| 		if (IntPending (state)) { | 	//	if (IntPending (state)) {
 | ||||||
| 			cpab = (state->MRC[CPNum]) (state, ARMul_INTERRUPT, | 	//		cpab = (state->MRC[CPNum]) (state, ARMul_INTERRUPT,
 | ||||||
| 						    instr, 0); | 	//					    instr, 0);
 | ||||||
| 			return (0); | 	//		return (0);
 | ||||||
| 		} | 	//	}
 | ||||||
| 		else | 	//	else
 | ||||||
| 			cpab = (state->MRC[CPNum]) (state, ARMul_BUSY, instr, | 	//		cpab = (state->MRC[CPNum]) (state, ARMul_BUSY, instr,
 | ||||||
| 						    &result); | 	//					    &result);
 | ||||||
| 	} | 	//}
 | ||||||
| 	if (cpab == ARMul_CANT) { | 	//if (cpab == ARMul_CANT) {
 | ||||||
| 		printf ("SKYEYE ARMul_MRC,CANT UndefInstr  CPnum is %x, instr %x\n", CPNum, instr); | 	//	printf ("SKYEYE ARMul_MRC,CANT UndefInstr  CPnum is %x, instr %x\n", CPNum, instr);
 | ||||||
| 		ARMul_Abort (state, ARMul_UndefinedInstrV); | 	//	ARMul_Abort (state, ARMul_UndefinedInstrV);
 | ||||||
| 		/* Parent will destroy the flags otherwise.  */ | 	//	/* Parent will destroy the flags otherwise.  */
 | ||||||
| 		result = ECC; | 	//	result = ECC;
 | ||||||
| 	} | 	//}
 | ||||||
| 	else { | 	//else {
 | ||||||
| 		BUSUSEDINCPCN; | 	//	BUSUSEDINCPCN;
 | ||||||
| 		ARMul_Ccycles (state, 1, 0); | 	//	ARMul_Ccycles (state, 1, 0);
 | ||||||
| 		ARMul_Icycles (state, 1, 0); | 	//	ARMul_Icycles (state, 1, 0);
 | ||||||
| 	} | 	//}
 | ||||||
| 
 | 
 | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -40,7 +40,7 @@ void Stop() { | ||||||
| 
 | 
 | ||||||
| /// Initialize the core
 | /// Initialize the core
 | ||||||
| int Init() { | int Init() { | ||||||
|     NOTICE_LOG(MASTER_LOG, "Core initialized OK"); |     NOTICE_LOG(MASTER_LOG, "initialized OK"); | ||||||
| 
 | 
 | ||||||
|     g_disasm = new ARM_Disasm(); |     g_disasm = new ARM_Disasm(); | ||||||
|     g_app_core = new ARM_Interpreter(); |     g_app_core = new ARM_Interpreter(); | ||||||
|  | @ -54,7 +54,7 @@ void Shutdown() { | ||||||
|     delete g_app_core; |     delete g_app_core; | ||||||
|     delete g_sys_core; |     delete g_sys_core; | ||||||
| 
 | 
 | ||||||
|     NOTICE_LOG(MASTER_LOG, "Core shutdown OK"); |     NOTICE_LOG(MASTER_LOG, "shutdown OK"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| } // namespace
 | } // namespace
 | ||||||
|  |  | ||||||
|  | @ -152,8 +152,16 @@ | ||||||
|     <ClCompile Include="elf\elf_reader.cpp" /> |     <ClCompile Include="elf\elf_reader.cpp" /> | ||||||
|     <ClCompile Include="file_sys\directory_file_system.cpp" /> |     <ClCompile Include="file_sys\directory_file_system.cpp" /> | ||||||
|     <ClCompile Include="file_sys\meta_file_system.cpp" /> |     <ClCompile Include="file_sys\meta_file_system.cpp" /> | ||||||
|  |     <ClCompile Include="hle\hle.cpp" /> | ||||||
|  |     <ClCompile Include="hle\service\apt.cpp" /> | ||||||
|  |     <ClCompile Include="hle\service\gsp.cpp" /> | ||||||
|  |     <ClCompile Include="hle\service\hid.cpp" /> | ||||||
|  |     <ClCompile Include="hle\service\service.cpp" /> | ||||||
|  |     <ClCompile Include="hle\service\srv.cpp" /> | ||||||
|  |     <ClCompile Include="hle\syscall.cpp" /> | ||||||
|     <ClCompile Include="hw\hw.cpp" /> |     <ClCompile Include="hw\hw.cpp" /> | ||||||
|     <ClCompile Include="hw\hw_lcd.cpp" /> |     <ClCompile Include="hw\lcd.cpp" /> | ||||||
|  |     <ClCompile Include="hw\ndma.cpp" /> | ||||||
|     <ClCompile Include="loader.cpp" /> |     <ClCompile Include="loader.cpp" /> | ||||||
|     <ClCompile Include="mem_map.cpp" /> |     <ClCompile Include="mem_map.cpp" /> | ||||||
|     <ClCompile Include="mem_map_funcs.cpp" /> |     <ClCompile Include="mem_map_funcs.cpp" /> | ||||||
|  | @ -182,8 +190,17 @@ | ||||||
|     <ClInclude Include="file_sys\directory_file_system.h" /> |     <ClInclude Include="file_sys\directory_file_system.h" /> | ||||||
|     <ClInclude Include="file_sys\file_sys.h" /> |     <ClInclude Include="file_sys\file_sys.h" /> | ||||||
|     <ClInclude Include="file_sys\meta_file_system.h" /> |     <ClInclude Include="file_sys\meta_file_system.h" /> | ||||||
|  |     <ClInclude Include="hle\function_wrappers.h" /> | ||||||
|  |     <ClInclude Include="hle\hle.h" /> | ||||||
|  |     <ClInclude Include="hle\service\apt.h" /> | ||||||
|  |     <ClInclude Include="hle\service\gsp.h" /> | ||||||
|  |     <ClInclude Include="hle\service\hid.h" /> | ||||||
|  |     <ClInclude Include="hle\service\service.h" /> | ||||||
|  |     <ClInclude Include="hle\service\srv.h" /> | ||||||
|  |     <ClInclude Include="hle\syscall.h" /> | ||||||
|     <ClInclude Include="hw\hw.h" /> |     <ClInclude Include="hw\hw.h" /> | ||||||
|     <ClInclude Include="hw\hw_lcd.h" /> |     <ClInclude Include="hw\lcd.h" /> | ||||||
|  |     <ClInclude Include="hw\ndma.h" /> | ||||||
|     <ClInclude Include="loader.h" /> |     <ClInclude Include="loader.h" /> | ||||||
|     <ClInclude Include="mem_map.h" /> |     <ClInclude Include="mem_map.h" /> | ||||||
|     <ClInclude Include="system.h" /> |     <ClInclude Include="system.h" /> | ||||||
|  |  | ||||||
|  | @ -22,6 +22,12 @@ | ||||||
|     <Filter Include="elf"> |     <Filter Include="elf"> | ||||||
|       <UniqueIdentifier>{7ae34319-6d72-4d12-bc62-9b438ba9241f}</UniqueIdentifier> |       <UniqueIdentifier>{7ae34319-6d72-4d12-bc62-9b438ba9241f}</UniqueIdentifier> | ||||||
|     </Filter> |     </Filter> | ||||||
|  |     <Filter Include="hle"> | ||||||
|  |       <UniqueIdentifier>{8b62769e-3e2a-4a57-a7bc-b3b2933c2bc7}</UniqueIdentifier> | ||||||
|  |     </Filter> | ||||||
|  |     <Filter Include="hle\service"> | ||||||
|  |       <UniqueIdentifier>{812c5189-ca49-4704-b842-3ffad09092d3}</UniqueIdentifier> | ||||||
|  |     </Filter> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <ClCompile Include="arm\disassembler\arm_disasm.cpp"> |     <ClCompile Include="arm\disassembler\arm_disasm.cpp"> | ||||||
|  | @ -63,9 +69,6 @@ | ||||||
|     <ClCompile Include="hw\hw.cpp"> |     <ClCompile Include="hw\hw.cpp"> | ||||||
|       <Filter>hw</Filter> |       <Filter>hw</Filter> | ||||||
|     </ClCompile> |     </ClCompile> | ||||||
|     <ClCompile Include="hw\hw_lcd.cpp"> |  | ||||||
|       <Filter>hw</Filter> |  | ||||||
|     </ClCompile> |  | ||||||
|     <ClCompile Include="elf\elf_reader.cpp"> |     <ClCompile Include="elf\elf_reader.cpp"> | ||||||
|       <Filter>elf</Filter> |       <Filter>elf</Filter> | ||||||
|     </ClCompile> |     </ClCompile> | ||||||
|  | @ -75,6 +78,33 @@ | ||||||
|     <ClCompile Include="mem_map_funcs.cpp" /> |     <ClCompile Include="mem_map_funcs.cpp" /> | ||||||
|     <ClCompile Include="system.cpp" /> |     <ClCompile Include="system.cpp" /> | ||||||
|     <ClCompile Include="core_timing.cpp" /> |     <ClCompile Include="core_timing.cpp" /> | ||||||
|  |     <ClCompile Include="hle\hle.cpp"> | ||||||
|  |       <Filter>hle</Filter> | ||||||
|  |     </ClCompile> | ||||||
|  |     <ClCompile Include="hle\syscall.cpp"> | ||||||
|  |       <Filter>hle</Filter> | ||||||
|  |     </ClCompile> | ||||||
|  |     <ClCompile Include="hle\service\service.cpp"> | ||||||
|  |       <Filter>hle\service</Filter> | ||||||
|  |     </ClCompile> | ||||||
|  |     <ClCompile Include="hle\service\apt.cpp"> | ||||||
|  |       <Filter>hle\service</Filter> | ||||||
|  |     </ClCompile> | ||||||
|  |     <ClCompile Include="hle\service\srv.cpp"> | ||||||
|  |       <Filter>hle\service</Filter> | ||||||
|  |     </ClCompile> | ||||||
|  |     <ClCompile Include="hle\service\gsp.cpp"> | ||||||
|  |       <Filter>hle\service</Filter> | ||||||
|  |     </ClCompile> | ||||||
|  |     <ClCompile Include="hle\service\hid.cpp"> | ||||||
|  |       <Filter>hle\service</Filter> | ||||||
|  |     </ClCompile> | ||||||
|  |     <ClCompile Include="hw\ndma.cpp"> | ||||||
|  |       <Filter>hw</Filter> | ||||||
|  |     </ClCompile> | ||||||
|  |     <ClCompile Include="hw\lcd.cpp"> | ||||||
|  |       <Filter>hw</Filter> | ||||||
|  |     </ClCompile> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <ClInclude Include="arm\disassembler\arm_disasm.h"> |     <ClInclude Include="arm\disassembler\arm_disasm.h"> | ||||||
|  | @ -131,9 +161,6 @@ | ||||||
|     <ClInclude Include="hw\hw.h"> |     <ClInclude Include="hw\hw.h"> | ||||||
|       <Filter>hw</Filter> |       <Filter>hw</Filter> | ||||||
|     </ClInclude> |     </ClInclude> | ||||||
|     <ClInclude Include="hw\hw_lcd.h"> |  | ||||||
|       <Filter>hw</Filter> |  | ||||||
|     </ClInclude> |  | ||||||
|     <ClInclude Include="elf\elf_reader.h"> |     <ClInclude Include="elf\elf_reader.h"> | ||||||
|       <Filter>elf</Filter> |       <Filter>elf</Filter> | ||||||
|     </ClInclude> |     </ClInclude> | ||||||
|  | @ -148,6 +175,36 @@ | ||||||
|     <ClInclude Include="loader.h" /> |     <ClInclude Include="loader.h" /> | ||||||
|     <ClInclude Include="mem_map.h" /> |     <ClInclude Include="mem_map.h" /> | ||||||
|     <ClInclude Include="system.h" /> |     <ClInclude Include="system.h" /> | ||||||
|  |     <ClInclude Include="hle\hle.h"> | ||||||
|  |       <Filter>hle</Filter> | ||||||
|  |     </ClInclude> | ||||||
|  |     <ClInclude Include="hle\function_wrappers.h"> | ||||||
|  |       <Filter>hle</Filter> | ||||||
|  |     </ClInclude> | ||||||
|  |     <ClInclude Include="hle\service\service.h"> | ||||||
|  |       <Filter>hle\service</Filter> | ||||||
|  |     </ClInclude> | ||||||
|  |     <ClInclude Include="hle\syscall.h"> | ||||||
|  |       <Filter>hle</Filter> | ||||||
|  |     </ClInclude> | ||||||
|  |     <ClInclude Include="hle\service\apt.h"> | ||||||
|  |       <Filter>hle\service</Filter> | ||||||
|  |     </ClInclude> | ||||||
|  |     <ClInclude Include="hle\service\srv.h"> | ||||||
|  |       <Filter>hle\service</Filter> | ||||||
|  |     </ClInclude> | ||||||
|  |     <ClInclude Include="hle\service\gsp.h"> | ||||||
|  |       <Filter>hle\service</Filter> | ||||||
|  |     </ClInclude> | ||||||
|  |     <ClInclude Include="hle\service\hid.h"> | ||||||
|  |       <Filter>hle\service</Filter> | ||||||
|  |     </ClInclude> | ||||||
|  |     <ClInclude Include="hw\ndma.h"> | ||||||
|  |       <Filter>hw</Filter> | ||||||
|  |     </ClInclude> | ||||||
|  |     <ClInclude Include="hw\lcd.h"> | ||||||
|  |       <Filter>hw</Filter> | ||||||
|  |     </ClInclude> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <Text Include="CMakeLists.txt" /> |     <Text Include="CMakeLists.txt" /> | ||||||
|  |  | ||||||
							
								
								
									
										736
									
								
								src/core/hle/function_wrappers.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										736
									
								
								src/core/hle/function_wrappers.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,736 @@ | ||||||
|  | // 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 | ||||||
|  | 
 | ||||||
|  | #include "common/common_types.h" | ||||||
|  | #include "core/mem_map.h" | ||||||
|  | #include "core/hle/hle.h" | ||||||
|  | 
 | ||||||
|  | // For easy parameter parsing and return value processing.
 | ||||||
|  | 
 | ||||||
|  | //32bit wrappers
 | ||||||
|  | template<void func()> void WrapV_V() { | ||||||
|  |     func(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | template<u32 func()> void WrapU_V() { | ||||||
|  |     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<float func()> void WrapF_V() { | ||||||
|  |     RETURNF(func()); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // TODO: Not sure about the floating point parameter passing
 | ||||||
|  | template<float func(int, float, u32)> void WrapF_IFU() { | ||||||
|  |     RETURNF(func(PARAM(0), PARAMF(0), PARAM(1))); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 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, float, float)> void WrapI_UFF() { | ||||||
|  |     // Not sure about the float arguments.
 | ||||||
|  |     int retval = func(PARAM(0), PARAMF(0), PARAMF(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 WrapI_V() { | ||||||
|  |     int retval = func(); | ||||||
|  |     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)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 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(const char *, int)> void WrapV_CI() { | ||||||
|  |     func(Memory::GetCharPointer(PARAM(0)), PARAM(1)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 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, u32, u32, u32, u32)> void WrapI_VUUUUU(){ | ||||||
|  |   u32 retval = func(Memory::GetPointer(PARAM(0)), PARAM(1), PARAM(2), PARAM(3), PARAM(4), PARAM(5)); | ||||||
|  |   RETURN(retval); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | template<int func(u32, s64)> void WrapI_US64() { | ||||||
|  |     int retval = func(PARAM(0), PARAM64(2)); | ||||||
|  |     RETURN(retval); | ||||||
|  | } | ||||||
							
								
								
									
										120
									
								
								src/core/hle/hle.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								src/core/hle/hle.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,120 @@ | ||||||
|  | // Copyright 2014 Citra Emulator Project
 | ||||||
|  | // Licensed under GPLv2
 | ||||||
|  | // Refer to the license.txt file included.  
 | ||||||
|  | 
 | ||||||
|  | #include <vector> | ||||||
|  | 
 | ||||||
|  | #include "core/mem_map.h" | ||||||
|  | #include "core/hle/hle.h" | ||||||
|  | #include "core/hle/syscall.h" | ||||||
|  | #include "core/hle/service/service.h" | ||||||
|  | 
 | ||||||
|  | ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | 
 | ||||||
|  | namespace HLE { | ||||||
|  | 
 | ||||||
|  | static std::vector<ModuleDef> g_module_db; | ||||||
|  | 
 | ||||||
|  | u8* g_command_buffer = NULL;    ///< Command buffer used for sharing between appcore and syscore
 | ||||||
|  | 
 | ||||||
|  | // Read from memory used by CTROS HLE functions
 | ||||||
|  | template <typename T> | ||||||
|  | inline void Read(T &var, const u32 addr) { | ||||||
|  |     if (addr >= HLE::CMD_BUFFER_ADDR && addr < HLE::CMD_BUFFER_ADDR_END) { | ||||||
|  |         var = *((const T*)&g_command_buffer[addr & CMD_BUFFER_MASK]); | ||||||
|  |     } else { | ||||||
|  |         ERROR_LOG(HLE, "unknown read from address %08X", addr); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Write to memory used by CTROS HLE functions
 | ||||||
|  | template <typename T> | ||||||
|  | inline void Write(u32 addr, const T data) { | ||||||
|  |     if (addr >= HLE::CMD_BUFFER_ADDR && addr < HLE::CMD_BUFFER_ADDR_END) { | ||||||
|  |         *(T*)&g_command_buffer[addr & CMD_BUFFER_MASK] = data; | ||||||
|  |     } else { | ||||||
|  |         ERROR_LOG(HLE, "unknown write to address %08X", addr); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | u8 *GetPointer(const u32 addr) { | ||||||
|  |     if (addr >= HLE::CMD_BUFFER_ADDR && addr < HLE::CMD_BUFFER_ADDR_END) { | ||||||
|  |         return g_command_buffer + (addr & CMD_BUFFER_MASK); | ||||||
|  |     } else { | ||||||
|  |         ERROR_LOG(HLE, "unknown pointer from address %08X", addr); | ||||||
|  |         return 0; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Explicitly instantiate template functions because we aren't defining this in the header:
 | ||||||
|  | 
 | ||||||
|  | template void Read<u64>(u64 &var, const u32 addr); | ||||||
|  | template void Read<u32>(u32 &var, const u32 addr); | ||||||
|  | template void Read<u16>(u16 &var, const u32 addr); | ||||||
|  | template void Read<u8>(u8 &var, const u32 addr); | ||||||
|  | 
 | ||||||
|  | template void Write<u64>(u32 addr, const u64 data); | ||||||
|  | template void Write<u32>(u32 addr, const u32 data); | ||||||
|  | template void Write<u16>(u32 addr, const u16 data); | ||||||
|  | template void Write<u8>(u32 addr, const u8 data); | ||||||
|  | 
 | ||||||
|  | const FunctionDef* GetSyscallInfo(u32 opcode) { | ||||||
|  |     u32 func_num = opcode & 0xFFFFFF; // 8 bits
 | ||||||
|  |     if (func_num > 0xFF) { | ||||||
|  |         ERROR_LOG(HLE,"Unknown syscall: 0x%02X", func_num);  | ||||||
|  |         return NULL; | ||||||
|  |     } | ||||||
|  |     return &g_module_db[0].func_table[func_num]; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void CallSyscall(u32 opcode) { | ||||||
|  |     const FunctionDef *info = GetSyscallInfo(opcode); | ||||||
|  | 
 | ||||||
|  |     if (!info) { | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |     if (info->func) { | ||||||
|  |         info->func(); | ||||||
|  |     } else { | ||||||
|  |         ERROR_LOG(HLE, "Unimplemented SysCall function %s(..)", info->name.c_str()); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /// 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(CMD_BUFFER_ADDR); | ||||||
|  |     return CMD_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); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void RegisterAllModules() { | ||||||
|  |     Syscall::Register(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Init() { | ||||||
|  |     Service::Init(); | ||||||
|  | 
 | ||||||
|  |     g_command_buffer = new u8[CMD_BUFFER_SIZE]; | ||||||
|  |      | ||||||
|  |     RegisterAllModules(); | ||||||
|  | 
 | ||||||
|  |     NOTICE_LOG(HLE, "initialized OK"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Shutdown() { | ||||||
|  |     Service::Shutdown(); | ||||||
|  | 
 | ||||||
|  |     delete g_command_buffer; | ||||||
|  | 
 | ||||||
|  |     g_module_db.clear(); | ||||||
|  | 
 | ||||||
|  |     NOTICE_LOG(HLE, "shutdown OK"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | } // namespace
 | ||||||
							
								
								
									
										66
									
								
								src/core/hle/hle.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								src/core/hle/hle.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,66 @@ | ||||||
|  | // Copyright 2014 Citra Emulator Project
 | ||||||
|  | // Licensed under GPLv2
 | ||||||
|  | // Refer to the license.txt file included.  
 | ||||||
|  | 
 | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include "common/common_types.h" | ||||||
|  | #include "core/core.h" | ||||||
|  | 
 | ||||||
|  | ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | 
 | ||||||
|  | #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 { | ||||||
|  | 
 | ||||||
|  | enum { | ||||||
|  |     CMD_BUFFER_ADDR     = 0xA0010000,    ///< Totally arbitrary unused address space
 | ||||||
|  |     CMD_BUFFER_SIZE     = 0x10000, | ||||||
|  |     CMD_BUFFER_MASK     = (CMD_BUFFER_SIZE - 1), | ||||||
|  |     CMD_BUFFER_ADDR_END = (CMD_BUFFER_ADDR + CMD_BUFFER_SIZE), | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | typedef u32 Addr; | ||||||
|  | typedef void (*Func)(); | ||||||
|  | 
 | ||||||
|  | struct FunctionDef { | ||||||
|  |     u32                 id; | ||||||
|  |     Func                func; | ||||||
|  |     std::string         name; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct ModuleDef { | ||||||
|  |     std::string         name; | ||||||
|  |     int                 num_funcs; | ||||||
|  |     const FunctionDef*  func_table; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | // Read from memory used by CTROS HLE functions
 | ||||||
|  | template <typename T> | ||||||
|  | inline void Read(T &var, const u32 addr); | ||||||
|  | 
 | ||||||
|  | // Write to memory used by CTROS HLE functions
 | ||||||
|  | template <typename T> | ||||||
|  | inline void Write(u32 addr, const T data); | ||||||
|  | 
 | ||||||
|  | u8* GetPointer(const u32 Address); | ||||||
|  | 
 | ||||||
|  | inline const char* GetCharPointer(const u32 address) { | ||||||
|  |     return (const char *)GetPointer(address); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void RegisterModule(std::string name, int num_functions, const FunctionDef *func_table); | ||||||
|  | 
 | ||||||
|  | void CallSyscall(u32 opcode); | ||||||
|  | 
 | ||||||
|  | Addr CallGetThreadCommandBuffer(); | ||||||
|  | 
 | ||||||
|  | void Init(); | ||||||
|  | 
 | ||||||
|  | void Shutdown(); | ||||||
|  | 
 | ||||||
|  | } // namespace
 | ||||||
							
								
								
									
										116
									
								
								src/core/hle/service/apt.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								src/core/hle/service/apt.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,116 @@ | ||||||
|  | // 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/apt.h" | ||||||
|  | 
 | ||||||
|  | ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | // Namespace APT_U
 | ||||||
|  | 
 | ||||||
|  | namespace APT_U { | ||||||
|  | 
 | ||||||
|  | void Initialize() { | ||||||
|  |     NOTICE_LOG(OSHLE, "APT_U::Sync - Initialize"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void GetLockHandle() { | ||||||
|  |     u32* cmd_buff = (u32*)HLE::GetPointer(HLE::CMD_BUFFER_ADDR + Service::kCommandHeaderOffset); | ||||||
|  |     cmd_buff[5] = 0x00000000; // TODO: This should be an actual mutex handle
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const HLE::FunctionDef 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"}, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | // Interface class
 | ||||||
|  | 
 | ||||||
|  | Interface::Interface() { | ||||||
|  |     Register(FunctionTable, ARRAY_SIZE(FunctionTable)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Interface::~Interface() { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | } // namespace
 | ||||||
							
								
								
									
										41
									
								
								src/core/hle/service/apt.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								src/core/hle/service/apt.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,41 @@ | ||||||
|  | // Copyright 2014 Citra Emulator Project
 | ||||||
|  | // Licensed under GPLv2
 | ||||||
|  | // Refer to the license.txt file included.
 | ||||||
|  | 
 | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include "core/hle/service/service.h" | ||||||
|  | 
 | ||||||
|  | ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | // Namespace APT_U
 | ||||||
|  | 
 | ||||||
|  | namespace APT_U { | ||||||
|  | 
 | ||||||
|  | // Application and title launching service. These services handle signaling for home/power button as
 | ||||||
|  | // well. Only one session for either APT service can be open at a time, normally processes close the
 | ||||||
|  | // service handle immediately once finished using the service. The commands for APT:U and APT:S are 
 | ||||||
|  | // exactly the same, however certain commands are only accessible with APT:S(NS module will call 
 | ||||||
|  | // svcBreak when the command isn't accessible). See http://3dbrew.org/wiki/NS#APT_Services.
 | ||||||
|  | 
 | ||||||
|  | /// Interface to "APT:U" service
 | ||||||
|  | class Interface : public Service::Interface { | ||||||
|  | public: | ||||||
|  | 
 | ||||||
|  |     Interface(); | ||||||
|  | 
 | ||||||
|  |     ~Interface(); | ||||||
|  | 
 | ||||||
|  |     /**
 | ||||||
|  |      * Gets the string port name used by CTROS for the service | ||||||
|  |      * @return Port name of service | ||||||
|  |      */ | ||||||
|  |     std::string GetPortName() const { | ||||||
|  |         return "APT:U"; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  | 
 | ||||||
|  |     DISALLOW_COPY_AND_ASSIGN(Interface); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | } // namespace
 | ||||||
							
								
								
									
										59
									
								
								src/core/hle/service/gsp.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								src/core/hle/service/gsp.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,59 @@ | ||||||
|  | // 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/gsp.h" | ||||||
|  | 
 | ||||||
|  | ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | // Namespace GSP_GPU
 | ||||||
|  | 
 | ||||||
|  | namespace GSP_GPU { | ||||||
|  | 
 | ||||||
|  | const HLE::FunctionDef FunctionTable[] = { | ||||||
|  |     {0x00010082, NULL, "WriteHWRegs"}, | ||||||
|  |     {0x00020084, NULL, "WriteHWRegsWithMask"}, | ||||||
|  |     {0x00030082, NULL, "WriteHWRegRepeat"}, | ||||||
|  |     {0x00040080, NULL, "ReadHWRegs"}, | ||||||
|  |     {0x00050200, NULL, "SetBufferSwap"}, | ||||||
|  |     {0x00060082, NULL, "SetCommandList"}, | ||||||
|  |     {0x000700C2, NULL, "RequestDma"}, | ||||||
|  |     {0x00080082, NULL, "FlushDataCache"}, | ||||||
|  |     {0x00090082, NULL, "InvalidateDataCache"}, | ||||||
|  |     {0x000A0044, NULL, "RegisterInterruptEvents"}, | ||||||
|  |     {0x000B0040, NULL, "SetLcdForceBlack"}, | ||||||
|  |     {0x000C0000, NULL, "TriggerCmdReqQueue"}, | ||||||
|  |     {0x000D0140, NULL, "SetDisplayTransfer"}, | ||||||
|  |     {0x000E0180, NULL, "SetTextureCopy"}, | ||||||
|  |     {0x000F0200, NULL, "SetMemoryFill"}, | ||||||
|  |     {0x00100040, NULL, "SetAxiConfigQoSMode"}, | ||||||
|  |     {0x00110040, NULL, "SetPerfLogMode"}, | ||||||
|  |     {0x00120000, NULL, "GetPerfLog"}, | ||||||
|  |     {0x00130042, NULL, "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"}, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | // Interface class
 | ||||||
|  | 
 | ||||||
|  | Interface::Interface() { | ||||||
|  |     Register(FunctionTable, ARRAY_SIZE(FunctionTable)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Interface::~Interface() { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | } // namespace
 | ||||||
							
								
								
									
										35
									
								
								src/core/hle/service/gsp.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								src/core/hle/service/gsp.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,35 @@ | ||||||
|  | // Copyright 2014 Citra Emulator Project
 | ||||||
|  | // Licensed under GPLv2
 | ||||||
|  | // Refer to the license.txt file included.
 | ||||||
|  | 
 | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include "core/hle/service/service.h" | ||||||
|  | 
 | ||||||
|  | ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | // Namespace GSP_GPU
 | ||||||
|  | 
 | ||||||
|  | namespace GSP_GPU { | ||||||
|  | 
 | ||||||
|  | /// Interface to "srv:" service
 | ||||||
|  | class Interface : public Service::Interface { | ||||||
|  | public: | ||||||
|  | 
 | ||||||
|  |     Interface(); | ||||||
|  | 
 | ||||||
|  |     ~Interface(); | ||||||
|  | 
 | ||||||
|  |     /**
 | ||||||
|  |      * Gets the string port name used by CTROS for the service | ||||||
|  |      * @return Port name of service | ||||||
|  |      */ | ||||||
|  |     std::string GetPortName() const { | ||||||
|  |         return "gsp::Gpu"; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  | 
 | ||||||
|  |     DISALLOW_COPY_AND_ASSIGN(Interface); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | } // namespace
 | ||||||
							
								
								
									
										33
									
								
								src/core/hle/service/hid.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								src/core/hle/service/hid.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,33 @@ | ||||||
|  | // 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/hid.h" | ||||||
|  | 
 | ||||||
|  | ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | // Namespace HID_User
 | ||||||
|  | 
 | ||||||
|  | namespace HID_User { | ||||||
|  | 
 | ||||||
|  | const HLE::FunctionDef FunctionTable[] = { | ||||||
|  |     {0x000A0000, NULL, "GetIPCHandles"}, | ||||||
|  |     {0x00110000, NULL, "EnableAccelerometer"}, | ||||||
|  |     {0x00130000, NULL, "EnableGyroscopeLow"}, | ||||||
|  |     {0x00150000, NULL, "GetGyroscopeLowRawToDpsCoefficient"}, | ||||||
|  |     {0x00160000, NULL, "GetGyroscopeLowCalibrateParam"}, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | // Interface class
 | ||||||
|  | 
 | ||||||
|  | Interface::Interface() { | ||||||
|  |     Register(FunctionTable, ARRAY_SIZE(FunctionTable)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Interface::~Interface() { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | } // namespace
 | ||||||
							
								
								
									
										37
									
								
								src/core/hle/service/hid.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								src/core/hle/service/hid.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,37 @@ | ||||||
|  | // Copyright 2014 Citra Emulator Project
 | ||||||
|  | // Licensed under GPLv2
 | ||||||
|  | // Refer to the license.txt file included.
 | ||||||
|  | 
 | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include "core/hle/service/service.h" | ||||||
|  | 
 | ||||||
|  | ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | // Namespace HID_User
 | ||||||
|  | 
 | ||||||
|  | // This service is used for interfacing to physical user controls... perhaps "Human Interface 
 | ||||||
|  | // Devices"? Uses include game pad controls, accelerometers, gyroscopes, etc.
 | ||||||
|  | 
 | ||||||
|  | namespace HID_User { | ||||||
|  | 
 | ||||||
|  | class Interface : public Service::Interface { | ||||||
|  | public: | ||||||
|  | 
 | ||||||
|  |     Interface(); | ||||||
|  | 
 | ||||||
|  |     ~Interface(); | ||||||
|  | 
 | ||||||
|  |     /**
 | ||||||
|  |      * Gets the string port name used by CTROS for the service | ||||||
|  |      * @return Port name of service | ||||||
|  |      */ | ||||||
|  |     std::string GetPortName() const { | ||||||
|  |         return "hid:USER"; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  | 
 | ||||||
|  |     DISALLOW_COPY_AND_ASSIGN(Interface); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | } // namespace
 | ||||||
							
								
								
									
										94
									
								
								src/core/hle/service/service.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								src/core/hle/service/service.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,94 @@ | ||||||
|  | // Copyright 2014 Citra Emulator Project
 | ||||||
|  | // Licensed under GPLv2
 | ||||||
|  | // Refer to the license.txt file included.
 | ||||||
|  | 
 | ||||||
|  | #include "common/common.h" | ||||||
|  | #include "common/log.h" | ||||||
|  | #include "common/string_util.h" | ||||||
|  | 
 | ||||||
|  | #include "core/hle/hle.h" | ||||||
|  | #include "core/hle/service/service.h" | ||||||
|  | #include "core/hle/service/apt.h" | ||||||
|  | #include "core/hle/service/gsp.h" | ||||||
|  | #include "core/hle/service/hid.h" | ||||||
|  | #include "core/hle/service/srv.h" | ||||||
|  | 
 | ||||||
|  | namespace Service { | ||||||
|  | 
 | ||||||
|  | Manager* g_manager = NULL;  ///< Service manager
 | ||||||
|  | 
 | ||||||
|  | ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | // Service Manager class
 | ||||||
|  | 
 | ||||||
|  | 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); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | // Module interface
 | ||||||
|  | 
 | ||||||
|  | /// Initialize ServiceManager
 | ||||||
|  | void Init() { | ||||||
|  |     g_manager = new Manager; | ||||||
|  |      | ||||||
|  |     g_manager->AddService(new SRV::Interface); | ||||||
|  |     g_manager->AddService(new APT_U::Interface); | ||||||
|  |     g_manager->AddService(new GSP_GPU::Interface); | ||||||
|  |     g_manager->AddService(new HID_User::Interface); | ||||||
|  | 
 | ||||||
|  |     NOTICE_LOG(HLE, "Services initialized OK"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /// Shutdown ServiceManager
 | ||||||
|  | void Shutdown() { | ||||||
|  |     delete g_manager; | ||||||
|  |     NOTICE_LOG(HLE, "Services shutdown OK"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | } | ||||||
							
								
								
									
										143
									
								
								src/core/hle/service/service.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										143
									
								
								src/core/hle/service/service.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,143 @@ | ||||||
|  | // Copyright 2014 Citra Emulator Project
 | ||||||
|  | // Licensed under GPLv2
 | ||||||
|  | // Refer to the license.txt file included.
 | ||||||
|  | 
 | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <vector> | ||||||
|  | #include <map> | ||||||
|  | #include <string> | ||||||
|  | 
 | ||||||
|  | #include "common/common.h" | ||||||
|  | #include "common/common_types.h" | ||||||
|  | #include "core/hle/syscall.h" | ||||||
|  | 
 | ||||||
|  | ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | // Namespace Service
 | ||||||
|  | 
 | ||||||
|  | namespace Service { | ||||||
|  | 
 | ||||||
|  | typedef s32 NativeUID;                          ///< Native handle for a service
 | ||||||
|  | 
 | ||||||
|  | static const int kMaxPortSize           = 0x08; ///< Maximum size of a port name (8 characters)
 | ||||||
|  | static const int kCommandHeaderOffset   = 0x80; ///< Offset into command buffer of header
 | ||||||
|  | 
 | ||||||
|  | class Manager; | ||||||
|  | 
 | ||||||
|  | /// Interface to a CTROS service
 | ||||||
|  | class Interface { | ||||||
|  |     friend class Manager; | ||||||
|  | public: | ||||||
|  | 
 | ||||||
|  |     Interface() { | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     virtual ~Interface() { | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /**
 | ||||||
|  |      * Gets the UID for the serice | ||||||
|  |      * @return UID of service in native format | ||||||
|  |      */ | ||||||
|  |     NativeUID GetUID() const { | ||||||
|  |         return (NativeUID)m_uid; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /**
 | ||||||
|  |      * Gets the string name used by CTROS for a service | ||||||
|  |      * @return Port name of service | ||||||
|  |      */ | ||||||
|  |     virtual std::string GetPortName() const { | ||||||
|  |         return "[UNKNOWN SERVICE PORT]"; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /**
 | ||||||
|  |      * Called when svcSendSyncRequest is called, loads command buffer and executes comand | ||||||
|  |      * @return Return result of svcSendSyncRequest passed back to user app | ||||||
|  |      */ | ||||||
|  |     Syscall::Result Sync() { | ||||||
|  |         u32* cmd_buff = (u32*)HLE::GetPointer(HLE::CMD_BUFFER_ADDR + kCommandHeaderOffset); | ||||||
|  |         auto itr = m_functions.find(cmd_buff[0]); | ||||||
|  | 
 | ||||||
|  |         if (itr == m_functions.end()) { | ||||||
|  |             ERROR_LOG(OSHLE, "Unknown/unimplemented function: port = %s, command = 0x%08X!",  | ||||||
|  |                 GetPortName().c_str(), cmd_buff[0]); | ||||||
|  |             return -1; | ||||||
|  |         } | ||||||
|  |         if (itr->second.func == NULL) { | ||||||
|  |             ERROR_LOG(OSHLE, "Unimplemented function: port = %s, name = %s!",  | ||||||
|  |                 GetPortName().c_str(), itr->second.name.c_str()); | ||||||
|  |             return -1; | ||||||
|  |         }  | ||||||
|  | 
 | ||||||
|  |         itr->second.func(); | ||||||
|  | 
 | ||||||
|  |         return 0; // TODO: Implement return from actual function
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | protected: | ||||||
|  |     /**
 | ||||||
|  |      * Registers the functions in the service | ||||||
|  |      */ | ||||||
|  |     void Register(const HLE::FunctionDef* functions, int len) { | ||||||
|  |         for (int i = 0; i < len; i++) { | ||||||
|  |             m_functions[functions[i].id] = functions[i]; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |     u32 m_uid; | ||||||
|  |     std::map<u32, HLE::FunctionDef> m_functions; | ||||||
|  | 
 | ||||||
|  |     DISALLOW_COPY_AND_ASSIGN(Interface); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /// Simple class to manage accessing services from ports and UID handles
 | ||||||
|  | class Manager { | ||||||
|  | 
 | ||||||
|  | public: | ||||||
|  |     Manager(); | ||||||
|  | 
 | ||||||
|  |     ~Manager(); | ||||||
|  | 
 | ||||||
|  |     /// Add a service to the manager (does not create it though)
 | ||||||
|  |     void AddService(Interface* service); | ||||||
|  | 
 | ||||||
|  |     /// Removes a service from the manager (does not delete it though)
 | ||||||
|  |     void DeleteService(std::string port_name); | ||||||
|  | 
 | ||||||
|  |     /// Get a Service Interface from its UID
 | ||||||
|  |     Interface* FetchFromUID(u32 uid); | ||||||
|  | 
 | ||||||
|  |     /// Get a Service Interface from its port
 | ||||||
|  |     Interface* FetchFromPortName(std::string port_name); | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  | 
 | ||||||
|  |     /// Convert an index into m_services vector into a UID
 | ||||||
|  |     static u32 GetUIDFromIndex(const int index) { | ||||||
|  |         return index | 0x10000000; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /// Convert a UID into an index into m_services
 | ||||||
|  |     static int GetIndexFromUID(const u32 uid) { | ||||||
|  |         return uid & 0x0FFFFFFF; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     std::vector<Interface*>     m_services; | ||||||
|  |     std::map<std::string, u32>  m_port_map; | ||||||
|  | 
 | ||||||
|  |     DISALLOW_COPY_AND_ASSIGN(Manager); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /// Initialize ServiceManager
 | ||||||
|  | void Init(); | ||||||
|  | 
 | ||||||
|  | /// Shutdown ServiceManager
 | ||||||
|  | void Shutdown(); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | extern Manager* g_manager; ///< Service manager
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | } // namespace
 | ||||||
							
								
								
									
										58
									
								
								src/core/hle/service/srv.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								src/core/hle/service/srv.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,58 @@ | ||||||
|  | // Copyright 2014 Citra Emulator Project
 | ||||||
|  | // Licensed under GPLv2
 | ||||||
|  | // Refer to the license.txt file included.
 | ||||||
|  | 
 | ||||||
|  | #include "core/hle/hle.h" | ||||||
|  | #include "core/hle/service/srv.h" | ||||||
|  | #include "core/hle/service/service.h" | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | // Namespace SRV
 | ||||||
|  | 
 | ||||||
|  | namespace SRV { | ||||||
|  | 
 | ||||||
|  | void Initialize() { | ||||||
|  |     NOTICE_LOG(OSHLE, "SRV::Sync - Initialize"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void GetServiceHandle() { | ||||||
|  |     Syscall::Result res = 0; | ||||||
|  |     u32* cmd_buff = (u32*)HLE::GetPointer(HLE::CMD_BUFFER_ADDR + Service::kCommandHeaderOffset); | ||||||
|  | 
 | ||||||
|  |     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->GetUID()); | ||||||
|  | 
 | ||||||
|  |     if (NULL != service) { | ||||||
|  |         cmd_buff[3] = service->GetUID(); | ||||||
|  |     } else { | ||||||
|  |         ERROR_LOG(OSHLE, "Service %s does not exist", port_name.c_str()); | ||||||
|  |         res = -1; | ||||||
|  |     } | ||||||
|  |     cmd_buff[1] = res; | ||||||
|  | 
 | ||||||
|  |     //return res;
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const HLE::FunctionDef FunctionTable[] = { | ||||||
|  |     {0x00010002, Initialize,        "Initialize"}, | ||||||
|  |     {0x00020000, NULL,              "GetProcSemaphore"}, | ||||||
|  |     {0x00030100, NULL,              "RegisterService"}, | ||||||
|  |     {0x000400C0, NULL,              "UnregisterService"}, | ||||||
|  |     {0x00050100, GetServiceHandle,  "GetServiceHandle"}, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | // Interface class
 | ||||||
|  | 
 | ||||||
|  | Interface::Interface() { | ||||||
|  |     Register(FunctionTable, ARRAY_SIZE(FunctionTable)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Interface::~Interface() { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | } // namespace
 | ||||||
							
								
								
									
										40
									
								
								src/core/hle/service/srv.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								src/core/hle/service/srv.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,40 @@ | ||||||
|  | // Copyright 2014 Citra Emulator Project
 | ||||||
|  | // Licensed under GPLv2
 | ||||||
|  | // Refer to the license.txt file included.
 | ||||||
|  | 
 | ||||||
|  | #include "core/hle/service/service.h" | ||||||
|  | 
 | ||||||
|  | ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | // Namespace SRV
 | ||||||
|  | 
 | ||||||
|  | namespace SRV { | ||||||
|  | 
 | ||||||
|  | /// Interface to "srv:" service
 | ||||||
|  | class Interface : public Service::Interface { | ||||||
|  | 
 | ||||||
|  | public: | ||||||
|  | 
 | ||||||
|  |     Interface(); | ||||||
|  | 
 | ||||||
|  |     ~Interface(); | ||||||
|  | 
 | ||||||
|  |     /**
 | ||||||
|  |      * Gets the string name used by CTROS for the service | ||||||
|  |      * @return Port name of service | ||||||
|  |      */ | ||||||
|  |     std::string GetPortName() const { | ||||||
|  |         return "srv:"; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /**
 | ||||||
|  |      * Called when svcSendSyncRequest is called, loads command buffer and executes comand | ||||||
|  |      * @return Return result of svcSendSyncRequest passed back to user app | ||||||
|  |      */ | ||||||
|  |     Syscall::Result Sync(); | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |       | ||||||
|  |     DISALLOW_COPY_AND_ASSIGN(Interface); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | } // namespace
 | ||||||
							
								
								
									
										197
									
								
								src/core/hle/syscall.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										197
									
								
								src/core/hle/syscall.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,197 @@ | ||||||
|  | // Copyright 2014 Citra Emulator Project
 | ||||||
|  | // Licensed under GPLv2
 | ||||||
|  | // Refer to the license.txt file included.  
 | ||||||
|  | 
 | ||||||
|  | #include <map> | ||||||
|  | 
 | ||||||
|  | #include "core/mem_map.h" | ||||||
|  | 
 | ||||||
|  | #include "core/hle/function_wrappers.h" | ||||||
|  | #include "core/hle/syscall.h" | ||||||
|  | #include "core/hle/service/service.h" | ||||||
|  | 
 | ||||||
|  | ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | // Namespace Syscall
 | ||||||
|  | 
 | ||||||
|  | namespace Syscall { | ||||||
|  | 
 | ||||||
|  | /// Map application or GSP heap memory
 | ||||||
|  | Result ControlMemory(void* outaddr, u32 addr0, u32 addr1, u32 size, u32 operation, u32 permissions) { | ||||||
|  |     u32 virtual_address = 0x00000000; | ||||||
|  | 
 | ||||||
|  |     switch (operation) { | ||||||
|  | 
 | ||||||
|  |     // Map GSP heap memory?
 | ||||||
|  |     case 0x00010003: | ||||||
|  |         virtual_address = Memory::MapBlock_HeapGSP(size, operation, permissions); | ||||||
|  |         break; | ||||||
|  | 
 | ||||||
|  |     // Unknown ControlMemory operation
 | ||||||
|  |     default: | ||||||
|  |         ERROR_LOG(OSHLE, "Unknown ControlMemory operation %08X", operation); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     Core::g_app_core->SetReg(1,  Memory::MapBlock_HeapGSP(size, operation, permissions)); | ||||||
|  |     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) { | ||||||
|  |     Service::Interface* service = Service::g_manager->FetchFromPortName(port_name); | ||||||
|  |     Core::g_app_core->SetReg(1, service->GetUID()); | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /// Synchronize to an OS service
 | ||||||
|  | Result SendSyncRequest(Handle session) { | ||||||
|  |     Service::Interface* service = Service::g_manager->FetchFromUID(session); | ||||||
|  |     service->Sync(); | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /// Close a handle
 | ||||||
|  | Result CloseHandle(Handle handle) { | ||||||
|  |     // ImplementMe
 | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /// Wait for a handle to synchronize, timeout after the specified nanoseconds
 | ||||||
|  | Result WaitSynchronization1(Handle handle, s64 nanoseconds) { | ||||||
|  |     // ImplementMe
 | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const HLE::FunctionDef Syscall_Table[] = { | ||||||
|  |     {0x00,  NULL,                               "Unknown"}, | ||||||
|  |     {0x01,  WrapI_VUUUUU<ControlMemory>,        "ControlMemory"}, | ||||||
|  |     {0x02,  NULL,                               "QueryMemory"}, | ||||||
|  |     {0x03,  NULL,                               "ExitProcess"}, | ||||||
|  |     {0x04,  NULL,                               "GetProcessAffinityMask"}, | ||||||
|  |     {0x05,  NULL,                               "SetProcessAffinityMask"}, | ||||||
|  |     {0x06,  NULL,                               "GetProcessIdealProcessor"}, | ||||||
|  |     {0x07,  NULL,                               "SetProcessIdealProcessor"}, | ||||||
|  |     {0x08,  NULL,                               "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,  NULL,                               "CreateMutex"}, | ||||||
|  |     {0x14,  NULL,                               "ReleaseMutex"}, | ||||||
|  |     {0x15,  NULL,                               "CreateSemaphore"}, | ||||||
|  |     {0x16,  NULL,                               "ReleaseSemaphore"}, | ||||||
|  |     {0x17,  NULL,                               "CreateEvent"}, | ||||||
|  |     {0x18,  NULL,                               "SignalEvent"}, | ||||||
|  |     {0x19,  NULL,                               "ClearEvent"}, | ||||||
|  |     {0x1A,  NULL,                               "CreateTimer"}, | ||||||
|  |     {0x1B,  NULL,                               "SetTimer"}, | ||||||
|  |     {0x1C,  NULL,                               "CancelTimer"}, | ||||||
|  |     {0x1D,  NULL,                               "ClearTimer"}, | ||||||
|  |     {0x1E,  NULL,                               "CreateMemoryBlock"}, | ||||||
|  |     {0x1F,  NULL,                               "MapMemoryBlock"}, | ||||||
|  |     {0x20,  NULL,                               "UnmapMemoryBlock"}, | ||||||
|  |     {0x21,  NULL,                               "CreateAddressArbiter"}, | ||||||
|  |     {0x22,  NULL,                               "ArbitrateAddress"}, | ||||||
|  |     {0x23,  WrapI_U<CloseHandle>,               "CloseHandle"}, | ||||||
|  |     {0x24,  WrapI_US64<WaitSynchronization1>,   "WaitSynchronization1"}, | ||||||
|  |     {0x25,  NULL,                               "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,  NULL,                               "GetThreadId"}, | ||||||
|  |     {0x38,  NULL,                               "GetResourceLimit"}, | ||||||
|  |     {0x39,  NULL,                               "GetResourceLimitLimitValues"}, | ||||||
|  |     {0x3A,  NULL,                               "GetResourceLimitCurrentValues"}, | ||||||
|  |     {0x3B,  NULL,                               "GetThreadContext"}, | ||||||
|  |     {0x3C,  NULL,                               "Break"}, | ||||||
|  |     {0x3D,  NULL,                               "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"}, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | void Register() { | ||||||
|  |     HLE::RegisterModule("SyscallTable", ARRAY_SIZE(Syscall_Table), Syscall_Table); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | } // namespace
 | ||||||
							
								
								
									
										19
									
								
								src/core/hle/syscall.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/core/hle/syscall.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,19 @@ | ||||||
|  | // Copyright 2014 Citra Emulator Project
 | ||||||
|  | // Licensed under GPLv2
 | ||||||
|  | // Refer to the license.txt file included.  
 | ||||||
|  | 
 | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include "common/common_types.h" | ||||||
|  | 
 | ||||||
|  | ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | // Namespace Syscall
 | ||||||
|  | 
 | ||||||
|  | namespace Syscall { | ||||||
|  | 
 | ||||||
|  | typedef u32 Handle; | ||||||
|  | typedef s32 Result; | ||||||
|  | 
 | ||||||
|  | void Register(); | ||||||
|  | 
 | ||||||
|  | } // namespace
 | ||||||
|  | @ -6,18 +6,73 @@ | ||||||
| #include "common/log.h" | #include "common/log.h" | ||||||
| 
 | 
 | ||||||
| #include "core/hw/hw.h" | #include "core/hw/hw.h" | ||||||
| #include "core/hw/hw_lcd.h" | #include "core/hw/lcd.h" | ||||||
|  | #include "core/hw/ndma.h" | ||||||
| 
 | 
 | ||||||
| namespace HW { | namespace HW { | ||||||
| 
 | 
 | ||||||
|  | enum { | ||||||
|  |     ADDRESS_CONFIG      = 0x10000000, | ||||||
|  |     ADDRESS_IRQ         = 0x10001000, | ||||||
|  |     ADDRESS_NDMA        = 0x10002000, | ||||||
|  |     ADDRESS_TIMER       = 0x10003000, | ||||||
|  |     ADDRESS_CTRCARD     = 0x10004000, | ||||||
|  |     ADDRESS_CTRCARD_2   = 0x10005000, | ||||||
|  |     ADDRESS_SDMC_NAND   = 0x10006000, | ||||||
|  |     ADDRESS_SDMC_NAND_2 = 0x10007000,   // Apparently not used on retail
 | ||||||
|  |     ADDRESS_PXI         = 0x10008000, | ||||||
|  |     ADDRESS_AES         = 0x10009000, | ||||||
|  |     ADDRESS_SHA         = 0x1000A000, | ||||||
|  |     ADDRESS_RSA         = 0x1000B000, | ||||||
|  |     ADDRESS_XDMA        = 0x1000C000, | ||||||
|  |     ADDRESS_SPICARD     = 0x1000D800, | ||||||
|  |     ADDRESS_CONFIG_2    = 0x10010000, | ||||||
|  |     ADDRESS_HASH        = 0x10101000, | ||||||
|  |     ADDRESS_CSND        = 0x10103000, | ||||||
|  |     ADDRESS_DSP         = 0x10140000, | ||||||
|  |     ADDRESS_PDN         = 0x10141000, | ||||||
|  |     ADDRESS_CODEC       = 0x10141000, | ||||||
|  |     ADDRESS_SPI         = 0x10142000, | ||||||
|  |     ADDRESS_SPI_2       = 0x10143000, | ||||||
|  |     ADDRESS_I2C         = 0x10144000, | ||||||
|  |     ADDRESS_CODEC_2     = 0x10145000, | ||||||
|  |     ADDRESS_HID         = 0x10146000, | ||||||
|  |     ADDRESS_PAD         = 0x10146000, | ||||||
|  |     ADDRESS_PTM         = 0x10146000, | ||||||
|  |     ADDRESS_I2C_2       = 0x10148000, | ||||||
|  |     ADDRESS_SPI_3       = 0x10160000, | ||||||
|  |     ADDRESS_I2C_3       = 0x10161000, | ||||||
|  |     ADDRESS_MIC         = 0x10162000, | ||||||
|  |     ADDRESS_PXI_2       = 0x10163000, | ||||||
|  |     ADDRESS_NTRCARD     = 0x10164000, | ||||||
|  |     ADDRESS_DSP_2       = 0x10203000, | ||||||
|  |     ADDRESS_HASH_2      = 0x10301000, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| template <typename T> | template <typename T> | ||||||
| inline void Read(T &var, const u32 addr) { | inline void Read(T &var, const u32 addr) { | ||||||
|     NOTICE_LOG(HW, "Hardware read from address %08X", addr); |     switch (addr & 0xFFFFF000) { | ||||||
|  |      | ||||||
|  |     case ADDRESS_NDMA: | ||||||
|  |         NDMA::Read(var, addr); | ||||||
|  |         break; | ||||||
|  | 
 | ||||||
|  |     default: | ||||||
|  |         ERROR_LOG(HW, "unknown Read%d @ 0x%08X", sizeof(var) * 8, addr); | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| template <typename T> | template <typename T> | ||||||
| inline void Write(u32 addr, const T data) { | inline void Write(u32 addr, const T data) { | ||||||
|     NOTICE_LOG(HW, "Hardware write to address %08X", addr); |     switch (addr & 0xFFFFF000) { | ||||||
|  |      | ||||||
|  |     case ADDRESS_NDMA: | ||||||
|  |         NDMA::Write(addr, data); | ||||||
|  |         break; | ||||||
|  | 
 | ||||||
|  |     default: | ||||||
|  |         ERROR_LOG(HW, "unknown Write%d 0x%08X @ 0x%08X", sizeof(data) * 8, data, addr); | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Explicitly instantiate template functions because we aren't defining this in the header:
 | // Explicitly instantiate template functions because we aren't defining this in the header:
 | ||||||
|  | @ -27,25 +82,27 @@ template void Read<u32>(u32 &var, const u32 addr); | ||||||
| template void Read<u16>(u16 &var, const u32 addr); | template void Read<u16>(u16 &var, const u32 addr); | ||||||
| template void Read<u8>(u8 &var, const u32 addr); | template void Read<u8>(u8 &var, const u32 addr); | ||||||
| 
 | 
 | ||||||
| template void Write<const u64>(u32 addr, const u64 data); | template void Write<u64>(u32 addr, const u64 data); | ||||||
| template void Write<const u32>(u32 addr, const u32 data); | template void Write<u32>(u32 addr, const u32 data); | ||||||
| template void Write<const u16>(u32 addr, const u16 data); | template void Write<u16>(u32 addr, const u16 data); | ||||||
| template void Write<const u8>(u32 addr, const u8 data); | template void Write<u8>(u32 addr, const u8 data); | ||||||
| 
 | 
 | ||||||
| /// Update hardware
 | /// Update hardware
 | ||||||
| void Update() { | void Update() { | ||||||
|     LCD::Update(); |     LCD::Update(); | ||||||
|  |     NDMA::Update(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// Initialize hardware
 | /// Initialize hardware
 | ||||||
| void Init() { | void Init() { | ||||||
|     LCD::Init(); |     LCD::Init(); | ||||||
|     NOTICE_LOG(HW, "Hardware initialized OK"); |     NDMA::Init(); | ||||||
|  |     NOTICE_LOG(HW, "initialized OK"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// Shutdown hardware
 | /// Shutdown hardware
 | ||||||
| void Shutdown() { | void Shutdown() { | ||||||
|     NOTICE_LOG(HW, "Hardware shutdown OK"); |     NOTICE_LOG(HW, "shutdown OK"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  | @ -6,7 +6,7 @@ | ||||||
| #include "common/log.h" | #include "common/log.h" | ||||||
| 
 | 
 | ||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
| #include "core/hw/hw_lcd.h" | #include "core/hw/lcd.h" | ||||||
| 
 | 
 | ||||||
| #include "video_core/video_core.h" | #include "video_core/video_core.h" | ||||||
| 
 | 
 | ||||||
|  | @ -37,12 +37,12 @@ void Update() { | ||||||
| /// Initialize hardware
 | /// Initialize hardware
 | ||||||
| void Init() { | void Init() { | ||||||
|     g_last_ticks = Core::g_app_core->GetTicks(); |     g_last_ticks = Core::g_app_core->GetTicks(); | ||||||
|     NOTICE_LOG(LCD, "LCD initialized OK"); |     NOTICE_LOG(LCD, "initialized OK"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// Shutdown hardware
 | /// Shutdown hardware
 | ||||||
| void Shutdown() { | void Shutdown() { | ||||||
|     NOTICE_LOG(LCD, "LCD shutdown OK"); |     NOTICE_LOG(LCD, "shutdown OK"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| } // namespace
 | } // namespace
 | ||||||
							
								
								
									
										48
									
								
								src/core/hw/ndma.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								src/core/hw/ndma.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,48 @@ | ||||||
|  | // Copyright 2014 Citra Emulator Project
 | ||||||
|  | // Licensed under GPLv2
 | ||||||
|  | // Refer to the license.txt file included.
 | ||||||
|  | 
 | ||||||
|  | #include "common/common_types.h" | ||||||
|  | #include "common/log.h" | ||||||
|  | 
 | ||||||
|  | #include "core/hw/ndma.h" | ||||||
|  | 
 | ||||||
|  | namespace NDMA { | ||||||
|  | 
 | ||||||
|  | template <typename T> | ||||||
|  | inline void Read(T &var, const u32 addr) { | ||||||
|  |     ERROR_LOG(NDMA, "unknown Read%d @ 0x%08X", sizeof(var) * 8, addr); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | template <typename T> | ||||||
|  | inline void Write(u32 addr, const T data) { | ||||||
|  |     ERROR_LOG(NDMA, "unknown Write%d 0x%08X @ 0x%08X", sizeof(data) * 8, data, addr); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Explicitly instantiate template functions because we aren't defining this in the header:
 | ||||||
|  | 
 | ||||||
|  | template void Read<u64>(u64 &var, const u32 addr); | ||||||
|  | template void Read<u32>(u32 &var, const u32 addr); | ||||||
|  | template void Read<u16>(u16 &var, const u32 addr); | ||||||
|  | template void Read<u8>(u8 &var, const u32 addr); | ||||||
|  | 
 | ||||||
|  | template void Write<u64>(u32 addr, const u64 data); | ||||||
|  | template void Write<u32>(u32 addr, const u32 data); | ||||||
|  | template void Write<u16>(u32 addr, const u16 data); | ||||||
|  | template void Write<u8>(u32 addr, const u8 data); | ||||||
|  | 
 | ||||||
|  | /// Update hardware
 | ||||||
|  | void Update() { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /// Initialize hardware
 | ||||||
|  | void Init() { | ||||||
|  |     NOTICE_LOG(LCD, "initialized OK"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /// Shutdown hardware
 | ||||||
|  | void Shutdown() { | ||||||
|  |     NOTICE_LOG(LCD, "shutdown OK"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | } // namespace
 | ||||||
							
								
								
									
										26
									
								
								src/core/hw/ndma.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								src/core/hw/ndma.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,26 @@ | ||||||
|  | // Copyright 2014 Citra Emulator Project
 | ||||||
|  | // Licensed under GPLv2
 | ||||||
|  | // Refer to the license.txt file included.
 | ||||||
|  | 
 | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include "common/common_types.h" | ||||||
|  | 
 | ||||||
|  | namespace NDMA { | ||||||
|  | 
 | ||||||
|  | template <typename T> | ||||||
|  | inline void Read(T &var, const u32 addr); | ||||||
|  | 
 | ||||||
|  | template <typename T> | ||||||
|  | inline void Write(u32 addr, const T data); | ||||||
|  | 
 | ||||||
|  | /// Update hardware
 | ||||||
|  | void Update(); | ||||||
|  | 
 | ||||||
|  | /// Initialize hardware
 | ||||||
|  | void Init(); | ||||||
|  | 
 | ||||||
|  | /// Shutdown hardware
 | ||||||
|  | void Shutdown(); | ||||||
|  | 
 | ||||||
|  | } // namespace
 | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| // Copyright 2014 Citra Emulator Project
 |  // Copyright 2014 Citra Emulator Project
 | ||||||
| // Licensed under GPLv2
 | // Licensed under GPLv2
 | ||||||
| // Refer to the license.txt file included.
 | // Refer to the license.txt file included.
 | ||||||
| 
 | 
 | ||||||
|  | @ -12,27 +12,27 @@ | ||||||
| 
 | 
 | ||||||
| namespace Memory { | namespace Memory { | ||||||
| 
 | 
 | ||||||
|      |  | ||||||
| u8*    g_base                   = NULL;         ///< The base pointer to the auto-mirrored arena.
 | u8*    g_base                   = NULL;         ///< The base pointer to the auto-mirrored arena.
 | ||||||
| 
 | 
 | ||||||
| MemArena g_arena;                               ///< The MemArena class
 | MemArena g_arena;                               ///< The MemArena class
 | ||||||
| 
 | 
 | ||||||
| u8* g_bootrom                   = NULL;         ///< Bootrom physical memory
 | u8* g_heap_gsp                  = NULL;         ///< GSP heap (main memory)
 | ||||||
| u8* g_fcram                     = NULL;         ///< Main memory (FCRAM) pointer
 | u8* g_heap                      = NULL;         ///< Application heap (main memory)
 | ||||||
| u8* g_vram                      = NULL;         ///< Video memory (VRAM) pointer
 | u8* g_vram                      = NULL;         ///< Video memory (VRAM) pointer
 | ||||||
| u8* g_scratchpad                = NULL;         ///< Scratchpad memory - Used for main thread stack
 |  | ||||||
| 
 | 
 | ||||||
| u8* g_physical_bootrom          = NULL;         ///< Bootrom physical memory
 | u8* g_physical_bootrom          = NULL;         ///< Bootrom physical memory
 | ||||||
| u8* g_uncached_bootrom          = NULL; | u8* g_uncached_bootrom          = NULL; | ||||||
| 
 | 
 | ||||||
| u8* g_physical_fcram            = NULL;         ///< Main physical memory (FCRAM)
 | u8* g_physical_fcram            = NULL;         ///< Main physical memory (FCRAM)
 | ||||||
|  | u8* g_physical_heap_gsp         = NULL; | ||||||
| u8* g_physical_vram             = NULL;         ///< Video physical memory (VRAM)
 | u8* g_physical_vram             = NULL;         ///< Video physical memory (VRAM)
 | ||||||
| u8* g_physical_scratchpad       = NULL;         ///< Scratchpad memory used for main thread stack
 | u8* g_physical_scratchpad       = NULL;         ///< Scratchpad memory used for main thread stack
 | ||||||
| 
 | 
 | ||||||
| // We don't declare the IO region in here since its handled by other means.
 | // We don't declare the IO region in here since its handled by other means.
 | ||||||
| static MemoryView g_views[] = { | static MemoryView g_views[] = { | ||||||
|     { &g_vram,  &g_physical_vram,   MEM_VRAM_VADDR,     MEM_VRAM_SIZE,  0 }, |     {&g_vram,       &g_physical_vram,       VRAM_VADDR,     VRAM_SIZE,      0}, | ||||||
|     { &g_fcram, &g_physical_fcram,  MEM_FCRAM_VADDR,    MEM_FCRAM_SIZE, MV_IS_PRIMARY_RAM }, |     {&g_heap_gsp,   &g_physical_heap_gsp,   HEAP_GSP_VADDR, HEAP_GSP_SIZE,  0}, | ||||||
|  |     {&g_heap,       &g_physical_fcram,      HEAP_VADDR,     HEAP_SIZE,      MV_IS_PRIMARY_RAM}, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /*static MemoryView views[] =
 | /*static MemoryView views[] =
 | ||||||
|  | @ -56,14 +56,12 @@ void Init() { | ||||||
| 
 | 
 | ||||||
|     for (size_t i = 0; i < ARRAY_SIZE(g_views); i++) { |     for (size_t i = 0; i < ARRAY_SIZE(g_views); i++) { | ||||||
|         if (g_views[i].flags & MV_IS_PRIMARY_RAM) |         if (g_views[i].flags & MV_IS_PRIMARY_RAM) | ||||||
|             g_views[i].size = MEM_FCRAM_SIZE; |             g_views[i].size = FCRAM_SIZE; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     g_base = MemoryMap_Setup(g_views, kNumMemViews, flags, &g_arena); |     g_base = MemoryMap_Setup(g_views, kNumMemViews, flags, &g_arena); | ||||||
| 
 | 
 | ||||||
|     g_scratchpad = new u8[MEM_SCRATCHPAD_SIZE]; |     NOTICE_LOG(MEMMAP, "initialized OK, RAM at %p (mirror at 0 @ %p)", g_heap,  | ||||||
| 
 |  | ||||||
|     NOTICE_LOG(MEMMAP, "Memory system initialized. RAM at %p (mirror at 0 @ %p)", g_fcram,  |  | ||||||
|         g_physical_fcram); |         g_physical_fcram); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -72,12 +70,9 @@ void Shutdown() { | ||||||
|     MemoryMap_Shutdown(g_views, kNumMemViews, flags, &g_arena); |     MemoryMap_Shutdown(g_views, kNumMemViews, flags, &g_arena); | ||||||
|      |      | ||||||
|     g_arena.ReleaseSpace(); |     g_arena.ReleaseSpace(); | ||||||
|     delete[] g_scratchpad; |     g_base = NULL; | ||||||
|      |  | ||||||
|     g_base          = NULL; |  | ||||||
|     g_scratchpad    = NULL; |  | ||||||
| 
 | 
 | ||||||
|     NOTICE_LOG(MEMMAP, "Memory system shut down."); |     NOTICE_LOG(MEMMAP, "shutdown OK"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| } // namespace
 | } // namespace
 | ||||||
|  |  | ||||||
|  | @ -4,39 +4,67 @@ | ||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////
 |  | ||||||
| 
 |  | ||||||
| #include "common/common.h" | #include "common/common.h" | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| 
 | 
 | ||||||
|  | namespace Memory { | ||||||
|  | 
 | ||||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||||
| 
 | 
 | ||||||
| enum { | enum { | ||||||
|     MEM_BOOTROM_SIZE        = 0x00010000,	///< Bootrom (super secret code/data @ 0x8000) size
 |     BOOTROM_SIZE            = 0x00010000,   ///< Bootrom (super secret code/data @ 0x8000) size
 | ||||||
|     MEM_MPCORE_PRIV_SIZE    = 0x00002000,	///< MPCore private memory region size
 |     MPCORE_PRIV_SIZE        = 0x00002000,   ///< MPCore private memory region size
 | ||||||
|     MEM_VRAM_SIZE           = 0x00600000,	///< VRAM size
 |     VRAM_SIZE               = 0x00600000,   ///< VRAM size
 | ||||||
|     MEM_DSP_SIZE            = 0x00080000,	///< DSP memory size
 |     DSP_SIZE                = 0x00080000,   ///< DSP memory size
 | ||||||
|     MEM_AXI_WRAM_SIZE       = 0x00080000,	///< AXI WRAM size
 |     AXI_WRAM_SIZE           = 0x00080000,   ///< AXI WRAM size
 | ||||||
|     MEM_FCRAM_SIZE          = 0x08000000,	///< FCRAM size... Really 0x07E00000, but power of 2
 |     FCRAM_SIZE              = 0x08000000,   ///< FCRAM size
 | ||||||
|                                             //      works much better
 |     SCRATCHPAD_SIZE         = 0x00004000,   ///< Typical stack size - TODO: Read from exheader
 | ||||||
|     MEM_SCRATCHPAD_SIZE     = 0x00004000,  ///< Typical stack size - TODO: Read from exheader
 |     HEAP_GSP_SIZE           = 0x02000000,   ///< GSP heap size... TODO: Define correctly?
 | ||||||
|                              |     HEAP_SIZE               = FCRAM_SIZE,   ///< Application heap size
 | ||||||
|     MEM_VRAM_MASK           = 0x007FFFFF, |  | ||||||
|     MEM_FCRAM_MASK          = (MEM_FCRAM_SIZE - 1),	            ///< FCRAM mask
 |  | ||||||
|     MEM_SCRATCHPAD_MASK     = (MEM_SCRATCHPAD_SIZE - 1),           ///< Scratchpad memory mask
 |  | ||||||
|                              |  | ||||||
|     MEM_FCRAM_PADDR     = 0x20000000,                           ///< FCRAM physical address
 |  | ||||||
|     MEM_FCRAM_PADDR_END = (MEM_FCRAM_PADDR + MEM_FCRAM_SIZE),   ///< FCRAM end of physical space
 |  | ||||||
|     MEM_FCRAM_VADDR     = 0x08000000,                           ///< FCRAM virtual address
 |  | ||||||
|     MEM_FCRAM_VADDR_END = (MEM_FCRAM_VADDR + MEM_FCRAM_SIZE),   ///< FCRAM end of virtual space
 |  | ||||||
| 
 | 
 | ||||||
|     MEM_VRAM_VADDR          = 0x1F000000, |     HEAP_PADDR              = HEAP_GSP_SIZE, | ||||||
|     MEM_SCRATCHPAD_VADDR    = (0x10000000 - MEM_SCRATCHPAD_SIZE),  ///< Scratchpad virtual address
 |     HEAP_PADDR_END          = (HEAP_PADDR + HEAP_SIZE), | ||||||
|  |     HEAP_VADDR              = 0x08000000, | ||||||
|  |     HEAP_VADDR_END          = (HEAP_VADDR + HEAP_SIZE), | ||||||
|  |     HEAP_GSP_VADDR          = 0x14000000, | ||||||
|  |     HEAP_GSP_VADDR_END      = (HEAP_GSP_VADDR + HEAP_GSP_SIZE), | ||||||
|  |     HEAP_GSP_PADDR          = 0x00000000, | ||||||
|  |     HEAP_GSP_PADDR_END      = (HEAP_GSP_PADDR + HEAP_GSP_SIZE), | ||||||
|  | 
 | ||||||
|  |     VRAM_MASK               = 0x007FFFFF, | ||||||
|  |     FCRAM_MASK              = (FCRAM_SIZE - 1),                 ///< FCRAM mask
 | ||||||
|  |     SCRATCHPAD_MASK         = (SCRATCHPAD_SIZE - 1),            ///< Scratchpad memory mask
 | ||||||
|  |     HEAP_GSP_MASK           = (HEAP_GSP_SIZE - 1), | ||||||
|  |     HEAP_MASK               = (HEAP_SIZE - 1), | ||||||
|  | 
 | ||||||
|  |     FCRAM_PADDR             = 0x20000000,                       ///< FCRAM physical address
 | ||||||
|  |     FCRAM_PADDR_END         = (FCRAM_PADDR + FCRAM_SIZE),       ///< FCRAM end of physical space
 | ||||||
|  |     FCRAM_VADDR             = 0x08000000,                       ///< FCRAM virtual address
 | ||||||
|  |     FCRAM_VADDR_END         = (FCRAM_VADDR + FCRAM_SIZE),       ///< FCRAM end of virtual space
 | ||||||
|  | 
 | ||||||
|  |     VRAM_VADDR              = 0x1F000000, | ||||||
|  |     SCRATCHPAD_VADDR_END    = 0x10000000, | ||||||
|  |     SCRATCHPAD_VADDR        = (SCRATCHPAD_VADDR_END - SCRATCHPAD_SIZE), ///< Stack space
 | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||||
| 
 | 
 | ||||||
| namespace Memory { | /// Represents a block of heap memory mapped by ControlMemory
 | ||||||
|  | struct HeapBlock { | ||||||
|  |     HeapBlock() : base_address(0), address(0), size(0), operation(0), permissions(0) { | ||||||
|  |     } | ||||||
|  |     u32 base_address; | ||||||
|  |     u32 address; | ||||||
|  |     u32 size; | ||||||
|  |     u32 operation; | ||||||
|  |     u32 permissions; | ||||||
|  | 
 | ||||||
|  |     const u32 GetVirtualAddress() const{ | ||||||
|  |         return base_address + address; | ||||||
|  |     } | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||||
| 
 | 
 | ||||||
| // Base is a pointer to the base of the memory map. Yes, some MMU tricks
 | // Base is a pointer to the base of the memory map. Yes, some MMU tricks
 | ||||||
| // are used to set up a full GC or Wii memory map in process memory.  on
 | // are used to set up a full GC or Wii memory map in process memory.  on
 | ||||||
|  | @ -50,9 +78,9 @@ extern u8 *g_base; | ||||||
| // These are guaranteed to point to "low memory" addresses (sub-32-bit).
 | // These are guaranteed to point to "low memory" addresses (sub-32-bit).
 | ||||||
| // 64-bit: Pointers to low-mem (sub-0x10000000) mirror
 | // 64-bit: Pointers to low-mem (sub-0x10000000) mirror
 | ||||||
| // 32-bit: Same as the corresponding physical/virtual pointers.
 | // 32-bit: Same as the corresponding physical/virtual pointers.
 | ||||||
| extern u8* g_fcram;			///< Main memory
 | extern u8* g_heap_gsp;      ///< GSP heap (main memory)
 | ||||||
| extern u8* g_vram;			///< Video memory (VRAM)
 | extern u8* g_heap;          ///< Application heap (main memory)
 | ||||||
| extern u8* g_scratchpad;    ///< Stack memory
 | extern u8* g_vram;          ///< Video memory (VRAM)
 | ||||||
| 
 | 
 | ||||||
| void Init(); | void Init(); | ||||||
| void Shutdown(); | void Shutdown(); | ||||||
|  | @ -70,4 +98,16 @@ void Write32(const u32 addr, const u32 data); | ||||||
| 
 | 
 | ||||||
| u8* GetPointer(const u32 Address); | u8* GetPointer(const u32 Address); | ||||||
| 
 | 
 | ||||||
|  | /**
 | ||||||
|  |  * Maps a block of memory on the GSP heap | ||||||
|  |  * @param size Size of block in bytes | ||||||
|  |  * @param operation Control memory operation | ||||||
|  |  * @param permissions Control memory permissions | ||||||
|  |  */ | ||||||
|  | u32 MapBlock_HeapGSP(u32 size, u32 operation, u32 permissions); | ||||||
|  | 
 | ||||||
|  | inline const char* GetCharPointer(const u32 address) { | ||||||
|  |     return (const char *)GetPointer(address); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| } // namespace
 | } // namespace
 | ||||||
|  |  | ||||||
|  | @ -2,151 +2,146 @@ | ||||||
| // Licensed under GPLv2
 | // Licensed under GPLv2
 | ||||||
| // Refer to the license.txt file included.
 | // Refer to the license.txt file included.
 | ||||||
| 
 | 
 | ||||||
|  | #include <map> | ||||||
|  | 
 | ||||||
| #include "common/common.h" | #include "common/common.h" | ||||||
| 
 | 
 | ||||||
| #include "core/mem_map.h" | #include "core/mem_map.h" | ||||||
| #include "core/hw/hw.h" | #include "core/hw/hw.h" | ||||||
|  | #include "hle/hle.h" | ||||||
| 
 | 
 | ||||||
| namespace Memory { | namespace Memory { | ||||||
| 
 | 
 | ||||||
|  | std::map<u32, HeapBlock> g_heap_gsp_map; | ||||||
|  | 
 | ||||||
|  | /// Convert a physical address to virtual address
 | ||||||
|  | u32 _AddressPhysicalToVirtual(const u32 addr) { | ||||||
|  |     // Our memory interface read/write functions assume virtual addresses. Put any physical address 
 | ||||||
|  |     // to virtual address translations here. This is obviously quite hacky... But we're not doing 
 | ||||||
|  |     // any MMU emulation yet or anything
 | ||||||
|  |     if ((addr >= FCRAM_PADDR) && (addr < (FCRAM_PADDR_END))) { | ||||||
|  |         return (addr & FCRAM_MASK) | FCRAM_VADDR; | ||||||
|  |     } | ||||||
|  |     return addr; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| template <typename T> | template <typename T> | ||||||
| inline void _Read(T &var, const u32 addr) { | inline void _Read(T &var, const u32 addr) { | ||||||
|     // TODO: Figure out the fastest order of tests for both read and write (they are probably different).
 |     // TODO: Figure out the fastest order of tests for both read and write (they are probably different).
 | ||||||
|     // TODO: Make sure this represents the mirrors in a correct way.
 |     // TODO: Make sure this represents the mirrors in a correct way.
 | ||||||
|     // Could just do a base-relative read, too.... TODO
 |     // Could just do a base-relative read, too.... TODO
 | ||||||
| 
 | 
 | ||||||
|  |     const u32 vaddr = _AddressPhysicalToVirtual(addr); | ||||||
|  |      | ||||||
|  |     // Memory allocated for HLE use that can be addressed from the emulated application
 | ||||||
|  |     // The primary use of this is sharing a commandbuffer between the HLE OS (syscore) and the LLE
 | ||||||
|  |     // core running the user application (appcore)
 | ||||||
|  |     if (vaddr >= HLE::CMD_BUFFER_ADDR && vaddr < HLE::CMD_BUFFER_ADDR_END) { | ||||||
|  |         HLE::Read<T>(var, vaddr); | ||||||
|  | 
 | ||||||
|     // Hardware I/O register reads
 |     // Hardware I/O register reads
 | ||||||
|     // 0x10XXXXXX- is physical address space, 0x1EXXXXXX is virtual address space
 |     // 0x10XXXXXX- is physical address space, 0x1EXXXXXX is virtual address space
 | ||||||
|     if ((addr & 0xFF000000) == 0x10000000 || (addr & 0xFF000000) == 0x1E000000) { |     } else if ((vaddr & 0xFF000000) == 0x10000000 || (vaddr & 0xFF000000) == 0x1E000000) { | ||||||
|         HW::Read<T>(var, addr); |         HW::Read<T>(var, vaddr); | ||||||
| 
 | 
 | ||||||
|     // FCRAM virtual address reads
 |     // FCRAM - GSP heap
 | ||||||
|     } else if ((addr & 0x3E000000) == 0x08000000) { |     } else if ((vaddr > HEAP_GSP_VADDR)  && (vaddr < HEAP_GSP_VADDR_END)) { | ||||||
|         var = *((const T*)&g_fcram[addr & MEM_FCRAM_MASK]); |         var = *((const T*)&g_heap_gsp[vaddr & HEAP_GSP_MASK]); | ||||||
| 
 | 
 | ||||||
|     // Scratchpad memory
 |     // FCRAM - application heap
 | ||||||
|     } else if (addr > MEM_SCRATCHPAD_VADDR && addr <= (MEM_SCRATCHPAD_VADDR + MEM_SCRATCHPAD_SIZE)) { |     } else if ((vaddr > HEAP_VADDR)  && (vaddr < HEAP_VADDR_END)) { | ||||||
|         var = *((const T*)&g_scratchpad[addr & MEM_SCRATCHPAD_MASK]); |         var = *((const T*)&g_heap[vaddr & HEAP_MASK]); | ||||||
|   |  | ||||||
|     /*else if ((addr & 0x3F800000) == 0x04000000) {
 |  | ||||||
|         var = *((const T*)&m_pVRAM[addr & VRAM_MASK]); |  | ||||||
|     }*/ |  | ||||||
| 
 | 
 | ||||||
|     // HACK(bunnei): There is no layer yet to translate virtual addresses to physical addresses. 
 |     /*else if ((vaddr & 0x3F800000) == 0x04000000) {
 | ||||||
|     // Until we progress far enough along, we'll accept all physical address reads here. I think 
 |         var = *((const T*)&m_pVRAM[vaddr & VRAM_MASK]);*/ | ||||||
|     // that this is typically a corner-case from usermode software unless they are trying to do 
 |  | ||||||
|     // bare-metal things (e.g. early 3DS homebrew writes directly to the FB @ 0x20184E60, etc.
 |  | ||||||
|     } else if (((addr & 0xF0000000) == MEM_FCRAM_PADDR) && (addr < (MEM_FCRAM_PADDR_END))) { |  | ||||||
|         var = *((const T*)&g_fcram[addr & MEM_FCRAM_MASK]); |  | ||||||
| 
 | 
 | ||||||
|     } else { |     } else { | ||||||
|         _assert_msg_(MEMMAP, false, "unknown memory read"); |         //_assert_msg_(MEMMAP, false, "unknown Read%d @ 0x%08X", sizeof(var) * 8, vaddr);
 | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| template <typename T> | template <typename T> | ||||||
| inline void _Write(u32 addr, const T data) { | inline void _Write(u32 addr, const T data) { | ||||||
|  |     u32 vaddr = _AddressPhysicalToVirtual(addr); | ||||||
|      |      | ||||||
|  |     // Memory allocated for HLE use that can be addressed from the emulated application
 | ||||||
|  |     // The primary use of this is sharing a commandbuffer between the HLE OS (syscore) and the LLE
 | ||||||
|  |     // core running the user application (appcore)
 | ||||||
|  |     if (vaddr >= HLE::CMD_BUFFER_ADDR && vaddr < HLE::CMD_BUFFER_ADDR_END) { | ||||||
|  |         HLE::Write<T>(vaddr, data); | ||||||
|  | 
 | ||||||
|     // Hardware I/O register writes
 |     // Hardware I/O register writes
 | ||||||
|     // 0x10XXXXXX- is physical address space, 0x1EXXXXXX is virtual address space
 |     // 0x10XXXXXX- is physical address space, 0x1EXXXXXX is virtual address space
 | ||||||
|     if ((addr & 0xFF000000) == 0x10000000 || (addr & 0xFF000000) == 0x1E000000) { |     } else if ((vaddr & 0xFF000000) == 0x10000000 || (vaddr & 0xFF000000) == 0x1E000000) { | ||||||
|         HW::Write<const T>(addr, data); |         HW::Write<T>(vaddr, data); | ||||||
|      |  | ||||||
|     // ExeFS:/.code is loaded here:
 |  | ||||||
|     } else if ((addr & 0xFFF00000) == 0x00100000) { |  | ||||||
|         // TODO(ShizZy): This is dumb... handle correctly. From 3DBrew:
 |  | ||||||
|         // http://3dbrew.org/wiki/Memory_layout#ARM11_User-land_memory_regions
 |  | ||||||
|         // The ExeFS:/.code is loaded here, executables must be loaded to the 0x00100000 region when
 |  | ||||||
|         // the exheader "special memory" flag is clear. The 0x03F00000-byte size restriction only 
 |  | ||||||
|         // applies when this flag is clear. Executables are usually loaded to 0x14000000 when the 
 |  | ||||||
|         // exheader "special memory" flag is set, however this address can be arbitrary.
 |  | ||||||
|         *(T*)&g_fcram[addr & MEM_FCRAM_MASK] = data; |  | ||||||
| 
 | 
 | ||||||
|     // Scratchpad memory
 |     // FCRAM - GSP heap
 | ||||||
|     } else if (addr > MEM_SCRATCHPAD_VADDR && addr <= (MEM_SCRATCHPAD_VADDR + MEM_SCRATCHPAD_SIZE)) { |     } else if ((vaddr > HEAP_GSP_VADDR)  && (vaddr < HEAP_GSP_VADDR_END)) { | ||||||
|         *(T*)&g_scratchpad[addr & MEM_SCRATCHPAD_MASK] = data; |         *(T*)&g_heap_gsp[vaddr & HEAP_GSP_MASK] = data; | ||||||
| 
 | 
 | ||||||
|     // Heap mapped by ControlMemory:
 |     // FCRAM - application heap
 | ||||||
|     } else if ((addr & 0x3E000000) == 0x08000000) { |     } else if ((vaddr > HEAP_VADDR)  && (vaddr < HEAP_VADDR_END)) { | ||||||
|         // TODO(ShizZy): Writes to this virtual address should be put in physical memory at FCRAM + GSP
 |         *(T*)&g_heap[vaddr & HEAP_MASK] = data; | ||||||
|         // heap size... the following is writing to FCRAM + 0, which is actually supposed to be the 
 |  | ||||||
|         // application's GSP heap
 |  | ||||||
|         *(T*)&g_fcram[addr & MEM_FCRAM_MASK] = data; |  | ||||||
| 
 | 
 | ||||||
|     } else if ((addr & 0xFF000000) == 0x14000000) { |     } else if ((vaddr & 0xFF000000) == 0x14000000) { | ||||||
|         _assert_msg_(MEMMAP, false, "umimplemented write to GSP heap"); |         _assert_msg_(MEMMAP, false, "umimplemented write to GSP heap"); | ||||||
|     } else if ((addr & 0xFFF00000) == 0x1EC00000) { |     } else if ((vaddr & 0xFFF00000) == 0x1EC00000) { | ||||||
|         _assert_msg_(MEMMAP, false, "umimplemented write to IO registers"); |         _assert_msg_(MEMMAP, false, "umimplemented write to IO registers"); | ||||||
|     } else if ((addr & 0xFF000000) == 0x1F000000) { |     } else if ((vaddr & 0xFF000000) == 0x1F000000) { | ||||||
|         _assert_msg_(MEMMAP, false, "umimplemented write to VRAM"); |         _assert_msg_(MEMMAP, false, "umimplemented write to VRAM"); | ||||||
|     } else if ((addr & 0xFFF00000) == 0x1FF00000) { |     } else if ((vaddr & 0xFFF00000) == 0x1FF00000) { | ||||||
|         _assert_msg_(MEMMAP, false, "umimplemented write to DSP memory"); |         _assert_msg_(MEMMAP, false, "umimplemented write to DSP memory"); | ||||||
|     } else if ((addr & 0xFFFF0000) == 0x1FF80000) { |     } else if ((vaddr & 0xFFFF0000) == 0x1FF80000) { | ||||||
|         _assert_msg_(MEMMAP, false, "umimplemented write to Configuration Memory"); |         _assert_msg_(MEMMAP, false, "umimplemented write to Configuration Memory"); | ||||||
|     } else if ((addr & 0xFFFFF000) == 0x1FF81000) { |     } else if ((vaddr & 0xFFFFF000) == 0x1FF81000) { | ||||||
|         _assert_msg_(MEMMAP, false, "umimplemented write to shared page"); |         _assert_msg_(MEMMAP, false, "umimplemented write to shared page"); | ||||||
|      |      | ||||||
|     // HACK(bunnei): There is no layer yet to translate virtual addresses to physical addresses. 
 |  | ||||||
|     // Until we progress far enough along, we'll accept all physical address writes here. I think 
 |  | ||||||
|     // that this is typically a corner-case from usermode software unless they are trying to do 
 |  | ||||||
|     // bare-metal things (e.g. early 3DS homebrew writes directly to the FB @ 0x20184E60, etc.
 |  | ||||||
|     } else if (((addr & 0xF0000000) == MEM_FCRAM_PADDR) && (addr < (MEM_FCRAM_PADDR_END))) { |  | ||||||
|         *(T*)&g_fcram[addr & MEM_FCRAM_MASK] = data; |  | ||||||
| 
 |  | ||||||
|     // Error out...
 |     // Error out...
 | ||||||
|     } else { |     } else { | ||||||
|         _assert_msg_(MEMMAP, false, "unknown memory write"); |         _assert_msg_(MEMMAP, false, "unknown Write%d 0x%08X @ 0x%08X", sizeof(data) * 8, | ||||||
|     } |             data, vaddr); | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool IsValidAddress(const u32 addr) { |  | ||||||
|     if ((addr & 0x3E000000) == 0x08000000) { |  | ||||||
|         return true; |  | ||||||
|     } else if ((addr & 0x3F800000) == 0x04000000) { |  | ||||||
|         return true; |  | ||||||
|     } else if ((addr & 0xBFFF0000) == 0x00010000) { |  | ||||||
|         return true; |  | ||||||
|     } else if ((addr & 0x3F000000) >= 0x08000000 && (addr & 0x3F000000) < 0x08000000 + MEM_FCRAM_MASK) { |  | ||||||
|         return true; |  | ||||||
|     } else { |  | ||||||
|         return false; |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| u8 *GetPointer(const u32 addr) { | u8 *GetPointer(const u32 addr) { | ||||||
|     // TODO(bunnei): Just a stub for now... ImplementMe!
 |     const u32 vaddr = _AddressPhysicalToVirtual(addr); | ||||||
|     if ((addr & 0x3E000000) == 0x08000000) { |  | ||||||
|         return g_fcram + (addr & MEM_FCRAM_MASK); |  | ||||||
| 
 | 
 | ||||||
|     // HACK(bunnei): There is no layer yet to translate virtual addresses to physical addresses. 
 |     // FCRAM - GSP heap
 | ||||||
|     // Until we progress far enough along, we'll accept all physical address reads here. I think 
 |     if ((vaddr >= HEAP_GSP_VADDR)  && (vaddr < HEAP_GSP_VADDR_END)) { | ||||||
|     // that this is typically a corner-case from usermode software unless they are trying to do 
 |         return g_heap_gsp + (vaddr & HEAP_GSP_MASK); | ||||||
|     // bare-metal things (e.g. early 3DS homebrew writes directly to the FB @ 0x20184E60, etc.
 | 
 | ||||||
|     } else if (((addr & 0xF0000000) == MEM_FCRAM_PADDR) && (addr < (MEM_FCRAM_PADDR_END))) { |     // FCRAM - application heap
 | ||||||
|         return g_fcram + (addr & MEM_FCRAM_MASK); |     } else if ((vaddr >= HEAP_VADDR)  && (vaddr < HEAP_VADDR_END)) { | ||||||
|  |         return g_heap + (vaddr & HEAP_MASK); | ||||||
| 
 | 
 | ||||||
|     //else if ((addr & 0x3F800000) == 0x04000000) {
 |  | ||||||
|     //    return g_vram + (addr & MEM_VRAM_MASK);
 |  | ||||||
|     //}
 |  | ||||||
|     //else if ((addr & 0x3F000000) >= 0x08000000 && (addr & 0x3F000000) < 0x08000000 + g_MemorySize) {
 |  | ||||||
|     //    return m_pRAM + (addr & g_MemoryMask);
 |  | ||||||
|     //}
 |  | ||||||
|     } else { |     } else { | ||||||
|         //ERROR_LOG(MEMMAP, "Unknown GetPointer %08x PC %08x LR %08x", addr, currentMIPS->pc, currentMIPS->r[MIPS_REG_RA]);
 |         ERROR_LOG(MEMMAP, "Unknown GetPointer @ 0x%08x", vaddr); | ||||||
|         ERROR_LOG(MEMMAP, "Unknown GetPointer %08x", addr); |  | ||||||
|         static bool reported = false; |  | ||||||
|         //if (!reported) {
 |  | ||||||
|         //    Reporting::ReportMessage("Unknown GetPointer %08x PC %08x LR %08x", addr, currentMIPS->pc, currentMIPS->r[MIPS_REG_RA]);
 |  | ||||||
|         //    reported = true;
 |  | ||||||
|         //}
 |  | ||||||
|         //if (!g_Config.bIgnoreBadMemAccess) {
 |  | ||||||
|         //    Core_EnableStepping(true);
 |  | ||||||
|         //    host->SetDebugMode(true);
 |  | ||||||
|         //}
 |  | ||||||
|         return 0; |         return 0; | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /**
 | ||||||
|  |  * Maps a block of memory on the GSP heap | ||||||
|  |  * @param size Size of block in bytes | ||||||
|  |  * @param flags Memory allocation flags | ||||||
|  |  */ | ||||||
|  | u32 MapBlock_HeapGSP(u32 size, u32 operation, u32 permissions) { | ||||||
|  |     HeapBlock block; | ||||||
|  |      | ||||||
|  |     block.base_address  = HEAP_GSP_VADDR; | ||||||
|  |     block.size          = size; | ||||||
|  |     block.operation     = operation; | ||||||
|  |     block.permissions   = permissions; | ||||||
|  |      | ||||||
|  |     if (g_heap_gsp_map.size() > 0) { | ||||||
|  |         const HeapBlock last_block = g_heap_gsp_map.rbegin()->second; | ||||||
|  |         block.address = last_block.address + last_block.size; | ||||||
|  |     } | ||||||
|  |     g_heap_gsp_map[block.GetVirtualAddress()] = block; | ||||||
|  | 
 | ||||||
|  |     return block.GetVirtualAddress(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| u8 Read8(const u32 addr) { | u8 Read8(const u32 addr) { | ||||||
|     u8 _var = 0; |     u8 _var = 0; | ||||||
|     _Read<u8>(_var, addr); |     _Read<u8>(_var, addr); | ||||||
|  |  | ||||||
|  | @ -7,6 +7,7 @@ | ||||||
| #include "core/mem_map.h" | #include "core/mem_map.h" | ||||||
| #include "core/system.h" | #include "core/system.h" | ||||||
| #include "core/hw/hw.h" | #include "core/hw/hw.h" | ||||||
|  | #include "core/hle/hle.h" | ||||||
| 
 | 
 | ||||||
| #include "video_core/video_core.h" | #include "video_core/video_core.h" | ||||||
| 
 | 
 | ||||||
|  | @ -19,15 +20,16 @@ void UpdateState(State state) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Init(EmuWindow* emu_window) { | void Init(EmuWindow* emu_window) { | ||||||
| 	Core::Init(); |     Core::Init(); | ||||||
| 	Memory::Init(); |     Memory::Init(); | ||||||
|     HW::Init(); |     HW::Init(); | ||||||
| 	CoreTiming::Init(); |     HLE::Init(); | ||||||
|  |     CoreTiming::Init(); | ||||||
|     VideoCore::Init(emu_window); |     VideoCore::Init(emu_window); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void RunLoopFor(int cycles) { | void RunLoopFor(int cycles) { | ||||||
| 	RunLoopUntil(CoreTiming::GetTicks() + cycles); |     RunLoopUntil(CoreTiming::GetTicks() + cycles); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void RunLoopUntil(u64 global_cycles) { | void RunLoopUntil(u64 global_cycles) { | ||||||
|  | @ -35,9 +37,12 @@ void RunLoopUntil(u64 global_cycles) { | ||||||
| 
 | 
 | ||||||
| void Shutdown() { | void Shutdown() { | ||||||
|     Core::Shutdown(); |     Core::Shutdown(); | ||||||
|  |     Memory::Shutdown(); | ||||||
|     HW::Shutdown(); |     HW::Shutdown(); | ||||||
|  |     HLE::Shutdown(); | ||||||
|  |     CoreTiming::Shutdown(); | ||||||
|     VideoCore::Shutdown(); |     VideoCore::Shutdown(); | ||||||
| 	g_ctr_file_system.Shutdown(); |     g_ctr_file_system.Shutdown(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| } // namespace
 | } // namespace
 | ||||||
|  |  | ||||||
|  | @ -2,6 +2,8 @@ | ||||||
| // Licensed under GPLv2
 | // Licensed under GPLv2
 | ||||||
| // Refer to the license.txt file included.
 | // Refer to the license.txt file included.
 | ||||||
| 
 | 
 | ||||||
|  | #include "core/hw/lcd.h" | ||||||
|  | 
 | ||||||
| #include "video_core/video_core.h" | #include "video_core/video_core.h" | ||||||
| #include "video_core/renderer_opengl/renderer_opengl.h" | #include "video_core/renderer_opengl/renderer_opengl.h" | ||||||
| 
 | 
 | ||||||
|  | @ -75,8 +77,8 @@ void RendererOpenGL::FlipFramebuffer(u32 addr, u8* out) { | ||||||
|  */ |  */ | ||||||
| void RendererOpenGL::RenderXFB(const Rect& src_rect, const Rect& dst_rect) {   | void RendererOpenGL::RenderXFB(const Rect& src_rect, const Rect& dst_rect) {   | ||||||
| 
 | 
 | ||||||
|     FlipFramebuffer(0x20282160, m_xfb_top_flipped); |     FlipFramebuffer(LCD::TOP_RIGHT_FRAME1,  m_xfb_top_flipped); | ||||||
|     FlipFramebuffer(0x202118E0, m_xfb_bottom_flipped); |     FlipFramebuffer(LCD::SUB_FRAME1,        m_xfb_bottom_flipped); | ||||||
| 
 | 
 | ||||||
|     // Blit the top framebuffer
 |     // Blit the top framebuffer
 | ||||||
|     // ------------------------
 |     // ------------------------
 | ||||||
|  | @ -84,7 +86,7 @@ void RendererOpenGL::RenderXFB(const Rect& src_rect, const Rect& dst_rect) { | ||||||
|     // Update textures with contents of XFB in RAM - top
 |     // Update textures with contents of XFB in RAM - top
 | ||||||
|     glBindTexture(GL_TEXTURE_2D, m_xfb_texture_top); |     glBindTexture(GL_TEXTURE_2D, m_xfb_texture_top); | ||||||
|     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, VideoCore::kScreenTopWidth, VideoCore::kScreenTopHeight, |     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, VideoCore::kScreenTopWidth, VideoCore::kScreenTopHeight, | ||||||
|         GL_RGB, GL_UNSIGNED_BYTE, m_xfb_top_flipped); |         GL_BGR, GL_UNSIGNED_BYTE, m_xfb_top_flipped); | ||||||
|     glBindTexture(GL_TEXTURE_2D, 0); |     glBindTexture(GL_TEXTURE_2D, 0); | ||||||
| 
 | 
 | ||||||
|     // Render target is destination framebuffer
 |     // Render target is destination framebuffer
 | ||||||
|  |  | ||||||
|  | @ -38,12 +38,13 @@ void Init(EmuWindow* emu_window) { | ||||||
| 
 | 
 | ||||||
|     g_current_frame = 0; |     g_current_frame = 0; | ||||||
| 
 | 
 | ||||||
|     NOTICE_LOG(VIDEO, "initialized ok"); |     NOTICE_LOG(VIDEO, "initialized OK"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// Shutdown the video core
 | /// Shutdown the video core
 | ||||||
| void Shutdown() { | void Shutdown() { | ||||||
|     delete g_renderer; |     delete g_renderer; | ||||||
|  |     NOTICE_LOG(VIDEO, "shutdown OK"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| } // namespace
 | } // namespace
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue