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