Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

447 lines
11 KiB

  1. #ifndef __PS3_HELPERS__
  2. #define __PS3_HELPERS__
  3. #ifndef SN_TARGET_PS3
  4. #error
  5. #endif
  6. #include <cellstatus.h>
  7. #include <sys/paths.h>
  8. #include <sys/prx.h>
  9. #include <sys/synchronization.h>
  10. #include <sys/ppu_thread.h>
  11. #include <sys/timer.h>
  12. #include "ppu_intrinsics.h"
  13. #include <np.h>
  14. #include <np/drm.h>
  15. // Forward declarations
  16. #ifndef _CERT
  17. #define PS3PRXLOADDIAGNOSTIC printf
  18. #else
  19. #define PS3PRXLOADDIAGNOSTIC( ... ) ((void)0)
  20. #endif
  21. struct TLSGlobals;
  22. // PS3 PRX load parameters structures
  23. struct PS3_PrxLoadParametersBase_t
  24. {
  25. int32_t cbSize;
  26. sys_prx_id_t sysPrxId;
  27. uint64_t uiFlags;
  28. uint64_t reserved[7];
  29. };
  30. struct PS3_PrxModuleEntry_t
  31. {
  32. PS3_PrxModuleEntry_t *pNextModule;
  33. char chName[256];
  34. uint32_t uiRefCount;
  35. PS3_PrxLoadParametersBase_t prxParams[0];
  36. };
  37. extern "C" PS3_PrxModuleEntry_t ** PS3_PrxGetModulesList();
  38. struct PS3_GcmSharedData;
  39. // exported from tier0
  40. extern "C" PS3_GcmSharedData *g_pGcmSharedData;
  41. struct PS3_GcmSharedData
  42. {
  43. void *m_pIoMemory;
  44. uint32_t m_nIoMemorySize;
  45. PS3_GcmSharedData()
  46. {
  47. memset(this, 0, sizeof(PS3_GcmSharedData));
  48. }
  49. // Thread for the QMS and Server (when host_thread_mode)
  50. // Thread wakes up on a semaphore and when it does so it checks for
  51. // sv_runflag and then qms runFlag and does the right thing
  52. // This is hand coded because the PS3 scheduler sometimes (regardless of priorities)
  53. // pushes out the main thread to run the server if the server is it's own job.
  54. // So we create a single thread, one which we have the ability to explicitly
  55. // run the server and the qms
  56. // The semaphore is there so that we can sleep instead of exiting the job
  57. // Otherwise the run flags actually control if we run locklessly
  58. // CheckForServerRequest() is called eregularly on the QMS and so allows the
  59. // server to interrupt the QMS and run pretty much where we need to to.
  60. //
  61. sys_ppu_thread_t m_thread;
  62. sys_semaphore_t m_semaphore;
  63. // Server
  64. volatile int m_svRunFlag;
  65. volatile int m_svDoneFlag;
  66. volatile int m_numTicks;
  67. void (*m_pfnAsyncServer)(int numTicks);
  68. // QMS
  69. volatile int m_qmsRunFlag;
  70. volatile int m_qmsDoneFlag;
  71. volatile void* m_cmat;
  72. volatile void* m_ptr;
  73. void (*m_func)(void*, void*);
  74. // Audio
  75. volatile int m_audioRunFlag;
  76. volatile int m_audioDoneFlag;
  77. void (*m_AudioFunc)(void);
  78. // Endframe Defrag
  79. volatile int m_bDeFrag;
  80. // Create semaphore & thread
  81. void Init()
  82. {
  83. // Create Semaphore
  84. sys_semaphore_attribute_t attr;
  85. sys_semaphore_attribute_initialize(attr);
  86. int ret = sys_semaphore_create(&m_semaphore, &attr, 0, 2); // No point in allowing > 2 posts
  87. if(ret != CELL_OK)
  88. {
  89. printf("Unable to create QMS sem\n");
  90. }
  91. }
  92. void RunServer(void (*pfn)(int), int numticks)
  93. {
  94. // Set global data
  95. m_pfnAsyncServer = pfn;
  96. m_numTicks = numticks;
  97. __lwsync();
  98. m_svRunFlag = 1;
  99. // Post semaphore incase trhead sleeps
  100. sys_semaphore_post(m_semaphore, 1);
  101. }
  102. void RunQMS(void (*func)(void* cmat, void* ptr), void* cmat, void* ptr )
  103. {
  104. m_func = func;
  105. m_cmat = cmat;
  106. m_ptr = ptr;
  107. __lwsync();
  108. m_qmsRunFlag = 1;
  109. // Post semaphore incase trhead sleeps
  110. sys_semaphore_post(m_semaphore, 1);
  111. }
  112. void WaitForServer()
  113. {
  114. while (!m_svDoneFlag) sys_timer_usleep(60);
  115. m_svDoneFlag = 0;
  116. }
  117. void WaitForQMS()
  118. {
  119. while (!m_qmsDoneFlag) sys_timer_usleep(60);
  120. m_qmsDoneFlag = 0;
  121. }
  122. void CheckForServerRequest()
  123. {
  124. if (m_svRunFlag)
  125. {
  126. m_svRunFlag = 0;
  127. m_pfnAsyncServer(m_numTicks);
  128. m_svDoneFlag = 1;
  129. }
  130. }
  131. // Audio
  132. void RunAudio(void (*pfn)(void))
  133. {
  134. // Set global data
  135. m_AudioFunc = pfn;
  136. __lwsync();
  137. m_audioRunFlag = 1;
  138. // Post semaphore incase trhead sleeps
  139. sys_semaphore_post(m_semaphore, 1);
  140. }
  141. void WaitForAudio()
  142. {
  143. while (!m_audioDoneFlag) sys_timer_usleep(60);
  144. m_audioDoneFlag = 0;
  145. }
  146. void CheckForAudioRequest()
  147. {
  148. if (g_pGcmSharedData->m_audioRunFlag)
  149. {
  150. g_pGcmSharedData->m_audioRunFlag = 0;
  151. g_pGcmSharedData->m_AudioFunc();
  152. g_pGcmSharedData->m_audioDoneFlag = 1;
  153. }
  154. }
  155. };
  156. class CPs3ContentPathInfo;
  157. struct PS3_LoadTier0_Parameters_t : public PS3_PrxLoadParametersBase_t
  158. {
  159. typedef TLSGlobals * ( *PFNGETTLSGLOBALS )();
  160. PFNGETTLSGLOBALS pfnGetTlsGlobals; // [IN] [ from launcher_main to tier0 ]
  161. PS3_PrxModuleEntry_t **ppPrxModulesList; // [IN] [ from launcher_main: head of the list of loaded PRX modules ]
  162. CPs3ContentPathInfo *pPS3PathInfo; // [IN] [ from launcher_main to tier0 ]
  163. uint64_t fiosLaunchTime; // [IN] [ from launcher_main: the time when the launcher was launched, the baseline time ]
  164. uint32_t nCLNumber; // [IN] [ from launcher_main to tier0: the changelist number for this image (0 if unknown) ]
  165. void(*pfnPushMarker)( const char * pName );
  166. void(*pfnPopMarker)();
  167. void(*pfnSwapBufferMarker)();
  168. // Raw SPU libSN functions
  169. void (*snRawSPULockHandler) (void);
  170. void (*snRawSPUUnlockHandler) (void);
  171. void (*snRawSPUNotifyCreation) (unsigned int uID);
  172. void (*snRawSPUNotifyDestruction) (unsigned int uID);
  173. void (*snRawSPUNotifyElfLoad) (unsigned int uID, unsigned int uEntry, const char *pFileName);
  174. void (*snRawSPUNotifyElfLoadNoWait) (unsigned int uID, unsigned int uEntry, const char *pFileName);
  175. void (*snRawSPUNotifyElfLoadAbs) (unsigned int uID, unsigned int uEntry, const char *pFileName);
  176. void (*snRawSPUNotifyElfLoadAbsNoWait) (unsigned int uID, unsigned int uEntry, const char *pFileName);
  177. void (*snRawSPUNotifySPUStopped) (unsigned int uID);
  178. void (*snRawSPUNotifySPUStarted) (unsigned int uID);
  179. struct PS3_GcmSharedData *m_pGcmSharedData;
  180. typedef void ( *PFNSHUTDOWN )();
  181. PFNSHUTDOWN pfnTier0Shutdown; // [OUT] [ tier0 shutdown procedure to be invoked ]
  182. };
  183. struct PS3_LoadLauncher_Parameters_t : public PS3_PrxLoadParametersBase_t
  184. {
  185. typedef int ( *PFNLAUNCHERMAIN )( int argc, char **argv );
  186. PFNLAUNCHERMAIN pfnLauncherMain; // [OUT] [ launcher entry point ]
  187. typedef void ( *PFNSHUTDOWN )();
  188. PFNSHUTDOWN pfnLauncherShutdown; // [OUT] [ launcher shutdown procedure to be invoked ]
  189. };
  190. struct PS3_LoadAppSystemInterface_Parameters_t : public PS3_PrxLoadParametersBase_t
  191. {
  192. typedef void* ( *PFNCREATEINTERFACE )( const char *pName, int *pReturnCode );
  193. PFNCREATEINTERFACE pfnCreateInterface; // [OUT] [ app system module create interface entry point ]
  194. uint64_t reserved[8];
  195. };
  196. inline int PS3_PrxLoad( const char *path, PS3_PrxLoadParametersBase_t *params )
  197. {
  198. #define NP_POOL_SIZE (128*1024)
  199. static uint8_t np_pool[NP_POOL_SIZE];
  200. int res;
  201. int modres;
  202. sys_prx_id_t id;
  203. if ( !params )
  204. return -1;
  205. PS3_PrxModuleEntry_t ** ppPrxModulesList = PS3_PrxGetModulesList();
  206. //
  207. // Walk the loaded list
  208. //
  209. for ( PS3_PrxModuleEntry_t *pEntry = *ppPrxModulesList; pEntry; pEntry = pEntry->pNextModule )
  210. {
  211. if ( strcmp( pEntry->chName, path ) )
  212. continue;
  213. ++ pEntry->uiRefCount;
  214. memcpy( params, pEntry->prxParams, ( pEntry->prxParams->cbSize <= params->cbSize ) ? pEntry->prxParams->cbSize : params->cbSize );
  215. PS3PRXLOADDIAGNOSTIC("PRX MODULE ADDREF: %s [0x%08X] (refs=%u)\n", path, params->sysPrxId, pEntry->uiRefCount);
  216. return 0;
  217. }
  218. //
  219. // Load a new instance of PRX
  220. //
  221. params->sysPrxId = -1;
  222. // If sceNp wasn't already initalised then we need to un-init it after we're done here. If Steam is loaded
  223. // after this and it finds NP is already intialised it won't like it
  224. int npInit = sceNpInit( NP_POOL_SIZE, np_pool );
  225. SceNpDrmKey key = { 0x2B, 0x8E, 0xD3, 0xE4, 0xDF, 0xF1, 0x43, 0xA2, 0xA5, 0xD7, 0x4D, 0x8D, 0x89, 0x29, 0xC5, 0xF4 };
  226. sceNpDrmIsAvailable( &key, path );
  227. id = sys_prx_load_module(path, 0, NULL);
  228. if (id < CELL_OK)
  229. {
  230. PS3PRXLOADDIAGNOSTIC("sys_prx_load_module failed: %s [0x%08x]\n", path, id);
  231. return id;
  232. }
  233. PS3PRXLOADDIAGNOSTIC("PRX MODULE LOADED: %s [0x%08X]\n", path, id);
  234. if ( npInit != SCE_NP_ERROR_ALREADY_INITIALIZED )
  235. {
  236. sceNpTerm();
  237. }
  238. params->sysPrxId = id;
  239. res = sys_prx_start_module(id, params->cbSize, params, &modres, 0, NULL);
  240. if (res < CELL_OK)
  241. {
  242. PS3PRXLOADDIAGNOSTIC("sys_prx_start_module failed: %s [0x%08x]\n", path, res);
  243. return res;
  244. }
  245. PS3PRXLOADDIAGNOSTIC("PRX MODULE STARTED: %s [0x%08X 0x%08X]\n", path, id, res);
  246. //
  247. // Add to the loaded list
  248. //
  249. if ( void *pvEntry = malloc( sizeof( PS3_PrxModuleEntry_t ) + params->cbSize ) )
  250. {
  251. PS3_PrxModuleEntry_t *pPrxEntry = ( PS3_PrxModuleEntry_t * ) pvEntry;
  252. pPrxEntry->pNextModule = *ppPrxModulesList;
  253. *ppPrxModulesList = pPrxEntry;
  254. strncpy( pPrxEntry->chName, path, sizeof( pPrxEntry->chName ) );
  255. pPrxEntry->uiRefCount = 1;
  256. memcpy( pPrxEntry->prxParams, params, params->cbSize );
  257. }
  258. return modres;
  259. }
  260. inline int PS3_PrxUnload( sys_prx_id_t id )
  261. {
  262. PS3_PrxModuleEntry_t ** ppPrxModulesList = PS3_PrxGetModulesList();
  263. //
  264. // Walk the loaded list
  265. //
  266. for ( PS3_PrxModuleEntry_t *pEntry = *ppPrxModulesList, **ppFromPrevEntry = ppPrxModulesList;
  267. pEntry; ppFromPrevEntry = &pEntry->pNextModule, pEntry = pEntry->pNextModule )
  268. {
  269. if ( pEntry->prxParams->sysPrxId != id )
  270. continue;
  271. if ( -- pEntry->uiRefCount )
  272. {
  273. PS3PRXLOADDIAGNOSTIC("PRX MODULE RELREF: %s [0x%08X] (refs=%u)\n", pEntry->chName, pEntry->prxParams->sysPrxId, pEntry->uiRefCount);
  274. return 0;
  275. }
  276. else
  277. {
  278. PS3PRXLOADDIAGNOSTIC("PRX MODULE UNLOAD: %s [0x%08X]\n", pEntry->chName, pEntry->prxParams->sysPrxId, pEntry->uiRefCount);
  279. *ppFromPrevEntry = pEntry->pNextModule;
  280. free( pEntry );
  281. break;
  282. }
  283. }
  284. //
  285. // Perform the system unload process
  286. //
  287. int modres;
  288. int res;
  289. res = sys_prx_stop_module(id, 0, NULL, &modres, 0, NULL);
  290. if (res < CELL_OK)
  291. {
  292. PS3PRXLOADDIAGNOSTIC("sys_prx_stop_module failed: id=0x%08x, 0x%08x\n", id, res);
  293. return res;
  294. }
  295. PS3PRXLOADDIAGNOSTIC("PRX MODULE STOPPED: id=0x%08x, 0x%08x\n", id, res);
  296. res = sys_prx_unload_module(id, 0, NULL);
  297. if (res < CELL_OK)
  298. {
  299. PS3PRXLOADDIAGNOSTIC("sys_prx_unload_module failed: id=0x%08X, 0x%08x\n", id, res);
  300. return res;
  301. }
  302. PS3PRXLOADDIAGNOSTIC("PRX MODULE UNLOADED: id=0x%08x, 0x%08x\n", id, res);
  303. return modres;
  304. }
  305. //////////////////////////////////////////////////////////////////////////
  306. //
  307. // DEFINITION OF BASIC APPSYSTEM PRX IMPLEMENTATION
  308. //
  309. //
  310. #include "ps3_changelistver.h"
  311. #ifndef PS3CLVERMAJOR
  312. #define PS3CLVERMAJOR ((APPCHANGELISTVERSION / 256) % 256)
  313. #define PS3CLVERMINOR (APPCHANGELISTVERSION % 256)
  314. #endif
  315. #ifdef _DEBUG
  316. #define PS3_PRX_SYS_MODULE_INFO_FULLMACROREPLACEMENTHELPER(ps3modulename) SYS_MODULE_INFO( ps3modulename##_dbg, 0, PS3CLVERMAJOR, PS3CLVERMINOR)
  317. #else
  318. #define PS3_PRX_SYS_MODULE_INFO_FULLMACROREPLACEMENTHELPER(ps3modulename) SYS_MODULE_INFO( ps3modulename##_rel, 0, PS3CLVERMAJOR, PS3CLVERMINOR)
  319. #endif
  320. #define PS3_PRX_SYS_MODULE_START_NAME_FULLMACROREPLACEMENTHELPER(ps3modulename) _##ps3modulename##_ps3_prx_entry
  321. #define PS3_PRX_APPSYSTEM_MODULE( ps3modulename ) \
  322. \
  323. PS3_PRX_SYS_MODULE_INFO_FULLMACROREPLACEMENTHELPER( ps3modulename ); \
  324. SYS_MODULE_START( PS3_PRX_SYS_MODULE_START_NAME_FULLMACROREPLACEMENTHELPER( ps3modulename ) ); \
  325. \
  326. extern "C" int PS3_PRX_SYS_MODULE_START_NAME_FULLMACROREPLACEMENTHELPER( ps3modulename )( unsigned int args, void *pArg ) \
  327. { \
  328. Assert( args >= sizeof( PS3_LoadAppSystemInterface_Parameters_t ) ); \
  329. PS3_LoadAppSystemInterface_Parameters_t *pParams = reinterpret_cast< PS3_LoadAppSystemInterface_Parameters_t * >( pArg ); \
  330. Assert( pParams->cbSize >= sizeof( PS3_LoadAppSystemInterface_Parameters_t ) ); \
  331. pParams->pfnCreateInterface = CreateInterface; \
  332. return SYS_PRX_RESIDENT; \
  333. } \
  334. //
  335. //
  336. // END DEFINITION OF BASIC APPSYSTEM PRX IMPLEMENTATION
  337. //
  338. //
  339. //////////////////////////////////////////////////////////////////////////
  340. #endif // __PS3_HELPERS__