/*---------------------------------------------------------------------------* Project: NintendoWare File: main.cpp Copyright (C)2009-2011 Nintendo/HAL Laboratory, Inc. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo and/or its licensed developers and are protected by national and international copyright laws. 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. The content herein is highly confidential and should be handled accordingly. $Revision: $ *---------------------------------------------------------------------------*/ #include "precompiled.h" #include #include #include "demolib.h" /*---------------------------------------------------------------------------* *---------------------------------------------------------------------------*/ namespace { const s32 SOUND_THREAD_PRIORITY = 4; const s32 LOAD_THREAD_PRIORITY = 3; const s32 SOUND_HEAP_SIZE = 10 * 1024 * 1024; const char SOUND_ARC_PATH[] = "simple.bcsar"; const char DEMO_TITLE[] = "HioSoundArchive"; const int CHAR_BUF_SIZE = 256; char s_HioFilePathBuffer[CHAR_BUF_SIZE]; const char* SOUND_ARC_DIR[] = { "tools/SoundMaker/_tmpForSoundPlayer/A", // DIR_TYPE_A "tools/SoundMaker/_tmpForSoundPlayer/B" // DIR_TYPE_B }; const char* SOUND_ARC_FILE = "tmp.bcsar"; const char* LATEST_COPY_FILE = "_latestCopy"; enum DirType { DIR_TYPE_A, DIR_TYPE_B }; DirType s_DirType; const char* GetHioNw4cRoot() { s32 result = nn::hio::GetEnvironmentVariable( s_HioFilePathBuffer, sizeof(s_HioFilePathBuffer), "NW4C_ROOT" ); if ( result < 0 ) { return NULL; } return s_HioFilePathBuffer; } const char* GetHioSoundArchiveFilePath( DirType type ) { std::snprintf( s_HioFilePathBuffer, CHAR_BUF_SIZE, "%s/%s/%s", GetHioNw4cRoot(), SOUND_ARC_DIR[type], SOUND_ARC_FILE ); return s_HioFilePathBuffer; } const char* GetHioLatestCopyFilePath( DirType type ) { std::snprintf( s_HioFilePathBuffer, CHAR_BUF_SIZE, "%s/%s/%s", GetHioNw4cRoot(), SOUND_ARC_DIR[type], LATEST_COPY_FILE ); return s_HioFilePathBuffer; } bool OpenLatestCopyFile( nn::hio::HostFile& file, DirType type ) { bool result = file.Open( GetHioLatestCopyFilePath( type ), nn::hio::HostFile::ACCESS_MODE_READ, nn::hio::HostFile::OPEN_DISP_OPEN_EXISTING ).IsSuccess(); NN_LOG("Open (%s) ... %d\n", GetHioLatestCopyFilePath( type ), result ); return result; } } // anonymous namespace /*---------------------------------------------------------------------------* アプリケーションクラス *---------------------------------------------------------------------------*/ class HioSoundArchiveApp : public nw::snd::demolib::AppBase { protected: virtual void OnInitialize(); virtual void OnFinalize(); virtual void OnDrawUpLCD( nw::font::TextWriter& ); virtual void OnDrawDownLCD( nw::font::TextWriter& ); virtual void OnUpdatePad( nw::demo::Pad& ); virtual void OnUpdate(); private: void InitializeSoundSystem(); bool InitializeSoundManager(); bool OpenSoundArchive(); void CloseSoundArchive(); nw::snd::HioSoundArchive m_Archive; nw::snd::SoundArchivePlayer m_ArchivePlayer; nw::snd::SoundDataManager m_DataManager; nw::snd::SoundHeap m_Heap; nw::snd::SoundHandle m_Handle; void* m_pMemoryForSoundSystem; void* m_pMemoryForInfoBlock; void* m_pMemoryForStringBlock; void* m_pMemoryForSoundDataManager; void* m_pMemoryForSoundArchivePlayer; void* m_pMemoryForSoundHeap; void* m_pMemoryForStreamBuffer; u32 m_SoundIndex; u32 m_SoundCount; bool m_IsOpenedSoundArchive; bool m_IsLoadStringBlock; }; /*---------------------------------------------------------------------------* アプリケーションクラス実装 *---------------------------------------------------------------------------*/ void HioSoundArchiveApp::OnInitialize() { // nn::hio { nn::Result result = nn::hio::Initialize( MemAlloc( nn::hio::WORKMEMORY_SIZE ) ); NW_ASSERT( result.IsSuccess() ); if ( result.IsFailure() ) { return; } } // アプリケーション初期化 m_IsOpenedSoundArchive = false; m_IsLoadStringBlock = false; m_SoundIndex = 0; m_SoundCount = 0; InitializeSoundSystem(); OpenSoundArchive(); } void HioSoundArchiveApp::InitializeSoundSystem() { // サウンドシステムの初期化 { nw::snd::SoundSystem::SoundSystemParam param; size_t workMemSize = nw::snd::SoundSystem::GetRequiredMemSize( param ); m_pMemoryForSoundSystem = MemAlloc( workMemSize ); nw::snd::SoundSystem::Initialize( param, reinterpret_cast( m_pMemoryForSoundSystem ), workMemSize ); } } bool HioSoundArchiveApp::InitializeSoundManager() { // サウンドデータマネージャーの初期化 { size_t setupSize = m_DataManager.GetRequiredMemSize( &m_Archive ); m_pMemoryForSoundDataManager = MemAlloc( setupSize ); m_DataManager.Initialize( &m_Archive, m_pMemoryForSoundDataManager, setupSize ); } // サウンドアーカイブプレイヤーの初期化 { size_t setupSize = m_ArchivePlayer.GetRequiredMemSize( &m_Archive ); m_pMemoryForSoundArchivePlayer = MemAlloc( setupSize, 32 ); size_t setupStrmBufferSize = m_ArchivePlayer.GetRequiredStreamBufferSize( &m_Archive ); m_pMemoryForStreamBuffer = MemAlloc( setupStrmBufferSize, 32 ); bool result = m_ArchivePlayer.Initialize( &m_Archive, &m_DataManager, m_pMemoryForSoundArchivePlayer, setupSize, m_pMemoryForStreamBuffer, setupStrmBufferSize ); NW_ASSERT( result ); if ( result == false ) { return false; } } // サウンドヒープの構築 { m_pMemoryForSoundHeap = MemAlloc( SOUND_HEAP_SIZE ); bool result = m_Heap.Create( m_pMemoryForSoundHeap, SOUND_HEAP_SIZE ); NW_ASSERT( result ); if ( result == false ) { return false; } } return true; } bool HioSoundArchiveApp::OpenSoundArchive() { bool ret = false; { nn::hio::HostFile file; ret = OpenLatestCopyFile( file, DIR_TYPE_A ); if ( ret == true ) { s_DirType = DIR_TYPE_A; } else { ret = OpenLatestCopyFile( file, DIR_TYPE_B ); if ( ret == true ) { s_DirType = DIR_TYPE_B; } else { return false; } } file.Close(); } const char* HIO_ARCHIVE_PATH = GetHioSoundArchiveFilePath( s_DirType ); NN_LOG("HIO_ARCHIVE_PATH(%s)\n", HIO_ARCHIVE_PATH ); // オープン { ret = m_Archive.Open( HIO_ARCHIVE_PATH ); if ( ret == false ) { // NW_ASSERTMSG( 0, "cannot open bcsar(%s)\n", HIO_ARCHIVE_PATH ); return false; } } // INFO ブロックのロード { u32 infoBlockSize = m_Archive.GetHeaderSize(); m_pMemoryForInfoBlock = MemAlloc( infoBlockSize ); if ( ! m_Archive.LoadHeader( m_pMemoryForInfoBlock, infoBlockSize ) ) { NW_ASSERTMSG( 0, "cannot load infoBlock(%s)", HIO_ARCHIVE_PATH ); } } // STRING ブロックのロード { u32 stringBlockSize = m_Archive.GetLabelStringDataSize(); // size == 0xffffffff のとき、文字列ブロックが含まれていない if ( stringBlockSize != 0xffffffff ) { m_pMemoryForStringBlock = MemAlloc( stringBlockSize ); if ( ! m_Archive.LoadLabelStringData( m_pMemoryForStringBlock, stringBlockSize ) ) { NW_ASSERTMSG( 0, "cannot load stringBlock(%s)", HIO_ARCHIVE_PATH ); } else { m_IsLoadStringBlock = true; } } } m_IsOpenedSoundArchive = true; m_SoundCount = m_Archive.GetSoundCount(); m_SoundIndex = 0; ret = InitializeSoundManager(); return ret; } // サウンドアーカイブ再読込のため、SoundArchive を一旦閉じる。 // (関連する SoundArchivePlayer, SoundDataManager なども Finalize する) void HioSoundArchiveApp::CloseSoundArchive() { if ( m_IsOpenedSoundArchive == false ) { return; } if ( m_Heap.IsValid() ) { m_Heap.Destroy(); MemFree( m_pMemoryForSoundHeap ); } if ( m_ArchivePlayer.IsAvailable() ) { m_ArchivePlayer.Finalize(); MemFree( m_pMemoryForSoundArchivePlayer ); MemFree( m_pMemoryForStreamBuffer ); } if ( m_DataManager.IsAvailable() ) { m_DataManager.Finalize(); MemFree( m_pMemoryForSoundDataManager ); } m_Archive.Close(); if ( m_IsLoadStringBlock ) { MemFree( m_pMemoryForStringBlock ); } MemFree( m_pMemoryForInfoBlock ); m_IsOpenedSoundArchive = false; m_IsLoadStringBlock = false; m_SoundIndex = 0; m_SoundCount = 0; } void HioSoundArchiveApp::OnFinalize() { nw::snd::SoundSystem::Finalize(); MemFree( m_pMemoryForSoundSystem ); MemFree( m_pMemoryForInfoBlock ); MemFree( m_pMemoryForSoundDataManager ); MemFree( m_pMemoryForSoundArchivePlayer ); MemFree( m_pMemoryForSoundHeap ); MemFree( m_pMemoryForStreamBuffer ); } void HioSoundArchiveApp::OnDrawUpLCD( nw::font::TextWriter& writer ) { writer.Printf(" DEMO nw::snd %s\n\n", DEMO_TITLE); writer.Print (" -- usage --\n\n"); writer.Print (" [A] Start Sound\n"); writer.Print (" [B] Stop Sound\n\n"); writer.Print (" [LEFT/RIGHT] Change Sound\n"); writer.Print (" [START] Reload Sound Archive\n\n"); // サウンド表示 if ( m_IsOpenedSoundArchive ) { nw::snd::SoundArchive::ItemId id = m_Archive.GetSoundIdFromIndex( m_SoundIndex ); if ( m_IsLoadStringBlock ) { const char* label = m_Archive.GetItemLabel( id ); if ( label == NULL ) { label = "..."; // 文字列 } writer.Printf(" [%08x] %s\n", id, label ); } } else { writer.Print (" SoundArchive is not opened.\n"); writer.Print (" Press START for open SoundArchive.\n"); } } void HioSoundArchiveApp::OnDrawDownLCD( nw::font::TextWriter& writer ) { (void)writer; } void HioSoundArchiveApp::OnUpdatePad( nw::demo::Pad& pad ) { if ( pad.IsButtonRepeatFast( nw::demo::Pad::BUTTON_LEFT ) ) { if ( m_SoundIndex == 0 ) { m_SoundIndex = m_SoundCount - 1; } else { m_SoundIndex -= 1; } } if ( pad.IsButtonRepeatFast( nw::demo::Pad::BUTTON_RIGHT ) ) { if ( m_SoundIndex == m_SoundCount - 1 ) { m_SoundIndex = 0; } else { m_SoundIndex += 1; } } if ( pad.IsButtonDown( nw::demo::Pad::BUTTON_START ) ) { CloseSoundArchive(); OpenSoundArchive(); } if ( m_IsOpenedSoundArchive ) { if ( pad.IsButtonDown( nw::demo::Pad::BUTTON_A ) ) { // 前のサウンドをストップ m_Handle.Stop( 0 ); // データロード (SEQ/WSDのみ) nw::snd::SoundArchive::ItemId id = m_Archive.GetSoundIdFromIndex( m_SoundIndex ); if ( m_Archive.GetSoundType( id ) != nw::snd::SoundArchive::SOUND_TYPE_STRM ) { if ( ! m_DataManager.IsDataLoaded( id ) ) { m_Heap.LoadState( 0 ); // ヒープリセット if ( ! m_DataManager.LoadData( id, &m_Heap ) ) { NW_WARNING( false, "load failed ... %08x is too big", id ); } } } bool ret = m_ArchivePlayer.StartSound( &m_Handle, id ).IsSuccess(); NN_LOG("StartSound(%08x) ... %d\n", id, ret ); } if ( pad.IsButtonDown( nw::demo::Pad::BUTTON_B ) ) { m_Handle.Stop( 3 ); } } } void HioSoundArchiveApp::OnUpdate() { m_ArchivePlayer.Update(); } /*---------------------------------------------------------------------------* メイン処理 *---------------------------------------------------------------------------*/ void nnMain() { HioSoundArchiveApp app; app.Initialize(); app.Run(); app.Finalize(); }