1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     main.cpp
4 
5   Copyright (C)2009-2011 Nintendo Co., Ltd./HAL Laboratory, Inc.  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   $Revision: 47435 $
14  *---------------------------------------------------------------------------*/
15 
16 
17 //------------------------------------------------------------------
18 // Demo: ResFont
19 //
20 // Overview
21 //   This sample builds and destroys nn::font::ResFont.
22 //
23 // Controls
24 //   None.
25 //
26 //------------------------------------------------------------------
27 
28 #include <nn.h>
29 #include <nn/fs.h>
30 #include <nn/font.h>
31 #include <nn/math.h>
32 #include <nn/util.h>
33 
34 #include "demo.h"
35 #include "applet.h"
36 
37 namespace
38 {
39 const char s_ShaderBinaryFilePath[] = "rom:/nnfont_RectDrawerShader.shbin";
40 const char s_FontFilePath[] = "rom:/tahoma.bcfnt";
41 
42 nn::fnd::ExpHeap          s_AppHeap;
43 demo::RenderSystemDrawing s_RenderSystem;
44 
45 const s32 nDeviceMemorySizeVideo = 4 * 1024 * 1024;
46 const s32 nDeviceMemorySizeOther = 4 * 1024 * 1024;
47 const s32 nDeviceMemorySize = nDeviceMemorySizeVideo + nDeviceMemorySizeOther;
48 
49 bool    s_InitAsciiString   = false;
50 u32     s_Counter           = 0;
51 u8      s_Color             = 0;
52 
53 //---------------------------------------------------------------------------
54 //
55 //
56 //
57 //---------------------------------------------------------------------------
58 void*
InitShaders(nn::font::RectDrawer * pDrawer)59 InitShaders(nn::font::RectDrawer* pDrawer)
60 {
61     nn::fs::FileReader shaderReader(s_ShaderBinaryFilePath);
62 
63     const u32 fileSize = (u32)shaderReader.GetSize();
64 
65     void* shaderBinary = s_AppHeap.Allocate(fileSize);
66     NN_NULL_ASSERT(shaderBinary);
67 
68 #ifndef NN_BUILD_RELEASE
69     s32 read =
70 #endif // NN_BUILD_RELEASE
71     shaderReader.Read(shaderBinary, fileSize);
72     NN_ASSERT(read == fileSize);
73 
74     const u32 vtxBufCmdBufSize =
75         nn::font::RectDrawer::GetVertexBufferCommandBufferSize(shaderBinary, fileSize);
76     void *const vtxBufCmdBuf = s_AppHeap.Allocate(vtxBufCmdBufSize);
77     NN_NULL_ASSERT(vtxBufCmdBuf);
78     pDrawer->Initialize(vtxBufCmdBuf, shaderBinary, fileSize);
79 
80     s_AppHeap.Free(shaderBinary);
81 
82     return vtxBufCmdBuf;
83 
84 }
85 
86 /*---------------------------------------------------------------------------*
87 
88  *---------------------------------------------------------------------------*/
89 void
InitGX()90 InitGX()
91 {
92     glClearColor(0.3f, 0.3f, 0.3f, 1.0f);
93 }
94 
95 //---------------------------------------------------------------------------
96 //
97 //
98 //
99 //
100 //---------------------------------------------------------------------------
101 void
InitDraw(int width,int height)102 InitDraw(
103     int     width,
104     int     height
105 )
106 {
107     // Color buffer information
108     // Switches the width and height to match the LCD direction.
109     const nn::font::ColorBufferInfo colBufInfo = { width, height, PICA_DATA_DEPTH24_STENCIL8_EXT };
110 
111     const u32 screenSettingCommands[] =
112     {
113 
114         // Viewport settings
115         NN_FONT_CMD_SET_VIEWPORT( 0, 0, colBufInfo.width, colBufInfo.height ),
116 
117         // Disable scissoring
118         NN_FONT_CMD_SET_DISABLE_SCISSOR( colBufInfo ),
119 
120         // Disable W buffer
121         // Set the depth range
122         // Disable polygon offset
123         NN_FONT_CMD_SET_WBUFFER_DEPTHRANGE_POLYGONOFFSET(
124             0.0f,           // wScale : W buffer is disabled at 0.0
125             0.0f,           // depth range near
126             1.0f,           // depth range far
127             0,              // polygon offset units : polygon offset is disabled with 0.0
128             colBufInfo),
129     };
130 
131     nngxAdd3DCommand(screenSettingCommands, sizeof(screenSettingCommands), true);
132 
133     static const u32 s_InitCommands[] =
134     {
135         // Disable culling
136         NN_FONT_CMD_SET_CULL_FACE( NN_FONT_CMD_CULL_FACE_DISABLE ),
137 
138         // Disable stencil test
139         NN_FONT_CMD_SET_DISABLE_STENCIL_TEST(),
140 
141         // Disable depth test
142         // Make all elements of the color buffer writable
143         NN_FONT_CMD_SET_DEPTH_FUNC_COLOR_MASK(
144             false,  // isDepthTestEnabled
145             0,      // depthFunc
146             true,   // depthMask
147             true,   // red
148             true,   // Green
149             true,   // Blue
150             true),  // Alpha
151 
152         // Disable early depth test
153         NN_FONT_CMD_SET_ENABLE_EARLY_DEPTH_TEST( false ),
154 
155         // Framebuffer access control
156         NN_FONT_CMD_SET_FBACCESS(
157             true,   // colorRead
158             true,   // colorWrite
159             false,  // depthRead
160             false,  // depthWrite
161             false,  // stencilRead
162             false), // stencilWrite
163     };
164 
165     nngxAdd3DCommand(s_InitCommands, sizeof(s_InitCommands), true);
166 }
167 
168 //---------------------------------------------------------------------------
169 //
170 //
171 //
172 //
173 //
174 //
175 //---------------------------------------------------------------------------
176 bool
InitFont(nn::font::ResFont * pFont,const char * filePath)177 InitFont(
178     nn::font::ResFont*  pFont,
179     const char*         filePath
180 )
181 {
182     // Loads font resources
183     nn::fs::FileReader fontReader(filePath);
184 
185     s32 fileSize = (s32)fontReader.GetSize();
186     if ( fileSize <= 0 )
187     {
188         return false;
189     }
190 
191     void* buffer = s_AppHeap.Allocate(fileSize, nn::font::GlyphDataAlignment);
192     if (buffer == NULL)
193     {
194         return false;
195     }
196 
197     s32 readSize = fontReader.Read(buffer, fileSize);
198     if (readSize != fileSize)
199     {
200         s_AppHeap.Free(buffer);
201         return false;
202     }
203 
204     // Sets the font resource.
205     bool bSuccess = pFont->SetResource(buffer);
206     NN_ASSERT(bSuccess);
207 
208     //--- Fails if the resource is already set, already loaded, or invalid.
209     if (! bSuccess)
210     {
211         s_AppHeap.Free(buffer);
212     }
213 
214     // Sets the render buffer.
215     const u32 drawBufferSize = nn::font::ResFont::GetDrawBufferSize(buffer);
216     void* drawBuffer = s_AppHeap.Allocate(drawBufferSize, 4);
217     NN_NULL_ASSERT(drawBuffer);
218     pFont->SetDrawBuffer(drawBuffer);
219 
220     return bSuccess;
221 }
222 
223 //---------------------------------------------------------------------------
224 //
225 //
226 //
227 //---------------------------------------------------------------------------
228 void
CleanupFont(nn::font::ResFont * pFont)229 CleanupFont(nn::font::ResFont* pFont)
230 {
231     // Disable render buffer
232     // If the render buffer is set, returns the pointer to the buffer passed to SetDrawBuffer during creation.
233     //
234     void *const drawBuffer = pFont->SetDrawBuffer(NULL);
235     if (drawBuffer != NULL)
236     {
237         s_AppHeap.Free(drawBuffer);
238     }
239 
240     // If the font is set, returns the pointer to the resource passed during SetResource.
241     //
242     void *const resource = pFont->RemoveResource();
243     if (resource != NULL)
244     {
245         s_AppHeap.Free(resource);
246     }
247 
248     // After RemoveResource is executed, data cannot be used as a font until SetResource is executed again.
249 }
250 
251 //---------------------------------------------------------------------------
252 //
253 //
254 //
255 //
256 //
257 //---------------------------------------------------------------------------
258 nn::font::DispStringBuffer*
AllocDispStringBuffer(int charMax)259 AllocDispStringBuffer(int charMax)
260 {
261     const u32 DrawBufferSize = nn::font::CharWriter::GetDispStringBufferSize(charMax);
262     void *const bufMem = s_AppHeap.Allocate(DrawBufferSize);
263     NN_NULL_ASSERT(bufMem);
264 
265     return nn::font::CharWriter::InitDispStringBuffer(bufMem, charMax);
266 }
267 
268 //---------------------------------------------------------------------------
269 //
270 //
271 //
272 //
273 //
274 //---------------------------------------------------------------------------
275 void
SetupTextCamera(nn::font::RectDrawer * pDrawer,int width,int height)276 SetupTextCamera(
277     nn::font::RectDrawer*   pDrawer,
278     int                     width,
279     int                     height
280 )
281 {
282     // Set the projection matrix for an orthogonal projection
283     {
284         // Sets the origin at the upper left, and the Y and Z axes in opposite directions.
285         nn::math::MTX44 proj;
286         f32 znear   =  0.0f;
287         f32 zfar    = -1.0f;
288         f32 t       =  0;
289         f32 b       =  static_cast<f32>(width);
290         f32 l       =  0;
291         f32 r       =  static_cast<f32>(height);
292         nn::math::MTX44OrthoPivot(&proj, l, r, b, t, znear, zfar, nn::math::PIVOT_UPSIDE_TO_TOP);
293         pDrawer->SetProjectionMtx(proj);
294     }
295 
296     // Set the model view matrix as an identity matrix
297     {
298         nn::math::MTX34 mv;
299         nn::math::MTX34Identity(&mv);
300         pDrawer->SetViewMtxForText(mv);
301     }
302 }
303 
304 //---------------------------------------------------------------------------
305 //
306 //
307 //
308 //
309 //
310 //
311 //
312 //---------------------------------------------------------------------------
313 void
DrawAscii(nn::font::RectDrawer * pDrawer,nn::font::DispStringBuffer * pDrawStringBuf,nn::font::ResFont * pFont,int width,int height)314 DrawAscii(
315     nn::font::RectDrawer*           pDrawer,
316     nn::font::DispStringBuffer*     pDrawStringBuf,
317     nn::font::ResFont*              pFont,
318     int                             width,
319     int                             height
320 )
321 {
322     nn::font::TextWriter writer;
323     writer.SetDispStringBuffer(pDrawStringBuf);
324     writer.SetFont(pFont);
325 
326     writer.SetCursor(0, 0);
327 
328     // Create the string render command once because the string does not change.
329     if (! s_InitAsciiString)
330     {
331         writer.StartPrint();
332             (void)writer.Print("DEMO: ResFont\n");
333             (void)writer.Print("\n");
334 
335             // Display a sample of ASCII characters
336             (void)writer.Print("All ASCII Character listing:\n");
337             (void)writer.Print("\n");
338             (void)writer.Print(" !\"#$%&'()*+,-./\n");
339             (void)writer.Print("0123456789:;<=>?\n");
340             (void)writer.Print("@ABCDEFGHIJKLMNO\n");
341             (void)writer.Print("PQRSTUVWXYZ[\\]^_\n");
342             (void)writer.Print("`abcdefghijklmno\n");
343             (void)writer.Print("pqrstuvwxyz{|}~\n");
344         writer.EndPrint();
345         pDrawer->BuildTextCommand(&writer);
346 
347         s_InitAsciiString = true;
348     }
349 
350     // The character's color can be changed without regenerating the string render command.
351     writer.SetTextColor(nn::util::Color8(s_Color, 255, s_Color, 255));
352     s_Color++;
353 
354     pDrawer->DrawBegin();
355 
356         SetupTextCamera(pDrawer, width, height);
357         writer.UseCommandBuffer();
358 
359     pDrawer->DrawEnd();
360 }
361 
362 //---------------------------------------------------------------------------
363 //
364 //
365 //
366 //
367 //
368 //
369 //
370 //---------------------------------------------------------------------------
371 void
DrawCounter(nn::font::RectDrawer * pDrawer,nn::font::DispStringBuffer * pDrawStringBuf,nn::font::ResFont * pFont,int width,int height)372 DrawCounter(
373     nn::font::RectDrawer*           pDrawer,
374     nn::font::DispStringBuffer*     pDrawStringBuf,
375     nn::font::ResFont*              pFont,
376     int                             width,
377     int                             height
378 )
379 {
380     nn::font::TextWriter writer;
381     writer.SetDispStringBuffer(pDrawStringBuf);
382     writer.SetFont(pFont);
383 
384     writer.SetCursor(0, 0);
385     writer.SetFixedWidth(10.5f);
386     writer.EnableFixedWidth(true);
387 
388     pDrawer->DrawBegin();
389 
390         SetupTextCamera(pDrawer, width, height);
391 
392         // Generates the counter render command each time to use it.
393         writer.StartPrint();
394             (void)writer.Printf("Counter      : %d\n", s_Counter);
395         writer.EndPrint();
396         pDrawer->BuildTextCommand(&writer);
397         writer.UseCommandBuffer();
398 
399         // Generates a counter 1/60 render command each time to use it.
400         writer.StartPrint();
401             (void)writer.Printf("Counter 1/60 : %d\n", s_Counter / 60);
402         writer.EndPrint();
403         pDrawer->BuildTextCommand(&writer);
404         writer.UseCommandBuffer();
405 
406     pDrawer->DrawEnd();
407 
408     s_Counter++;
409 }
410 
411 }   // Namespace
412 
413 
414 //---------------------------------------------------------------------------
415 //
416 //---------------------------------------------------------------------------
StartDemo()417 void StartDemo()
418 {
419     nn::fs::Initialize();
420 
421     const size_t ROMFS_BUFFER_SIZE = 1024 * 64;
422     static char buffer[ROMFS_BUFFER_SIZE];
423     NN_UTIL_PANIC_IF_FAILED(
424         nn::fs::MountRom(16, 16, buffer, ROMFS_BUFFER_SIZE));
425 
426     // Prepare device memory
427     uptr addrDeviceMemory = nn::os::GetDeviceMemoryAddress();
428     s_AppHeap.Initialize(addrDeviceMemory, nDeviceMemorySize );
429     uptr addrDeviceMemoryVideo = reinterpret_cast<uptr>(s_AppHeap.Allocate(nDeviceMemorySizeVideo));
430     s_RenderSystem.Initialize(addrDeviceMemoryVideo, nDeviceMemorySizeVideo);
431 
432     InitGX();
433 
434     nn::font::ResFont font;
435 
436     // Build font
437     {
438 #ifndef NN_BUILD_RELEASE
439         bool bSuccess =
440 #endif // NN_BUILD_RELEASE
441         InitFont(&font, s_FontFilePath);
442         NN_ASSERTMSG(bSuccess, "Failed to load ResFont.");
443     }
444 
445     // Build the render resource
446     nn::font::RectDrawer drawer;
447     void *const drawerBuf = InitShaders(&drawer);
448 
449     // Allocate buffer for render string
450     nn::font::DispStringBuffer *const pDrawStringBuf0 = AllocDispStringBuffer(512);
451     nn::font::DispStringBuffer *const pDrawStringBuf1 = AllocDispStringBuffer(128);
452 
453     // After this, the application itself handles sleep
454     TransitionHandler::EnableSleep();
455 
456     // Display font data
457     volatile bool loop = true;
458     while (loop)
459     {
460         s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY0);
461         {
462             glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
463 
464             InitDraw(NN_GX_DISPLAY0_WIDTH, NN_GX_DISPLAY0_HEIGHT);
465 
466             DrawAscii(&drawer, pDrawStringBuf0, &font, NN_GX_DISPLAY0_WIDTH, NN_GX_DISPLAY0_HEIGHT);
467         }
468         s_RenderSystem.SwapBuffers();
469 
470         s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY1);
471         {
472             glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
473 
474             InitDraw(NN_GX_DISPLAY1_WIDTH, NN_GX_DISPLAY1_HEIGHT);
475 
476             DrawCounter(&drawer, pDrawStringBuf1, &font, NN_GX_DISPLAY1_WIDTH, NN_GX_DISPLAY1_HEIGHT);
477         }
478         s_RenderSystem.SwapBuffers();
479 
480         s_RenderSystem.WaitVsync(NN_GX_DISPLAY_BOTH);
481 
482         // Run sleep, HOME Menu, and POWER Menu transitions.
483         TransitionHandler::Process();
484         // Determine whether there has been an exit notification.
485         if (TransitionHandler::IsExitRequired())
486         {
487             break;
488         }
489     }
490 
491     drawer.Finalize();
492 
493     // Destroy render resource
494     s_AppHeap.Free(drawerBuf);
495 
496     // Destroy font
497     CleanupFont(&font);
498 
499     // Free the render string buffer
500     s_AppHeap.Free(pDrawStringBuf1);
501     s_AppHeap.Free(pDrawStringBuf0);
502     s_AppHeap.Free(reinterpret_cast<void*>(addrDeviceMemoryVideo));
503 
504     s_AppHeap.Finalize();
505 }
506 
nnMain()507 void nnMain()
508 {
509     NN_LOG("Demo Start\n");
510 
511     // Initialize via the applet.
512     // Sleep Mode is rejected automatically until TransitionHandler::EnableSleep is called.
513     TransitionHandler::Initialize();
514     // Here we need to check for exit notifications.
515     if (!TransitionHandler::IsExitRequired())
516     {
517         StartDemo();
518     }
519     // Finalize via the applet.
520     TransitionHandler::Finalize();
521 
522     NN_LOG("Demo End\n");
523 
524     // Finalize the application. The call to nn::applet::CloseApplication does not return.
525     nn::applet::CloseApplication();
526 }
527