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