1 /*
2  * xvmaki.c - load routine for `MAKI' format pictures.
3  *
4  * The `MAKI' format was used by some Japanese personal computer users.
5  */
6 
7 #include "xv.h"
8 #include <setjmp.h>
9 
10 #ifdef HAVE_MAKI
11 
12 typedef unsigned short data16;
13 typedef unsigned int data32;
14 
15 struct maki_info {
16     jmp_buf jmp;
17     FILE *fp;
18     long fsize;
19     int x0, y0, x1, y1;
20     int width, height;
21     float aspect;
22     long fb_size;
23     long pa_size, pb_size;
24     int m_maki01b, m_200, m_dig8;
25     data16 ext_flag;
26     byte *fa, *fb, *pa, *pb;
27     byte *vs;
28     int numcols;
29     byte *forma, *formb;
30 };
31 
32 
33 static void maki_open_file             PARM((struct maki_info*, char*));
34 static void maki_check_id              PARM((struct maki_info*));
35 static void maki_skip_comment          PARM((struct maki_info*));
36 static void maki_read_header           PARM((struct maki_info*));
37 static void maki_read_palette          PARM((struct maki_info*,
38 					     byte*, byte*, byte*));
39 static void maki_read_flags            PARM((struct maki_info*));
40 static void maki_read_pixel_data       PARM((struct maki_info*));
41 static void maki_expand_virtual_screen PARM((struct maki_info*));
42 static void maki_expand_pixel_data     PARM((struct maki_info*, byte**));
43 static void maki_init_info             PARM((struct maki_info*));
44 
45 static void maki_make_pixel_data       PARM((struct maki_info*, byte*));
46 static void maki_make_virtual_screen   PARM((struct maki_info*));
47 static void maki_make_flags            PARM((struct maki_info*));
48 static void maki_write_check_id        PARM((struct maki_info*));
49 static void maki_write_comment         PARM((struct maki_info*));
50 static void maki_write_header          PARM((struct maki_info*));
51 static void maki_write_palette         PARM((struct maki_info*,
52 					     byte*, byte*, byte*, int));
53 static void maki_write_flags           PARM((struct maki_info*));
54 static void maki_write_pixel_data      PARM((struct maki_info*));
55 
56 static void maki_cleanup_maki_info     PARM((struct maki_info*, int));
57 static void maki_cleanup_pinfo         PARM((PICINFO*));
58 static void maki_memory_error          PARM((char*, char*));
59 static void maki_error                 PARM((struct maki_info*, int));
60 static void maki_file_error            PARM((struct maki_info*, int));
61 static void maki_file_warning          PARM((struct maki_info*, int));
62 static void maki_show_maki_info        PARM((struct maki_info*));
63 static void *maki_malloc               PARM((size_t, char*));
64 static void *maki_realloc              PARM((void *, size_t, char*));
65 
66 static char maki_id_a[] = "MAKI01A ";
67 static char maki_id_b[] = "MAKI01B ";
68 
69 static char *maki_msgs[] = {
70     NULL,
71 #define MAKI_OPEN 1
72     "can't open file.",
73 #define MAKI_CORRUPT 2
74     "file corrupted.",
75 #define MAKI_FORMAT 3
76     "not MAKI format.",
77 #define MAKI_BAD_DATA 4
78     "bad data.",
79 #define MAKI_COMMENT 5
80     "no '^Z' after comment.",
81 #define MAKI_SIZE 6
82     "bad size.",
83 #define MAKI_WRITE 7
84     "write failed.",
85 };
86 
87 #define H4(b) ((b) >> 4 & 0xf)
88 #define L4(b) ((b)      & 0xf)
89 #define error(msg_num) longjmp(mi->jmp, msg_num)
90 
LoadMAKI(fname,pinfo)91 int LoadMAKI(fname, pinfo)
92     char *fname;
93     PICINFO *pinfo;
94 {
95     struct maki_info maki;
96     int e;
97 
98     if(DEBUG) fputs("LoadMAKI:\n", stderr);
99 
100     pinfo->comment = NULL;
101     maki_init_info(&maki);
102     if((e = setjmp(maki.jmp)) != 0){
103 	/* When an error occurs, comes here. */
104 	maki_cleanup_maki_info(&maki, 0);
105 	maki_cleanup_pinfo(pinfo);
106 	return 0;
107     }
108 
109     maki_open_file(&maki, fname);
110     maki_check_id(&maki);
111     maki_skip_comment(&maki);
112     maki_read_header(&maki);
113     maki_read_palette(&maki, pinfo->r, pinfo->g, pinfo->b);
114     maki_read_flags(&maki);
115     maki_read_pixel_data(&maki);
116     maki_expand_virtual_screen(&maki);
117     maki_expand_pixel_data(&maki, &pinfo->pic);
118 
119     pinfo->w = pinfo->normw = maki.width;
120     pinfo->h = pinfo->normh = maki.height;
121     pinfo->type = PIC8;
122     pinfo->frmType = F_MAKI;
123     pinfo->colType = F_FULLCOLOR;
124     sprintf(pinfo->fullInfo, "MAKI, 16 colors (%ld bytes)", maki.fsize);
125     sprintf(pinfo->shrtInfo, "%dx%d MAKI", maki.width, maki.height);
126     normaspect = maki.aspect;
127 
128     maki_cleanup_maki_info(&maki, 0);
129     return 1;
130 }
131 
maki_open_file(mi,fname)132 static void maki_open_file(mi, fname)
133     struct maki_info *mi;
134     char *fname;
135 {
136     if((mi->fp = fopen(fname, "rb")) == NULL)
137 	maki_file_error(mi, MAKI_OPEN);
138     fseek(mi->fp, (size_t) 0, SEEK_END);
139     mi->fsize = ftell(mi->fp);
140     fseek(mi->fp, (size_t) 0, SEEK_SET);
141 }
142 
maki_check_id(mi)143 static void maki_check_id(mi)
144     struct maki_info *mi;
145 {
146     char buf[8];
147     if(fread(buf, (size_t) 8, (size_t) 1, mi->fp) != 1)
148 	maki_file_error(mi, MAKI_CORRUPT);
149     if(strncmp(buf, maki_id_a, (size_t) 8) != 0 &&
150        strncmp(buf, maki_id_b, (size_t) 8) != 0)
151 	maki_error(mi, MAKI_FORMAT);
152     mi->m_maki01b = (buf[6] == 'B');
153 }
154 
maki_skip_comment(mi)155 static void maki_skip_comment(mi)
156     struct maki_info *mi;
157 {
158     int i;
159     int c;
160 
161     for(i = 0; i < 24; i++){
162 	if((c = fgetc(mi->fp)) == EOF)
163 	    maki_file_error(mi, MAKI_CORRUPT);
164 	if(c == '\032')	/* ^Z, 0x1a */
165 	    break;
166     }
167     if(c != '\032')
168 	maki_file_error(mi, MAKI_COMMENT);
169 
170     fseek(mi->fp, 32L, SEEK_SET);
171 }
172 
maki_read_header(mi)173 static void maki_read_header(mi)
174     struct maki_info *mi;
175 {
176     byte buf[16];
177 
178     if(fread(buf, (size_t) 16, (size_t) 1, mi->fp) != 1)
179 	maki_file_error(mi, MAKI_CORRUPT);
180 
181     mi->fb_size  = (long)buf[ 0] << 8 | (long)buf[ 1];
182     mi->pa_size  = (long)buf[ 2] << 8 | (long)buf[ 3];
183     mi->pb_size  = (long)buf[ 4] << 8 | (long)buf[ 5];
184     mi->ext_flag = (long)buf[ 6] << 8 | (long)buf[ 7];
185     mi->x0       = (long)buf[ 8] << 8 | (long)buf[ 9];
186     mi->y0       = (long)buf[10] << 8 | (long)buf[11];
187     mi->x1       = (long)buf[12] << 8 | (long)buf[13];
188     mi->y1       = (long)buf[14] << 8 | (long)buf[15];
189 
190     mi->width  = mi->x1-- - mi->x0;
191     mi->height = mi->y1-- - mi->y0;
192     mi->m_200  = mi->ext_flag & 1;
193     mi->m_dig8 = mi->ext_flag & 2;
194     mi->aspect = mi->m_200 ? 0.5 : 1.0;
195 
196     if(DEBUG) maki_show_maki_info(mi);
197 }
198 
maki_read_palette(mi,r,g,b)199 static void maki_read_palette(mi, r, g, b)
200     struct maki_info *mi;
201     byte *r, *g, *b;
202 {
203     byte buf[48], *p;
204 
205     if(fread(buf, (size_t) 48, (size_t) 1, mi->fp) != 1)
206 	maki_file_error(mi, MAKI_CORRUPT);
207 
208     for(p = buf; p < &buf[48]; ){
209 	*g++ = *p++;
210 	*r++ = *p++;
211 	*b++ = *p++;
212     }
213 }
214 
maki_read_flags(mi)215 static void maki_read_flags(mi)
216     struct maki_info *mi;
217 {
218     mi->fa = maki_malloc((size_t) 1000       , "maki_read_flags#1");
219     mi->fb = maki_malloc((size_t) mi->fb_size, "maki_read_flags#2");
220 
221     if(fread(mi->fa, (size_t) 1000, (size_t) 1, mi->fp) != 1)
222 	maki_file_warning(mi, MAKI_CORRUPT);
223     if(fread(mi->fb, (size_t) mi->fb_size, (size_t) 1, mi->fp) != 1)
224 	maki_file_warning(mi, MAKI_CORRUPT);
225 }
226 
maki_read_pixel_data(mi)227 static void maki_read_pixel_data(mi)
228     struct maki_info *mi;
229 {
230     mi->pa = maki_malloc((size_t) mi->pa_size, "maki_read_pixel_data#1");
231     mi->pb = maki_malloc((size_t) mi->pb_size, "maki_read_pixel_data#2");
232 
233     if(fread(mi->pa, (size_t) mi->pa_size, (size_t) 1, mi->fp) != 1)
234 	maki_file_warning(mi, MAKI_CORRUPT);
235     if(fread(mi->pb, (size_t) mi->pb_size, (size_t) 1, mi->fp) != 1)
236 	maki_file_warning(mi, MAKI_CORRUPT);
237 }
238 
maki_expand_virtual_screen(mi)239 static void maki_expand_virtual_screen(mi)
240     struct maki_info *mi;
241 {
242     int x, y, fai, fbi;
243     int bpl = mi->width / 2 / 8;		/* bytes per line */
244     byte mask;
245     mi->vs = maki_malloc((size_t) bpl * mi->height,  // GRR POSSIBLE OVERFLOW / FIXME
246 			 "maki_expand_virtual_screen");
247 
248     fai = fbi = 0;
249     mask = 0x80;
250     for(y = 0; y < mi->height; y += 4){
251 	for(x = 0; x < mi->width / 2; x += 4){
252 	    if(mi->fa[fai] & mask){
253 		byte bh, bl;
254 		bh = mi->fb[fbi++];
255 		bl = mi->fb[fbi++];
256 		if(x % 8 == 0){
257 		    mi->vs[ y      * bpl + x / 8] = H4(bh) << 4;
258 		    mi->vs[(y + 1) * bpl + x / 8] = L4(bh) << 4;
259 		    mi->vs[(y + 2) * bpl + x / 8] = H4(bl) << 4;
260 		    mi->vs[(y + 3) * bpl + x / 8] = L4(bl) << 4;
261 		}else{
262 		    mi->vs[ y      * bpl + x / 8] |= H4(bh);
263 		    mi->vs[(y + 1) * bpl + x / 8] |= L4(bh);
264 		    mi->vs[(y + 2) * bpl + x / 8] |= H4(bl);
265 		    mi->vs[(y + 3) * bpl + x / 8] |= L4(bl);
266 		}
267 	    }else{
268 		if(x % 8 == 0){
269 		    mi->vs[ y      * bpl + x / 8] = 0;
270 		    mi->vs[(y + 1) * bpl + x / 8] = 0;
271 		    mi->vs[(y + 2) * bpl + x / 8] = 0;
272 		    mi->vs[(y + 3) * bpl + x / 8] = 0;
273 		}else{
274 /*		    mi->vs[ y      * bpl + x / 8] |= 0;
275 		    mi->vs[(y + 1) * bpl + x / 8] |= 0;
276 		    mi->vs[(y + 2) * bpl + x / 8] |= 0;
277 		    mi->vs[(y + 3) * bpl + x / 8] |= 0; */
278 		}
279 	    }
280 
281 	    if((mask >>= 1) == 0){
282 		mask = 0x80;
283 		fai++;
284 	    }
285 	}
286     }
287 }
288 
maki_expand_pixel_data(mi,pic)289 static void maki_expand_pixel_data(mi, pic)
290     struct maki_info *mi;
291     byte **pic;
292 {
293     int x, y;
294     int vsi, pi, max_pi;
295     byte *p;
296     byte mask;
297     int gap;
298     *pic = maki_malloc((size_t) mi->width * mi->height,  // GRR POSSIBLE OVERFLOW / FIXME
299 		       "maki_expand_pixel_data");
300 
301     vsi = pi = 0;
302     p = mi->pa;
303     max_pi = mi->pa_size - 1;
304     mask = 0x80;
305     for(y = 0; y < mi->height; y++){
306 	for(x = 0; x < mi->width; x += 2){
307 	    if(mi->vs[vsi] & mask){
308 		if(pi > max_pi){
309 		    if(p == mi->pb)
310 			maki_error(mi, MAKI_BAD_DATA);
311 		    pi = 0;
312 		    p = mi->pb;
313 		    max_pi = mi->pb_size - 1;
314 		}
315 		(*pic)[y * mi->width + x    ] = H4(p[pi]);
316 		(*pic)[y * mi->width + x + 1] = L4(p[pi]);
317 		pi++;
318 	    }else{
319 		(*pic)[y * mi->width + x    ] = 0;
320 		(*pic)[y * mi->width + x + 1] = 0;
321 	    }
322 
323 	    if((mask >>= 1) == 0){
324 		mask = 0x80;
325 		vsi++;
326 	    }
327 	}
328     }
329 
330     gap = mi->m_maki01b ? 4 : 2;
331 
332     for(y = gap; y < mi->height; y++){
333 	for(x = 0; x < mi->width; x++)
334 	    (*pic)[y * mi->width + x] ^= (*pic)[(y - gap) * mi->width + x];
335     }
336 }
337 
338 
WriteMAKI(fp,pic,ptype,w,h,rmap,gmap,bmap,numcols,colorstyle)339 int WriteMAKI(fp, pic, ptype, w, h, rmap, gmap, bmap, numcols, colorstyle)
340     FILE *fp;
341     byte *pic;
342     int ptype, w, h;
343     byte *rmap, *gmap, *bmap;
344     int numcols, colorstyle;
345 {
346     byte rtemp[256], gtemp[256], btemp[256];
347     struct maki_info maki, *mi = &maki;
348     int e;
349 
350     if(DEBUG) fputs("WriteMAKI:\n", stderr);
351 
352     maki_init_info(&maki);
353     if((e = setjmp(maki.jmp)) != 0){
354 	/* An error occurs */
355 	maki_cleanup_maki_info(&maki, 1);
356 	return -1;
357     }
358 
359     if(w != 640 || h != 400) {
360         char  str[512];
361         sprintf(str,"MAKI: %s Should be 640x400", maki_msgs[MAKI_SIZE]);
362 	ErrPopUp(str, "\nBummer!");
363 	maki_error(mi, MAKI_SIZE);
364     }
365 
366     maki.fp = fp;
367     maki.width = w;
368     maki.height = h;
369     maki.x1 = w - 1;
370     maki.y1 = h - 1;
371 
372     if(ptype == PIC24){
373 	if(!(pic = Conv24to8(pic, w, h, 16, rtemp, gtemp, btemp)))
374 	    maki_memory_error("Conv24to8#1", "WriteMAKI");
375 	rmap = rtemp;
376 	gmap = gtemp;
377 	bmap = btemp;
378     }else if(numcols > 16){
379 	if(!(pic = Conv8to24(pic, w, h, rmap, gmap, bmap)))
380 	    maki_memory_error("Conv8to24", "WriteMAKI");
381 	if(!(pic = Conv24to8(pic, w, h, 16, rtemp, gtemp, btemp)))
382 	    maki_memory_error("Conv24to8#2", "WriteMAKI");
383 	rmap = rtemp;
384 	gmap = gtemp;
385 	bmap = btemp;
386     }else
387 	maki.numcols = numcols;
388 
389     maki_make_pixel_data(&maki, pic);
390     maki_make_virtual_screen(&maki);
391     maki_make_flags(&maki);
392     maki_write_check_id(&maki);
393     maki_write_comment(&maki);
394     maki_write_header(&maki);
395     maki_write_palette(&maki, rmap, gmap, bmap, colorstyle == F_GREYSCALE);
396     maki_write_flags(&maki);
397     maki_write_pixel_data(&maki);
398 
399     maki_cleanup_maki_info(&maki, 1);
400     return 0;
401 }
402 
maki_make_pixel_data(mi,pic)403 static void maki_make_pixel_data(mi, pic)
404     struct maki_info *mi;
405     byte *pic;
406 {
407     int x, y, i;
408     int nza, nzb;
409 
410     mi->forma = maki_malloc((size_t) mi->width / 2 * mi->height,  // GRR POSSIBLE OVERFLOW / FIXME
411 			    "maki_make_pixel_data#1");
412     mi->formb = maki_malloc((size_t) mi->width / 2 * mi->height,  // GRR POSSIBLE OVERFLOW / FIXME
413 			    "maki_make_pixel_data#2");
414 
415     for(y = 0; y < mi->height; y++){
416 	for(x = 0; x < mi->width; x += 2){
417 	    byte b;
418 	    b = pic[y * mi->width + x] << 4 | pic[y * mi->width + x + 1];
419 	    mi->forma[y * mi->width / 2 + x / 2] = b;
420 	    mi->formb[y * mi->width / 2 + x / 2] = b;
421 	}
422     }
423 
424     for(y = mi->height - 1; y >= 2; y--){
425 	for(x = 0; x < mi->width / 2; x++){
426 	    mi->forma[y * mi->width / 2 + x] ^=
427 		mi->forma[(y - 2) * mi->width / 2 + x];
428 	}
429     }
430 
431     for(y = mi->height - 1; y >= 4; y--){
432 	for(x = 0; x < mi->width / 2; x++){
433 	    mi->formb[y * mi->width / 2 + x] ^=
434 		mi->formb[(y - 4) * mi->width / 2 + x];
435 	}
436     }
437 
438     nza = nzb = 0;
439     for(i = 0; i < mi->width / 2 * mi->height; i++){
440 	if(mi->forma[i] != 0)
441 	    nza++;
442 	if(mi->formb[i] != 0)
443 	    nzb++;
444     }
445     if(nza > nzb){
446 	mi->m_maki01b = 1;
447 	free(mi->forma);
448 	mi->forma = NULL;
449     }else{
450 	mi->m_maki01b = 0;
451 	free(mi->formb);
452 	mi->formb = NULL;
453     }
454 }
455 
maki_make_virtual_screen(mi)456 static void maki_make_virtual_screen(mi)
457     struct maki_info *mi;
458 {
459     int bpl = mi->width / 2 / 8;
460     int vsi, pai, pbi, max_pai, max_pbi;
461     byte mask;
462     byte *pixels;
463     int x, y;
464 
465     mi->vs = maki_malloc((size_t) bpl * mi->height,  // GRR POSSIBLE OVERFLOW / FIXME
466 			 "maki_make_virtual_screen#1");
467 
468     if(mi->m_maki01b)
469 	pixels = mi->formb;
470     else
471 	pixels = mi->forma;
472 
473     vsi = pai = pbi = 0;
474     max_pai = max_pbi = -1;
475     mask = 0x80;
476     for(y = 0; y < mi->height; y++){
477 	for(x = 0; x < mi->width / 2; x++){
478 	    if(pixels[y * mi->width / 2 + x] == 0){
479 		mi->vs[vsi] &= ~mask;
480 	    }else{
481 		mi->vs[vsi] |= mask;
482 		if(y < 200){
483 		    if(pai > max_pai){
484 			max_pai += 1024;
485 			mi->pa = maki_realloc(mi->pa, (size_t) max_pai + 1,
486 					      "maki_make_virtual_screen#2");
487 		    }
488 		    mi->pa[pai++] = pixels[y * mi->width / 2 + x];
489 		}else{
490 		    if(pbi > max_pbi){
491 			max_pbi += 1024;
492 			mi->pb = maki_realloc(mi->pb, (size_t) max_pbi + 2,
493 					      "maki_make_virtual_screen#3");
494 		    }
495 		    mi->pb[pbi++] = pixels[y * mi->width / 2 + x];
496 		}
497 	    }
498 
499 	    if((mask >>= 1) == 0){
500 		mask = 0x80;
501 		vsi++;
502 	    }
503 	}
504     }
505 
506     mi->pa_size = pai;
507     mi->pb_size = pbi;
508 }
509 
maki_make_flags(mi)510 static void maki_make_flags(mi)
511     struct maki_info *mi;
512 {
513     int bpl = mi->width / 2 / 8;
514     int fbi, max_fbi;
515     int fai;
516     int x, y;
517     byte mask;
518 
519     mi->fa = maki_malloc((size_t) bpl * mi->height, "maki_make_flags#1");  // GRR POSSIBLE OVERFLOW / FIXME
520 
521     fbi = fai = 0;
522     max_fbi = -1;
523     mask = 0x80;
524     for(y = 0; y < mi->height; y += 4){
525 	for(x = 0; x < mi->width / 2; x += 4){
526 	    if(x % 8 == 0){
527 		if(H4(mi->vs[ y      * bpl + x / 8]) == 0 &&
528 		   H4(mi->vs[(y + 1) * bpl + x / 8]) == 0 &&
529 		   H4(mi->vs[(y + 2) * bpl + x / 8]) == 0 &&
530 		   H4(mi->vs[(y + 3) * bpl + x / 8]) == 0){
531 		    mi->fa[fai] &= ~mask;
532 		}else{
533 		    mi->fa[fai] |= mask;
534 		    if(fbi + 1 > max_fbi){
535 			max_fbi += 1024;
536 			mi->fb = maki_realloc(mi->fb, (size_t) max_fbi + 1,
537 					      "maki_make_flags#2");
538 		    }
539 		    mi->fb[fbi++] = H4(mi->vs[ y      * bpl + x / 8]) << 4
540 				  | H4(mi->vs[(y + 1) * bpl + x / 8]);
541 		    mi->fb[fbi++] = H4(mi->vs[(y + 2) * bpl + x / 8]) << 4
542 				  | H4(mi->vs[(y + 3) * bpl + x / 8]);
543 		}
544 	    }else{
545 		if(L4(mi->vs[ y      * bpl + x / 8]) == 0 &&
546 		   L4(mi->vs[(y + 1) * bpl + x / 8]) == 0 &&
547 		   L4(mi->vs[(y + 2) * bpl + x / 8]) == 0 &&
548 		   L4(mi->vs[(y + 3) * bpl + x / 8]) == 0){
549 		    mi->fa[fai] &= ~mask;
550 		}else{
551 		    mi->fa[fai] |= mask;
552 		    if(fbi + 1 > max_fbi){
553 			max_fbi += 1024;
554 			mi->fb = maki_realloc(mi->fb, (size_t) max_fbi + 1,
555 					      "maki_make_flags#3");
556 		    }
557 		    mi->fb[fbi++] = L4(mi->vs[ y      * bpl + x / 8]) << 4
558 				  | L4(mi->vs[(y + 1) * bpl + x / 8]);
559 		    mi->fb[fbi++] = L4(mi->vs[(y + 2) * bpl + x / 8]) << 4
560 				  | L4(mi->vs[(y + 3) * bpl + x / 8]);
561 		}
562 	    }
563 
564 	    if((mask >>= 1) == 0){
565 		mask = 0x80;
566 		fai++;
567 	    }
568 	}
569     }
570 
571     mi->fb_size = fbi;
572 }
573 
maki_write_check_id(mi)574 static void maki_write_check_id(mi)
575     struct maki_info *mi;
576 {
577     char *id = mi->m_maki01b ? maki_id_b : maki_id_a;
578     if(fwrite(id, (size_t) 8, (size_t) 1, mi->fp) != 1)
579 	maki_file_error(mi, MAKI_WRITE);
580 }
581 
maki_write_comment(mi)582 static void maki_write_comment(mi)
583     struct maki_info *mi;
584 {
585     char buf[24];
586     char *p;
587     int i = 0;
588 
589     strcpy(buf, "XV   ");
590 
591     if((p = (char *) getenv("USER")) == NULL)
592 	p = "????????";
593     for(i = 5; i < 23; i++){
594 	if(*p == '\0')
595 	    break;
596 	buf[i] = *p++;
597     }
598     for( ; i < 23; i++)
599 	buf[i] = ' ';
600 
601     buf[i] = '\032';	/* ^Z, 0x1a */
602 
603     if(fwrite(buf, (size_t) 24, (size_t) 1, mi->fp) != 1)
604 	maki_file_error(mi, MAKI_WRITE);
605 }
606 
maki_write_header(mi)607 static void maki_write_header(mi)
608     struct maki_info *mi;
609 {
610     byte buf[16];
611 
612     if(DEBUG) maki_show_maki_info(mi);
613 
614 #define set_word(i, v) {buf[i]=(v)>>8&0xff;buf[i+1]=(v)&0xff;}
615     set_word(0, mi->fb_size);
616     set_word(2, mi->pa_size);
617     set_word(4, mi->pb_size);
618     set_word(6, mi->ext_flag);
619     set_word(8, mi->x0);
620     set_word(10, mi->y0);
621     set_word(12, mi->x1 + 1);
622     set_word(14, mi->y1 + 1);
623 #undef set_word
624 
625     if(fwrite(buf, (size_t) 16, (size_t) 1, mi->fp) != 1)
626 	maki_file_error(mi, MAKI_WRITE);
627 }
628 
maki_write_palette(mi,r,g,b,grey)629 static void maki_write_palette(mi, r, g, b, grey)
630     struct maki_info *mi;
631     byte *r, *g, *b;
632     int grey;
633 {
634     int i;
635     char buf[3];
636     for(i = 0; i < mi->numcols; i++){
637 	buf[0] = *g++;
638 	buf[1] = *r++;
639 	buf[2] = *b++;
640 	if(grey)
641 	    buf[0] = buf[1] = buf[2] = MONO(buf[1], buf[0], buf[2]);
642 	if(fwrite(buf, (size_t) 3, (size_t) 1, mi->fp) != 1)
643 	    maki_file_error(mi, MAKI_WRITE);
644     }
645     for( ; i < 16; i++){
646 	if(fwrite(buf, (size_t) 3, (size_t) 1, mi->fp) != 1)
647 	    maki_file_error(mi, MAKI_WRITE);
648     }
649 }
650 
maki_write_flags(mi)651 static void maki_write_flags(mi)
652     struct maki_info *mi;
653 {
654     int bpl = mi->width / 2 / 8;
655     if(fwrite(mi->fa, (size_t) bpl * mi->height / 16, (size_t) 1, mi->fp) != 1)
656 	maki_file_error(mi, MAKI_WRITE);
657 
658     if(fwrite(mi->fb, (size_t) mi->fb_size, (size_t) 1, mi->fp) != 1)
659 	maki_file_error(mi, MAKI_WRITE);
660 }
661 
maki_write_pixel_data(mi)662 static void maki_write_pixel_data(mi)
663     struct maki_info *mi;
664 {
665     if(fwrite(mi->pa, (size_t) mi->pa_size, (size_t) 1, mi->fp) != 1)
666 	maki_file_error(mi, MAKI_WRITE);
667 
668     if(fwrite(mi->pb, (size_t) mi->pb_size, (size_t) 1, mi->fp) != 1)
669 	maki_file_error(mi, MAKI_WRITE);
670 }
671 
672 
673 
maki_init_info(mi)674 static void maki_init_info(mi)
675     struct maki_info *mi;
676 {
677     xvbzero((char *)mi, sizeof(struct maki_info));
678     mi->fp = NULL;
679     mi->fsize = 0;
680     mi->x0 = mi->y0 = mi->x1 = mi->y1 = 0;
681     mi->width = mi->height = 0;
682     mi->aspect = 1.0;
683     mi->fb_size = mi->pa_size = mi->pb_size = 0;
684     mi->m_maki01b = mi->m_200 = mi->m_dig8 = 0;
685     mi->ext_flag = 0;
686     mi->fa = mi->fb = mi->pa = mi->pb = NULL;
687     mi->vs = NULL;
688     mi->numcols = 16;
689     mi->forma = mi->formb = NULL;
690 }
691 
maki_cleanup_maki_info(mi,writing)692 static void maki_cleanup_maki_info(mi, writing)
693     struct maki_info *mi;
694     int writing;
695 {
696     if(mi->fp && !writing)
697 	fclose(mi->fp);
698     if(mi->fa)
699 	free(mi->fa);
700     if(mi->fb)
701 	free(mi->fb);
702     if(mi->pa)
703 	free(mi->pa);
704     if(mi->pb)
705 	free(mi->pb);
706     if(mi->vs)
707 	free(mi->vs);
708     if(mi->forma)
709 	free(mi->forma);
710     if(mi->formb)
711 	free(mi->formb);
712 }
713 
maki_cleanup_pinfo(pi)714 static void maki_cleanup_pinfo(pi)
715     PICINFO *pi;
716 {
717     if(pi->pic){
718 	free(pi->pic);
719 	pi->pic = NULL;
720     }
721 }
722 
maki_memory_error(scm,fn)723 static void maki_memory_error(scm, fn)
724     char *scm, *fn;
725 {
726     char buf[128];
727     sprintf(buf, "%s: coulndn't allocate memory. (%s)", scm, fn);
728     FatalError(buf);
729 }
730 
maki_error(mi,mn)731 static void maki_error(mi, mn)
732     struct maki_info *mi;
733     int mn;
734 {
735     SetISTR(ISTR_WARNING, "%s", maki_msgs[mn]);
736     longjmp(mi->jmp, 1);
737 }
738 
maki_file_error(mi,mn)739 static void maki_file_error(mi, mn)
740     struct maki_info *mi;
741     int mn;
742 {
743     if(feof(mi->fp))
744 	SetISTR(ISTR_WARNING, "%s (end of file)", maki_msgs[mn]);
745     else
746 	SetISTR(ISTR_WARNING, "%s (%s)", maki_msgs[mn], ERRSTR(errno));
747     longjmp(mi->jmp, 1);
748 }
749 
maki_file_warning(mi,mn)750 static void maki_file_warning(mi, mn)
751     struct maki_info *mi;
752     int mn;
753 {
754     if(feof(mi->fp))
755 	SetISTR(ISTR_WARNING, "%s (end of file)", maki_msgs[mn]);
756     else
757 	SetISTR(ISTR_WARNING, "%s (%s)", maki_msgs[mn], ERRSTR(errno));
758 }
759 
maki_show_maki_info(mi)760 static void maki_show_maki_info(mi)
761     struct maki_info *mi;
762 {
763     fprintf(stderr, "  file size: %ld.\n", mi->fsize);
764     fprintf(stderr, "  image size: %dx%d.\n", mi->width, mi->height);
765     fprintf(stderr, "  aspect: %f.\n", mi->aspect);
766     fprintf(stderr, "  flag B size: %ld.\n", mi->fb_size);
767     fprintf(stderr, "  pixel data size: A:%ld, B:%ld.\n",
768 	    mi->pa_size, mi->pb_size);
769     fprintf(stderr, "  MAKI01B: %s.\n", mi->m_maki01b ? "true" : "false");
770     fprintf(stderr, "  200 line mode: %s.\n", mi->m_200 ? "true" : "false");
771     fprintf(stderr, "  digital 8 colors: %s.\n", mi->m_dig8 ? "true" : "false");
772 }
773 
maki_malloc(n,fn)774 static void *maki_malloc(n, fn)
775     size_t n;
776     char *fn;
777 {
778     void *r = (void *) malloc(n);
779     if(r == NULL)
780 	maki_memory_error("malloc", fn);
781     return r;
782 }
783 
maki_realloc(p,n,fn)784 static void *maki_realloc(p, n, fn)
785     void *p;
786     size_t n;
787     char *fn;
788 {
789     void *r = (p == NULL) ? (void *) malloc(n) : (void *) realloc(p, n);
790     if(r == NULL)
791 	maki_memory_error("realloc", fn);
792     return r;
793 }
794 #endif /* HAVE_MAKI */
795