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