home *** CD-ROM | disk | FTP | other *** search
/ RISC DISC 2 / RISC_DISC_2.iso / pd_share / program / sprtools / c / sprite < prev    next >
Encoding:
Text File  |  1994-07-18  |  31.0 KB  |  1,038 lines

  1. /****************************************************************************
  2.  *                                                                          *
  3.  * sprite.c                                                                 *
  4.  * ========                                                                 *
  5.  *                                                                          *
  6.  * Sprite ops for conversion routines                                       *
  7.  *                                                                          *
  8.  * Recognises RISCOS 3.10 modes:                                            *
  9.  * standard, multi, VGA, SVGA,                                              *
  10.  * new multi (896x352), DEEJ large (1152x424 to 1280x512)                   *
  11.  *                                                                          *
  12.  * RISCOS 3 True colour 256 by (2) 24 bit palette entry sprites             *
  13.  * RISCOS 3 Deep sprites in 1,2,4,8,15/16,24/32 bit depths            *
  14.  *                                                                          *
  15.  * Also DEEJ Technology sprite formats:                                     *
  16.  *                                                                          *
  17.  * OLD:                                                                     *
  18.  * mode 0x200 - 15 bpp, 1x1 eig, 2 byte pixels %gggrrrrr,%0bbbbbgg          *
  19.  * mode 0x201 - 15 bpp, 1x2 eig, 2 byte pixels %gggrrrrr,%0bbbbbgg          *
  20.  *(modes 0x202 & 0x203 reserved for 16bpp paletted, not yet implemented)    *
  21.  * mode 0x300 - 24 bpp, 1x1 eig, 3 byte pixels 0xRR,0xGG,0xBB               *
  22.  * mode 0x301 - 24 bpp, 1x2 eig, 3 byte pixels 0xRR,0xGG,0xBB               *
  23.  * mode 0x402 - 24 bpp, 1x1 eig, 1 WORD pixels 0x00BBGGRR                   *
  24.  * mode 0x403 - 24 bpp, 1x2 eig, 1 WORD pixels 0x00BBGGRR                   *
  25.  *                                                                          *
  26.  * NEW:                                                                     *
  27.  * Deep sprite type 8 - 24 bpp, 3 byte pixels 0xRR,0xGG,0xBB                *
  28.  *                                                                          *
  29.  * Version 5.10 (15-Jul-1994)                                               *
  30.  *                                                                          *
  31.  * (C) 1993/4 DEEJ Technology PLC                                           *
  32.  *                                                                          *
  33.  ****************************************************************************/
  34.  
  35. #include <stdlib.h>
  36. #include <stdio.h>
  37. #include <string.h>
  38. #include "io.h"
  39. #include "sprite.h"
  40.  
  41. static uint read_pixel_val_1(spr_info_str*, int, int);
  42. static uint read_pixel_rgb_1(spr_info_str*, int, int);
  43. static void write_pixel_val_1(spr_info_str*, int, int, uint);
  44. static void write_pixel_rgb_1(spr_info_str*, int, int, uint);
  45. static uint read_pixel_val_2(spr_info_str*, int, int);
  46. static uint read_pixel_rgb_2(spr_info_str*, int, int);
  47. static void write_pixel_val_2(spr_info_str*, int, int, uint);
  48. static void write_pixel_rgb_2(spr_info_str*, int, int, uint);
  49. static uint read_pixel_val_4(spr_info_str*, int, int);
  50. static uint read_pixel_rgb_4(spr_info_str*, int, int);
  51. static void write_pixel_val_4(spr_info_str*, int, int, uint);
  52. static void write_pixel_rgb_4(spr_info_str*, int, int, uint);
  53. static uint read_pixel_val_8(spr_info_str*, int, int);
  54. static uint read_pixel_rgb_8(spr_info_str*, int, int);
  55. static void write_pixel_val_8(spr_info_str*, int, int, uint);
  56. static void write_pixel_rgb_8(spr_info_str*, int, int, uint);
  57. static uint read_pixel_val_15(spr_info_str*, int, int);
  58. static uint read_pixel_rgb_15(spr_info_str*, int, int);
  59. static void write_pixel_val_15(spr_info_str*, int, int, uint);
  60. static void write_pixel_rgb_15(spr_info_str*, int, int, uint);
  61. static uint read_pixel_24_24(spr_info_str*, int, int);
  62. static void write_pixel_24_24(spr_info_str*, int, int, uint);
  63. static uint read_pixel_24_32_LE(spr_info_str*, int, int);
  64. static uint read_pixel_24_32_BE(spr_info_str*, int, int);
  65. static void write_pixel_24_32_LE(spr_info_str*, int, int, uint);
  66. static void write_pixel_24_32_BE(spr_info_str*, int, int, uint);
  67.  
  68. /*
  69.  * global description of spritefile structure for read/write_struct()
  70.  */
  71.  
  72. int spritefile_descr[] = { 4,4,4, 4,12, 4,4, 4,4, 4,4, 4, -1 };
  73.  
  74.  
  75. extern void alloc_spr_data(spr_info_str *sinfo)
  76. {
  77.         if((sinfo->spr_data = (uchar*)malloc(sinfo->line_size*sinfo->Y))==0)
  78.         {
  79.                 fprintf(stderr,"Could not allocate memory for sprite buffer\n");
  80.                 exit(2);
  81.         }
  82. }
  83.  
  84. extern void alloc_spr_line(spr_info_str *sinfo)
  85. {
  86.         if((sinfo->spr_data = (uchar*)malloc(sinfo->line_size))==0)
  87.         {
  88.                 fprintf(stderr,"Could not allocate memory for sprite buffer\n");
  89.                 exit(2);
  90.         }
  91. }
  92.  
  93. /*
  94.  * fill out spr_info fields
  95.  * depending on mode number
  96.  */
  97.  
  98. void mode_info(spr_info_str *sinfo, spritefile *sprite)
  99. {
  100.     int xres,yres,type;
  101.  
  102.         sinfo->mode = sprite->mode;
  103.         sinfo->Xasp = 1;
  104.  
  105.         switch(sprite->mode)
  106.         {
  107.           case    18:
  108.           case    23: /* hi-res mono */
  109.           case    25:
  110.           case    29: sinfo->bpp = 1;  sinfo->pix = 1;  sinfo->Yasp = 1;  break;
  111.           case     0:
  112.           case    37:
  113.           case   108:
  114.           case   112: sinfo->bpp = 1;  sinfo->pix = 1;  sinfo->Yasp = 2;  break;
  115.  
  116.           case    19:
  117.           case    26:
  118.           case    30: sinfo->bpp = 2;  sinfo->pix = 2;  sinfo->Yasp = 1;  break;
  119.           case     8:
  120.           case    38:
  121.           case   109:
  122.           case   113: sinfo->bpp = 2;  sinfo->pix = 2;  sinfo->Yasp = 2;  break;
  123.  
  124.           case    20:
  125.           case    27:
  126.           case    31: sinfo->bpp = 4;  sinfo->pix = 4;  sinfo->Yasp = 1;  break;
  127.           case    12:
  128.           case    39:
  129.           case   110:
  130.           case   114: sinfo->bpp = 4;  sinfo->pix = 4;  sinfo->Yasp = 2;  break;
  131.  
  132.           case    21:
  133.           case    28:
  134.           case    32: sinfo->bpp = 8;  sinfo->pix = 8;  sinfo->Yasp = 1;  break;
  135.           case    15:
  136.           case    40:
  137.           case   111:
  138.           case   115: sinfo->bpp = 8;  sinfo->pix = 8;  sinfo->Yasp = 2;  break;
  139.           case    13: sinfo->bpp = 8;  sinfo->pix = 8;  sinfo->Yasp = 2;  
  140.                                                         sinfo->Xasp = 2;  break;
  141.  
  142.       /* old extended mode numbers */
  143.  
  144.           /* 8 bit extended format, retained for compatablity with old lib */
  145.           case 0x100:
  146.           case 0x102: sinfo->bpp = 8;  sinfo->pix = 8;  sinfo->Yasp = 1;  break;
  147.           case 0x101:
  148.           case 0x103: sinfo->bpp = 8;  sinfo->pix = 8;  sinfo->Yasp = 2;  break;
  149.  
  150.           /* 15 bpp 16 bit units */
  151.           case 0x200: sinfo->bpp = 15; sinfo->pix = 16; sinfo->Yasp = 1;  break;
  152.           case 0x201: sinfo->bpp = 15; sinfo->pix = 16; sinfo->Yasp = 2;  break;
  153.  
  154.           /* 24 bpp */
  155.           case 0x300: sinfo->bpp = 24; sinfo->pix = 24; sinfo->Yasp = 1;  break;
  156.           case 0x301: sinfo->bpp = 24; sinfo->pix = 24; sinfo->Yasp = 2;  break;
  157.  
  158.           /* 24 bpp 32 bit units */
  159.           case 0x400: sinfo->bpp = 24; sinfo->pix = 32; sinfo->Yasp = 1;  break;
  160.           case 0x401: sinfo->bpp = 24; sinfo->pix = 32; sinfo->Yasp = 2;  break;
  161.  
  162.           default:
  163.         /* check for new deep sprite format */
  164.  
  165.         type = (unsigned)sinfo->mode >> 27;
  166.             xres = (sinfo->mode >>  1) & 0xFFF;
  167.             yres = (sinfo->mode >> 14) & 0xFFF;
  168.  
  169.         if(type != 0)
  170.         {
  171.             switch(type)
  172.             {
  173.               case 1: sinfo->bpp =  1; sinfo->pix =  1; break;
  174.               case 2: sinfo->bpp =  2; sinfo->pix =  2; break;
  175.               case 3: sinfo->bpp =  4; sinfo->pix =  4; break;
  176.               case 4: sinfo->bpp =  8; sinfo->pix =  8; break;
  177.               case 5: sinfo->bpp = 15; sinfo->pix = 16; break;
  178.               case 6: sinfo->bpp = 24; sinfo->pix = 32; break;
  179.                /* case 7: 32 bit CMYK not supported */
  180.               case 8: sinfo->bpp = 24; sinfo->pix = 24; break;
  181.                /* ^^^^^^ DEEJ extension to deep sprite format */
  182.               default:
  183.                 fprintf(stderr,"Unsupported mode type %d\n",
  184.                     type);
  185.                 exit(2);
  186.             }
  187.             sinfo->Xasp = xres==45 ? 2:1;
  188.             sinfo->Yasp = yres==45 ? 2:1;
  189.         }
  190.         else
  191.         {
  192.             fprintf(stderr,"Unrecognised mode %d\n",sinfo->mode);
  193.             exit(2);
  194.         }
  195.                 break;
  196.         }
  197.  
  198.         sinfo->cols      = 1<<sinfo->bpp;
  199.         sinfo->line_size = (sprite->width+1)*4;
  200.         sinfo->X         = (sprite->width*32 +(sprite->right-sprite->left)+1) /
  201.                            sinfo->pix;
  202.         sinfo->Y         = sprite->height + 1;
  203.  
  204.     /* setup best pixel reading and writing functions */
  205.  
  206.     spr_init_funcs(sinfo);
  207. }
  208.  
  209. /*
  210.  * fills in rest of spr_info_structure
  211.  * from pix,bpp,X,Y,Yasp fields
  212.  * choses appropriate mode from bpp & pix
  213.  */
  214.  
  215. void fill_info(spr_info_str *sinfo)
  216. {
  217.     int type,xres,yres;
  218.  
  219.     type = 0;
  220.  
  221.         switch(sinfo->bpp)
  222.         {
  223.             case  1:
  224.                 if(sinfo->Yasp==1) sinfo->mode = 18;
  225.                 else               sinfo->mode = 0;
  226.         sinfo->pix = sinfo->bpp;
  227.                 break;
  228.  
  229.             case  2:
  230.                 if(sinfo->Yasp==1) sinfo->mode = 19;
  231.                 else               sinfo->mode = 8;
  232.         sinfo->pix = sinfo->bpp;
  233.                 break;
  234.  
  235.             case  4:
  236.                 if(sinfo->Yasp==1) sinfo->mode = 20;
  237.                 else               sinfo->mode = 12;
  238.         sinfo->pix = sinfo->bpp;
  239.                 break;
  240.  
  241.             case  8: 
  242.                 if(sinfo->Yasp==1) sinfo->mode = 21;
  243.                 else               sinfo->mode = 15;
  244.         sinfo->pix = sinfo->bpp;
  245.                 break;
  246.  
  247.             case 15:
  248.         type = 5;
  249.         xres = 90;
  250.                 if(sinfo->Yasp!=1) yres = 45;
  251.                 else               yres = 90;
  252.         sinfo->pix = 16;
  253.                 break;
  254.  
  255.             case 24:
  256.                 if(sinfo->pix == 24)
  257.                 {
  258.             /* DEEJ extension to deep sprite format */
  259.             type = 8;
  260.             xres = 90;
  261.                         if(sinfo->Yasp!=1) yres = 45;
  262.                     else               yres = 90;
  263.             sinfo->pix = 24;
  264.                 }
  265.                 else
  266.                 {
  267.             type = 6;
  268.             xres = 90;
  269.                         if(sinfo->Yasp!=1) yres = 45;
  270.                     else               yres = 90;
  271.             sinfo->pix = 32;
  272.                 }
  273.                 break;
  274.  
  275.             default:
  276.                 break;
  277.         }
  278.  
  279.     /* make mode number for deep sprite type */
  280.  
  281.     if(type != 0)
  282.     {
  283.         sinfo->mode = ((unsigned)type << 27) |
  284.                   (xres <<  1)           |
  285.                   (yres << 14)           | 1;
  286.     }
  287.  
  288.         sinfo->Xasp         = 1;
  289.         sinfo->cols         = 1<<sinfo->bpp;
  290.         sinfo->line_size    = (((sinfo->X*sinfo->pix)+31)/32)*4;
  291.         sinfo->has_palette  = (sinfo->bpp<=8) ? sinfo->cols : 0;
  292.  
  293.     /* setup best pixel reading and writing functions */
  294.  
  295.     spr_init_funcs(sinfo);
  296. }
  297.  
  298. /*
  299.  * makes a standard 256 colour palette
  300.  */
  301.  
  302. void palette256(uint *palette)
  303. {
  304.         int i;
  305.         uint t,r,g,b;
  306.  
  307.         for(i=0; i<256; i++)
  308.         {
  309.                 t = i & 3;
  310.                 r = ((i>>1) & 8) | (i      & 4) | t;
  311.                 g = ((i>>3) & 12)               | t;
  312.                 b = ((i>>4) & 8) | ((i>>1) & 4) | t;
  313.                 palette[i] = ((r*0x11)<<8) + ((g*0x11)<<16) + ((b*0x11)<<24);
  314.         }
  315. }
  316.  
  317. /*
  318.  * Reads palette for all standard sprites
  319.  * and new 8 & 15 bpp modes
  320.  */
  321.  
  322. void read_palette(spr_info_str *sinfo, int size, FILE *infile)
  323. {
  324.         int i;
  325.         uint words[2];
  326.  
  327.         if(size>0)
  328.         {
  329.                 for(i=0; i<size/8; i++)
  330.                 {
  331.                         /* read flash 1/2 pair 0xBBGGRR00 (LE) */
  332.                         fread(words, 8, 1, infile);
  333.                         /*
  334.                         if(words[0] != words[1])
  335.                                 sprintf(stderr,
  336.                                   "Warining: palette entry %d is flashing\n",i);
  337.                         */
  338.                         sinfo->palette[i] = endian(LE,words[0]);
  339.                 }
  340.                 sinfo->has_palette = size/8;
  341.  
  342.                 /* account for 256 colour sprites with old format palette */
  343.  
  344.                 if(sinfo->cols==256 && ((size/8)==16 || (size/8)==64))
  345.                 {
  346.                         default_palette(sinfo);
  347.                 }
  348.         }
  349.         else
  350.         {
  351.                 /* no palette data in file - make default palettes for mode */
  352.  
  353.                 default_palette(sinfo);
  354.         }
  355. }
  356.  
  357. /*
  358.  * makes default palettes for all modes
  359.  */
  360.  
  361. void default_palette(spr_info_str *sinfo)
  362. {
  363.         int i;
  364.  
  365.         switch(sinfo->bpp)
  366.         {
  367.             case 1:
  368.                 sinfo->palette[0]  = 0x00000000;
  369.                 sinfo->palette[1]  = 0xFFFFFF00;
  370.                 sinfo->has_palette = 2;
  371.                 break;
  372.  
  373.             case 2:
  374.                 sinfo->palette[0]  = 0x00000000;
  375.                 sinfo->palette[1]  = 0x0000FF00;
  376.                 sinfo->palette[2]  = 0x00FFFF00;
  377.                 sinfo->palette[3]  = 0xFFFFFF00;
  378.                 sinfo->has_palette = 4;
  379.                 break;
  380.  
  381.             case 4:
  382.                 sinfo->palette[0]  = 0x00000000;
  383.                 sinfo->palette[1]  = 0x0000FF00;
  384.                 sinfo->palette[2]  = 0x00FF0000;
  385.                 sinfo->palette[3]  = 0x00FFFF00;
  386.                 sinfo->palette[4]  = 0xFF000000;
  387.                 sinfo->palette[5]  = 0xFF00FF00;
  388.                 sinfo->palette[6]  = 0xFFFF0000;
  389.                 sinfo->palette[7]  = 0xFFFFFF00;
  390.                 sinfo->has_palette = 8;
  391.  
  392.                 /* substitute for flashing colours of default palette */
  393.                 for(i=0; i<8; i++)
  394.                         sinfo->palette[i+8] = sinfo->palette[i];
  395.                 break;
  396.  
  397.             case 8:
  398.                 palette256(sinfo->palette);
  399.                 sinfo->has_palette = 256;
  400.                 break;
  401.  
  402.             default:
  403.                 /* >8 bpp modes have value derived palettes */
  404.                 sinfo->has_palette = FALSE;
  405.                 break;
  406.         }
  407. }
  408.  
  409. /*
  410.  * read sprite from input source
  411.  * fill in spr_info structure 
  412.  * assigning approriate palette to output
  413.  */
  414.  
  415. void read_sprite_header(spr_info_str *in, FILE *infile)
  416. {
  417.         spritefile sprite;
  418.  
  419.         /* read sprite file header to 'sprite' */
  420.  
  421.         read_struct(LE, (BYTE*)&sprite, spritefile_descr, infile);
  422.  
  423.     if(sprite.offset != 16)
  424.     {
  425.         fprintf(stderr,"Error: bad sprite header offset (corrupt or not a sprite?)\n");
  426.         exit(1);
  427.     }
  428.     if(sprite.number != 1)
  429.         fprintf(stderr,"Warning: more than one sprite in file\n");
  430.     if(sprite.left != 0)
  431.         fprintf(stderr,"Warning: left wastage no longer supported\n");
  432.  
  433.         /* get mode dependant info from sprite */
  434.  
  435.         mode_info(in, &sprite);
  436.         read_palette(in, sprite.sprite-44, infile);
  437.  
  438.         /* read_palette should leave us at sprite data */
  439. }
  440.  
  441. /*
  442.  * read sprite header, allocate memory and read sprite data
  443.  */
  444.  
  445. void read_sprite(spr_info_str *in, FILE *infile)
  446. {
  447.         read_sprite_header(in, infile);
  448.  
  449.         alloc_spr_data(in);
  450.  
  451.         fread(in->spr_data, in->line_size, in->Y, infile); 
  452. }
  453.  
  454. /*
  455.  * write sprite header to file
  456.  * using info structure
  457.  */
  458.  
  459. void write_sprite_header(spr_info_str *out, FILE *outfile)
  460. {
  461.         int        i, pal_size, spr_size;
  462.         uint       words[2];
  463.         spritefile sprite;
  464.  
  465.     if(out->bpp > 8)
  466.                 pal_size = 0;
  467.     else
  468.                 pal_size = out->cols*8;
  469.  
  470.         spr_size = out->line_size * out->Y;
  471.  
  472.         sprite.number = 1;
  473.         sprite.offset = 16;
  474.         sprite.free   = spr_size + pal_size + 44 + sprite.offset;
  475.         sprite.next   = spr_size + pal_size + 44;
  476.         sprite.width  = out->line_size/4 -1;
  477.         sprite.height = out->Y-1;
  478.         sprite.left   = 0;
  479.         sprite.right  = 31 - (out->line_size*8 - out->X*out->pix);
  480.         sprite.sprite = pal_size + 44;
  481.         sprite.mask   = sprite.sprite;
  482.         sprite.mode   = out->mode;
  483.  
  484.         memset(sprite.name, 0, 12);
  485.  
  486.         switch(out->pix)
  487.         {
  488.             case 1:
  489.             case 2:
  490.             case 4:
  491.             case 8:
  492.             case 15:
  493.             case 24:
  494.                     sprintf(sprite.name,"sprite%dbpp",out->bpp);
  495.                     break;
  496.             case 32:
  497.                     sprintf(sprite.name,"sprite24/32");
  498.                     break;
  499.             default:
  500.                     break;
  501.         }
  502.  
  503.         /* write header to file */
  504.  
  505.         write_struct(LE, (BYTE*)&sprite, spritefile_descr, outfile);
  506.  
  507.         /* write palette */
  508.  
  509.         if(pal_size > 0)
  510.         {
  511.                 for(i=0; i<out->cols; i++)
  512.                 {
  513.                         words[0] = endian(LE,out->palette[i]);
  514.                         words[1] = words[0];
  515.                         fwrite((char*)words, 8, 1, outfile);
  516.                 }
  517.         }
  518.         /* sprite data can now be written to file */
  519. }
  520.  
  521. void write_sprite(spr_info_str *out, FILE *outfile)
  522. {
  523.         write_sprite_header(out, outfile);
  524.         fwrite(out->spr_data, out->line_size, out->Y, outfile); 
  525. }
  526.  
  527. /*
  528.  * general purpose
  529.  * read 0xBBGGRR00 palette word
  530.  * for sprite pixel x,y
  531.  */
  532.  
  533. uint read_pixel_RGB(spr_info_str *s, int x, int y)
  534. {
  535.         uint x0,x1,ppb;
  536.         uint value, r,g,b;
  537.  
  538.         switch(s->bpp)
  539.         {
  540.             case  8:
  541.                 value = s->spr_data[s->line_size*y + x];
  542.                 break;
  543.         
  544.             case  1:
  545.             case  2:
  546.             case  4:
  547.                 ppb   = 8/s->pix;
  548.                 x0    = x / ppb;
  549.                 x1    = (x % ppb)*s->bpp;
  550.                 value = s->spr_data[s->line_size*y + x0];
  551.                 value = (value >> x1) & (s->cols-1);
  552.                 break;
  553.  
  554.             case 15:
  555.                 value = s->spr_data[s->line_size*y + x*2 + 0] +
  556.                        (s->spr_data[s->line_size*y + x*2 + 1] << 8);
  557.  
  558.                 /* extract 5 bit colour fields from index */
  559.  
  560.                 r = (value >> 0)  & 0x1F;
  561.                 g = (value >> 5)  & 0x1F;
  562.                 b = (value >> 10) & 0x1F;
  563.  
  564.                 /* convert 5 bit to 8 bit using  */
  565.                 /* upper 3 bits for lower 3 bits */
  566.  
  567.                 r = (r << 3) | (r >> 2);
  568.                 g = (g << 3) | (g >> 2);
  569.                 b = (b << 3) | (b >> 2);
  570.  
  571.                 return( (b<<24) | (g<<16) | (r<<8) );
  572.                 break;
  573.  
  574.             case 24:
  575.                 if(s->pix==24)
  576.                 {
  577.                     value = (s->spr_data[s->line_size*y + x*3 + 0] <<  8) |
  578.                             (s->spr_data[s->line_size*y + x*3 + 1] << 16) |
  579.                             (s->spr_data[s->line_size*y + x*3 + 2] << 24);
  580.                 }
  581.                 else
  582.                 {
  583.                     value=endian(LE,*((int*)&s->spr_data[s->line_size*y+x*4]));
  584.  
  585.                     /* xxBBGGRR to BBGGRRxx */
  586.             value = (value << 8) | (value >> 24);
  587.                 }
  588.                 return(value);
  589.                 break;
  590.  
  591.             default:
  592.                 break;
  593.         }
  594.  
  595.         /* left with paletted modes, so do lookup */
  596.  
  597.         return(s->palette[value]);
  598. }
  599.  
  600. /*
  601.  * general purpose
  602.  * read actual data
  603.  * for sprite pixel x,y
  604.  */
  605.  
  606. uint read_pixel_val(spr_info_str *s, int x, int y)
  607. {
  608.         int x0,x1,ppb;
  609.         uint value;
  610.  
  611.         switch(s->bpp)
  612.         {
  613.             case  8:
  614.                 value = s->spr_data[s->line_size*y + x];
  615.                 break;
  616.         
  617.             case  1:
  618.             case  2:
  619.             case  4:
  620.                 ppb   = 8/s->pix;
  621.                 x0    = x / ppb;
  622.                 x1    = (x % ppb)*s->bpp;
  623.                 value = s->spr_data[s->line_size*y + x0];
  624.                 value = (value >> x1) & (s->cols-1);
  625.                 break;
  626.  
  627.             case 15:
  628.                 value = s->spr_data[s->line_size*y + x*2 + 0] +
  629.                        (s->spr_data[s->line_size*y + x*2 + 1] << 8);
  630.                 break;
  631.  
  632.             case 24:
  633.                 if(s->pix==24)
  634.                 {
  635.                     value = (s->spr_data[s->line_size*y + x*3 + 0] <<  8) |
  636.                             (s->spr_data[s->line_size*y + x*3 + 1] << 16) |
  637.                             (s->spr_data[s->line_size*y + x*3 + 2] << 24);
  638.                 }
  639.                 else
  640.                 {
  641.                     value=endian(LE,*((int*)&s->spr_data[s->line_size*y+x*4]));
  642.  
  643.                     /* xxBBGGRR to BBGGRRxx */
  644.             value = (value << 8) | (value >> 24);
  645.                 }
  646.                 break;
  647.  
  648.             default:
  649.                 break;
  650.         }
  651.  
  652.         return(value);
  653. }
  654.  
  655. /*
  656.  * general purpose
  657.  * write actual pixel data
  658.  * for sprite pixel x,y
  659.  */
  660.  
  661. void write_pixel_val(spr_info_str *s, int x, int y, uint value)
  662. {
  663.         int x0,x1,ppb;
  664.         uint oldval;
  665.  
  666.         switch(s->bpp)
  667.         {
  668.             case  8:
  669.                 s->spr_data[s->line_size*y + x] = value;
  670.                 break;
  671.  
  672.             case  1:
  673.             case  2:
  674.             case  4:
  675.                 ppb    = 8/s->pix;
  676.                 x0     = x / ppb;
  677.                 x1     = (x % ppb)*s->bpp;
  678.                 oldval = s->spr_data[s->line_size*y + x0];
  679.                 value  = (value << x1) | (oldval & ~((s->cols-1) << x1));
  680.                 s->spr_data[s->line_size*y + x0] = value;
  681.                 break;
  682.  
  683.             case 15:
  684.                 s->spr_data[s->line_size*y + x*2 + 0] = value;
  685.                 s->spr_data[s->line_size*y + x*2 + 1] = value >> 8;
  686.                 break;
  687.  
  688.             case 24:
  689.                 if(s->pix==24)
  690.                 {
  691.                     s->spr_data[s->line_size*y + x*3 + 0] = value >> 8;
  692.                     s->spr_data[s->line_size*y + x*3 + 1] = value >> 16;
  693.                     s->spr_data[s->line_size*y + x*3 + 2] = value >> 24;
  694.                 }
  695.                 else
  696.                 {
  697.                     /* BBGGRRxx to xxBBGGRR */
  698.             value = (value >> 8) | (value << 24);
  699.  
  700.                     *((uint*)&s->spr_data[s->line_size*y + x*4]) =
  701.                                                                endian(LE,value);
  702.                 }
  703.                 break;
  704.  
  705.             default:
  706.                 break;
  707.         }
  708. }
  709.  
  710. static uint read_pixel_val_1(spr_info_str *s, int x, int y)
  711. {
  712.         uint x0    = x>>3;
  713.         uint x1    = (x - (x0<<3))*s->bpp;
  714.         uint value = s->spr_data[s->line_size*y + x0];
  715.         return((value >> x1) & (s->cols-1));
  716. }
  717.  
  718. static uint read_pixel_rgb_1(spr_info_str *s, int x, int y)
  719. {
  720.         uint x0    = x>>3;
  721.         uint x1    = (x - (x0<<3))*s->bpp;
  722.         uint value = s->spr_data[s->line_size*y + x0];
  723.         return(s->palette[(value >> x1) & (s->cols-1)]);
  724. }
  725.  
  726. static void write_pixel_val_1(spr_info_str *s, int x, int y, uint value)
  727. {
  728.         uint x0          = x>>3;
  729.         uint x1          = (x - (x0<<3))*s->bpp;
  730.         uint off         = s->line_size*y + x0;
  731.         uint oldval      = s->spr_data[off];
  732.         value            = (value << x1) | (oldval & ~((s->cols-1) << x1));
  733.         s->spr_data[off] = value;
  734. }
  735.  
  736. static void write_pixel_rgb_1(spr_info_str *s, int x, int y, uint value)
  737. {
  738.     pix_str pix;
  739.         uint x0          = x>>3;
  740.         uint x1          = (x - (x0<<3))*s->bpp;
  741.         uint off         = s->line_size*y + x0;
  742.         uint oldval      = s->spr_data[off];
  743.     pix.red          = (value >>  8) & 0xFF;
  744.     pix.green        = (value >> 16) & 0xFF;
  745.     pix.blue         = (value >> 24) & 0xFF;
  746.         s->spr_data[off] = (s->closest_rgb(s, &pix)->value << x1)
  747.                  | (oldval & ~((s->cols-1) << x1));
  748. }
  749.  
  750. static uint read_pixel_val_2(spr_info_str *s, int x, int y)
  751. {
  752.         uint x0    = x>>2;
  753.         uint x1    = (x - (x0<<2))*s->bpp;
  754.         uint value = s->spr_data[s->line_size*y + x0];
  755.         return((value >> x1) & (s->cols-1));
  756. }
  757.  
  758. static uint read_pixel_rgb_2(spr_info_str *s, int x, int y)
  759. {
  760.         uint x0    = x>>2;
  761.         uint x1    = (x - (x0<<2))*s->bpp;
  762.         uint value = s->spr_data[s->line_size*y + x0];
  763.         return(s->palette[(value >> x1) & (s->cols-1)]);
  764. }
  765.  
  766. static void write_pixel_val_2(spr_info_str *s, int x, int y, uint value)
  767. {
  768.         uint x0          = x>>2;
  769.         uint x1          = (x - (x0<<2))*s->bpp;
  770.         uint off         = s->line_size*y + x0;
  771.         uint oldval      = s->spr_data[off];
  772.         value            = (value << x1) | (oldval & ~((s->cols-1) << x1));
  773.         s->spr_data[off] = value;
  774. }
  775.  
  776. static void write_pixel_rgb_2(spr_info_str *s, int x, int y, uint value)
  777. {
  778.     pix_str pix;
  779.         uint x0          = x>>2;
  780.         uint x1          = (x - (x0<<2))*s->bpp;
  781.         uint off         = s->line_size*y + x0;
  782.         uint oldval      = s->spr_data[off];
  783.     pix.red          = (value >>  8) & 0xFF;
  784.     pix.green        = (value >> 16) & 0xFF;
  785.     pix.blue         = (value >> 24) & 0xFF;
  786.         s->spr_data[off] = (s->closest_rgb(s, &pix)->value << x1)
  787.                  | (oldval & ~((s->cols-1) << x1));
  788. }
  789. static uint read_pixel_val_4(spr_info_str *s, int x, int y)
  790. {
  791.         uint x0    = x>>1;
  792.         uint x1    = (x - (x0<<1))*s->bpp;
  793.         uint value = s->spr_data[s->line_size*y + x0];
  794.         return((value >> x1) & (s->cols-1));
  795. }
  796.  
  797. static uint read_pixel_rgb_4(spr_info_str *s, int x, int y)
  798. {
  799.         uint x0    = x>>1;
  800.         uint x1    = (x - (x0<<1))*s->bpp;
  801.         uint value = s->spr_data[s->line_size*y + x0];
  802.         return(s->palette[(value >> x1) & (s->cols-1)]);
  803. }
  804.  
  805. static void write_pixel_val_4(spr_info_str *s, int x, int y, uint value)
  806. {
  807.         uint x0          = x>>1;
  808.         uint x1          = (x - (x0<<1))*s->bpp;
  809.         uint off         = s->line_size*y + x0;
  810.         uint oldval      = s->spr_data[off];
  811.         value            = (value << x1) | (oldval & ~((s->cols-1) << x1));
  812.         s->spr_data[off] = value;
  813. }
  814.  
  815. static void write_pixel_rgb_4(spr_info_str *s, int x, int y, uint value)
  816. {
  817.     pix_str pix;
  818.         uint x0          = x>>1;
  819.         uint x1          = (x - (x0<<1))*s->bpp;
  820.         uint off         = s->line_size*y + x0;
  821.         uint oldval      = s->spr_data[off];
  822.     pix.red          = (value >>  8) & 0xFF;
  823.     pix.green        = (value >> 16) & 0xFF;
  824.     pix.blue         = (value >> 24) & 0xFF;
  825.         s->spr_data[off] = (s->closest_rgb(s, &pix)->value << x1)
  826.                  | (oldval & ~((s->cols-1) << x1));
  827. }
  828.  
  829. static uint read_pixel_val_8(spr_info_str *s, int x, int y)
  830. {
  831.         return(s->spr_data[s->line_size*y + x]);
  832. }
  833.  
  834. static uint read_pixel_rgb_8(spr_info_str *s, int x, int y)
  835. {
  836.         return(s->palette[s->spr_data[s->line_size*y + x]]);
  837. }
  838.  
  839. static void write_pixel_val_8(spr_info_str *s, int x, int y, uint value)
  840. {
  841.         s->spr_data[s->line_size*y + x] = value;
  842. }
  843.  
  844. static void write_pixel_rgb_8(spr_info_str *s, int x, int y, uint value)
  845. {
  846.     pix_str pix;
  847.     pix.red   = (value >>  8) & 0xFF;
  848.     pix.green = (value >> 16) & 0xFF;
  849.     pix.blue  = (value >> 24) & 0xFF;
  850.         s->spr_data[s->line_size*y + x] = s->closest_rgb(s, &pix)->value;
  851. }
  852.  
  853.  
  854. static uint read_pixel_val_15(spr_info_str *s, int x, int y)
  855. {
  856.         return( s->spr_data[s->line_size*y + (x<<1)] +
  857.                (s->spr_data[s->line_size*y + (x<<1)+1] << 8));
  858. }
  859.  
  860. static uint read_pixel_rgb_15(spr_info_str *s, int x, int y)
  861. {
  862.         uint value, r,g,b;
  863.  
  864.         value = s->spr_data[s->line_size*y + (x<<1)] +
  865.                (s->spr_data[s->line_size*y + (x<<1)+1] << 8);
  866.  
  867.         /* extract 5 bit colour fields from index */
  868.  
  869.         r = (value >> 0)  & 0x1F;
  870.         g = (value >> 5)  & 0x1F;
  871.         b = (value >> 10) & 0x1F;
  872.  
  873.         /* convert 5 bit to 8 bit using  */
  874.         /* upper 3 bits for lower 3 bits */
  875.  
  876.         r = (r << 3) | (r >> 2);
  877.         g = (g << 3) | (g >> 2);
  878.         b = (b << 3) | (b >> 2);
  879.  
  880.         return( (b<<24) | (g<<16) | (r<<8) );
  881. }
  882.  
  883. static void write_pixel_val_15(spr_info_str *s, int x, int y, uint value)
  884. {
  885.         s->spr_data[s->line_size*y + (x<<1)]   = value;
  886.         s->spr_data[s->line_size*y + (x<<1)+1] = value >> 8;
  887. }
  888.  
  889. static void write_pixel_rgb_15(spr_info_str *s, int x, int y, uint value)
  890. {
  891.     pix_str pix;
  892.     pix.red   = (value >>  8) & 0xFF;
  893.     pix.green = (value >> 16) & 0xFF;
  894.     pix.blue  = (value >> 24) & 0xFF;
  895.         value     = s->closest_rgb(s, &pix)->value;
  896.         s->spr_data[s->line_size*y + (x<<1)]   = value;
  897.         s->spr_data[s->line_size*y + (x<<1)+1] = value >> 8;
  898. }
  899.  
  900. static uint read_pixel_24_24(spr_info_str *s, int x, int y)
  901. {
  902.     int off = s->line_size*y + x*3;
  903.         return((s->spr_data[off]   <<  8) |
  904.                (s->spr_data[off+1] << 16) |
  905.                (s->spr_data[off+2] << 24));
  906. }
  907.  
  908. static void write_pixel_24_24(spr_info_str *s, int x, int y, uint value)
  909. {
  910.     int off = s->line_size*y + x*3;
  911.         s->spr_data[off]   = value >>  8;
  912.         s->spr_data[off+1] = value >> 16;
  913.         s->spr_data[off+2] = value >> 24;
  914. }
  915.  
  916. static uint read_pixel_24_32_LE(spr_info_str *s, int x, int y)
  917. {
  918.         uint value = *((int*)&s->spr_data[s->line_size*y + (x<<2)]);
  919.  
  920.         /* xxBBGGRR to BBGGRRxx */
  921.     return((value << 8) | (value >> 24));
  922. }
  923.  
  924. static uint read_pixel_24_32_BE(spr_info_str *s, int x, int y)
  925. {
  926.         uint value=swap_endian(*((int*)&s->spr_data[s->line_size*y+(x<<2)]));
  927.  
  928.         /* xxBBGGRR to BBGGRRxx */
  929.     return((value << 8) | (value >> 24));
  930. }
  931.  
  932. static void write_pixel_24_32_LE(spr_info_str *s, int x, int y, uint value)
  933. {
  934.         /* BBGGRRxx to xxBBGGRR */
  935.         *((uint*)&s->spr_data[s->line_size*y + (x<<2)]) = (value >> 8) |
  936.                                                           (value << 24);
  937. }
  938.  
  939. static void write_pixel_24_32_BE(spr_info_str *s, int x, int y, uint value)
  940. {
  941.         /* BBGGRRxx to xxBBGGRR */
  942.         *((uint*)&s->spr_data[s->line_size*y + (x<<2)]) =
  943.                 swap_endian((value >> 8) | (value >> 24));
  944. }
  945.  
  946. static pix_str *default_closest_rgb(spr_info_str *s, pix_str *p)
  947. {
  948.     p = p;
  949.  
  950.     fprintf(stderr,"closest_rgb function pointer not set up (%08X)\n",
  951.                        (int)s);
  952.     exit(1);
  953.  
  954.     return(0);
  955. }
  956.  
  957. /*
  958.  * calculate the best functions to use for
  959.  * reading and writing pixels
  960.  *
  961.  * NOTE: the write_pixel_RGB functions require
  962.  *       the closest_rgb function pointer to
  963.  *       be set up AFTER calling this function
  964.  */
  965.  
  966. void spr_init_funcs(spr_info_str *sinfo)
  967. {
  968.     switch(sinfo->bpp)
  969.     {
  970.         case 1:
  971.         sinfo->read_pixel_val  = read_pixel_val_1;
  972.         sinfo->read_pixel_rgb  = read_pixel_rgb_1;
  973.         sinfo->write_pixel_val = write_pixel_val_1;
  974.         sinfo->write_pixel_rgb = write_pixel_rgb_1;
  975.         break;
  976.  
  977.         case 2:
  978.         sinfo->read_pixel_val  = read_pixel_val_2;
  979.         sinfo->read_pixel_rgb  = read_pixel_rgb_2;
  980.         sinfo->write_pixel_val = write_pixel_val_2;
  981.         sinfo->write_pixel_rgb = write_pixel_rgb_2;
  982.         break;
  983.  
  984.             case 4:
  985.         sinfo->read_pixel_val  = read_pixel_val_4;
  986.         sinfo->read_pixel_rgb  = read_pixel_rgb_4;
  987.         sinfo->write_pixel_val = write_pixel_val_4;
  988.         sinfo->write_pixel_rgb = write_pixel_rgb_4;
  989.         break;
  990.  
  991.             case 8:
  992.         sinfo->read_pixel_val  = read_pixel_val_8;
  993.         sinfo->read_pixel_rgb  = read_pixel_rgb_8;
  994.         sinfo->write_pixel_val = write_pixel_val_8;
  995.         sinfo->write_pixel_rgb = write_pixel_rgb_8;
  996.         break;
  997.  
  998.             case 15:
  999.         sinfo->read_pixel_val  = read_pixel_val_15;
  1000.         sinfo->read_pixel_rgb  = read_pixel_rgb_15;
  1001.         sinfo->write_pixel_val = write_pixel_val_15;
  1002.         sinfo->write_pixel_rgb = write_pixel_rgb_15;
  1003.         break;
  1004.  
  1005.             case 24:
  1006.         if(sinfo->pix == 24)
  1007.         {
  1008.             sinfo->read_pixel_val  = read_pixel_24_24;
  1009.             sinfo->read_pixel_rgb  = read_pixel_24_24;
  1010.             sinfo->write_pixel_val = write_pixel_24_24;
  1011.             sinfo->write_pixel_rgb = write_pixel_24_24;
  1012.         }
  1013.         else
  1014.         {
  1015.             if(ENDIAN_TYPE == LITTLE_ENDIAN)
  1016.             {
  1017.             sinfo->read_pixel_val  = read_pixel_24_32_LE;
  1018.             sinfo->read_pixel_rgb  = read_pixel_24_32_LE;
  1019.             sinfo->write_pixel_val = write_pixel_24_32_LE;
  1020.             sinfo->write_pixel_rgb = write_pixel_24_32_LE;
  1021.             }
  1022.             else
  1023.             {
  1024.             sinfo->read_pixel_val  = read_pixel_24_32_BE;
  1025.             sinfo->read_pixel_rgb  = read_pixel_24_32_BE;
  1026.             sinfo->write_pixel_val = write_pixel_24_32_BE;
  1027.             sinfo->write_pixel_rgb = write_pixel_24_32_BE;
  1028.             }
  1029.         }
  1030.         break;
  1031.  
  1032.         default:
  1033.         break;
  1034.     }
  1035.  
  1036.     sinfo->closest_rgb = default_closest_rgb;
  1037. }
  1038.