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