essentially : get commandIndex and totalCommands, calculate offset of new command, copy command and update totalCommands use LDREX/STREX because this data may also be accessed by the GSP module and we don't want to break stuff (mostly, we could overwrite the buffer header with wrong data and make the GSP module reexecute old commands)
| 402 | //use LDREX/STREX because this data may also be accessed by the GSP module and we don't want to break stuff |
| 403 | //(mostly, we could overwrite the buffer header with wrong data and make the GSP module reexecute old commands) |
| 404 | Result gspSubmitGxCommand(const u32 gxCommand[0x8]) |
| 405 | { |
| 406 | u32* sharedGspCmdBuf = (u32*)((u8*)gspSharedMem + 0x800 + gspThreadId*0x200); |
| 407 | u32 cmdBufHeader = __ldrex((s32*)sharedGspCmdBuf); |
| 408 | |
| 409 | u8 commandIndex=cmdBufHeader&0xFF; |
| 410 | u8 totalCommands=(cmdBufHeader>>8)&0xFF; |
| 411 | |
| 412 | if(totalCommands>=15)return -2; |
| 413 | |
| 414 | u8 nextCmd=(commandIndex+totalCommands)%15; //there are 15 command slots |
| 415 | u32* dst=&sharedGspCmdBuf[8*(1+nextCmd)]; |
| 416 | memcpy(dst, gxCommand, 0x20); |
| 417 | |
| 418 | __dsb(); |
| 419 | totalCommands++; |
| 420 | cmdBufHeader=((cmdBufHeader)&0xFFFF00FF)|(((u32)totalCommands)<<8); |
| 421 | |
| 422 | while(1) |
| 423 | { |
| 424 | if (!__strex((s32*)sharedGspCmdBuf, cmdBufHeader)) break; |
| 425 | |
| 426 | cmdBufHeader = __ldrex((s32*)sharedGspCmdBuf); |
| 427 | totalCommands=((cmdBufHeader&0xFF00)>>8)+1; |
| 428 | cmdBufHeader=((cmdBufHeader)&0xFFFF00FF)|((totalCommands<<8)&0xFF00); |
| 429 | } |
| 430 | |
| 431 | if(totalCommands==1)return GSPGPU_TriggerCmdReqQueue(); |
| 432 | return 0; |
| 433 | } |
| 434 | |
| 435 | Result GSPGPU_WriteHWRegs(u32 regAddr, const u32* data, u8 size) |
| 436 | { |
no test coverage detected