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