Merge branch 'feature/handle-quit-event'
[jumpnbump.git] / modify / gobpack.c
blob7e524a80233b446e0d2ddb85942a6ed4a553974d
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
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;
15 static void read_pcx(FILE * handle, void *buf, int buf_len, char *pal)
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;
34 if (pal != 0) {
35 fseek(handle, 1, SEEK_CUR);
36 for (c1 = 0; c1 < 768; c1++)
37 pal[c1] = fgetc(handle) >> 2;
42 static void write_pcx(FILE *pcxfile, unsigned char *data, int width, int height, unsigned char *palette)
44 int i;
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);
73 /* pack the image */
75 for (i = 0 ; i < width*height ; i++)
76 if ( (*data & 0xc0) != 0xc0)
77 fputc(*data++, pcxfile);
78 else
80 fputc(0xc1, pcxfile);
81 fputc(*data++, pcxfile);
84 /* write the palette */
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);
95 int read_gob(FILE *handle, gob_t *gob, int len)
97 unsigned char *gob_data;
98 int i;
100 gob_data = malloc(len);
101 fread(gob_data, 1, len, handle);
103 gob->num_images = (short)((gob_data[0]) + (gob_data[1] << 8));
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;
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);
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;
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];
127 free(gob_data);
128 return 0;
131 int write_gob(FILE *handle, gob_t *gob)
133 int i;
134 int offset;
136 fputc((gob->num_images >> 0) & 0xff, handle);
137 fputc((gob->num_images >> 8) & 0xff, handle);
139 offset = 2 + (gob->num_images * 4);
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);
147 offset += 8;
148 offset += gob->width[i] * gob->height[i];
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);
154 fputc((gob->height[i] >> 0) & 0xff, handle);
155 fputc((gob->height[i] >> 8) & 0xff, handle);
157 fputc((gob->hs_x[i] >> 0) & 0xff, handle);
158 fputc((gob->hs_x[i] >> 8) & 0xff, handle);
160 fputc((gob->hs_y[i] >> 0) & 0xff, handle);
161 fputc((gob->hs_y[i] >> 8) & 0xff, handle);
163 fwrite(gob->data[i], 1, gob->width[i] * gob->height[i], handle);
165 return 0;
168 int main(int argc, char **argv)
170 int usage = 0;
171 int unpack = 0;
172 FILE *f;
173 int len;
174 gob_t gob;
175 char *filename = NULL;
177 if (argc < 2)
178 usage = 1;
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;
190 if (usage) {
191 printf("Usage: gobpack [-u] <file> [palette.pcx]\n\t-u to unpack the gob\n");
192 return 1;
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;
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);
214 fclose(f);
218 filename = malloc(strlen(argv[2]) + 5);
219 if (!filename) {
220 printf("Not enough memory!\n");
221 return -1;
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;
231 fseek(f, 0, SEEK_END);
232 len = ftell(f);
233 fseek(f, 0, SEEK_SET);
235 read_gob(f, &gob, len);
237 fclose(f);
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];
247 width+=2;
248 height+=2;
250 data = malloc(400*256);
251 if (!data) {
252 printf("Not enough memory!\n");
253 return -1;
255 memset(data, 0, 400*256);
257 x_count = 400 / width;
258 y_count = 256 / width;
260 for (yi = 0; yi < y_count; yi++) {
261 for (xi = 0; xi < x_count; xi++) {
262 int x,y;
263 unsigned char *src;
265 i = yi * x_count + xi;
266 if (i >= gob.num_images)
267 continue;
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];
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;
287 write_pcx(f, data, 400, 256, pal);
289 fclose(f);
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;
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++) {
303 i = yi * x_count + xi;
304 if (i >= gob.num_images)
305 continue;
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");
318 fclose(f);
319 } else {
320 unsigned char *data;
321 int i = 0;
322 int x_pos = 0, y_pos = 0;
324 data = malloc(400*256);
325 if (!data) {
326 printf("Not enough memory!\n");
327 return -1;
330 filename = malloc(strlen(argv[1]) + 5);
331 if (!filename) {
332 printf("Not enough memory!\n");
333 return -1;
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;
344 read_pcx(f, data, 400*256, NULL);
346 fclose(f);
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;
356 gob.num_images = 0;
358 while (!feof(f)) {
359 char buffer[1024];
360 int value;
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;
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;
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)];
403 fclose(f);
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;
413 write_gob(f, &gob);
415 fclose(f);
417 printf("%s build\n", filename);
420 return 0;