1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     gx_FragmentLightingSimpleCmd.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: 47228 $
14  *---------------------------------------------------------------------------*/
15 
16 #include <nn/os.h>
17 #include <nn/fnd.h>
18 #include <nn/gx.h>
19 #include <nn/math.h>
20 #include <nn/fs.h>
21 #include <nn/init.h>
22 #include <nn/applet.h>
23 
24 #include "MemoryManager.h"
25 
26 #include "nn/gx/CTR/gx_CommandAccess.h"
27 
28 namespace
29 {
30     GLuint s_CmdlistID = 0;
31     GLuint s_FramebufferID = 0;
32     GLuint s_RenderbufferID[2];
33     GLuint s_Displaybuffer0ID[2];
34     GLuint s_Displaybuffer1ID[2];
35     GLint s_CurrentDisplaybuffer0 = 0;
36     GLint s_CurrentDisplaybuffer1 = 0;
37 
38     nn::fnd::ExpHeap s_AppHeap;
39     uptr s_HeapForGx;
40     const u32 s_GxHeapSize = 0x800000;
41 
42     nn::math::Vector3 s_CameraPosition(0.0f, 1.0f, 4.0f);
43     nn::math::Vector3 s_CameraUp(0.0f, 1.0f, 0.0f);
44     nn::math::Vector3 s_CameraTarget(0.0f, 0.0f, 0.0f);
45 
46     nn::math::Matrix34 s_ViewMatrix;
47 
48     u32 s_MaterialShininess = 8;
49 
50     GLuint s_ArrayBufferID = 0;
51     GLuint s_ElementArrayBufferID = 0;
52 
53     GLfloat* s_VertexArray = NULL;
54     GLushort* s_IndexArray = NULL;
55 
56     const u32 LUT_TABLE_SIZE = 512;
57     const u32 LUT_TABLE_HALF_SIZE = LUT_TABLE_SIZE / 2;
58     GLfloat s_LutArray[LUT_TABLE_SIZE];
59 
60     u32 s_VertexAttributeBaseAddress    = 0x0;
61     u32 s_VertexAttribute0AddressOffset = 0x0;
62     u32 s_VertexAttribute1AddressOffset = 0x0;
63     u32 s_VertexAttribute2AddressOffset = 0x0;
64     u32 s_VertexIndexAddressOffset      = 0x0;
65     u32 s_VertexNum = 4;
66     u32 s_IndexNum = 6;
67 
68     const u32 FRAME_COUNTER_THRE = 60;
69     u32 s_FrameCount = 0;
70 }
71 
72 void InitializeGraphics(void);
73 void InitializeVBO(void);
74 void InitializeD0Lut(const u32 materialShininess);
75 
76 void AddDepthBufferCommand(void);
77 
78 void UpdateCamera(void);
79 
80 void DrawDisplay0(void);
81 void DrawDisplay1(void);
82 void AddViewportCommand(const s32 display);
83 
84 void AddFirstDrawCommand(void);
85 void AddVertexShaderCommand(void);
86 void AddVertexAttributeCommand(void);
87 void AddVertexShaderUniformCommand(void);
88 void AddTextureCombinerCommand(void);
89 void AddFragmentLightCommand(void);
90 void AddLUTCommand(void);
91 
92 void AddDrawPlaneCommand(void);
93 
94 void AddFrameBufferControlCommand(void);
95 
Initialize(void)96 void Initialize(void)
97 {
98     // fs initialization
99     nn::fs::Initialize();
100 
101     const size_t ROMFS_BUFFER_SIZE = 1024 * 64;
102     static char buffer[ROMFS_BUFFER_SIZE];
103     NN_UTIL_PANIC_IF_FAILED(
104         nn::fs::MountRom(16, 16, buffer, ROMFS_BUFFER_SIZE));
105 
106     InitializeGraphics();
107 }
108 
InitializeVBO(void)109 void InitializeVBO(void)
110 {
111     u32 positionSize = sizeof(GLfloat) * 4 * s_VertexNum;
112     u32 colorSize = sizeof(GLfloat) * 4 * s_VertexNum;
113     u32 normalSize = sizeof(GLfloat) * 3 * s_VertexNum;
114     u32 vertexSize = positionSize + colorSize + normalSize;
115     u32 indexSize = sizeof(GLushort) * s_IndexNum;
116 
117     GLenum arrayFlag        = GL_ARRAY_BUFFER | NN_GX_MEM_FCRAM | GL_NO_COPY_FCRAM_DMP;
118     GLenum elementArrayFlag = GL_ELEMENT_ARRAY_BUFFER | NN_GX_MEM_FCRAM | GL_NO_COPY_FCRAM_DMP;
119 
120     s_VertexArray = (GLfloat*) demo::memory_manager::Alloc(NN_GX_MEM_VERTEXBUFFER, vertexSize);
121 
122     u32 vertexArrayPhysicalAddress = nngxGetPhysicalAddr( (uptr) s_VertexArray );
123     // NN_LOG("s_VertexArray = 0x%x, Physical address = 0x%p\n", s_VertexArray, vertexArrayPhysicalAddress);
124 
125     f32 s_HalfEdge = 2.0f;
126 
127     // Position
128     s_VertexArray[0] = s_HalfEdge;
129     s_VertexArray[1] = 0.0f;
130     s_VertexArray[2] = s_HalfEdge;
131     s_VertexArray[3] = 1.0f;
132 
133     s_VertexArray[4] = (- s_HalfEdge);
134     s_VertexArray[5] = 0.0f;
135     s_VertexArray[6] = s_HalfEdge;
136     s_VertexArray[7] = 1.0f;
137 
138     s_VertexArray[8]  = (- s_HalfEdge);
139     s_VertexArray[9]  = 0.0f;
140     s_VertexArray[10] = (- s_HalfEdge);
141     s_VertexArray[11] =  1.0f;
142 
143     s_VertexArray[12] = s_HalfEdge;
144     s_VertexArray[13] = 0.0f;
145     s_VertexArray[14] = (- s_HalfEdge);
146     s_VertexArray[15] = 1.0f;
147 
148     // Color
149     u32 offset = 4 * s_VertexNum;
150     s_VertexArray[offset + 0] = 1.0f;
151     s_VertexArray[offset + 1] = 0.0f;
152     s_VertexArray[offset + 2] = 0.0f;
153     s_VertexArray[offset + 3] = 0.0f;
154 
155     s_VertexArray[offset + 4] = 0.0f;
156     s_VertexArray[offset + 5] = 1.0f;
157     s_VertexArray[offset + 6] = 0.0f;
158     s_VertexArray[offset + 7] = 0.0f;
159 
160     s_VertexArray[offset +  8] = 0.0f;
161     s_VertexArray[offset +  9] = 0.0f;
162     s_VertexArray[offset + 10] = 1.0f;
163     s_VertexArray[offset + 11] = 1.0f;
164 
165     s_VertexArray[offset + 12] = 1.0f;
166     s_VertexArray[offset + 13] = 1.0f;
167     s_VertexArray[offset + 14] = 0.0f;
168     s_VertexArray[offset + 15] = 1.0f;
169 
170     // Normal
171     offset += 16;
172 
173     s_VertexArray[offset + 0] = 0.0f;
174     s_VertexArray[offset + 1] = 1.0f;
175     s_VertexArray[offset + 2] = 0.0f;
176 
177     s_VertexArray[offset + 3] = 0.0f;
178     s_VertexArray[offset + 4] = 1.0f;
179     s_VertexArray[offset + 5] = 0.0f;
180 
181     s_VertexArray[offset + 6] = 0.0f;
182     s_VertexArray[offset + 7] = 1.0f;
183     s_VertexArray[offset + 8] = 0.0f;
184 
185     s_VertexArray[offset +  9] = 0.0f;
186     s_VertexArray[offset + 10] = 1.0f;
187     s_VertexArray[offset + 11] = 0.0f;
188 
189     s_IndexArray = (GLushort*) demo::memory_manager::Alloc(NN_GX_MEM_VERTEXBUFFER, indexSize);
190 
191     u32 indexArrayPhysicalAddress = nngxGetPhysicalAddr( (uptr) s_IndexArray);
192     // NN_LOG("s_IndexArray = 0x%x, physical address = 0x%p\n", s_IndexArray, indexArrayPhysicalAddress);
193 
194     // Index
195     s_IndexArray[0] = 0;
196     s_IndexArray[1] = 2;
197     s_IndexArray[2] = 1;
198 
199     s_IndexArray[3] = 0;
200     s_IndexArray[4] = 3;
201     s_IndexArray[5] = 2;
202 
203     glGenBuffers(1, &s_ArrayBufferID);
204     glBindBuffer(GL_ARRAY_BUFFER, s_ArrayBufferID);
205     glBufferData(arrayFlag, vertexSize, s_VertexArray, GL_STATIC_DRAW);
206 
207     glGenBuffers(1, &s_ElementArrayBufferID);
208     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s_ElementArrayBufferID);
209     glBufferData(elementArrayFlag, indexSize, s_IndexArray, GL_STATIC_DRAW);
210 
211     // Base address is aligned to 16 bytes
212     u32 alignOffset = (uptr)vertexArrayPhysicalAddress % 16;
213     u32 baseAddress = vertexArrayPhysicalAddress - alignOffset;
214 
215     s_VertexAttributeBaseAddress = PICA_CMD_DATA_VERTEX_ATTR_ARRAYS_BASE_ADDR(baseAddress);
216     s_VertexAttribute0AddressOffset = vertexArrayPhysicalAddress - baseAddress;
217     s_VertexAttribute1AddressOffset = alignOffset + positionSize;
218     s_VertexAttribute2AddressOffset = alignOffset + positionSize + colorSize;
219     s_VertexIndexAddressOffset = indexArrayPhysicalAddress - baseAddress;
220 }
221 
InitializeGraphics(void)222 void InitializeGraphics(void)
223 {
224     s_AppHeap.Initialize(nn::os::GetDeviceMemoryAddress(),
225         nn::os::GetDeviceMemorySize() );
226     s_HeapForGx = reinterpret_cast<uptr>(s_AppHeap.Allocate(s_GxHeapSize));
227 
228     demo::memory_manager::InitializeMemoryManager(s_HeapForGx, s_GxHeapSize);
229     nngxInitialize(demo::memory_manager::GetAllocator, demo::memory_manager::GetDeallocator);
230 
231     /* Generate and allocate command list object */
232     nngxGenCmdlists(1, &s_CmdlistID);
233     nngxBindCmdlist(s_CmdlistID);
234     nngxCmdlistStorage(0x40000, 128);
235 
236     /* Generate, allocate and attach framebuffer object and render buffer */
237     glGenFramebuffers(1, &s_FramebufferID);
238     glBindFramebuffer(GL_FRAMEBUFFER, s_FramebufferID);
239 
240     glGenRenderbuffers(2, s_RenderbufferID);
241     glBindRenderbuffer(GL_RENDERBUFFER, s_RenderbufferID[0]);
242     glRenderbufferStorage(GL_RENDERBUFFER | NN_GX_MEM_VRAMA, GL_RGBA8_OES,
243                           nn::gx::DISPLAY0_WIDTH, nn::gx::DISPLAY0_HEIGHT);
244     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, s_RenderbufferID[0]);
245 
246     glBindRenderbuffer(GL_RENDERBUFFER, s_RenderbufferID[1]);
247     glRenderbufferStorage(GL_RENDERBUFFER | NN_GX_MEM_VRAMB, GL_DEPTH24_STENCIL8_EXT,
248                           nn::gx::DISPLAY0_WIDTH, nn::gx::DISPLAY0_HEIGHT);
249     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, s_RenderbufferID[1]);
250 
251     /* Generate and allocate display buffer; set display region */
252     nngxGenDisplaybuffers(2, s_Displaybuffer0ID);
253     nngxActiveDisplay(NN_GX_DISPLAY0);
254     nngxDisplayEnv(0, 0);
255     nngxBindDisplaybuffer(s_Displaybuffer0ID[0]);
256     nngxDisplaybufferStorage(GL_RGB8_OES, nn::gx::DISPLAY0_WIDTH, nn::gx::DISPLAY0_HEIGHT, NN_GX_MEM_FCRAM);
257 
258     nngxBindDisplaybuffer(s_Displaybuffer0ID[1]);
259     nngxDisplaybufferStorage(GL_RGB8_OES, nn::gx::DISPLAY0_WIDTH, nn::gx::DISPLAY0_HEIGHT, NN_GX_MEM_FCRAM);
260 
261     nngxGenDisplaybuffers(2, s_Displaybuffer1ID);
262     nngxActiveDisplay(NN_GX_DISPLAY1);
263     nngxDisplayEnv(0, 0);
264     nngxBindDisplaybuffer(s_Displaybuffer1ID[0]);
265     nngxDisplaybufferStorage(GL_RGB8_OES, nn::gx::DISPLAY0_WIDTH, nn::gx::DISPLAY0_HEIGHT, NN_GX_MEM_FCRAM);
266 
267     nngxBindDisplaybuffer(s_Displaybuffer1ID[1]);
268     nngxDisplaybufferStorage(GL_RGB8_OES, nn::gx::DISPLAY0_WIDTH, nn::gx::DISPLAY0_HEIGHT, NN_GX_MEM_FCRAM);
269 
270     nngxRunCmdlist();
271 
272     glClearColor(0.3f, 0.3f, 0.3f, 1.0f);
273     glClearDepthf(1.0f);
274 
275     AddDepthBufferCommand();
276 
277     glEnable(GL_CULL_FACE);
278     glFrontFace(GL_CCW);
279     glCullFace(GL_BACK);
280 
281     InitializeD0Lut(s_MaterialShininess);
282     InitializeVBO();
283 }
284 
285 
AddDepthBufferCommand(void)286 void AddDepthBufferCommand(void)
287 {
288     /*
289     glEnable(GL_DEPTH_TEST);
290     glDepthFunc(GL_LESS);
291     */
292 
293     u32 commandBuffer[] =
294     {
295         // Depth test
296         // 0x107
297         PICA_CMD_DATA_DEPTH_COLOR_MASK(
298             // enableDepthTest
299             1,
300             // depthFunc
301             PICA_DATA_DEPTH_TEST_LESS,
302             // red, green, blue, alpha
303             0, 0, 0, 0,
304             // depthMask
305             0),
306         PICA_CMD_HEADER_SINGLE_BE(PICA_REG_DEPTH_COLOR_MASK, 0x1),
307 
308         // dmp_Gas.deltaZ
309         // 0x126 [25:24]
310         PICA_CMD_DATA_GAS_DELTAZ_DEPTH(0, PICA_DATA_DEPTH_TEST2_OTHER),
311         PICA_CMD_HEADER_SINGLE_BE(PICA_REG_GAS_DELTAZ_DEPTH, 0x8),
312     };
313 
314     nngxAdd3DCommand(commandBuffer, sizeof(commandBuffer), GL_TRUE);
315 }
316 
AddViewportCommand(s32 display)317 void AddViewportCommand(s32 display)
318 {
319     if ( display == NN_GX_DISPLAY0 )
320     {
321         // glViewport(0, 0, nn::gx::DISPLAY0_WIDTH, nn::gx::DISPLAY0_HEIGHT);
322         u32 commandBuffer[] =
323         {
324             // Set the Viewport width (set width to f32, divide by two, and convert to f24)
325             // 0x41
326             0x45E000, PICA_CMD_HEADER_SINGLE(PICA_REG_VIEWPORT_WIDTH1),
327 
328             // Set the Viewport height (set height to f32, divide by two, and convert to f24)
329             // 0x43
330             0x469000, PICA_CMD_HEADER_SINGLE(PICA_REG_VIEWPORT_HEIGHT1),
331 
332             // Set Viewport width (Divide 2 by width, convert to f31, and shift 1 bit left)
333             // 0x42
334             0x38111111, PICA_CMD_HEADER_SINGLE(PICA_REG_VIEWPORT_WIDTH2),
335 
336             // Set Viewport height (Divide 2 by height, convert to f31, and shift 1 bit left)
337             // 0x44
338             0x3747AE14, PICA_CMD_HEADER_SINGLE(PICA_REG_VIEWPORT_HEIGHT2),
339 
340             // x = 0, y = 0
341             // 0x68
342             PICA_CMD_DATA_VIEWPORT_XY(0, 0),  PICA_CMD_HEADER_SINGLE(PICA_REG_VIEWPORT_XY)
343         };
344 
345         nngxAdd3DCommand(commandBuffer, sizeof(commandBuffer), GL_TRUE);
346     }
347     else if ( display == NN_GX_DISPLAY1 )
348     {
349         // glViewport(0, 0, nn::gx::DISPLAY1_WIDTH, nn::gx::DISPLAY1_HEIGHT);
350         u32 commandBuffer[] =
351         {
352             // Set the Viewport width (set width to f32, divide by two, and convert to f24)
353             // 0x41
354             0x45E000, PICA_CMD_HEADER_SINGLE(PICA_REG_VIEWPORT_WIDTH1),
355 
356             // Set the Viewport height (set height to f32, divide by two, and convert to f24)
357             // 0x43
358             0x464000, PICA_CMD_HEADER_SINGLE(PICA_REG_VIEWPORT_HEIGHT1),
359 
360             // Set Viewport width (Divide 2 by width, convert to f31, and shift 1 bit left)
361             // 0x42
362             0x38111111, PICA_CMD_HEADER_SINGLE(PICA_REG_VIEWPORT_WIDTH2),
363 
364             // Set Viewport height (Divide 2 by height, convert to f31, and shift 1 bit left)
365             // 0x44
366             0x37999999, PICA_CMD_HEADER_SINGLE(PICA_REG_VIEWPORT_HEIGHT2),
367 
368             // x = 0, y = 0
369             // 0x68
370             PICA_CMD_DATA_VIEWPORT_XY(0, 0),  PICA_CMD_HEADER_SINGLE(PICA_REG_VIEWPORT_XY)
371         };
372 
373         nngxAdd3DCommand(commandBuffer, sizeof(commandBuffer), GL_TRUE);
374     }
375 }
376 
InitializeD0Lut(const u32 materialShininess)377 void InitializeD0Lut(const u32 materialShininess)
378 {
379     for (u32 index = 0; index < LUT_TABLE_SIZE; index++)
380     {
381         s_LutArray[index] = 0.0f;
382     }
383 
384     for (u32 j = 0; j < LUT_TABLE_HALF_SIZE; j++)
385     {
386         f32 value = 1.0f;
387         for (u32 count = 0; count < materialShininess; count++)
388         {
389             value *= (j / 255.0f);
390         }
391         s_LutArray[j] = value;
392     }
393 
394     for (u32 j = 0; j < (LUT_TABLE_HALF_SIZE - 1); j++)
395     {
396         s_LutArray[j + LUT_TABLE_HALF_SIZE] = s_LutArray[j + 1] - s_LutArray[j];
397     }
398     s_LutArray[(LUT_TABLE_HALF_SIZE - 1) + LUT_TABLE_HALF_SIZE] =
399         1.0f - s_LutArray[LUT_TABLE_HALF_SIZE - 1];
400 }
401 
Finalize(void)402 void Finalize(void)
403 {
404     if ( s_VertexArray != NULL )
405     {
406         demo::memory_manager::Free(s_VertexArray);
407         s_VertexArray = NULL;
408     }
409 
410     if ( s_IndexArray != NULL )
411     {
412         demo::memory_manager::Free(s_IndexArray);
413         s_IndexArray = NULL;
414     }
415 
416     nngxFinalize();
417 
418     s_AppHeap.Free(reinterpret_cast<void*>( s_HeapForGx) );
419     s_AppHeap.Finalize();
420 }
421 
DrawFrame(void)422 bool DrawFrame(void)
423 {
424     UpdateCamera();
425 
426     DrawDisplay0();
427     DrawDisplay1();
428 
429     nngxActiveDisplay(NN_GX_DISPLAY0);
430     nngxBindDisplaybuffer(s_Displaybuffer0ID[s_CurrentDisplaybuffer0]);
431 
432     nngxActiveDisplay(NN_GX_DISPLAY1);
433     nngxBindDisplaybuffer(s_Displaybuffer1ID[s_CurrentDisplaybuffer1]);
434 
435     nngxSwapBuffers(NN_GX_DISPLAY_BOTH);
436 
437     s_CurrentDisplaybuffer0 = (s_CurrentDisplaybuffer0 == 0 ? 1 : 0);
438     s_CurrentDisplaybuffer1 = (s_CurrentDisplaybuffer1 == 0 ? 1 : 0);
439 
440     nngxClearCmdlist();
441     nngxRunCmdlist();
442 
443     nngxWaitVSync(NN_GX_DISPLAY_BOTH);
444 
445     if ( s_FrameCount == 0 )
446     {
447         nngxStartLcdDisplay();
448     }
449 
450     if ( ( s_FrameCount % FRAME_COUNTER_THRE) == 0 )
451     {
452         NN_LOG("Total frame count = %d\n", s_FrameCount);
453     }
454 
455     s_FrameCount += 1;
456 
457     return true;
458 }
459 
UpdateCamera(void)460 void UpdateCamera(void)
461 {
462     nn::math::MTX34LookAt(&s_ViewMatrix, s_CameraPosition, s_CameraUp, s_CameraTarget);
463 }
464 
DrawDisplay0(void)465 void DrawDisplay0(void)
466 {
467     static bool firstFlag = true;
468 
469     glBindFramebuffer(GL_FRAMEBUFFER, s_FramebufferID);
470     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
471     AddViewportCommand(NN_GX_DISPLAY0);
472 
473     if ( firstFlag )
474     {
475         AddFirstDrawCommand();
476         firstFlag = false;
477     }
478 
479     AddDrawPlaneCommand();
480 
481     nngxSplitDrawCmdlist();
482     nngxRunCmdlist();
483     nngxWaitCmdlistDone();
484 
485     nngxTransferRenderImage(s_Displaybuffer0ID[s_CurrentDisplaybuffer0], NN_GX_ANTIALIASE_NOT_USED, GL_FALSE, 0, 0);
486 }
487 
AddFirstDrawCommand(void)488 void AddFirstDrawCommand(void)
489 {
490     AddVertexShaderCommand();
491     AddVertexAttributeCommand();
492     AddVertexShaderUniformCommand();
493 
494     AddFragmentLightCommand();
495     AddLUTCommand();
496 }
497 
498 
AddVertexShaderCommand(void)499 void AddVertexShaderCommand(void)
500 {
501     /*
502     s_ProgramId = glCreateProgram();
503 
504     // Load vertex shader
505     s_ShaderId = glCreateShader(GL_VERTEX_SHADER);
506     nn::fs::FileReader file(L"rom:/shader.shbin");
507     size_t fileSize = file.GetSize();
508     void* buf = s_AppHeap.Allocate(fileSize);
509     s32 read = file.Read(buf, fileSize);
510     glShaderBinary(1, &s_ShaderId, GL_PLATFORM_BINARY_DMP, buf, read);
511     file.Finalize();
512     s_AppHeap.Free(buf);
513 
514     glAttachShader(s_ProgramId, s_ShaderId);
515     glAttachShader(s_ProgramId, GL_DMP_FRAGMENT_SHADER_DMP);
516 
517     glBindAttribLocation(s_ProgramId, 0, "aPosition");
518     glBindAttribLocation(s_ProgramId, 1, "aColor");
519     glBindAttribLocation(s_ProgramId, 2, "aNormal");
520 
521     glLinkProgram(s_ProgramId);
522     glValidateProgram(s_ProgramId);
523     */
524 
525     {
526         u32 commandBuffer[] =
527         {
528             // 0x229
529             // Do not use geometry shader
530             PICA_CMD_SET_VS_GS_MODE(0, 0),
531             // Do not use geometry shader
532             // 0x244 : 0x0 (BE 0x1)
533             PICA_CMD_SET_VS_COM_MODE(0x0),
534             // Set the load address for the vertex shader program code to 0
535             // 0x2CB : 0x0 (BE 0xF)
536             PICA_CMD_DATA_VS_PROG_ADDR(0x0), PICA_CMD_HEADER_SINGLE(PICA_REG_VS_PROG_ADDR)
537         };
538 
539         nngxAdd3DCommand(commandBuffer, sizeof(commandBuffer), GL_TRUE);
540     }
541 
542     {
543         u32 commandBuffer[] =
544         {
545             // Vertex shader program data
546             // BurstSingle (28 times, BE 0xF)
547             // 0x2CC : 0xBE24000
548             0xBE24000, PICA_CMD_HEADER_BURST(PICA_REG_VS_PROG_DATA0, 28),
549 
550             // 0x2CC : 0xBE25001
551             // 0x2CC : 0xBE26002
552             0xBE25001, 0xBE26002,
553 
554             // 0x2CC : 0xBE27003
555             // 0x2CC : 0x7C26102
556             0xBE27003, 0x7C26102,
557 
558             // 0x2CC : 0x7C24100
559             // 0x2CC : 0x7C25101
560             0x7C24100, 0x7C25101,
561 
562             // 0x2CC : 0x4C41F004
563             // 0x2CC : 0x8020F80
564             0x4C41F004, 0x8020F80,
565 
566             // 0x2CC : 0x8021F81
567             // 0x2CC : 0xB807DF05
568             0x8021F81, 0xB807DF05,
569 
570             // 0x2CC : 0x287DF06
571             // 0x2CC : 0x8022F82
572             0x287DF06, 0x8022F82,
573 
574             // 0x2CC : 0x8023F83
575             // 0x2CC : 0x2287EA07
576             0x8023F83, 0x2287EA07,
577 
578             // 0x2CC : 0x4C27D008
579             // 0x2CC : 0x3E814009
580             0x4C27D008, 0x3E814009,
581 
582             // 0x2CC : 0x22A7EF07
583             // 0x2CC : 0xA1805401
584             0x22A7EF07, 0xA1805401,
585 
586             // 0x2CC : 0x3821400A
587             // 0x2CC : 0x20215A0B
588             0x3821400A, 0x20215A0B,
589 
590             // 0x2CC : 0x4C27D00C
591             // 0x2CC : 0x84000000
592             0x4C27D00C, 0x84000000,
593 
594             // 0x2CC : 0x84000000
595             // 0x2CC : 0x90000017
596             0x84000000, 0x90000017,
597 
598             // 0x2CC : 0x4C60100D
599             // 0x2CC : 0x88000000
600             0x4C60100D, 0x88000000,
601 
602             // 0x2CC : 0x84000000
603             0x84000000, 0x0
604         };
605 
606         nngxAdd3DCommand(commandBuffer, sizeof(commandBuffer), GL_TRUE);
607     }
608 
609     {
610         u32 commandBuffer[] =
611         {
612             // Notification that update of vertex shader program is complete
613             // 0x2BF : 0x1 (BE 0xF)
614             PICA_CMD_DATA_VS_PROG_END(0x1), PICA_CMD_HEADER_SINGLE(PICA_REG_VS_PROG_UPDATE_END)
615         };
616 
617         nngxAdd3DCommand(commandBuffer, sizeof(commandBuffer), GL_TRUE);
618     }
619 
620     {
621         u32 commandBuffer[] =
622         {
623             // Set the Swizzle pattern's load address to 0
624             // 0x2D5 : 0x0 (BE 0xF)
625             PICA_CMD_DATA_VS_PROG_SWIZZLE_ADDR(0x0), PICA_CMD_HEADER_SINGLE(PICA_REG_VS_PROG_SWIZZLE_ADDR),
626 
627             // Set the Swizzle pattern's data
628             // BurstSingle (14 times, BE 0xF)
629             // 0x2D6 : 0x8006C368
630             PICA_CMD_DATA_VS_PROG_SWIZZLE_DATA(0x8006C368), PICA_CMD_HEADER_BURST(PICA_REG_VS_PROG_SWIZZLE_DATA0, 14),
631 
632             // 0x2D6 : 0x8006C364
633             // 0x2D6 : 0x8006C362
634             PICA_CMD_DATA_VS_PROG_SWIZZLE_DATA(0x8006C364), PICA_CMD_DATA_VS_PROG_SWIZZLE_DATA(0x8006C362),
635 
636             // 0x2D6 : 0x8006C361
637             // 0x2D6 : 0x8000037F
638             PICA_CMD_DATA_VS_PROG_SWIZZLE_DATA(0x8006C361), PICA_CMD_DATA_VS_PROG_SWIZZLE_DATA(0x8000037F),
639 
640             // 0x2D6 : 0x802A8AB0
641             // 0x2D6 : 0x802A8AAF
642             PICA_CMD_DATA_VS_PROG_SWIZZLE_DATA(0x802A8AB0), PICA_CMD_DATA_VS_PROG_SWIZZLE_DATA(0x802A8AAF),
643 
644             // 0x2D6 : 0x8006D54F
645             // 0x2D6 : 0x80000001
646             PICA_CMD_DATA_VS_PROG_SWIZZLE_DATA(0x8006D54F), PICA_CMD_DATA_VS_PROG_SWIZZLE_DATA(0x80000001),
647 
648             // 0x2D6 : 0x8000000F
649             // 0x2D6 : 0x80000002
650             PICA_CMD_DATA_VS_PROG_SWIZZLE_DATA(0x8000000F), PICA_CMD_DATA_VS_PROG_SWIZZLE_DATA(0x80000002),
651 
652             // 0x2D6 : 0x8006C36C
653             // 0x2D6 : 0x8000080E
654             PICA_CMD_DATA_VS_PROG_SWIZZLE_DATA(0x8006C36C), PICA_CMD_DATA_VS_PROG_SWIZZLE_DATA(0x8000080E),
655 
656             // 0x2D6 : 0x8000036F
657             PICA_CMD_DATA_VS_PROG_SWIZZLE_DATA(0x8000036F), PICA_CMD_DATA_VS_PROG_SWIZZLE_DATA(0x0),
658         };
659 
660         nngxAdd3DCommand(commandBuffer, sizeof(commandBuffer), GL_TRUE);
661     }
662 
663      {
664         u32 commandBuffer[] =
665         {
666             // BurstSequence (4 times, BE 0xF)
667             // 0x2C0 : 0x5D
668             PICA_CMD_DATA_VS_FLOAT_ADDR(PICA_DATA_VS_F24, 0x5D),
669             PICA_CMD_HEADER_BURSTSEQ(PICA_REG_VS_FLOAT_ADDR, 0x4),
670 
671             // 0x2C1 : 0x40800040
672             // 0x2C2 : 0x3F00
673             PICA_CMD_DATA_VS_FLOAT_DATA(0x40800040), PICA_CMD_DATA_VS_FLOAT_DATA(0x3F00),
674 
675             // 0x2C3 : 0x0
676             PICA_CMD_DATA_VS_FLOAT_DATA(0x0), PICA_CMD_DATA_VS_FLOAT_DATA(0x0)
677         };
678 
679         nngxAdd3DCommand(commandBuffer, sizeof(commandBuffer), GL_TRUE);
680      }
681 
682      {
683         u32 commandBuffer[] =
684         {
685             // BurstSequence (4 times, BE 0xF)
686             // 0x2C0 : 0x5E
687             PICA_CMD_DATA_VS_FLOAT_ADDR(PICA_DATA_VS_F24, 0x5E),
688             PICA_CMD_HEADER_BURSTSEQ(PICA_REG_VS_FLOAT_ADDR, 0x4),
689 
690             // 0x2C1 : 0x3D00003E
691             // 0x2C2 : 0x3700
692             PICA_CMD_DATA_VS_FLOAT_DATA(0x3D00003E), PICA_CMD_DATA_VS_FLOAT_DATA(0x3700),
693 
694             // 0x2C3 : 0x3C0000
695             PICA_CMD_DATA_VS_FLOAT_DATA(0x3C0000), PICA_CMD_DATA_VS_FLOAT_DATA(0x0)
696         };
697 
698         nngxAdd3DCommand(commandBuffer, sizeof(commandBuffer), GL_TRUE);
699      }
700 }
701 
AddVertexAttributeCommand(void)702 void AddVertexAttributeCommand(void)
703 {
704     {
705         u32 commandBuffer[] =
706         {
707             // BurstSequence (39 times, BE 0xF)
708 
709             // Common base address for all vertex arrays
710             // 0x200 : BaseAddress
711             s_VertexAttributeBaseAddress, PICA_CMD_HEADER_BURSTSEQ(PICA_REG_VERTEX_ATTR_ARRAYS_BASE_ADDR, 39),
712 
713             // 0x201 : 0xBFF
714             //   Attribute0  [3:0] 0xF : size=4, GL_FLOAT
715             //   Attribute1  [7:4] 0xF : size=4, GL_FLOAT
716             //   Attribute1 [11:8] 0xB : size=3, GL_FLOAT
717             //
718             // 0x202 : 0x20000000
719             //   [31:28] TotalVertexAttributeNum - 1
720             0xBFF, 0x20000000,
721 
722             // 0x203 : 0x8
723             //   Byte offset from the the base address of load array 0
724             //
725             // 0x204 : 0x0
726             //   [3:0] The 1st element of load array 0 is internal vertex attribute 0
727             s_VertexAttribute0AddressOffset, 0x0,
728 
729             // 0x205 : 0x10100000
730             //   [23:16] : Number of bytes per vertex in load array 0: 16 (Bytes)
731             //   [31:28] : Number of elements in load array 0: 1
732             //
733             // 0x206 : 0x30
734             //   Byte offset from the the base address of load array 1
735             0x10100000, s_VertexAttribute1AddressOffset,
736 
737             // 0x207 : 0x1
738             //   [3:0] The 1st element of load array 1 is internal vertex attribute 1
739             //
740             // 0x208 : 0x10100000
741             //   [23:16] : Number of bytes per vertex in load array 1: 16 (Bytes)
742             //   [31:28] : Number of elements in load array 1: 1
743             0x1, 0x10100000,
744 
745             // 0x209 : 0x88
746             // 0x20A : 0x2 internal vertex attribute 2
747             s_VertexAttribute2AddressOffset, 0x2,
748 
749             // 0x20B : 0x100C0000
750             //   [23:16] : Number of bytes per vertex in load array 1: 12 (Bytes)
751             //   [31:28] : Number of elements in load array 1: 1
752             // 0x20C : 0x0
753             0x100C0000, 0x0,
754 
755             // 0x20D : 0x0
756             // 0x20E : 0x0
757             0x0, 0x0,
758 
759             // 0x20F : 0x0
760             // 0x210 : 0x0
761             0x0, 0x0,
762 
763             // 0x211 : 0x0
764             // 0x212 : 0x0
765             0x0, 0x0,
766 
767             // 0x213 : 0x0
768             // 0x214 : 0x0
769             0x0, 0x0,
770 
771             // 0x215 : 0x0
772             // 0x216 : 0x0
773             0x0, 0x0,
774 
775             // 0x217 : 0x0
776             // 0x218 : 0x0
777             0x0, 0x0,
778 
779             // 0x219 : 0x0
780             // 0x21A : 0x0
781             0x0, 0x0,
782 
783             // 0x21B : 0x0
784             // 0x21C : 0x0
785             0x0, 0x0,
786 
787             // 0x21D : 0x0
788             // 0x21E : 0x0
789             0x0, 0x0,
790 
791             // 0x21F : 0x0
792             // 0x220 : 0x0
793             0x0, 0x0,
794 
795             // 0x221 : 0x0
796             // 0x222 : 0x0
797             0x0, 0x0,
798 
799             // 0x223 : 0x0
800             // 0x224 : 0x0
801             0x0, 0x0,
802 
803             // 0x225 : 0x0
804             // 0x226 : 0x0
805             0x0, 0x0
806         };
807 
808         nngxAdd3DCommand(commandBuffer, sizeof(commandBuffer), GL_TRUE);
809     }
810 
811     {
812         u32 commandBuffer[] =
813         {
814             // 0x2BB : 0x210 (BE 0xF)
815             // Register that sets the input register map for vertex attributes 0-8
816             //   [3:0] = 0 (The index of the input register for the storage location of the first vertex attribute that was input)
817             //   [7:4] = 1 (The index of the input register for the storage location of the second vertex attribute that was input)
818             //  [11:8] = 2 (The index of the input register for the storage location of the third vertex attribute that was input)
819             PICA_CMD_DATA_VS_ATTR_IN_REG_MAP0(0, 1, 2, 0, 0, 0, 0, 0),
820             PICA_CMD_HEADER_SINGLE(PICA_REG_VS_ATTR_IN_REG_MAP0),
821 
822             // 0x2BC : 0x0 (BE 0xF)
823             // Register that sets the input register map for vertex attributes 9-12
824             PICA_CMD_DATA_VS_ATTR_IN_REG_MAP1(0, 0, 0, 0),
825             PICA_CMD_HEADER_SINGLE(PICA_REG_VS_ATTR_IN_REG_MAP1)
826         };
827 
828         nngxAdd3DCommand(commandBuffer, sizeof(commandBuffer), GL_TRUE);
829     }
830 
831     /*
832     glEnableVertexAttribArray(0);
833     glEnableVertexAttribArray(1);
834     glEnableVertexAttribArray(2);
835 
836     glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0) ;
837     glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, (GLvoid*) positionSize);
838     glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*) (positionSize + colorSize) );
839     */
840     {
841         u32 commandBuffer[] =
842         {
843             // Register that sets the number of vertex attribute inputs.
844             //
845             // 0x2B9 : 0xA0000000 | 0x2 (BE 0xB = 1011(2) )
846             // PICA_CMD_DATA_VS_ATTR_NUM0(0x3), PICA_CMD_HEADER_SINGLE_BE(PICA_REG_VS_ATTR_NUM0, 0xB),
847             //
848             // 0x242 : 0x2 (BE 0xF)
849             // PICA_CMD_DATA_VS_ATTR_NUM1(0x3), PICA_CMD_HEADER_SINGLE(PICA_REG_VS_ATTR_NUM1)
850             PICA_CMD_SET_VS_ATTR_NUM(0x3),
851 
852             // Register that sets the number of vertex attributes to input to the vertex shader
853             //
854             // 0x4F : 0x4
855             // 0x4, PICA_CMD_HEADER_SINGLE(PICA_REG_VS_OUT_REG_NUM0)
856             //
857             // 0x24A : 0x3 (BE 0xF)
858             // 0x4 - 0x1, PICA_CMD_HEADER_SINGLE(PICA_REG_VS_OUT_REG_NUM1),
859             //
860             // 0x251 [3:0] : 0x3 (BE 0xF)
861             // 0x4 - 0x1, PICA_CMD_HEADER_SINGLE(PICA_REG_VS_OUT_REG_NUM2),
862             PICA_CMD_SET_VS_GS_OUT_REG_NUM(0x4),
863 
864             // 0x2BA [15:0]  : Sets the data address of the vertex shader
865             //       [31:16] : Sets 0x7FFF
866             // 0x7FFF0018 (BE 0xF)
867             PICA_CMD_DATA_VS_START_ADDR(0x18), PICA_CMD_HEADER_SINGLE(PICA_REG_VS_START_ADDR),
868 
869             // 0x2BD : 0x3 (BE 0xF)
870             // Set the mask for the vertex shader output register (o0 = [0:0], o1 = [1;1])
871             PICA_CMD_DATA_VS_OUT_MASK(0xF), PICA_CMD_HEADER_SINGLE(PICA_REG_VS_OUT_REG_MASK),
872 
873             // Register that sets the vertex shader output attribute
874             // 0x50 : 0x3020100 (BE 0xF)
875             // #pragma output_map ( position, o0 )
876             //   [ 4: 0] : Vertex coordinate x, 0x00
877             //   [12: 8] : Vertex coordinate y, 0x01
878             //   [20:16] : Vertex coordinate z, 0x02
879             //   [28:24] : Vertex coordinate w, 0x03
880             PICA_CMD_DATA_VS_GS_OUT_ATTR(PICA_DATA_VS_OUT_ATTR_X,
881                 PICA_DATA_VS_OUT_ATTR_Y, PICA_DATA_VS_OUT_ATTR_Z,
882                 PICA_DATA_VS_OUT_ATTR_W),
883             PICA_CMD_HEADER_SINGLE(PICA_REG_VS_OUT_ATTR0),
884 
885             // Register that sets the vertex shader output attribute
886             // 0x51 : 0x7060504 (BE 0xF)
887             // #pragma output_map ( quaternion, o1 )
888             //   [ 4: 0] : Quaternion x, 0x04
889             //   [12: 8] : Quaternion y, 0x05
890             //   [20:16] : Quaternion z, 0x06
891             //   [28:24] : Quaternion w, 0x07
892             PICA_CMD_DATA_VS_GS_OUT_ATTR(PICA_DATA_VS_OUT_ATTR_QUART_X,
893                 PICA_DATA_VS_OUT_ATTR_QUART_Y, PICA_DATA_VS_OUT_ATTR_QUART_Z,
894                 PICA_DATA_VS_OUT_ATTR_QUART_W),
895             PICA_CMD_HEADER_SINGLE(PICA_REG_VS_OUT_ATTR1),
896 
897             // Register that sets the vertex shader output attribute
898             // 0x52 : 0x1F141312
899             // #pragma output_map ( view, o2 )
900             //   [ 4: 0] : View vector x, 0x12
901             //   [12: 8] : View vector y, 0x13
902             //   [20:16] : View vector z, 0x14
903             //   [28:24] : Invalid, 0x1f
904             PICA_CMD_DATA_VS_GS_OUT_ATTR(PICA_DATA_VS_OUT_ATTR_VIEW_X,
905                 PICA_DATA_VS_OUT_ATTR_VIEW_Y, PICA_DATA_VS_OUT_ATTR_VIEW_Z,
906                 PICA_DATA_VS_OUT_ATTR_INVALID),
907             PICA_CMD_HEADER_SINGLE(0x52),
908 
909             // 0x53 : 0xB0A0908
910             // #pragma output_map ( color, o3 )
911             //   [ 4: 0] : Vertex color R, 0x08
912             //   [12: 8] : Vertex color G, 0x09
913             //   [20:16] : Vertex color B, 0x0a
914             //   [28:24] : Vertex color A, 0x0b
915             PICA_CMD_DATA_VS_GS_OUT_ATTR(PICA_DATA_VS_OUT_ATTR_R,
916                 PICA_DATA_VS_OUT_ATTR_G, PICA_DATA_VS_OUT_ATTR_B,
917                 PICA_DATA_VS_OUT_ATTR_A),
918             PICA_CMD_HEADER_SINGLE(0x53),
919 
920             // Clock control setting register for output attributes from the vertex shader
921             // 0x6F : 0x1000003 (BE 0xF)
922             // Output vertex coordinates z, output vertex colors, output view vectors, and quaternions
923             //
924             PICA_CMD_DATA_VS_GS_OUT_ATTR_CLK(1, 1, 0, 0, 0, 0, 1), PICA_CMD_HEADER_SINGLE(PICA_REG_VS_OUT_ATTR_CLK)
925         };
926 
927         nngxAdd3DCommand(commandBuffer, sizeof(commandBuffer), GL_TRUE);
928     }
929 }
930 
AddVertexShaderUniformCommand(void)931 void AddVertexShaderUniformCommand(void)
932 {
933     /*
934     // Upper screen vertex uniform settings
935     nn::math::Matrix44 s_Display0ProjectionMatrix;
936     nn::math::Matrix44 s_Display1ProjectionMatrix;
937 
938     nn::math::MTX34LookAt(&s_ViewMatrix, s_CameraPosition, s_CameraUp, s_CameraTarget);
939     nn::math::MTX44 modelViewMatrix(s_ViewMatrix);
940 
941     nn::math::Matrix44 worldMatrix;
942     MTX44Identity(&worldMatrix);
943     nn::math::MTX44Mult(&modelViewMatrix, &modelViewMatrix, &worldMatrix);
944 
945     glUniformMatrix4fv(demo::s_UniformLocations[demo::VERTEX_UNIFORM_MODELVIEW],
946         1, GL_TRUE, static_cast<f32*>(modelViewMatrix));
947 
948     glUniformMatrix4fv(demo::s_UniformLocations[demo::VERTEX_UNIFORM_PROJECTION],
949         1, GL_TRUE, static_cast<f32*>(s_Display0ProjectionMatrix));
950     */
951 
952     {
953         u32 commandBuffer[] =
954         {
955             // Index of floating-point registers for vertex shader
956             // 0x2C0 : 0x80000000 (BE 0xF)
957             PICA_CMD_DATA_VS_FLOAT_ADDR(PICA_DATA_VS_F32, 0x0),
958             PICA_CMD_HEADER_SINGLE(PICA_REG_VS_FLOAT_ADDR)
959         };
960 
961         nngxAdd3DCommand(commandBuffer, sizeof(commandBuffer), GL_TRUE);
962     }
963 
964     {
965         u32 commandBuffer[] =
966         {
967             // Settings for floating-point registers of the vertex shader
968             // BurstSingle (32 times, BE 0xF)
969             // 0x2C1 : 0x0
970             PICA_CMD_DATA_VS_FLOAT(0x0), PICA_CMD_HEADER_BURST(PICA_REG_VS_FLOAT1, 32),
971 
972             // 0x2C1 : 0x0
973             // 0x2C1 : 0x401A8279
974             PICA_CMD_DATA_VS_FLOAT(0x0), PICA_CMD_DATA_VS_FLOAT(0x401A8279),
975 
976             // 0x2C1 : 0x0
977             // 0x2C1 : 0x80000000
978             PICA_CMD_DATA_VS_FLOAT(0x0), PICA_CMD_DATA_VS_FLOAT(0x80000000),
979 
980             // 0x2C1 : 0x80000000
981             // 0x2C1 : 0x80000000
982             PICA_CMD_DATA_VS_FLOAT(0x80000000), PICA_CMD_DATA_VS_FLOAT(0x80000000),
983 
984             // 0x2C1 : 0xBFB9695E
985             // 0x2C1 : 0x3DCDD443
986             PICA_CMD_DATA_VS_FLOAT(0xBFB9695E), PICA_CMD_DATA_VS_FLOAT(0x3DCDD443),
987 
988             // 0x2C1 : 0x3F80A4AA
989             // 0x2C1 : 0x0
990             PICA_CMD_DATA_VS_FLOAT(0x3F80A4AA), PICA_CMD_DATA_VS_FLOAT(0x0),
991 
992             // 0x2C1 : 0x0
993             // 0x2C1 : 0x0
994             PICA_CMD_DATA_VS_FLOAT(0x0), PICA_CMD_DATA_VS_FLOAT(0x0),
995 
996             // 0x2C1 : 0xBF800000
997             // 0x2C1 : 0x0
998             PICA_CMD_DATA_VS_FLOAT(0xBF800000), PICA_CMD_DATA_VS_FLOAT(0x0),
999 
1000             // 0x2C1 : 0x0
1001             // 0x2C1 : 0x0
1002             PICA_CMD_DATA_VS_FLOAT(0x0), PICA_CMD_DATA_VS_FLOAT(0x0),
1003 
1004             // 0x2C1 : 0x0
1005             // 0x2C1 : 0x0
1006             PICA_CMD_DATA_VS_FLOAT(0x0), PICA_CMD_DATA_VS_FLOAT(0x0),
1007 
1008             // 0x2C1 : 0x3F800000
1009             // 0x2C1 : 0x0
1010             PICA_CMD_DATA_VS_FLOAT(0x3F800000), PICA_CMD_DATA_VS_FLOAT(0x0),
1011 
1012             // 0x2C1 : 0xBE785B43
1013             // 0x2C1 : 0x3F785B43
1014             PICA_CMD_DATA_VS_FLOAT(0xBE785B43), PICA_CMD_DATA_VS_FLOAT(0x3F785B43),
1015 
1016             // 0x2C1 : 0x0
1017             // 0x2C1 : 0xC083F07C
1018             PICA_CMD_DATA_VS_FLOAT(0x0), PICA_CMD_DATA_VS_FLOAT(0xC083F07C),
1019 
1020             // 0x2C1 : 0x3F785B43
1021             // 0x2C1 : 0x3E785B43
1022             PICA_CMD_DATA_VS_FLOAT(0x3F785B43), PICA_CMD_DATA_VS_FLOAT(0x3E785B43),
1023 
1024             // 0x2C1 : 0x0
1025             // 0x2C1 : 0x3F800000
1026             PICA_CMD_DATA_VS_FLOAT(0x0), PICA_CMD_DATA_VS_FLOAT(0x3F800000),
1027 
1028             // 0x2C1 : 0x0
1029             // 0x2C1 : 0x0
1030             PICA_CMD_DATA_VS_FLOAT(0x0), PICA_CMD_DATA_VS_FLOAT(0x0),
1031 
1032             // 0x2C1 : 0x0
1033             PICA_CMD_DATA_VS_FLOAT(0x0), PICA_CMD_DATA_VS_FLOAT(0x0)
1034         };
1035 
1036         nngxAdd3DCommand(commandBuffer, sizeof(commandBuffer), GL_TRUE);
1037     }
1038 
1039     {
1040         u32 commandBuffer[] =
1041         {
1042             // Vertex shader Boolean register
1043             // 0x2B0 : 0x7FFF0000 (BE 0xF)
1044             PICA_CMD_DATA_VS_BOOL(0x0), PICA_CMD_HEADER_SINGLE(PICA_REG_VS_BOOL),
1045 
1046             // Vertex shader integer register i0
1047             // 0x2B1 : 0x0 (BE 0xF)
1048             PICA_CMD_DATA_VS_INT(0x0, 0x0, 0x0), PICA_CMD_HEADER_SINGLE(PICA_REG_VS_INT0),
1049 
1050             // Vertex shader integer register i1
1051             // 0x2B2 : 0x0 (BE 0xF)
1052             PICA_CMD_DATA_VS_INT(0x0, 0x0, 0x0), PICA_CMD_HEADER_SINGLE(PICA_REG_VS_INT1),
1053 
1054             // Vertex shader integer register i2
1055             // 0x2B3 : 0x0 (BE 0xF)
1056             PICA_CMD_DATA_VS_INT(0x0, 0x0, 0x0), PICA_CMD_HEADER_SINGLE(PICA_REG_VS_INT2),
1057 
1058             // Vertex shader integer register i3
1059             // 0x2B4 : 0x0 (BE 0xF)
1060             PICA_CMD_DATA_VS_INT(0x0, 0x0, 0x0), PICA_CMD_HEADER_SINGLE(PICA_REG_VS_INT3)
1061         };
1062 
1063         nngxAdd3DCommand(commandBuffer, sizeof(commandBuffer), GL_TRUE);
1064     }
1065 }
1066 
AddTextureCombinerCommand(void)1067 void AddTextureCombinerCommand(void)
1068 {
1069     {
1070         u32 commandBuffer[] =
1071         {
1072             // 0xd0 : 0xF210F21 (BE 0xF)
1073             // srcRgb, srcAlpha
1074             // glUniform3i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_SRC_RGB],
1075             //     GL_FRAGMENT_PRIMARY_COLOR_DMP, GL_FRAGMENT_SECONDARY_COLOR_DMP, GL_PREVIOUS);
1076             // glUniform3i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_SRC_ALPHA],
1077             //     GL_FRAGMENT_PRIMARY_COLOR_DMP, GL_FRAGMENT_SECONDARY_COLOR_DMP, GL_PREVIOUS);
1078             PICA_CMD_DATA_TEX_ENV_SRC(PICA_DATA_TEX_ENV_SRC_RGBA_FRAGMENT_PRIMARY_COLOR_DMP,
1079                                       PICA_DATA_TEX_ENV_SRC_RGBA_FRAGMENT_SECONDARY_COLOR_DMP,
1080                                       PICA_DATA_TEX_ENV_SRC_RGBA_PREVIOUS,
1081                                       PICA_DATA_TEX_ENV_SRC_RGBA_FRAGMENT_PRIMARY_COLOR_DMP,
1082                                       PICA_DATA_TEX_ENV_SRC_RGBA_FRAGMENT_SECONDARY_COLOR_DMP,
1083                                       PICA_DATA_TEX_ENV_SRC_RGBA_PREVIOUS),
1084             PICA_CMD_HEADER_SINGLE(PICA_REG_TEX_ENV2),
1085 
1086             // combineRgb, combineAlpha
1087             // 0xd2 : 0x20002 (BE 0xF)
1088             // glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_COMBINE_RGB], GL_ADD);
1089             // glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_COMBINE_ALPHA], GL_ADD);
1090             PICA_CMD_DATA_TEX_ENV_COMBINE(PICA_DATA_TEX_ENV_COMBINE_ADD, PICA_DATA_TEX_ENV_COMBINE_ADD),
1091             PICA_CMD_HEADER_SINGLE(PICA_REG_TEX_ENV2_COMBINE)
1092          };
1093 
1094          nngxAdd3DCommand(commandBuffer, sizeof(commandBuffer), GL_TRUE);
1095     }
1096 }
1097 
AddFragmentLightCommand(void)1098 void AddFragmentLightCommand(void)
1099 {
1100     /*
1101     // LightEnv
1102     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_LIGHT_ENV_CONFIG], GL_LIGHT_ENV_LAYER_CONFIG0_DMP);
1103     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_LIGHT_ENV_LUT_ENABLED_REFL], GL_FALSE);
1104     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_LIGHT_ENV_CLAMP_HIGHLIGHTS], GL_TRUE);
1105 
1106     // D0
1107     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_LIGHT_ENV_ABS_LUT_INPUT_D0], GL_TRUE);
1108     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_LIGHT_ENV_LUT_INPUT_D0], GL_LIGHT_ENV_NH_DMP);
1109     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_MATERIAL_SAMPLER_D0], 0);
1110 
1111     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE0_GEOM_FACTOR1], GL_FALSE);
1112     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE0_GEOM_FACTOR0], GL_FALSE);
1113     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE0_TWO_SIDE_DIFFUSE], GL_FALSE);
1114 
1115     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE1_ENABLED], GL_FALSE);
1116     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE2_ENABLED], GL_FALSE);
1117     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE3_ENABLED], GL_FALSE);
1118     */
1119 
1120     // Enable FragmentLight
1121     // glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHTING_ENABLED], GL_TRUE);
1122     // 0x8F : 0x1 (BE 0xF)
1123     // 0x1C6 : 0x0 (BE 0xF)
1124     {
1125         u32 commandBuffer[] =
1126         {
1127             PICA_CMD_SET_FRAG_LIGHT_ENABLE(0x1)
1128         };
1129 
1130         nngxAdd3DCommand(commandBuffer, sizeof(commandBuffer), GL_TRUE);
1131     }
1132 
1133     AddTextureCombinerCommand();
1134 
1135     // 0x1c2
1136     // glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE0_ENABLED], GL_TRUE);
1137 
1138     {
1139         // Light0 specular0, 0x140 : 0xFF3FCFF (BE 0xF)
1140         // glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_MATERIAL_SPECULAR0], 1, s_MaterialSpecular0);
1141         // glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_MATERIAL_SPECULAR1], 1, s_MaterialSpecular1);
1142         // glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE0_SPECULAR0], 1, s_Light0.m_Specular0);
1143         // glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE0_SPECULAR1], 1, s_Light0.m_Specular1);
1144         // dmp_FragmentMaterial.specular0 * dmp_FragmentLightSource[0].specular0
1145         // dmp_FragmentMaterial.specular1 * dmp_FragmentLightSource[0].specular1
1146 
1147         // Fragment uniform : Material
1148         // f32 s_MaterialSpecular0[] = {1.0f, 1.0f, 1.0f, 1.0f};
1149         // f32 s_MaterialSpecular1[] = {0.0f, 0.0f, 0.0f, 1.0f};
1150         // s_Light0.m_Specular0[0] = 1.0f;
1151         // s_Light0.m_Specular0[1] = 1.0f;
1152         // s_Light0.m_Specular0[2] = 1.0f;
1153         // s_Light0.m_Specular0[3] = 1.0f;
1154         // s_Light0.m_Specular1[0] = 0.0.0f;
1155         // s_Light0.m_Specular1[1] = 0.0.0f;
1156         // s_Light0.m_Specular1[2] = 0.0.0f;
1157         // s_Light0.m_Specular1[3] = 1.0f;
1158 
1159         u32 commandBuffer[] =
1160         {
1161             0xff3fcff, PICA_CMD_HEADER_SINGLE(PICA_REG_FRAG_LIGHT_START)
1162         };
1163 
1164         nngxAdd3DCommand(commandBuffer, sizeof(commandBuffer), GL_TRUE);
1165     }
1166 
1167     {
1168         u32 commandBuffer[] =
1169         {
1170             // Light0 diffuse,     0x142 h: 0x9900000
1171             // f32 s_MaterialDiffuse[] = {0.6f, 0.6f, 0.6f, 1.0f};
1172             // s_Light0.m_Diffuse[0] = 1.0f;
1173             // s_Light0.m_Diffuse[1] = 0.0.0f;
1174             // s_Light0.m_Diffuse[2] = 0.0.0f;
1175             // s_Light0.m_Diffuse[3] = 1.0f;
1176             // glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_MATERIAL_DIFFUSE], 1, s_MaterialDiffuse);
1177             // glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE0_DIFFUSE], 1, s_Light0.m_Diffuse);
1178             //   dmp_FragmentMaterial.diffuse * dmp_FragmentLightSource[0].diffuse
1179             0x9900000,
1180             // BurstSequence (4 times, BE 0xF)
1181             PICA_CMD_HEADER_BURSTSEQ(PICA_REG_FRAG_LIGHT0_DIFFUSE, 0x4),
1182 
1183             // Light0 ambient,     0x143 : 0xA0280A
1184             // f32 s_MaterialAmbient[] = {0.2f, 0.2f, 0.2f, 1.0f};
1185             // s_Light0.m_Ambient[0] = 0.2f;
1186             // s_Light0.m_Ambient[1] = 0.2f;
1187             // s_Light0.m_Ambient[2] = 0.2f;
1188             // s_Light0.m_Ambient[3] = 1.0f;
1189             // glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE0_AMBIENT], 1, s_Light0.m_Ambient);
1190             // glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_MATERIAL_AMBIENT], 1, s_MaterialAmbient);
1191             //   dmp_FragmentMaterial.ambient * dmp_FragmentLightSource[0].ambient
1192             0xA0280A,
1193 
1194             // Light0 position_xy, 0x144 : 0x3BC20000
1195             // s_Light0.m_Position[0] = 0.0f;
1196             // s_Light0.m_Position[1] = 1.0.0f;
1197             // s_Light0.m_Position[2] = 0.0f;
1198 
1199             // nn::math::MTX34 s_LightWorldMatrix;
1200             // nn::math::MTX34Identity(&s_LightWorldMatrix);
1201             // nn::math::VEC3 position(s_Light0.m_Position[0], s_Light0.m_Position[1], s_Light0.m_Position[2]);
1202             // nn::math::MTX34Translate(&s_LightWorldMatrix, &position);
1203             // nn::math::Matrix34 lightViewMatrix;
1204             // nn::math::MTX34Mult(&lightViewMatrix, s_ViewMatrix, s_LightWorldMatrix);
1205             // glUniform4f(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE0_POSITION],
1206             //     lightViewMatrix.m[0][3], lightViewMatrix.m[1][3], lightViewMatrix.m[2][3],
1207             //     1.0f);
1208             // dmp_FragmentLightSource[i].position xy
1209             0x3BC20000,
1210 
1211             // Light0 position_z,  0x145 : 0xC3C2
1212             // dmp_FragmentLightSource[i].position z
1213             0xC3C2, 0x0,
1214 
1215             // Light0 position.w   0x149 : 0x0
1216             // dmp_FragmentLightSource[i].position w
1217             0x0, PICA_CMD_HEADER_SINGLE(PICA_REG_FRAG_LIGHT0_TYPE)
1218         };
1219 
1220         nngxAdd3DCommand(commandBuffer, sizeof(commandBuffer), GL_TRUE);
1221     }
1222 
1223     u32 fragLightFuncMode = 0;
1224 
1225     u32 shadowed = 0;
1226     u32 spotEnabled = 0;
1227     u32 distanceAttenuationEnabled = 0;
1228     for (u32 lightIndex = 0; lightIndex < 8; lightIndex++)
1229     {
1230         fragLightFuncMode |= PICA_CMD_DATA_FRAG_LIGHT_FUNC_MODE1_LIGHT_SOURCE(lightIndex,
1231             shadowed, spotEnabled, distanceAttenuationEnabled);
1232     }
1233 
1234     u32 lutEnabledD0 = 1;
1235     u32 lutEnabledD1 = 0;
1236     u32 fresnelSelector = 0;
1237     u32 lutEnabledRef1 = 0;
1238     fragLightFuncMode |= PICA_CMD_DATA_FRAG_LIGHT_FUNC_MODE1_LUT(lutEnabledD0,
1239             lutEnabledD1, fresnelSelector, lutEnabledRef1);
1240     {
1241         u32 commandBuffer[] =
1242         {
1243             // 0x1C0 : 0x1405014 (BE 0xF)
1244             // f32 s_GlobalAmbientLight[] = { 0.4f,  0.4f,  0.4f, 1.0f};
1245             // glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHTING_AMBIENT], 1, s_GlobalAmbientLight);
1246             0x1405014, PICA_CMD_HEADER_SINGLE(PICA_REG_FRAG_LIGHT_AMBIENT),
1247 
1248             // 0x1C4 : 0xFFFEFFFF (BE 0xF)
1249             // glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_LIGHT_ENV_LUT_ENABLED_D0], GL_TRUE);
1250             fragLightFuncMode,
1251             PICA_CMD_HEADER_SINGLE(PICA_REG_FRAG_LIGHT_FUNC_MODE1),
1252 
1253             // 0x1D0 : 0x2222220 (BE 0xF)
1254             PICA_CMD_DATA_FRAG_LIGHT_ABSLUTINPUT(1, 0, 0, 0, 0, 0, 0),
1255             PICA_CMD_HEADER_SINGLE(PICA_REG_FRAG_LIGHT_ABSLUTINPUT)
1256         };
1257 
1258         nngxAdd3DCommand(commandBuffer, sizeof(commandBuffer), GL_TRUE);
1259     }
1260 }
1261 
1262 // Convert from float32 to unsigned fixed12 (12-bit fraction)
1263 #define UTL_F2UFX_12W_0I(_inarg, _outarg) \
1264    { \
1265         float f_ = (_inarg); \
1266         unsigned val_; \
1267         unsigned v_ = *(unsigned*)&f_; \
1268         if (f_ <= 0 || (v_ & 0x7f800000) == 0x7f800000) \
1269             val_ = 0; \
1270         else \
1271         { \
1272             f_ *= 1 << (12 - 0); \
1273             if (f_ >= (1 << 12)) \
1274                 val_ = (1 << 12) - 1; \
1275             else \
1276                 val_ = (unsigned)(f_); \
1277         } \
1278         (_outarg) = val_; \
1279     }
1280 
1281 // Convert from float32 to signed fixed12 (11-bit fraction)
1282 #define UTL_F2FX_12W_1I_F(_inarg, _outarg) \
1283     { \
1284         float f_; \
1285         unsigned v_; \
1286         f_ = (_inarg); \
1287         v_ = *(unsigned*)&f_; \
1288         if (f_ == 0.f || (v_ & 0x7f800000) == 0x7f800000) \
1289             _outarg = 0; \
1290         else \
1291         { \
1292             f_ *= (1 << (12 - 1)); \
1293             if (f_ < 0) \
1294             { \
1295                 _outarg = 1 << (12 - 1); \
1296                 f_ = -f_; \
1297             } \
1298             else \
1299                 _outarg = 0; \
1300             if (f_ >= (1 << (12 - 1))) f_ = (1 << (12 - 1)) - 1; \
1301             _outarg |= (unsigned)(f_); \
1302         } \
1303     }
1304 
AddLUTCommand(void)1305 void AddLUTCommand(void)
1306 {
1307     /*
1308     GLenum target = GL_LUT_TEXTURE0_DMP;
1309     glGenTextures(1, &s_D0LutTextureId);
1310     glBindTexture(GL_LUT_TEXTURE0_DMP, s_D0LutTextureId);
1311     glTexImage1D(target, 0, GL_LUMINANCEF_DMP, LUT_TABLE_SIZE,
1312         0, GL_LUMINANCEF_DMP, GL_FLOAT, s_LutArray);
1313     */
1314 
1315     {
1316         u32 commandBuffer[] =
1317         {
1318             // 0x1C5 : 0x0 (BE 0xF)
1319             PICA_CMD_DATA_FRAG_LIGHT_LUT(0x0, PICA_DATA_SAMPLER_D0),
1320             PICA_CMD_HEADER_SINGLE(PICA_REG_FRAG_LIGHT_LUT)
1321         };
1322 
1323         nngxAdd3DCommand(commandBuffer, sizeof(commandBuffer), GL_TRUE);
1324     }
1325 
1326     // 0x1C8
1327     u32 old_data = 0;
1328     for (u32 i = 0; i < LUT_TABLE_HALF_SIZE; i++)
1329     {
1330         u32 index0 = i;
1331         u32 index1 = i + 256;
1332 
1333         // Convert from float32 to unsigned fixed12 (12-bit fraction)
1334         u32 data0 = 0;
1335         UTL_F2UFX_12W_0I(s_LutArray[index0], data0);
1336         data0 &= 0xfff;
1337 
1338         // Convert from float32 to signed fixed12 (11-bit fraction)
1339         u32 data1 = 0;
1340         UTL_F2FX_12W_1I_F(s_LutArray[index1], data1);
1341         data1 &= 0xfff;
1342 
1343         u32 data = PICA_CMD_DATA_FRAG_LIGHT_LUT_DATA(data0, data1);
1344 
1345         if ( i == 0 )
1346         {
1347             u32 commandBuffer[] =
1348             {
1349                 data, PICA_CMD_HEADER_BURST(PICA_REG_FRAG_LIGHT_LUT_DATA0, LUT_TABLE_HALF_SIZE)
1350             };
1351 
1352             nngxAdd3DCommand(commandBuffer, sizeof(commandBuffer), GL_TRUE);
1353         }
1354         else if ( i == (LUT_TABLE_HALF_SIZE - 1) )
1355         {
1356             u32 commandBuffer[] =
1357             {
1358                 data, 0x0
1359             };
1360 
1361             nngxAdd3DCommand(commandBuffer, sizeof(commandBuffer), GL_TRUE);
1362         }
1363         else if ( (i % 2) == 1 )
1364         {
1365             old_data = data;
1366         }
1367         else if ( (i % 2) == 0 )
1368         {
1369             u32 commandBuffer[] =
1370             {
1371                 old_data, data
1372             };
1373 
1374             nngxAdd3DCommand(commandBuffer, sizeof(commandBuffer), GL_TRUE);
1375         }
1376     }
1377 }
1378 
AddDrawPlaneCommand(void)1379 void AddDrawPlaneCommand(void)
1380 {
1381     AddFrameBufferControlCommand();
1382 
1383     {
1384         u32 commandBuffer[] =
1385         {
1386             // 0x229
1387             // Using glDrawElements function and GL_TRIANGLES, so drawMode = 1
1388             PICA_CMD_SET_DRAW_MODE0(1)
1389         };
1390 
1391         nngxAdd3DCommand(commandBuffer, sizeof(commandBuffer), GL_TRUE);
1392     }
1393 
1394     // glDrawElements(GL_TRIANGLES, indexNum, GL_UNSIGNED_SHORT, 0);
1395     {
1396         u32 commandBuffer[] =
1397         {
1398             // 0x253 [0:8]
1399             // Using glDrawElements function and GL_TRIANGLES, so [8:8] = 1
1400             0x100,
1401             PICA_CMD_HEADER_SINGLE_BE( PICA_REG_DRAW_MODE1, 0x2 ),
1402 
1403             // 0x25e [9:8]
1404             // Using glDrawElements function and mode = GL_TRIANGLES, so [9:8] = PICA_DATA_DRAW_TRIANGLES = 3
1405             PICA_CMD_SET_DRAW_MODE2(PICA_DATA_DRAW_TRIANGLES),
1406 
1407             // Clear the internal states of vertex indices when drawing triangles
1408             // 0x25f
1409             PICA_CMD_DATA_START_DRAW_FUNC1(0x1),
1410             PICA_CMD_HEADER_SINGLE(PICA_REG_START_DRAW_FUNC1),
1411 
1412             // 0x253[0:0] is set equal to 0 when nngxInitialize() is run, so this is unnecessary.
1413             // 0x253 [0:0]
1414             // Using vertex buffer and glDrawElements function, so [0:0] = 0
1415             // PICA_CMD_DATA_DRAW_MODE1(0x0, 0x0),
1416             // PICA_CMD_HEADER_SINGLE_BE(PICA_REG_DRAW_MODE1, 0x1),
1417 
1418             // 0x227 [27:0]
1419             // Vertex index address offset
1420             // Vertex index type is GL_UNSIGNED_SHORT, so [31:31] = 1
1421             PICA_CMD_DATA_INDEX_ARRAY_ADDR_OFFSET(s_VertexIndexAddressOffset,
1422                 PICA_DATA_INDEX_ARRAY_UNSIGNED_SHORT),
1423             PICA_CMD_HEADER_SINGLE(PICA_REG_INDEX_ARRAY_ADDR_OFFSET),
1424 
1425             // 0x228 [31:0]
1426             // Set the number of vertices to render: 6
1427             s_IndexNum, PICA_CMD_HEADER_SINGLE(PICA_REG_DRAW_VERTEX_NUM),
1428 
1429             // Render kick command macro
1430             // 1. Set to 0 immediately before Draw
1431             //    0x245 = 0x0
1432             // 2. Render kick command
1433             //    0x22f = Write 1 to any bit
1434             // 3. Set to 1 immediately after Draw
1435             //    0x245 = 0x1
1436             // 4. Immediately after the render kick command, clear the vertex cache.
1437             //    0x231 = 0x1
1438             PICA_CMD_SET_START_DRAW_ELEMENT(1),
1439 
1440             // Immediately after the render kick command, clear both color buffer and depth buffer caches.
1441             PICA_CMD_SET_COLOR_DEPTH_BUFFER_CLEAR(0x1, 0x1)
1442         };
1443 
1444         nngxAdd3DCommand(commandBuffer, sizeof(commandBuffer), GL_TRUE);
1445     }
1446 }
1447 
AddFrameBufferControlCommand(void)1448 void AddFrameBufferControlCommand(void)
1449 {
1450     {
1451         u32 cmdbuf[] =
1452         {
1453             // Clear the color buffer and depth buffer caches.
1454             PICA_CMD_SET_COLOR_DEPTH_BUFFER_CLEAR(0x1, 0x1),
1455 
1456             // To disable color buffer read, set to 0
1457             // 0x112 [3:0]
1458             PICA_CMD_DATA_FRAME_BUFFER_MODE(0x0),
1459             PICA_CMD_HEADER_SINGLE(PICA_REG_COLOR_BUFFER_READ),
1460 
1461             // To enable color buffer write, set to 0xF.
1462             // 0x113 [3:0]
1463             PICA_CMD_DATA_FRAME_BUFFER_MODE(0xF),
1464             PICA_CMD_HEADER_SINGLE(PICA_REG_COLOR_BUFFER_WRITE),
1465 
1466             // To enable depth buffer read, set [1:1] to 1.
1467             // To disable stencil buffer read, set to [0:0] to 0.
1468             // 0x114 [1:0]
1469             PICA_CMD_DATA_FRAME_BUFFER_MODE(0x2),
1470             PICA_CMD_HEADER_SINGLE(PICA_REG_DEPTH_STENCIL_BUFFER_READ),
1471 
1472             // To enable depth buffer write, set to [1:1] to 1.
1473             // To disable stencil buffer write, set to [0:0] to 0.
1474             // 0x115 [1:0]
1475             PICA_CMD_DATA_FRAME_BUFFER_MODE(0x2),
1476             PICA_CMD_HEADER_SINGLE(PICA_REG_DEPTH_STENCIL_BUFFER_WRITE),
1477 
1478             // Clear the color buffer and depth buffer caches.
1479             PICA_CMD_SET_COLOR_DEPTH_BUFFER_CLEAR(0x1, 0x1)
1480         };
1481 
1482         nngxAdd3DCommand(cmdbuf, sizeof(cmdbuf), GL_TRUE);
1483     }
1484 }
1485 
DrawDisplay1(void)1486 void DrawDisplay1(void)
1487 {
1488     AddViewportCommand(NN_GX_DISPLAY1);
1489     glBindFramebuffer(GL_FRAMEBUFFER, s_FramebufferID);
1490     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1491     nngxTransferRenderImage(s_Displaybuffer1ID[s_CurrentDisplaybuffer1], NN_GX_ANTIALIASE_NOT_USED, GL_FALSE, 0, 0);
1492 
1493     nngxRunCmdlist();
1494     nngxWaitCmdlistDone();
1495 }
1496 
nnMain(void)1497 void nnMain(void)
1498 {
1499     // Call only nn::applet::Enable to also allow execution from the HOME Menu
1500     // HOME Menu transitions, POWER Button presses, and sleep are all unsupported
1501     nn::applet::Enable();
1502 
1503     Initialize();
1504 
1505     bool flag = true;
1506     while ( flag )
1507     {
1508         flag = DrawFrame();
1509     }
1510 
1511     Finalize();
1512 }
1513