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