/*! @file sysHeap.cpp @brief ヒープ */ //#include "sys.h" #include "sysHeap.h" #ifndef NW_RELEASE //#include "sceneManager.h" #endif static const size_t scMainHeapSize = 0x800000; // 8MB static const size_t scSceneHeapSize = 0x200000; // 2MB static const size_t scDeviceHeapSize = 0x1000000; // 16MB #ifdef DEBUG_MEMORY static size_t smSceneHeapSize = 0xffffffff; static size_t smMainHeapSize = 0xffffffff; static size_t smDeviceHeapSize = 0xffffffff; #endif // デフォルトのStartUp関数を呼ばないようにする extern "C" void nninitStartUp(void) { nn::os::SetDeviceMemorySize(0); nn::os::SetHeapSize(0); } namespace sys { #ifndef NW_RELEASE Mem::MemList Mem::smList; #endif Heap Mem::smMainHeap; Heap Mem::smSceneHeap; Heap Mem::smDeviceHeap; /*! 初期化 */ void Mem::init() { NN_LOG("Use Memory Size:0x%x %x\n", nn::os::GetUsingMemorySize(), nn::os::GetAppMemorySize() ); nn::os::SetHeapSize( scMainHeapSize + scSceneHeapSize ); nn::Result result = nn::os::SetDeviceMemorySize( scDeviceHeapSize ); NN_UTIL_PANIC_IF_FAILED( result ); size_t size = nn::os::GetHeapSize(); uptr address = nn::os::GetHeapAddress(); NN_LOG("################# Main Memory : 0x%x - 0x%x #################\n", ( uint )address, ( ( uint )address + size ) ); // メインメモリ初期化 smMainHeap.getHeap()->Initialize( address, scMainHeapSize, nn::os::ALLOCATE_OPTION_LINEAR ); // シーンメモリ初期化 smSceneHeap.getHeap()->Initialize( address + scMainHeapSize, size - scMainHeapSize, nn::os::ALLOCATE_OPTION_LINEAR ); // デバイス用メモリ初期化 smDeviceHeap.getHeap()->Initialize( nn::os::GetDeviceMemoryAddress(), scDeviceHeapSize, nn::os::ALLOCATE_OPTION_LINEAR ); nwosPrintf("################# Device Memory : 0x%x - 0x%x #################\n", nn::os::GetDeviceMemoryAddress(), nn::os::GetDeviceMemoryAddress() + scDeviceHeapSize ); { s32 memSize = nn::fs::GetRomRequiredMemorySize( /*ROMFS_MAX_FILE, ROMFS_MAX_DIRECTORY*/128, 128 ); // s32 memSize = 32 * 1024; u8* fs_buf = new( &smMainHeap ) u8[ memSize ]; bool ret = nn::fs::MountRom( 128,//ROMFS_MAX_FILE, 128,//ROMFS_MAX_DIRECTORY, fs_buf, memSize ).IsSuccess(); // NN_LOG("RomFS: mem(%p) size(%d) files(%d) dirs(%d)\n", // fs_buf, memSize, // /*ROMFS_MAX_FILE, ROMFS_MAX_DIRECTORY*/128, 128 ); } #ifndef NW_RELEASE // デバッグ用SDカードアクセス nn::fs::MountSdmc(); #endif } /*! 終了処理 */ void Mem::finish() { smSceneHeap.getHeap()->Invalidate(); smMainHeap.getHeap()->Invalidate(); smDeviceHeap.getHeap()->Invalidate(); nn::os::SetHeapSize(0); nn::os::SetDeviceMemorySize(0); } void* Mem::AllocDeviceMemory( size_t size, s32 alignment ) { // 2のべき乗のチェック NW_ASSERT( (alignment & (alignment - 1)) == 0 ); if ( alignment == 0 ) { alignment = NN_FND_HEAP_DEFAULT_ALIGNMENT; } void* memory = smDeviceHeap.getHeap()->Allocate( size, alignment ); #ifdef DEBUG_MEMORY if( smDeviceHeap.getHeap()->GetAllocatableSize() < smDeviceHeapSize ) { smDeviceHeapSize = smDeviceHeap.getHeap()->GetAllocatableSize(); NN_LOG("DeviceHeap AllocatableSize: 0x%x\n", smDeviceHeapSize ); // sys::Mem::getDeviceHeap()->getHeap()->Dump(); } #endif return memory; } void* Mem::Alloc( Heap* p_heap, size_t size, s32 alignment ) { // 2のべき乗のチェック NW_ASSERT( (alignment & (alignment - 1)) == 0 ); NW_ASSERT( p_heap != &smDeviceHeap ); if( alignment == 0 ) alignment = NN_FND_HEAP_DEFAULT_ALIGNMENT; if( p_heap == NULL ) p_heap = &smMainHeap; void* memory = p_heap->getHeap()->Allocate( size, alignment ); #ifndef NW_RELEASE if( p_heap == &smSceneHeap ) { NW_ASSERTMSG(memory, "Failed allocate SceneHeap %d/%d", size, scSceneHeapSize - p_heap->getHeap()->GetTotalSize() ); //SceneMem* mem = new( &smMainHeap ) SceneMem( memory, scene::Manager::getActiveSceneID(), size ); //smList.PushBack( mem ); } #endif #ifdef DEBUG_MEMORY if( p_heap == &smSceneHeap && smSceneHeap.getHeap()->GetAllocatableSize() < smSceneHeapSize ) { smSceneHeapSize = smSceneHeap.getHeap()->GetAllocatableSize(); NN_LOG("SceneHeap AllocatableSize: 0x%x\n", smSceneHeapSize ); // sys::Mem::getSceneHeap()->getHeap()->Dump(); } if( p_heap == &smMainHeap && smMainHeap.getHeap()->GetAllocatableSize() < smMainHeapSize ) { smMainHeapSize = smMainHeap.getHeap()->GetAllocatableSize(); NN_LOG("MainHeap AllocatableSize: 0x%x\n", smMainHeapSize ); // sys::Mem::getMainHeap()->getHeap()->Dump(); } #endif return memory; } void Mem::Free( void* memory ) { if( smDeviceHeap.getHeap()->HasAddress( memory ) ) { smDeviceHeap.getHeap()->Free( memory ); } else if( smMainHeap.getHeap()->HasAddress( memory ) ) { smMainHeap.getHeap()->Free( memory ); } else { smSceneHeap.getHeap()->Free( memory ); #ifndef NW_RELEASE for( MemList::Iterator it = smList.GetBeginIter(); it != smList.GetEndIter(); ++it ) { SceneMem* mem = reinterpret_cast< SceneMem* >( &(*it) ); if( mem->getAddress() == memory ) { smList.Erase( mem ); delete mem; break; } } #endif } } /*! シーンヒープに開放忘れがないかチェック */ #ifndef NW_RELEASE bool Mem::checkSceneHeap( int scene_id ) { bool ret = true; for( MemList::Iterator it = smList.GetBeginIter(); it != smList.GetEndIter(); ++it ) { SceneMem* mem = reinterpret_cast< SceneMem* >( &(*it) ); if( mem->getID() == scene_id ) { NN_LOG("%d Scene Memory Leak!!(size%d) (addr%x)\n", scene_id, mem->getSize(), mem->getAddress() ); ret = false; } } return ret; } #endif } void* operator new( size_t size, int alignment ) throw() { NW_ASSERT( 0 ); return operator new( size, NULL, alignment ); } void* operator new( size_t size, sys::Heap* p_heap, int alignment ) throw() { if( p_heap == sys::Mem::getDeviceHeap() ) { return sys::Mem::AllocDeviceMemory( size, alignment ); } return sys::Mem::Alloc( p_heap, size, alignment ); } void* operator new[]( size_t size, int alignment ) throw() { NW_ASSERT( 0 ); return operator new[]( size, NULL, alignment ); } void* operator new[]( size_t size, const ::std::nothrow_t& ) throw() { return operator new[]( size, NULL, NN_FND_HEAP_DEFAULT_ALIGNMENT ); } void* operator new[]( size_t size, sys::Heap* p_heap, int alignment ) throw() { if( p_heap == sys::Mem::getDeviceHeap() ) { return sys::Mem::AllocDeviceMemory( size, alignment ); } return sys::Mem::Alloc( p_heap, size, alignment ); } void operator delete( void* mem_block ) throw() { if( mem_block != NULL ) { sys::Mem::Free( mem_block ); } } void operator delete[]( void* mem_block ) throw() { if( mem_block != NULL ) { sys::Mem::Free( mem_block ); } }