1 /*---------------------------------------------------------------------------*
2 Project: NintendoWare
3 File: snd_SoundArchiveFileReader.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: 31311 $
16 *---------------------------------------------------------------------------*/
17
18 #include "precompiled.h"
19 #include <nw/snd/snd_SoundArchiveFileReader.h>
20 #include <nw/snd/snd_ItemType.h>
21
22 namespace nw {
23 namespace snd {
24 namespace internal {
25
26 namespace {
27
28 const u32 SIGNATURE_STRING_BLOCK = NW_UT_MAKE_SIGWORD( 'S', 'T', 'R', 'G' );
29 const u32 SIGNATURE_INFO_BLOCK = NW_UT_MAKE_SIGWORD( 'I', 'N', 'F', 'O' );
30 const u32 SIGNATURE_DATA_BLOCK = NW_UT_MAKE_SIGWORD( 'D', 'A', 'T', 'A' );
31 const u32 SUPPORTED_FILE_VERSION = 0x02000000;
32 const u32 CURRENT_FILE_VERSION = 0x02000000;
33
IsValidFileHeader(const void * soundArchiveData)34 bool IsValidFileHeader( const void* soundArchiveData )
35 {
36 const ut::BinaryFileHeader& header =
37 *reinterpret_cast<const ut::BinaryFileHeader*>( soundArchiveData );
38
39 // シグニチャ確認
40 NW_ASSERTMSG( header.signature == SoundArchiveFileReader::SIGNATURE_FILE,
41 "invalid file signature." );
42 if ( header.signature != SoundArchiveFileReader::SIGNATURE_FILE )
43 {
44 return false;
45 }
46
47 // バージョン確認
48 NW_ASSERTMSG(
49 header.version >= SUPPORTED_FILE_VERSION,
50 "sound archive file is not supported version.\n"
51 "please reconvert file using new version tools.\n"
52 "(SUPPORTED_FILE_VERSION:0x%08x >= your version:0x%08x)\n",
53 SUPPORTED_FILE_VERSION, header.version
54 );
55 if ( header.version < SUPPORTED_FILE_VERSION )
56 {
57 return false;
58 }
59 NW_ASSERTMSG(
60 header.version <= CURRENT_FILE_VERSION,
61 "sound archive file is not supported version.\n"
62 "please reconvert file using new version tools.\n"
63 "(CURRENT_FILE_VERSION:0x%08x <= your version:0x%08x)\n",
64 CURRENT_FILE_VERSION, header.version
65 );
66 if ( header.version > CURRENT_FILE_VERSION )
67 {
68 return false;
69 }
70 return true;
71 }
72
73 } // anonymous namespace
74
SoundArchiveFileReader()75 SoundArchiveFileReader::SoundArchiveFileReader()
76 : m_pStringBlockBody( NULL ),
77 m_pInfoBlockBody( NULL ),
78 m_pFileBlockBody( NULL )
79 {
80 }
81
Initialize(const void * soundArchiveData)82 void SoundArchiveFileReader::Initialize( const void* soundArchiveData )
83 {
84 NW_NULL_ASSERT( soundArchiveData );
85 if ( ! IsValidFileHeader( soundArchiveData ) ) return;
86
87 const SoundArchiveFile::FileHeader& header =
88 *reinterpret_cast<const SoundArchiveFile::FileHeader*>( soundArchiveData );
89 m_Header = header; // 構造体コピー
90 }
91
Finalize()92 void SoundArchiveFileReader::Finalize()
93 {
94 m_pStringBlockBody = NULL;
95 m_pInfoBlockBody = NULL;
96 m_pFileBlockBody = NULL;
97 }
98
SetStringBlock(const void * stringBlock)99 void SoundArchiveFileReader::SetStringBlock( const void* stringBlock )
100 {
101 m_pStringBlockBody =
102 &reinterpret_cast<const SoundArchiveFile::StringBlock*>( stringBlock )->body;
103 }
104
SetInfoBlock(const void * infoBlock)105 void SoundArchiveFileReader::SetInfoBlock( const void* infoBlock )
106 {
107 m_pInfoBlockBody =
108 &reinterpret_cast<const SoundArchiveFile::InfoBlock*>( infoBlock )->body;
109 }
110
GetStringCount() const111 u32 SoundArchiveFileReader::GetStringCount() const
112 {
113 NW_NULL_ASSERT( m_pStringBlockBody );
114 return m_pStringBlockBody->GetStringCount();
115 }
GetString(SoundArchive::ItemId stringId) const116 const char* SoundArchiveFileReader::GetString( SoundArchive::ItemId stringId ) const
117 {
118 NW_NULL_ASSERT( m_pStringBlockBody );
119 return m_pStringBlockBody->GetString( stringId );
120 }
121
DumpTree() const122 void SoundArchiveFileReader::DumpTree() const
123 {
124 NW_NULL_ASSERT( m_pStringBlockBody );
125 m_pStringBlockBody->DumpTree();
126 }
127
GetItemId(const char * pStr) const128 SoundArchive::ItemId SoundArchiveFileReader::GetItemId( const char* pStr ) const
129 {
130 if ( m_pStringBlockBody == NULL )
131 {
132 return SoundArchive::INVALID_ID;
133 }
134 return m_pStringBlockBody->GetItemId( pStr );
135 }
GetItemLabel(SoundArchive::ItemId id) const136 const char* SoundArchiveFileReader::GetItemLabel( SoundArchive::ItemId id ) const
137 {
138 NW_NULL_ASSERT( m_pInfoBlockBody );
139 if ( m_pStringBlockBody == NULL )
140 {
141 return NULL;
142 }
143 SoundArchive::StringId stringId = m_pInfoBlockBody->GetItemStringId( id );
144 if ( stringId == SoundArchive::INVALID_ID )
145 {
146 return NULL;
147 }
148 return m_pStringBlockBody->GetString( stringId );
149 }
GetItemFileId(SoundArchive::ItemId id) const150 SoundArchive::FileId SoundArchiveFileReader::GetItemFileId( SoundArchive::ItemId id ) const
151 {
152 NW_NULL_ASSERT( m_pInfoBlockBody );
153 return m_pInfoBlockBody->GetItemFileId( id );
154 }
155
GetSoundCount() const156 u32 SoundArchiveFileReader::GetSoundCount() const
157 {
158 NW_NULL_ASSERT( m_pInfoBlockBody );
159 return m_pInfoBlockBody->GetSoundCount();
160 }
161
GetBankCount() const162 u32 SoundArchiveFileReader::GetBankCount() const
163 {
164 NW_NULL_ASSERT( m_pInfoBlockBody );
165 return m_pInfoBlockBody->GetBankCount();
166 }
167
GetPlayerCount() const168 u32 SoundArchiveFileReader::GetPlayerCount() const
169 {
170 NW_NULL_ASSERT( m_pInfoBlockBody );
171 return m_pInfoBlockBody->GetPlayerCount();
172 }
173
GetSoundGroupCount() const174 u32 SoundArchiveFileReader::GetSoundGroupCount() const
175 {
176 NW_NULL_ASSERT( m_pInfoBlockBody );
177 return m_pInfoBlockBody->GetSoundGroupCount();
178 }
179
GetGroupCount() const180 u32 SoundArchiveFileReader::GetGroupCount() const
181 {
182 NW_NULL_ASSERT( m_pInfoBlockBody );
183 return m_pInfoBlockBody->GetGroupCount();
184 }
185
GetWaveArchiveCount() const186 u32 SoundArchiveFileReader::GetWaveArchiveCount() const
187 {
188 NW_NULL_ASSERT( m_pInfoBlockBody );
189 return m_pInfoBlockBody->GetWaveArchiveCount();
190 }
191
GetFileCount() const192 u32 SoundArchiveFileReader::GetFileCount() const
193 {
194 NW_NULL_ASSERT( m_pInfoBlockBody );
195 return m_pInfoBlockBody->GetFileCount();
196 }
197
ReadSoundInfo(SoundArchive::ItemId soundId,SoundArchive::SoundInfo * info) const198 bool SoundArchiveFileReader::ReadSoundInfo(
199 SoundArchive::ItemId soundId, SoundArchive::SoundInfo* info ) const
200 {
201 NW_NULL_ASSERT( m_pInfoBlockBody );
202 NW_NULL_ASSERT( info );
203
204 const SoundArchiveFile::SoundInfo* data = m_pInfoBlockBody->GetSoundInfo( soundId );
205 if ( data == NULL ) return false;
206
207 info->fileId = data->fileId;
208 info->playerId = data->playerId;
209 info->volume = data->volume;
210 info->panMode = data->GetPanMode();
211 info->panCurve = data->GetPanCurve();
212 info->playerPriority = data->GetPlayerPriority();
213 info->actorPlayerId = data->GetActorPlayerId();
214 info->isFrontBypass = data->IsFrontBypass();
215
216 return true;
217 }
218
ReadBankInfo(SoundArchive::ItemId bankId,SoundArchive::BankInfo * info) const219 bool SoundArchiveFileReader::ReadBankInfo(
220 SoundArchive::ItemId bankId, SoundArchive::BankInfo* info ) const
221 {
222 NW_NULL_ASSERT( m_pInfoBlockBody );
223 NW_NULL_ASSERT( info );
224
225 const SoundArchiveFile::BankInfo* data = m_pInfoBlockBody->GetBankInfo( bankId );
226 if ( data == NULL ) return false;
227
228 info->fileId = data->fileId;
229 return true;
230 }
231
ReadPlayerInfo(SoundArchive::ItemId playerId,SoundArchive::PlayerInfo * info) const232 bool SoundArchiveFileReader::ReadPlayerInfo(
233 SoundArchive::ItemId playerId, SoundArchive::PlayerInfo* info ) const
234 {
235 NW_NULL_ASSERT( m_pInfoBlockBody );
236 NW_NULL_ASSERT( info );
237
238 const SoundArchiveFile::PlayerInfo* data = m_pInfoBlockBody->GetPlayerInfo( playerId );
239 if ( data == NULL ) return false;
240
241 info->playableSoundMax = data->playableSoundMax;
242 info->playerHeapSize = data->GetPlayerHeapSize();
243
244 return true;
245 }
246
ReadSoundGroupInfo(SoundArchive::ItemId soundGroupId,SoundArchive::SoundGroupInfo * info) const247 bool SoundArchiveFileReader::ReadSoundGroupInfo(
248 SoundArchive::ItemId soundGroupId, SoundArchive::SoundGroupInfo* info ) const
249 {
250 NW_NULL_ASSERT( m_pInfoBlockBody );
251 NW_NULL_ASSERT( info );
252
253 const SoundArchiveFile::SoundGroupInfo* data = m_pInfoBlockBody->GetSoundGroupInfo( soundGroupId );
254 if ( data == NULL ) return false;
255
256 info->startId = data->startId;
257 info->endId = data->endId;
258 info->fileIdTable = data->GetFileIdTable();
259 return true;
260 }
261
ReadGroupInfo(SoundArchive::ItemId groupId,SoundArchive::GroupInfo * info) const262 bool SoundArchiveFileReader::ReadGroupInfo(
263 SoundArchive::ItemId groupId, SoundArchive::GroupInfo* info ) const
264 {
265 NW_NULL_ASSERT( m_pInfoBlockBody );
266 NW_NULL_ASSERT( info );
267
268 const SoundArchiveFile::GroupInfo* data = m_pInfoBlockBody->GetGroupInfo( groupId );
269 if ( data == NULL ) return false;
270
271 info->fileId = data->fileId;
272 return true;
273 }
274
ReadWaveArchiveInfo(SoundArchive::ItemId warcId,SoundArchive::WaveArchiveInfo * info) const275 bool SoundArchiveFileReader::ReadWaveArchiveInfo(
276 SoundArchive::ItemId warcId, SoundArchive::WaveArchiveInfo* info ) const
277 {
278 NW_NULL_ASSERT( m_pInfoBlockBody );
279 NW_NULL_ASSERT( info );
280
281 const SoundArchiveFile::WaveArchiveInfo* data = m_pInfoBlockBody->GetWaveArchiveInfo( warcId );
282 if ( data == NULL ) return false;
283
284 info->fileId = data->fileId;
285 info->waveCount = data->GetWaveCount();
286 info->isLoadIndividual = data->isLoadIndividual;
287 return true;
288 }
289
ReadFileInfo(SoundArchive::FileId id,SoundArchive::FileInfo * info,int index) const290 bool SoundArchiveFileReader::ReadFileInfo(
291 SoundArchive::FileId id, SoundArchive::FileInfo* info, int index ) const
292 {
293 NW_NULL_ASSERT( m_pInfoBlockBody );
294 NW_NULL_ASSERT( info );
295 NW_UNUSED_VARIABLE( index );
296
297 const SoundArchiveFile::FileInfo* data = m_pInfoBlockBody->GetFileInfo( id );
298 if ( data == NULL ) return false;
299
300 switch ( data->GetFileLocationType() )
301 {
302 case SoundArchiveFile::FILE_LOCATION_TYPE_INTERNAL:
303 {
304 const SoundArchiveFile::InternalFileInfo* location = data->GetInternalFileInfo();
305 info->fileSize = location->GetFileSize();
306 info->offsetFromFileBlockHead = location->GetOffsetFromFileBlockHead();
307 }
308 break;
309 case SoundArchiveFile::FILE_LOCATION_TYPE_EXTERNAL:
310 {
311 const SoundArchiveFile::ExternalFileInfo* location = data->GetExternalFileInfo();
312 info->externalFilePath = location->filePath;
313 }
314 break;
315 case SoundArchiveFile::FILE_LOCATION_TYPE_NONE:
316 return false;
317 }
318 return true;
319 }
320
ReadSoundArchivePlayerInfo(SoundArchive::SoundArchivePlayerInfo * info) const321 bool SoundArchiveFileReader::ReadSoundArchivePlayerInfo(
322 SoundArchive::SoundArchivePlayerInfo* info ) const
323 {
324 NW_NULL_ASSERT( m_pInfoBlockBody );
325 NW_NULL_ASSERT( info );
326
327 const SoundArchiveFile::SoundArchivePlayerInfo* data = m_pInfoBlockBody->GetSoundArchivePlayerInfo();
328 if ( data == NULL ) return false;
329
330 info->sequenceSoundMax = data->sequenceSoundMax;
331 info->sequenceTrackMax = data->sequenceTrackMax;
332 info->streamSoundMax = data->streamSoundMax;
333 info->streamTrackMax = data->streamTrackMax;
334 info->streamChannelMax = data->streamChannelMax;
335 info->waveSoundMax = data->waveSoundMax;
336 info->waveTrackMax = data->waveTrackmax;
337 return true;
338 }
339
ReadSound3DInfo(SoundArchive::ItemId soundId,SoundArchive::Sound3DInfo * info) const340 bool SoundArchiveFileReader::ReadSound3DInfo(
341 SoundArchive::ItemId soundId, SoundArchive::Sound3DInfo* info ) const
342 {
343 NW_NULL_ASSERT( m_pInfoBlockBody );
344 NW_NULL_ASSERT( info );
345
346 const SoundArchiveFile::SoundInfo* soundInfo = m_pInfoBlockBody->GetSoundInfo( soundId );
347 if ( soundInfo == NULL )
348 {
349 return false;
350 }
351
352 const SoundArchiveFile::Sound3DInfo* sound3dInfo = soundInfo->GetSound3DInfo();
353 if ( sound3dInfo == NULL )
354 {
355 return false;
356 }
357 info->flags = sound3dInfo->flags;
358 info->decayRatio = sound3dInfo->decayRatio;
359 info->decayCurve = sound3dInfo->decayCurve;
360 info->dopplerFactor = sound3dInfo->dopplerFactor;
361 return true;
362 }
363
ReadSequenceSoundInfo(SoundArchive::ItemId soundId,SoundArchive::SequenceSoundInfo * info) const364 bool SoundArchiveFileReader::ReadSequenceSoundInfo(
365 SoundArchive::ItemId soundId, SoundArchive::SequenceSoundInfo* info ) const
366 {
367 NW_NULL_ASSERT( m_pInfoBlockBody );
368 NW_NULL_ASSERT( info );
369
370 const SoundArchiveFile::SoundInfo* soundInfo = m_pInfoBlockBody->GetSoundInfo( soundId );
371 if ( soundInfo == NULL )
372 {
373 return false;
374 }
375 if ( soundInfo->GetSoundType() != SoundArchive::SOUND_TYPE_SEQ )
376 {
377 return false;
378 }
379
380 const SoundArchiveFile::SequenceSoundInfo& seqSoundInfo = soundInfo->GetSequenceSoundInfo();
381 info->startOffset = seqSoundInfo.GetStartOffset();
382 info->allocateTrackFlags = seqSoundInfo.allocateTrackFlags;
383 info->channelPriority = seqSoundInfo.GetChannelPriority();
384 info->isReleasePriorityFix = seqSoundInfo.IsReleasePriorityFix();
385 seqSoundInfo.GetBankIds( info->bankIds );
386 return true;
387 }
388
ReadStreamSoundInfo(SoundArchive::ItemId soundId,SoundArchive::StreamSoundInfo * info) const389 bool SoundArchiveFileReader::ReadStreamSoundInfo(
390 SoundArchive::ItemId soundId, SoundArchive::StreamSoundInfo* info ) const
391 {
392 NW_NULL_ASSERT( m_pInfoBlockBody );
393 NW_NULL_ASSERT( info );
394
395 const SoundArchiveFile::SoundInfo* soundInfo = m_pInfoBlockBody->GetSoundInfo( soundId );
396 if ( soundInfo == NULL )
397 {
398 return false;
399 }
400 if ( soundInfo->GetSoundType() != SoundArchive::SOUND_TYPE_STRM )
401 {
402 return false;
403 }
404
405 const SoundArchiveFile::StreamSoundInfo& strmSoundInfo = soundInfo->GetStreamSoundInfo();
406 info->allocTrackCount = strmSoundInfo.allocTrackCount;
407 info->allocChannelCount = strmSoundInfo.allocChannelCount;
408 return true;
409 }
410
ReadWaveSoundInfo(SoundArchive::ItemId soundId,SoundArchive::WaveSoundInfo * info) const411 bool SoundArchiveFileReader::ReadWaveSoundInfo(
412 SoundArchive::ItemId soundId, SoundArchive::WaveSoundInfo* info ) const
413 {
414 NW_NULL_ASSERT( m_pInfoBlockBody );
415 NW_NULL_ASSERT( info );
416
417 const SoundArchiveFile::SoundInfo* soundInfo = m_pInfoBlockBody->GetSoundInfo( soundId );
418 if ( soundInfo == NULL )
419 {
420 return false;
421 }
422 if ( soundInfo->GetSoundType() != SoundArchive::SOUND_TYPE_WAVE )
423 {
424 return false;
425 }
426
427 const SoundArchiveFile::WaveSoundInfo& waveSoundInfo = soundInfo->GetWaveSoundInfo();
428 info->index = waveSoundInfo.index;
429 info->allocTrackCount = waveSoundInfo.allocTrackCount;
430 info->channelPriority = waveSoundInfo.GetChannelPriority();
431 info->isReleasePriorityFix = waveSoundInfo.GetIsReleasePriorityFix() > 0 ? true : false;
432
433 return true;
434 }
435
436 const internal::Util::Table<u32>*
GetWaveArchiveIdTable(SoundArchive::ItemId id) const437 SoundArchiveFileReader::GetWaveArchiveIdTable( SoundArchive::ItemId id ) const
438 {
439 NW_NULL_ASSERT( m_pInfoBlockBody );
440
441 switch ( Util::GetItemType( id ) )
442 {
443 case ItemType_Sound:
444 {
445 const SoundArchiveFile::SoundInfo* pInfo =
446 m_pInfoBlockBody->GetSoundInfo( id );
447 NW_NULL_ASSERT( pInfo );
448
449 if ( pInfo->GetSoundType() == SoundArchive::SOUND_TYPE_WAVE )
450 {
451 // ウェーブサウンド ID → ウェーブサウンドセット ID を引く
452 for ( u32 i = 0; i < m_pInfoBlockBody->GetSoundGroupCount(); i++ )
453 {
454 const SoundArchiveFile::SoundGroupInfo* pGroupInfo =
455 m_pInfoBlockBody->GetSoundGroupInfo(
456 Util::GetMaskedItemId( i, ItemType_SoundGroup ) );
457 NW_NULL_ASSERT( pGroupInfo );
458
459 if ( id < pGroupInfo->startId || pGroupInfo->endId < id )
460 {
461 continue;
462 }
463
464 // 該当するウェーブサウンドセットの波形アーカイブテーブルを返す
465 const SoundArchiveFile::WaveSoundGroupInfo*
466 pWaveSoundGroupInfo = pGroupInfo->GetWaveSoundGroupInfo();
467 NW_NULL_ASSERT( pWaveSoundGroupInfo );
468
469 return pWaveSoundGroupInfo->GetWaveArchiveItemIdTable();
470 }
471 }
472 return NULL;
473 }
474 case ItemType_SoundGroup:
475 {
476 const SoundArchiveFile::SoundGroupInfo* pInfo =
477 m_pInfoBlockBody->GetSoundGroupInfo( id );
478 NW_NULL_ASSERT( pInfo );
479
480 const SoundArchiveFile::WaveSoundGroupInfo*
481 pWaveSoundGroupInfo = pInfo->GetWaveSoundGroupInfo();
482 NW_NULL_ASSERT( pWaveSoundGroupInfo );
483
484 return pWaveSoundGroupInfo->GetWaveArchiveItemIdTable();
485 }
486 case ItemType_Bank:
487 {
488 const SoundArchiveFile::BankInfo* pInfo =
489 m_pInfoBlockBody->GetBankInfo( id );
490 NW_NULL_ASSERT( pInfo );
491
492 return pInfo->GetWaveArchiveItemIdTable();
493 }
494 default:
495 return NULL;
496 }
497 }
498
499 SoundArchive::SoundType
GetSoundType(SoundArchive::ItemId soundId) const500 SoundArchiveFileReader::GetSoundType( SoundArchive::ItemId soundId ) const
501 {
502 NW_NULL_ASSERT( m_pInfoBlockBody );
503
504 const SoundArchiveFile::SoundInfo* soundInfo = m_pInfoBlockBody->GetSoundInfo( soundId );
505 NW_NULL_ASSERT( soundInfo );
506 return soundInfo->GetSoundType();
507 }
508
509 u32
GetSoundUserParam(SoundArchive::ItemId soundId) const510 SoundArchiveFileReader::GetSoundUserParam( SoundArchive::ItemId soundId ) const
511 {
512 NW_NULL_ASSERT( m_pInfoBlockBody );
513
514 const SoundArchiveFile::SoundInfo* soundInfo = m_pInfoBlockBody->GetSoundInfo( soundId );
515 NW_NULL_ASSERT( soundInfo );
516 return soundInfo->GetUserParam();
517 }
518
519
520 } // namespace nw::snd::internal
521 } // namespace nw::snd
522 } // namespace nw
523