1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     snd_SoundArchiveLoader.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: 22506 $
14  *---------------------------------------------------------------------------*/
15 
16 #include "precompiled.h"
17 
18 #include <nw/snd/snd_SoundArchiveLoader.h>
19 #include <nw/snd/snd_SoundMemoryAllocatable.h>
20 
21 namespace nw {
22 namespace snd {
23 namespace internal {
24 
25 namespace
26 {
27 
28 class FileStreamHandle
29 {
30 public:
FileStreamHandle(io::FileStream * stream)31     FileStreamHandle( io::FileStream* stream ) : m_pStream( stream ) { }
~FileStreamHandle()32     ~FileStreamHandle() { if ( m_pStream != NULL ) m_pStream->Close(); }
33 
GetFileStream()34     io::FileStream* GetFileStream() { return m_pStream; }
operator ->()35     io::FileStream* operator->() { return m_pStream; }
operator bool() const36     operator bool() const { return m_pStream != NULL; }
37 
38 private:
39     io::FileStream* m_pStream;
40 };
41 
42 } // anonymous namespace
43 
44 /*---------------------------------------------------------------------------*
45   Name:         SoundArchiveLoader
46 
47   Description:  コンストラクタ
48 
49   Arguments:    arc - ローダで使用するサウンドアーカイブ
50 
51   Returns:      なし
52  *---------------------------------------------------------------------------*/
SoundArchiveLoader(const SoundArchive & arc)53 SoundArchiveLoader::SoundArchiveLoader( const SoundArchive& arc )
54 : m_Arc( arc )
55 {
56     m_CriticalSection.Initialize();
57 }
58 
59 /*---------------------------------------------------------------------------*
60   Name:         SoundArchiveLoader
61 
62   Description:  デストラクタ
63 
64   Arguments:    なし
65 
66   Returns:      なし
67  *---------------------------------------------------------------------------*/
~SoundArchiveLoader()68 SoundArchiveLoader::~SoundArchiveLoader()
69 {
70     m_CriticalSection.Finalize();
71 }
72 
73 /*---------------------------------------------------------------------------*
74   Name:         ReadFile
75 
76   Description:  サウンドアーカイブ内のファイルの一部をメモリ上に読み出します。
77                 ID が fileId のファイルの offset バイト目から size だけ読み出します。
78 
79   Arguments:    fileId - サウンドアーカイブ内のファイル ID です。
80                 buffer - ロードするバッファの先頭アドレスです。
81                 size   - 読み出すサイズです。
82                 offset - ファイル「ファイル ID」の先頭からのオフセットです。
83 
84   Returns:      読み込んだサイズを返します。
85                 失敗したときは、-1 を返します。
86  *---------------------------------------------------------------------------*/
ReadFile(SoundArchive::FileId fileId,void * buffer,size_t size,s32 offset,size_t loadBlockSize)87 s32 SoundArchiveLoader::ReadFile(
88         SoundArchive::FileId fileId,
89         void* buffer,
90         size_t size,
91         s32 offset,
92         size_t loadBlockSize )
93 {
94 	nn::os::CriticalSection::ScopedLock lock(m_CriticalSection); // 他スレッドからのデータロードを考慮
95 
96     FileStreamHandle stream = const_cast<SoundArchive&>(m_Arc).detail_OpenFileStream(
97             fileId, m_StreamArea, sizeof(m_StreamArea) );
98     if ( ! stream )
99     {
100         return -1;
101     }
102     if ( ! stream->CanSeek() || ! stream->CanRead() )
103     {
104         return -1;
105     }
106 
107     stream->Seek( offset, io::FILE_STREAM_SEEK_BEGIN );
108 
109     if ( loadBlockSize == 0 )
110     {
111         // 一括ロード
112         s32 readByte = stream->Read( buffer, ut::RoundUp( static_cast<u32>( size ), 32 ) );
113         if ( readByte < 0 )
114         {
115             return -1;
116         }
117     }
118     else
119     {
120         // 分割ロード
121         u8* ptr = reinterpret_cast<u8*>( buffer );
122         u32 restSize = size;
123         while ( restSize > 0 )
124         {
125             u32 curReadingSize = ut::RoundUp( ut::Min<u32>( loadBlockSize, restSize ), 32 );
126             s32 readByte = stream->Read( ptr, curReadingSize );
127             if ( readByte < 0 )
128             {
129                 return -1;
130             }
131             if ( restSize > readByte )
132             {
133                 restSize -= readByte;
134                 ptr += readByte;
135             }
136             else
137             {
138                 restSize = 0;
139             }
140         }
141     }
142 
143     return size;
144 }
145 
146 /*---------------------------------------------------------------------------*
147   Name:         LoadFile
148 
149   Description:  サウンドアーカイブ内のファイルをロードします。
150 
151   Arguments:    fileId   - サウンドアーカイブ内のファイル ID です。
152                 allocator - ファイルを格納するメモリを確保するアロケータです。
153                 loadBlockSize - 分割ロード時、1回の Read で読み取るサイズ。
154                                 0 だと一括ロードする。
155                 needDeviceMemory - デバイスメモリへのロードが必要かどうかのフラグです。
156 
157   Returns:      ロードしたメモリアドレス
158                 ロード失敗時には NULL を返す
159  *---------------------------------------------------------------------------*/
LoadFile(SoundArchive::FileId fileId,SoundMemoryAllocatable * allocator,size_t loadBlockSize,bool needDeviceMemory)160 void* SoundArchiveLoader::LoadFile(
161     SoundArchive::FileId fileId,
162     SoundMemoryAllocatable* allocator,
163     size_t loadBlockSize,
164     bool needDeviceMemory )
165 {
166     NW_NULL_ASSERT( allocator );
167 
168     SoundArchive::FileInfo fileInfo;
169     if ( ! m_Arc.detail_ReadFileInfo( fileId, &fileInfo ) )
170     {
171         return NULL;
172     }
173     u32 fileSize = fileInfo.fileSize;
174     if ( fileSize == 0 )
175     {
176         return NULL;
177     }
178 
179     void* buffer = allocator->Alloc( fileSize );
180     if ( buffer == NULL )
181     {
182         return NULL;
183     }
184     if ( needDeviceMemory )
185     {
186         if ( ! Util::IsDeviceMemory( reinterpret_cast<uptr>(buffer), fileSize )  )
187         {
188             NW_ASSERTMSG( false, "buffer, buffer + fileSize is not Device Memory.");
189             return false;
190         }
191     }
192 
193     if ( ReadFile( fileId, buffer, (s32)fileSize, 0, loadBlockSize ) != fileSize )
194     {
195         return NULL;
196     }
197 #ifdef NW_PLATFORM_CTR
198     nn::snd::FlushDataCache( reinterpret_cast<uptr>(buffer), fileSize );
199 #endif
200 
201     return buffer;
202 }
203 
204 } // namespace nw::snd::internal
205 } // namespace nw::snd
206 } // namespace nw
207 
208