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