1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     snd_RomSoundArchive.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: 24309 $
14  *---------------------------------------------------------------------------*/
15 
16 #include "precompiled.h"
17 
18 #include <nw/snd/snd_RomSoundArchive.h>
19 #include <nw/snd/snd_Util.h>
20 
21 // #define NW_SND_DEBUG_PRINT_ENABLE
22 
23 namespace nw {
24 namespace snd {
25 
26 /*---------------------------------------------------------------------------*
27   Name:         RomSoundArchive
28 
29   Description:  コンストラクタ
30 
31   Arguments:    None.
32 
33   Returns:      None.
34  *---------------------------------------------------------------------------*/
RomSoundArchive()35 RomSoundArchive::RomSoundArchive()
36 : m_IsOpened( false )
37 {
38 }
39 
40 /*---------------------------------------------------------------------------*
41   Name:         ~RomSoundArchive
42 
43   Description:  デストラクタ
44 
45   Arguments:    None.
46 
47   Returns:      None.
48  *---------------------------------------------------------------------------*/
~RomSoundArchive()49 RomSoundArchive::~RomSoundArchive()
50 {
51     Close();
52 }
53 
Open(const char * path)54 bool RomSoundArchive::Open( const char* path )
55 {
56 #ifdef NW_PLATFORM_CTRWIN
57     // for PC_SDK
58     {
59         bool result = nn::fs::OpenFile( &m_FileInfo, path );
60         if ( result == false )
61         {
62             NW_WARNING( false, "Cannot open file(%s)\n", path );
63             return false;
64         }
65         m_IsOpened = true;
66     }
67 #else
68     // for CTR_SDK
69     {
70         m_FileReader.Initialize( path );
71         m_IsOpened = true;
72     }
73 #endif
74 
75     {
76         bool result = LoadFileHeader();
77         if ( result == false )
78         {
79             NW_WARNING( false, "Cannot load header\n" );
80             return false;
81         }
82     }
83 
84     std::size_t len = std::strlen( path );
85     for ( int i = static_cast<int>( len ) - 1; i >= 0; i-- )
86     {
87         const char ch = path[ i ] ;
88         if ( ch == '/' || ch == '\\' )
89         {
90             char dirBuffer[ FILE_PATH_MAX ];
91             NW_ASSERT( i < FILE_PATH_MAX );
92             if ( i >= FILE_PATH_MAX )
93             {
94                 return false;
95             }
96 
97             ut::strncpy( dirBuffer, FILE_PATH_MAX, path, static_cast<u32>( i ) );
98             dirBuffer[ i ] = '\0';
99 
100             SetExternalFileRoot( dirBuffer );
101             break;
102         }
103     }
104 
105     return true;
106 }
107 #if 0
108 bool RomSoundArchive::Open( const wchar_t* path )
109 {
110     {
111         m_FileReader.Initialize( path );
112         m_IsOpened = true;
113     }
114 
115     {
116         bool result = LoadFileHeader();
117         if ( result == false )
118         {
119             NW_WARNING( false, "Cannot load header\n" );
120             return false;
121         }
122     }
123 
124     return true;
125 }
126 #endif
127 
128 /*---------------------------------------------------------------------------*
129   Name:         Close
130 
131   Description:  サウンドアーカイブを閉じる
132 
133   Arguments:    None.
134 
135   Returns:      None.
136  *---------------------------------------------------------------------------*/
Close()137 void RomSoundArchive::Close()
138 {
139     if ( m_IsOpened )
140     {
141 #ifdef NW_PLATFORM_CTRWIN
142         nn::fs::CloseFile( &m_FileInfo );
143 #else
144         m_FileReader.Finalize();
145 #endif
146         m_ArchiveReader.Finalize();
147         m_IsOpened = false;
148     }
149 
150     Finalize();
151 }
152 
153 io::FileStream*
OpenStream(void * buffer,int size,u32 begin,u32 length)154 RomSoundArchive::OpenStream( void* buffer, int size, u32 begin, u32 length )
155 {
156 #ifdef NW_PLATFORM_CTRWIN
157     if ( ! m_IsOpened ) return NULL;
158     if ( size < sizeof( RomFileStream ) ) return NULL;
159     RomFileStream* stream = new( buffer ) RomFileStream( &m_FileInfo, begin, length );
160     return stream;
161 #else
162     if ( ! m_IsOpened ) return NULL;
163     if ( size < sizeof( RomFileStream ) ) return NULL;
164     RomFileStream* stream = new( buffer ) RomFileStream( &m_FileReader, begin, length );
165     return stream;
166 #endif
167 }
168 
169 io::FileStream*
OpenExtStream(void * buffer,int size,const char * extFilePath,u32 begin,u32 length) const170 RomSoundArchive::OpenExtStream(
171         void* buffer,
172         int size,
173         const char* extFilePath,
174         // const wchar_t* extFilePath,
175         u32 begin,
176         u32 length ) const
177 {
178     if ( ! m_IsOpened ) return NULL;
179     if ( size < sizeof( RomFileStream ) ) return NULL;
180 
181     RomFileStream* stream = new( buffer ) RomFileStream( extFilePath, begin, length );
182     return stream;
183 }
184 
detail_GetRequiredStreamBufferSize() const185 size_t RomSoundArchive::detail_GetRequiredStreamBufferSize() const
186 {
187     return sizeof( RomFileStream );
188 }
189 
190 /*---------------------------------------------------------------------------*
191   Name:         LoadFileHeader
192 
193   Description:  サウンドアーカイブファイルのヘッダをロードする
194 
195   Arguments:    None.
196 
197   Returns:      成功したら true 失敗したら false
198  *---------------------------------------------------------------------------*/
LoadFileHeader()199 bool RomSoundArchive::LoadFileHeader()
200 {
201     NW_ASSERT( m_IsOpened );
202 
203     const unsigned long headerAlignSize = static_cast<unsigned long>(
204         ut::RoundUp( sizeof(internal::SoundArchiveFile::FileHeader), 32 )
205     );
206     u8 headerArea[ sizeof(internal::SoundArchiveFile::FileHeader) + 32*2 ]; // 前後32バイトずつの余裕を持つ
207     void* file = ut::RoundUp( headerArea, 32 );
208 
209 #ifdef NW_PLATFORM_CTRWIN
210     s32 readSize = nn::fs::ReadFile( &m_FileInfo, file, static_cast<s32>(headerAlignSize) );
211 #else
212     s32 readSize = m_FileReader.Read( file, static_cast<s32>(headerAlignSize) );
213 #endif
214     if ( readSize != headerAlignSize )
215     {
216         NW_WARNING(
217             false,
218             "RomSoundArchive::LoadFileHeader cannot read file.\n"
219         );
220         return false;
221     }
222 
223     m_ArchiveReader.Initialize( file );
224     Initialize( &m_ArchiveReader );
225 
226     return true;
227 }
228 
229 /*---------------------------------------------------------------------------*
230   Name:         LoadHeader
231 
232   Description:  サウンドデータの情報テーブルをロードする
233 
234   Arguments:    buffer - ロードアドレス
235                 size - バッファサイズ
236 
237   Returns:      成功したら true 失敗したら false
238  *---------------------------------------------------------------------------*/
LoadHeader(void * buffer,unsigned long size)239 bool RomSoundArchive::LoadHeader( void* buffer, unsigned long size )
240 {
241     NW_ASSERT( m_IsOpened );
242 
243     const s32 infoChunkOffset = m_ArchiveReader.GetInfoBlockOffset();
244     const u32 infoChunkSize = m_ArchiveReader.GetInfoBlockSize();
245 
246     if ( size < infoChunkSize )
247     {
248         NW_WARNING(
249             size >= infoChunkSize,
250             "RomSoundArchive::LoadHeader buffer size is too small.\n"
251         );
252         return false;
253     }
254 
255     //-----------------------------------------------------------------------------
256     // 情報テーブルのロード
257 #ifdef NW_PLATFORM_CTRWIN
258     nn::fs::SeekFile( &m_FileInfo, infoChunkOffset, nn::fs::FS_SEEK_SET );
259     s32 readSize = nn::fs::ReadFile(
260         &m_FileInfo,
261         buffer,
262         static_cast<s32>(infoChunkSize)
263     );
264 #else
265     m_FileReader.Seek( infoChunkOffset, nn::fs::POSITION_BASE_BEGIN );
266     s32 readSize = m_FileReader.Read( buffer, static_cast<s32>(infoChunkSize) );
267 #endif
268     if ( readSize != infoChunkSize )
269     {
270         NW_WARNING(
271             false,
272             "RomSoundArchive::LoadHeader cannot read file.\n"
273         );
274         return false;
275     }
276 
277     m_ArchiveReader.SetInfoBlock( buffer /*, infoChunkSize */ );
278 
279 #ifdef NW_SND_DEBUG_PRINT_ENABLE
280     // デバッグ出力
281     {
282         // サウンド情報
283         NN_LOG("### Sound INFO(%d)\n", m_ArchiveReader.GetSoundCount() );
284         for ( u32 i = 0; i < m_ArchiveReader.GetSoundCount(); i++ )
285         {
286             // サウンド共通情報
287             SoundArchive::ItemId soundId = GetSoundIdFromIndex( i );
288             SoundArchive::SoundType type = m_ArchiveReader.GetSoundType( soundId );
289             SoundArchive::SoundInfo info;
290             bool ret = m_ArchiveReader.ReadSoundInfo( soundId, &info );
291             NN_LOG("[%08X]?(%d) fileId(%d) playerId(0x%08X) actorId(%d) type(%d)\n",
292                     soundId, ret, info.fileId, info.playerId, info.actorPlayerId, type );
293             NN_LOG("  *common* volume(%d) panMode(%d) panCurve (%d)\n",
294                     info.volume, info.panMode, info.panCurve );
295 
296             // 3D サウンド情報
297             {
298                 SoundArchive::Sound3DInfo info3d;
299                 if ( ReadSound3DInfo( soundId, &info3d ) )
300                 {
301                     u32 flag = info3d.flags;
302                     NN_LOG("  *3D* ra(%.2f) cv(%d) df(%d) vol(%d) pr(%d) pa(%d) sp(%d) bqf(%d)\n",
303                             info3d.decayRatio, info3d.decayCurve, info3d.dopplerFactor,
304                             (flag & Sound3DInfo::FLAG_CTRL_VOLUME) > 0,
305                             (flag & Sound3DInfo::FLAG_CTRL_PRIORITY) > 0,
306                             (flag & Sound3DInfo::FLAG_CTRL_PAN) > 0,
307                             (flag & Sound3DInfo::FLAG_CTRL_SPAN) > 0,
308                             (flag & Sound3DInfo::FLAG_CTRL_FILTER) > 0 );
309                 }
310                 else
311                 {
312                     NN_LOG("  *3D* data not found\n");
313                 }
314             }
315 
316             // サウンド別個別情報
317             switch ( type )
318             {
319             case SoundArchive::SOUND_TYPE_SEQ:
320             {
321                 SoundArchive::SequenceSoundInfo seqInfo;
322                 bool retDetail = m_ArchiveReader.ReadSequenceSoundInfo( soundId, &seqInfo );
323                 NN_LOG(" *SEQ* ret(%d) ofs(%d) bnk(0x%08X,0x%08X,0x%08X,0x%08X) trk(0x%x) chPrio(%d) rPrioFix(%d)\n",
324                         retDetail,
325                         seqInfo.startOffset,
326                         seqInfo.bankIds[0], seqInfo.bankIds[1],
327                         seqInfo.bankIds[2], seqInfo.bankIds[3],
328                         seqInfo.allocateTrackFlags,
329                         seqInfo.channelPriority, seqInfo.isReleasePriorityFix );
330             }
331             break;
332             case SoundArchive::SOUND_TYPE_STRM:
333             {
334                 SoundArchive::StreamSoundInfo strmInfo;
335                 bool retDetail = m_ArchiveReader.ReadStreamSoundInfo( soundId, &strmInfo );
336                 NN_LOG("  *STRM* ret(%d) trk(%d) channel(%d)\n",
337                         retDetail, strmInfo.allocTrackCount, strmInfo.allocChannelCount );
338             }
339             break;
340             case SoundArchive::SOUND_TYPE_WAVE:
341             {
342                 SoundArchive::WaveSoundInfo wsdInfo;
343                 bool retDetail = m_ArchiveReader.ReadWaveSoundInfo( soundId, &wsdInfo );
344                 NN_LOG("  *WSD* ret(%d) index(%d) trk(0x%x) chPrio(%d) rPrioFix(%d)\n",
345                         retDetail,
346                         wsdInfo.index, wsdInfo.allocTrackCount,
347                         wsdInfo.channelPriority, wsdInfo.isReleasePriorityFix );
348             }
349             break;
350             case SoundArchive::SOUND_TYPE_INVALID:
351             {
352                 NN_LOG("Invalid SoundType (not STRM/WSD/SEQ)\n");
353             }
354             break;
355             }
356         }
357 
358         // バンク情報
359         NN_LOG("### BANK Info(%d)\n", m_ArchiveReader.GetBankCount() );
360         for ( u32 i = 0; i < m_ArchiveReader.GetBankCount(); i++ )
361         {
362             SoundArchive::ItemId bankId = GetBankIdFromIndex( i );
363             SoundArchive::BankInfo info;
364             bool ret = m_ArchiveReader.ReadBankInfo( bankId, &info );
365             NN_LOG("[%08X]?(%d) fileId(%d)\n", bankId, ret, info.fileId );
366         }
367 
368         // プレイヤー情報
369         NN_LOG("### PLAYER Info(%d)\n", m_ArchiveReader.GetPlayerCount() );
370         for ( u32 i = 0; i < m_ArchiveReader.GetPlayerCount(); i++ )
371         {
372             SoundArchive::ItemId playerId = GetPlayerIdFromIndex( i );
373             SoundArchive::PlayerInfo info;
374             bool ret = m_ArchiveReader.ReadPlayerInfo( playerId, &info );
375             NN_LOG("[%08X]?(%d) max(%d) heapSize(%d)\n",
376                     playerId, ret, info.playableSoundMax, info.playerHeapSize );
377         }
378 
379         // サウンドグループ情報
380         NN_LOG("### SOUND-GROUP Info(%d)\n", m_ArchiveReader.GetSoundGroupCount() );
381         for ( u32 i = 0; i < m_ArchiveReader.GetSoundGroupCount(); i++ )
382         {
383             SoundArchive::ItemId soundGroupId = GetSoundGroupIdFromIndex( i );
384             SoundArchive::SoundGroupInfo info;
385             bool ret = m_ArchiveReader.ReadSoundGroupInfo( soundGroupId, &info );
386             NN_LOG("[%08X]?(%d) startId(%08X) end(%08X) fileId:count(%d)",
387                     soundGroupId, ret, info.startId, info.endId, info.fileIdTable->count );
388             for ( u32 j = 0; j < info.fileIdTable->count; j++ )
389             {
390                 NN_LOG(" [%08X]", info.fileIdTable->item[j]);
391             }
392             NN_LOG("\n");
393         }
394 
395         // グループ情報
396         NN_LOG("### GROUP Info(%d)\n", m_ArchiveReader.GetGroupCount() );
397         for ( u32 i = 0; i < m_ArchiveReader.GetGroupCount(); i++ )
398         {
399             SoundArchive::ItemId groupId = GetGroupIdFromIndex( i );
400             SoundArchive::GroupInfo info;
401             bool ret = m_ArchiveReader.ReadGroupInfo( groupId, &info );
402             NN_LOG("[%08X]?(%d) fileId(%d)\n", groupId, ret, info.fileId );
403         }
404 
405         // 波形アーカイブ情報
406         NN_LOG("### WAVE-ARCHIVE Info(%d)\n", m_ArchiveReader.GetWaveArchiveCount() );
407         for ( u32 i = 0; i < m_ArchiveReader.GetWaveArchiveCount(); i++ )
408         {
409             SoundArchive::ItemId warcId = GetWaveArchiveIdFromIndex( i );
410             SoundArchive::WaveArchiveInfo info;
411             bool ret = m_ArchiveReader.ReadWaveArchiveInfo( warcId, &info );
412             NN_LOG("[%08X]?(%d) fileId(%d)\n", warcId, ret, info.fileId );
413         }
414 
415         // ファイル情報
416         NN_LOG("### FILE Info(%d)\n", m_ArchiveReader.GetFileCount() );
417         for ( u32 i = 0; i < m_ArchiveReader.GetFileCount(); i++ )
418         {
419             SoundArchive::FileInfo info;
420             bool ret = m_ArchiveReader.ReadFileInfo( i, &info );
421             if ( info.externalFilePath != NULL )
422             {
423                 NN_LOG("[%4d]?(%d) fileSize(%8d) ofs(%8d) path(%s)\n", i, ret,
424                         info.fileSize, info.offsetFromFileBlockHead, info.externalFilePath );
425             }
426             else
427             {
428                 NN_LOG("[%4d]?(%d) fileSize(%8d) ofs(%8d) path((null))\n", i, ret,
429                         info.fileSize, info.offsetFromFileBlockHead );
430             }
431         }
432 
433         // サウンドアーカイブプレイヤー情報
434         NN_LOG("### SOUND-ARCHIVE-PLAYER Info\n");
435         {
436             SoundArchive::SoundArchivePlayerInfo info;
437             bool ret = m_ArchiveReader.ReadSoundArchivePlayerInfo( &info );
438             NN_LOG("sequenceSoundMax (%2d)\n", info.sequenceSoundMax );
439             NN_LOG("sequenceTrackMax (%2d)\n", info.sequenceTrackMax );
440             NN_LOG("streamSoundMax   (%2d)\n", info.streamSoundMax );
441             NN_LOG("streamTrackMax   (%2d)\n", info.streamTrackMax );
442             NN_LOG("streamChannelMax (%2d)\n", info.streamChannelMax );
443             NN_LOG("waveSoundMax     (%2d)\n", info.waveSoundMax );
444             NN_LOG("waveTrackMax     (%2d)\n", info.waveTrackMax );
445         }
446     }
447 #endif /* NW_SND_DEBUG_PRINT_ENABLE */
448 
449     return true;
450 }
451 
452 /*---------------------------------------------------------------------------*
453   Name:         LoadLabelStringData
454 
455   Description:  ラベルデータをロードする
456 
457   Arguments:    buffer - ロードアドレス
458                 size - バッファサイズ
459 
460   Returns:      成功したら true 失敗したら false
461  *---------------------------------------------------------------------------*/
LoadLabelStringData(void * buffer,unsigned long size)462 bool RomSoundArchive::LoadLabelStringData( void* buffer, unsigned long size )
463 {
464     NW_ASSERT( m_IsOpened );
465 
466     const s32 stringBlockOffset = m_ArchiveReader.GetStringBlockOffset();
467     const u32 stringBlockSize = m_ArchiveReader.GetStringBlockSize();
468 
469     if ( stringBlockOffset == internal::Util::Reference::INVALID_OFFSET )
470     {
471         // サウンドアーカイブの文字列ブロックが含まれていない
472         return false;
473     }
474 
475     if ( size < stringBlockSize )
476     {
477         NW_WARNING(
478             size >= stringBlockSize,
479             "RomSoundArchive::LoadLabelStringData buffer size is too small."
480         );
481         return false;
482     }
483 
484 #ifdef NW_PLATFORM_CTRWIN
485     nn::fs::SeekFile( &m_FileInfo, stringBlockOffset, nn::fs::FS_SEEK_SET );
486     s32 readSize = nn::fs::ReadFile(
487         &m_FileInfo,
488         buffer,
489         static_cast<s32>(stringBlockSize)
490     );
491 #else
492     m_FileReader.Seek( stringBlockOffset, nn::fs::POSITION_BASE_BEGIN );
493     s32 readSize = m_FileReader.Read( buffer, static_cast<s32>(stringBlockSize) );
494 #endif
495     if ( readSize != stringBlockSize )
496     {
497         NW_WARNING(
498             false,
499             "RomSoundArchive::LoadLabelStringData cannot read file.\n"
500         );
501         return false;
502     }
503 
504     m_ArchiveReader.SetStringBlock( buffer/*, stringBlockSize*/ );
505 
506 #ifdef NW_SND_DEBUG_PRINT_ENABLE
507     // デバッグ出力
508     {
509         NN_LOG("### PATRICIA-TREE Info\n");
510         m_ArchiveReader.DumpTree();
511 
512         NN_LOG("### LABEL => ID\n");
513         int count = m_ArchiveReader.GetStringCount();
514         for ( int i = 0; i < count; i++ )
515         {
516             const char* str = m_ArchiveReader.GetString( i );
517             NN_LOG("[%02d] (%-16s) => ItemId(0x%08X)\n", i, str, GetItemId( str ) );
518 #if 0
519             NN_LOG("     as Sound ID:       (0x%08X)\n", GetSoundId( str ) );
520             NN_LOG("     as Bank ID:        (0x%08X)\n", GetBankId( str ) );
521             NN_LOG("     as Player ID:      (0x%08X)\n", GetPlayerId( str ) );
522             NN_LOG("     as SoundGroup ID:  (0x%08X)\n", GetSoundGroupId( str ) );
523             NN_LOG("     as Group ID:       (0x%08X)\n", GetGroupId( str ) );
524             NN_LOG("     as WaveArchive ID: (0x%08X)\n", GetWaveArchiveId( str ) );
525 #endif
526         }
527 
528         NN_LOG("### ID => LABEL\n");
529         NN_LOG("[Sound]\n");
530         for ( u32 i = 0; i < GetSoundCount(); i++ )
531         {
532             u32 id = GetSoundIdFromIndex( i );
533             NN_LOG("  [%08X] (%s)\n", id, GetItemLabel(id) );
534         }
535         NN_LOG("[Bank]\n");
536         for ( u32 i = 0; i < GetBankCount(); i++ )
537         {
538             u32 id = GetBankIdFromIndex( i );
539             NN_LOG("  [%08X] (%s)\n", id, GetItemLabel(id) );
540         }
541         NN_LOG("[Player]\n");
542         for ( u32 i = 0; i < GetPlayerCount(); i++ )
543         {
544             u32 id = GetPlayerIdFromIndex( i );
545             NN_LOG("  [%08X] (%s)\n", id, GetItemLabel(id) );
546         }
547         NN_LOG("[SoundGroup]\n");
548         for ( u32 i = 0; i < GetSoundGroupCount(); i++ )
549         {
550             u32 id = GetSoundGroupIdFromIndex( i );
551             NN_LOG("  [%08X] (%s)\n", id, GetItemLabel(id) );
552         }
553         NN_LOG("[Group]\n");
554         for ( u32 i = 0; i < GetGroupCount(); i++ )
555         {
556             u32 id = GetGroupIdFromIndex( i );
557             NN_LOG("  [%08X] (%s)\n", id, GetItemLabel(id) );
558         }
559         NN_LOG("[WaveArchive]\n");
560         for ( u32 i = 0; i < GetWaveArchiveCount(); i++ )
561         {
562             u32 id = GetWaveArchiveIdFromIndex( i );
563             const char* label = GetItemLabel( id );
564             if ( label != NULL )
565             {
566                 NN_LOG("  [%08X] (%s)\n", id, label );
567             }
568             else
569             {
570                 NN_LOG("  [%08X] ((anonymous))\n", id );
571             }
572         }
573     }
574 #endif /* NW_SND_DEBUG_PRINT_ENABLE */
575 
576     return true;
577 }
578 
579 #if 0
580 /*---------------------------------------------------------------------------*
581   Name:         RomFileStream
582 
583   Description:  コンストラクタ
584 
585   Arguments:    entryNum - DVDエントリ番号
586                 offset - DVDファイル先頭からのオフセット
587                 size   - ストリームサイズ
588 
589   Returns:      None.
590  *---------------------------------------------------------------------------*/
591 RomSoundArchive::RomFileStream::RomFileStream( s32 entryNum, u32 offset, u32 size )
592 : ut::RomLockedFileStream( entryNum ),
593   m_Offset( static_cast<s32>( offset ) ),
594   m_Size( size )
595 {
596     NW_ASSERT( m_Size <= ut::RomLockedFileStream::GetSize() );
597 
598     ut::RomLockedFileStream::Seek( m_Offset, ut::FILE_STREAM_SEEK_BEGIN );
599 }
600 #endif
601 
RomFileStream(const char * path,u32 offset,u32 size)602 RomSoundArchive::RomFileStream::RomFileStream( const char* path, u32 offset, u32 size )
603 // RomSoundArchive::RomFileStream::RomFileStream( const wchar_t* path, u32 offset, u32 size )
604 : io::RomFileStream( path ),
605   m_Offset( static_cast<s32>( offset ) ),
606   m_Size( size )
607 {
608     NW_ASSERT( m_Size <= io::RomFileStream::GetSize() );
609     if ( size == 0 )
610     {
611         m_Size = io::RomFileStream::GetSize();
612     }
613     io::RomFileStream::Seek( m_Offset, io::FILE_STREAM_SEEK_BEGIN );
614 }
615 
616 #ifdef NW_PLATFORM_CTRWIN
617 // オープン済みのファイルからストリームを作成して内部で持つ
RomFileStream(const nn::fs::File * fileInfo,u32 offset,u32 size)618 RomSoundArchive::RomFileStream::RomFileStream(
619         const nn::fs::File* fileInfo, u32 offset, u32 size )
620 : io::RomFileStream( fileInfo, false ),
621   m_Offset( static_cast<s32>( offset ) ),
622   m_Size( size )
623 {
624     NW_ASSERT( m_Size <= io::RomFileStream::GetSize() );
625     if ( size == 0 )
626     {
627         m_Size = io::RomFileStream::GetSize();
628     }
629     io::RomFileStream::Seek( m_Offset, io::FILE_STREAM_SEEK_BEGIN );
630 }
631 #else
632 // オープン済みのファイルからストリームを作成して内部で持つ
RomFileStream(nn::fs::FileReader * fileReader,u32 offset,u32 size)633 RomSoundArchive::RomFileStream::RomFileStream(
634         nn::fs::FileReader* fileReader, u32 offset, u32 size )
635 : io::RomFileStream( fileReader, false ),
636   m_Offset( static_cast<s32>( offset ) ),
637   m_Size( size )
638 {
639     NW_ASSERT( m_Size <= io::RomFileStream::GetSize() );
640     if ( size == 0 )
641     {
642         m_Size = io::RomFileStream::GetSize();
643     }
644     io::RomFileStream::Seek( m_Offset, io::FILE_STREAM_SEEK_BEGIN );
645 }
646 #endif
647 
Read(void * buf,u32 length)648 s32 RomSoundArchive::RomFileStream::Read( void* buf, u32 length )
649 {
650     NW_ALIGN32_ASSERT( buf );
651     NW_ALIGN32_ASSERT( length );
652 
653     u32 curPos = io::RomFileStream::Tell();
654     if ( curPos + length > m_Offset + m_Size ) {
655         length = static_cast<u32>( ut::RoundUp( m_Offset + m_Size - curPos, 32 ) );
656     }
657     return io::RomFileStream::Read( buf, length );
658 }
659 
Seek(s32 offset,u32 origin)660 void RomSoundArchive::RomFileStream::Seek( s32 offset, u32 origin )
661 {
662     switch( origin ) {
663     case io::FILE_STREAM_SEEK_BEGIN:
664         offset += m_Offset;
665         break;
666     case io::FILE_STREAM_SEEK_CURRENT:
667         offset += io::RomFileStream::Tell();
668         break;
669     case io::FILE_STREAM_SEEK_END:
670         offset = m_Offset + static_cast<s32>( m_Size ) - offset;
671         break;
672     default:
673         NW_ASSERTMSG( false, "Unsupported Seek origin" );
674         return;
675     }
676 
677     if ( offset < m_Offset )
678     {
679         offset = m_Offset;
680     }
681     else if ( offset > m_Offset + static_cast<s32>( m_Size ) )
682     {
683         offset = m_Offset + static_cast<s32>( m_Size );
684     }
685 
686     io::RomFileStream::Seek( offset, io::FILE_STREAM_SEEK_BEGIN );
687 }
688 
689 } // namespace nw::snd
690 } // namespace nw
691 
692