1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     demolib.cpp
4 
5   Copyright (C)2009-2010 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:$
14  *---------------------------------------------------------------------------*/
15 
16 #include "precompiled.h"
17 
18 #include "demolib.h"
19 
20 #if NN_CURRENT_VERSION_NUMBER >= NN_VERSION_NUMBER(0,13,0,0)
21     #define NW_SND_AVAILABLE_NN_PL_SHARED_FONT
22     // NW_SND_AVAILABLE_NN_PL_SHARED_FONT が無効な場合、
23     // ビルドは通るが、おそらく実行時にエラーになる
24 #endif
25 
26 #ifdef NW_SND_AVAILABLE_NN_PL_SHARED_FONT
27 #include <nn/pl.h>
28 #endif
29 
30 #ifdef NW_PLATFORM_CTRWIN
31     #include <windows.h>    // WAVE_MAPPER
32 #endif
33 
34 namespace nw {
35 namespace snd {
36 namespace demolib {
37 
38 namespace {
39 
40 #ifdef NW_PLATFORM_CTRWIN
41 const char FONT_PATH[]           = NW_SND_DEMO_PATH_PREFIX "sampleFont.bcfnt";
42 #endif
43 const size_t ROMFS_MAX_FILE      = 128;
44 const size_t ROMFS_MAX_DIRECTORY = 128;
45 const s32 DRAW_STRING_BUFFER_UPPER_LCD = 512;
46 const s32 DRAW_STRING_BUFFER_LOWER_LCD = 512;
47 
48 const f32 FONT_SIZE_HIGHT = 14.0f;
49 
50 const nw::ut::FloatColor CLEAR_BUFFER_COLOR( 0.3f, 0.3f, 0.3f, 1.0f );
51 const f32 CLEAR_BUFFER_DEPTH = 0.0f;
52 
53 } // anonymous namespace
54 
AppBase()55 AppBase::AppBase()
56 : m_pMemoryForRomFileSystem( NULL ),
57   m_IsDraw( true )
58 {
59 }
60 
LoadDspComponent()61 void AppBase::LoadDspComponent()
62 {
63 #ifdef NW_PLATFORM_CTR
64     nn::Result result;
65     result = nn::dsp::LoadDefaultComponent();
66     NN_UTIL_PANIC_IF_FAILED(result);
67 #endif
68 }
69 
InitializeSDK()70 void AppBase::InitializeSDK()
71 {
72     // サウンド SDK の初期化
73     // (サウンド以外に初期化は demo_GraphicsSysteCTR.cppi の InitializeGraphicsSystem() で行われます。)
74   #ifdef NW_PLATFORM_CTRWIN
75     {
76         AI_Init( WAVE_MAPPER );
77         AX_Init();
78     }
79   #else
80     {
81         nn::Result result;
82         result = nn::dsp::Initialize();
83         NN_UTIL_PANIC_IF_FAILED(result);
84         LoadDspComponent();
85         result = nn::snd::Initialize();
86         NN_UTIL_PANIC_IF_FAILED(result);
87     }
88   #endif
89 }
90 
InitializeDraw(int width,int height)91 void AppBase::InitializeDraw( int width, int height )
92 {
93     // カラーバッファ情報
94     // LCDの向きに合わせて、幅と高さを入れ替えています。
95     const nw::font::ColorBufferInfo colBufInfo = { height, width, PICA_DATA_DEPTH24_STENCIL8_EXT };
96 
97     const u32 screenSettingCommands[] =
98     {
99         // ビューポートの設定
100         NW_FONT_CMD_SET_VIEWPORT( 0, 0, colBufInfo.width, colBufInfo.height ),
101 
102         // シザー処理を無効
103         NW_FONT_CMD_SET_DISABLE_SCISSOR( colBufInfo ),
104 
105         // wバッファの無効化
106         // デプスレンジの設定
107         // ポリゴンオフセットの無効化
108         NW_FONT_CMD_SET_WBUFFER_DEPTHRANGE_POLYGONOFFSET(
109             0.0f,           // wScale : 0.0 でWバッファが無効
110             0.0f,           // depth range near
111             1.0f,           // depth range far
112             0,              // polygon offset units : 0.0 で ポリゴンオフセットが無効
113             colBufInfo),
114     };
115 
116     nngxAdd3DCommand(screenSettingCommands, sizeof(screenSettingCommands), true);
117 
118     static const u32 s_InitCommands[] =
119     {
120         // カリングを無効
121         NW_FONT_CMD_SET_CULL_FACE( NW_FONT_CMD_CULL_FACE_DISABLE ),
122 
123         // ステンシルテストを無効
124         NW_FONT_CMD_SET_DISABLE_STENCIL_TEST(),
125 
126         // デプステストを無効
127         // カラーバッファの全ての成分を書き込み可
128         NW_FONT_CMD_SET_DEPTH_FUNC_COLOR_MASK(
129             false,  // isDepthTestEnabled
130             0,      // depthFunc
131             true,   // depthMask
132             true,   // red
133             true,   // green
134             true,   // blue
135             true),  // alpha
136 
137         // アーリーデプステストを無効
138         NW_FONT_CMD_SET_ENABLE_EARLY_DEPTH_TEST( false ),
139 
140         // フレームバッファアクセス制御
141         NW_FONT_CMD_SET_FBACCESS(
142             true,   // colorRead
143             true,   // colorWrite
144             false,  // depthRead
145             false,  // depthWrite
146             false,  // stencilRead
147             false), // stencilWrite
148     };
149 
150     nngxAdd3DCommand(s_InitCommands, sizeof(s_InitCommands), true);
151 }
152 
InitializeFont()153 bool AppBase::InitializeFont()
154 {
155     void* buffer = NULL;
156 
157 #ifdef NW_PLATFORM_CTRWIN
158     {
159         nn::fs::FileReader fontReader( FONT_PATH );
160 
161         s32 fileSize = (s32)fontReader.GetSize();
162         if ( fileSize <= 0 ) { return false; }
163 
164         buffer = MemAlloc( fileSize, nw::font::GlyphDataAlignment );
165         if ( buffer == NULL ) { return false; }
166 
167         s32 readSize = fontReader.Read( buffer, fileSize );
168         if ( readSize != fileSize )
169         {
170             MemFree( buffer );
171             return false;
172         }
173     }
174 #else
175     {
176     #ifdef NW_SND_AVAILABLE_NN_PL_SHARED_FONT
177         nn::pl::Initialize();
178         NN_UTIL_PANIC_IF_FAILED(nn::pl::InitializeSharedFont());
179 
180         // 共有フォントのロードが完了するまで待機
181         while (nn::pl::GetSharedFontLoadState() != nn::pl::SHARED_FONT_LOAD_STATE_LOADED)
182         {
183             // 共有フォントのロードに失敗していないか確認
184             if (nn::pl::GetSharedFontLoadState() == nn::pl::SHARED_FONT_LOAD_STATE_FAILED)
185             {
186                 NN_TPANIC_("failed to load shared font!\n");
187             }
188             nn::os::Thread::Sleep(nn::fnd::TimeSpan::FromMilliSeconds(10));
189             NN_LOG("loading SharedFont ...\n");
190         }
191         buffer = nn::pl::GetSharedFontAddress();
192         nn::pl::Finalize();
193     #endif
194     }
195 #endif
196 
197     // フォントリソースをセットします
198     bool bSuccess = m_Font.SetResource( buffer );
199     NW_ASSERT( bSuccess );
200 
201     if ( !bSuccess )
202     {
203         MemFree( buffer );
204     }
205 
206     // 描画用バッファの設定。 (処理速度高速化のため。)
207     const size_t drawBufferSize = nw::font::ResFont::GetDrawBufferSize( buffer );
208     void* drawBuffer = MemAlloc( drawBufferSize, 4 );
209     NW_NULL_ASSERT(drawBuffer);
210     m_Font.SetDrawBuffer( drawBuffer );
211 
212     return bSuccess;
213 }
214 
FinalizeFont()215 void AppBase::FinalizeFont()
216 {
217     void *const drawBuffer = m_Font.SetDrawBuffer( NULL );
218     if ( drawBuffer != NULL )
219     {
220         MemFree( drawBuffer );
221     }
222 
223     void *const resource = m_Font.RemoveResource();
224     if ( resource != NULL )
225     {
226         MemFree( resource );
227     }
228 }
229 
InitializeShaders()230 void AppBase::InitializeShaders()
231 {
232     // NOTE: demo/font/ResFont の InitShaders を参考にした。
233     const wchar_t* shaders = NW_DEMO_FILE_PATH( NW_FONT_RECTDRAWER_SHADERBINARY );
234     nn::fs::FileReader shaderReader( shaders );
235 
236     const u32 fileSize = (u32)shaderReader.GetSize();
237     void* shaderBinary = MemAlloc( fileSize );
238     NW_NULL_ASSERT( shaderBinary );
239 
240     s32 read = shaderReader.Read( shaderBinary, fileSize );
241     NW_ASSERT( read == fileSize );
242 
243     const u32 vtxBufCmdBufSize =
244         nw::font::RectDrawer::GetVertexBufferCommandBufferSize( shaderBinary, fileSize );
245     void *const vtxBufCmdBuf = MemAlloc( vtxBufCmdBufSize );
246     NW_NULL_ASSERT( vtxBufCmdBuf );
247     m_Drawer.Initialize( vtxBufCmdBuf, shaderBinary, fileSize );
248 
249     MemFree( shaderBinary );
250     m_pMemoryForDrawBuffer = vtxBufCmdBuf;
251 }
252 
FinalizeShaders()253 void AppBase::FinalizeShaders()
254 {
255     m_Drawer.Finalize();
256     MemFree( m_pMemoryForDrawBuffer );
257 }
258 
InitializeDrawStringBuffer()259 void AppBase::InitializeDrawStringBuffer()
260 {
261     m_pDrawStringBufferUpperLcd = AllocDispStringBuffer( DRAW_STRING_BUFFER_UPPER_LCD );
262     m_pDrawStringBufferLowerLcd = AllocDispStringBuffer( DRAW_STRING_BUFFER_LOWER_LCD );
263 }
FinalizeDrawStringBuffer()264 void AppBase::FinalizeDrawStringBuffer()
265 {
266     MemFree( m_pDrawStringBufferUpperLcd );
267     MemFree( m_pDrawStringBufferLowerLcd );
268 }
269 
270 nw::font::DispStringBuffer*
AllocDispStringBuffer(int charMax)271 AppBase::AllocDispStringBuffer(int charMax)
272 {
273     const u32 DrawBufferSize = nw::font::CharWriter::GetDispStringBufferSize(charMax);
274     void *const bufMem = MemAlloc(DrawBufferSize);
275     NN_NULL_ASSERT(bufMem);
276 
277     return nw::font::CharWriter::InitDispStringBuffer(bufMem, charMax);
278 }
279 
280 
FinalizeSDK()281 void AppBase::FinalizeSDK()
282 {
283 #ifdef NW_PLATFORM_CTRWIN
284 #else
285     {
286         nn::Result result;
287         result = nn::snd::Finalize();
288         NN_UTIL_PANIC_IF_FAILED( result );
289 
290         result = nn::dsp::UnloadComponent();
291         NN_UTIL_PANIC_IF_FAILED( result );
292 
293         nn::dsp::Finalize();
294 
295         MemFree( m_pMemoryForRomFileSystem );   // fs::Finalize が無いので、解放するとまずい?
296     }
297 
298     // nn::fs::Finalize は無い
299     // nn::os::Finalize は無い
300 #endif
301 }
302 
SetupTextCamera(nw::font::RectDrawer * pDrawer,int width,int height)303 void AppBase::SetupTextCamera(
304         nw::font::RectDrawer* pDrawer,
305         int width,
306         int height )
307 {
308     // 射影行列を正射影に設定
309     {
310         // 左上原点とし、Y軸とZ軸の向きが逆になるように設定します。
311         nn::math::MTX44 proj;
312         f32 znear   =  0.0f;
313         f32 zfar    = -1.0f;
314         f32 t       =  0;
315         f32 b       =  static_cast<f32>(height);
316         f32 l       =  0;
317         f32 r       =  static_cast<f32>(width);
318         nn::math::MTX44OrthoPivot(&proj, l, r, b, t, znear, zfar, nn::math::PIVOT_UPSIDE_TO_TOP);
319         pDrawer->SetProjectionMtx(proj);
320     }
321 
322     // モデルビュー行列を単位行列に設定
323     {
324         nn::math::MTX34 mv;
325         nn::math::MTX34Identity(&mv);
326         pDrawer->SetViewMtxForText(mv);
327     }
328 }
329 
Initialize()330 void AppBase::Initialize()
331 {
332     // 規定の初期化
333     nw::demo::SimpleApp::GetInstance().Initialize();
334     InitializeSDK();
335 
336     // フォントの構築
337     InitializeFont();
338 
339     // 描画リソースの構築
340     InitializeShaders();
341     InitializeDrawStringBuffer();
342 
343     // ユーザーの初期化処理
344     OnInitialize();
345 }
346 
Finalize()347 void AppBase::Finalize()
348 {
349     // ユーザーの終了処理
350     OnFinalize();
351 
352     // 規定の終了処理
353     FinalizeDrawStringBuffer();
354     FinalizeShaders();
355 
356     FinalizeFont();
357     FinalizeSDK();
358 
359     // demoPadの終了処理
360     nw::demo::PadFactory::Finalize();
361 }
362 
Run()363 void AppBase::Run()
364 {
365     while ( true )
366     {
367         // パッドなどの更新処理
368         Update();
369 
370         // 描画 (Vブランク待ちを含む)
371         Draw();
372     }
373 }
374 
DrawStringPreProcess(nw::font::TextWriter & writer,const nw::gfx::FrameBufferObject & frameBufferObject,int width,int height)375 void AppBase::DrawStringPreProcess(
376         nw::font::TextWriter& writer,
377         const nw::gfx::FrameBufferObject& frameBufferObject,
378         int width,
379         int height )
380 {
381     frameBufferObject.ClearBuffer( CLEAR_BUFFER_COLOR, CLEAR_BUFFER_DEPTH );
382 
383     InitializeDraw( width, height );
384 
385     writer.SetDispStringBuffer( m_pDrawStringBufferUpperLcd );
386     writer.SetCursor( 0, 0 );
387 
388     writer.StartPrint();
389 }
DrawStringPostProcess(nw::font::TextWriter & writer,int width,int height)390 void AppBase::DrawStringPostProcess( nw::font::TextWriter& writer, int width, int height )
391 {
392     writer.EndPrint();
393     m_Drawer.BuildTextCommand( &writer );
394 
395     m_Drawer.DrawBegin();
396     {
397         SetupTextCamera( &m_Drawer, width, height );
398         writer.UseCommandBuffer();
399     }
400     m_Drawer.DrawEnd();
401 }
Draw()402 void AppBase::Draw()
403 {
404     nw::demo::SimpleApp& app = nw::demo::SimpleApp::GetInstance();
405 
406     if ( m_IsDraw == true )
407     {
408         nw::font::TextWriter writer;
409         writer.SetFont( &m_Font );
410         writer.SetCharSpace( 1.0f );
411         writer.EnableFixedWidth( true );
412         writer.SetFontSize( FONT_SIZE_HIGHT );
413         writer.SetFixedWidth( writer.GetLineHeight() / 2.f );
414 
415         app.SetRenderingTarget( app.DISPLAY0 );
416         {
417             DrawStringPreProcess(
418                     writer,
419                     app.GetFrameBufferObject(),
420                     app.DISPLAY0_WIDTH,
421                     app.DISPLAY0_HEIGHT );
422             OnDrawUpLCD( writer );
423             DrawStringPostProcess( writer, app.DISPLAY0_WIDTH, app.DISPLAY0_HEIGHT );
424         }
425 
426         app.SetRenderingTarget( app.DISPLAY1 );
427         {
428             DrawStringPreProcess(
429                     writer,
430                     app.GetFrameBufferObject(),
431                     app.DISPLAY1_WIDTH,
432                     app.DISPLAY1_HEIGHT );
433             OnDrawDownLCD( writer );
434             DrawStringPostProcess( writer, app.DISPLAY1_WIDTH, app.DISPLAY1_HEIGHT );
435         }
436     }
437 
438     app.SwapBuffer(app.DISPLAY_BOTH);
439 }
440 
441 
Update()442 void AppBase::Update()
443 {
444     // パッド更新。
445     UpdatePad();
446 
447     // ユーザー関数。
448     OnUpdate();
449 }
450 
UpdatePad()451 void AppBase::UpdatePad()
452 {
453     nw::demo::Pad* pad = nw::demo::PadFactory::GetPad();
454     pad->Update();
455     OnUpdatePad( (*pad) );
456 }
457 
MemAlloc(size_t size,u8 alignment)458 void* AppBase::MemAlloc( size_t size, u8 alignment )
459 {
460 #ifdef NW_PLATFORM_CTRWIN
461     void* ret = nw::demo::Alloc( size, alignment );
462 #else
463     void* ret = nw::demo::SimpleApp::AllocateDeviceMemory( size, alignment );
464 #endif
465 
466     // メモリをランダムに初期化しても動作するか確認する。
467     if ( ret != NULL )
468     {
469         std::memset( ret, 0xcd, size );
470     }
471     return ret;
472 }
473 
MemFree(void * memory)474 void AppBase::MemFree( void* memory )
475 {
476 #ifdef NW_PLATFORM_CTRWIN
477     nw::demo::Free( memory );
478 #else
479     nw::demo::SimpleApp::Free( memory );
480 #endif
481 }
482 
483 } // namespace nw::snd::demolib
484 } // namespace nw::snd
485 } // namespace nw
486