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