Added AI by Ricardo Cruz. This also adds mouse controls.
[crow/jumpnbump.git] / modify / gobpack.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4
5 typedef struct {
6         int num_images;
7         int *width;
8         int *height;
9         int *hs_x;
10         int *hs_y;
11         void **data;
12         void **orig_data;
13 } gob_t;
14
15 static void read_pcx(FILE * handle, void *buf, int buf_len, char *pal)
16 {
17         unsigned char *buffer=buf;
18         short c1;
19         short a, b;
20         long ofs1;
21         if (buffer != 0) {
22                 fseek(handle, 128, SEEK_CUR);
23                 ofs1 = 0;
24                 while (ofs1 < buf_len) {
25                         a = fgetc(handle);
26                         if ((a & 0xc0) == 0xc0) {
27                                 b = fgetc(handle);
28                                 a &= 0x3f;
29                                 for (c1 = 0; c1 < a && ofs1 < buf_len; c1++)
30                                         buffer[ofs1++] = (char) b;
31                         } else
32                                 buffer[ofs1++] = (char) a;
33                 }
34                 if (pal != 0) {
35                         fseek(handle, 1, SEEK_CUR);
36                         for (c1 = 0; c1 < 768; c1++)
37                                 pal[c1] = fgetc(handle) >> 2;
38                 }
39         }
40 }
41
42 static void write_pcx(FILE *pcxfile, unsigned char *data, int width, int height, unsigned char *palette)
43 {
44         int    i;
45
46         fputc(0x0a, pcxfile); /* manufacturer */
47         fputc(5, pcxfile); /* version */
48         fputc(1, pcxfile); /* encoding */
49         fputc(8, pcxfile); /* bits_per_pixel */
50         fputc(0, pcxfile); /* xmin */
51         fputc(0, pcxfile);
52         fputc(0, pcxfile); /* ymin */
53         fputc(0, pcxfile);
54         fputc((width - 1) & 0xff, pcxfile); /* xmax */
55         fputc(((width - 1) >> 8) & 0xff, pcxfile);
56         fputc((height - 1) & 0xff, pcxfile); /* ymax */
57         fputc(((height - 1) >> 8) & 0xff, pcxfile);
58         fputc(width & 0xff, pcxfile); /* hres */
59         fputc((width >> 8) & 0xff, pcxfile);
60         fputc(height & 0xff, pcxfile); /* vres */
61         fputc((height >> 8) & 0xff, pcxfile);
62         for (i = 0; i < 48; i++) /* palette */
63                 fputc(0, pcxfile);
64         fputc(0, pcxfile); /* reserved */
65         fputc(1, pcxfile); /* color_planes */
66         fputc(width & 0xff, pcxfile); /* bytes_per_line */
67         fputc((width >> 8) & 0xff, pcxfile);
68         fputc(1 & 0xff, pcxfile); /* palette_type */
69         fputc((1 >> 8) & 0xff, pcxfile);
70         for (i = 0; i < 58; i++) /* filler */
71                 fputc(0, pcxfile);
72
73         /* pack the image */
74
75         for (i = 0 ; i < width*height ; i++)
76                 if ( (*data & 0xc0) != 0xc0)
77                         fputc(*data++, pcxfile);
78                 else
79                 {
80                         fputc(0xc1, pcxfile);
81                         fputc(*data++, pcxfile);
82                 }
83
84         /* write the palette */
85
86         fputc(0x0c, pcxfile); /* palette ID byte */
87         if (palette)
88                 for (i = 0 ; i < 768 ; i++)
89                         fputc(*palette++, pcxfile);
90         else
91                 for (i = 0 ; i < 768 ; i++)
92                         fputc(i / 3, pcxfile);
93 }
94
95 int read_gob(FILE *handle, gob_t *gob, int len)
96 {
97         unsigned char *gob_data;
98         int i;
99
100         gob_data = malloc(len);
101         fread(gob_data, 1, len, handle);
102
103         gob->num_images = (short)((gob_data[0]) + (gob_data[1] << 8));
104
105         gob->width = malloc(gob->num_images*sizeof(int));
106         gob->height = malloc(gob->num_images*sizeof(int));
107         gob->hs_x = malloc(gob->num_images*sizeof(int));
108         gob->hs_y = malloc(gob->num_images*sizeof(int));
109         gob->data = malloc(gob->num_images*sizeof(void *));
110         gob->orig_data = malloc(gob->num_images*sizeof(void *));
111         for (i=0; i<gob->num_images; i++) {
112                 int image_size;
113                 int offset;
114
115                 offset = (gob_data[i*4+2]) + (gob_data[i*4+3] << 8) + (gob_data[i*4+4] << 16) + (gob_data[i*4+5] << 24);
116
117                 gob->width[i]  = (short)((gob_data[offset]) + (gob_data[offset+1] << 8)); offset += 2;
118                 gob->height[i] = (short)((gob_data[offset]) + (gob_data[offset+1] << 8)); offset += 2;
119                 gob->hs_x[i]   = (short)((gob_data[offset]) + (gob_data[offset+1] << 8)); offset += 2;
120                 gob->hs_y[i]   = (short)((gob_data[offset]) + (gob_data[offset+1] << 8)); offset += 2;
121
122                 image_size = gob->width[i] * gob->height[i];
123                 gob->orig_data[i] = malloc(image_size);
124                 memcpy(gob->orig_data[i], &gob_data[offset], image_size);
125                 gob->data[i] = (unsigned short *)gob->orig_data[i];
126         }
127         free(gob_data);
128         return 0;
129 }
130
131 int write_gob(FILE *handle, gob_t *gob)
132 {
133         int i;
134         int offset;
135
136         fputc((gob->num_images >> 0) & 0xff, handle);
137         fputc((gob->num_images >> 8) & 0xff, handle);
138
139         offset = 2 + (gob->num_images * 4);
140
141         for (i=0; i<gob->num_images; i++) {
142                 fputc((offset >> 0) & 0xff, handle);
143                 fputc((offset >> 8) & 0xff, handle);
144                 fputc((offset >> 16) & 0xff, handle);
145                 fputc((offset >> 24) & 0xff, handle);
146
147                 offset += 8;
148                 offset += gob->width[i] * gob->height[i];
149         }
150         for (i=0; i<gob->num_images; i++) {
151                 fputc((gob->width[i] >> 0) & 0xff, handle);
152                 fputc((gob->width[i] >> 8) & 0xff, handle);
153
154                 fputc((gob->height[i] >> 0) & 0xff, handle);
155                 fputc((gob->height[i] >> 8) & 0xff, handle);
156
157                 fputc((gob->hs_x[i] >> 0) & 0xff, handle);
158                 fputc((gob->hs_x[i] >> 8) & 0xff, handle);
159
160                 fputc((gob->hs_y[i] >> 0) & 0xff, handle);
161                 fputc((gob->hs_y[i] >> 8) & 0xff, handle);
162
163                 fwrite(gob->data[i], 1, gob->width[i] * gob->height[i], handle);
164         }
165         return 0;
166 }
167
168 int main(int argc, char **argv)
169 {
170         int usage = 0;
171         int unpack = 0;
172         FILE *f;
173         int len;
174         gob_t gob;
175         char *filename = NULL;
176
177         if (argc < 2)
178                 usage = 1;
179
180         if (argc > 1)
181                 if (argv[1][0] == '-') {
182                         if (argv[1][1] == 'u') {
183                                 if (argc < 3)
184                                         usage = 1;
185                                 unpack = 1;
186                         } else
187                                 usage = 1;
188                 }
189         
190         if (usage) {
191                 printf("Usage: gobpack [-u] <file> [palette.pcx]\n\t-u to unpack the gob\n");
192                 return 1;
193         }
194
195         if (unpack) {
196                 int width, height;
197                 int x_count, y_count;
198                 int xi, yi;
199                 int i;
200                 unsigned char *data;
201                 unsigned char *dst;
202                 unsigned char palette[768];
203                 unsigned char *pal = NULL;
204
205                 if (argc > 3) {
206                         f = fopen(argv[3], "rb");
207                         if (f) {
208                                 fseek(f, -769, SEEK_END);
209                                 i = fgetc(f);
210                                 if (i == 0x0c) {
211                                         pal = palette;
212                                         fread(pal, 1, 768, f);
213                                 }
214                                 fclose(f);
215                         }
216                 }
217
218                 filename = malloc(strlen(argv[2]) + 5);
219                 if (!filename) {
220                         printf("Not enough memory!\n");
221                         return -1;
222                 }
223
224                 strcpy(filename, argv[2]);
225                 strcat(filename, ".gob");
226                 f = fopen(filename, "rb");
227                 if (!f) {
228                         printf("Couldn't open file %s\n", filename);
229                         return -1;
230                 }
231                 fseek(f, 0, SEEK_END);
232                 len = ftell(f);
233                 fseek(f, 0, SEEK_SET);
234
235                 read_gob(f, &gob, len);
236
237                 fclose(f);
238
239                 width = 0;
240                 height = 0;
241                 for (i = 0; i < gob.num_images; i++) {
242                         if (gob.height[i] > height)
243                                 height = gob.height[i];
244                         if (gob.width[i] > width)
245                                 width = gob.width[i];
246                 }
247                 width+=2;
248                 height+=2;
249
250                 data = malloc(400*256);
251                 if (!data) {
252                         printf("Not enough memory!\n");
253                         return -1;
254                 }
255                 memset(data, 0, 400*256);
256
257                 x_count = 400 / width;
258                 y_count = 256 / width;
259
260                 for (yi = 0; yi < y_count; yi++) {
261                         for (xi = 0; xi < x_count; xi++) {
262                                 int x,y;
263                                 unsigned char *src;
264
265                                 i = yi * x_count + xi;
266                                 if (i >= gob.num_images)
267                                         continue;
268
269                                 src = gob.data[i];
270                                 dst = &data[(yi * height) * 400 + (xi * width)];
271                                 for (y = 0; y < gob.height[i]; y++) {
272                                         for (x = 0; x < gob.width[i]; x++) {
273                                                 dst[y * 400 + x] = src[y * gob.width[i] + x];
274                                         }
275                                 }
276                         }
277                 }
278                 
279                 strcpy(filename, argv[2]);
280                 strcat(filename, ".pcx");
281                 f = fopen(filename, "wb");
282                 if (!f) {
283                         printf("Couldn't open file %s\n", filename);
284                         return -1;
285                 }
286
287                 write_pcx(f, data, 400, 256, pal);
288
289                 fclose(f);
290
291                 strcpy(filename, argv[2]);
292                 strcat(filename, ".txt");
293                 f = fopen(filename, "w");
294                 if (!f) {
295                         printf("Couldn't open file %s\n", filename);
296                         return -1;
297                 }
298
299                 fprintf(f, "num_images: %i\n\n", gob.num_images);
300                 for (yi = 0; yi < y_count; yi++) {
301                         for (xi = 0; xi < x_count; xi++) {
302                                 
303                                 i = yi * x_count + xi;
304                                 if (i >= gob.num_images)
305                                         continue;
306
307                                 fprintf(f, "image: %i\n", i + 1);
308                                 fprintf(f, "x: %i\n", (xi * width));
309                                 fprintf(f, "y: %i\n", (yi * height));
310                                 fprintf(f, "width: %i\n", gob.width[i]);
311                                 fprintf(f, "height: %i\n", gob.height[i]);
312                                 fprintf(f, "hotspot_x: %i\n", gob.hs_x[i]);
313                                 fprintf(f, "hotspot_y: %i\n", gob.hs_y[i]);
314                                 fprintf(f, "\n");
315                         }
316                 }
317
318                 fclose(f);
319         } else {
320                 unsigned char *data;
321                 int i = 0;
322                 int x_pos = 0, y_pos = 0;
323
324                 data = malloc(400*256);
325                 if (!data) {
326                         printf("Not enough memory!\n");
327                         return -1;
328                 }
329
330                 filename = malloc(strlen(argv[1]) + 5);
331                 if (!filename) {
332                         printf("Not enough memory!\n");
333                         return -1;
334                 }
335
336                 strcpy(filename, argv[1]);
337                 strcat(filename, ".pcx");
338                 f = fopen(filename, "rb");
339                 if (!f) {
340                         printf("Couldn't open file %s\n", filename);
341                         return -1;
342                 }
343
344                 read_pcx(f, data, 400*256, NULL);
345
346                 fclose(f);
347
348                 strcpy(filename, argv[1]);
349                 strcat(filename, ".txt");
350                 f = fopen(filename, "r");
351                 if (!f) {
352                         printf("Couldn't open file %s\n", filename);
353                         return -1;
354                 }
355
356                 gob.num_images = 0;
357
358                 while (!feof(f)) {
359                         char buffer[1024];
360                         int value;
361
362                         fscanf(f, "%s %i\n", buffer, &value);
363                         if (strcmp(buffer, "num_images:") == 0) {
364                                 if (gob.num_images != 0) {
365                                         printf("Parse error in %s\n", filename);
366                                         return -1;
367                                 }
368                                 gob.num_images = value;
369                                 gob.width = malloc(gob.num_images*sizeof(int));
370                                 gob.height = malloc(gob.num_images*sizeof(int));
371                                 gob.hs_x = malloc(gob.num_images*sizeof(int));
372                                 gob.hs_y = malloc(gob.num_images*sizeof(int));
373                                 gob.data = malloc(gob.num_images*sizeof(void *));
374                                 gob.orig_data = malloc(gob.num_images*sizeof(void *));
375                         } else if (strcmp(buffer, "image:") == 0) {
376                                 i = value - 1;
377                         } else if (strcmp(buffer, "x:") == 0) {
378                                 x_pos = value;
379                         } else if (strcmp(buffer, "y:") == 0) {
380                                 y_pos = value;
381                         } else if (strcmp(buffer, "width:") == 0) {
382                                 gob.width[i] = value;
383                         } else if (strcmp(buffer, "height:") == 0) {
384                                 gob.height[i] = value;
385                         } else if (strcmp(buffer, "hotspot_x:") == 0) {
386                                 gob.hs_x[i] = value;
387                         } else if (strcmp(buffer, "hotspot_y:") == 0) {
388                                 int x, y;
389                                 unsigned char *dst;
390
391                                 gob.hs_y[i] = value;
392                                 gob.orig_data[i] = malloc(gob.width[i] * gob.height[i]);
393                                 gob.data[i] = gob.orig_data[i];
394                                 dst = gob.data[i];
395                                 for (y = 0; y < gob.height[i]; y++) {
396                                         for (x = 0; x < gob.width[i]; x++) {
397                                                 dst[y * gob.width[i] + x] = data[(y_pos + y) * 400 + (x_pos + x)];
398                                         }
399                                 }
400                         }
401                 }
402
403                 fclose(f);
404
405                 strcpy(filename, argv[1]);
406                 strcat(filename, ".gob");
407                 f = fopen(filename, "wb");
408                 if (!f) {
409                         printf("Couldn't open file %s\n", filename);
410                         return -1;
411                 }
412
413                 write_gob(f, &gob);
414
415                 fclose(f);
416
417                 printf("%s build\n", filename);
418         }
419
420         return 0;
421 }