1 /*
2  * High-colour textures support for Polymost
3  * by Jonathon Fowler
4  * See the included license file "BUILDLIC.TXT" for license info.
5  */
6 
7 #include "build.h"
8 
9 #if USE_POLYMOST && USE_OPENGL
10 
11 #include "kplib.h"
12 #include "hightile_priv.h"
13 
14 palette_t hictinting[MAXPALOOKUPS];
15 
16 hicreplctyp *hicreplc[MAXTILES];
17 int hicfirstinit = 0;
18 
19 /**
20  * Find a substitute definition which satisfies the given parameters.
21  * This will try for a perfect match with the requested palette, or if
22  * none is found, try and find a palette 0 equivalent.
23  *
24  * @param picnum tile number
25  * @param palnum palette index
26  * @param skybox 'true' to find a substitute that defines a skybox
27  * @return the substitute header, or null
28  */
hicfindsubst(int picnum,int palnum,int skybox)29 hicreplctyp * hicfindsubst(int picnum, int palnum, int skybox)
30 {
31 	hicreplctyp *hr;
32 
33 	if (!hicfirstinit) return NULL;
34 	if ((unsigned int)picnum >= (unsigned int)MAXTILES) return NULL;
35 
36 	do {
37 		for (hr = hicreplc[picnum]; hr; hr = hr->next) {
38 			if (hr->palnum == palnum) {
39 				if (skybox) {
40 					if (hr->skybox && !hr->skybox->ignore) return hr;
41 				} else {
42 					if (!hr->ignore) return hr;
43 				}
44 			}
45 		}
46 
47 		if (palnum == 0) break;
48 		palnum = 0;
49 	} while (1);
50 
51 	return NULL;	// no replacement found
52 }
53 
54 
55 /**
56  * Initialise the high-colour stuff to a default state
57  */
hicinit(void)58 void hicinit(void)
59 {
60 	int i,j;
61 	hicreplctyp *hr, *next;
62 
63 	for (i=0;i<MAXPALOOKUPS;i++) {	// all tints should be 100%
64 		hictinting[i].r = hictinting[i].g = hictinting[i].b = 0xff;
65 		hictinting[i].f = 0;
66 	}
67 
68 	if (hicfirstinit) {
69 		for (i=MAXTILES-1;i>=0;i--) {
70 			for (hr=hicreplc[i]; hr; ) {
71 				next = hr->next;
72 
73 				if (hr->skybox) {
74 					for (j=5;j>=0;j--) {
75 						if (hr->skybox->face[j]) {
76 							free(hr->skybox->face[j]);
77 						}
78 					}
79 					free(hr->skybox);
80 				}
81 				if (hr->filename) free(hr->filename);
82 				free(hr);
83 
84 				hr = next;
85 			}
86 		}
87 	}
88 	memset(hicreplc,0,sizeof(hicreplc));
89 
90 	hicfirstinit = 1;
91 }
92 
93 
94 //
95 // hicsetpalettetint(pal,r,g,b,effect)
96 //   The tinting values represent a mechanism for emulating the effect of global sector
97 //   palette shifts on true-colour textures and only true-colour textures.
98 //   effect bitset: 1 = greyscale, 2 = invert
99 //
hicsetpalettetint(int palnum,unsigned char r,unsigned char g,unsigned char b,unsigned char effect)100 void hicsetpalettetint(int palnum, unsigned char r, unsigned char g, unsigned char b, unsigned char effect)
101 {
102 	if ((unsigned int)palnum >= (unsigned int)MAXPALOOKUPS) return;
103 	if (!hicfirstinit) hicinit();
104 
105 	hictinting[palnum].r = r;
106 	hictinting[palnum].g = g;
107 	hictinting[palnum].b = b;
108 	hictinting[palnum].f = effect & HICEFFECTMASK;
109 }
110 
111 
112 //
113 // hicsetsubsttex(picnum,pal,filen,alphacut)
114 //   Specifies a replacement graphic file for an ART tile.
115 //
hicsetsubsttex(int picnum,int palnum,char * filen,float alphacut,unsigned char flags)116 int hicsetsubsttex(int picnum, int palnum, char *filen, float alphacut, unsigned char flags)
117 {
118 	hicreplctyp *hr, *hrn;
119 
120 	if ((unsigned int)picnum >= (unsigned int)MAXTILES) return -1;
121 	if ((unsigned int)palnum >= (unsigned int)MAXPALOOKUPS) return -1;
122 	if (!hicfirstinit) hicinit();
123 
124 	for (hr = hicreplc[picnum]; hr; hr = hr->next) {
125 		if (hr->palnum == palnum)
126 			break;
127 	}
128 
129 	if (!hr) {
130 		// no replacement yet defined
131 		hrn = (hicreplctyp *)calloc(1,sizeof(hicreplctyp));
132 		if (!hrn) return -1;
133 		hrn->palnum = palnum;
134 	} else hrn = hr;
135 
136 	// store into hicreplc the details for this replacement
137 	if (hrn->filename) free(hrn->filename);
138 
139 	hrn->filename = strdup(filen);
140 	if (!hrn->filename) {
141 		if (hrn->skybox) return -1;	// don't free the base structure if there's a skybox defined
142 		if (hr == NULL) free(hrn);	// not yet a link in the chain
143 		return -1;
144 	}
145 	hrn->ignore = 0;
146 	hrn->alphacut = min(alphacut,1.0);
147 	hrn->flags = flags;
148 	if (hr == NULL) {
149 		hrn->next = hicreplc[picnum];
150 		hicreplc[picnum] = hrn;
151 	}
152 
153 	//printf("Replacement [%d,%d]: %s\n", picnum, palnum, hicreplc[i]->filename);
154 
155 	return 0;
156 }
157 
158 
159 //
160 // hicsetskybox(picnum,pal,faces[6])
161 //   Specifies a graphic files making up a skybox.
162 //
hicsetskybox(int picnum,int palnum,char * faces[6])163 int hicsetskybox(int picnum, int palnum, char *faces[6])
164 {
165 	hicreplctyp *hr, *hrn;
166 	int j;
167 
168 	if ((unsigned int)picnum >= (unsigned int)MAXTILES) return -1;
169 	if ((unsigned int)palnum >= (unsigned int)MAXPALOOKUPS) return -1;
170 	for (j=5;j>=0;j--) if (!faces[j]) return -1;
171 	if (!hicfirstinit) hicinit();
172 
173 	for (hr = hicreplc[picnum]; hr; hr = hr->next) {
174 		if (hr->palnum == palnum)
175 			break;
176 	}
177 
178 	if (!hr) {
179 		// no replacement yet defined
180 		hrn = (hicreplctyp *)calloc(1,sizeof(hicreplctyp));
181 		if (!hrn) return -1;
182 
183 		hrn->palnum = palnum;
184 	} else hrn = hr;
185 
186 	if (!hrn->skybox) {
187 		hrn->skybox = (struct hicskybox_t *)calloc(1,sizeof(struct hicskybox_t));
188 		if (!hrn->skybox) {
189 			if (hr == NULL) free(hrn);	// not yet a link in the chain
190 			return -1;
191 		}
192 	} else {
193 		for (j=5;j>=0;j--) {
194 			if (hrn->skybox->face[j])
195 				free(hrn->skybox->face[j]);
196 		}
197 	}
198 
199 	// store each face's filename
200 	for (j=0;j<6;j++) {
201 		hrn->skybox->face[j] = strdup(faces[j]);
202 		if (!hrn->skybox->face[j]) {
203 			for (--j; j>=0; --j)	// free any previous faces
204 				free(hrn->skybox->face[j]);
205 			free(hrn->skybox);
206 			hrn->skybox = NULL;
207 			if (hr == NULL) free(hrn);
208 			return -1;
209 		}
210 	}
211 	hrn->skybox->ignore = 0;
212 	if (hr == NULL) {
213 		hrn->next = hicreplc[picnum];
214 		hicreplc[picnum] = hrn;
215 	}
216 
217 	return 0;
218 }
219 
220 
221 //
222 // hicclearsubst(picnum,pal)
223 //   Clears a replacement for an ART tile, including skybox faces.
224 //
hicclearsubst(int picnum,int palnum)225 int hicclearsubst(int picnum, int palnum)
226 {
227 	hicreplctyp *hr, *hrn = NULL;
228 
229 	if ((unsigned int)picnum >= (unsigned int)MAXTILES) return -1;
230 	if ((unsigned int)palnum >= (unsigned int)MAXPALOOKUPS) return -1;
231 	if (!hicfirstinit) return 0;
232 
233 	for (hr = hicreplc[picnum]; hr; hrn = hr, hr = hr->next) {
234 		if (hr->palnum == palnum)
235 			break;
236 	}
237 
238 	if (!hr) return 0;
239 
240 	if (hr->filename) free(hr->filename);
241 	if (hr->skybox) {
242 		int i;
243 		for (i=5;i>=0;i--)
244 			if (hr->skybox->face[i])
245 				free(hr->skybox->face[i]);
246 		free(hr->skybox);
247 	}
248 
249 	if (hrn) hrn->next = hr->next;
250 	else hicreplc[picnum] = hr->next;
251 	free(hr);
252 
253 	return 0;
254 }
255 
256 #endif //USE_POLYMOST && USE_OPENGL
257