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