1 /* OpenCP Module Player
2  * copyright (c) '94-'10 Niklas Beisert <nbeisert@physik.tu-muenchen.de>
3  *
4  * CPIFace background picture loader
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  *
20  * revision history: (please note changes here)
21  *  -nb980510   Niklas Beisert <nbeisert@physik.tu-muenchen.de>
22  *    -first release
23  *  -kb980717   Tammo Hinrichs <opencp@gmx.net>
24  *    -some minor changes
25  *  -doj980928  Dirk Jagdmann <doj@cubic.org>
26  *    -wrote a more compatible TGA loader which is found in the file tga.cpp
27  *    -changed this file to meet dependencies from the new TGA loader
28  *    -added comments
29  *  -doj980930  Dirk Jagdmann <doj@cubic.org>
30  *    -added gif loader
31  *  -doj981105  Dirk Jagdmann <doj@cubic.org>
32  *    -now the plOpenCPPict is cleared if no file is found / valid
33  *    -modified memory allocation a bit to remove unnecessary new/delete
34  *  -fd981119   Felix Domke <tmbinc@gmx.net>
35  *    -added the really important 'NO_CPIFACE_IMPORT'
36  *  -doj20020902 Dirk Jagdmann <doj@cubic.org>
37  *    -added wildcard for picture loading
38  */
39 
40 #include "config.h"
41 #include <sys/types.h>
42 #include <sys/stat.h>
43 #include <unistd.h>
44 #include <dirent.h>
45 #include <ctype.h>
46 #include <fcntl.h>
47 #include <stdlib.h>
48 #include <stdio.h>
49 #include <string.h>
50 #include "types.h"
51 #include "boot/psetting.h"
52 #include "cpiface.h"
53 #include "stuff/compat.h"
54 
55 #ifdef HAVE_LZW
56 #include "gif.h"
57 #endif
58 #include "tga.h"
59 
60 unsigned char *plOpenCPPict=0; /* an array containing the raw picture */
61 unsigned char plOpenCPPal[768]; /* the palette for the picture */
62 
63 static const int picWidth=640;
64 static const int picHeight=384;
65 
66 struct node_t
67 {
68 	char *name;
69 	struct node_t *next;
70 };
71 
72 static struct node_t *files=0;
73 static int filesSize=0;
74 
match(const char * name)75 static int match(const char *name)
76 {
77 /* check file suffixes*/
78 	int l=strlen(name);
79 	if(l<5)
80 		return 0;
81 	if(name[l-4]!='.')
82 		return 1;
83 #ifdef HAVE_LZW
84 	if(tolower(name[l-3])=='g' && tolower(name[l-2])=='i' && tolower(name[l-1])=='f')
85 		return 1;
86 #endif
87 	if(tolower(name[l-3])=='t' && tolower(name[l-2])=='g' && tolower(name[l-1])=='a')
88 		return 1;
89 	return 0;
90 }
91 
plReadOpenCPPic(void)92 void plReadOpenCPPic(void)
93 {
94 	int i;
95 	int n;
96 	struct node_t* nd;
97 
98 	static int lastN=-1;
99 	int file, filesize;
100 	unsigned char *filecache;
101 
102 	int low;
103 	int high;
104 	int move;
105 
106 	/* setup file names */
107 
108 	if(lastN==-1)
109 	{
110 		struct node_t* *current=&files;
111 		/* get the resource containing background pictures */
112 		const char *picstr=cfGetProfileString2(cfScreenSec, "screen", "usepics", "");
113 
114 		int wildcardflag=0;
115 
116 		/* n contains the number of background pictures */
117 		n=cfCountSpaceList(picstr, 12);
118 		for(i=0; i<n; i++)
119 		{
120 			char name[128];
121 			if(cfGetSpaceListEntry(name, &picstr, sizeof(name)) == 0)
122 				break;
123 			if(!match(name))
124 				continue;
125 			/* check for wildcard */
126 #ifdef HAVE_LZW
127 			if(!strncasecmp(name, "*.gif", 5) || !strncasecmp(name, "*.tga", 5))
128 #else
129 			if(!strncasecmp(name, "*.tga", 5))
130 #endif
131 			{
132 				DIR *dir;
133 				if(wildcardflag)
134 					continue;
135 				dir=opendir(cfDataDir);
136 				if(dir)
137 				{
138 					struct dirent *dp;
139 					while((dp=readdir(dir)))
140 					{
141 						if(match(dp->d_name))
142 						{
143 							nd=calloc(1, sizeof(struct node_t));
144 							makepath_malloc(&nd->name, 0, cfDataDir, dp->d_name, 0);
145 							nd->next=0;
146 							*current=nd;
147 							current=&nd->next;
148 							filesSize++;
149 						}
150 					}
151 					closedir(dir);
152 				}
153 				dir=opendir(cfConfigDir);
154 				if(dir)
155 				{
156 					struct dirent *dp;
157 					while((dp=readdir(dir)))
158 					{
159 						if(match(dp->d_name))
160 						{
161 							nd=calloc(1, sizeof(struct node_t));
162 							makepath_malloc(&nd->name, 0, cfConfigDir, dp->d_name, 0);
163 							nd->next=0;
164 							*current=nd;
165 							current=&nd->next;
166 							filesSize++;
167 						}
168 					}
169 					closedir(dir);
170 				}
171 				wildcardflag=1;
172 			} else {
173 				nd=calloc(1, sizeof(struct node_t));
174 				nd->name=strdup(name);
175 				nd->next=0;
176 				*current=nd;
177 				current=&nd->next;
178 				filesSize++;
179 			}
180 		}
181 	}
182 
183 	/* if there are no background pictures we can skip the rest */
184 	if (filesSize<=0)
185 		return;
186 	/* choose a new picture */
187 	n=rand()%filesSize;
188 	/* we have loaded that picture already */
189 	if(n==lastN)
190 		return;
191 	lastN=n;
192 
193 	/* get filename */
194 	nd=files;
195 	for(i=0; i<n; i++)
196 		nd=files->next;
197 
198 	/* read the file into a filecache */
199 	file=open(nd->name, O_RDONLY);
200 	if(file<0)
201 		return;
202 	filesize=lseek(file, 0, SEEK_END);
203 	if(filesize<0)
204 	{
205 		close(file);
206 		return ;
207 	}
208 	if(lseek(file, 0, SEEK_SET)<0)
209 	{
210 		close(file);
211 		return ;
212 	}
213 	filecache=calloc(sizeof(unsigned char), filesize);
214 	if(filecache==0)
215 	{
216 		close(file);
217 			return ;
218 	}
219 	if(read(file, filecache, filesize)!=filesize)
220 	{
221 		free(filecache);
222 		close(file);
223 		return ;
224 	}
225 	close(file);
226 
227 	/* allocate memory for a new picture */
228 	if(plOpenCPPict==0)
229 	{
230 		plOpenCPPict=calloc(sizeof(unsigned char), picWidth*picHeight);
231 		if(plOpenCPPict==0)
232 			return;
233 		memset(plOpenCPPict, 0, picWidth*picHeight);
234 	}
235 
236 	/* read the picture */
237 #ifdef HAVE_LZW
238 	GIF87read(filecache, filesize, plOpenCPPict, plOpenCPPal, picWidth, picHeight);
239 #endif
240 	TGAread(filecache, filesize, plOpenCPPict, plOpenCPPal, picWidth, picHeight);
241 
242 	free(filecache);
243 
244 	/* determine if the lower or upper part of the palette is left blank for
245 	 * our own screen colors
246 	 */
247 
248 	low=high=0;
249 	for (i=0; i<picWidth*picHeight; i++)
250 		if (plOpenCPPict[i]<0x30)
251 			low=1;
252 		else if (plOpenCPPict[i]>=0xD0)
253 			high=1;
254 
255 	move=(low&&!high)*0x90;
256 
257 	/* if the color indices are bad, we have to move every color map entry */
258 	if (move)
259 		for (i=0; i<picWidth*picHeight; i++)
260 		      plOpenCPPict[i]+=0x30;
261 
262 	/* adjust the RGB palette to 6bit, because standard VGA is limited */
263 	for (i=0x2FD; i>=0x90; i--)
264 		plOpenCPPal[i]=plOpenCPPal[i-move]>>2;
265 }
266