#include "spursConfiguration.h" #include "spursSupportInterface.h" #include #include #include #include #include #include #include #define SCE_EXTERNAL_RELEASE // for CELL_FS_MAX_FS_PATH_LENGTH #include static uint32_t _g_uiNextEventQueueKey=0x92400ABDUL; uint32_t _SpursSupportGetUniqueEventQueueKey() { return _g_uiNextEventQueueKey++; } sys_event_queue_t _g_SpuPrintfEventQueue; sys_ppu_thread_t _g_SpursPrintfThread; void _SpursPrintfThreadMain(uint64_t arg); #define SPURS_PPU_THREAD_PRIO 1001 #define SPU_PRINTF_EVENT_QUEUE_SIZE 8 #define SPU_PRINTF_EVENT_QUEUE_PORT 0x1 #define SPU_PRINTF_THREAD_PRIO 1001 #define SPU_PRINTF_THREAD_STACK_SIZE (64 * 1024) /* typedef struct BulletSpursElf { const char *pcElfName; void *pvElfImage; } BulletSpursElf; */ #ifdef _DEBUG extern char _binary_spu_SpeexSpursTaskDebug_elf_start[]; void *g_SpursTaskElfStart = _binary_spu_SpeexSpursTaskDebug_elf_start; #else extern char _binary_spu_SpeexSpursTaskRelease_elf_start[]; void *g_SpursTaskElfStart = _binary_spu_SpeexSpursTaskRelease_elf_start; #endif //#ifdef _DEBUG /* BulletSpursElf _g_aSPURSElfs[]={ #ifdef _DEBUG {"test.elf", _binary_spu_PS3_SPURS_SpeexDebug_elf_start} #else {"test.elf", _binary_spu_PS3_SPURS_SpeexRelease_elf_start} #endif }; */ /* #ifndef SCE_EXTERNAL_RELEASE // Here's the search path for the SPURS programs: char *_g_apcSPURSELFSearchPaths[]={ "/app_home/", "/app_home/../../lib/", // works with samples "/app_home/../../../lib/", // works with tutorials "/app_home/../../../../lib/", "/app_home/../../../../../lib/", }; unsigned int _g_uiSPURSELFSearchPathCount=sizeof(_g_apcSPURSELFSearchPaths)/sizeof(char *); #endif // SCE_EXTERNAL_RELEASE */ // E The priority for the SPU thread group used by SPURS #define SPURS_SPU_THREAD_PRIORITY 200 static CellSpurs *g_spursInstance=0; static CellSpursTaskset g_spursTaskSet __attribute__ ((aligned(128))); static int g_iDefaultSPUCount=CELL_SPURS_DEFAULT_SPU_COUNT; static bool g_bSpursInitialized=false; static bool g_bUserSpursGiven=false; static uint32_t g_uiSpursReferenceCounter=0; /** * E This is the main function of the spu_printf service thread. * It listens for messages and calls the printf handler when it gets them, * then notifies the SPU of completion by using a mailbox. */ //UPDATE: this function is not currently being used in the speex task or spurs manager void _SpursPrintfThreadMain(uint64_t arg) { sys_event_t event; int iReturn; // E For unused parameter warnings (void) arg; while (1) { iReturn=sys_event_queue_receive(_g_SpuPrintfEventQueue, &event, SYS_NO_TIMEOUT); if (iReturn!=CELL_OK) { fprintf(stderr, "Event queue receive wasn't successful: %i\n", iReturn); exit(-1); } iReturn=spu_thread_printf(event.data1, event.data3); sys_spu_thread_write_spu_mb(event.data1, iReturn); } } /* void *loadBulletImage(const char *pcFilename) { void *pvElf; FILE *pfInputFile=fopen(pcFilename, "rb"); uint64_t uiFileSize; if (!pfInputFile) { return 0; } fseek(pfInputFile, 0, SEEK_END); uiFileSize=ftell(pfInputFile); fseek(pfInputFile, 0, SEEK_SET); pvElf=memalign(128, uiFileSize); if (!pvElf) { printf("Cannot allocate memory for file %s\n", pcFilename); fclose(pfInputFile); return 0; } fread(pvElf, 1, uiFileSize, pfInputFile); fclose(pfInputFile); return pvElf; } void unloadBulletSpursElfs() { #ifdef SCE_EXTERNAL_RELEASE return; #endif for (int iELF=0; iELF6) { return CELL_SPURS_EINVAL; } return initializeSpursTaskSet(pSpurs, iSPUCount, auiPriorities); } /** * Sets the number of SPUs to be used by a Bullet-initialized SPURS. * Valid iSPUCount is in the range 1-6. * Return is: * CELL_SPURS_OK on success * CELL_SPURS_EBUSY if SPU usage has already been initialized * CELL_SPURS_EINVAL if iSPUCount is out of range or if SPURS couldn't be * initialized to that many SPUs. */ int spursConfiguration_initWithSpuCount(int iSPUCount) { if (g_bSpursInitialized) { return CELL_SPURS_EBUSY; } if (iSPUCount<1 || iSPUCount>6) { return CELL_SPURS_EINVAL; } return initializeSpursTaskSet(0, iSPUCount, 0); } /** * Terminates (or disconnects from) SPURS. * Return is: * CELL_SPURS_OK if SPURS terminates ok, or if it was previously terminated/ * never initialized. * CELL_SPURS_EBUSY if there are existing Scenes which would need SPURS. */ int spursConfiguration_terminate() { if (!g_bSpursInitialized) { return CELL_SPURS_OK; } if (g_uiSpursReferenceCounter) { return CELL_SPURS_EBUSY; } int iReturn; bool bUserSpurs=g_bUserSpursGiven; g_bSpursInitialized=false; g_bUserSpursGiven=false; iReturn=cellSpursShutdownTaskset(&g_spursTaskSet); if (iReturn!=CELL_OK) { return -1; //fprintf(stderr, "Bullet: Error shutting down SPURS task set: %i\n", iReturn); } iReturn=cellSpursJoinTaskset(&g_spursTaskSet); if (iReturn!=CELL_OK) { return -2; //fprintf(stderr, "Bullet: Error joining SPURS task set: %i\n", iReturn); } if (!bUserSpurs) { int iReturn=cellSpursFinalize(g_spursInstance); if (iReturn!=CELL_OK) { return -3; //fprintf(stderr, "Bullet: Error shutting down SPURS: %d\n", iReturn); } free(g_spursInstance); } g_spursInstance=0; // Not loading SPURS task from file anymore //unloadBulletSpursElfs(); // printf code is commented out for the time being //#warning TODO: Clean up SPU printf thread. return CELL_SPURS_OK; } /** * Queries whether SPU usage has been initialized. * Return is: * true if initialized. */ bool spursConfiguration_isSpursInitialized() { return g_bSpursInitialized; } SpursSupportInterface::SpursSupportInterface() { //assert(elfId < SPU_ELF_LAST); //m_elfId=elfId; m_bQueueInitialized=false; cellAtomicIncr32(&g_uiSpursReferenceCounter); } SpursSupportInterface::~SpursSupportInterface() { stopSPU(); cellAtomicDecr32(&g_uiSpursReferenceCounter); } int SpursSupportInterface::startSPU() { int iReturn; if (!m_bQueueInitialized) { if (checkSpursTaskSet() != CELL_SPURS_OK) { return -1; } iReturn=cellSpursQueueInitialize(&g_spursTaskSet, &m_responseQueue, m_aResponseBuffer, sizeof(CellSPURSArgument), CELL_SPURS_RESPONSE_QUEUE_SIZE, CELL_SPURS_QUEUE_SPU2PPU); if (iReturn!=CELL_OK) { return -2; } iReturn=cellSpursQueueAttachLv2EventQueue(&m_responseQueue); if (iReturn!=CELL_OK) { return -3; } m_bQueueInitialized=true; } return 0; } int SpursSupportInterface::stopSPU() { if (m_bQueueInitialized) { int iReturn=cellSpursQueueDetachLv2EventQueue(&m_responseQueue); if (iReturn != CELL_OK) return -1; m_bQueueInitialized=false; } return 0; } int SpursSupportInterface::sendRequest(uint32_t uiCommand, uint32_t uiArgument0, uint32_t uiArgument1) { int iReturn; CellSpursTaskId taskId; CellSPURSArgument arguments; arguments.ppuResponseQueue=&m_responseQueue; arguments.uiCommand=uiCommand; arguments.uiArgument0=uiArgument0; arguments.uiArgument1=uiArgument1; if (checkSpursTaskSet() != CELL_SPURS_OK) { return -1; } iReturn=cellSpursCreateTask(&g_spursTaskSet, &taskId, g_SpursTaskElfStart, NULL, 0, 0, &arguments.spursArgument); if (iReturn!=CELL_OK) { return -2; } return 0; } /** * Wait for the SPU to send an event back to our event queue. */ int SpursSupportInterface::waitForResponse(unsigned int *puiArgument0, unsigned int *puiArgument1) { CellSPURSArgument response __attribute__((aligned(16))); int iReturn; iReturn=cellSpursQueuePop(&m_responseQueue, (void *) &response); if (iReturn!=CELL_OK) { return -1; } if (puiArgument0) *puiArgument0=response.uiArgument0; if (puiArgument1) *puiArgument1=response.uiArgument1; return 0; }