1 /*---------------------------------------------------------------------------*
2 Project: NintendoWare
3 File: snd_FrameHeap.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: 27749 $
14 *---------------------------------------------------------------------------*/
15
16 #include "precompiled.h"
17
18 #include <nw/snd/snd_FrameHeap.h>
19
20 #include <nw/snd/snd_BankFileReader.h>
21 #include <nw/snd/snd_GroupFileReader.h>
22 #include <nw/snd/snd_SequenceSoundFileReader.h>
23 #include <nw/snd/snd_WaveArchiveFileReader.h>
24 #include <nw/snd/snd_WaveFileReader.h>
25 #include <nw/snd/snd_WaveSoundFileReader.h>
26 #include <nw/snd/snd_Util.h>
27 #include <new>
28
29 namespace nw {
30 namespace snd {
31 namespace internal {
32
33 namespace
34 {
GetWaveArchiveId(u32 fileId,const SoundArchive & arc)35 u32 GetWaveArchiveId( u32 fileId, const SoundArchive& arc )
36 {
37 for ( u32 j = 0; j < arc.GetWaveArchiveCount(); j++ )
38 {
39 SoundArchive::WaveArchiveInfo info;
40 SoundArchive::ItemId id =
41 Util::GetMaskedItemId( j, ItemType_WaveArchive );
42 if ( arc.ReadWaveArchiveInfo( id, &info ) )
43 {
44 if ( info.fileId == fileId )
45 {
46 return id;
47 }
48 }
49 }
50 return SoundArchive::INVALID_ID;
51 }
52
53 } // anonymous namespace
54
55 /* ========================================================================
56 member function
57 ======================================================================== */
58
59 /*---------------------------------------------------------------------------*
60 Name: FrameHeap
61
62 Description: コンストラクタ
63
64 Arguments: なし
65
66 Returns: なし
67 *---------------------------------------------------------------------------*/
FrameHeap()68 FrameHeap::FrameHeap()
69 : m_pHeap( NULL )
70 {
71 }
72
73 /*---------------------------------------------------------------------------*
74 Name: ~FrameHeap
75
76 Description: デストラクタ
77
78 Arguments: なし
79
80 Returns: なし
81 *---------------------------------------------------------------------------*/
~FrameHeap()82 FrameHeap::~FrameHeap()
83 {
84 if ( IsValid() )
85 {
86 Destroy();
87 }
88 }
89
90 /*---------------------------------------------------------------------------*
91 Name: Create
92
93 Description: ヒープを作成
94
95 Arguments: startAddress - 開始アドレス
96 size - メモリサイズ
97
98 Returns: ヒープハンドル
99 *---------------------------------------------------------------------------*/
Create(void * startAddress,u32 size)100 bool FrameHeap::Create( void* startAddress, u32 size )
101 {
102 NW_NULL_ASSERT( startAddress );
103
104 if ( IsValid() )
105 {
106 Destroy();
107 }
108
109 void* endAddress = static_cast<u8*>( startAddress ) + size;
110 startAddress = ut::RoundUp( startAddress, 4 ); // Heap align
111
112 if ( startAddress > endAddress ) return false;
113
114 size = static_cast<u32>( static_cast<u8*>( endAddress ) - static_cast<u8*>( startAddress ) );
115
116 m_pHeap = ut::FrameHeap::Create( startAddress, size );
117 if ( m_pHeap == NULL ) return false;
118
119 // ベースセクションの作成
120 if ( ! NewSection() ) return false;
121
122 return true;
123 }
124
125 /*---------------------------------------------------------------------------*
126 Name: Destroy
127
128 Description: ヒープを破棄します
129
130 Arguments: None.
131
132 Returns: None.
133 *---------------------------------------------------------------------------*/
Destroy()134 void FrameHeap::Destroy()
135 {
136 if ( IsValid() )
137 {
138 // セクションの破棄
139 ClearSection();
140
141 // ヒープのクリア
142 m_pHeap->Free( ut::FrameHeap::FREE_ALL );
143
144 // ヒープの破棄
145 m_pHeap->Destroy();
146
147 m_pHeap = NULL;
148 }
149 }
150
151 /*---------------------------------------------------------------------------*
152 Name: Clear
153
154 Description: ヒープを作成時の状態に戻す
155
156 Arguments: None.
157
158 Returns: None.
159 *---------------------------------------------------------------------------*/
Clear()160 void FrameHeap::Clear()
161 {
162 NW_ASSERT( IsValid() );
163
164 // セクションの破棄
165 ClearSection();
166
167 // ヒープのクリア
168 m_pHeap->Free( ut::FrameHeap::FREE_ALL );
169
170 // ベースセクションの作成
171 bool result = NewSection();
172 NW_ASSERTMSG( result, "FrameHeap::Clear(): NewSection is Failed");
173 }
174
175 /*---------------------------------------------------------------------------*
176 Name: Alloc
177
178 Description: ヒープからメモリを確保
179
180 Arguments: size - メモリサイズ
181 callback - メモリが破棄されたときに呼びだされるコールバック関数
182 callbackArg - コールバック引数
183
184 Returns: 確保したメモリへのポインタ
185 *---------------------------------------------------------------------------*/
Alloc(u32 size,FrameHeap::DisposeCallback callback,void * callbackArg)186 void* FrameHeap::Alloc( u32 size, FrameHeap::DisposeCallback callback, void* callbackArg )
187 {
188 NW_ASSERT( IsValid() );
189
190 const unsigned long blockSize = ut::RoundUp( sizeof(Block), HEAP_ALIGN );
191 void* mem = m_pHeap->Alloc(
192 blockSize + ut::RoundUp( size, HEAP_ALIGN ),
193 HEAP_ALIGN
194 );
195 if ( mem == NULL ) return NULL;
196 void* buffer = ut::AddOffsetToPtr( mem, blockSize );
197 NW_ASSERTMSG( ( reinterpret_cast<IntPtr>(buffer) & 0x1f ) == 0, "FrameHeap::Alloc: Internal Error" );
198
199 Block* block = new ( mem ) Block( buffer, size, callback, callbackArg );
200
201 m_SectionList.GetBack().AppendBlock( block );
202
203 return buffer;
204 }
205
206 /*---------------------------------------------------------------------------*
207 Name: SaveState
208
209 Description: ヒープの状態を保存
210
211 Arguments: None.
212
213 Returns: 保存した階層レベルを返す
214 失敗時には、-1
215 *---------------------------------------------------------------------------*/
SaveState()216 int FrameHeap::SaveState()
217 {
218 NW_ASSERT( IsValid() );
219
220 if ( ! m_pHeap->RecordState( m_SectionList.GetSize() ) ) {
221 return -1;
222 }
223
224 if ( ! NewSection() ) {
225 int result = m_pHeap->FreeByState( 0 );
226 NW_ASSERTMSG( result, "FrameHeap::SaveState(): ut::FrameHeap::FreeByState is Failed");
227 return -1;
228 }
229
230 return static_cast<int>( m_SectionList.GetSize() ) - 1;
231 }
232
233 /*---------------------------------------------------------------------------*
234 Name: LoadState
235
236 Description: ヒープの状態を戻す
237
238 Arguments: level - 階層レベル
239
240 Returns: None.
241 *---------------------------------------------------------------------------*/
LoadState(int level)242 void FrameHeap::LoadState( int level )
243 {
244 NW_ASSERT( IsValid() );
245 NW_MINMAXLT_ASSERT( level, 0, static_cast<int>( m_SectionList.GetSize() ) );
246
247 if ( level == 0 ) {
248 Clear();
249 return;
250 }
251 while( level < static_cast<int>( m_SectionList.GetSize() ) )
252 {
253 // get latest section
254 Section& section = m_SectionList.GetBack();
255
256 // call dispose callback
257 section.~Section();
258
259 // セクションリストからの削除
260 m_SectionList.Erase( §ion );
261 }
262
263 // ヒープ状態を復元
264 int result = m_pHeap->FreeByState( static_cast<u32>( level ) );
265 NW_UNUSED_VARIABLE( result );
266 NW_ASSERTMSG( result, "FrameHeap::LoadState(): ut::FrameHeap::FreeByState is Failed");
267
268 // 再度記録
269 result = m_pHeap->RecordState( m_SectionList.GetSize() );
270 NW_ASSERTMSG( result, "FrameHeap::LoadState(): ut::FrameHea::RecordState is Failed");
271
272 // セクションの作成
273 bool result2 = NewSection();
274 NW_ASSERTMSG( result2, "FrameHeap::LoadState(): NewSection is Failed");
275 }
276
277 /*---------------------------------------------------------------------------*
278 Name: GetCurrentLevel
279
280 Description: ヒープの現在の階層レベルを取得
281
282 Arguments: None.
283
284 Returns: 現在の階層レベル
285 *---------------------------------------------------------------------------*/
GetCurrentLevel() const286 int FrameHeap::GetCurrentLevel() const
287 {
288 NW_ASSERT( IsValid() );
289
290 return static_cast<int>( m_SectionList.GetSize() ) - 1;
291 }
292
293 /*---------------------------------------------------------------------------*
294 Name: GetSize
295
296 Description: ヒープの容量を取得
297
298 Arguments: None.
299
300 Returns: ヒープの容量
301 *---------------------------------------------------------------------------*/
GetSize() const302 u32 FrameHeap::GetSize() const
303 {
304 NW_ASSERT( IsValid() );
305
306 return static_cast<u32>(
307 static_cast<u8*>( m_pHeap->GetHeapEndAddress() ) -
308 static_cast<u8*>( m_pHeap->GetHeapStartAddress() )
309 );
310 }
311
312 /*---------------------------------------------------------------------------*
313 Name: GetFreeSize
314
315 Description: ヒープの空き容量を取得
316
317 Arguments: None.
318
319 Returns: 空き容量
320 *---------------------------------------------------------------------------*/
GetFreeSize() const321 u32 FrameHeap::GetFreeSize() const
322 {
323 NW_ASSERT( IsValid() );
324
325 u32 size = m_pHeap->GetAllocatableSize( HEAP_ALIGN );
326
327 if ( size < sizeof( Block ) ) return 0;
328 size -= sizeof( Block );
329
330 size &= ~(HEAP_ALIGN-1);
331
332 return size;
333 }
334
335 /*---------------------------------------------------------------------------*
336 Name: NewSection
337
338 Description: 新しいセクションを作成
339
340 Arguments: None.
341
342 Returns: 成功したかどうか
343 *---------------------------------------------------------------------------*/
NewSection()344 bool FrameHeap::NewSection()
345 {
346 // new HeapSection
347 void* buffer = m_pHeap->Alloc( sizeof( Section ) );
348 if ( buffer == NULL ) return false;
349
350 Section* section = new( buffer ) Section();
351 m_SectionList.PushBack( section );
352 return true;
353 }
354
355 /*---------------------------------------------------------------------------*
356 Name: ClearSection
357
358 Description: セクションを全て破棄する
359
360 Arguments: None.
361
362 Returns: None.
363 *---------------------------------------------------------------------------*/
ClearSection()364 void FrameHeap::ClearSection()
365 {
366 // セクションの破棄
367 while ( !m_SectionList.IsEmpty() )
368 {
369 Section& section = m_SectionList.GetBack();
370
371 // コールバックの呼び出し
372 section.~Section();
373
374 // セクションリストからの削除
375 m_SectionList.Erase( §ion );
376 }
377 }
378
Dump(nw::snd::SoundDataManager & mgr,nw::snd::SoundArchive & arc)379 void FrameHeap::Dump(
380 nw::snd::SoundDataManager& mgr, nw::snd::SoundArchive& arc )
381 {
382 int i = 0;
383 for ( SectionList::Iterator itr = m_SectionList.GetBeginIter();
384 itr != m_SectionList.GetEndIter(); )
385 {
386 SectionList::Iterator curItr = itr++;
387 NN_LOG("section[%d]\n", i++ );
388 curItr->Dump( mgr, arc );
389 }
390 }
391
392 /* ========================================================================
393 FrameHeap::Section class member function
394 ======================================================================== */
395
~Section()396 FrameHeap::Section::~Section()
397 {
398 // コールバックを登録逆順に呼びだし
399 BlockList::Iterator itr = m_BlockList.GetEndIter();
400 while ( itr != m_BlockList.GetBeginIter() )
401 {
402 (void)--itr;
403 itr->~Block();
404 }
405 }
406
Dump(nw::snd::SoundDataManager & mgr,nw::snd::SoundArchive & arc)407 void FrameHeap::Section::Dump(
408 nw::snd::SoundDataManager& mgr, nw::snd::SoundArchive& arc )
409 {
410 int i = 0;
411 for ( BlockList::Iterator itr = m_BlockList.GetBeginIter();
412 itr != m_BlockList.GetEndIter(); )
413 {
414 BlockList::Iterator curItr = itr++;
415 const void* ptr = curItr->GetBufferAddr();
416
417 u32 sign = *reinterpret_cast<const u32*>(ptr);
418
419 char signature[5];
420 signature[4] = '\0';
421 std::memcpy( signature, &sign, 4 );
422
423 u32 fileId = mgr.detail_GetFileIdFromTable( ptr );
424
425 SoundArchive::ItemId itemId = SoundArchive::INVALID_ID;
426 u32 waveIndex = 0xffffffff;
427 switch ( sign )
428 {
429 case BankFileReader::SIGNATURE_FILE:
430 for ( u32 j = 0; j < arc.GetBankCount(); j++ )
431 {
432 SoundArchive::BankInfo info;
433 SoundArchive::ItemId id =
434 Util::GetMaskedItemId( j, ItemType_Bank );
435 if ( arc.ReadBankInfo( id, &info ) )
436 {
437 if ( info.fileId == fileId )
438 {
439 itemId = id;
440 break;
441 }
442 }
443 }
444 break;
445 case GroupFileReader::SIGNATURE_FILE:
446 for ( u32 j = 0; j < arc.GetGroupCount(); j++ )
447 {
448 SoundArchive::GroupInfo info;
449 SoundArchive::ItemId id =
450 Util::GetMaskedItemId( j, ItemType_Group );
451 if ( arc.detail_ReadGroupInfo( id, &info ) )
452 {
453 if ( info.fileId == fileId )
454 {
455 itemId = id;
456 break;
457 }
458 }
459 }
460 break;
461 case SequenceSoundFileReader::SIGNATURE_FILE:
462 case WaveSoundFileReader::SIGNATURE_FILE:
463 for ( u32 j = 0; j < arc.GetSoundCount(); j++ )
464 {
465 SoundArchive::SoundInfo info;
466 SoundArchive::ItemId id =
467 Util::GetMaskedItemId( j, ItemType_Sound );
468 if ( arc.ReadSoundInfo( id, &info ) )
469 {
470 if ( info.fileId == fileId )
471 {
472 itemId = id;
473 break;
474 }
475 }
476 }
477 break;
478 case WaveArchiveFileReader::SIGNATURE_FILE:
479 itemId = GetWaveArchiveId( fileId, arc );
480 break;
481 // 個別ロードの波形
482 case SoundDataManager::SIGNATURE_INDIVIDUAL_WAVE:
483 {
484 const u32* pU32Array = reinterpret_cast<const u32*>(ptr);
485 fileId = pU32Array[1];
486 waveIndex = pU32Array[2];
487 itemId = GetWaveArchiveId( fileId, arc );
488 }
489 break;
490 default:
491 itemId = SoundArchive::INVALID_ID;
492 break;
493 }
494
495 const char* pItemLabel = arc.GetItemLabel( itemId );
496 if ( pItemLabel != NULL )
497 {
498 NN_LOG(" block[%d] 0x%08X [%s] fileId(%6d) itemId(%08X) [%s]",
499 i++, ptr, signature, fileId, itemId, pItemLabel );
500 }
501 else
502 {
503 NN_LOG(" block[%d] 0x%08X [%s] fileId(%6d) itemId(%08X) [(anonymous)]",
504 i++, ptr, signature, fileId, itemId );
505 }
506
507 if ( waveIndex != 0xffffffff )
508 {
509 NN_LOG("(%d)\n", waveIndex );
510 }
511 else
512 {
513 NN_LOG("\n");
514 }
515 }
516 }
517
518 } // namespace nw::snd::internal
519 } // namespace nw::snd
520 } // namespace nw
521
522