1 #include <cstring>
2 #include "Iop_SifCmd.h"
3 #include "IopBios.h"
4 #include "../ee/SIF.h"
5 #include "../Log.h"
6 #include "../states/StructCollectionStateFile.h"
7 
8 using namespace Iop;
9 
10 #define LOG_NAME ("iop_sifcmd")
11 #define STATE_MODULES ("iop_sifcmd/modules.xml")
12 #define STATE_MODULE ("Module")
13 #define STATE_MODULE_SERVER_DATA_ADDRESS ("ServerDataAddress")
14 
15 #define CUSTOM_FINISHEXECREQUEST 0x666
16 #define CUSTOM_FINISHEXECCMD 0x667
17 #define CUSTOM_FINISHBINDRPC 0x668
18 #define CUSTOM_SLEEPTHREAD 0x669
19 #define CUSTOM_DELAYTHREAD 0x66A
20 
21 #define MODULE_NAME "sifcmd"
22 #define MODULE_VERSION 0x101
23 
24 #define FUNCTION_SIFGETSREG "SifGetSreg"
25 #define FUNCTION_SIFSETCMDBUFFER "SifSetCmdBuffer"
26 #define FUNCTION_SIFADDCMDHANDLER "SifAddCmdHandler"
27 #define FUNCTION_SIFSENDCMD "SifSendCmd"
28 #define FUNCTION_ISIFSENDCMD "iSifSendCmd"
29 #define FUNCTION_SIFINITRPC "SifInitRpc"
30 #define FUNCTION_SIFBINDRPC "SifBindRpc"
31 #define FUNCTION_SIFCALLRPC "SifCallRpc"
32 #define FUNCTION_SIFREGISTERRPC "SifRegisterRpc"
33 #define FUNCTION_SIFCHECKSTATRPC "SifCheckStatRpc"
34 #define FUNCTION_SIFSETRPCQUEUE "SifSetRpcQueue"
35 #define FUNCTION_SIFGETNEXTREQUEST "SifGetNextRequest"
36 #define FUNCTION_SIFEXECREQUEST "SifExecRequest"
37 #define FUNCTION_SIFRPCLOOP "SifRpcLoop"
38 #define FUNCTION_SIFGETOTHERDATA "SifGetOtherData"
39 #define FUNCTION_SIFREMOVERPC "SifRemoveRpc"
40 #define FUNCTION_SIFREMOVERPCQUEUE "SifRemoveRpcQueue"
41 #define FUNCTION_SIFSENDCMDINTR "SifSendCmdIntr"
42 #define FUNCTION_FINISHEXECREQUEST "FinishExecRequest"
43 #define FUNCTION_FINISHEXECCMD "FinishExecCmd"
44 #define FUNCTION_FINISHBINDRPC "FinishBindRpc"
45 #define FUNCTION_SLEEPTHREAD "SleepThread"
46 #define FUNCTION_DELAYTHREAD "DelayThread"
47 
48 #define SYSTEM_COMMAND_ID 0x80000000
49 
CSifCmd(CIopBios & bios,CSifMan & sifMan,CSysmem & sysMem,uint8 * ram)50 CSifCmd::CSifCmd(CIopBios& bios, CSifMan& sifMan, CSysmem& sysMem, uint8* ram)
51     : m_bios(bios)
52     , m_sifMan(sifMan)
53     , m_sysMem(sysMem)
54     , m_ram(ram)
55 {
56 	m_moduleDataAddr = m_sysMem.AllocateMemory(sizeof(MODULEDATA), 0, 0);
57 	memset(m_ram + m_moduleDataAddr, 0, sizeof(MODULEDATA));
58 	m_trampolineAddr = m_moduleDataAddr + offsetof(MODULEDATA, trampoline);
59 	m_sendCmdExtraStructAddr = m_moduleDataAddr + offsetof(MODULEDATA, sendCmdExtraStruct);
60 	m_sysCmdBufferAddr = m_moduleDataAddr + offsetof(MODULEDATA, sysCmdBuffer);
61 	sifMan.SetModuleResetHandler([&](const std::string& path) { bios.ProcessModuleReset(path); });
62 	sifMan.SetCustomCommandHandler([&](uint32 commandHeaderAddr) { ProcessCustomCommand(commandHeaderAddr); });
63 	BuildExportTable();
64 }
65 
~CSifCmd()66 CSifCmd::~CSifCmd()
67 {
68 	ClearServers();
69 }
70 
LoadState(Framework::CZipArchiveReader & archive)71 void CSifCmd::LoadState(Framework::CZipArchiveReader& archive)
72 {
73 	ClearServers();
74 
75 	auto modulesFile = CStructCollectionStateFile(*archive.BeginReadFile(STATE_MODULES));
76 	{
77 		for(CStructCollectionStateFile::StructIterator structIterator(modulesFile.GetStructBegin());
78 		    structIterator != modulesFile.GetStructEnd(); ++structIterator)
79 		{
80 			const auto& structFile(structIterator->second);
81 			uint32 serverDataAddress = structFile.GetRegister32(STATE_MODULE_SERVER_DATA_ADDRESS);
82 			auto serverData = reinterpret_cast<SIFRPCSERVERDATA*>(m_ram + serverDataAddress);
83 			auto module = new CSifDynamic(*this, serverDataAddress);
84 			m_servers.push_back(module);
85 			m_sifMan.RegisterModule(serverData->serverId, module);
86 		}
87 	}
88 }
89 
SaveState(Framework::CZipArchiveWriter & archive) const90 void CSifCmd::SaveState(Framework::CZipArchiveWriter& archive) const
91 {
92 	auto modulesFile = new CStructCollectionStateFile(STATE_MODULES);
93 	{
94 		int moduleIndex = 0;
95 		for(const auto& module : m_servers)
96 		{
97 			auto moduleName = std::string(STATE_MODULE) + std::to_string(moduleIndex++);
98 			CStructFile moduleStruct;
99 			{
100 				uint32 serverDataAddress = module->GetServerDataAddress();
101 				moduleStruct.SetRegister32(STATE_MODULE_SERVER_DATA_ADDRESS, serverDataAddress);
102 			}
103 			modulesFile->InsertStruct(moduleName.c_str(), moduleStruct);
104 		}
105 	}
106 	archive.InsertFile(modulesFile);
107 }
108 
GetId() const109 std::string CSifCmd::GetId() const
110 {
111 	return MODULE_NAME;
112 }
113 
GetFunctionName(unsigned int functionId) const114 std::string CSifCmd::GetFunctionName(unsigned int functionId) const
115 {
116 	switch(functionId)
117 	{
118 	case 6:
119 		return FUNCTION_SIFGETSREG;
120 		break;
121 	case 8:
122 		return FUNCTION_SIFSETCMDBUFFER;
123 		break;
124 	case 10:
125 		return FUNCTION_SIFADDCMDHANDLER;
126 		break;
127 	case 12:
128 		return FUNCTION_SIFSENDCMD;
129 		break;
130 	case 13:
131 		return FUNCTION_ISIFSENDCMD;
132 		break;
133 	case 14:
134 		return FUNCTION_SIFINITRPC;
135 		break;
136 	case 15:
137 		return FUNCTION_SIFBINDRPC;
138 		break;
139 	case 16:
140 		return FUNCTION_SIFCALLRPC;
141 		break;
142 	case 17:
143 		return FUNCTION_SIFREGISTERRPC;
144 		break;
145 	case 18:
146 		return FUNCTION_SIFCHECKSTATRPC;
147 		break;
148 	case 19:
149 		return FUNCTION_SIFSETRPCQUEUE;
150 		break;
151 	case 20:
152 		return FUNCTION_SIFGETNEXTREQUEST;
153 		break;
154 	case 21:
155 		return FUNCTION_SIFEXECREQUEST;
156 		break;
157 	case 22:
158 		return FUNCTION_SIFRPCLOOP;
159 		break;
160 	case 23:
161 		return FUNCTION_SIFGETOTHERDATA;
162 		break;
163 	case 24:
164 		return FUNCTION_SIFREMOVERPC;
165 		break;
166 	case 25:
167 		return FUNCTION_SIFREMOVERPCQUEUE;
168 		break;
169 	case 28:
170 		return FUNCTION_SIFSENDCMDINTR;
171 		break;
172 	case CUSTOM_FINISHEXECREQUEST:
173 		return FUNCTION_FINISHEXECREQUEST;
174 		break;
175 	case CUSTOM_FINISHEXECCMD:
176 		return FUNCTION_FINISHEXECCMD;
177 		break;
178 	case CUSTOM_FINISHBINDRPC:
179 		return FUNCTION_FINISHBINDRPC;
180 		break;
181 	case CUSTOM_SLEEPTHREAD:
182 		return FUNCTION_SLEEPTHREAD;
183 		break;
184 	case CUSTOM_DELAYTHREAD:
185 		return FUNCTION_DELAYTHREAD;
186 		break;
187 	default:
188 		return "unknown";
189 		break;
190 	}
191 }
192 
Invoke(CMIPS & context,unsigned int functionId)193 void CSifCmd::Invoke(CMIPS& context, unsigned int functionId)
194 {
195 	switch(functionId)
196 	{
197 	case 6:
198 		context.m_State.nGPR[CMIPS::V0].nV0 = SifGetSreg(
199 		    context.m_State.nGPR[CMIPS::A0].nV0);
200 		break;
201 	case 8:
202 		context.m_State.nGPR[CMIPS::V0].nV0 = SifSetCmdBuffer(
203 		    context.m_State.nGPR[CMIPS::A0].nV0,
204 		    context.m_State.nGPR[CMIPS::A1].nV0);
205 		break;
206 	case 10:
207 		SifAddCmdHandler(
208 		    context.m_State.nGPR[CMIPS::A0].nV0,
209 		    context.m_State.nGPR[CMIPS::A1].nV0,
210 		    context.m_State.nGPR[CMIPS::A2].nV0);
211 		break;
212 	case 12:
213 	case 13:
214 		context.m_State.nGPR[CMIPS::V0].nV0 = SifSendCmd(
215 		    context.m_State.nGPR[CMIPS::A0].nV0,
216 		    context.m_State.nGPR[CMIPS::A1].nV0,
217 		    context.m_State.nGPR[CMIPS::A2].nV0,
218 		    context.m_State.nGPR[CMIPS::A3].nV0,
219 		    context.m_pMemoryMap->GetWord(context.m_State.nGPR[CMIPS::SP].nV0 + 0x10),
220 		    context.m_pMemoryMap->GetWord(context.m_State.nGPR[CMIPS::SP].nV0 + 0x14));
221 		break;
222 	case 14:
223 		CLog::GetInstance().Print(LOG_NAME, FUNCTION_SIFINITRPC "();\r\n");
224 		break;
225 	case 15:
226 		SifBindRpc(context);
227 		break;
228 	case 16:
229 		SifCallRpc(context);
230 		break;
231 	case 17:
232 		SifRegisterRpc(context);
233 		break;
234 	case 18:
235 		context.m_State.nGPR[CMIPS::V0].nV0 = SifCheckStatRpc(
236 		    context.m_State.nGPR[CMIPS::A0].nV0);
237 		break;
238 	case 19:
239 		SifSetRpcQueue(context.m_State.nGPR[CMIPS::A0].nV0,
240 		               context.m_State.nGPR[CMIPS::A1].nV0);
241 		break;
242 	case 20:
243 		context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(SifGetNextRequest(
244 		    context.m_State.nGPR[CMIPS::A0].nV0));
245 		break;
246 	case 21:
247 		SifExecRequest(context);
248 		break;
249 	case 22:
250 		SifRpcLoop(context);
251 		break;
252 	case 23:
253 		context.m_State.nGPR[CMIPS::V0].nV0 = SifGetOtherData(
254 		    context.m_State.nGPR[CMIPS::A0].nV0,
255 		    context.m_State.nGPR[CMIPS::A1].nV0,
256 		    context.m_State.nGPR[CMIPS::A2].nV0,
257 		    context.m_State.nGPR[CMIPS::A3].nV0,
258 		    context.m_pMemoryMap->GetWord(context.m_State.nGPR[CMIPS::SP].nV0 + 0x10));
259 		break;
260 	case 24:
261 		context.m_State.nGPR[CMIPS::V0].nV0 = SifRemoveRpc(
262 		    context.m_State.nGPR[CMIPS::A0].nV0,
263 		    context.m_State.nGPR[CMIPS::A1].nV0);
264 		break;
265 	case 25:
266 		context.m_State.nGPR[CMIPS::V0].nV0 = SifRemoveRpcQueue(
267 		    context.m_State.nGPR[CMIPS::A0].nV0);
268 		break;
269 	case 28:
270 		context.m_State.nGPR[CMIPS::V0].nV0 = SifSendCmdIntr(
271 		    context.m_State.nGPR[CMIPS::A0].nV0,
272 		    context.m_State.nGPR[CMIPS::A1].nV0,
273 		    context.m_State.nGPR[CMIPS::A2].nV0,
274 		    context.m_State.nGPR[CMIPS::A3].nV0,
275 		    context.m_pMemoryMap->GetWord(context.m_State.nGPR[CMIPS::SP].nV0 + 0x10),
276 		    context.m_pMemoryMap->GetWord(context.m_State.nGPR[CMIPS::SP].nV0 + 0x14),
277 		    context.m_pMemoryMap->GetWord(context.m_State.nGPR[CMIPS::SP].nV0 + 0x18),
278 		    context.m_pMemoryMap->GetWord(context.m_State.nGPR[CMIPS::SP].nV0 + 0x1C));
279 		break;
280 	case CUSTOM_FINISHEXECREQUEST:
281 		FinishExecRequest(
282 		    context.m_State.nGPR[CMIPS::A0].nV0,
283 		    context.m_State.nGPR[CMIPS::A1].nV0);
284 		break;
285 	case CUSTOM_FINISHBINDRPC:
286 		FinishBindRpc(
287 		    context.m_State.nGPR[CMIPS::A0].nV0,
288 		    context.m_State.nGPR[CMIPS::A1].nV0);
289 		break;
290 	case CUSTOM_FINISHEXECCMD:
291 		FinishExecCmd();
292 		break;
293 	case CUSTOM_SLEEPTHREAD:
294 		SleepThread();
295 		break;
296 	case CUSTOM_DELAYTHREAD:
297 		DelayThread(
298 		    context.m_State.nGPR[CMIPS::A0].nV0);
299 		break;
300 	default:
301 		CLog::GetInstance().Warn(LOG_NAME, "Unknown function called (%d).\r\n",
302 		                         functionId);
303 		break;
304 	}
305 }
306 
ClearServers()307 void CSifCmd::ClearServers()
308 {
309 	for(const auto& server : m_servers)
310 	{
311 		auto serverData = reinterpret_cast<SIFRPCSERVERDATA*>(m_ram + server->GetServerDataAddress());
312 		m_sifMan.UnregisterModule(serverData->serverId);
313 		delete server;
314 	}
315 	m_servers.clear();
316 }
317 
BuildExportTable()318 void CSifCmd::BuildExportTable()
319 {
320 	auto exportTable = reinterpret_cast<uint32*>(m_ram + m_trampolineAddr);
321 	*(exportTable++) = 0x41E00000;
322 	*(exportTable++) = 0;
323 	*(exportTable++) = MODULE_VERSION;
324 	strcpy(reinterpret_cast<char*>(exportTable), MODULE_NAME);
325 	exportTable += (strlen(MODULE_NAME) + 3) / 4;
326 
327 	{
328 		CMIPSAssembler assembler(exportTable);
329 
330 		//Trampoline for SifGetNextRequest
331 		uint32 sifGetNextRequestAddr = (reinterpret_cast<uint8*>(exportTable) - m_ram) + (assembler.GetProgramSize() * 4);
332 		assembler.JR(CMIPS::RA);
333 		assembler.ADDIU(CMIPS::R0, CMIPS::R0, 20);
334 
335 		//Trampoline for SifExecRequest
336 		uint32 sifExecRequestAddr = (reinterpret_cast<uint8*>(exportTable) - m_ram) + (assembler.GetProgramSize() * 4);
337 		assembler.JR(CMIPS::RA);
338 		assembler.ADDIU(CMIPS::R0, CMIPS::R0, 21);
339 
340 		uint32 finishExecRequestAddr = (reinterpret_cast<uint8*>(exportTable) - m_ram) + (assembler.GetProgramSize() * 4);
341 		assembler.JR(CMIPS::RA);
342 		assembler.ADDIU(CMIPS::R0, CMIPS::R0, CUSTOM_FINISHEXECREQUEST);
343 
344 		uint32 finishExecCmdAddr = (reinterpret_cast<uint8*>(exportTable) - m_ram) + (assembler.GetProgramSize() * 4);
345 		assembler.JR(CMIPS::RA);
346 		assembler.ADDIU(CMIPS::R0, CMIPS::R0, CUSTOM_FINISHEXECCMD);
347 
348 		uint32 finishBindRpcAddr = (reinterpret_cast<uint8*>(exportTable) - m_ram) + (assembler.GetProgramSize() * 4);
349 		assembler.JR(CMIPS::RA);
350 		assembler.ADDIU(CMIPS::R0, CMIPS::R0, CUSTOM_FINISHBINDRPC);
351 
352 		uint32 sleepThreadAddr = (reinterpret_cast<uint8*>(exportTable) - m_ram) + (assembler.GetProgramSize() * 4);
353 		assembler.JR(CMIPS::RA);
354 		assembler.ADDIU(CMIPS::R0, CMIPS::R0, CUSTOM_SLEEPTHREAD);
355 
356 		uint32 delayThreadAddr = (reinterpret_cast<uint8*>(exportTable) - m_ram) + (assembler.GetProgramSize() * 4);
357 		assembler.JR(CMIPS::RA);
358 		assembler.ADDIU(CMIPS::R0, CMIPS::R0, CUSTOM_DELAYTHREAD);
359 
360 		//Assemble SifRpcLoop
361 		{
362 			static const int16 stackAlloc = 0x10;
363 
364 			m_sifRpcLoopAddr = (reinterpret_cast<uint8*>(exportTable) - m_ram) + (assembler.GetProgramSize() * 4);
365 			auto checkNextRequestLabel = assembler.CreateLabel();
366 			auto sleepThreadLabel = assembler.CreateLabel();
367 
368 			assembler.ADDIU(CMIPS::SP, CMIPS::SP, -stackAlloc);
369 			assembler.SW(CMIPS::RA, 0x00, CMIPS::SP);
370 			assembler.SW(CMIPS::S0, 0x04, CMIPS::SP);
371 			assembler.ADDU(CMIPS::S0, CMIPS::A0, CMIPS::R0);
372 
373 			//checkNextRequest:
374 			assembler.MarkLabel(checkNextRequestLabel);
375 			assembler.JAL(sifGetNextRequestAddr);
376 			assembler.ADDU(CMIPS::A0, CMIPS::S0, CMIPS::R0);
377 			assembler.BEQ(CMIPS::V0, CMIPS::R0, sleepThreadLabel);
378 			assembler.NOP();
379 
380 			assembler.JAL(sifExecRequestAddr);
381 			assembler.ADDU(CMIPS::A0, CMIPS::V0, CMIPS::R0);
382 
383 			//sleepThread:
384 			assembler.MarkLabel(sleepThreadLabel);
385 			assembler.JAL(sleepThreadAddr);
386 			assembler.NOP();
387 			assembler.BEQ(CMIPS::R0, CMIPS::R0, checkNextRequestLabel);
388 			assembler.NOP();
389 
390 			assembler.LW(CMIPS::S0, 0x04, CMIPS::SP);
391 			assembler.LW(CMIPS::RA, 0x00, CMIPS::SP);
392 			assembler.JR(CMIPS::RA);
393 			assembler.ADDIU(CMIPS::SP, CMIPS::SP, stackAlloc);
394 		}
395 
396 		//Assemble SifExecRequest
397 		{
398 			static const int16 stackAlloc = 0x20;
399 
400 			m_sifExecRequestAddr = (reinterpret_cast<uint8*>(exportTable) - m_ram) + (assembler.GetProgramSize() * 4);
401 
402 			assembler.ADDIU(CMIPS::SP, CMIPS::SP, -stackAlloc);
403 			assembler.SW(CMIPS::RA, 0x1C, CMIPS::SP);
404 			assembler.SW(CMIPS::S0, 0x18, CMIPS::SP);
405 			assembler.ADDU(CMIPS::S0, CMIPS::A0, CMIPS::R0);
406 
407 			assembler.LW(CMIPS::A0, offsetof(SIFRPCSERVERDATA, rid), CMIPS::S0);
408 			assembler.LW(CMIPS::A1, offsetof(SIFRPCSERVERDATA, buffer), CMIPS::S0);
409 			assembler.LW(CMIPS::A2, offsetof(SIFRPCSERVERDATA, rsize), CMIPS::S0);
410 			assembler.LW(CMIPS::T0, offsetof(SIFRPCSERVERDATA, function), CMIPS::S0);
411 			assembler.JALR(CMIPS::T0);
412 			assembler.NOP();
413 
414 			assembler.ADDU(CMIPS::A0, CMIPS::S0, CMIPS::R0);
415 			assembler.JAL(finishExecRequestAddr);
416 			assembler.ADDU(CMIPS::A1, CMIPS::V0, CMIPS::R0);
417 
418 			assembler.LW(CMIPS::S0, 0x18, CMIPS::SP);
419 			assembler.LW(CMIPS::RA, 0x1C, CMIPS::SP);
420 			assembler.JR(CMIPS::RA);
421 			assembler.ADDIU(CMIPS::SP, CMIPS::SP, stackAlloc);
422 		}
423 
424 		//Assemble SifExecCmdHandler
425 		{
426 			static const int16 stackAlloc = 0x20;
427 
428 			m_sifExecCmdHandlerAddr = (reinterpret_cast<uint8*>(exportTable) - m_ram) + (assembler.GetProgramSize() * 4);
429 
430 			assembler.ADDIU(CMIPS::SP, CMIPS::SP, -stackAlloc);
431 			assembler.SW(CMIPS::RA, 0x1C, CMIPS::SP);
432 			assembler.SW(CMIPS::S0, 0x18, CMIPS::SP);
433 			assembler.ADDU(CMIPS::S0, CMIPS::A0, CMIPS::R0);
434 
435 			assembler.ADDU(CMIPS::A0, CMIPS::A1, CMIPS::R0); //A0 = Packet Address
436 			assembler.LW(CMIPS::A1, offsetof(SIFCMDDATA, data), CMIPS::S0);
437 			assembler.LW(CMIPS::T0, offsetof(SIFCMDDATA, sifCmdHandler), CMIPS::S0);
438 			assembler.JALR(CMIPS::T0);
439 			assembler.NOP();
440 
441 			assembler.JAL(finishExecCmdAddr);
442 			assembler.NOP();
443 
444 			assembler.LW(CMIPS::S0, 0x18, CMIPS::SP);
445 			assembler.LW(CMIPS::RA, 0x1C, CMIPS::SP);
446 			assembler.JR(CMIPS::RA);
447 			assembler.ADDIU(CMIPS::SP, CMIPS::SP, stackAlloc);
448 		}
449 
450 		//Assemble SifBindRpc
451 		{
452 			static const int16 stackAlloc = 0x20;
453 
454 			m_sifBindRpcAddr = (reinterpret_cast<uint8*>(exportTable) - m_ram) + (assembler.GetProgramSize() * 4);
455 
456 			assembler.ADDIU(CMIPS::SP, CMIPS::SP, -stackAlloc);
457 			assembler.SW(CMIPS::RA, 0x1C, CMIPS::SP);
458 			assembler.SW(CMIPS::S0, 0x18, CMIPS::SP);
459 			assembler.SW(CMIPS::S1, 0x14, CMIPS::SP);
460 			assembler.ADDU(CMIPS::S0, CMIPS::A0, CMIPS::R0);
461 			assembler.ADDU(CMIPS::S1, CMIPS::A1, CMIPS::R0);
462 
463 			assembler.LI(CMIPS::A0, 500);
464 			assembler.JAL(delayThreadAddr);
465 			assembler.NOP();
466 
467 			assembler.ADDU(CMIPS::A0, CMIPS::S0, CMIPS::R0);
468 			assembler.ADDU(CMIPS::A1, CMIPS::S1, CMIPS::R0);
469 			assembler.JAL(finishBindRpcAddr);
470 			assembler.NOP();
471 
472 			assembler.ADDU(CMIPS::V0, CMIPS::R0, CMIPS::R0);
473 
474 			assembler.LW(CMIPS::S1, 0x14, CMIPS::SP);
475 			assembler.LW(CMIPS::S0, 0x18, CMIPS::SP);
476 			assembler.LW(CMIPS::RA, 0x1C, CMIPS::SP);
477 			assembler.JR(CMIPS::RA);
478 			assembler.ADDIU(CMIPS::SP, CMIPS::SP, stackAlloc);
479 		}
480 	}
481 }
482 
ProcessInvocation(uint32 serverDataAddr,uint32 methodId,uint32 * params,uint32 size)483 void CSifCmd::ProcessInvocation(uint32 serverDataAddr, uint32 methodId, uint32* params, uint32 size)
484 {
485 	auto serverData = reinterpret_cast<SIFRPCSERVERDATA*>(m_ram + serverDataAddr);
486 	auto queueData = reinterpret_cast<SIFRPCQUEUEDATA*>(m_ram + serverData->queueAddr);
487 
488 	//Copy params
489 	if(serverData->buffer != 0)
490 	{
491 		memcpy(&m_ram[serverData->buffer], params, size);
492 	}
493 	serverData->rid = methodId;
494 	serverData->rsize = size;
495 
496 	assert(queueData->serverDataLink == 0);
497 	assert(queueData->serverDataStart == serverDataAddr);
498 	queueData->serverDataLink = serverDataAddr;
499 
500 	auto thread = m_bios.GetThread(queueData->threadId);
501 	assert(thread->status == CIopBios::THREAD_STATUS_SLEEPING);
502 	m_bios.WakeupThread(queueData->threadId, true);
503 	m_bios.Reschedule();
504 }
505 
FinishExecRequest(uint32 serverDataAddr,uint32 returnDataAddr)506 void CSifCmd::FinishExecRequest(uint32 serverDataAddr, uint32 returnDataAddr)
507 {
508 	auto serverData = reinterpret_cast<SIFRPCSERVERDATA*>(m_ram + serverDataAddr);
509 	auto returnData = m_ram + returnDataAddr;
510 	m_sifMan.SendCallReply(serverData->serverId, returnData);
511 }
512 
FinishExecCmd()513 void CSifCmd::FinishExecCmd()
514 {
515 	auto moduleData = reinterpret_cast<MODULEDATA*>(m_ram + m_moduleDataAddr);
516 
517 	assert(moduleData->executingCmd);
518 	moduleData->executingCmd = false;
519 
520 	auto pendingCmdBuffer = moduleData->pendingCmdBuffer;
521 	auto commandHeader = reinterpret_cast<const SIFCMDHEADER*>(pendingCmdBuffer);
522 
523 	uint8 commandPacketSize = commandHeader->packetSize;
524 	assert(moduleData->pendingCmdBufferSize >= commandPacketSize);
525 	memmove(pendingCmdBuffer, pendingCmdBuffer + commandPacketSize, PENDING_CMD_BUFFER_SIZE - moduleData->pendingCmdBufferSize);
526 	moduleData->pendingCmdBufferSize -= commandPacketSize;
527 
528 	if(moduleData->pendingCmdBufferSize > 0)
529 	{
530 		ProcessNextDynamicCommand();
531 	}
532 }
533 
FinishBindRpc(uint32 clientDataAddr,uint32 serverId)534 void CSifCmd::FinishBindRpc(uint32 clientDataAddr, uint32 serverId)
535 {
536 	auto clientData = reinterpret_cast<SIFRPCCLIENTDATA*>(m_ram + clientDataAddr);
537 	clientData->serverDataAddr = serverId;
538 	clientData->header.semaId = m_bios.CreateSemaphore(0, 1);
539 
540 	int32 result = CIopBios::KERNEL_RESULT_OK;
541 	result = m_bios.WaitSemaphore(clientData->header.semaId);
542 	assert(result == CIopBios::KERNEL_RESULT_OK);
543 
544 	SIFRPCBIND bindPacket;
545 	memset(&bindPacket, 0, sizeof(SIFRPCBIND));
546 	bindPacket.header.commandId = SIF_CMD_BIND;
547 	bindPacket.header.packetSize = sizeof(SIFRPCBIND);
548 	bindPacket.serverId = serverId;
549 	bindPacket.clientDataAddr = clientDataAddr;
550 	m_sifMan.SendPacket(&bindPacket, sizeof(bindPacket));
551 }
552 
ProcessCustomCommand(uint32 commandHeaderAddr)553 void CSifCmd::ProcessCustomCommand(uint32 commandHeaderAddr)
554 {
555 	auto commandHeader = reinterpret_cast<const SIFCMDHEADER*>(m_ram + commandHeaderAddr);
556 	switch(commandHeader->commandId)
557 	{
558 	case SIF_CMD_SETSREG:
559 		ProcessSetSreg(commandHeaderAddr);
560 		break;
561 	case 0x80000004:
562 		//No clue what this is used for, but seems to be used after "WriteToIop" is used.
563 		//Could be FlushCache or something like that
564 		break;
565 	case SIF_CMD_REND:
566 		ProcessRpcRequestEnd(commandHeaderAddr);
567 		break;
568 	default:
569 		ProcessDynamicCommand(commandHeaderAddr);
570 		break;
571 	}
572 }
573 
ProcessSetSreg(uint32 commandHeaderAddr)574 void CSifCmd::ProcessSetSreg(uint32 commandHeaderAddr)
575 {
576 	auto setSreg = reinterpret_cast<const SIFSETSREG*>(m_ram + commandHeaderAddr);
577 	assert(setSreg->header.packetSize == sizeof(SIFSETSREG));
578 	assert(setSreg->index < MAX_SREG);
579 	if(setSreg->index >= MAX_SREG) return;
580 	auto moduleData = reinterpret_cast<MODULEDATA*>(m_ram + m_moduleDataAddr);
581 	moduleData->sreg[setSreg->index] = setSreg->value;
582 }
583 
ProcessRpcRequestEnd(uint32 commandHeaderAddr)584 void CSifCmd::ProcessRpcRequestEnd(uint32 commandHeaderAddr)
585 {
586 	auto requestEnd = reinterpret_cast<const SIFRPCREQUESTEND*>(m_ram + commandHeaderAddr);
587 	assert(requestEnd->clientDataAddr != 0);
588 	auto clientData = reinterpret_cast<SIFRPCCLIENTDATA*>(m_ram + requestEnd->clientDataAddr);
589 	if(requestEnd->commandId == SIF_CMD_BIND)
590 	{
591 		//When serverDataAddr is 0, EE failed to find requested server ID
592 		assert(requestEnd->serverDataAddr != 0);
593 		clientData->serverDataAddr = requestEnd->serverDataAddr;
594 		clientData->buffPtr = requestEnd->buffer;
595 		clientData->cbuffPtr = requestEnd->cbuffer;
596 	}
597 	else if(requestEnd->commandId == SIF_CMD_CALL)
598 	{
599 		if(clientData->endFctPtr != 0)
600 		{
601 			m_bios.TriggerCallback(clientData->endFctPtr, clientData->endParam);
602 		}
603 	}
604 	else
605 	{
606 		assert(0);
607 	}
608 	//Unlock/delete semaphore
609 	{
610 		assert(clientData->header.semaId != 0);
611 		int32 result = CIopBios::KERNEL_RESULT_OK;
612 		result = m_bios.SignalSemaphore(clientData->header.semaId, true);
613 		assert(result == CIopBios::KERNEL_RESULT_OK);
614 		result = m_bios.DeleteSemaphore(clientData->header.semaId);
615 		assert(result == CIopBios::KERNEL_RESULT_OK);
616 		clientData->header.semaId = 0;
617 	}
618 }
619 
ProcessDynamicCommand(uint32 commandHeaderAddr)620 void CSifCmd::ProcessDynamicCommand(uint32 commandHeaderAddr)
621 {
622 	auto moduleData = reinterpret_cast<MODULEDATA*>(m_ram + m_moduleDataAddr);
623 	auto commandHeader = reinterpret_cast<const SIFCMDHEADER*>(m_ram + commandHeaderAddr);
624 
625 	uint8 commandPacketSize = commandHeader->packetSize;
626 	assert((moduleData->pendingCmdBufferSize + commandPacketSize) <= PENDING_CMD_BUFFER_SIZE);
627 
628 	if((moduleData->pendingCmdBufferSize + commandPacketSize) <= PENDING_CMD_BUFFER_SIZE)
629 	{
630 		memcpy(moduleData->pendingCmdBuffer + moduleData->pendingCmdBufferSize, commandHeader, commandPacketSize);
631 		moduleData->pendingCmdBufferSize += commandPacketSize;
632 
633 		if(!moduleData->executingCmd)
634 		{
635 			ProcessNextDynamicCommand();
636 		}
637 	}
638 }
639 
ProcessNextDynamicCommand()640 void CSifCmd::ProcessNextDynamicCommand()
641 {
642 	auto moduleData = reinterpret_cast<MODULEDATA*>(m_ram + m_moduleDataAddr);
643 
644 	assert(!moduleData->executingCmd);
645 	moduleData->executingCmd = true;
646 
647 	uint32 commandHeaderAddr = m_moduleDataAddr + offsetof(MODULEDATA, pendingCmdBuffer);
648 	auto commandHeader = reinterpret_cast<const SIFCMDHEADER*>(m_ram + commandHeaderAddr);
649 	bool isSystemCommand = (commandHeader->commandId & SYSTEM_COMMAND_ID) != 0;
650 	uint32 cmd = commandHeader->commandId & ~SYSTEM_COMMAND_ID;
651 	uint32 cmdBufferAddr = isSystemCommand ? m_sysCmdBufferAddr : moduleData->usrCmdBufferAddr;
652 	uint32 cmdBufferLen = isSystemCommand ? MAX_SYSTEM_COMMAND : moduleData->usrCmdBufferLen;
653 
654 	if((cmdBufferAddr != 0) && (cmd < cmdBufferLen))
655 	{
656 		const auto& cmdDataEntry = reinterpret_cast<SIFCMDDATA*>(m_ram + cmdBufferAddr)[cmd];
657 
658 		CLog::GetInstance().Print(LOG_NAME, "Calling SIF command handler for command 0x%08X at 0x%08X with data 0x%08X.\r\n",
659 		                          commandHeader->commandId, cmdDataEntry.sifCmdHandler, cmdDataEntry.data);
660 
661 		assert(cmdDataEntry.sifCmdHandler != 0);
662 		if(cmdDataEntry.sifCmdHandler != 0)
663 		{
664 			//This expects to be in an interrupt and the handler is called in the interrupt.
665 			//That's not the case here though, so we try for the same effect by calling the handler outside of an interrupt.
666 			uint32 cmdDataEntryAddr = reinterpret_cast<const uint8*>(&cmdDataEntry) - m_ram;
667 			m_bios.TriggerCallback(m_sifExecCmdHandlerAddr, cmdDataEntryAddr, commandHeaderAddr);
668 			m_bios.Reschedule();
669 		}
670 		else
671 		{
672 			FinishExecCmd();
673 		}
674 	}
675 	else
676 	{
677 		assert(false);
678 		FinishExecCmd();
679 	}
680 }
681 
SifGetSreg(uint32 regIndex)682 int32 CSifCmd::SifGetSreg(uint32 regIndex)
683 {
684 	CLog::GetInstance().Print(LOG_NAME, FUNCTION_SIFGETSREG "(regIndex = %d);\r\n",
685 	                          regIndex);
686 	assert(regIndex < MAX_SREG);
687 	if(regIndex >= MAX_SREG)
688 	{
689 		return 0;
690 	}
691 	auto moduleData = reinterpret_cast<const MODULEDATA*>(m_ram + m_moduleDataAddr);
692 	uint32 result = moduleData->sreg[regIndex];
693 	return result;
694 }
695 
SifSetCmdBuffer(uint32 cmdBufferAddr,uint32 length)696 uint32 CSifCmd::SifSetCmdBuffer(uint32 cmdBufferAddr, uint32 length)
697 {
698 	CLog::GetInstance().Print(LOG_NAME, FUNCTION_SIFSETCMDBUFFER "(cmdBufferAddr = 0x%08X, length = %d);\r\n",
699 	                          cmdBufferAddr, length);
700 
701 	auto moduleData = reinterpret_cast<MODULEDATA*>(m_ram + m_moduleDataAddr);
702 	uint32 originalBuffer = moduleData->usrCmdBufferAddr;
703 	moduleData->usrCmdBufferAddr = cmdBufferAddr;
704 	moduleData->usrCmdBufferLen = length;
705 
706 	return originalBuffer;
707 }
708 
SifAddCmdHandler(uint32 pos,uint32 handler,uint32 data)709 void CSifCmd::SifAddCmdHandler(uint32 pos, uint32 handler, uint32 data)
710 {
711 	CLog::GetInstance().Print(LOG_NAME, FUNCTION_SIFADDCMDHANDLER "(pos = 0x%08X, handler = 0x%08X, data = 0x%08X);\r\n",
712 	                          pos, handler, data);
713 
714 	auto moduleData = reinterpret_cast<const MODULEDATA*>(m_ram + m_moduleDataAddr);
715 	bool isSystemCommand = (pos & SYSTEM_COMMAND_ID) != 0;
716 	uint32 cmd = pos & ~SYSTEM_COMMAND_ID;
717 	uint32 cmdBufferAddr = isSystemCommand ? m_sysCmdBufferAddr : moduleData->usrCmdBufferAddr;
718 	uint32 cmdBufferLen = isSystemCommand ? MAX_SYSTEM_COMMAND : moduleData->usrCmdBufferLen;
719 
720 	if((cmdBufferAddr != 0) && (cmd < cmdBufferLen))
721 	{
722 		auto& cmdDataEntry = reinterpret_cast<SIFCMDDATA*>(m_ram + cmdBufferAddr)[cmd];
723 		cmdDataEntry.sifCmdHandler = handler;
724 		cmdDataEntry.data = data;
725 	}
726 	else
727 	{
728 		CLog::GetInstance().Print(LOG_NAME, "SifAddCmdHandler - error command buffer too small or not set.\r\n");
729 	}
730 }
731 
SifSendCmd(uint32 commandId,uint32 packetPtr,uint32 packetSize,uint32 srcExtraPtr,uint32 dstExtraPtr,uint32 sizeExtra)732 uint32 CSifCmd::SifSendCmd(uint32 commandId, uint32 packetPtr, uint32 packetSize, uint32 srcExtraPtr, uint32 dstExtraPtr, uint32 sizeExtra)
733 {
734 	CLog::GetInstance().Print(LOG_NAME, FUNCTION_SIFSENDCMD "(commandId = 0x%08X, packetPtr = 0x%08X, packetSize = 0x%08X, srcExtraPtr = 0x%08X, dstExtraPtr = 0x%08X, sizeExtra = 0x%08X);\r\n",
735 	                          commandId, packetPtr, packetSize, srcExtraPtr, dstExtraPtr, sizeExtra);
736 
737 	assert(packetSize >= 0x10);
738 
739 	auto packetData = m_ram + packetPtr;
740 	auto header = reinterpret_cast<SIFCMDHEADER*>(packetData);
741 	header->commandId = commandId;
742 	header->packetSize = packetSize;
743 	header->destSize = 0;
744 	header->dest = 0;
745 
746 	if(sizeExtra != 0 && srcExtraPtr != 0 && dstExtraPtr != 0)
747 	{
748 		header->destSize = sizeExtra;
749 		header->dest = dstExtraPtr;
750 
751 		auto dmaReg = reinterpret_cast<SIFDMAREG*>(m_ram + m_sendCmdExtraStructAddr);
752 		dmaReg->srcAddr = srcExtraPtr;
753 		dmaReg->dstAddr = dstExtraPtr;
754 		dmaReg->size = sizeExtra;
755 		dmaReg->flags = 0;
756 
757 		m_sifMan.SifSetDma(m_sendCmdExtraStructAddr, 1);
758 	}
759 
760 	m_sifMan.SendPacket(packetData, packetSize);
761 
762 	return 1;
763 }
764 
SifBindRpc(CMIPS & context)765 void CSifCmd::SifBindRpc(CMIPS& context)
766 {
767 	uint32 clientDataAddr = context.m_State.nGPR[CMIPS::A0].nV0;
768 	uint32 serverId = context.m_State.nGPR[CMIPS::A1].nV0;
769 	uint32 mode = context.m_State.nGPR[CMIPS::A2].nV0;
770 
771 	CLog::GetInstance().Print(LOG_NAME, FUNCTION_SIFBINDRPC "(clientDataAddr = 0x%08X, serverId = 0x%08X, mode = 0x%08X);\r\n",
772 	                          clientDataAddr, serverId, mode);
773 
774 	//Could be in non waiting mode
775 	assert(mode == 0);
776 
777 	context.m_State.nPC = m_sifBindRpcAddr;
778 }
779 
SifCallRpc(CMIPS & context)780 void CSifCmd::SifCallRpc(CMIPS& context)
781 {
782 	uint32 clientDataAddr = context.m_State.nGPR[CMIPS::A0].nV0;
783 	uint32 rpcNumber = context.m_State.nGPR[CMIPS::A1].nV0;
784 	uint32 mode = context.m_State.nGPR[CMIPS::A2].nV0;
785 	uint32 sendAddr = context.m_State.nGPR[CMIPS::A3].nV0;
786 	uint32 sendSize = context.m_pMemoryMap->GetWord(context.m_State.nGPR[CMIPS::SP].nV0 + 0x10);
787 	uint32 recvAddr = context.m_pMemoryMap->GetWord(context.m_State.nGPR[CMIPS::SP].nV0 + 0x14);
788 	uint32 recvSize = context.m_pMemoryMap->GetWord(context.m_State.nGPR[CMIPS::SP].nV0 + 0x18);
789 	uint32 endFctAddr = context.m_pMemoryMap->GetWord(context.m_State.nGPR[CMIPS::SP].nV0 + 0x1C);
790 	uint32 endParam = context.m_pMemoryMap->GetWord(context.m_State.nGPR[CMIPS::SP].nV0 + 0x20);
791 
792 	assert(mode == 0);
793 
794 	CLog::GetInstance().Print(LOG_NAME, FUNCTION_SIFCALLRPC "(clientDataAddr = 0x%08X, rpcNumber = 0x%08X, mode = 0x%08X, sendAddr = 0x%08X, sendSize = 0x%08X, "
795 	                                                        "recvAddr = 0x%08X, recvSize = 0x%08X, endFctAddr = 0x%08X, endParam = 0x%08X);\r\n",
796 	                          clientDataAddr, rpcNumber, mode, sendAddr, sendSize, recvAddr, recvSize, endFctAddr, endParam);
797 
798 	auto clientData = reinterpret_cast<SIFRPCCLIENTDATA*>(m_ram + clientDataAddr);
799 	assert(clientData->serverDataAddr != 0);
800 	clientData->endFctPtr = endFctAddr;
801 	clientData->endParam = endParam;
802 	clientData->header.semaId = m_bios.CreateSemaphore(0, 1);
803 	int32 result = CIopBios::KERNEL_RESULT_OK;
804 	result = m_bios.WaitSemaphore(clientData->header.semaId);
805 	assert(result == CIopBios::KERNEL_RESULT_OK);
806 
807 	{
808 		auto dmaReg = reinterpret_cast<SIFDMAREG*>(m_ram + m_sendCmdExtraStructAddr);
809 		dmaReg->srcAddr = sendAddr;
810 		dmaReg->dstAddr = clientData->buffPtr;
811 		dmaReg->size = sendSize;
812 		dmaReg->flags = 0;
813 
814 		m_sifMan.SifSetDma(m_sendCmdExtraStructAddr, 1);
815 	}
816 
817 	SIFRPCCALL callPacket;
818 	memset(&callPacket, 0, sizeof(SIFRPCCALL));
819 	callPacket.header.commandId = SIF_CMD_CALL;
820 	callPacket.header.packetSize = sizeof(SIFRPCCALL);
821 	callPacket.header.destSize = sendSize;
822 	callPacket.header.dest = clientData->buffPtr;
823 	callPacket.rpcNumber = rpcNumber;
824 	callPacket.sendSize = sendSize;
825 	callPacket.recv = recvAddr;
826 	callPacket.recvSize = recvSize;
827 	callPacket.recvMode = 1;
828 	callPacket.clientDataAddr = clientDataAddr;
829 	callPacket.serverDataAddr = clientData->serverDataAddr;
830 
831 	m_sifMan.SendPacket(&callPacket, sizeof(callPacket));
832 
833 	context.m_State.nGPR[CMIPS::V0].nD0 = 0;
834 }
835 
SifRegisterRpc(CMIPS & context)836 void CSifCmd::SifRegisterRpc(CMIPS& context)
837 {
838 	uint32 serverDataAddr = context.m_State.nGPR[CMIPS::A0].nV0;
839 	uint32 serverId = context.m_State.nGPR[CMIPS::A1].nV0;
840 	uint32 function = context.m_State.nGPR[CMIPS::A2].nV0;
841 	uint32 buffer = context.m_State.nGPR[CMIPS::A3].nV0;
842 	uint32 cfunction = context.m_pMemoryMap->GetWord(context.m_State.nGPR[CMIPS::SP].nV0 + 0x10);
843 	uint32 cbuffer = context.m_pMemoryMap->GetWord(context.m_State.nGPR[CMIPS::SP].nV0 + 0x14);
844 	uint32 queueAddr = context.m_pMemoryMap->GetWord(context.m_State.nGPR[CMIPS::SP].nV0 + 0x18);
845 
846 	CLog::GetInstance().Print(LOG_NAME, FUNCTION_SIFREGISTERRPC "(serverData = 0x%08X, serverId = 0x%08X, function = 0x%08X, buffer = 0x%08X, cfunction = 0x%08X, cbuffer = 0x%08X, queue = 0x%08X);\r\n",
847 	                          serverDataAddr, serverId, function, buffer, cfunction, cbuffer, queueAddr);
848 
849 	bool moduleRegistered = m_sifMan.IsModuleRegistered(serverId);
850 	if(!moduleRegistered)
851 	{
852 		auto module = new CSifDynamic(*this, serverDataAddr);
853 		m_servers.push_back(module);
854 		m_sifMan.RegisterModule(serverId, module);
855 	}
856 
857 	if(serverDataAddr != 0)
858 	{
859 		auto serverData = reinterpret_cast<SIFRPCSERVERDATA*>(&m_ram[serverDataAddr]);
860 		serverData->serverId = serverId;
861 		serverData->function = function;
862 		serverData->buffer = buffer;
863 		serverData->cfunction = cfunction;
864 		serverData->cbuffer = cbuffer;
865 		serverData->queueAddr = queueAddr;
866 		//If a serverId was already registed before this call to SifRegisterRpc, we mark serverData as
867 		//not being active. This is important for SifRemoveRpc because it might try to unregister
868 		//something that was present before (ex.: FF12 with MCSERV)
869 		serverData->active = moduleRegistered ? false : true;
870 	}
871 
872 	if(queueAddr != 0)
873 	{
874 		auto queueData = reinterpret_cast<SIFRPCQUEUEDATA*>(m_ram + queueAddr);
875 		assert(queueData->serverDataStart == 0);
876 		queueData->serverDataStart = serverDataAddr;
877 	}
878 
879 	context.m_State.nGPR[CMIPS::V0].nD0 = 0;
880 }
881 
SifSetRpcQueue(uint32 queueDataAddr,uint32 threadId)882 void CSifCmd::SifSetRpcQueue(uint32 queueDataAddr, uint32 threadId)
883 {
884 	CLog::GetInstance().Print(LOG_NAME, FUNCTION_SIFSETRPCQUEUE "(queueData = 0x%08X, threadId = %d);\r\n",
885 	                          queueDataAddr, threadId);
886 
887 	if(queueDataAddr != 0)
888 	{
889 		auto queueData = reinterpret_cast<SIFRPCQUEUEDATA*>(m_ram + queueDataAddr);
890 		queueData->threadId = threadId;
891 		queueData->active = 0;
892 		queueData->serverDataLink = 0;
893 		queueData->serverDataStart = 0;
894 		queueData->serverDataEnd = 0;
895 		queueData->queueNext = 0;
896 	}
897 }
898 
SifGetNextRequest(uint32 queueDataAddr)899 uint32 CSifCmd::SifGetNextRequest(uint32 queueDataAddr)
900 {
901 	CLog::GetInstance().Print(LOG_NAME, FUNCTION_SIFGETNEXTREQUEST "(queueData = 0x%08X);\r\n",
902 	                          queueDataAddr);
903 
904 	uint32 result = 0;
905 	if(queueDataAddr != 0)
906 	{
907 		auto queueData = reinterpret_cast<SIFRPCQUEUEDATA*>(m_ram + queueDataAddr);
908 		result = queueData->serverDataLink;
909 		queueData->serverDataLink = 0;
910 	}
911 	return result;
912 }
913 
SifExecRequest(CMIPS & context)914 void CSifCmd::SifExecRequest(CMIPS& context)
915 {
916 	uint32 serverDataAddr = context.m_State.nGPR[CMIPS::A0].nV0;
917 	auto serverData = reinterpret_cast<SIFRPCSERVERDATA*>(&m_ram[serverDataAddr]);
918 	CLog::GetInstance().Print(LOG_NAME, FUNCTION_SIFEXECREQUEST "(serverData = 0x%08X, serverId=0x%x, function=0x%x, rid=0x%x, buffer=0x%x, rsize=0x%x);\r\n",
919 	                          serverDataAddr, serverData->serverId, serverData->function, serverData->rid, serverData->buffer, serverData->rsize);
920 	context.m_State.nPC = m_sifExecRequestAddr;
921 }
922 
SifCheckStatRpc(uint32 clientDataAddress)923 uint32 CSifCmd::SifCheckStatRpc(uint32 clientDataAddress)
924 {
925 	CLog::GetInstance().Print(LOG_NAME, FUNCTION_SIFCHECKSTATRPC "(clientData = 0x%08X);\r\n",
926 	                          clientDataAddress);
927 	return 0;
928 }
929 
SifRpcLoop(CMIPS & context)930 void CSifCmd::SifRpcLoop(CMIPS& context)
931 {
932 	uint32 queueAddr = context.m_State.nGPR[CMIPS::A0].nV0;
933 	CLog::GetInstance().Print(LOG_NAME, FUNCTION_SIFRPCLOOP "(queue = 0x%08X);\r\n",
934 	                          queueAddr);
935 	context.m_State.nPC = m_sifRpcLoopAddr;
936 }
937 
SifRemoveRpc(uint32 serverDataAddr,uint32 queueDataAddr)938 uint32 CSifCmd::SifRemoveRpc(uint32 serverDataAddr, uint32 queueDataAddr)
939 {
940 	CLog::GetInstance().Print(LOG_NAME, FUNCTION_SIFREMOVERPC "(server = 0x%08X, queue = 0x%08X);\r\n",
941 	                          serverDataAddr, queueDataAddr);
942 
943 	if(serverDataAddr == 0)
944 	{
945 		CLog::GetInstance().Warn(LOG_NAME, FUNCTION_SIFREMOVERPC ": serverDataAddr is null.\r\n");
946 		return 0;
947 	}
948 
949 	auto serverData = reinterpret_cast<const SIFRPCSERVERDATA*>(&m_ram[serverDataAddr]);
950 	if(!serverData->active)
951 	{
952 		//Server was not active, don't bother unregistering it
953 		return 1;
954 	}
955 
956 	bool registered = m_sifMan.IsModuleRegistered(serverData->serverId);
957 	if(!registered)
958 	{
959 		CLog::GetInstance().Warn(LOG_NAME, FUNCTION_SIFREMOVERPC ": server not registered.\r\n");
960 		return 0;
961 	}
962 
963 	m_sifMan.UnregisterModule(serverData->serverId);
964 
965 	return 1;
966 }
967 
SifRemoveRpcQueue(uint32 queueDataAddr)968 uint32 CSifCmd::SifRemoveRpcQueue(uint32 queueDataAddr)
969 {
970 	CLog::GetInstance().Print(LOG_NAME, FUNCTION_SIFREMOVERPCQUEUE "(queue = 0x%08X);\r\n",
971 	                          queueDataAddr);
972 	return 1;
973 }
974 
SifGetOtherData(uint32 packetPtr,uint32 src,uint32 dst,uint32 size,uint32 mode)975 uint32 CSifCmd::SifGetOtherData(uint32 packetPtr, uint32 src, uint32 dst, uint32 size, uint32 mode)
976 {
977 	CLog::GetInstance().Print(LOG_NAME, FUNCTION_SIFGETOTHERDATA "(packetPtr = 0x%08X, src = 0x%08X, dst = 0x%08X, size = 0x%08X, mode = %d);\r\n",
978 	                          packetPtr, src, dst, size, mode);
979 	m_sifMan.GetOtherData(dst, src, size);
980 	return 0;
981 }
982 
SifSendCmdIntr(uint32 commandId,uint32 packetPtr,uint32 packetSize,uint32 srcExtraPtr,uint32 dstExtraPtr,uint32 sizeExtra,uint32 callbackPtr,uint32 callbackDataPtr)983 uint32 CSifCmd::SifSendCmdIntr(uint32 commandId, uint32 packetPtr, uint32 packetSize, uint32 srcExtraPtr, uint32 dstExtraPtr, uint32 sizeExtra, uint32 callbackPtr, uint32 callbackDataPtr)
984 {
985 	CLog::GetInstance().Print(LOG_NAME, FUNCTION_SIFSENDCMDINTR "(commandId = 0x%08X, packetPtr = 0x%08X, packetSize = 0x%08X, srcExtraPtr = 0x%08X, dstExtraPtr = 0x%08X, sizeExtra = 0x%08X, callbackPtr = 0x%08X, callbackDataPtr = 0x%08X);\r\n",
986 	                          commandId, packetPtr, packetSize, srcExtraPtr, dstExtraPtr, sizeExtra, callbackPtr, callbackDataPtr);
987 
988 	uint32 result = SifSendCmd(commandId, packetPtr, packetSize, srcExtraPtr, dstExtraPtr, sizeExtra);
989 	m_bios.TriggerCallback(callbackPtr, callbackDataPtr);
990 	return result;
991 }
992 
SleepThread()993 void CSifCmd::SleepThread()
994 {
995 	m_bios.SleepThread();
996 }
997 
DelayThread(uint32 delay)998 void CSifCmd::DelayThread(uint32 delay)
999 {
1000 	m_bios.DelayThread(delay);
1001 }
1002