1 // "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman
2 // Ken Silverman's official web site: "http://www.advsys.net/ken"
3 // See the included license file "BUILDLIC.TXT" for license info.
4 //
5 // This file has been modified from Ken Silverman's original release
6 // by Jonathon Fowler (jf@jonof.id.au)
7 
8 #include "compat.h"
9 #include "pragmas.h"
10 
11 #define MAXPALOOKUPS 256
12 
13 static int numpalookups, transratio;
14 static char palettefilename[13];
15 static unsigned char origpalookup[MAXPALOOKUPS<<8];
16 static unsigned char palette[768], palookup[MAXPALOOKUPS<<8], transluc[65536];
17 static unsigned char closestcol[64][64][64];
18 
19 #define FASTPALGRIDSIZ 8
20 static int rdist[129], gdist[129], bdist[129];
21 static unsigned char colhere[((FASTPALGRIDSIZ+2)*(FASTPALGRIDSIZ+2)*(FASTPALGRIDSIZ+2))>>3];
22 static unsigned char colhead[(FASTPALGRIDSIZ+2)*(FASTPALGRIDSIZ+2)*(FASTPALGRIDSIZ+2)];
23 static int colnext[256];
24 static char coldist[8] = {0,1,2,3,4,3,2,1};
25 static int colscan[27];
26 
27 
28 
getclosestcol(int r,int g,int b)29 unsigned char getclosestcol(int r, int g, int b)
30 {
31 	int i, j, k, dist, mindist, retcol;
32 	int *rlookup, *glookup, *blookup;
33 	unsigned char *ptr;
34 
35 	if (closestcol[r][g][b] != 255) return(closestcol[r][g][b]);
36 
37 	j = (r>>3)*FASTPALGRIDSIZ*FASTPALGRIDSIZ+(g>>3)*FASTPALGRIDSIZ+(b>>3)+FASTPALGRIDSIZ*FASTPALGRIDSIZ+FASTPALGRIDSIZ+1;
38 	mindist = min(rdist[coldist[r&7]+64+8],gdist[coldist[g&7]+64+8]);
39 	mindist = min(mindist,bdist[coldist[b&7]+64+8]);
40 	mindist++;
41 
42 	rlookup = (int *)&rdist[64-r];
43 	glookup = (int *)&gdist[64-g];
44 	blookup = (int *)&bdist[64-b];
45 
46 	retcol = -1;
47 	for(k=26;k>=0;k--)
48 	{
49 		i = colscan[k]+j; if ((colhere[i>>3]&(1<<(i&7))) == 0) continue;
50 		for(i=colhead[i];i>=0;i=colnext[i])
51 		{
52 			ptr = &palette[i*3];
53 			dist = glookup[ptr[1]]; if (dist >= mindist) continue;
54 			dist += rlookup[ptr[0]]; if (dist >= mindist) continue;
55 			dist += blookup[ptr[2]]; if (dist >= mindist) continue;
56 			mindist = dist; retcol = i;
57 		}
58 	}
59 	if (retcol < 0)
60 	{
61 		mindist = 0x7fffffff;
62 		ptr = &palette[768-3];
63 		for(i=255;i>=0;i--,ptr-=3)
64 		{
65 			dist = glookup[ptr[1]]; if (dist >= mindist) continue;
66 			dist += rlookup[ptr[0]]; if (dist >= mindist) continue;
67 			dist += blookup[ptr[2]]; if (dist >= mindist) continue;
68 			mindist = dist; retcol = i;
69 		}
70 	}
71 	ptr = &closestcol[r][g][b];
72 	*ptr = retcol;
73 	if ((r >= 4) && (ptr[(-2)<<12] == retcol)) ptr[(-3)<<12] = retcol, ptr[(-2)<<12] = retcol, ptr[(-1)<<12] = retcol;
74 	if ((g >= 4) && (ptr[(-2)<<6] == retcol)) ptr[(-3)<<6] = retcol, ptr[(-2)<<6] = retcol, ptr[(-1)<<6] = retcol;
75 	if ((b >= 4) && (ptr[(-2)] == retcol)) ptr[(-3)] = retcol, ptr[(-2)] = retcol, ptr[(-1)] = retcol;
76 	if ((r < 64-4) && (ptr[(2)<<12] == retcol)) ptr[(3)<<12] = retcol, ptr[(2)<<12] = retcol, ptr[(1)<<12] = retcol;
77 	if ((g < 64-4) && (ptr[(2)<<6] == retcol)) ptr[(3)<<6] = retcol, ptr[(2)<<6] = retcol, ptr[(1)<<6] = retcol;
78 	if ((b < 64-4) && (ptr[(2)] == retcol)) ptr[(3)] = retcol, ptr[(2)] = retcol, ptr[(1)] = retcol;
79 	if ((r >= 2) && (ptr[(-1)<<12] == retcol)) ptr[(-1)<<12] = retcol;
80 	if ((g >= 2) && (ptr[(-1)<<6] == retcol)) ptr[(-1)<<6] = retcol;
81 	if ((b >= 2) && (ptr[(-1)] == retcol)) ptr[(-1)] = retcol;
82 	if ((r < 64-2) && (ptr[(1)<<12] == retcol)) ptr[(1)<<12] = retcol;
83 	if ((g < 64-2) && (ptr[(1)<<6] == retcol)) ptr[(1)<<6] = retcol;
84 	if ((b < 64-2) && (ptr[(1)] == retcol)) ptr[(1)] = retcol;
85 	return(retcol);
86 }
87 
getpalookup(char dashade,unsigned char dacol)88 unsigned char getpalookup(char dashade, unsigned char dacol)
89 {
90 	int r, g, b, t;
91 	unsigned char *ptr;
92 
93 	ptr = &palette[dacol*3];
94 	t = divscale16(numpalookups-dashade,numpalookups);
95 	r = ((ptr[0]*t+32768)>>16);
96 	g = ((ptr[1]*t+32768)>>16);
97 	b = ((ptr[2]*t+32768)>>16);
98 	return(getclosestcol(r,g,b));
99 }
100 
gettrans(unsigned char dat1,unsigned char dat2,int datransratio)101 unsigned char gettrans(unsigned char dat1, unsigned char dat2, int datransratio)
102 {
103 	int r, g, b;
104 	unsigned char *ptr, *ptr2;
105 
106 	ptr = &palette[dat1*3];
107 	ptr2 = &palette[dat2*3];
108 	r = ptr[0]; r += (((ptr2[0]-r)*datransratio+128)>>8);
109 	g = ptr[1]; g += (((ptr2[1]-g)*datransratio+128)>>8);
110 	b = ptr[2]; b += (((ptr2[2]-b)*datransratio+128)>>8);
111 	return(getclosestcol(r,g,b));
112 }
113 
initfastcolorlookup(int rscale,int gscale,int bscale)114 void initfastcolorlookup(int rscale, int gscale, int bscale)
115 {
116 	int i, j, x, y, z;
117 	unsigned char *ptr;
118 
119 	j = 0;
120 	for(i=64;i>=0;i--)
121 	{
122 		//j = (i-64)*(i-64);
123 		rdist[i] = rdist[128-i] = j*rscale;
124 		gdist[i] = gdist[128-i] = j*gscale;
125 		bdist[i] = bdist[128-i] = j*bscale;
126 		j += 129-(i<<1);
127 	}
128 
129 	memset(colhere,0,sizeof(colhere));
130 	memset(colhead,0,sizeof(colhead));
131 
132 	ptr = &palette[768-3];
133 	for(i=255;i>=0;i--,ptr-=3)
134 	{
135 		j = (ptr[0]>>3)*FASTPALGRIDSIZ*FASTPALGRIDSIZ+(ptr[1]>>3)*FASTPALGRIDSIZ+(ptr[2]>>3)+FASTPALGRIDSIZ*FASTPALGRIDSIZ+FASTPALGRIDSIZ+1;
136 		if (colhere[j>>3]&(1<<(j&7))) colnext[i] = colhead[j]; else colnext[i] = -1;
137 		colhead[j] = i;
138 		colhere[j>>3] |= (1<<(j&7));
139 	}
140 
141 	i = 0;
142 	for(x=-FASTPALGRIDSIZ*FASTPALGRIDSIZ;x<=FASTPALGRIDSIZ*FASTPALGRIDSIZ;x+=FASTPALGRIDSIZ*FASTPALGRIDSIZ)
143 		for(y=-FASTPALGRIDSIZ;y<=FASTPALGRIDSIZ;y+=FASTPALGRIDSIZ)
144 			for(z=-1;z<=1;z++)
145 				colscan[i++] = x+y+z;
146 	i = colscan[13]; colscan[13] = colscan[26]; colscan[26] = i;
147 }
148 
main(int argc,char ** argv)149 int main(int argc, char **argv)
150 {
151 	char transonly = 0;
152 	short orignumpalookups, s;
153 	int fil, i, j, rscale, gscale, bscale;
154 	unsigned char col, buf[65536];
155 
156 	if (argc>1) {
157 		if (argv[1][0] == '-') {
158 			if (argv[1][1] == 't') { transonly = 1; puts("Updating translucency table ONLY"); }
159 			argc--;
160 			argv++;
161 		}
162 	}
163 
164 	if ((argc != 3) && (argc != 6))
165 	{
166 		printf("TRANSPAL [-t] [numshades][trans#(0-inv,256-opa)][r][g][b]     by Kenneth Silverman\n");
167 		printf("   Ex #1: transpal 32 170 30 59 11      (I use these values in my BUILD demo)\n");
168 		printf("                          └──┴──┴─── The RGB scales are optional\n");
169 		printf("   Ex #2: transpal 64 160\n\n");
170 		printf("Once tables are generated, the optional -t switch determines what to save:\n");
171 		printf("   Exclude -t to update both the shade table and transluscent table\n");
172 		printf("   Include -t to update the transluscent table ONLY\n");
173 		exit(0);
174 	}
175 
176 	strcpy(palettefilename,"palette.dat");
177 	numpalookups = atol(argv[1]);
178 	transratio = atol(argv[2]);
179 
180 	if (argc == 6)
181 	{
182 		rscale = atol(argv[3]);
183 		gscale = atol(argv[4]);
184 		bscale = atol(argv[5]);
185 	}
186 	else
187 	{
188 		rscale = 30;
189 		gscale = 59;
190 		bscale = 11;
191 	}
192 
193 	if ((numpalookups < 1) || (numpalookups > 256))
194 		{ printf("Invalid number of shades\n"); exit(0); }
195 	if ((transratio < 0) || (transratio > 256))
196 		{ printf("Invalid transluscent ratio\n"); exit(0); }
197 
198 	if ((fil = Bopen(palettefilename,BO_BINARY|BO_RDONLY,BS_IREAD)) == -1)
199 	{
200 		printf("%s not found",palettefilename);
201 		return(0);
202 	}
203 	Bread(fil,palette,768);
204 	Bread(fil,&orignumpalookups,2); orignumpalookups = B_LITTLE16(orignumpalookups);
205 	orignumpalookups = min(max(orignumpalookups,1),256);
206 	Bread(fil,origpalookup,(int)orignumpalookups<<8);
207 	Bclose(fil);
208 
209 	memset(buf,0,65536);
210 
211 	initfastcolorlookup(rscale,gscale,bscale);
212 	memset(closestcol, 0xff, 262144);
213 
214 	for(i=0;i<numpalookups;i++)
215 		for(j=0;j<256;j++)
216 		{
217 			col = getpalookup((char)i,(unsigned char)j);
218 			palookup[(i<<8)+j] = col;
219 
220 			drawpixel(((((i<<1)+0)*320+(j+8))>>2)+buf,(int)col);
221 			drawpixel(((((i<<1)+1)*320+(j+8))>>2)+buf,(int)col);
222 		}
223 
224 	for(i=0;i<256;i++)
225 		for(j=0;j<6;j++)
226 		{
227 			drawpixel((((j+132+0)*320+(i+8))>>2)+buf,i);
228 
229 			drawpixel((((i+132+8)*320+(j+0))>>2)+buf,i);
230 		}
231 
232 	for(i=0;i<256;i++)
233 		for(j=0;j<256;j++)
234 		{
235 			col = gettrans((unsigned char)i,(unsigned char)j,transratio);
236 			transluc[(i<<8)+j] = col;
237 
238 			drawpixel((((j+132+8)*320+(i+8))>>2)+buf,(int)col);
239 		}
240 
241     if ((fil = Bopen(palettefilename,BO_BINARY|BO_TRUNC|BO_CREAT|BO_WRONLY,BS_IREAD|BS_IWRITE)) == -1)
242         { printf("Couldn't save file %s",palettefilename); return(0); }
243     Bwrite(fil,palette,768);
244     if (transonly) {
245         s = B_LITTLE16(orignumpalookups); Bwrite(fil,&s,2);
246         Bwrite(fil,origpalookup,(int)orignumpalookups<<8);
247         printf("Transluscent table updated\n");
248     } else {
249         s = B_LITTLE16(numpalookups); Bwrite(fil,&s,2);
250         Bwrite(fil,palookup,numpalookups<<8);
251         printf("Shade table AND transluscent table updated\n");
252     }
253     Bwrite(fil,transluc,65536);
254     Bclose(fil);
255 
256 	return 0;
257 }
258 
259