1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     snd_SoundDataManager.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_SoundDataManager.h>
19 
20 #include <nw/snd/snd_DisposeCallbackManager.h>
21 #include <nw/snd/snd_DriverCommand.h>
22 #include <nw/snd/snd_SoundArchiveLoader.h>
23 #include <nw/snd/snd_GroupFileReader.h>
24 #include <nw/snd/snd_WaveArchiveFile.h>
25 #include <nw/snd/snd_Util.h>
26 #include <nn/os.h>
27 
28 namespace nw {
29 namespace snd {
30 
31 
SoundDataManager()32 SoundDataManager::SoundDataManager()
33 : m_pFileTable ( NULL ),
34   m_pFileManager( NULL )
35 {
36 }
37 
~SoundDataManager()38 SoundDataManager::~SoundDataManager()
39 {
40 }
41 
GetRequiredMemSize(const SoundArchive * arc) const42 size_t SoundDataManager::GetRequiredMemSize( const SoundArchive* arc ) const
43 {
44     NW_NULL_ASSERT( arc );
45     size_t size = 0;
46 
47     size += ut::RoundUp(
48             sizeof( u32 ) +
49             sizeof( FileAddress ) * arc->detail_GetFileCount(), 4 );
50     return size;
51 }
52 
Initialize(const SoundArchive * arc,void * buffer,u32 size)53 bool SoundDataManager::Initialize( const SoundArchive* arc, void* buffer, u32 size )
54 {
55     NW_NULL_ASSERT( arc );
56     NW_NULL_ASSERT( buffer );
57     NW_ALIGN4_ASSERT( buffer );
58     NW_ASSERT( size >= GetRequiredMemSize( arc ) );
59 
60     void* endp = static_cast<char*>(buffer) + size;
61     void* buf = buffer;
62 
63     if ( ! CreateFileAddressTable( arc, &buf, endp ) )
64     {
65         return false;
66     }
67 
68     NW_ASSERT( static_cast<char*>(buf) - static_cast<char*>(buffer) == GetRequiredMemSize( arc ) );
69     SetSoundArchive( arc );
70 
71     internal::DriverCommandManager& cmdmgr = internal::DriverCommandManager::GetInstance();
72 
73     internal::DriverCommandDisposeCallback* command =
74         cmdmgr.AllocCommand<internal::DriverCommandDisposeCallback>();
75     command->id = internal::DRIVER_COMMAND_REGIST_DISPOSE_CALLBACK;
76     command->callback = this;
77     cmdmgr.PushCommand(command);
78 
79     return true;
80 }
81 
Finalize()82 void SoundDataManager::Finalize()
83 {
84     internal::DriverCommandManager& cmdmgr = internal::DriverCommandManager::GetInstance();
85 
86     internal::DriverCommandDisposeCallback* command =
87         cmdmgr.AllocCommand<internal::DriverCommandDisposeCallback>();
88     command->id = internal::DRIVER_COMMAND_UNREGIST_DISPOSE_CALLBACK;
89     command->callback = this;
90     cmdmgr.PushCommand(command);
91     u32 tag = cmdmgr.FlushCommand( true );
92     cmdmgr.WaitCommandReply( tag );
93 
94     m_pFileManager = NULL;
95     m_pFileTable = NULL;
96 }
97 
CreateFileAddressTable(const SoundArchive * arc,void ** buffer,void * endp)98 bool SoundDataManager::CreateFileAddressTable(
99     const SoundArchive* arc,
100     void** buffer,
101     void* endp
102 )
103 {
104     size_t requiredSize =
105         sizeof( u32 ) +
106         sizeof( FileAddress ) * arc->detail_GetFileCount();
107 
108     void* ep = ut::RoundUp( ut::AddOffsetToPtr( *buffer, requiredSize ), 4 );
109     if ( ut::ComparePtr( ep, endp ) > 0 )
110     {
111         return false;
112     }
113     m_pFileTable = reinterpret_cast< FileTable* >(*buffer);
114     *buffer = ep;
115 
116 
117     m_pFileTable->count = arc->detail_GetFileCount();
118     for( u32 i = 0 ; i < m_pFileTable->count ; i++ )
119     {
120         m_pFileTable->item[ i ].address = NULL;
121     }
122 
123     return true;
124 }
125 
126 
127 /*---------------------------------------------------------------------------*
128   Name:         InvalidateData
129 
130   Description:  ロードされたデータが破棄されたときにテーブルから削除する
131 
132   Arguments:    start - 開始アドレス
133                 end   - 終了アドレス
134 
135   Returns:      None.
136  *---------------------------------------------------------------------------*/
InvalidateData(const void * start,const void * end)137 void SoundDataManager::InvalidateData( const void* start, const void* end )
138 {
139     // ファイルアドレステーブルから破棄
140     if ( m_pFileTable != NULL )
141     {
142         for( u32 i = 0 ; i < m_pFileTable->count ; i++ )
143         {
144             const void* addr = m_pFileTable->item[ i ].address;
145             if ( start <= addr && addr <= end )
146             {
147                 m_pFileTable->item[ i ].address = NULL;
148             }
149         }
150     }
151 
152     if ( ut::GetOffsetFromPtr( start, end ) >= sizeof(IndividualWaveInfo) )
153     {
154         if ( start != NULL )
155         {
156             const IndividualWaveInfo* info =
157                 reinterpret_cast<const IndividualWaveInfo*>( start );
158             if ( info->signature == SoundDataManager::SIGNATURE_INDIVIDUAL_WAVE )
159             {
160                 const void* pWarcTable = GetFileAddressFromTable( info->fileId );
161                 if ( pWarcTable != NULL )
162                 {
163                     internal::WaveArchiveFileReader reader( pWarcTable, true );
164                     reader.SetWaveFile( info->waveIndex, NULL );
165                 }
166             }
167         }
168     }
169 }
170 
171 /*---------------------------------------------------------------------------*
172   Name:         detail_GetFileAddress
173 
174   Description:  記憶させたファイルアドレスを取得
175 
176   Arguments:    fileId - ファイルID
177 
178   Returns:      ファイルアドレス
179  *---------------------------------------------------------------------------*/
detail_GetFileAddress(SoundArchive::FileId fileId) const180 const void* SoundDataManager::detail_GetFileAddress( SoundArchive::FileId fileId ) const
181 {
182     return GetFileAddressImpl( fileId );
183 }
184 
GetFileAddressImpl(SoundArchive::FileId fileId) const185 const void* SoundDataManager::GetFileAddressImpl( SoundArchive::FileId fileId ) const
186 {
187     // 外部のファイルマネージャに問い合わせ
188     if ( m_pFileManager != NULL )
189     {
190         const void* addr = m_pFileManager->GetFileAddress( fileId );
191         if ( addr != NULL ) return addr;
192     }
193 
194     // サウンドアーカイブに問い合わせ
195     {
196         const void* addr = GetFileAddressFromSoundArchive( fileId );
197         if ( addr != NULL ) return addr;
198     }
199 
200     // ファイルアドレステーブルを参照
201     {
202         const void* fileData = GetFileAddressFromTable( fileId );
203         if ( fileData != NULL ) return fileData;
204     }
205     return NULL;
206 }
207 
SetFileAddressToTable(SoundArchive::FileId fileId,const void * address)208 const void* SoundDataManager::SetFileAddressToTable(
209         SoundArchive::FileId fileId,
210         const void* address )
211 {
212     if ( m_pFileTable == NULL )
213     {
214         NW_WARNING(
215             m_pFileTable != NULL,
216             "Failed to SoundDataManager::SetFileAddress because file table is not allocated.\n"
217         );
218         return NULL;
219     }
220 
221     NW_MINMAXLT_ASSERT( fileId, 0, m_pFileTable->count );
222 
223     const void* preAddress = m_pFileTable->item[ fileId ].address;
224     m_pFileTable->item[ fileId ].address = address;
225     return preAddress;
226 }
227 
228 
229 /*---------------------------------------------------------------------------*
230   Name:         GetFileAddressFromTable
231 
232   Description:  記憶させたファイルアドレスを取得
233 
234   Arguments:    fileId - ファイルID
235 
236   Returns:      ファイルアドレス
237  *---------------------------------------------------------------------------*/
GetFileAddressFromTable(SoundArchive::FileId fileId) const238 const void* SoundDataManager::GetFileAddressFromTable( SoundArchive::FileId fileId ) const
239 {
240     if ( m_pFileTable == NULL )
241     {
242         NW_WARNING(
243             m_pFileTable != NULL,
244             "Failed to SoundDataManager::GetFileAddress because file table is not allocated.\n"
245         );
246         return NULL;
247     }
248 
249     if ( fileId >= m_pFileTable->count ) return NULL;
250 
251     return m_pFileTable->item[ fileId ].address;
252 }
253 
254 /*---------------------------------------------------------------------------*
255   Name:         SetFileAddress
256 
257   Description:  ファイルアドレスを記憶
258 
259   Arguments:    fileId - ファイル番号
260                 address - ファイルアドレス
261 
262   Returns:      セットする前に書かれていたファイルアドレス
263  *---------------------------------------------------------------------------*/
264 const void*
SetFileAddress(SoundArchive::FileId fileId,const void * address)265 SoundDataManager::SetFileAddress( SoundArchive::FileId fileId, const void* address )
266 {
267     return SetFileAddressToTable( fileId, address );
268 }
269 
270 // ロード済みファイルテーブルの中から、
271 // 引数と一致するアドレスを持つファイルのファイル ID を取得する
detail_GetFileIdFromTable(const void * address) const272 u32 SoundDataManager::detail_GetFileIdFromTable( const void* address ) const
273 {
274     for ( u32 i = 0; i < m_pFileTable->count; i++ )
275     {
276         if ( address == m_pFileTable->item[i].address )
277         {
278             return i;
279         }
280     }
281     return SoundArchive::INVALID_ID;
282 }
283 
284 #if 0
285 void SoundDataManager::InvalidateSoundData( void* mem, size_t size )
286 {
287     internal::DriverCommandManager& cmdmgr = internal::DriverCommandManager::GetInstance();
288 
289     internal::DriverCommandInvalidateData* command =
290         cmdmgr.AllocCommand<internal::DriverCommandInvalidateData>();
291     command->id = internal::DRIVER_COMMAND_INVALIDATE_DATA;
292     command->mem = mem;
293     command->size = size;
294     cmdmgr.PushCommand(command);
295     u32 tag = cmdmgr.FlushCommand( true );
296     cmdmgr.WaitCommandReply( tag );
297 }
298 #endif
299 
300 
301 } // namespace nw::snd
302 } // namespace nw
303 
304