/*---------------------------------------------------------------------------* Project: NintendoWare File: lyt_ArcResourceAccessor.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: 31311 $ *---------------------------------------------------------------------------*/ #include "precompiled.h" #include #include #include #include namespace nw { namespace lyt { namespace { /*!--------------------------------------------------------------------------* @brief 文字列を小文字として比較します。 @param[in] string1 比較対象の文字列です。 @param[in] string2 比較対象の文字列です。 @return 比較結果を返します。 *---------------------------------------------------------------------------*/ inline int wcsicmp( const wchar_t *string1, const wchar_t *string2) { #ifdef NW_COMPILER_MSVC return ::_wcsicmp(string1, string2); #else return std::wcscasecmp(string1, string2); #endif } /*!--------------------------------------------------------------------------* @brief 文字列をコピーします。 src 文字列を コピーし、必ず nul の終端文字を追加します。 destCount が src文字列の長さより小さい場合は切り詰めてコピーされますが、 必ず nul 終端文字が挿入されます。 @tparam 文字の型です。 @param[in] dest コピー先のバッファのアドレスです。 @param[in] destCount コピー先のバッファサイズです。 @param[in] src コピー元の文字列のアドレスです。 @return コピーした文字数を返します。 *---------------------------------------------------------------------------*/ size_t strncpy( wchar_t* dest, std::size_t destCount, const char* src ) { NW_ASSERT(destCount > 0); --destCount; // 終端文字分減らす size_t length = 0; while (length < destCount && *src != '\0') { *dest = *src; ++dest; ++src; ++length; } *dest = L'\0'; return length; } /*---------------------------------------------------------------------------* @brief 指定されたリソース名を持つリソースをファイル情報テーブルから 探し出します。 @param pArcHandle ARCHandleオブジェクトへのポインタ。 @param resName リソース名へのポインタ。 @return リソースが見つかれば、そのリソースのファイル情報エントリへの インデックスを返します。 *---------------------------------------------------------------------------*/ s32 FindNameResource( ARCHandle* pArcHandle, const wchar_t* resName ) { s32 entryNum = -1; ARCDir dir; bool bSuccess = ARCOpenDir(pArcHandle, L".", &dir); NW_UNUSED_VARIABLE(bSuccess); NW_ASSERT(bSuccess); ARCDirEntry dirEntry; while (ARCReadDir(&dir, &dirEntry)) { if (dirEntry.isDir) { bSuccess = ARCChangeDir(pArcHandle, dirEntry.name); NW_ASSERT(bSuccess); entryNum = FindNameResource(pArcHandle, resName); bSuccess = ARCChangeDir(pArcHandle, L".."); NW_ASSERT(bSuccess); if (entryNum != -1) { break; } } else { if (wcsicmp(resName, dirEntry.name) == 0) { entryNum = s32(dirEntry.entryNum); break; } } } bSuccess = ARCCloseDir(&dir); NW_ASSERT(bSuccess); return entryNum; } void* GetResourceSub( ARCHandle* pArcHandle, const wchar_t* resRootDir, nw::lyt::ResType resType, const wchar_t* name, u32* pSize ) { s32 entryNum = -1; if (-1 != ARCConvertPathToEntrynum(pArcHandle, resRootDir)) { if (ARCChangeDir(pArcHandle, resRootDir)) // リソースのルートディレクトリに移動 { if (resType == 0) // リソースタイプが省略されている場合 { entryNum = FindNameResource(pArcHandle, name); } else // リソースタイプが指定されている場合 { wchar_t resTypeStr[5]; resTypeStr[0] = u8(resType >> 24); resTypeStr[1] = u8(resType >> 16); resTypeStr[2] = u8(resType >> 8); resTypeStr[3] = u8(resType >> 0); resTypeStr[4] = 0; if (-1 != ARCConvertPathToEntrynum(pArcHandle, resTypeStr)) { if (ARCChangeDir(pArcHandle, resTypeStr)) { entryNum = ARCConvertPathToEntrynum(pArcHandle, name); bool bSuccess = ARCChangeDir(pArcHandle, L".."); // 元に戻す NW_ASSERT(bSuccess); } } } bool bSuccess = ARCChangeDir(pArcHandle, L".."); // 元に戻す NW_ASSERT(bSuccess); } } if (entryNum != -1) { ARCFileInfo arcFileInfo; bool bSuccess = ARCFastOpen(pArcHandle, entryNum, &arcFileInfo); NW_ASSERT(bSuccess); void* resPtr = ARCGetStartAddrInMem(&arcFileInfo); if (pSize) { *pSize = ARCGetLength(&arcFileInfo); } ARCClose(&arcFileInfo); return resPtr; } return NULL; } } // namespace ArcResourceAccessor::ArcResourceAccessor() : m_ArcBuf(0) { } bool ArcResourceAccessor::Attach( void* archiveStart, const char* resourceRootDirectory ) { NW_ASSERT(! IsAttached()); NW_NULL_ASSERT(archiveStart); NW_NULL_ASSERT(resourceRootDirectory); bool bSuccess = ARCInitHandle(archiveStart, &m_ArcHandle); if (! bSuccess) { return false; } m_ArcBuf = archiveStart; // ルートディレクトリ文字列のコピー const int dstBufCount = sizeof(m_ResRootDir) / sizeof(m_ResRootDir[0]); strncpy(m_ResRootDir, dstBufCount, resourceRootDirectory); return true; } void* ArcResourceAccessor::Detach() { NW_ASSERT(IsAttached()); void* ret = m_ArcBuf; m_ArcBuf = 0; return ret; } void* ArcResourceAccessor::GetResource( ResType resType, const char* name, u32* pSize ) { const int dstBufCount = sizeof(m_ResNameWork) / sizeof(m_ResNameWork[0]); strncpy(m_ResNameWork, dstBufCount, name); return GetResourceSub(&m_ArcHandle, m_ResRootDir, resType, m_ResNameWork, pSize); } bool ArcResourceLink::Set( void* archiveStart, const char* resourceRootDirectory ) { NW_NULL_ASSERT(archiveStart); NW_NULL_ASSERT(resourceRootDirectory); bool bSuccess = ARCInitHandle(archiveStart, &m_ArcHandle); if (! bSuccess) { return false; } // ルートディレクトリ文字列のコピー const int dstBufCount = sizeof(m_ResRootDir) / sizeof(m_ResRootDir[0]); strncpy(m_ResRootDir, dstBufCount, resourceRootDirectory); return true; } const void* ArcResourceLink::GetArchiveDataStart() const { return m_ArcHandle.archiveStartAddr; } font::Font* ArcResourceAccessor::GetFont(const char *name) { font::Font* pFont = m_FontList.FindFontByName(name); if (pFont == NULL) { pFont = this->LoadFont(name); if (pFont != NULL) { (void)m_FontList.RegistFont(name, pFont, true); } } return pFont; } FontKey ArcResourceAccessor::RegistFont(const char* name, font::Font* pFont) { return m_FontList.RegistFont(name, pFont, false); } void ArcResourceAccessor::UnregistFont(FontKey key) { m_FontList.UnregistFont(key); } const TextureInfo ArcResourceAccessor::GetTexture(const char *name) { TextureInfo texInfo = m_TextureList.FindTextureByName(name); if (texInfo.IsValid()) { return texInfo; } else { texInfo = this->LoadTexture(name); if (texInfo.IsValid()) { (void) m_TextureList.RegistTexture(name, texInfo); } return texInfo; } } TextureKey ArcResourceAccessor::RegistTexture(const char* name, const TextureInfo& textureInfo) { return m_TextureList.RegistTexture(name, textureInfo); } void ArcResourceAccessor::UnregistTexture(TextureKey key) { m_TextureList.UnregistTexture(key); } MultiArcResourceAccessor::MultiArcResourceAccessor() { } MultiArcResourceAccessor::~MultiArcResourceAccessor() { DetachAll(); } void MultiArcResourceAccessor::Attach(ArcResourceLink* pLink) { NW_NULL_ASSERT(pLink); m_ArcList.PushBack(pLink); } ArcResourceLink* MultiArcResourceAccessor::Detach(const void* archiveStart) { NW_NULL_ASSERT(archiveStart); for (internal::ArcResourceList::Iterator it = m_ArcList.GetBeginIter(); it != m_ArcList.GetEndIter(); ++it) { if (archiveStart == it->GetArchiveDataStart()) { ArcResourceLink* ret = &(*it); m_ArcList.Erase(it); return ret; } } return 0; } void MultiArcResourceAccessor::Detach(ArcResourceLink* pLink) { NW_NULL_ASSERT(pLink); m_ArcList.Erase(pLink); } void MultiArcResourceAccessor::DetachAll() { m_ArcList.Clear(); } void* MultiArcResourceAccessor::GetResource( ResType resType, const char* name, u32* pSize ) { const int dstBufCount = sizeof(m_ResNameWork) / sizeof(m_ResNameWork[0]); strncpy(m_ResNameWork, dstBufCount, name); for (internal::ArcResourceList::Iterator it = m_ArcList.GetBeginIter(); it != m_ArcList.GetEndIter(); ++it) { ARCHandle* pArcHandle = it->GetArcHandle(); if (void* resPtr = GetResourceSub(pArcHandle, it->GetResRootDir(), resType, m_ResNameWork, pSize)) { return resPtr; } } return NULL; } font::Font* MultiArcResourceAccessor::GetFont(const char *name) { font::Font* pFont = m_FontList.FindFontByName(name); if (pFont == NULL) { pFont = this->LoadFont(name); if (pFont != NULL) { (void)m_FontList.RegistFont(name, pFont, true); } } return pFont; } FontKey MultiArcResourceAccessor::RegistFont(const char* name, font::Font* pFont) { return m_FontList.RegistFont(name, pFont, false); } void MultiArcResourceAccessor::UnregistFont(FontKey key) { m_FontList.UnregistFont(key); } const TextureInfo MultiArcResourceAccessor::GetTexture(const char *name) { TextureInfo texInfo = m_TextureList.FindTextureByName(name); if (texInfo.IsValid()) { return texInfo; } else { texInfo = this->LoadTexture(name); if (texInfo.IsValid()) { (void) m_TextureList.RegistTexture(name, texInfo); } return texInfo; } } TextureKey MultiArcResourceAccessor::RegistTexture(const char* name, const TextureInfo& textureInfo) { return m_TextureList.RegistTexture(name, textureInfo); } void MultiArcResourceAccessor::UnregistTexture(TextureKey key) { m_TextureList.UnregistTexture(key); } } // namespace lyt } // namespace nw