1 // BlinkenSisters - Hunt for the Lost Pixels
2 //     Bringing back the fun of the 80s
3 //
4 // (C) 2005-07 Rene Schickbauer, Wolfgang Dautermann
5 //
6 // See License.txt for licensing information
7 //
8 
9 
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #ifdef WIN32
14 #include <direct.h>
15 #else // NO WIN32
16 #include <dirent.h>
17 #endif
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 
21 
22 #include "globals.h"
23 #include "extractmetabmf.h"
24 #include "memops.h"
25 #include "debug.h"
26 #include "errorhandler.h"
27 
28 #include "minilzo.h"
29 #include "bmfconvert.h"
30 #include "config.h"
31 #include "drawprimitives.h"
32 #include "bsscreen.h"
33 
34 #define IN_LEN 10000000
35 #define IN_LEN 10000000
36 #define OUT_LEN 10000000
37 
38 static unsigned char __LZO_MMODEL in  [ IN_LEN ];
39 static unsigned char __LZO_MMODEL out [ OUT_LEN ];
40 
41 SDL_Surface* decrunchingbg = 0;
42 
initExtractMetaBMF()43 void initExtractMetaBMF() {
44 	decrunchingbg = BS_IMG_Load_DisplayFormat(configGetPath("decrunchingbg.png"),DIE_ON_FILE_ERROR);
45 }
46 
47 
extractMetaBMF(char * fname,bool preStartup)48 bool extractMetaBMF(char* fname, bool preStartup) {
49     int r;
50     lzo_uint in_len;
51     lzo_uint out_len = 0;
52     lzo_uint new_len;
53 
54 	char infname[MAX_FNAME_LENGTH];
55 	extractMetaBMFprogress(0, preStartup);
56 
57     in_len = IN_LEN;
58 
59 	FILE* ifh = fopen(fname, "rb");
60 	if(!ifh) {
61 		printf("Can't open file %s for input\n", fname);
62 		return false;
63 	}
64 	Uint32 tmpnum;
65 	Uint32 bmftype;
66 
67 	// Check magic number
68 	tmpnum = bmfReadInt(ifh);
69 	if(tmpnum != BMFTYPE_MAGIC) {
70 		DIE(ERROR_BMFMAGIC, fname);
71 	}
72 
73 	bool running = true;
74 #ifndef WIN32
75     DIR *tmpdir;
76 #endif
77     FILE *ofh;
78 	while(running) {
79 		bmftype = bmfReadInt(ifh);
80 		switch(bmftype) {
81 			case BMFTYPE_VERSION:
82 				tmpnum = bmfReadInt(ifh);
83 				if(tmpnum != BMF_VERSION) {
84 					if(tmpnum == 1) {
85 						printf("Warning: Older (compatible) Version1 BMF found - continuing\n");
86 					} else {
87 						DIE(ERROR_BMFVERSION, fname);
88 					}
89 				}
90 				break;
91 			case BMFTYPE_DIR:
92 				tmpnum = bmfReadInt(ifh);
93 				if(!fread(infname, tmpnum, 1, ifh)) {
94 					DIE(ERROR_BMFEOF, fname);
95 				}
96 				infname[tmpnum] = 0;
97 				//printf("Installing directory '%s'\n", configGetPath(infname));
98 				MKDIR(configGetPath(infname));
99 
100 				infname[0] = 0;
101 				break;
102 			case BMFTYPE_FILENAME:
103 				tmpnum = bmfReadInt(ifh);
104 				if(!fread(infname, tmpnum, 1, ifh)) {
105 					DIE(ERROR_BMFEOF, fname);
106 				}
107 				infname[tmpnum] = 0;
108 				//printf("Next file: %s\n", infname);
109 				break;
110 			case BMFTYPE_REGISTER_ADDON:
111 				tmpnum = bmfReadInt(ifh);
112 				if(!fread(infname, tmpnum, 1, ifh)) {
113 					DIE(ERROR_BMFEOF, fname);
114 				}
115 				infname[tmpnum] = 0;
116 				registerAddOn(infname);
117 				infname[0] = 0;
118 				break;
119 			case BMFTYPE_REGISTER_MUSIC:
120 				tmpnum = bmfReadInt(ifh);
121 				if(!fread(infname, tmpnum, 1, ifh)) {
122 					DIE(ERROR_BMFEOF, fname);
123 				}
124 				infname[tmpnum] = 0;
125 				registerMusic(infname);
126 				infname[0] = 0;
127 				break;
128 			case BMFTYPE_REGISTER_POSCAP:
129 				tmpnum = bmfReadInt(ifh);
130 				if(!fread(infname, tmpnum, 1, ifh)) {
131 					DIE(ERROR_BMFEOF, fname);
132 				}
133 				infname[tmpnum] = 0;
134 				registerPosCap(infname);
135 				infname[0] = 0;
136 				break;
137 			case BMFTYPE_METAFILE_COMPRESSED:
138 			case BMFTYPE_METAFILE_UNCOMPRESSED:
139 				if(strlen(infname) == 0) {
140 					printf("Got file without filename!!\n");
141 					DIE(ERROR_FILE_WRITE, "No filename!");
142 				} else {
143 					//printf("Installing file '%s'\n", configGetPath(infname));
144 				}
145 				in_len = bmfReadInt(ifh);
146 				if(!fread(in, in_len, 1, ifh)) {
147 					DIE(ERROR_BMFEOF, fname);
148 				}
149 
150 				if(bmftype == BMFTYPE_METAFILE_UNCOMPRESSED) {
151 					// No compression, just memcopy to output area
152 					//printf("Uncompressed file %s with len %lu\n", infname, in_len);
153 					memcpy(out, in, in_len);
154 					out_len = in_len;
155 				} else {
156 
157 					r = lzo1x_decompress(in,in_len,out,&new_len,NULL);
158 					if (r == LZO_E_OK) {
159 						/*
160 						printf("decompressed %lu bytes back into %lu bytes\n",
161 							(unsigned long) in_len, (unsigned long) new_len);
162 						*/
163 
164 						out_len = new_len;
165 
166 					}
167 					else
168 					{
169 						/* this should NEVER happen */
170 						DIE(ERROR_LZO, "decompression failed");
171 					}
172 
173 				}
174 
175 				// Write File
176 				ofh = fopen(configGetPath(infname), "wb");
177 				if(!ofh) {
178 					DIE(ERROR_FILE_WRITE, configGetPath(infname));
179 				}
180 				fwrite(out, out_len, 1, ofh);
181 				fclose(ofh);
182 
183 
184 				infname[0] = 0; // Delete fname so we don't overwrite
185 				break;
186 
187 			case BMFTYPE_END_OF_FILE:
188 				running = false;
189 				break;
190 
191 			default:
192 				printf("Unknown BMFTYPE %d...\n", bmftype);
193 				exit(1);
194 		}
195 	}
196 
197 	fclose(ifh);
198 
199 	return true;
200 
201 }
202 
extractMetaBMFprogress(Uint32 progress,bool preStartup)203 void extractMetaBMFprogress(Uint32 progress, bool preStartup) {
204 
205      // Avoid compiler warning about unused argument  FIXME
206      progress = 0;
207 
208 	if(preStartup) {
209 		return;
210 	}
211 	// Lock Surface if needed
212 	if (SDL_MUSTLOCK(gScreen))
213 		if (SDL_LockSurface(gScreen) < 0)
214 			return;
215 
216 	if (SDL_MUSTLOCK(decrunchingbg))
217 		if (SDL_LockSurface(decrunchingbg) < 0)
218 			return;
219 
220 
221 	Uint32 bigpitch = gScreen->pitch;
222 	Uint32 bigpitchBG = decrunchingbg->pitch;
223 
224 	long fc_src_long = (long)decrunchingbg->pixels;
225 	long fc_dst_long = (long)gScreen->pixels;
226 
227 	for(Uint32 j=0; j < SCR_HEIGHT; j++) {
228 		fc_src = (fastcopy *)fc_src_long;
229 		fc_dest = (fastcopy *)fc_dst_long;
230 		*fc_dest = *fc_src;
231 		fc_dst_long += bigpitch;
232 		fc_src_long += bigpitchBG;
233 	}
234 
235 	/*
236 	// Progress BG
237 	blend_darkenRect(20, 250, 600, 50, 0x00a0a0a0);
238 
239 	// Progress bar
240 	if(percent) {
241 		drawrect(20, 250, percent*6, 50, 0x909090);
242 	}
243 
244 	// Progress outline
245 	drawrect(20, 250, 600, 1, 0xd0d0d0);
246 	drawrect(20, 250, 1, 50, 0xd0d0d0);
247 	drawrect(20, 300, 600, 1, 0xd0d0d0);
248 	drawrect(619, 250, 1, 50, 0xd0d0d0);
249 	*/
250 
251 
252 	// Unlock Surface if needed
253 	if (SDL_MUSTLOCK(decrunchingbg))
254 		SDL_UnlockSurface(decrunchingbg);
255 	if (SDL_MUSTLOCK(gScreen))
256 		SDL_UnlockSurface(gScreen);
257 	BS_Flip(gScreen); /* Update whole screen */
258 }
259 
260 
deInitExtractMetaBMF()261 void deInitExtractMetaBMF() {
262 	SDL_FreeSurface(decrunchingbg);
263 	decrunchingbg = 0;
264 }
265 
registerAddOn(char * regStr)266 void registerAddOn(char *regStr) {
267 	char regLines[100][1000];
268 	memset(regLines, 0, sizeof(regLines));
269 	FILE* fh;
270 	char line[1000];
271 	char *tmp;
272 	Uint32 cnt = 0;
273 	bool found = false;
274 	fh = fopen(configGetPath("addons.dat"), "r");
275 	if(fh) {
276 		while(fgets(line, sizeof(line), fh)) {
277 			// Remove Comments and newline characters
278 			while((tmp = strchr(line, '\n'))) {
279 				*tmp = 0;
280 			}
281 			while((tmp = strchr(line, '\r'))) {
282 				*tmp = 0;
283 			}
284 			while((tmp = strchr(line, '#'))) {
285 				*tmp = 0;
286 			}
287 
288 			if(line[0] == '\0') {
289 				// Ignore remark or empty line
290 				continue;
291 			}
292 			sprintf(regLines[cnt], "%s", line);
293 			cnt++;
294 		}
295 		fclose(fh);
296 
297 		for(Uint32 i = 0; i < cnt; i++) {
298 			if(strcmp(regStr, regLines[i]) == 0) {
299 				found = true;
300 			}
301 		}
302 	}
303 
304 	if(!found) {
305 		sprintf(regLines[cnt], "%s", regStr);
306 		cnt++;
307 
308 		fh = fopen(configGetPath("addons.dat"), "w");
309 		if(!fh) {
310 			DIE(ERROR_FILE_WRITE, configGetPath("addons.dat"));
311 		}
312 		for(Uint32 i = 0; i < cnt; i++) {
313 			fprintf(fh, "%s\r\n", regLines[i]);
314 		}
315 		fclose(fh);
316 	}
317 	return;
318 }
319 
registerMusic(char * regStr)320 void registerMusic(char *regStr) {
321 	char regLines[100][1000];
322 	memset(regLines, 0, sizeof(regLines));
323 	FILE* fh;
324 	char line[1000];
325 	char *tmp;
326 	Uint32 cnt = 0;
327 	bool found = false;
328 	fh = fopen(configGetPath("playersounds.dat"), "r");
329 	if(fh) {
330 		while(fgets(line, sizeof(line), fh)) {
331 			// Remove Comments and newline characters
332 			while((tmp = strchr(line, '\n'))) {
333 				*tmp = 0;
334 			}
335 			while((tmp = strchr(line, '\r'))) {
336 				*tmp = 0;
337 			}
338 			while((tmp = strchr(line, '#'))) {
339 				*tmp = 0;
340 			}
341 
342 			if(line[0] == '\0') {
343 				// Ignore remark or empty line
344 				continue;
345 			}
346 			sprintf(regLines[cnt], "%s", line);
347 			cnt++;
348 		}
349 		fclose(fh);
350 
351 		for(Uint32 i = 0; i < cnt; i++) {
352 			if(strcmp(regStr, regLines[i]) == 0) {
353 				found = true;
354 			}
355 		}
356 	}
357 
358 	if(!found) {
359 		sprintf(regLines[cnt], "%s", regStr);
360 		cnt++;
361 
362 		fh = fopen(configGetPath("playersounds.dat"), "w");
363 		if(!fh) {
364 			DIE(ERROR_FILE_WRITE, configGetPath("playersounds.dat"));
365 		}
366 		for(Uint32 i = 0; i < cnt; i++) {
367 			fprintf(fh, "%s\r\n", regLines[i]);
368 		}
369 		fclose(fh);
370 	}
371 	return;
372 }
373 
registerPosCap(char * regStr)374 void registerPosCap(char *regStr) {
375 	char regLines[100][1000];
376 	memset(regLines, 0, sizeof(regLines));
377 	FILE* fh;
378 	char line[1000];
379 	char *tmp;
380 	Uint32 cnt = 0;
381 	bool found = false;
382 	fh = fopen(configGetPath("poscaps.dat"), "r");
383 	if(fh) {
384 		while(fgets(line, sizeof(line), fh)) {
385 			// Remove Comments and newline characters
386 			while((tmp = strchr(line, '\n'))) {
387 				*tmp = 0;
388 			}
389 			while((tmp = strchr(line, '\r'))) {
390 				*tmp = 0;
391 			}
392 			while((tmp = strchr(line, '#'))) {
393 				*tmp = 0;
394 			}
395 
396 			if(line[0] == '\0') {
397 				// Ignore remark or empty line
398 				continue;
399 			}
400 			sprintf(regLines[cnt], "%s", line);
401 			cnt++;
402 		}
403 		fclose(fh);
404 
405 		for(Uint32 i = 0; i < cnt; i++) {
406 			if(strcmp(regStr, regLines[i]) == 0) {
407 				found = true;
408 			}
409 		}
410 	}
411 
412 	if(!found) {
413 		sprintf(regLines[cnt], "%s", regStr);
414 		cnt++;
415 
416 		fh = fopen(configGetPath("playersounds.dat"), "w");
417 		if(!fh) {
418 			DIE(ERROR_FILE_WRITE, configGetPath("playersounds.dat"));
419 		}
420 		for(Uint32 i = 0; i < cnt; i++) {
421 			fprintf(fh, "%s\r\n", regLines[i]);
422 		}
423 		fclose(fh);
424 	}
425 	return;
426 }
427