1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     lyt_ArcResourceAccessor.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: 25196 $
14  *---------------------------------------------------------------------------*/
15 
16 #include "precompiled.h"
17 #include <nw/lyt/lyt_ArcResourceAccessor.h>
18 #include <nw/lyt/lyt_Resources.h>
19 #include <cctype>
20 #include <cwchar>
21 
22 namespace nw
23 {
24 namespace lyt
25 {
26 
27 namespace
28 {
29 
30 /*!--------------------------------------------------------------------------*
31   @brief        文字列を小文字として比較します。
32 
33   @param[in]    string1 比較対象の文字列です。
34   @param[in]    string2 比較対象の文字列です。
35 
36   @return       比較結果を返します。
37  *---------------------------------------------------------------------------*/
38 inline
39 int
wcsicmp(const wchar_t * string1,const wchar_t * string2)40 wcsicmp(
41     const wchar_t *string1,
42     const wchar_t *string2)
43 {
44 #ifdef NW_COMPILER_MSVC
45     return ::_wcsicmp(string1, string2);
46 #else
47     return std::wcscasecmp(string1, string2);
48 #endif
49 }
50 
51 /*!--------------------------------------------------------------------------*
52   @brief        文字列をコピーします。
53 
54                 src 文字列を コピーし、必ず nul の終端文字を追加します。
55                 destCount が src文字列の長さより小さい場合は切り詰めてコピーされますが、
56                 必ず nul 終端文字が挿入されます。
57 
58   @tparam       文字の型です。
59 
60   @param[in]    dest コピー先のバッファのアドレスです。
61   @param[in]    destCount コピー先のバッファサイズです。
62   @param[in]    src コピー元の文字列のアドレスです。
63 
64   @return       コピーした文字数を返します。
65  *---------------------------------------------------------------------------*/
66 size_t
strncpy(wchar_t * dest,std::size_t destCount,const char * src)67 strncpy(
68     wchar_t*        dest,
69     std::size_t     destCount,
70     const char*     src
71 )
72 {
73     NW_ASSERT(destCount > 0);
74 
75     --destCount;    // 終端文字分減らす
76     size_t length = 0;
77     while (length < destCount && *src != '\0')
78     {
79         *dest = *src;
80         ++dest;
81         ++src;
82         ++length;
83     }
84 
85     *dest = L'\0';
86 
87     return length;
88 }
89 
90 
91 /*---------------------------------------------------------------------------*
92   @brief 指定されたリソース名を持つリソースをファイル情報テーブルから
93   探し出します。
94 
95   @param pArcHandle ARCHandleオブジェクトへのポインタ。
96   @param resName リソース名へのポインタ。
97 
98   @return リソースが見つかれば、そのリソースのファイル情報エントリへの
99   インデックスを返します。
100  *---------------------------------------------------------------------------*/
101 s32
FindNameResource(ARCHandle * pArcHandle,const wchar_t * resName)102 FindNameResource(
103     ARCHandle* pArcHandle,
104     const wchar_t* resName
105 )
106 {
107     s32 entryNum = -1;
108 
109     ARCDir          dir;
110     bool bSuccess = ARCOpenDir(pArcHandle, L".", &dir);
111     NW_UNUSED_VARIABLE(bSuccess);
112     NW_ASSERT(bSuccess);
113 
114     ARCDirEntry     dirEntry;
115 
116     while (ARCReadDir(&dir, &dirEntry))
117     {
118         if (dirEntry.isDir)
119         {
120             bSuccess = ARCChangeDir(pArcHandle, dirEntry.name);
121             NW_ASSERT(bSuccess);
122             entryNum = FindNameResource(pArcHandle, resName);
123             bSuccess = ARCChangeDir(pArcHandle, L"..");
124             NW_ASSERT(bSuccess);
125             if (entryNum != -1)
126             {
127                 break;
128             }
129         }
130         else
131         {
132             if (wcsicmp(resName, dirEntry.name) == 0)
133             {
134                 entryNum = s32(dirEntry.entryNum);
135                 break;
136             }
137         }
138     }
139 
140     bSuccess = ARCCloseDir(&dir);
141     NW_ASSERT(bSuccess);
142 
143     return entryNum;
144 }
145 
146 void*
GetResourceSub(ARCHandle * pArcHandle,const wchar_t * resRootDir,nw::lyt::ResType resType,const wchar_t * name,u32 * pSize)147 GetResourceSub(
148     ARCHandle* pArcHandle,
149     const wchar_t* resRootDir,
150     nw::lyt::ResType resType,
151     const wchar_t* name,
152     u32* pSize
153 )
154 {
155     s32 entryNum = -1;
156 
157     if (-1 != ARCConvertPathToEntrynum(pArcHandle, resRootDir))
158     {
159         if (ARCChangeDir(pArcHandle, resRootDir)) // リソースのルートディレクトリに移動
160         {
161             if (resType == 0)   // リソースタイプが省略されている場合
162             {
163                 entryNum = FindNameResource(pArcHandle, name);
164             }
165             else                // リソースタイプが指定されている場合
166             {
167                 wchar_t resTypeStr[5];
168                 resTypeStr[0] = u8(resType >> 24);
169                 resTypeStr[1] = u8(resType >> 16);
170                 resTypeStr[2] = u8(resType >>  8);
171                 resTypeStr[3] = u8(resType >>  0);
172                 resTypeStr[4] = 0;
173 
174                 if (-1 != ARCConvertPathToEntrynum(pArcHandle, resTypeStr))
175                 {
176                     if (ARCChangeDir(pArcHandle, resTypeStr))
177                     {
178                         entryNum = ARCConvertPathToEntrynum(pArcHandle, name);
179 
180                         bool bSuccess = ARCChangeDir(pArcHandle, L"..");    // 元に戻す
181                         NW_ASSERT(bSuccess);
182                     }
183                 }
184             }
185 
186             bool bSuccess = ARCChangeDir(pArcHandle, L"..");    // 元に戻す
187             NW_ASSERT(bSuccess);
188         }
189     }
190 
191     if (entryNum != -1)
192     {
193         ARCFileInfo arcFileInfo;
194         bool bSuccess = ARCFastOpen(pArcHandle, entryNum, &arcFileInfo);
195         NW_ASSERT(bSuccess);
196         void* resPtr = ARCGetStartAddrInMem(&arcFileInfo);
197         if (pSize)
198         {
199             *pSize = ARCGetLength(&arcFileInfo);
200         }
201         ARCClose(&arcFileInfo);
202 
203         return resPtr;
204     }
205 
206     return NULL;
207 }
208 
209 }   // namespace
210 
ArcResourceAccessor()211 ArcResourceAccessor::ArcResourceAccessor()
212 :   m_ArcBuf(0)
213 {
214 }
215 
216 bool
Attach(void * archiveStart,const char * resourceRootDirectory)217 ArcResourceAccessor::Attach(
218     void*       archiveStart,
219     const char* resourceRootDirectory
220 )
221 {
222     NW_ASSERT(! IsAttached());
223     NW_NULL_ASSERT(archiveStart);
224     NW_NULL_ASSERT(resourceRootDirectory);
225 
226     bool bSuccess = ARCInitHandle(archiveStart, &m_ArcHandle);
227     if (! bSuccess)
228     {
229         return false;
230     }
231 
232     m_ArcBuf = archiveStart;
233     // ルートディレクトリ文字列のコピー
234     const int dstBufCount = sizeof(m_ResRootDir) / sizeof(m_ResRootDir[0]);
235     strncpy(m_ResRootDir, dstBufCount, resourceRootDirectory);
236 
237     return true;
238 }
239 
240 void*
Detach()241 ArcResourceAccessor::Detach()
242 {
243     NW_ASSERT(IsAttached());
244 
245     void* ret = m_ArcBuf;
246     m_ArcBuf = 0;
247     return ret;
248 }
249 
250 void*
GetResource(ResType resType,const char * name,u32 * pSize)251 ArcResourceAccessor::GetResource(
252     ResType     resType,
253     const char* name,
254     u32*        pSize
255 )
256 {
257     const int dstBufCount = sizeof(m_ResNameWork) / sizeof(m_ResNameWork[0]);
258     strncpy(m_ResNameWork, dstBufCount, name);
259     return GetResourceSub(&m_ArcHandle, m_ResRootDir, resType, m_ResNameWork, pSize);
260 }
261 
262 bool
Set(void * archiveStart,const char * resourceRootDirectory)263 ArcResourceLink::Set(
264     void*       archiveStart,
265     const char* resourceRootDirectory
266 )
267 {
268     NW_NULL_ASSERT(archiveStart);
269     NW_NULL_ASSERT(resourceRootDirectory);
270 
271     bool bSuccess = ARCInitHandle(archiveStart, &m_ArcHandle);
272     if (! bSuccess)
273     {
274         return false;
275     }
276 
277     // ルートディレクトリ文字列のコピー
278     const int dstBufCount = sizeof(m_ResRootDir) / sizeof(m_ResRootDir[0]);
279     strncpy(m_ResRootDir, dstBufCount, resourceRootDirectory);
280 
281     return true;
282 }
283 
284 const void*
GetArchiveDataStart() const285 ArcResourceLink::GetArchiveDataStart() const
286 {
287     return m_ArcHandle.archiveStartAddr;
288 }
289 
290 font::Font*
GetFont(const char * name)291 ArcResourceAccessor::GetFont(const char *name)
292 {
293     font::Font* pFont = m_FontList.FindFontByName(name);
294 
295     if (pFont == NULL)
296     {
297         pFont = this->LoadFont(name);
298 
299         if (pFont != NULL)
300         {
301             (void)m_FontList.RegistFont(name, pFont, true);
302         }
303     }
304 
305     return pFont;
306 }
307 
308 FontKey
RegistFont(const char * name,font::Font * pFont)309 ArcResourceAccessor::RegistFont(const char* name, font::Font* pFont)
310 {
311     return m_FontList.RegistFont(name, pFont, false);
312 }
313 
314 void
UnregistFont(FontKey key)315 ArcResourceAccessor::UnregistFont(FontKey key)
316 {
317     m_FontList.UnregistFont(key);
318 }
319 
320 const TextureInfo
GetTexture(const char * name)321 ArcResourceAccessor::GetTexture(const char *name)
322 {
323     TextureInfo texInfo = m_TextureList.FindTextureByName(name);
324     if (texInfo.IsValid())
325     {
326         return texInfo;
327     }
328     else
329     {
330         texInfo = this->LoadTexture(name);
331 
332         if (texInfo.IsValid())
333         {
334             (void) m_TextureList.RegistTexture(name, texInfo);
335         }
336 
337         return texInfo;
338     }
339 }
340 
341 TextureKey
RegistTexture(const char * name,const TextureInfo & textureInfo)342 ArcResourceAccessor::RegistTexture(const char* name, const TextureInfo& textureInfo)
343 {
344     return m_TextureList.RegistTexture(name, textureInfo);
345 }
346 
347 void
UnregistTexture(TextureKey key)348 ArcResourceAccessor::UnregistTexture(TextureKey key)
349 {
350     m_TextureList.UnregistTexture(key);
351 }
352 
MultiArcResourceAccessor()353 MultiArcResourceAccessor::MultiArcResourceAccessor()
354 {
355 }
356 
~MultiArcResourceAccessor()357 MultiArcResourceAccessor::~MultiArcResourceAccessor()
358 {
359     DetachAll();
360 }
361 
362 void
Attach(ArcResourceLink * pLink)363 MultiArcResourceAccessor::Attach(ArcResourceLink* pLink)
364 {
365     NW_NULL_ASSERT(pLink);
366 
367     m_ArcList.PushBack(pLink);
368 }
369 
370 ArcResourceLink*
Detach(const void * archiveStart)371 MultiArcResourceAccessor::Detach(const void* archiveStart)
372 {
373     NW_NULL_ASSERT(archiveStart);
374 
375     for (internal::ArcResourceList::Iterator it = m_ArcList.GetBeginIter(); it != m_ArcList.GetEndIter(); ++it)
376     {
377         if (archiveStart == it->GetArchiveDataStart())
378         {
379             ArcResourceLink* ret = &(*it);
380             m_ArcList.Erase(it);
381             return ret;
382         }
383     }
384 
385     return 0;
386 }
387 
388 void
Detach(ArcResourceLink * pLink)389 MultiArcResourceAccessor::Detach(ArcResourceLink* pLink)
390 {
391     NW_NULL_ASSERT(pLink);
392 
393     m_ArcList.Erase(pLink);
394 }
395 
396 void
DetachAll()397 MultiArcResourceAccessor::DetachAll()
398 {
399     m_ArcList.Clear();
400 }
401 
402 void*
GetResource(ResType resType,const char * name,u32 * pSize)403 MultiArcResourceAccessor::GetResource(
404     ResType     resType,
405     const char* name,
406     u32*        pSize
407 )
408 {
409     const int dstBufCount = sizeof(m_ResNameWork) / sizeof(m_ResNameWork[0]);
410     strncpy(m_ResNameWork, dstBufCount, name);
411 
412     for (internal::ArcResourceList::Iterator it = m_ArcList.GetBeginIter(); it != m_ArcList.GetEndIter(); ++it)
413     {
414         ARCHandle* pArcHandle = it->GetArcHandle();
415         if (void* resPtr = GetResourceSub(pArcHandle, it->GetResRootDir(), resType, m_ResNameWork, pSize))
416         {
417             return resPtr;
418         }
419     }
420 
421     return NULL;
422 }
423 
424 font::Font*
GetFont(const char * name)425 MultiArcResourceAccessor::GetFont(const char *name)
426 {
427     font::Font* pFont = m_FontList.FindFontByName(name);
428 
429     if (pFont == NULL)
430     {
431         pFont = this->LoadFont(name);
432 
433         if (pFont != NULL)
434         {
435             (void)m_FontList.RegistFont(name, pFont, true);
436         }
437     }
438 
439     return pFont;
440 }
441 
442 FontKey
RegistFont(const char * name,font::Font * pFont)443 MultiArcResourceAccessor::RegistFont(const char* name, font::Font* pFont)
444 {
445     return m_FontList.RegistFont(name, pFont, false);
446 }
447 
448 void
UnregistFont(FontKey key)449 MultiArcResourceAccessor::UnregistFont(FontKey key)
450 {
451     m_FontList.UnregistFont(key);
452 }
453 
454 const TextureInfo
GetTexture(const char * name)455 MultiArcResourceAccessor::GetTexture(const char *name)
456 {
457     TextureInfo texInfo = m_TextureList.FindTextureByName(name);
458     if (texInfo.IsValid())
459     {
460         return texInfo;
461     }
462     else
463     {
464         texInfo = this->LoadTexture(name);
465 
466         if (texInfo.IsValid())
467         {
468             (void) m_TextureList.RegistTexture(name, texInfo);
469         }
470 
471         return texInfo;
472     }
473 }
474 
475 TextureKey
RegistTexture(const char * name,const TextureInfo & textureInfo)476 MultiArcResourceAccessor::RegistTexture(const char* name, const TextureInfo& textureInfo)
477 {
478     return m_TextureList.RegistTexture(name, textureInfo);
479 }
480 
481 void
UnregistTexture(TextureKey key)482 MultiArcResourceAccessor::UnregistTexture(TextureKey key)
483 {
484     m_TextureList.UnregistTexture(key);
485 }
486 
487 }   // namespace lyt
488 }   // namespace nw
489