1 /*
2  * HLLib
3  * Copyright (C) 2006-2010 Ryan Gregg
4 
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later
9  * version.
10  */
11 
12 #include "HLLib.h"
13 #include "WADFile.h"
14 #include "Streams.h"
15 
16 using namespace HLLib;
17 
18 const char *CWADFile::lpAttributeNames[] = { "Version" };
19 const char *CWADFile::lpItemAttributeNames[] = { "Width", "Height", "Palette Entries", "Mipmaps", "Compressed", "Type" };
20 
CWADFile()21 CWADFile::CWADFile() : CPackage(), pHeaderView(0), pLumpView(0), pHeader(0), lpLumps(0), lpLumpInfo(0)
22 {
23 
24 }
25 
~CWADFile()26 CWADFile::~CWADFile()
27 {
28 	this->Close();
29 }
30 
GetType() const31 HLPackageType CWADFile::GetType() const
32 {
33 	return HL_PACKAGE_WAD;
34 }
35 
GetExtension() const36 const hlChar *CWADFile::GetExtension() const
37 {
38 	return "wad";
39 }
40 
GetDescription() const41 const hlChar *CWADFile::GetDescription() const
42 {
43 	return "Half-Life Texture Package File";
44 }
45 
MapDataStructures()46 hlBool CWADFile::MapDataStructures()
47 {
48 	if(sizeof(WADHeader) > this->pMapping->GetMappingSize())
49 	{
50 		LastError.SetErrorMessage("Invalid file: the file map is too small for it's header.");
51 		return hlFalse;
52 	}
53 
54 	if(!this->pMapping->Map(this->pHeaderView, 0, sizeof(WADHeader)))
55 	{
56 		return hlFalse;
57 	}
58 	this->pHeader = (WADHeader *)this->pHeaderView->GetView();
59 
60 	if(memcmp(this->pHeader->lpSignature, "WAD3", 4) != 0)
61 	{
62 		LastError.SetErrorMessage("Invalid file: the file's signature does not match.");
63 		return hlFalse;
64 	}
65 
66 	if(!this->pMapping->Map(this->pLumpView, this->pHeader->uiLumpOffset, this->pHeader->uiLumpCount * sizeof(WADLump)))
67 	{
68 		return hlFalse;
69 	}
70 	this->lpLumps = (WADLump *)this->pLumpView->GetView();
71 
72 	this->lpLumpInfo = new WADLumpInfo[this->pHeader->uiLumpCount];
73 	memset(this->lpLumpInfo, 0, sizeof(WADLumpInfo) * this->pHeader->uiLumpCount);
74 
75 	return hlTrue;
76 }
77 
UnmapDataStructures()78 hlVoid CWADFile::UnmapDataStructures()
79 {
80 	delete []this->lpLumpInfo;
81 
82 	this->lpLumps = 0;
83 	this->pMapping->Unmap(this->pLumpView);
84 
85 	this->pHeader = 0;
86 	this->pMapping->Unmap(this->pHeaderView);
87 }
88 
CreateRoot()89 CDirectoryFolder *CWADFile::CreateRoot()
90 {
91 	CDirectoryFolder *pRoot = new CDirectoryFolder(this);
92 
93 	// Loop through each lump in the WAD file.
94 	for(hlUInt i = 0; i < this->pHeader->uiLumpCount; i++)
95 	{
96 		hlChar lpName[64];
97 		sprintf(lpName, "%s.bmp", this->lpLumps[i].lpName);
98 
99 		// Add the lump as a bitmap.
100 		pRoot->AddFile(lpName, i);
101 	}
102 
103 	return pRoot;
104 }
105 
GetAttributeCountInternal() const106 hlUInt CWADFile::GetAttributeCountInternal() const
107 {
108 	return HL_WAD_PACKAGE_COUNT;
109 }
110 
GetAttributeNameInternal(HLPackageAttribute eAttribute) const111 const hlChar *CWADFile::GetAttributeNameInternal(HLPackageAttribute eAttribute) const
112 {
113 	if(eAttribute < HL_WAD_PACKAGE_COUNT)
114 	{
115 		return this->lpAttributeNames[eAttribute];
116 	}
117 
118 	return 0;
119 }
120 
GetAttributeInternal(HLPackageAttribute eAttribute,HLAttribute & Attribute) const121 hlBool CWADFile::GetAttributeInternal(HLPackageAttribute eAttribute, HLAttribute &Attribute) const
122 {
123 	switch(eAttribute)
124 	{
125 	case HL_WAD_PACKAGE_VERSION:
126 		hlAttributeSetUnsignedInteger(&Attribute, this->lpAttributeNames[eAttribute], this->pHeader->lpSignature[3] - '0', hlFalse);
127 		return hlTrue;
128 	default:
129 		return hlFalse;
130 	}
131 }
132 
GetItemAttributeCountInternal() const133 hlUInt CWADFile::GetItemAttributeCountInternal() const
134 {
135 	return HL_WAD_ITEM_COUNT;
136 }
137 
GetItemAttributeNameInternal(HLPackageAttribute eAttribute) const138 const hlChar *CWADFile::GetItemAttributeNameInternal(HLPackageAttribute eAttribute) const
139 {
140 	if(eAttribute < HL_WAD_ITEM_COUNT)
141 	{
142 		return this->lpItemAttributeNames[eAttribute];
143 	}
144 
145 	return 0;
146 }
147 
GetItemAttributeInternal(const CDirectoryItem * pItem,HLPackageAttribute eAttribute,HLAttribute & Attribute) const148 hlBool CWADFile::GetItemAttributeInternal(const CDirectoryItem *pItem, HLPackageAttribute eAttribute, HLAttribute &Attribute) const
149 {
150 	switch(pItem->GetType())
151 	{
152 		case HL_ITEM_FILE:
153 		{
154 			const CDirectoryFile *pFile = static_cast<const CDirectoryFile *>(pItem);
155 			const WADLump *pLump = this->lpLumps + pFile->GetID();
156 			switch(eAttribute)
157 			{
158 				case HL_WAD_ITEM_WIDTH:
159 				{
160 					hlUInt uiWidth = 0, uiHeight = 0, uiPaletteSize = 0;
161 					this->GetLumpInfo(*pFile, uiWidth, uiHeight, uiPaletteSize);
162 					hlAttributeSetUnsignedInteger(&Attribute, this->lpItemAttributeNames[eAttribute], uiWidth, hlFalse);
163 					return hlTrue;
164 				}
165 				case HL_WAD_ITEM_HEIGHT:
166 				{
167 					hlUInt uiWidth = 0, uiHeight = 0, uiPaletteSize = 0;
168 					this->GetLumpInfo(*pFile, uiWidth, uiHeight, uiPaletteSize);
169 					hlAttributeSetUnsignedInteger(&Attribute, this->lpItemAttributeNames[eAttribute], uiHeight, hlFalse);
170 					return hlTrue;
171 				}
172 				case HL_WAD_ITEM_PALETTE_ENTRIES:
173 				{
174 					hlUInt uiWidth = 0, uiHeight = 0, uiPaletteSize = 0;
175 					this->GetLumpInfo(*pFile, uiWidth, uiHeight, uiPaletteSize);
176 					hlAttributeSetUnsignedInteger(&Attribute, this->lpItemAttributeNames[eAttribute], uiPaletteSize, hlFalse);
177 					return hlTrue;
178 				}
179 				case HL_WAD_ITEM_MIPMAPS:
180 				{
181 					hlUInt uiMipmaps = 0;
182 					if(pLump->iType == 0x42)
183 					{
184 						uiMipmaps = 1;
185 					}
186 					else if(pLump->iType == 0x43)
187 					{
188 						uiMipmaps = 4;
189 					}
190 					hlAttributeSetUnsignedInteger(&Attribute, this->lpItemAttributeNames[eAttribute], uiMipmaps, hlFalse);
191 					return hlTrue;
192 				}
193 				case HL_WAD_ITEM_COMPRESSED:
194 				{
195 					hlAttributeSetBoolean(&Attribute, this->lpItemAttributeNames[eAttribute], pLump->iCompression != 0);
196 					return hlTrue;
197 				}
198 				case HL_WAD_ITEM_TYPE:
199 				{
200 					hlAttributeSetUnsignedInteger(&Attribute, this->lpItemAttributeNames[eAttribute], (hlUInt)pLump->iType, hlTrue);
201 					return hlTrue;
202 				}
203 			}
204 			break;
205 		}
206 	}
207 
208 	return hlFalse;
209 }
210 
GetFileExtractableInternal(const CDirectoryFile * pFile,hlBool & bExtractable) const211 hlBool CWADFile::GetFileExtractableInternal(const CDirectoryFile *pFile, hlBool &bExtractable) const
212 {
213 	const WADLump *pLump = this->lpLumps + pFile->GetID();
214 
215 	bExtractable = (pLump->iType == 0x42 || pLump->iType == 0x43) && pLump->iCompression == 0;
216 
217 	return hlTrue;
218 }
219 
GetFileSizeInternal(const CDirectoryFile * pFile,hlUInt & uiSize) const220 hlBool CWADFile::GetFileSizeInternal(const CDirectoryFile *pFile, hlUInt &uiSize) const
221 {
222 	hlUInt uiWidth, uiHeight, uiPaletteSize;
223 	if(!const_cast<CWADFile *>(this)->GetLumpInfo(*pFile, uiWidth, uiHeight, uiPaletteSize))
224 	{
225 		return hlFalse;
226 	}
227 
228 	uiSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + uiPaletteSize * 4 + uiWidth * uiHeight;
229 
230 	return hlTrue;
231 }
232 
GetFileSizeOnDiskInternal(const CDirectoryFile * pFile,hlUInt & uiSize) const233 hlBool CWADFile::GetFileSizeOnDiskInternal(const CDirectoryFile *pFile, hlUInt &uiSize) const
234 {
235 	uiSize = this->lpLumps[pFile->GetID()].uiDiskLength;
236 
237 	return hlTrue;
238 }
239 
GetImageSize(const CDirectoryFile * pFile,hlUInt & uiPaletteDataSize,hlUInt & uiPixelDataSize)240 hlBool CWADFile::GetImageSize(const CDirectoryFile *pFile, hlUInt &uiPaletteDataSize, hlUInt &uiPixelDataSize)
241 {
242 	uiPaletteDataSize = uiPixelDataSize = 0;
243 
244 	if(!this->GetOpened() || pFile == 0 || pFile->GetPackage() != this)
245 	{
246 		LastError.SetErrorMessage("File does not belong to package.");
247 		return hlFalse;
248 	}
249 
250 	hlUInt uiWidth, uiHeight, uiPaletteSize;
251 	if(!const_cast<CWADFile *>(this)->GetLumpInfo(*pFile, uiWidth, uiHeight, uiPaletteSize))
252 	{
253 		return hlFalse;
254 	}
255 
256 	uiPaletteDataSize = uiPaletteSize * 3;
257 	uiPixelDataSize = uiWidth * uiHeight;
258 
259 	return hlTrue;
260 }
261 
GetImageData(const CDirectoryFile * pFile,hlUInt & uiWidth,hlUInt & uiHeight,hlByte * lpPaletteData,hlByte * lpPixelData)262 hlBool CWADFile::GetImageData(const CDirectoryFile *pFile, hlUInt &uiWidth, hlUInt &uiHeight, hlByte *lpPaletteData, hlByte *lpPixelData)
263 {
264 	uiWidth = uiHeight = 0;
265 
266 	if(!this->GetOpened() || pFile == 0 || pFile->GetPackage() != this)
267 	{
268 		LastError.SetErrorMessage("File does not belong to package.");
269 		return hlFalse;
270 	}
271 
272 	hlUInt uiPaletteSize;
273 	const hlByte *lpPalette, *lpPixels;
274 	Mapping::CView *pView = 0;
275 
276 	if(!const_cast<CWADFile *>(this)->GetLumpInfo(*pFile, uiWidth, uiHeight, uiPaletteSize, lpPalette, lpPixels, pView))
277 	{
278 		return hlFalse;
279 	}
280 
281 	memcpy(lpPaletteData, lpPalette, uiPaletteSize * 3);
282 	memcpy(lpPixelData, lpPixels, uiWidth * uiHeight);
283 
284 	this->pMapping->Unmap(pView);
285 
286 	return hlTrue;
287 }
288 
GetImageSize(const CDirectoryFile * pFile,hlUInt & uiPixelDataSize)289 hlBool CWADFile::GetImageSize(const CDirectoryFile *pFile, hlUInt &uiPixelDataSize)
290 {
291 	uiPixelDataSize = 0;
292 
293 	if(!this->GetOpened() || pFile == 0 || pFile->GetPackage() != this)
294 	{
295 		LastError.SetErrorMessage("File does not belong to package.");
296 		return hlFalse;
297 	}
298 
299 	hlUInt uiWidth, uiHeight, uiPaletteSize;
300 	if(!const_cast<CWADFile *>(this)->GetLumpInfo(*pFile, uiWidth, uiHeight, uiPaletteSize))
301 	{
302 		return hlFalse;
303 	}
304 
305 	uiPixelDataSize = uiWidth * uiHeight * 3;
306 
307 	return hlTrue;
308 }
309 
GetImageData(const CDirectoryFile * pFile,hlUInt & uiWidth,hlUInt & uiHeight,hlByte * lpPixelData)310 hlBool CWADFile::GetImageData(const CDirectoryFile *pFile, hlUInt &uiWidth, hlUInt &uiHeight, hlByte *lpPixelData)
311 {
312 	uiWidth = uiHeight = 0;
313 
314 	if(!this->GetOpened() || pFile == 0 || pFile->GetPackage() != this)
315 	{
316 		LastError.SetErrorMessage("File does not belong to package.");
317 		return hlFalse;
318 	}
319 
320 	hlUInt uiPaletteSize;
321 	const hlByte *lpPalette, *lpPixels;
322 	Mapping::CView *pView = 0;
323 
324 	if(!const_cast<CWADFile *>(this)->GetLumpInfo(*pFile, uiWidth, uiHeight, uiPaletteSize, lpPalette, lpPixels, pView))
325 	{
326 		return hlFalse;
327 	}
328 
329 	for(hlUInt i = 0; i < uiWidth; i++)
330 	{
331 		for(hlUInt j = 0; j < uiHeight; j++)
332 		{
333 			hlUInt uiPixelIndex = i + j * uiWidth;
334 			hlUInt uiPaletteIndex = (hlUInt)lpPixels[uiPixelIndex] * 3;
335 
336 			uiPixelIndex *= 3;
337 			lpPixelData[uiPixelIndex + 0] = lpPalette[uiPaletteIndex + 0];
338 			lpPixelData[uiPixelIndex + 1] = lpPalette[uiPaletteIndex + 1];
339 			lpPixelData[uiPixelIndex + 2] = lpPalette[uiPaletteIndex + 2];
340 		}
341 	}
342 
343 	this->pMapping->Unmap(pView);
344 
345 	return hlTrue;
346 }
347 
CreateStreamInternal(const CDirectoryFile * pFile,Streams::IStream * & pStream) const348 hlBool CWADFile::CreateStreamInternal(const CDirectoryFile *pFile, Streams::IStream *&pStream) const
349 {
350 	hlUInt uiWidth, uiHeight, uiPaletteSize;
351 	const hlByte *lpPalette, *lpPixels;
352 	Mapping::CView *pView = 0;
353 
354 	if(!const_cast<CWADFile *>(this)->GetLumpInfo(*pFile, uiWidth, uiHeight, uiPaletteSize, lpPalette, lpPixels, pView))
355 	{
356 		return hlFalse;
357 	}
358 
359 	hlUInt uiBufferSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + uiPaletteSize * 4 + uiWidth * uiHeight;
360 	hlByte *lpBuffer = new hlByte[uiBufferSize];
361 
362 	//
363 	// Allocate data.
364 	//
365 
366 	BITMAPFILEHEADER *pFileHeader = (BITMAPFILEHEADER *)lpBuffer;
367 	BITMAPINFOHEADER *pInfoHeader = (BITMAPINFOHEADER *)((hlByte *)pFileHeader + sizeof(BITMAPFILEHEADER));
368 	hlByte *lpPaletteData = (hlByte *)pInfoHeader + sizeof(BITMAPINFOHEADER);
369 	hlByte *lpPixelData = lpPaletteData + uiPaletteSize * 4;
370 
371 	memset(pFileHeader, 0, sizeof(BITMAPFILEHEADER));
372 	memset(pInfoHeader, 0, sizeof(BITMAPINFOHEADER));
373 
374 	//
375 	// Fill in headers.
376 	//
377 
378 	pFileHeader->bfType = ('M' << 8) | 'B';
379 	pFileHeader->bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + uiPaletteSize * 4 + uiWidth * uiHeight;
380 	pFileHeader->bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + uiPaletteSize * 4;
381 
382 	pInfoHeader->biSize = sizeof(BITMAPINFOHEADER);
383 	pInfoHeader->biWidth = uiWidth;
384 	pInfoHeader->biHeight = uiHeight;
385 	pInfoHeader->biPlanes = 1;
386 	pInfoHeader->biBitCount = 8;
387 	pInfoHeader->biSizeImage = 0;
388 	pInfoHeader->biClrUsed = uiPaletteSize;
389 	pInfoHeader->biClrImportant = uiPaletteSize;
390 
391 	//
392 	// Fill in Palette data.
393 	//
394 
395 	for(hlUInt i = 0; i < uiPaletteSize; i++)
396 	{
397 		lpPaletteData[i * 4 + 0] = lpPalette[i * 3 + 2];
398 		lpPaletteData[i * 4 + 1] = lpPalette[i * 3 + 1];
399 		lpPaletteData[i * 4 + 2] = lpPalette[i * 3 + 0];
400 		lpPaletteData[i * 4 + 3] = 0;
401 	}
402 
403 	//
404 	// Fill in Index data.
405 	//
406 
407 	for(hlUInt i = 0; i < uiWidth; i++)
408 	{
409 		for(hlUInt j = 0; j < uiHeight; j++)
410 		{
411 			lpPixelData[i + (uiHeight - 1 - j) * uiWidth] = lpPixels[i + j * uiWidth];
412 		}
413 	}
414 
415 	this->pMapping->Unmap(pView);
416 
417 	pStream = new Streams::CMemoryStream(lpBuffer, uiBufferSize);
418 
419 	return hlTrue;
420 }
421 
ReleaseStreamInternal(Streams::IStream & Stream) const422 hlVoid CWADFile::ReleaseStreamInternal(Streams::IStream &Stream) const
423 {
424 	delete [](hlByte *)static_cast<Streams::CMemoryStream &>(Stream).GetBuffer();
425 }
426 
GetLumpInfo(const CDirectoryFile & File,hlUInt & uiWidth,hlUInt & uiHeight,hlUInt & uiPaletteSize,hlUInt uiMipmap) const427 hlBool CWADFile::GetLumpInfo(const CDirectoryFile &File, hlUInt &uiWidth, hlUInt &uiHeight, hlUInt &uiPaletteSize, hlUInt uiMipmap) const
428 {
429 	const WADLump &Lump = this->lpLumps[File.GetID()];
430 
431 	if(Lump.iCompression)
432 	{
433 		LastError.SetErrorMessageFormated("Error reading lump: compression format %#.2x not supported.", Lump.iCompression);
434 		return hlFalse;
435 	}
436 
437 	if(Lump.iType == 0x42)
438 	{
439 		if(uiMipmap > 0)
440 		{
441 			LastError.SetErrorMessageFormated("Error reading lump: invalid mipmap level %u.", uiMipmap);
442 			return hlFalse;
443 		}
444 	}
445 	else if(Lump.iType == 0x43)
446 	{
447 		if(uiMipmap > 3)
448 		{
449 			LastError.SetErrorMessageFormated("Error reading lump: invalid mipmap level %u.", uiMipmap);
450 			return hlFalse;
451 		}
452 	}
453 	else
454 	{
455 		LastError.SetErrorMessageFormated("Error reading lump: lump type %#.2x not supported.", Lump.iType);
456 		return hlFalse;
457 	}
458 
459 	WADLumpInfo &Info = this->lpLumpInfo[File.GetID()];
460 
461 	if(Info.uiWidth && Info.uiHeight && Info.uiPaletteSize)
462 	{
463 		uiWidth = Info.uiWidth;
464 		uiHeight = Info.uiHeight;
465 		uiPaletteSize = Info.uiPaletteSize;
466 	}
467 	else
468 	{
469 		Mapping::CView *pView = 0;
470 
471 		if(!this->pMapping->Map(pView, Lump.uiOffset, Lump.uiDiskLength))
472 		{
473 			return hlFalse;
474 		}
475 
476 		hlByte *lpData = (hlByte *)pView->GetView();
477 
478 		// Type 0x42 has no name, type 0x43 does.  Are these flags?
479 		if(Lump.iType == 0x42)
480 		{
481 			// Get Width.
482 			uiWidth = *(hlUInt *)lpData;
483 			lpData += 4;
484 
485 			// Get Height.
486 			uiHeight = *(hlUInt *)lpData;
487 			lpData += 4;
488 
489 			// Scan past pixel data.
490 			lpData += (uiWidth * uiHeight);
491 
492 			// Get palette size.
493 			uiPaletteSize = (hlUInt)(*(hlUInt16 *)lpData);
494 		}
495 		else if(Lump.iType == 0x43)
496 		{
497 			// Scan past name.
498 			lpData += 16;
499 
500 			// Get Width.
501 			uiWidth = *(hlUInt *)lpData;
502 			lpData += 4;
503 
504 			// Get Height.
505 			uiHeight = *(hlUInt *)lpData;
506 			lpData += 4;
507 
508 			// Scan past pixel offset.
509 			lpData += 16;
510 
511 			hlUInt uiPixelSize = uiWidth * uiHeight;
512 
513 			switch(uiMipmap)
514 			{
515 			case 1:
516 				lpData += (uiPixelSize);
517 				break;
518 			case 2:
519 				lpData += (uiPixelSize) + (uiPixelSize / 4);
520 				break;
521 			case 3:
522 				lpData += (uiPixelSize) + (uiPixelSize / 4) + (uiPixelSize / 16);
523 				break;
524 			}
525 
526 			// Scan past data.
527 			lpData += (uiPixelSize) + (uiPixelSize / 4) + (uiPixelSize / 16) + (uiPixelSize / 64);
528 
529 			// Get palette size.
530 			uiPaletteSize = (hlUInt)(*(hlUInt16 *)lpData);
531 		}
532 
533 		this->pMapping->Unmap(pView);
534 
535 		Info.uiWidth = uiWidth;
536 		Info.uiHeight = uiHeight;
537 		Info.uiPaletteSize = uiPaletteSize;
538 	}
539 
540 	switch(uiMipmap)
541 	{
542 	case 1:
543 		uiWidth /= 2;
544 		uiHeight /= 2;
545 		break;
546 	case 2:
547 		uiWidth /= 4;
548 		uiHeight /= 4;
549 		break;
550 	case 3:
551 		uiWidth /= 8;
552 		uiHeight /= 8;
553 		break;
554 	}
555 
556 	return hlTrue;
557 }
558 
GetLumpInfo(const CDirectoryFile & File,hlUInt & uiWidth,hlUInt & uiHeight,hlUInt & uiPaletteSize,const hlByte * & lpPalette,const hlByte * & lpPixels,Mapping::CView * & pView,hlUInt uiMipmap) const559 hlBool CWADFile::GetLumpInfo(const CDirectoryFile &File, hlUInt &uiWidth, hlUInt &uiHeight, hlUInt &uiPaletteSize, const hlByte *&lpPalette, const hlByte *&lpPixels, Mapping::CView *&pView, hlUInt uiMipmap) const
560 {
561 	const WADLump &Lump = this->lpLumps[File.GetID()];
562 
563 	pView = 0;
564 
565 	if(Lump.iCompression)
566 	{
567 		LastError.SetErrorMessageFormated("Error reading lump: compression format %#.2x not supported.", Lump.iCompression);
568 		return hlFalse;
569 	}
570 
571 	if(Lump.iType == 0x42)
572 	{
573 		if(uiMipmap > 0)
574 		{
575 			LastError.SetErrorMessageFormated("Error reading lump: invalid mipmap level %u.", uiMipmap);
576 			return hlFalse;
577 		}
578 	}
579 	else if(Lump.iType == 0x43)
580 	{
581 		if(uiMipmap > 3)
582 		{
583 			LastError.SetErrorMessageFormated("Error reading lump: invalid mipmap level %u.", uiMipmap);
584 			return hlFalse;
585 		}
586 	}
587 	else
588 	{
589 		LastError.SetErrorMessageFormated("Error reading lump: lump type %#.2x not supported.", Lump.iType);
590 		return hlFalse;
591 	}
592 
593 	if(!this->pMapping->Map(pView, Lump.uiOffset, Lump.uiDiskLength))
594 	{
595 		return hlFalse;
596 	}
597 
598 	hlByte *lpData = (hlByte *)pView->GetView();
599 
600 	// Type 0x42 has no name, type 0x43 does.  Are these flags?
601 	if(Lump.iType == 0x42)
602 	{
603 		// Get Width.
604 		uiWidth = *(hlUInt *)lpData;
605 		lpData += sizeof(hlUInt);
606 
607 		// Get Height.
608 		uiHeight = *(hlUInt *)lpData;
609 		lpData += sizeof(hlUInt);
610 
611 		// Get pixel data.
612 		lpPixels = lpData;
613 		lpData += (uiWidth * uiHeight);
614 
615 		// Get palette size.
616 		uiPaletteSize = (hlUInt)(*(hlUInt16 *)lpData);
617 		lpData += sizeof(hlUInt16);
618 
619 		// Get palette.
620 		lpPalette = lpData;
621 	}
622 	else if(Lump.iType == 0x43)
623 	{
624 		// Scan past name.
625 		lpData += 16;
626 
627 		// Get Width.
628 		uiWidth = *(hlUInt *)lpData;
629 		lpData += sizeof(hlUInt);
630 
631 		// Get Height.
632 		uiHeight = *(hlUInt *)lpData;
633 		lpData += sizeof(hlUInt);
634 
635 		// Get pixel offset.
636 		hlUInt uiPixelOffset = *(hlUInt *)lpData;
637 		lpData += 16;
638 
639 		lpPixels = (hlByte *)pView->GetView() + uiPixelOffset;
640 
641 		hlUInt uiPixelSize = uiWidth * uiHeight;
642 
643 		switch(uiMipmap)
644 		{
645 		case 1:
646 			lpData += (uiPixelSize);
647 			break;
648 		case 2:
649 			lpData += (uiPixelSize) + (uiPixelSize / 4);
650 			break;
651 		case 3:
652 			lpData += (uiPixelSize) + (uiPixelSize / 4) + (uiPixelSize / 16);
653 			break;
654 		}
655 
656 		// Scan past data.
657 		lpData += (uiPixelSize) + (uiPixelSize / 4) + (uiPixelSize / 16) + (uiPixelSize / 64);
658 
659 		// Get palette size.
660 		uiPaletteSize = (hlUInt)(*(hlUInt16 *)lpData);
661 		lpData += sizeof(hlUInt16);
662 
663 		// Get palette.
664 		lpPalette = lpData;
665 	}
666 
667 	//this->pMapping->Unmap(pView);
668 
669 	switch(uiMipmap)
670 	{
671 	case 1:
672 		uiWidth /= 2;
673 		uiHeight /= 2;
674 		break;
675 	case 2:
676 		uiWidth /= 4;
677 		uiHeight /= 4;
678 		break;
679 	case 3:
680 		uiWidth /= 8;
681 		uiHeight /= 8;
682 		break;
683 	}
684 
685 	return hlTrue;
686 }
687