1 //-----------------------------------------------------------------------------
2 //
3 // ImageLib Sources
4 // Copyright (C) 2000-2009 by Denton Woods
5 // Last modified: 03/07/2009
6 //
7 // Filename: src-IL/src/il_wal.c
8 //
9 // Description: Loads a Quake .wal texture.
10 //
11 //-----------------------------------------------------------------------------
12 
13 
14 #include "il_internal.h"
15 #ifndef IL_NO_WAL
16 #include "il_manip.h"
17 #include "il_q2pal.h"
18 
19 
20 typedef struct WALHEAD
21 {
22 	ILbyte	FileName[32];	// Image name
23 	ILuint	Width;			// Width of first image
24 	ILuint	Height;			// Height of first image
25 	ILuint	Offsets[4];		// Offsets to image data
26 	ILbyte	AnimName[32];	// Name of next frame
27 	ILuint	Flags;			// ??
28 	ILuint	Contents;		// ??
29 	ILuint	Value;			// ??
30 } WALHEAD;
31 
32 ILboolean iLoadWalInternal(void);
33 
34 
35 //! Reads a .wal file
ilLoadWal(ILconst_string FileName)36 ILboolean ilLoadWal(ILconst_string FileName)
37 {
38 	ILHANDLE	WalFile;
39 	ILboolean	bWal = IL_FALSE;
40 
41 	WalFile = iopenr(FileName);
42 	if (WalFile == NULL) {
43 		ilSetError(IL_COULD_NOT_OPEN_FILE);
44 		return bWal;
45 	}
46 
47 	bWal = ilLoadWalF(WalFile);
48 	icloser(WalFile);
49 
50 	return bWal;
51 }
52 
53 
54 //! Reads an already-opened .wal file
ilLoadWalF(ILHANDLE File)55 ILboolean ilLoadWalF(ILHANDLE File)
56 {
57 	ILuint		FirstPos;
58 	ILboolean	bRet;
59 
60 	iSetInputFile(File);
61 	FirstPos = itell();
62 	bRet = iLoadWalInternal();
63 	iseek(FirstPos, IL_SEEK_SET);
64 
65 	return bRet;
66 }
67 
68 
69 //! Reads from a memory "lump" that contains a .wal file
ilLoadWalL(const void * Lump,ILuint Size)70 ILboolean ilLoadWalL(const void *Lump, ILuint Size)
71 {
72 	iSetInputLump(Lump, Size);
73 	return iLoadWalInternal();
74 }
75 
76 
iLoadWalInternal()77 ILboolean iLoadWalInternal()
78 {
79 	WALHEAD	Header;
80 	ILimage	*Mipmaps[3], *CurImage;
81 	ILuint	i, NewW, NewH;
82 
83 	if (iCurImage == NULL) {
84 		ilSetError(IL_ILLEGAL_OPERATION);
85 		return IL_FALSE;
86 	}
87 	CurImage = iCurImage;
88 
89 
90 	// Read header
91 	iread(&Header.FileName, 1, 32);
92 	Header.Width = GetLittleUInt();
93 	Header.Height = GetLittleUInt();
94 
95 	for (i = 0; i < 4; i++)
96 		Header.Offsets[i] = GetLittleUInt();
97 
98 	iread(Header.AnimName, 1, 32);
99 	Header.Flags = GetLittleUInt();
100 	Header.Contents = GetLittleUInt();
101 	Header.Value = GetLittleUInt();
102 
103 	if (!ilTexImage(Header.Width, Header.Height, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL))
104 		return IL_FALSE;
105 
106 	for (i = 0; i < 3; i++) {
107 		Mipmaps[i] = (ILimage*)icalloc(sizeof(ILimage), 1);
108 		if (Mipmaps[i] == NULL)
109 			goto cleanup_error;
110 		Mipmaps[i]->Pal.Palette = (ILubyte*)ialloc(768);
111 		if (Mipmaps[i]->Pal.Palette == NULL)
112 			goto cleanup_error;
113 		memcpy(Mipmaps[i]->Pal.Palette, ilDefaultQ2Pal, 768);
114 		Mipmaps[i]->Pal.PalType = IL_PAL_RGB24;
115 	}
116 
117 	NewW = Header.Width;
118 	NewH = Header.Height;
119 	for (i = 0; i < 3; i++) {
120 		NewW /= 2;
121 		NewH /= 2;
122 		iCurImage = Mipmaps[i];
123 		if (!ilTexImage(NewW, NewH, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL))
124 			goto cleanup_error;
125 		// Don't set until now so ilTexImage won't get rid of the palette.
126 		Mipmaps[i]->Pal.PalSize = 768;
127 		Mipmaps[i]->Origin = IL_ORIGIN_UPPER_LEFT;
128 	}
129 
130 	iCurImage = CurImage;
131 	ilCloseImage(iCurImage->Mipmaps);
132 	iCurImage->Mipmaps = Mipmaps[0];
133 	Mipmaps[0]->Mipmaps = Mipmaps[1];
134 	Mipmaps[1]->Mipmaps = Mipmaps[2];
135 
136 	iCurImage->Origin = IL_ORIGIN_UPPER_LEFT;
137 
138 	if (iCurImage->Pal.Palette && iCurImage->Pal.PalSize && iCurImage->Pal.PalType != IL_PAL_NONE)
139 		ifree(iCurImage->Pal.Palette);
140 	iCurImage->Pal.Palette = (ILubyte*)ialloc(768);
141 	if (iCurImage->Pal.Palette == NULL)
142 		goto cleanup_error;
143 
144 	iCurImage->Pal.PalSize = 768;
145 	iCurImage->Pal.PalType = IL_PAL_RGB24;
146 	memcpy(iCurImage->Pal.Palette, ilDefaultQ2Pal, 768);
147 
148 	iseek(Header.Offsets[0], IL_SEEK_SET);
149 	if (iread(iCurImage->Data, Header.Width * Header.Height, 1) != 1)
150 		goto cleanup_error;
151 
152 	for (i = 0; i < 3; i++) {
153 		iseek(Header.Offsets[i+1], IL_SEEK_SET);
154 		if (iread(Mipmaps[i]->Data, Mipmaps[i]->Width * Mipmaps[i]->Height, 1) != 1)
155 			goto cleanup_error;
156 	}
157 
158 	// Fixes all images, even mipmaps.
159 	return ilFixImage();
160 
161 cleanup_error:
162 	for (i = 0; i < 3; i++) {
163 		ilCloseImage(Mipmaps[i]);
164 	}
165 	return IL_FALSE;
166 }
167 
168 
169 #endif//IL_NO_WAL
170