1 /*---------------------------------------------------------------------------* 2 Project: Horizon 3 File: gr_Utility.cpp 4 5 Copyright (C)2009-2012 Nintendo Co., Ltd. All rights reserved. 6 7 These coded instructions, statements, and computer programs contain 8 proprietary information of Nintendo of America Inc. and/or Nintendo 9 Company Ltd., and are protected by Federal copyright law. They may 10 not be disclosed to third parties or copied or duplicated in any form, 11 in whole or in part, without the prior written consent of Nintendo. 12 13 $Rev: 48274 $ 14 *---------------------------------------------------------------------------*/ 15 16 #include <nn/gr/CTR/gr_Utility.h> 17 18 #include <nn/gr/CTR/gr_Shader.h> 19 #include <nn/gr/CTR/gr_Vertex.h> 20 #include <nn/gr/CTR/gr_Fog.h> 21 #include <nn/gr/CTR/gr_FragmentLight.h> 22 #include <nn/gr/CTR/gr_Texture.h> 23 #include <nn/gr/CTR/gr_RenderState.h> 24 25 namespace nn 26 { 27 namespace gr 28 { 29 namespace CTR 30 { 31 CommandBufferJumpHelper(bit32 * address)32 CommandBufferJumpHelper::CommandBufferJumpHelper(bit32* address) 33 : m_CurrentPtr(address) 34 , m_StartPtr(address) 35 , m_ReturnPtr(address) 36 , m_CmdSizePtr(0) 37 , m_SizeToFirstJump(0) 38 { 39 } 40 ~CommandBufferJumpHelper()41 CommandBufferJumpHelper::~CommandBufferJumpHelper() 42 { 43 } 44 FinalizeJump(bit32 * endAddress)45 void CommandBufferJumpHelper::FinalizeJump(bit32* endAddress) 46 { 47 m_CurrentPtr = endAddress; 48 49 if ( m_CmdSizePtr ) 50 { 51 *(reinterpret_cast<u32*>(m_CmdSizePtr)) = GetOffsetFromPtr(m_ReturnPtr, m_CurrentPtr) >> 3; 52 } 53 54 m_StartPtr = m_CurrentPtr; 55 m_ReturnPtr = m_CurrentPtr; 56 m_CmdSizePtr = 0; 57 m_SizeToFirstJump = 0; 58 } 59 AddDummyDataForCommandBuffer(bit32 * command,const size_t addSize)60 bit32* AddDummyDataForCommandBuffer( bit32* command, const size_t addSize ) 61 { 62 if ( addSize % 16 ) 63 { 64 int num = (addSize >> 2) % 4; 65 66 for ( int i=4; i>num; --i ) 67 { 68 *command++ = 0; 69 } 70 } 71 return command; 72 } 73 74 // Compiles with ARM code 75 #include <nn/hw/ARM/code32.h> 76 77 //-------------------------------------------------------------------------------- CopyMtx34WithHeader(f32 *,const nn::math::MTX34 *,u32)78 asm void CopyMtx34WithHeader( 79 f32* /* dst */, 80 const nn::math::MTX34* /* src */, 81 u32 /* header */ ) 82 { 83 VLDMIA r1!,{s0-s11} 84 STR r2,[r0,#4] 85 VSTR.F32 s0,[r0,#16] 86 VSTR.F32 s1,[r0,#12] 87 VSTR.F32 s2,[r0,#8] 88 VSTR.F32 s3,[r0,#0] 89 VSTR.F32 s4,[r0,#32] 90 VSTR.F32 s5,[r0,#28] 91 VSTR.F32 s6,[r0,#24] 92 VSTR.F32 s7,[r0,#20] 93 VSTR.F32 s8,[r0,#48] 94 VSTR.F32 s9,[r0,#44] 95 VSTR.F32 s10,[r0,#40] 96 VSTR.F32 s11,[r0,#36] 97 BX lr 98 } 99 100 //-------------------------------------------------------------------------------- 101 CopyMtx44WithHeader(f32 *,const nn::math::MTX44 *,u32)102 asm void CopyMtx44WithHeader( 103 f32* /* dst */, 104 const nn::math::MTX44* /* src */, 105 u32 /* header */ ) 106 { 107 VLDMIA r1!,{s0-s15} 108 STR r2,[r0,#4] 109 VSTR.F32 s0,[r0,#16] 110 VSTR.F32 s1,[r0,#12] 111 VSTR.F32 s2,[r0,#8] 112 VSTR.F32 s3,[r0,#0] 113 VSTR.F32 s4,[r0,#32] 114 VSTR.F32 s5,[r0,#28] 115 VSTR.F32 s6,[r0,#24] 116 VSTR.F32 s7,[r0,#20] 117 VSTR.F32 s8,[r0,#48] 118 VSTR.F32 s9,[r0,#44] 119 VSTR.F32 s10,[r0,#40] 120 VSTR.F32 s11,[r0,#36] 121 VSTR.F32 s12,[r0,#64] 122 VSTR.F32 s13,[r0,#60] 123 VSTR.F32 s14,[r0,#56] 124 VSTR.F32 s15,[r0,#52] 125 BX lr 126 } 127 128 // Restores the original settings 129 #include <nn/hw/ARM/codereset.h> 130 131 //-------------------------------------------------------------------------------- 132 MakeDisableAllCommand(bit32 * command)133 bit32* MakeDisableAllCommand( bit32* command ) 134 { 135 // Disable Shader 136 command = nn::gr::CTR::Shader::MakeDisableCommand( command ); 137 138 // Disable Vertex 139 command = nn::gr::CTR::Vertex::MakeDisableCommand( command ); 140 141 // Disable Fog/Gas 142 command = nn::gr::CTR::Fog::MakeDisableCommand( command ); 143 144 // Disable FragmentLight 145 command = nn::gr::CTR::FragmentLight::MakeDisableCommand( command ); 146 147 // Disable Texture 148 command = nn::gr::CTR::Texture::MakeDisableCommand( command ); 149 150 // Disable Early depth 0x62[0:0] 151 *command++ = 0x0; 152 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_EARLY_DEPTH_TEST1, 0x1 ); 153 // Disable Early depth 0x118[0:0] 154 *command++ = 0x0; 155 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_EARLY_DEPTH_TEST2, 0x1 ); 156 157 // Disable Clipping Plane 0x47[0:0] 158 *command++ = 0x0; 159 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_FRAGOP_CLIP, 0x1 ); 160 161 // Disable RenderState 162 command = nn::gr::CTR::RenderState::MakeDisableCommand( command ); 163 164 // Set 8x8 RenderBlockMode 0x11b[0:0] 165 *command++ = 0x0; 166 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_RENDER_BLOCK_FORMAT ); 167 168 return command; 169 } 170 171 //-------------------------------------------------------------------------------- 172 MakeChannelKickCommand(bit32 * command,const CommandBufferChannel channel)173 bit32* MakeChannelKickCommand( bit32* command, const CommandBufferChannel channel ) 174 { 175 NN_GR_ASSERT( channel == CMD_BUF_CH0 || channel == CMD_BUF_CH1 ); 176 177 // Kick register 0x23c or 0x23d [31:0] (any value is OK) 178 *command++ = 0x1; 179 *command++ = PICA_CMD_HEADER_SINGLE( channel == CMD_BUF_CH0 ? PICA_REG_COMMAND_BUF_KICK_CH0 : PICA_REG_COMMAND_BUF_KICK_CH1 ); 180 181 return command; 182 } 183 184 //------------------------------------------------------------------------------------ 185 MakeChannel0SubroutineCommand(bit32 * command,uptr * bufferSizePtr,const uptr commandBufferPtr,const size_t commandBufferSize)186 bit32* MakeChannel0SubroutineCommand( bit32* command, uptr* bufferSizePtr, 187 const uptr commandBufferPtr, const size_t commandBufferSize ) 188 { 189 // The address of the command buffer specified as the subroutine is 16-byte aligned and the byte size is a multiple of 16 190 NN_GR_ASSERT( (commandBufferPtr >> 3) % 2 == 0 && (commandBufferSize >> 3) % 2 == 0 ); 191 192 // When executed with the subroutine as channel 0 and the return destination as channel 1, all required registers can be set with burst access. 193 194 // Subroutine command buffer size 0x238[20:0] 195 *command++ = commandBufferSize >> 3; 196 *command++ = PICA_CMD_HEADER_BURSTSEQ( PICA_REG_COMMAND_BUF_SIZE_CH0, 5 ); 197 198 // Buffer size after returning from the subroutine 0x239[20:0] 199 // Since it is unknown at this time, enter dummy data and return an address 200 *bufferSizePtr = reinterpret_cast<uptr>(command); 201 *command++ = 0; 202 203 // Subroutine address 0x23a[28:0] 204 *command++ = nngxGetPhysicalAddr(commandBufferPtr) >> 3; 205 206 // Return destination from the subroutine 0x23b[28:0] 207 *command++ = nngxGetPhysicalAddr(reinterpret_cast<uptr>(command + 2)) >> 3; 208 209 // Subroutine kick command 0x23c[31:0] (any value is OK) 210 *command++ = 0x1; 211 212 return command; 213 } 214 MakeChannel1SubroutineCommand(bit32 * command,uptr * bufferSizePtr,const uptr commandBufferPtr,const size_t commandBufferSize)215 bit32* MakeChannel1SubroutineCommand( bit32* command, uptr* bufferSizePtr, 216 const uptr commandBufferPtr, const size_t commandBufferSize ) 217 { 218 // Buffer size after returning from the subroutine 0x238[20:0] 219 // Since it is unknown at this time, enter dummy data and return an address 220 *bufferSizePtr = reinterpret_cast<uptr>(command); 221 *command++ = 0; 222 *command++ = PICA_CMD_HEADER_BURSTSEQ( PICA_REG_COMMAND_BUF_SIZE_CH0, 3 ); 223 224 // Subroutine command buffer size 0x239[20:0] 225 *command++ = commandBufferSize >> 3; 226 227 // Return destination address from the subroutine 0x23a[28:0] 228 *command++ = nngxGetPhysicalAddr(reinterpret_cast<uptr>(command + 5)) >> 3; 229 230 // Subroutine address 0x23b[28:0] 231 *command++ = nngxGetPhysicalAddr(commandBufferPtr) >> 3; 232 233 // Dummy data (for 64-bit alignment) 234 *command++ = 0; 235 236 // Kick register 0x23d [31:0] (any value is OK) 237 *command++ = 0x1; 238 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_COMMAND_BUF_KICK_CH1 ); 239 240 return command; 241 } 242 243 //------------------------------------------------------------------------------------ 244 MakeChannel0JumpCommand(bit32 * command,const uptr commandBufferPtr,const size_t commandBufferSize)245 bit32* MakeChannel0JumpCommand( bit32* command, const uptr commandBufferPtr, const size_t commandBufferSize ) 246 { 247 // The address of the command buffer specified as the subroutine is 16-byte aligned and the byte size is a multiple of 16 248 NN_GR_ASSERT( (commandBufferPtr >> 3) % 2 == 0 && (commandBufferSize >> 3) % 2 == 0 ); 249 250 // Command buffer size 0x238 or 0x239[20:0] 251 *command++ = commandBufferSize >> 3; 252 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_COMMAND_BUF_SIZE_CH0, 0x7 ); 253 254 // Command buffer address 0x23a or 0x23b[28:0] 255 *command++ = nngxGetPhysicalAddr(commandBufferPtr) >> 3; 256 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_COMMAND_BUF_ADDR_CH0 ); 257 258 // Kick register 0x23c or 0x23d [31:0] (any value is OK) 259 *command++ = 0x1; 260 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_COMMAND_BUF_KICK_CH0 ); 261 262 return command; 263 } 264 265 //------------------------------------------------------------------------------------ 266 MakeChannel1JumpCommand(bit32 * command,const uptr commandBufferPtr,const size_t commandBufferSize)267 bit32* MakeChannel1JumpCommand( bit32* command, const uptr commandBufferPtr, const size_t commandBufferSize ) 268 { 269 // The address of the command buffer specified as the subroutine is 16-byte aligned and the byte size is a multiple of 16 270 NN_GR_ASSERT( (commandBufferPtr >> 3) % 2 == 0 && (commandBufferSize >> 3) % 2 == 0 ); 271 272 // Command buffer size 0x238 or 0x239[20:0] 273 *command++ = commandBufferSize >> 3; 274 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_COMMAND_BUF_SIZE_CH1, 0x7 ); 275 276 // Command buffer address 0x23a or 0x23b[28:0] 277 *command++ = nngxGetPhysicalAddr(commandBufferPtr) >> 3; 278 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_COMMAND_BUF_ADDR_CH1 ); 279 280 // Kick register 0x23c or 0x23d [31:0] (any value is OK) 281 *command++ = 0x1; 282 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_COMMAND_BUF_KICK_CH1 ); 283 284 return command; 285 } 286 MakePostVertexCacheEntryTypeCommand(bit32 * command,const PostVertexCacheEntryType type)287 bit32* MakePostVertexCacheEntryTypeCommand( bit32* command, const PostVertexCacheEntryType type ) 288 { 289 NN_GR_ASSERT( type == POST_VERTEX_CACHE_ENTRY_TYPE_32 || type == POST_VERTEX_CACHE_ENTRY_TYPE_16 ); 290 291 // Register 0x22d [7:0] specifies number of entries in the post-vertex cache (do not access other bits) 292 *command++ = ( type == POST_VERTEX_CACHE_ENTRY_TYPE_32 ? 0x04 : 0x84 ); 293 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_POST_VERTEX_CACHE_NUM, 0x1 ); 294 295 return command; 296 } 297 } // namespace CTR 298 } // namespace gr 299 } // namespace nn 300