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