/*---------------------------------------------------------------------------* Project: NintendoWare File: snd_SoundArchiveLoader.cpp Copyright (C)2009-2010 Nintendo Co., Ltd./HAL Laboratory, Inc. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Revision: 22506 $ *---------------------------------------------------------------------------*/ #include "precompiled.h" #include #include namespace nw { namespace snd { namespace internal { namespace { class FileStreamHandle { public: FileStreamHandle( io::FileStream* stream ) : m_pStream( stream ) { } ~FileStreamHandle() { if ( m_pStream != NULL ) m_pStream->Close(); } io::FileStream* GetFileStream() { return m_pStream; } io::FileStream* operator->() { return m_pStream; } operator bool() const { return m_pStream != NULL; } private: io::FileStream* m_pStream; }; } // anonymous namespace /*---------------------------------------------------------------------------* Name: SoundArchiveLoader Description: コンストラクタ Arguments: arc - ローダで使用するサウンドアーカイブ Returns: なし *---------------------------------------------------------------------------*/ SoundArchiveLoader::SoundArchiveLoader( const SoundArchive& arc ) : m_Arc( arc ) { m_CriticalSection.Initialize(); } /*---------------------------------------------------------------------------* Name: SoundArchiveLoader Description: デストラクタ Arguments: なし Returns: なし *---------------------------------------------------------------------------*/ SoundArchiveLoader::~SoundArchiveLoader() { m_CriticalSection.Finalize(); } /*---------------------------------------------------------------------------* Name: ReadFile Description: サウンドアーカイブ内のファイルの一部をメモリ上に読み出します。 ID が fileId のファイルの offset バイト目から size だけ読み出します。 Arguments: fileId - サウンドアーカイブ内のファイル ID です。 buffer - ロードするバッファの先頭アドレスです。 size - 読み出すサイズです。 offset - ファイル「ファイル ID」の先頭からのオフセットです。 Returns: 読み込んだサイズを返します。 失敗したときは、-1 を返します。 *---------------------------------------------------------------------------*/ s32 SoundArchiveLoader::ReadFile( SoundArchive::FileId fileId, void* buffer, size_t size, s32 offset, size_t loadBlockSize ) { nn::os::CriticalSection::ScopedLock lock(m_CriticalSection); // 他スレッドからのデータロードを考慮 FileStreamHandle stream = const_cast(m_Arc).detail_OpenFileStream( fileId, m_StreamArea, sizeof(m_StreamArea) ); if ( ! stream ) { return -1; } if ( ! stream->CanSeek() || ! stream->CanRead() ) { return -1; } stream->Seek( offset, io::FILE_STREAM_SEEK_BEGIN ); if ( loadBlockSize == 0 ) { // 一括ロード s32 readByte = stream->Read( buffer, ut::RoundUp( static_cast( size ), 32 ) ); if ( readByte < 0 ) { return -1; } } else { // 分割ロード u8* ptr = reinterpret_cast( buffer ); u32 restSize = size; while ( restSize > 0 ) { u32 curReadingSize = ut::RoundUp( ut::Min( loadBlockSize, restSize ), 32 ); s32 readByte = stream->Read( ptr, curReadingSize ); if ( readByte < 0 ) { return -1; } if ( restSize > readByte ) { restSize -= readByte; ptr += readByte; } else { restSize = 0; } } } return size; } /*---------------------------------------------------------------------------* Name: LoadFile Description: サウンドアーカイブ内のファイルをロードします。 Arguments: fileId - サウンドアーカイブ内のファイル ID です。 allocator - ファイルを格納するメモリを確保するアロケータです。 loadBlockSize - 分割ロード時、1回の Read で読み取るサイズ。 0 だと一括ロードする。 needDeviceMemory - デバイスメモリへのロードが必要かどうかのフラグです。 Returns: ロードしたメモリアドレス ロード失敗時には NULL を返す *---------------------------------------------------------------------------*/ void* SoundArchiveLoader::LoadFile( SoundArchive::FileId fileId, SoundMemoryAllocatable* allocator, size_t loadBlockSize, bool needDeviceMemory ) { NW_NULL_ASSERT( allocator ); SoundArchive::FileInfo fileInfo; if ( ! m_Arc.detail_ReadFileInfo( fileId, &fileInfo ) ) { return NULL; } u32 fileSize = fileInfo.fileSize; if ( fileSize == 0 ) { return NULL; } void* buffer = allocator->Alloc( fileSize ); if ( buffer == NULL ) { return NULL; } if ( needDeviceMemory ) { if ( ! Util::IsDeviceMemory( reinterpret_cast(buffer), fileSize ) ) { NW_ASSERTMSG( false, "buffer, buffer + fileSize is not Device Memory."); return false; } } if ( ReadFile( fileId, buffer, (s32)fileSize, 0, loadBlockSize ) != fileSize ) { return NULL; } #ifdef NW_PLATFORM_CTR nn::snd::FlushDataCache( reinterpret_cast(buffer), fileSize ); #endif return buffer; } } // namespace nw::snd::internal } // namespace nw::snd } // namespace nw