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