1 #pragma once
2 
3 #include "Iop_Module.h"
4 #include "Iop_SifMan.h"
5 #include "Iop_SifDynamic.h"
6 #include "Iop_Sysmem.h"
7 #include "zip/ZipArchiveWriter.h"
8 #include "zip/ZipArchiveReader.h"
9 
10 class CIopBios;
11 
12 namespace Iop
13 {
14 	class CSifCmd : public CModule
15 	{
16 	public:
17 		CSifCmd(CIopBios&, CSifMan&, CSysmem&, uint8*);
18 		virtual ~CSifCmd();
19 
20 		std::string GetId() const override;
21 		std::string GetFunctionName(unsigned int) const override;
22 		void Invoke(CMIPS&, unsigned int) override;
23 
24 		void ProcessInvocation(uint32, uint32, uint32*, uint32);
25 
26 		void LoadState(Framework::CZipArchiveReader&) override;
27 		void SaveState(Framework::CZipArchiveWriter&) const override;
28 
29 		void SifBindRpc(CMIPS&);
30 		void SifCallRpc(CMIPS&);
31 
32 	private:
33 		typedef std::list<CSifDynamic*> DynamicModuleList;
34 
35 		struct SIFRPCQUEUEDATA
36 		{
37 			uint32 threadId;
38 			uint32 active;
39 			uint32 serverDataLink;  //Set when there's a pending request
40 			uint32 serverDataStart; //Set when a RPC server has been registered on the queue
41 			uint32 serverDataEnd;
42 			uint32 queueNext;
43 		};
44 
45 		struct SIFRPCSERVERDATA
46 		{
47 			uint32 serverId;
48 
49 			uint32 function;
50 			uint32 buffer;
51 			uint32 size;
52 
53 			uint32 cfunction;
54 			uint32 cbuffer;
55 			uint32 csize;
56 
57 			uint32 rsize;
58 			uint32 rid;
59 
60 			uint32 queueAddr;
61 
62 			//This field is not a part of the real structure, added for bookkeeping reasons.
63 			uint32 active;
64 		};
65 		static_assert(sizeof(SIFRPCSERVERDATA) <= 0x44, "Size of SIFRPCSERVERDATA must be less or equal to 68 bytes.");
66 
67 		struct SIFCMDDATA
68 		{
69 			//There might be an additional GP member in here, but some games such as
70 			//Shadow Hearts 2 rely on the fact that this structure is 8 bytes long
71 			uint32 sifCmdHandler;
72 			uint32 data;
73 		};
74 
75 		enum
76 		{
77 			MAX_SYSTEM_COMMAND = 0x20,
78 			MAX_SREG = 0x20,
79 			PENDING_CMD_BUFFER_SIZE = 0x400,
80 		};
81 
82 		struct MODULEDATA
83 		{
84 			uint8 trampoline[0x800];
85 			uint8 sendCmdExtraStruct[0x10];
86 			uint32 sreg[MAX_SREG];
87 			SIFCMDDATA sysCmdBuffer[MAX_SYSTEM_COMMAND];
88 			uint32 usrCmdBufferAddr;
89 			uint32 usrCmdBufferLen;
90 			uint32 executingCmd;
91 			uint8 pendingCmdBuffer[PENDING_CMD_BUFFER_SIZE];
92 			uint32 pendingCmdBufferSize;
93 		};
94 
95 		void ClearServers();
96 		void BuildExportTable();
97 
98 		void ProcessCustomCommand(uint32);
99 		void ProcessSetSreg(uint32);
100 		void ProcessRpcRequestEnd(uint32);
101 		void ProcessDynamicCommand(uint32);
102 		void ProcessNextDynamicCommand();
103 
104 		int32 SifGetSreg(uint32);
105 		uint32 SifSetCmdBuffer(uint32, uint32);
106 		void SifAddCmdHandler(uint32, uint32, uint32);
107 		uint32 SifSendCmd(uint32, uint32, uint32, uint32, uint32, uint32);
108 		void SifRegisterRpc(CMIPS&);
109 		uint32 SifCheckStatRpc(uint32);
110 		void SifSetRpcQueue(uint32, uint32);
111 		uint32 SifGetNextRequest(uint32);
112 		void SifExecRequest(CMIPS&);
113 		void SifRpcLoop(CMIPS&);
114 		uint32 SifGetOtherData(uint32, uint32, uint32, uint32, uint32);
115 		uint32 SifRemoveRpc(uint32, uint32);
116 		uint32 SifRemoveRpcQueue(uint32);
117 		uint32 SifSendCmdIntr(uint32, uint32, uint32, uint32, uint32, uint32, uint32, uint32);
118 		void FinishExecRequest(uint32, uint32);
119 		void FinishExecCmd();
120 		void FinishBindRpc(uint32, uint32);
121 		void SleepThread();
122 		void DelayThread(uint32);
123 
124 		CIopBios& m_bios;
125 		CSifMan& m_sifMan;
126 		CSysmem& m_sysMem;
127 		uint8* m_ram = nullptr;
128 		uint32 m_moduleDataAddr = 0;
129 		uint32 m_trampolineAddr = 0;
130 		uint32 m_sendCmdExtraStructAddr = 0;
131 		uint32 m_sysCmdBufferAddr = 0;
132 		uint32 m_sifRpcLoopAddr = 0;
133 		uint32 m_sifExecRequestAddr = 0;
134 		uint32 m_sifExecCmdHandlerAddr = 0;
135 		uint32 m_sifBindRpcAddr = 0;
136 		DynamicModuleList m_servers;
137 	};
138 
139 	typedef std::shared_ptr<CSifCmd> SifCmdPtr;
140 }
141