/*---------------------------------------------------------------------------* Project: Horizon File: main.cpp Copyright (C)2009-2011 Nintendo Co., Ltd./HAL Laboratory, Inc. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Revision: 47435 $ *---------------------------------------------------------------------------*/ //------------------------------------------------------------------ // Demo: ResFont // // Overview // This sample builds and destroys nn::font::ResFont. // // Controls // None. // //------------------------------------------------------------------ #include #include #include #include #include #include "demo.h" #include "applet.h" namespace { const char s_ShaderBinaryFilePath[] = "rom:/nnfont_RectDrawerShader.shbin"; const char s_FontFilePath[] = "rom:/tahoma.bcfnt"; nn::fnd::ExpHeap s_AppHeap; demo::RenderSystemDrawing s_RenderSystem; const s32 nDeviceMemorySizeVideo = 4 * 1024 * 1024; const s32 nDeviceMemorySizeOther = 4 * 1024 * 1024; const s32 nDeviceMemorySize = nDeviceMemorySizeVideo + nDeviceMemorySizeOther; bool s_InitAsciiString = false; u32 s_Counter = 0; u8 s_Color = 0; //--------------------------------------------------------------------------- // // // //--------------------------------------------------------------------------- void* InitShaders(nn::font::RectDrawer* pDrawer) { nn::fs::FileReader shaderReader(s_ShaderBinaryFilePath); const u32 fileSize = (u32)shaderReader.GetSize(); void* shaderBinary = s_AppHeap.Allocate(fileSize); NN_NULL_ASSERT(shaderBinary); #ifndef NN_BUILD_RELEASE s32 read = #endif // NN_BUILD_RELEASE shaderReader.Read(shaderBinary, fileSize); NN_ASSERT(read == fileSize); const u32 vtxBufCmdBufSize = nn::font::RectDrawer::GetVertexBufferCommandBufferSize(shaderBinary, fileSize); void *const vtxBufCmdBuf = s_AppHeap.Allocate(vtxBufCmdBufSize); NN_NULL_ASSERT(vtxBufCmdBuf); pDrawer->Initialize(vtxBufCmdBuf, shaderBinary, fileSize); s_AppHeap.Free(shaderBinary); return vtxBufCmdBuf; } /*---------------------------------------------------------------------------* *---------------------------------------------------------------------------*/ void InitGX() { glClearColor(0.3f, 0.3f, 0.3f, 1.0f); } //--------------------------------------------------------------------------- // // // // //--------------------------------------------------------------------------- void InitDraw( int width, int height ) { // Color buffer information // Switches the width and height to match the LCD direction. const nn::font::ColorBufferInfo colBufInfo = { width, height, PICA_DATA_DEPTH24_STENCIL8_EXT }; const u32 screenSettingCommands[] = { // Viewport settings NN_FONT_CMD_SET_VIEWPORT( 0, 0, colBufInfo.width, colBufInfo.height ), // Disable scissoring NN_FONT_CMD_SET_DISABLE_SCISSOR( colBufInfo ), // Disable W buffer // Set the depth range // Disable polygon offset NN_FONT_CMD_SET_WBUFFER_DEPTHRANGE_POLYGONOFFSET( 0.0f, // wScale : W buffer is disabled at 0.0 0.0f, // depth range near 1.0f, // depth range far 0, // polygon offset units : polygon offset is disabled with 0.0 colBufInfo), }; nngxAdd3DCommand(screenSettingCommands, sizeof(screenSettingCommands), true); static const u32 s_InitCommands[] = { // Disable culling NN_FONT_CMD_SET_CULL_FACE( NN_FONT_CMD_CULL_FACE_DISABLE ), // Disable stencil test NN_FONT_CMD_SET_DISABLE_STENCIL_TEST(), // Disable depth test // Make all elements of the color buffer writable NN_FONT_CMD_SET_DEPTH_FUNC_COLOR_MASK( false, // isDepthTestEnabled 0, // depthFunc true, // depthMask true, // red true, // Green true, // Blue true), // Alpha // Disable early depth test NN_FONT_CMD_SET_ENABLE_EARLY_DEPTH_TEST( false ), // Framebuffer access control NN_FONT_CMD_SET_FBACCESS( true, // colorRead true, // colorWrite false, // depthRead false, // depthWrite false, // stencilRead false), // stencilWrite }; nngxAdd3DCommand(s_InitCommands, sizeof(s_InitCommands), true); } //--------------------------------------------------------------------------- // // // // // // //--------------------------------------------------------------------------- bool InitFont( nn::font::ResFont* pFont, const char* filePath ) { // Loads font resources nn::fs::FileReader fontReader(filePath); s32 fileSize = (s32)fontReader.GetSize(); if ( fileSize <= 0 ) { return false; } void* buffer = s_AppHeap.Allocate(fileSize, nn::font::GlyphDataAlignment); if (buffer == NULL) { return false; } s32 readSize = fontReader.Read(buffer, fileSize); if (readSize != fileSize) { s_AppHeap.Free(buffer); return false; } // Sets the font resource. bool bSuccess = pFont->SetResource(buffer); NN_ASSERT(bSuccess); //--- Fails if the resource is already set, already loaded, or invalid. if (! bSuccess) { s_AppHeap.Free(buffer); } // Sets the render buffer. const u32 drawBufferSize = nn::font::ResFont::GetDrawBufferSize(buffer); void* drawBuffer = s_AppHeap.Allocate(drawBufferSize, 4); NN_NULL_ASSERT(drawBuffer); pFont->SetDrawBuffer(drawBuffer); return bSuccess; } //--------------------------------------------------------------------------- // // // //--------------------------------------------------------------------------- void CleanupFont(nn::font::ResFont* pFont) { // Disable render buffer // If the render buffer is set, returns the pointer to the buffer passed to SetDrawBuffer during creation. // void *const drawBuffer = pFont->SetDrawBuffer(NULL); if (drawBuffer != NULL) { s_AppHeap.Free(drawBuffer); } // If the font is set, returns the pointer to the resource passed during SetResource. // void *const resource = pFont->RemoveResource(); if (resource != NULL) { s_AppHeap.Free(resource); } // After RemoveResource is executed, data cannot be used as a font until SetResource is executed again. } //--------------------------------------------------------------------------- // // // // // //--------------------------------------------------------------------------- nn::font::DispStringBuffer* AllocDispStringBuffer(int charMax) { const u32 DrawBufferSize = nn::font::CharWriter::GetDispStringBufferSize(charMax); void *const bufMem = s_AppHeap.Allocate(DrawBufferSize); NN_NULL_ASSERT(bufMem); return nn::font::CharWriter::InitDispStringBuffer(bufMem, charMax); } //--------------------------------------------------------------------------- // // // // // //--------------------------------------------------------------------------- void SetupTextCamera( nn::font::RectDrawer* pDrawer, int width, int height ) { // Set the projection matrix for an orthogonal projection { // Sets the origin at the upper left, and the Y and Z axes in opposite directions. nn::math::MTX44 proj; f32 znear = 0.0f; f32 zfar = -1.0f; f32 t = 0; f32 b = static_cast(width); f32 l = 0; f32 r = static_cast(height); nn::math::MTX44OrthoPivot(&proj, l, r, b, t, znear, zfar, nn::math::PIVOT_UPSIDE_TO_TOP); pDrawer->SetProjectionMtx(proj); } // Set the model view matrix as an identity matrix { nn::math::MTX34 mv; nn::math::MTX34Identity(&mv); pDrawer->SetViewMtxForText(mv); } } //--------------------------------------------------------------------------- // // // // // // // //--------------------------------------------------------------------------- void DrawAscii( nn::font::RectDrawer* pDrawer, nn::font::DispStringBuffer* pDrawStringBuf, nn::font::ResFont* pFont, int width, int height ) { nn::font::TextWriter writer; writer.SetDispStringBuffer(pDrawStringBuf); writer.SetFont(pFont); writer.SetCursor(0, 0); // Create the string render command once because the string does not change. if (! s_InitAsciiString) { writer.StartPrint(); (void)writer.Print("DEMO: ResFont\n"); (void)writer.Print("\n"); // Display a sample of ASCII characters (void)writer.Print("All ASCII Character listing:\n"); (void)writer.Print("\n"); (void)writer.Print(" !\"#$%&'()*+,-./\n"); (void)writer.Print("0123456789:;<=>?\n"); (void)writer.Print("@ABCDEFGHIJKLMNO\n"); (void)writer.Print("PQRSTUVWXYZ[\\]^_\n"); (void)writer.Print("`abcdefghijklmno\n"); (void)writer.Print("pqrstuvwxyz{|}~\n"); writer.EndPrint(); pDrawer->BuildTextCommand(&writer); s_InitAsciiString = true; } // The character's color can be changed without regenerating the string render command. writer.SetTextColor(nn::util::Color8(s_Color, 255, s_Color, 255)); s_Color++; pDrawer->DrawBegin(); SetupTextCamera(pDrawer, width, height); writer.UseCommandBuffer(); pDrawer->DrawEnd(); } //--------------------------------------------------------------------------- // // // // // // // //--------------------------------------------------------------------------- void DrawCounter( nn::font::RectDrawer* pDrawer, nn::font::DispStringBuffer* pDrawStringBuf, nn::font::ResFont* pFont, int width, int height ) { nn::font::TextWriter writer; writer.SetDispStringBuffer(pDrawStringBuf); writer.SetFont(pFont); writer.SetCursor(0, 0); writer.SetFixedWidth(10.5f); writer.EnableFixedWidth(true); pDrawer->DrawBegin(); SetupTextCamera(pDrawer, width, height); // Generates the counter render command each time to use it. writer.StartPrint(); (void)writer.Printf("Counter : %d\n", s_Counter); writer.EndPrint(); pDrawer->BuildTextCommand(&writer); writer.UseCommandBuffer(); // Generates a counter 1/60 render command each time to use it. writer.StartPrint(); (void)writer.Printf("Counter 1/60 : %d\n", s_Counter / 60); writer.EndPrint(); pDrawer->BuildTextCommand(&writer); writer.UseCommandBuffer(); pDrawer->DrawEnd(); s_Counter++; } } // Namespace //--------------------------------------------------------------------------- // //--------------------------------------------------------------------------- void StartDemo() { nn::fs::Initialize(); const size_t ROMFS_BUFFER_SIZE = 1024 * 64; static char buffer[ROMFS_BUFFER_SIZE]; NN_UTIL_PANIC_IF_FAILED( nn::fs::MountRom(16, 16, buffer, ROMFS_BUFFER_SIZE)); // Prepare device memory uptr addrDeviceMemory = nn::os::GetDeviceMemoryAddress(); s_AppHeap.Initialize(addrDeviceMemory, nDeviceMemorySize ); uptr addrDeviceMemoryVideo = reinterpret_cast(s_AppHeap.Allocate(nDeviceMemorySizeVideo)); s_RenderSystem.Initialize(addrDeviceMemoryVideo, nDeviceMemorySizeVideo); InitGX(); nn::font::ResFont font; // Build font { #ifndef NN_BUILD_RELEASE bool bSuccess = #endif // NN_BUILD_RELEASE InitFont(&font, s_FontFilePath); NN_ASSERTMSG(bSuccess, "Failed to load ResFont."); } // Build the render resource nn::font::RectDrawer drawer; void *const drawerBuf = InitShaders(&drawer); // Allocate buffer for render string nn::font::DispStringBuffer *const pDrawStringBuf0 = AllocDispStringBuffer(512); nn::font::DispStringBuffer *const pDrawStringBuf1 = AllocDispStringBuffer(128); // After this, the application itself handles sleep TransitionHandler::EnableSleep(); // Display font data volatile bool loop = true; while (loop) { s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY0); { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); InitDraw(NN_GX_DISPLAY0_WIDTH, NN_GX_DISPLAY0_HEIGHT); DrawAscii(&drawer, pDrawStringBuf0, &font, NN_GX_DISPLAY0_WIDTH, NN_GX_DISPLAY0_HEIGHT); } s_RenderSystem.SwapBuffers(); s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY1); { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); InitDraw(NN_GX_DISPLAY1_WIDTH, NN_GX_DISPLAY1_HEIGHT); DrawCounter(&drawer, pDrawStringBuf1, &font, NN_GX_DISPLAY1_WIDTH, NN_GX_DISPLAY1_HEIGHT); } s_RenderSystem.SwapBuffers(); s_RenderSystem.WaitVsync(NN_GX_DISPLAY_BOTH); // Run sleep, HOME Menu, and POWER Menu transitions. TransitionHandler::Process(); // Determine whether there has been an exit notification. if (TransitionHandler::IsExitRequired()) { break; } } drawer.Finalize(); // Destroy render resource s_AppHeap.Free(drawerBuf); // Destroy font CleanupFont(&font); // Free the render string buffer s_AppHeap.Free(pDrawStringBuf1); s_AppHeap.Free(pDrawStringBuf0); s_AppHeap.Free(reinterpret_cast(addrDeviceMemoryVideo)); s_AppHeap.Finalize(); } void nnMain() { NN_LOG("Demo Start\n"); // Initialize via the applet. // Sleep Mode is rejected automatically until TransitionHandler::EnableSleep is called. TransitionHandler::Initialize(); // Here we need to check for exit notifications. if (!TransitionHandler::IsExitRequired()) { StartDemo(); } // Finalize via the applet. TransitionHandler::Finalize(); NN_LOG("Demo End\n"); // Finalize the application. The call to nn::applet::CloseApplication does not return. nn::applet::CloseApplication(); }