/*---------------------------------------------------------------------------* Project: NintendoWare File: demolib.cpp Copyright (C)2009-2010 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:$ *---------------------------------------------------------------------------*/ #include "precompiled.h" #include "demolib.h" #include #ifdef NW_PLATFORM_CTRWIN #include // WAVE_MAPPER #endif namespace nw { namespace snd { namespace demolib { namespace { #ifdef NW_PLATFORM_CTRWIN const char FONT_PATH[] = NW_SND_DEMO_PATH_PREFIX "sampleFont.bcfnt"; #endif const size_t ROMFS_MAX_FILE = 128; const size_t ROMFS_MAX_DIRECTORY = 128; const s32 DRAW_STRING_BUFFER_UPPER_LCD = 512; const s32 DRAW_STRING_BUFFER_LOWER_LCD = 512; const f32 FONT_SIZE_HIGHT = 14.0f; const nw::ut::FloatColor CLEAR_BUFFER_COLOR( 0.3f, 0.3f, 0.3f, 1.0f ); const f32 CLEAR_BUFFER_DEPTH = 0.0f; } // anonymous namespace AppBase::AppBase() : m_pMemoryForRomFileSystem( NULL ), m_IsDraw( true ) { } void AppBase::LoadDspComponent() { #ifdef NW_PLATFORM_CTR nn::Result result; result = nn::dsp::LoadDefaultComponent(); NN_UTIL_PANIC_IF_FAILED(result); #endif } void AppBase::InitializeSDK() { // サウンド SDK の初期化 // (サウンド以外に初期化は demo_GraphicsSysteCTR.cppi の InitializeGraphicsSystem() で行われます。) #ifdef NW_PLATFORM_CTRWIN { AI_Init( WAVE_MAPPER ); AX_Init(); } #else { nn::Result result; result = nn::dsp::Initialize(); NN_UTIL_PANIC_IF_FAILED(result); LoadDspComponent(); result = nn::snd::Initialize(); NN_UTIL_PANIC_IF_FAILED(result); } #endif } void AppBase::InitializeDraw( int width, int height ) { // カラーバッファ情報 // LCDの向きに合わせて、幅と高さを入れ替えています。 const nw::font::ColorBufferInfo colBufInfo = { height, width, PICA_DATA_DEPTH24_STENCIL8_EXT }; const u32 screenSettingCommands[] = { // ビューポートの設定 NW_FONT_CMD_SET_VIEWPORT( 0, 0, colBufInfo.width, colBufInfo.height ), // シザー処理を無効 NW_FONT_CMD_SET_DISABLE_SCISSOR( colBufInfo ), // wバッファの無効化 // デプスレンジの設定 // ポリゴンオフセットの無効化 NW_FONT_CMD_SET_WBUFFER_DEPTHRANGE_POLYGONOFFSET( 0.0f, // wScale : 0.0 でWバッファが無効 0.0f, // depth range near 1.0f, // depth range far 0, // polygon offset units : 0.0 で ポリゴンオフセットが無効 colBufInfo), }; nngxAdd3DCommand(screenSettingCommands, sizeof(screenSettingCommands), true); static const u32 s_InitCommands[] = { // カリングを無効 NW_FONT_CMD_SET_CULL_FACE( NW_FONT_CMD_CULL_FACE_DISABLE ), // ステンシルテストを無効 NW_FONT_CMD_SET_DISABLE_STENCIL_TEST(), // デプステストを無効 // カラーバッファの全ての成分を書き込み可 NW_FONT_CMD_SET_DEPTH_FUNC_COLOR_MASK( false, // isDepthTestEnabled 0, // depthFunc true, // depthMask true, // red true, // green true, // blue true), // alpha // アーリーデプステストを無効 NW_FONT_CMD_SET_ENABLE_EARLY_DEPTH_TEST( false ), // フレームバッファアクセス制御 NW_FONT_CMD_SET_FBACCESS( true, // colorRead true, // colorWrite false, // depthRead false, // depthWrite false, // stencilRead false), // stencilWrite }; nngxAdd3DCommand(s_InitCommands, sizeof(s_InitCommands), true); } bool AppBase::InitializeFont() { void* buffer = NULL; #ifdef NW_PLATFORM_CTRWIN { nn::fs::FileReader fontReader( FONT_PATH ); s32 fileSize = (s32)fontReader.GetSize(); if ( fileSize <= 0 ) { return false; } buffer = MemAlloc( fileSize, nw::font::GlyphDataAlignment ); if ( buffer == NULL ) { return false; } s32 readSize = fontReader.Read( buffer, fileSize ); if ( readSize != fileSize ) { MemFree( buffer ); return false; } } #else { NN_UTIL_PANIC_IF_FAILED(nn::pl::InitializeSharedFont()); // 共有フォントのロードが完了するまで待機 while (nn::pl::GetSharedFontLoadState() != nn::pl::SHARED_FONT_LOAD_STATE_LOADED) { // 共有フォントのロードに失敗していないか確認 if (nn::pl::GetSharedFontLoadState() == nn::pl::SHARED_FONT_LOAD_STATE_FAILED) { NN_TPANIC_("failed to load shared font!\n"); } nn::os::Thread::Sleep(nn::fnd::TimeSpan::FromMilliSeconds(10)); NN_LOG("loading SharedFont ...\n"); } buffer = nn::pl::GetSharedFontAddress(); } #endif // フォントリソースをセットします bool bSuccess = m_Font.SetResource( buffer ); NW_ASSERT( bSuccess ); if ( !bSuccess ) { MemFree( buffer ); } // 描画用バッファの設定。 (処理速度高速化のため。) const size_t drawBufferSize = nw::font::ResFont::GetDrawBufferSize( buffer ); void* drawBuffer = MemAlloc( drawBufferSize, 4 ); NW_NULL_ASSERT(drawBuffer); m_Font.SetDrawBuffer( drawBuffer ); return bSuccess; } void AppBase::FinalizeFont() { void *const drawBuffer = m_Font.SetDrawBuffer( NULL ); if ( drawBuffer != NULL ) { MemFree( drawBuffer ); } void *const resource = m_Font.RemoveResource(); if ( resource != NULL ) { MemFree( resource ); } } void AppBase::InitializeShaders() { // NOTE: demo/font/ResFont の InitShaders を参考にした。 const wchar_t* shaders = NW_DEMO_FILE_PATH( NW_FONT_RECTDRAWER_SHADERBINARY ); nn::fs::FileReader shaderReader( shaders ); const u32 fileSize = (u32)shaderReader.GetSize(); void* shaderBinary = MemAlloc( fileSize ); NW_NULL_ASSERT( shaderBinary ); s32 read = shaderReader.Read( shaderBinary, fileSize ); NW_ASSERT( read == fileSize ); const u32 vtxBufCmdBufSize = nw::font::RectDrawer::GetVertexBufferCommandBufferSize( shaderBinary, fileSize ); void *const vtxBufCmdBuf = MemAlloc( vtxBufCmdBufSize ); NW_NULL_ASSERT( vtxBufCmdBuf ); m_Drawer.Initialize( vtxBufCmdBuf, shaderBinary, fileSize ); MemFree( shaderBinary ); m_pMemoryForDrawBuffer = vtxBufCmdBuf; } void AppBase::FinalizeShaders() { m_Drawer.Finalize(); MemFree( m_pMemoryForDrawBuffer ); } void AppBase::InitializeDrawStringBuffer() { m_pDrawStringBufferUpperLcd = AllocDispStringBuffer( DRAW_STRING_BUFFER_UPPER_LCD ); m_pDrawStringBufferLowerLcd = AllocDispStringBuffer( DRAW_STRING_BUFFER_LOWER_LCD ); } void AppBase::FinalizeDrawStringBuffer() { MemFree( m_pDrawStringBufferUpperLcd ); MemFree( m_pDrawStringBufferLowerLcd ); } nw::font::DispStringBuffer* AppBase::AllocDispStringBuffer(int charMax) { const u32 DrawBufferSize = nw::font::CharWriter::GetDispStringBufferSize(charMax); void *const bufMem = MemAlloc(DrawBufferSize); NN_NULL_ASSERT(bufMem); return nw::font::CharWriter::InitDispStringBuffer(bufMem, charMax); } void AppBase::FinalizeSDK() { #ifdef NW_PLATFORM_CTRWIN #else { nn::Result result; result = nn::snd::Finalize(); NN_UTIL_PANIC_IF_FAILED( result ); result = nn::dsp::UnloadComponent(); NN_UTIL_PANIC_IF_FAILED( result ); nn::dsp::Finalize(); MemFree( m_pMemoryForRomFileSystem ); // fs::Finalize が無いので、解放するとまずい? } // nn::fs::Finalize は無い // nn::os::Finalize は無い #endif } void AppBase::SetupTextCamera( nw::font::RectDrawer* pDrawer, int width, int height ) { // 射影行列を正射影に設定 { // 左上原点とし、Y軸とZ軸の向きが逆になるように設定します。 nn::math::MTX44 proj; f32 znear = 0.0f; f32 zfar = -1.0f; f32 t = 0; f32 b = static_cast(height); f32 l = 0; f32 r = static_cast(width); nn::math::MTX44OrthoPivot(&proj, l, r, b, t, znear, zfar, nn::math::PIVOT_UPSIDE_TO_TOP); pDrawer->SetProjectionMtx(proj); } // モデルビュー行列を単位行列に設定 { nn::math::MTX34 mv; nn::math::MTX34Identity(&mv); pDrawer->SetViewMtxForText(mv); } } void AppBase::Initialize() { // 規定の初期化 nw::demo::SimpleApp::GetInstance().Initialize(); InitializeSDK(); // フォントの構築 InitializeFont(); // 描画リソースの構築 InitializeShaders(); InitializeDrawStringBuffer(); // ユーザーの初期化処理 OnInitialize(); } void AppBase::Finalize() { // ユーザーの終了処理 OnFinalize(); // 規定の終了処理 FinalizeDrawStringBuffer(); FinalizeShaders(); FinalizeFont(); FinalizeSDK(); // demoPadの終了処理 nw::demo::PadFactory::Finalize(); } void AppBase::Run() { while ( true ) { // パッドなどの更新処理 Update(); // 描画 (Vブランク待ちを含む) Draw(); } } void AppBase::DrawStringPreProcess( nw::font::TextWriter& writer, const nw::gfx::FrameBufferObject& frameBufferObject, int width, int height ) { frameBufferObject.ClearBuffer( CLEAR_BUFFER_COLOR, CLEAR_BUFFER_DEPTH ); InitializeDraw( width, height ); writer.SetDispStringBuffer( m_pDrawStringBufferUpperLcd ); writer.SetCursor( 0, 0 ); writer.StartPrint(); } void AppBase::DrawStringPostProcess( nw::font::TextWriter& writer, int width, int height ) { writer.EndPrint(); m_Drawer.BuildTextCommand( &writer ); m_Drawer.DrawBegin(); { SetupTextCamera( &m_Drawer, width, height ); writer.UseCommandBuffer(); } m_Drawer.DrawEnd(); } void AppBase::Draw() { nw::demo::SimpleApp& app = nw::demo::SimpleApp::GetInstance(); if ( m_IsDraw == true ) { nw::font::TextWriter writer; writer.SetFont( &m_Font ); writer.SetCharSpace( 1.0f ); writer.EnableFixedWidth( true ); writer.SetFontSize( FONT_SIZE_HIGHT ); writer.SetFixedWidth( writer.GetLineHeight() / 2.f ); app.SetRenderingTarget( app.DISPLAY0 ); { DrawStringPreProcess( writer, app.GetFrameBufferObject(), app.DISPLAY0_WIDTH, app.DISPLAY0_HEIGHT ); OnDrawUpLCD( writer ); DrawStringPostProcess( writer, app.DISPLAY0_WIDTH, app.DISPLAY0_HEIGHT ); } app.SetRenderingTarget( app.DISPLAY1 ); { DrawStringPreProcess( writer, app.GetFrameBufferObject(), app.DISPLAY1_WIDTH, app.DISPLAY1_HEIGHT ); OnDrawDownLCD( writer ); DrawStringPostProcess( writer, app.DISPLAY1_WIDTH, app.DISPLAY1_HEIGHT ); } } app.SwapBuffer(app.DISPLAY_BOTH); } void AppBase::Update() { // パッド更新。 UpdatePad(); // ユーザー関数。 OnUpdate(); } void AppBase::UpdatePad() { nw::demo::Pad* pad = nw::demo::PadFactory::GetPad(); pad->Update(); OnUpdatePad( (*pad) ); } void* AppBase::MemAlloc( size_t size, u8 alignment ) { #ifdef NW_PLATFORM_CTRWIN void* ret = nw::demo::Alloc( size, alignment ); #else void* ret = nw::demo::SimpleApp::AllocateDeviceMemory( size, alignment ); #endif // メモリをランダムに初期化しても動作するか確認する。 if ( ret != NULL ) { std::memset( ret, 0xcd, size ); } return ret; } void AppBase::MemFree( void* memory ) { #ifdef NW_PLATFORM_CTRWIN nw::demo::Free( memory ); #else nw::demo::SimpleApp::Free( memory ); #endif } } // namespace nw::snd::demolib } // namespace nw::snd } // namespace nw