1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #include <ronin/ronin.h>
24 #include <string.h>
25 
26 #include "icon.h"
27 
create_vmicon(void * buffer)28 void Icon::create_vmicon(void *buffer)
29 {
30   unsigned short *pal = (unsigned short *)buffer;
31   unsigned char *pix = ((unsigned char *)buffer)+32;
32 
33   for (int n = 0; n<16; n++) {
34 	int p = palette[n];
35 	pal[n] =
36 	  ((p>>16)&0xf000)|
37 	  ((p>>12)&0x0f00)|
38 	  ((p>> 8)&0x00f0)|
39 	  ((p>> 4)&0x000f);
40   }
41 
42   for (int line = 0; line < 32; line++) {
43 	memcpy(pix, &bitmap[32/2*(31-line)], 32/2);
44 	pix += 32/2;
45   }
46 }
47 
create_texture()48 void Icon::create_texture()
49 {
50   static unsigned char tt[16] = { 0, 1, 4, 5, 16, 17, 20, 21,
51 				  64, 65, 68, 69, 80, 81, 84, 85 };
52   unsigned short *tex = (unsigned short *)ta_txalloc(512);
53   unsigned short *linebase;
54   unsigned char *src = bitmap+sizeof(bitmap)-17;
55   for (int y=0; y<16; y++) {
56 	linebase = tex + (tt[y]<<1);
57 	for (int x=0; x<16; x++, --src)
58 	  linebase[tt[x]] = src[16]|(src[0]<<8);
59 	src -= 16;
60   }
61   texture = tex;
62 }
63 
setPalette(int pal)64 void Icon::setPalette(int pal)
65 {
66   unsigned int (*hwpal)[64][16] = (unsigned int (*)[64][16])0xa05f9000;
67   for (int n = 0; n<16; n++)
68 	(*hwpal)[pal][n] = palette[n];
69 }
70 
draw(float x1,float y1,float x2,float y2,int pal,unsigned int argb)71 void Icon::draw(float x1, float y1, float x2, float y2, int pal,
72 		unsigned int argb)
73 {
74   struct polygon_list mypoly;
75   struct packed_colour_vertex_list myvertex;
76 
77   mypoly.cmd =
78 	TA_CMD_POLYGON|TA_CMD_POLYGON_TYPE_TRANSPARENT|TA_CMD_POLYGON_SUBLIST|
79 	TA_CMD_POLYGON_STRIPLENGTH_2|TA_CMD_POLYGON_PACKED_COLOUR|TA_CMD_POLYGON_TEXTURED;
80   mypoly.mode1 = TA_POLYMODE1_Z_ALWAYS|TA_POLYMODE1_NO_Z_UPDATE;
81   mypoly.mode2 =
82 	TA_POLYMODE2_BLEND_SRC_ALPHA|TA_POLYMODE2_BLEND_DST_INVALPHA|
83 	TA_POLYMODE2_FOG_DISABLED|TA_POLYMODE2_ENABLE_ALPHA|
84 	TA_POLYMODE2_TEXTURE_MODULATE_ALPHA|TA_POLYMODE2_U_SIZE_32|
85 	TA_POLYMODE2_V_SIZE_32;
86   mypoly.texture = TA_TEXTUREMODE_CLUT4|TA_TEXTUREMODE_CLUTBANK4(pal)|
87 	TA_TEXTUREMODE_ADDRESS(texture);
88 
89   mypoly.red = mypoly.green = mypoly.blue = mypoly.alpha = 0;
90 
91   ta_commit_list(&mypoly);
92 
93   myvertex.cmd = TA_CMD_VERTEX;
94   myvertex.ocolour = 0;
95   myvertex.colour = argb;
96   myvertex.z = 0.5;
97   myvertex.u = 0.0;
98   myvertex.v = 1.0;
99 
100   myvertex.x = x1;
101   myvertex.y = y1;
102   ta_commit_list(&myvertex);
103 
104   myvertex.x = x2;
105   myvertex.v = 0.0;
106   ta_commit_list(&myvertex);
107 
108   myvertex.x = x1;
109   myvertex.y = y2;
110   myvertex.u = 1.0;
111   myvertex.v = 1.0;
112   ta_commit_list(&myvertex);
113 
114   myvertex.x = x2;
115   myvertex.v = 0.0;
116   myvertex.cmd |= TA_CMD_VERTEX_EOS;
117   ta_commit_list(&myvertex);
118 }
119 
find_unused_pixel(const unsigned char * mask)120 int Icon::find_unused_pixel(const unsigned char *mask)
121 {
122   int use[16];
123   memset(use, 0, sizeof(use));
124   unsigned char *p = bitmap;
125   for (int n=0; n<32*32/2/4; n++) {
126 	unsigned char mbits = ~*mask++;
127 	for (int i=0; i<4; i++) {
128 	  unsigned char pix = *p++;
129 	  if(mbits & 64)
130 	use[pix&0xf]++;
131 	  if(mbits & 128)
132 	use[pix>>4]++;
133 	  mbits <<= 2;
134 	}
135   }
136   for (int i=0; i<16; i++)
137 	if (!use[i])
138 	  return i;
139   return -1;
140 }
141 
load_image2(const void * data,int len)142 bool Icon::load_image2(const void *data, int len)
143 {
144   struct {
145 	int size, w, h;
146 	short pla, bitcnt;
147 	int comp, sizeimg, xres, yres, used, imp;
148   } hdr;
149   if (len < 40)
150 	return false;
151   memcpy(&hdr, data, 40);
152   if (hdr.size != 40 || /* hdr.sizeimg<=0 || */ hdr.w<0 || hdr.h<0 ||
153 	 hdr.bitcnt<0 || hdr.used<0)
154 	return false;
155   if (!hdr.used)
156 	hdr.used = 1<<hdr.bitcnt;
157   hdr.h >>= 1;
158   /* Fix incorrect sizeimg (The Dig) */
159   if (hdr.sizeimg < ((hdr.w*hdr.h*(1+hdr.bitcnt)+7)>>3))
160 	hdr.sizeimg = ((hdr.w*hdr.h*(1+hdr.bitcnt)+7)>>3);
161   if (hdr.size + (hdr.used<<2) + hdr.sizeimg > len /* ||
162 	 hdr.sizeimg < ((hdr.w*hdr.h*(1+hdr.bitcnt)+7)>>3) */)
163 	return false;
164   if (hdr.w != 32 || hdr.h != 32 || hdr.bitcnt != 4 || hdr.used > 16)
165 	return false;
166   memcpy(palette, ((const char *)data)+hdr.size, hdr.used<<2);
167   memcpy(bitmap, ((const char *)data)+hdr.size+(hdr.used<<2), 32*32/2);
168   for (int i=0; i<16; i++)
169 	palette[i] |= 0xff000000;
170   for (int i=hdr.used; i<16; i++)
171 	palette[i] = 0;
172   const unsigned char *mask =
173 	((const unsigned char *)data)+hdr.size+(hdr.used<<2)+32*32/2;
174   int unused = find_unused_pixel(mask);
175   if (unused >= 0) {
176 	unsigned char *pix = bitmap;
177 	for (int y=0; y<32; y++)
178 	  for (int x=0; x<32/8; x++) {
179 	unsigned char mbits = *mask++;
180 	for (int z=0; z<4; z++) {
181 	  unsigned char pbits = *pix;
182 	  if (mbits & 64) pbits = (pbits & ~0xf) | unused;
183 	  if (mbits & 128) pbits = (pbits & 0xf) | (unused << 4);
184 	  *pix++ = pbits;
185 	  mbits <<= 2;
186 	}
187 	  }
188 	palette[unused] = 0;
189   }
190   return true;
191 }
192 
load_image1(const void * data,int len,int offs)193 bool Icon::load_image1(const void *data, int len, int offs)
194 {
195   struct {
196 	char w, h, colors, rsrv;
197 	short pla, bitcnt;
198 	int bytes, offs;
199   } hdr;
200   if (len < offs+16)
201 	return false;
202   memcpy(&hdr, ((const char *)data)+offs, 16);
203   if (hdr.bytes > 0 && hdr.offs >= 0 && hdr.offs+hdr.bytes <= len)
204 	return load_image2(((const char *)data)+hdr.offs, hdr.bytes);
205   else
206 	return false;
207 }
208 
load(const void * data,int len,int offs)209 bool Icon::load(const void *data, int len, int offs)
210 {
211   struct { short rsrv, type, cnt; } hdr;
212   memset(bitmap, 0, sizeof(bitmap));
213   memset(palette, 0, sizeof(palette));
214   texture = NULL;
215   if (len < offs+6)
216 	return false;
217   memcpy(&hdr, ((const char *)data)+offs, 6);
218   if (hdr.type != 1 || hdr.cnt < 1 || offs+6+(hdr.cnt<<4) > len)
219 	return false;
220   for (int i=0; i<hdr.cnt; i++)
221 	if (load_image1(data, len, offs+6+(i<<4)))
222 	  return true;
223   return false;
224 }
225 
load(const char * filename)226 bool Icon::load(const char *filename)
227 {
228   char buf[2048];
229   int fd;
230   if ((fd = open(filename, O_RDONLY))>=0) {
231 	int sz;
232 	sz = read(fd, buf, sizeof(buf));
233 	close(fd);
234 	if (sz>0)
235 	  return load(buf, sz);
236   }
237   return false;
238 }
239