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