home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / program / lynxlib / picture.c < prev    next >
C/C++ Source or Header  |  1993-10-23  |  21KB  |  676 lines

  1. /* This source file is part of the LynxLib miscellaneous library by
  2. Robert Fischer, and is Copyright 1990 by Robert Fischer.  It costs no
  3. money, and you may not make money off of it, but you may redistribute
  4. it.  It comes with ABSOLUTELY NO WARRANTY.  See the file LYNXLIB.DOC
  5. for more details.
  6. To contact the author:
  7.     Robert Fischer \\80 Killdeer Rd \\Hamden, CT   06517   USA
  8.     (203) 288-9599     fischer-robert@cs.yale.edu                 */
  9.  
  10. /* for loading & dicompressing pictures */
  11. /* This file is missing stuff about printing pictures from the pascal code */
  12.  
  13. /* Will load a NEO or D*E*G*A*S picture from disk
  14. Structure of a NEO file:
  15. 2 words:    unused
  16. 16 words:   color palette, hardware format
  17. 46 words:   unknown (rotation info, unused, etc)
  18. 32000 bytes:    the picture, hardware format
  19.  
  20. Structure of a DEGAS file:
  21. 1 word:     resolution
  22. 16 words:   palette
  23. 32000 bytes:    the picture
  24.  
  25. You can only tell the difference by size.  Degas files are 32033 bytes long,
  26. and NEO files are 32128 bytes long.
  27.  
  28. Structure of a DOODLE file:
  29.  
  30. */
  31.  
  32. #include <stddef.h>
  33. #include <e_osbind.h>
  34. #include <picture.h>
  35. #include <vfile.h>
  36.  
  37. /* -------------------------------------------------------- */
  38. pic_type find_pictype(name) /* Figures out the type of a picture file */
  39. char *name;                 /* The name */
  40. {
  41. TRANS_BUF *old_trans_p;
  42. TRANS_BUF trans;
  43. pic_type out;
  44. GFILE h;
  45. WORD first_2;   /* First 2 bytes of SPC file.  It's an SPC file */
  46.                 /* if the WORD contains $5350 */
  47. char ext[5];    /* Extender of file name */
  48. int i;
  49.  
  50.     old_trans_p = (TRANS_BUF *)Fgetdta();
  51.     Fsetdta(&trans);
  52.  
  53.     out = ERROR;
  54.     if (Fsfirst(name, NO_ATTRIB) != E_OK) goto err;
  55.     if (trans.size == DEGAS_SIZE) out = DEGAS;
  56.     else if (trans.size == NEO_SIZE) out = NEO;
  57.     else if (trans.size == DOODLE_SIZE) out = DOODLE;
  58.     else if (trans.size == SPU_SIZE) out = SPU;
  59.     else if (trans.size == SCR_SIZE) out = PLAIN_SCREEN;
  60.     else {  /* We think it's SPC or COMPRESS.  Look in it to find out */
  61.         if ((h = Fopen(name, G_READ)) <= 0) goto err;
  62.         if (Fread(h, 2, &first_2) == 2)
  63.             if (first_2 == 0x5350) out = SPC;
  64. #if 0
  65.             else if (first_2 == 0x9310) out = SPLAY;
  66.             else if (first_2 == 0x1f9d) out = COMPRESS;
  67. #endif
  68.         Fclose(h);
  69.  
  70.         /* It may still be unidentified, in which case we look @ name */
  71.         /* To tell if it's a TINY picture */
  72.         if (out == ERROR) {
  73.             for (i = 0; name[i] != '.'; i++) ;  /* Find dot */
  74.             strncpy(ext, &name[i+1], 4);
  75.             pstrupper(ext);
  76.             if (ext[2] >= '1' && ext[2] <= '3') ext[2] = 'Y';
  77.             if (strcmp(ext, "TNY") == 0) out = TINY;
  78.         }
  79.     }
  80. err:
  81.     Fsetdta(old_trans_p);
  82.     return out;
  83. }
  84. /* -------------------------------------------------------- */
  85. raster_convert(pic, atari, ci, bi)
  86. /* Convert one scanline from DOODLE to NEO */
  87. DOODLE_PIC *pic;
  88. PLANE_ARRAY atari;  /* Current color place in NEO picture */
  89. int ci,bi;      /* Color index & raster byte index */
  90. {
  91. int ai,b,i,j,ai_base;
  92. int color;
  93. BOOLEAN for_bool, bak_bool;
  94. register BYTE *k;
  95.     for (i = 0, ai_base = 0; i < 20; i++, ai_base += 8) {
  96.         for (b = 0; b < 2; b++, ci++, bi += 8) {
  97.             ai = ai_base + b;
  98.             color = pic->c[ci];
  99.             for (j = 0; j < 4; j++) {
  100.                 bak_bool = (color >> j) & 1;
  101.                 for_bool = (color >> (j+4)) & 1;
  102.  
  103.                 k = &atari[ai + (j<<1)];
  104.                 if (for_bool) {
  105.                     if (bak_bool) *k = 0xFF;
  106.                     else *k = pic->b[bi];
  107.                 } else {
  108.                     if (bak_bool) *k = ~(pic->b[bi]);
  109.                     else *k = 0;
  110.                 }
  111.             }   /* for j */
  112.         }   /* for b */
  113.     }   /* for i, ai_base */
  114. }
  115. /* --------------------------------------------------------------- */
  116. BOOLEAN read_degas(in, res, pal, pic)
  117. /* Reads a DEGAS picture from in */
  118. VFILE *in;      /* File to read from */
  119. WORD *res;      /* Resolution */
  120. char *pal;      /* Palette to read to */
  121. char *pic;      /* Picture data to read to */
  122. {
  123.     read_bytes(in, 2L, res);    /* Read res word */
  124.     read_bytes(in, (LONG)PAL_SIZE, pal);    /* Read palette */
  125.     read_bytes(in, (LONG)SCR_SIZE, pic);
  126. }
  127. /* -------------------------------------------------------- */
  128. BOOLEAN read_neo(in, res, pal, pic)
  129. /* Reads a DEGAS picture from in */
  130. VFILE *in;      /* File to read from */
  131. WORD *res;      /* Resolution */
  132. char *pal;      /* Palette to read to */
  133. char *pic;      /* Picture data to read to */
  134. {
  135.     *res = LOW_RES;
  136.     read_bytes(in, 4L, pic);                /* Read unused bytes */
  137.     read_bytes(in, (LONG)PAL_SIZE, pal);    /* Read palette */
  138.     read_bytes(in, 92L, pic);               /* Read unused bytes */
  139.     read_bytes(in, (LONG)SCR_SIZE, pic);    /* Read the picture data */
  140. }
  141. /* -------------------------------------------------------- */
  142. BOOLEAN read_doodle(in, res, pal, pic)
  143. /* Reads a DEGAS picture from in */
  144. VFILE *in;      /* File to read from */
  145. WORD *res;      /* Resolution */
  146. PALETTE pal;        /* Palette to read to */
  147. char *pic;      /* Picture data to read to */
  148. {
  149. static WORD doodle_pal[] = {    /* Commodore's palette */
  150.     0x0000, 0x0777, 0x0700, 0x0066, 0x0527, 0x0160, 0x0007, 0x0771,
  151.     0x0740, 0x0530, 0x0745, 0x0333, 0x0555, 0x0573, 0x0467, 0x0666
  152. };
  153. DOODLE_PIC *dpic;   /* Doodle picture pointer */
  154. int row;        /* current row we're converting */
  155. int color_index, raster_index;
  156. BYTE *cur_neo;      /* Current place in neo picture */
  157.  
  158.     *res = LOW_RES;
  159.  
  160.     /* Load the picture */
  161.     dpic = malloc(sizeof(*dpic));
  162.     read_bytes(in, (LONG)DOODLE_SIZE, dpic);
  163.     if (dpic->load_addr != 92) {
  164.         free(dpic);
  165.         return FALSE;
  166.     }
  167.  
  168.     /* Convert the data from Doodle to Neochrome format */
  169.     cur_neo = pic;
  170.     for (row = 0; row < 200; row++) {
  171.         color_index = (row >> 3) * 40;
  172.         raster_index = (color_index << 3) + (row & 0x7);
  173.         raster_convert(dpic, cur_neo, color_index, raster_index);
  174.         cur_neo += 160;
  175.     }
  176.  
  177.     /* Copy the palette */
  178.     for (row = 0; row < 16; row++)
  179.         pal[row] = doodle_pal[row];
  180.  
  181.     /* Free memory and leave */
  182.     free(dpic);
  183.     return TRUE;
  184. }
  185. /* -------------------------------------------------------- */
  186. BOOLEAN read_plainscr(in, res, pal, pic)
  187. /* Reads a DEGAS picture from in */
  188. VFILE *in;      /* File to read from */
  189. WORD *res;      /* Resolution */
  190. PALETTE pal;        /* Palette to read to */
  191. char *pic;      /* Picture data to read to */
  192. {
  193. int i;
  194.     read_bytes(in, (LONG)SCR_SIZE, pic);
  195.  
  196.     /* No palette or resolution is provided -- use current */
  197.     for (i = 0; i < 16; i++) pal[i] = Setcolor(i, -1);
  198.     *res = Getres();
  199. }
  200. /* -------------------------------------------------------- */
  201. BOOLEAN read_spec(in, pt, res, pal, pic)
  202. /* Reads a SPEC picture from in */
  203. VFILE *in;      /* File to read from */
  204. pic_type pt;    /* Either SPC or SPU */
  205. WORD *res;      /* Resolution */
  206. PALETTE pal;        /* Palette to read to */
  207. char *pic;      /* Picture data to read to */
  208. {
  209. char *spec_pic, *spec_color;
  210. BOOLEAN out;
  211.     /* Allocate memory for spectrum picture */
  212.     spec_pic = malloc(SCR_SIZE);
  213.     spec_color = malloc(SPEC_PAL_SIZE);
  214.  
  215.     if (pt == SPC) out = load_spc(in, spec_pic, spec_color);
  216.     else out = load_spu(in, spec_pic, spec_color);
  217.     if (out) {
  218.         spu_to_degas(spec_pic, spec_color, pic, pal);
  219.     }
  220.  
  221.     free(spec_pic);
  222.     free(spec_color);
  223.     *res = LOW_RES;
  224.     return out;
  225. }
  226. /* -------------------------------------------------------- */
  227. BOOLEAN read_tiny(in, res, pal, pic)
  228. /* Reads a TINY picture */
  229. VFILE *in;      /* File to read from */
  230. WORD *res;      /* Resolution */
  231. PALETTE pal;        /* Palette to read to */
  232. char *pic;      /* Picture data to read to */
  233. {
  234. WORD numctrl;   /* # control bytes */
  235. WORD numdata;   /* # data bytes */
  236. BYTE *ctrl_buf; /* Buffer of control bytes */
  237. VFILE *c;   /* VFILES for ctrl_buf & pic, respectively */
  238. VFILE *p;
  239.  
  240. BYTE dum[4];
  241. BOOLEAN out = FALSE;
  242. WORD b;
  243. register BYTE q, r;
  244.  
  245.     /* Read resolution and possible color rotation data */
  246.     *res = vgetc(in);
  247.     if (*res > HIGH_RES) {  /* This could be wrong, but I haven't */
  248.         *res -= 3;          /* found a counterexample */
  249.         read_bytes(in, 4L, dum);
  250.     }
  251.  
  252.     /* Read the rest of header */
  253.     read_bytes(in, (LONG)PAL_SIZE, pal);
  254.     read_bytes(in, 2L, &numctrl);
  255.     read_bytes(in, 2L, &numdata);
  256.     numdata <<= 1;
  257.     if (veof(in)) return FALSE;
  258.  
  259.     /* Allocate memory for control bytes & read it in */
  260.     if ((ctrl_buf = malloc(numctrl)) == NULL) return FALSE;
  261.     read_bytes(in, (LONG)numctrl, ctrl_buf);
  262.     if (veof(in)) {
  263.         free(ctrl_buf);
  264.         return FALSE;
  265.     }
  266.  
  267.     c = open_mfile(ctrl_buf, (LONG)numctrl);
  268.     p = open_mfile(pic, (LONG)SCR_SIZE);
  269.  
  270.     /* Convert the data */
  271.     for (b = (WORD)vgetc(c); !veof(c); b = (WORD)vgetc(c)) {
  272.         if (b > 127) {      /* Short copy-word */
  273.             b = (256-b) << 1;
  274.             for (; b > 0; b--) vputc(vgetc(in), p);
  275.         } else if (b == 0)  {   /* Long repeat-word */
  276.             read_bytes(c, 2L, &b);
  277.             read_bytes(in, 2L, dum);
  278.             q = dum[0];
  279.             r = dum[1];
  280.             for (; b > 0; b--) {
  281.                 vputc(q, p);
  282.                 vputc(r, p);
  283.             }
  284.         } else if (b == 1) {    /* Long copy-word */
  285.             read_bytes(c, 2L, &b);
  286.             b <<= 1;
  287.             for (; b > 0; b--) vputc(vgetc(in), p);
  288.         } else {    /* Short repeat-word */
  289.             read_bytes(in, 2L, dum);
  290.             q = dum[0];
  291.             r = dum[1];
  292.             for (; b > 0; b--) {
  293.                 vputc(q, p);
  294.                 vputc(r, p);
  295.             }
  296.         }
  297.     }
  298.  
  299.     free(ctrl_buf);
  300.     vclose(c);
  301.     vclose(p);
  302. }
  303. /* -------------------------------------------------------- */
  304. #if 0
  305. my_uncompress(v)
  306. VFILE_REC *v;
  307. {
  308.     decompress(v->in, v->out);
  309.     vclose(v->in);
  310.     vclose(v->out);
  311. }
  312. /* -------------------------------------------------------- */
  313. my_unsplay(v)
  314. VFILE_REC *v;
  315. {
  316.     unsplay(v->in, v->out);
  317.     vclose(v->in);
  318.     vclose(v->out);
  319. }
  320. #endif
  321. /* -------------------------------------------------------- */
  322. BOOLEAN load_pic(pic, name) /* Loads a picture from disk */
  323. register pic_rec *pic;  /* The place to load it to */
  324. char *name;             /* The name of the picture to load */
  325. /* Returns TRUE if the picture loaded OK */
  326. {
  327. GFILE h;
  328. pic_type pt;
  329. char *pic_buf;      /* The buffer that the picture file is read into */
  330. LONG dum;
  331. long size;      /* Size of picture */
  332. VFILE *in;      /* Input file */
  333. #if 0
  334. VFILE_REC vrec; /* Arguments to uncompress */
  335. #endif
  336. BOOLEAN b;
  337. BOOLEAN out = FALSE;
  338.     /* Find first useable byte in picture array */
  339.     pic->p_start = (char *)(((LONG)(pic->p) + 255) & 0xFFFFFF00L);
  340.  
  341.     /* Figure out picture type */
  342.     pt = find_pictype(name);
  343.     if (pt == ERROR) return FALSE;
  344.  
  345.     /* Read picture file image into memory & set up a memory VFILE */
  346.     g_file_attrib(name, &dum, &dum, &size);
  347.  
  348.     pic_buf = lmalloc(size);
  349.     h = Fopen(name, READ_MODE);
  350.     if (h <= 0) goto err;
  351.     if (Fread(h, size, pic_buf) != size) {
  352.         Fclose(h);
  353.         goto err;
  354.     }
  355.     if (Fclose(h) != E_OK) goto vclose_err;
  356.     in = open_mfile(pic_buf, size);
  357.  
  358. /*  in = open_ffile(name, "rb");*/
  359. #if 0
  360.     /* Change in to a cofile handle on uncompress(), if pic is compressed */
  361.     if (pt == SPLAY) {
  362.         /* Rearrange file handles */
  363.         vrec.in = in;
  364.         in = open_cofile(&my_unsplay, &vrec, 2000L, &vrec.out);
  365.  
  366.         /* Find size and type */
  367.         pt = vgetc(in);
  368.         read_bytes(in, 4L, &size);
  369.     }
  370.  
  371.     if (pt == COMPRESS) {
  372.         /* Rearrange file handles */
  373.         vrec.in = in;
  374.         in = open_cofile(&my_uncompress, &vrec, 2000L, &vrec.out);
  375.  
  376.         /* Find size and type */
  377.         pt = vgetc(in);
  378.         read_bytes(in, 4L, &size);
  379.     }
  380. #endif
  381.     /* Read in the file to appropriate data structure */
  382.     switch(pt) {
  383.         case SPC :
  384.         case SPU :
  385.             b = read_spec(in, pt, &(pic->rez), pic->pal, pic->p_start);
  386.         break;
  387.         case DEGAS :
  388.             b = read_degas(in, &(pic->rez), pic->pal, pic->p_start);
  389.         break;
  390.         case NEO :
  391.             b = read_neo(in, &(pic->rez), pic->pal, pic->p_start);
  392.         break;
  393.         case DOODLE :
  394.             b = read_doodle(in, &(pic->rez), pic->pal, pic->p_start);
  395.         break;
  396.         case TINY :
  397.             b = read_tiny(in, &(pic->rez), pic->pal, pic->p_start);
  398.         break;
  399.         case PLAIN_SCREEN : /* No data other than bit image */
  400.             b = read_plainscr(in, &(pic->rez), pic->pal, pic->p_start);
  401.         break;
  402.     }   /* Switch */
  403.  
  404.     out = TRUE;
  405. vclose_err:
  406.     vclose(in);
  407. err:
  408.     free(pic_buf);
  409.  
  410.     return out;
  411. }
  412. /* -------------------------------------------------------- */
  413. setres(res)     /* Sets the current resolution to res, if possible */
  414. /* This needs 32256 bytes in malloc'able memory, if the resolution changes */
  415. int res;
  416. {
  417. int ores;
  418. char *pic;
  419. char *p;
  420. char *old_phys, *old_log;
  421.  
  422.     /* Try to save effort */
  423.     ores = Getres();
  424.     if (res == HIGH_RES || ores == HIGH_RES) return;
  425.     if (res == ores) return;
  426.  
  427.     /* Now, really do it! */
  428.     pic = malloc(32256);
  429.     p = (char *)(((LONG)(pic) + 255) & 0xFFFFFF00L);
  430.     old_phys = Physbase();
  431.     old_log = Logbase();
  432.     Setscreen(p, -1, -1);
  433.     Setscreen(-1, p, -1);
  434.     Setscreen(-1, -1, res);
  435.     Setscreen(old_log, -1, -1);
  436.     Setscreen(-1, old_phys, -1);
  437.     free(pic);
  438. }
  439. /* -------------------------------------------------------- */
  440. switch_pic(pic) /* Switches screen to the specified picture */
  441. register pic_rec *pic;  /* The picture to switch to */
  442. {
  443. int i;
  444.  
  445.     /* Take care of resolution */
  446.     pic->old_rez = Getres();
  447.     setres(pic->rez);
  448.  
  449.     /* Take care of screen location */
  450.     pic->old_phys = Physbase();
  451.     pic->old_log = Logbase();
  452.     Setscreen(pic->p_start, pic->p_start, -1);
  453.  
  454.     /* Take care of palette */
  455.     for (i = 0; i <= 15; i++) {
  456.         pic->old_pal[i] = Setcolor(i, pic->pal[i]);
  457.     }
  458. }
  459. /* -------------------------------------------------------- */
  460. switch_norm(pic)    /* Switches back to the normal screen */
  461. register pic_rec *pic;  /* The picture to switch from */
  462. {
  463.     setres(pic->old_rez);
  464.     Setscreen(pic->old_log, pic->old_phys, -1);
  465.  
  466.     /* Take care of pallette */
  467.     Setpalette(pic->old_pal);
  468. }
  469. /* -------------------------------------------------------- */
  470. BOOLEAN save_neo(pic, name)
  471. register pic_rec *pic;  /* The place to load it to */
  472. char *name;             /* The name of the picture to load */
  473. /* Returns TRUE if the picture saved OK */
  474. {
  475. int h;  /* File handle */
  476. WORD filler[46];        /* Zeros to write in neo file */
  477.     if (pic->rez != LOW_RES) return FALSE;  /* NEO format only low resolution */
  478.  
  479.     for (h = 0; h < 46; h++)
  480.         filler[h] = 0;
  481.  
  482.     h = Fcreate(name, 0);
  483.     if (h <= 0) return FALSE;
  484.     if (Fwrite(h, (LONG)(2*sizeof(WORD)), filler) != 2*sizeof(WORD)) goto err;
  485.     if (Fwrite(h, (LONG)sizeof(PALETTE), pic->pal) != sizeof(PALETTE)) goto err;
  486.     if (Fwrite(h, (LONG)(46*sizeof(WORD)), filler) != 46*sizeof(WORD)) goto err;
  487.     if (Fwrite(h, (LONG)SCR_SIZE, pic->p_start) != SCR_SIZE) goto err;
  488.  
  489.     Fclose(h);
  490.     return TRUE;
  491. err:
  492.     Fclose(h);
  493.     return FALSE;
  494. }
  495. /* -------------------------------------------------------- */
  496. /* Picture conversion routines -- usually, convert between resolutions */
  497. /* -------------------------------------------------------- */
  498. /* -------------------------------------------------------- */
  499. /* Convert a low-res picture to a high-res picture */
  500. /* This great-o routine was created by Roland Lieger in 1988. */
  501. /* He was so gratious to let Robert Fischer steal it while */
  502. /* only including this little message */
  503. ltoh(pic)
  504. pic_rec *pic;
  505. {
  506. register WORD l1,l2,l3,l4;
  507. WORD temp1,temp2,temp3,temp4;
  508. WORD *p1,*p2,*p3,*p4;
  509. LONG *line1,*line2;
  510. WORD buffer[80];
  511. int curcol;
  512. int red,green,blue,brightness;
  513. int grayscale[16];
  514. int code[16];
  515. register int currcol;
  516. int i,j,k,line;
  517. int lev1,lev2,lev3;
  518. LONG long1,long2;
  519.  
  520. static BYTE data[]={0x09,0x03,0x0a,0x06,0x0c,0x05,0x09,0x03,0x0a,
  521.             0x06,0x0c,0x05,0x09,0x03,0x06,0x0a};
  522.         /* different patterns of 2 bits in 4 in a good order */
  523.  
  524. /* ----------- Calculate the palette ----------- */
  525.     for (i=0;i<16;i++) {
  526.         curcol=pic->pal[i];
  527.         red=(curcol>>8)&7;
  528.         green=(curcol>>4)&7;
  529.         blue=curcol&7;
  530.         brightness=red*red+green*green+blue*blue;
  531.         if (brightness>108) grayscale[i]=0;
  532.         else if (brightness>70) grayscale[i]=1;
  533.         else if (brightness>43) grayscale[i]=2;
  534.         else if (brightness>7) grayscale[i]=3;
  535.         else grayscale[i]=4;
  536.     }
  537.     lev1=0;
  538.     lev2=0;
  539.     lev3=0;
  540.  
  541.     for (i=0;i<16;i++) {
  542.  
  543.         for (j=0;j<i;j++) {
  544.             if (pic->pal[i]==pic->pal[j]) {
  545.                 code[i]=code[j];
  546.                 break;
  547.             }
  548.         }
  549.  
  550.         if (i==j) {
  551.             if (grayscale[i]==0) {
  552.                 code[i]=0;
  553.             } else if (grayscale[i]==4) {
  554.                 code[i]=0xf;
  555.             } else if (grayscale[i]==1) {
  556.                 code[i]=1<<(lev1&3);
  557.                 lev1++;
  558.             } else if (grayscale[i]==2) {
  559.                 lev2++;
  560.                 code[i]=data[lev2];
  561.             } else {
  562.                 code[i]=(0xee>>(lev3&3)&0xf);
  563.                 lev3++;
  564.             }
  565.         }
  566.     }
  567.  
  568.     /*---------------- Process the picture -----------------*/
  569.  
  570.     p1=((WORD*)(pic->p_start))+3;
  571.     p2=((WORD*)(pic->p_start))+2;
  572.     p3=((WORD*)(pic->p_start))+1;
  573.     p4=((WORD*)(pic->p_start));
  574.  
  575.     line1=((LONG*)pic->p_start);
  576.     line2=((LONG*)pic->p_start)+20; /* 20 LONGs make up a 640 dot line */
  577.  
  578.     for (line=0;line<200;line++) {
  579.         j=0;
  580.         for (i=0;i<20;i++) {
  581.             l1=*p1;
  582.             l2=*p2;
  583.             l3=*p3;
  584.             l4=*p4;
  585.  
  586.             temp1=(l1&0x5555)<<1; /* Flip all the bits around to be able to */
  587.             temp2=(l2&0xaaaa)>>1; /* Get the colors out */
  588.             l1=(l1&0xaaaa)+temp2;
  589.             l2=(l2&0x5555)+temp1;
  590.             temp3=(l3&0x5555)<<1;
  591.             temp4=(l4&0xaaaa)>>1;
  592.             l3=(l3&0xaaaa)+temp4;
  593.             l4=(l4&0x5555)+temp3;
  594.             temp1=l1&0x3333;
  595.             temp2=l2&0x3333;
  596.             temp3=l3&0xcccc;
  597.             temp4=l4&0xcccc;
  598.             l1=(l1&0xcccc)+(temp3>>2);
  599.             l2=(l2&0xcccc)+(temp4>>2);
  600.             l3=(l3&0x3333)+(temp1<<2);
  601.             l4=(l4&0x3333)+(temp2<<2);
  602.  
  603.             buffer[j++]=l1;
  604.             buffer[j++]=l2;
  605.             buffer[j++]=l3;
  606.             buffer[j++]=l4;
  607.  
  608.             p1+=4;
  609.             p2+=4;
  610.             p3+=4;
  611.             p4+=4;
  612.         } /* end of the for loop - one color (= 2 monochrome )pictureline done */
  613.         for (i=0;i<80;i+=4) {
  614.             l1=buffer[i];
  615.             l2=buffer[i+1];
  616.             l3=buffer[i+2];
  617.             l4=buffer[i+3];
  618.  
  619.             for (k=0;k<4;k++) {
  620.                 currcol=code[((l1&0xf000)>>12)];
  621.                 l1<<=4;
  622.                 long1<<=2;
  623.                 long2<<=2;
  624.                 long1+=((currcol&0x0c)>>2);
  625.                 long2+=(currcol&0x03);
  626.  
  627.                 currcol=code[((l2&0xf000)>>12)];
  628.                 l2<<=4;
  629.                 long1<<=2;
  630.                 long2<<=2;
  631.                 long1+=((currcol&0x0c)>>2);
  632.                 long2+=(currcol&0x03);
  633.  
  634.                 currcol=code[((l3&0xf000)>>12)];
  635.                 l3<<=4;
  636.                 long1<<=2;
  637.                 long2<<=2;
  638.                 long1+=((currcol&0x0c)>>2);
  639.                 long2+=(currcol&0x03);
  640.  
  641.                 currcol=code[((l4&0xf000)>>12)];
  642.                 l4<<=4;
  643.                 long1<<=2;
  644.                 long2<<=2;
  645.                 long1+=((currcol&0x0c)>>2);
  646.                 long2+=(currcol&0x03);
  647.             }
  648.             *line1=long1;
  649.             *line2=long2;
  650.             line1++;
  651.             line2++;
  652.         }
  653.         line1+=20; /* One 640 dot line has 20 LONGs */
  654.         line2+=20; /* line1 and line 2 each skip over each others screenlines */
  655.     } /* end of for (line... */
  656.  
  657.     /* Change the palette so it's the "standard" for B&W: */
  658.     /* White backround, black forground */
  659.     pic->pal[0] = 1;
  660. } /* end of ltoh */
  661. /* -------------------------------------------------------- */
  662. BOOLEAN change_res(pic, dest_res)
  663. /* Converts a picture from its current resolution to the destination res */
  664. pic_rec *pic;   /* Picture to convert */
  665. int dest_res;   /* Destination resolution */
  666. {
  667.     if (pic->rez == dest_res) return TRUE;
  668.     if (pic->rez == LOW_RES && dest_res == HIGH_RES) {
  669.         ltoh(pic);
  670.         pic->rez = HIGH_RES;
  671.         return TRUE;
  672.     }
  673.     return FALSE;
  674. }
  675. /* -------------------------------------------------------- */
  676.