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