1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     snd_SoundArchive.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: 13420 $
14  *---------------------------------------------------------------------------*/
15 
16 #include "precompiled.h"
17 
18 #include <nw/snd/snd_SoundArchive.h>
19 
20 #include <cstring>      // strlen, etc...
21 #include <nw/assert.h>
22 #include <nw/io/io_FileStream.h>
23 #include <nw/snd/snd_SoundArchiveFileReader.h>
24 
25 namespace nw {
26 namespace snd {
27 
28 /* ========================================================================
29         static variables
30    ======================================================================== */
31 
32 namespace {
33 const char sNullString = '\0';
34 } // namespace
35 
36 /*---------------------------------------------------------------------------*
37   Name:         SoundArchive
38 
39   Description:  コンストラクタ
40 
41   Arguments:    None.
42 
43   Returns:      None.
44  *---------------------------------------------------------------------------*/
SoundArchive()45 SoundArchive::SoundArchive()
46 : m_pFileReader( NULL )
47 {
48     m_ExtFileRoot[0] = '/';
49     m_ExtFileRoot[1] = '\0';
50 }
51 
52 /*---------------------------------------------------------------------------*
53   Name:         ~SoundArchive
54 
55   Description:  デストラクタ
56 
57   Arguments:    None.
58 
59   Returns:      None.
60  *---------------------------------------------------------------------------*/
~SoundArchive()61 SoundArchive::~SoundArchive()
62 {
63 }
64 
IsAvailable() const65 bool SoundArchive::IsAvailable() const
66 {
67     if ( m_pFileReader == NULL ) return false;
68     return true;
69 }
70 
Initialize(internal::SoundArchiveFileReader * fileReader)71 void SoundArchive::Initialize( internal::SoundArchiveFileReader* fileReader )
72 {
73     NW_NULL_ASSERT( fileReader );
74     m_pFileReader = fileReader;
75     m_FileBlockOffset = m_pFileReader->GetFileBlockOffset();
76 }
77 
78 /*---------------------------------------------------------------------------*
79   Name:         Shutdown
80 
81   Description:  シャットダウン
82 
83   Arguments:    None.
84 
85   Returns:      None.
86  *---------------------------------------------------------------------------*/
Finalize()87 void SoundArchive::Finalize()
88 {
89     m_pFileReader = NULL;
90     m_ExtFileRoot[0] = '/';
91     m_ExtFileRoot[1] = '\0';
92 }
93 
GetSoundCount() const94 u32 SoundArchive::GetSoundCount() const
95 {
96     return m_pFileReader->GetSoundCount();
97 }
GetPlayerCount() const98 u32 SoundArchive::GetPlayerCount() const
99 {
100     return m_pFileReader->GetPlayerCount();
101 }
GetSoundGroupCount() const102 u32 SoundArchive::GetSoundGroupCount() const
103 {
104     return m_pFileReader->GetSoundGroupCount();
105 }
GetGroupCount() const106 u32 SoundArchive::GetGroupCount() const
107 {
108     return m_pFileReader->GetGroupCount();
109 }
GetBankCount() const110 u32 SoundArchive::GetBankCount() const
111 {
112     return m_pFileReader->GetBankCount();
113 }
GetWaveArchiveCount() const114 u32 SoundArchive::GetWaveArchiveCount() const
115 {
116     return m_pFileReader->GetWaveArchiveCount();
117 }
detail_GetFileCount() const118 u32 SoundArchive::detail_GetFileCount() const
119 {
120     return m_pFileReader->GetFileCount();
121 }
122 
GetItemLabel(ItemId id) const123 const char* SoundArchive::GetItemLabel( ItemId id ) const
124 {
125     return m_pFileReader->GetItemLabel( id );
126 }
GetItemId(const char * pStr) const127 SoundArchive::ItemId SoundArchive::GetItemId( const char* pStr ) const
128 {
129     return m_pFileReader->GetItemId( pStr );
130 }
GetItemFileId(ItemId id) const131 SoundArchive::FileId SoundArchive::GetItemFileId( ItemId id ) const
132 {
133     return m_pFileReader->GetItemFileId( id );
134 }
135 
GetSoundUserParam(ItemId soundId) const136 u32 SoundArchive::GetSoundUserParam( ItemId soundId ) const
137 {
138     return m_pFileReader->GetSoundUserParam( soundId );
139 }
140 
GetSoundType(ItemId soundId) const141 SoundArchive::SoundType SoundArchive::GetSoundType( ItemId soundId ) const
142 {
143     return m_pFileReader->GetSoundType( soundId );
144 }
ReadSoundInfo(ItemId soundId,SoundInfo * info) const145 bool SoundArchive::ReadSoundInfo( ItemId soundId, SoundInfo* info ) const
146 {
147     return m_pFileReader->ReadSoundInfo( soundId, info );
148 }
ReadSequenceSoundInfo(ItemId soundId,SequenceSoundInfo * info) const149 bool SoundArchive::ReadSequenceSoundInfo( ItemId soundId, SequenceSoundInfo* info ) const
150 {
151     return m_pFileReader->ReadSequenceSoundInfo( soundId, info );
152 }
detail_ReadStreamSoundInfo(ItemId soundId,StreamSoundInfo * info) const153 bool SoundArchive::detail_ReadStreamSoundInfo( ItemId soundId, StreamSoundInfo* info ) const
154 {
155     return m_pFileReader->ReadStreamSoundInfo( soundId, info );
156 }
detail_ReadWaveSoundInfo(ItemId soundId,WaveSoundInfo * info) const157 bool SoundArchive::detail_ReadWaveSoundInfo( ItemId soundId, WaveSoundInfo* info ) const
158 {
159     return m_pFileReader->ReadWaveSoundInfo( soundId, info );
160 }
ReadPlayerInfo(ItemId playerId,PlayerInfo * info) const161 bool SoundArchive::ReadPlayerInfo( ItemId playerId, PlayerInfo* info ) const
162 {
163     return m_pFileReader->ReadPlayerInfo( playerId, info );
164 }
ReadSoundArchivePlayerInfo(SoundArchivePlayerInfo * info) const165 bool SoundArchive::ReadSoundArchivePlayerInfo( SoundArchivePlayerInfo* info ) const
166 {
167     return m_pFileReader->ReadSoundArchivePlayerInfo( info );
168 }
ReadSound3DInfo(ItemId soundId,Sound3DInfo * info) const169 bool SoundArchive::ReadSound3DInfo( ItemId soundId, Sound3DInfo* info ) const
170 {
171     return m_pFileReader->ReadSound3DInfo( soundId, info );
172 }
ReadBankInfo(ItemId bankId,BankInfo * info) const173 bool SoundArchive::ReadBankInfo( ItemId bankId, BankInfo* info ) const
174 {
175     return m_pFileReader->ReadBankInfo( bankId, info );
176 }
ReadWaveArchiveInfo(ItemId warcId,WaveArchiveInfo * info) const177 bool SoundArchive::ReadWaveArchiveInfo( ItemId warcId, WaveArchiveInfo* info ) const
178 {
179     return m_pFileReader->ReadWaveArchiveInfo( warcId, info );
180 }
detail_ReadSoundGroupInfo(ItemId soundGroupId,SoundGroupInfo * info) const181 bool SoundArchive::detail_ReadSoundGroupInfo( ItemId soundGroupId, SoundGroupInfo* info ) const
182 {
183     return m_pFileReader->ReadSoundGroupInfo( soundGroupId, info );
184 }
detail_ReadGroupInfo(ItemId groupId,GroupInfo * info) const185 bool SoundArchive::detail_ReadGroupInfo( ItemId groupId, GroupInfo* info ) const
186 {
187     return m_pFileReader->ReadGroupInfo( groupId, info );
188 }
189 #if 0
190 bool SoundArchive::detail_ReadGroupItemInfo( GroupId groupId, unsigned long index, GroupItemInfo* info ) const
191 {
192     return m_pFileReader->ReadGroupItemInfo( groupId, index, info );
193 }
194 #endif
detail_ReadFileInfo(FileId fileId,FileInfo * info) const195 bool SoundArchive::detail_ReadFileInfo( FileId fileId, FileInfo* info ) const
196 {
197     return m_pFileReader->ReadFileInfo( fileId, info );
198 }
199 #if 0
200 bool SoundArchive::detail_ReadFilePos( FileId fileId, unsigned long index, FilePos* info ) const
201 {
202     return m_pFileReader->ReadFilePos( fileId, index, info );
203 }
204 #endif
205 
206 const internal::Util::Table<u32>*
detail_GetWaveArchiveIdTable(ItemId id) const207 SoundArchive::detail_GetWaveArchiveIdTable( ItemId id ) const
208 {
209     // id にはウェーブサウンドの ID か、バンクの ID しか入らない
210     return m_pFileReader->GetWaveArchiveIdTable( id );
211 }
212 
detail_OpenFileStream(FileId fileId,void * buffer,int size)213 io::FileStream* SoundArchive::detail_OpenFileStream(
214         FileId fileId, void* buffer, int size )
215 {
216     // ファイル情報取得
217     FileInfo fileInfo;
218     if ( ! detail_ReadFileInfo( fileId, &fileInfo ) )
219     {
220         return NULL;
221     }
222 
223     // 外部参照ファイル
224     if ( fileInfo.externalFilePath != NULL )
225     {
226         io::FileStream* stream =
227             OpenExtStreamImpl( buffer, size, fileInfo.externalFilePath, 0, 0 );
228         return stream;
229     }
230 
231     // サウンドアーカイブ内ファイル
232     io::FileStream* stream = OpenStream(
233         buffer,
234         size,
235         fileInfo.offsetFromFileBlockHead + m_FileBlockOffset,
236         fileInfo.fileSize
237     );
238     return stream;
239 }
240 
241 #if 0
242 io::FileStream* SoundArchive::detail_OpenFileWaveDataStream( FileId fileId, void* buffer, int size ) const
243 {
244     // ファイル情報取得
245     FileInfo fileInfo;
246     if ( ! detail_ReadFileInfo( fileId, &fileInfo ) )
247     {
248         return NULL;
249     }
250 
251     // ファイル位置情報取得
252     FilePos filePos;
253     if ( ! detail_ReadFilePos( fileId, 0, &filePos ) )
254     {
255         return NULL;
256     }
257 
258     // グループ情報取得
259     GroupInfo groupInfo;
260     if ( ! detail_ReadGroupInfo( filePos.groupId, &groupInfo ) )
261     {
262         return NULL;
263     }
264     GroupItemInfo itemInfo;
265     if ( ! detail_ReadGroupItemInfo( filePos.groupId, filePos.index, &itemInfo ) )
266     {
267         return NULL;
268     }
269 
270     const u32 itemOffset = groupInfo.waveDataOffset + itemInfo.waveDataOffset;
271     const u32 itemSize = itemInfo.waveDataSize;
272 
273     if ( groupInfo.externalFilePath != NULL )
274     {
275         // 外部参照グループ
276         io::FileStream* stream = OpenExtStreamImpl( buffer, size, groupInfo.externalFilePath, itemOffset, itemSize );
277         return stream;
278     }
279 
280     io::FileStream* stream = OpenStream( buffer, size, itemOffset, itemSize );
281     return stream;
282 }
283 
284 io::FileStream* SoundArchive::detail_OpenGroupStream( GroupId groupId, void* buffer, int size ) const
285 {
286     GroupInfo groupInfo;
287     if ( ! detail_ReadGroupInfo( groupId, &groupInfo ) ) return NULL;
288 
289     if ( groupInfo.externalFilePath != NULL )
290     {
291         io::FileStream* stream = OpenExtStreamImpl( buffer, size, groupInfo.externalFilePath, groupInfo.offset, groupInfo.size );
292         return stream;
293     }
294 
295     io::FileStream* stream = OpenStream( buffer, size, groupInfo.offset, groupInfo.size );
296     return stream;
297 }
298 
299 io::FileStream* SoundArchive::detail_OpenGroupWaveDataStream( GroupId groupId, void* buffer, int size ) const
300 {
301     GroupInfo groupInfo;
302     if ( ! detail_ReadGroupInfo( groupId, &groupInfo ) ) return NULL;
303 
304     if ( groupInfo.externalFilePath != NULL )
305     {
306         io::FileStream* stream = OpenExtStreamImpl( buffer, size, groupInfo.externalFilePath, groupInfo.waveDataOffset, groupInfo.waveDataSize );
307         return stream;
308     }
309 
310     io::FileStream* stream = OpenStream( buffer, size, groupInfo.waveDataOffset, groupInfo.waveDataSize );
311     return stream;
312 }
313 #endif
314 
OpenExtStreamImpl(void * buffer,int size,const char * externalFilePath,u32 begin,u32 length) const315 io::FileStream* SoundArchive::OpenExtStreamImpl(
316     void* buffer,
317     int size,
318     const char* externalFilePath,
319     // const wchar_t* externalFilePath,
320     u32 begin,
321     u32 length
322 ) const
323 {
324     const char* fullPath;
325     char pathBuffer[ FILE_PATH_MAX ];
326 
327     if ( externalFilePath[0] == '/' )
328     {
329         fullPath = externalFilePath;
330     }
331     else
332     {
333         std::size_t fileLen = std::strlen( externalFilePath );
334         std::size_t dirLen = std::strlen( m_ExtFileRoot );
335         if ( fileLen + dirLen >= sizeof( pathBuffer ) / sizeof( pathBuffer[0] ) )
336         {
337             NW_WARNING( false, "Too long file path \"%s/%s\"",
338                     m_ExtFileRoot, externalFilePath );
339             return NULL;
340         }
341         ut::strncpy( pathBuffer, FILE_PATH_MAX, m_ExtFileRoot, dirLen+1 );
342         ut::strncat( pathBuffer, FILE_PATH_MAX, externalFilePath, fileLen+1 );
343         fullPath = pathBuffer;
344     }
345 
346     return OpenExtStream( buffer, size, fullPath, begin, length );
347 }
348 
SetExternalFileRoot(const char * extFileRoot)349 void SoundArchive::SetExternalFileRoot( const char* extFileRoot )
350 {
351     std::size_t len = std::strlen( extFileRoot );
352     std::size_t nullPos = len;
353 
354     ut::strncpy( m_ExtFileRoot, FILE_PATH_MAX, extFileRoot, len );
355 
356     if ( extFileRoot[ len-1 ] != '/' )
357     {
358         m_ExtFileRoot[ len ] = '/';
359         nullPos++;
360     }
361 
362     NW_ASSERT( nullPos < FILE_PATH_MAX );
363     m_ExtFileRoot[ nullPos ] = '\0';
364 }
365 
366 
367 } // namespace nw::snd
368 } // namespace nw
369 
370