home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / rexx / library2 / gbmrexx / gbm / gbmspr.c < prev    next >
C/C++ Source or Header  |  1993-09-27  |  23KB  |  811 lines

  1. /*
  2.  
  3. GBMSPR.C  Archimedes Sprite from RiscOS Format support
  4.  
  5. In Archimedes terminology, a sprite is a bitmap with an optional mask plane.
  6.  
  7. Reads a sprite from file created by *ScreenSave or *SSave command.
  8. Will also write such a file containing a single sprite.
  9.  
  10. Input options: index=# (default: 0)
  11.  
  12. */
  13.  
  14. /*...sincludes:0:*/
  15. #include <stdio.h>
  16. #include <ctype.h>
  17. #include <stddef.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <memory.h>
  21. #include <malloc.h>
  22. #ifdef AIX
  23. #include <unistd.h>
  24. #else
  25. #include <io.h>
  26. #endif
  27. #include <fcntl.h>
  28. #include <sys/types.h>
  29. #include <sys/stat.h>
  30. #include "standard.h"
  31. #include "gbm.h"
  32.  
  33. /*...vgbm\46\h:0:*/
  34.  
  35. #ifndef min
  36. #define    min(a,b)    (((a)<(b))?(a):(b))
  37. #endif
  38. /*...e*/
  39.  
  40. /*...suseful:0:*/
  41. #define    low_byte(w)    ((byte)  ((w)&0x00ff)    )
  42. #define    high_byte(w)    ((byte) (((w)&0xff00)>>8))
  43. #define    make_word(a,b)    (((word)a) + (((word)b) << 8))
  44. /*...e*/
  45. /*...ssame:0:*/
  46. static BOOLEAN same(char *s1, char *s2, int n)
  47.     {
  48.     for ( ; n--; s1++, s2++ )
  49.         if ( tolower(*s1) != tolower(*s2) )
  50.             return ( FALSE );
  51.     return ( TRUE );
  52.     }
  53. /*...e*/
  54. /*...sfind_word_prefix:0:*/
  55. static char *find_word_prefix(char *str, char *substr)
  56.     {
  57.     char    buf [100+1], *s;
  58.     int    len = strlen(substr);
  59.  
  60.     for ( s  = strtok(strcpy(buf, str), " \t,");
  61.           s != NULL;
  62.           s  = strtok(NULL, " \t,") )
  63.         if ( same(s, substr, len) )
  64.             return ( str + (s - buf) );
  65.     return ( NULL );
  66.     }
  67. /*...e*/
  68.  
  69. /*...sread_word:0:*/
  70. static BOOLEAN read_word(int fd, word *w)
  71.     {
  72.     byte    low = 0, high = 0;
  73.  
  74.     read(fd, (char *) &low, 1);
  75.     read(fd, (char *) &high, 1);
  76.     *w = (word) (low + ((word) high << 8));
  77.     return ( TRUE );
  78.     }
  79. /*...e*/
  80. /*...sread_dword:0:*/
  81. static BOOLEAN read_dword(int fd, dword *d)
  82.     {
  83.     word    low, high;
  84.  
  85.     read_word(fd, &low);
  86.     read_word(fd, &high);
  87.     *d = low + ((dword) high << 16);
  88.     return ( TRUE );
  89.     }
  90. /*...e*/
  91. /*...swrite_word:0:*/
  92. static BOOLEAN write_word(int fd, word w)
  93.     {
  94.     byte    low  = (byte) w;
  95.     byte    high = (byte) (w >> 8);
  96.  
  97.     return ( write(fd, &low, 1) == 1 && write(fd, &high, 1) == 1 );
  98.     }
  99. /*...e*/
  100. /*...swrite_dword:0:*/
  101. static BOOLEAN write_dword(int fd, dword d)
  102.     {
  103.     return ( write_word(fd, (word) d) && write_word(fd, (word) (d >> 16)) );
  104.     }
  105. /*...e*/
  106.  
  107. static GBMFT spr_gbmft =
  108.     {
  109.     "Sprite",
  110.     "Archimedes Sprite from RiscOS",
  111.     "SPR",
  112.     GBM_FT_R1|GBM_FT_R4|GBM_FT_R8|
  113.     GBM_FT_W1|GBM_FT_W4|GBM_FT_W8,
  114.     };
  115.  
  116. #define    GBM_ERR_SPR_FIRST    ((GBM_ERR) 1400)
  117. #define    GBM_ERR_SPR_MODE    ((GBM_ERR) 1401)
  118. #define    GBM_ERR_SPR_OFFSET    ((GBM_ERR) 1402)
  119. #define    GBM_ERR_SPR_PAL8    ((GBM_ERR) 1403)
  120.  
  121. typedef struct
  122.     {
  123.     long pos_palette, pos_image, pos_mask;
  124.     dword bytes_per_line, first_bit, last_bit, actual_bpp;
  125.     } SPR_PRIV;
  126.  
  127. /*...sbpp_of_mode\44\ mode_of_bpp:0:*/
  128. static int bpp_of_mode [] =
  129.     {
  130.     1,    /*  0: 640x256 */
  131.     2,    /*  1: 320x256 */
  132.     4,    /*  2: 160x256 */
  133.     -1,    /*  3: Text only */
  134.     1,    /*  4: 320x256 */
  135.     2,    /*  5: 160x256 */
  136.     2,    /*  6: 160x256 */
  137.     -1,    /*  7: Teletext */
  138.     2,    /*  8: 640x256 */
  139.     4,    /*  9: 320x256 */
  140.     8,    /* 10: 160x256 */
  141.     2,    /* 11: 640x250 */
  142.     4,    /* 12: 640x256 */
  143.     8,    /* 13: 320x256 */
  144.     4,    /* 14: 640x250 */
  145.     8,    /* 15: 640x256 */
  146.     4,    /* 16: 1056x250 */
  147.     4,    /* 17: 1056x256 */
  148.     1,    /* 18: 640x512 multisync-monitor */
  149.     2,    /* 19: 640x512 multisync-monitor */
  150.     4,    /* 20: 640x512 multisync-monitor */
  151.     8,    /* 21: 640x512 multisync-monitor */
  152.     -1,    /* 22: ? */
  153.     1,    /* 23: 1152x896 61.2Hz-hires-montor */
  154.     8,    /* 24: 1056x256 */
  155.     1,    /* 25: 640x480 multisync-or-60Hz-VGA-monitor */
  156.     2,    /* 26: 640x480 multisync-or-60Hz-VGA-monitor */
  157.     4,    /* 27: 640x480 multisync-or-60Hz-VGA-monitor */
  158.     8,    /* 28: 640x480 multisync-or-60Hz-VGA-monitor */
  159.     };
  160.  
  161. #define    N_MODES    29
  162.  
  163. /* Return highest resolution mode for given bits per pixel. */
  164.  
  165. static int mode_of_bpp [] = { -1,23,-1,-1,17,-1,-1,-1,24 };
  166. /*...e*/
  167. /*...squick tables:0:*/
  168. /* These are to account for the reverse ordering of pixels in a scan line. */
  169.  
  170. static byte nibble_swap [0x100] =
  171.     {
  172.     0x00,0x10,0x20,0x30,0x40,0x50,0x60,0x70,
  173.     0x80,0x90,0xa0,0xb0,0xc0,0xd0,0xe0,0xf0,
  174.     0x01,0x11,0x21,0x31,0x41,0x51,0x61,0x71,
  175.     0x81,0x91,0xa1,0xb1,0xc1,0xd1,0xe1,0xf1,
  176.     0x02,0x12,0x22,0x32,0x42,0x52,0x62,0x72,
  177.     0x82,0x92,0xa2,0xb2,0xc2,0xd2,0xe2,0xf2,
  178.     0x03,0x13,0x23,0x33,0x43,0x53,0x63,0x73,
  179.     0x83,0x93,0xa3,0xb3,0xc3,0xd3,0xe3,0xf3,
  180.     0x04,0x14,0x24,0x34,0x44,0x54,0x64,0x74,
  181.     0x84,0x94,0xa4,0xb4,0xc4,0xd4,0xe4,0xf4,
  182.     0x05,0x15,0x25,0x35,0x45,0x55,0x65,0x75,
  183.     0x85,0x95,0xa5,0xb5,0xc5,0xd5,0xe5,0xf5,
  184.     0x06,0x16,0x26,0x36,0x46,0x56,0x66,0x76,
  185.     0x86,0x96,0xa6,0xb6,0xc6,0xd6,0xe6,0xf6,
  186.     0x07,0x17,0x27,0x37,0x47,0x57,0x67,0x77,
  187.     0x87,0x97,0xa7,0xb7,0xc7,0xd7,0xe7,0xf7,
  188.     0x08,0x18,0x28,0x38,0x48,0x58,0x68,0x78,
  189.     0x88,0x98,0xa8,0xb8,0xc8,0xd8,0xe8,0xf8,
  190.     0x09,0x19,0x29,0x39,0x49,0x59,0x69,0x79,
  191.     0x89,0x99,0xa9,0xb9,0xc9,0xd9,0xe9,0xf9,
  192.     0x0a,0x1a,0x2a,0x3a,0x4a,0x5a,0x6a,0x7a,
  193.     0x8a,0x9a,0xaa,0xba,0xca,0xda,0xea,0xfa,
  194.     0x0b,0x1b,0x2b,0x3b,0x4b,0x5b,0x6b,0x7b,
  195.     0x8b,0x9b,0xab,0xbb,0xcb,0xdb,0xeb,0xfb,
  196.     0x0c,0x1c,0x2c,0x3c,0x4c,0x5c,0x6c,0x7c,
  197.     0x8c,0x9c,0xac,0xbc,0xcc,0xdc,0xec,0xfc,
  198.     0x0d,0x1d,0x2d,0x3d,0x4d,0x5d,0x6d,0x7d,
  199.     0x8d,0x9d,0xad,0xbd,0xcd,0xdd,0xed,0xfd,
  200.     0x0e,0x1e,0x2e,0x3e,0x4e,0x5e,0x6e,0x7e,
  201.     0x8e,0x9e,0xae,0xbe,0xce,0xde,0xee,0xfe,
  202.     0x0f,0x1f,0x2f,0x3f,0x4f,0x5f,0x6f,0x7f,
  203.     0x8f,0x9f,0xaf,0xbf,0xcf,0xdf,0xef,0xff,
  204.     };
  205. static byte bit_swap [0x100] =
  206.     {
  207.     0x00,0x80,0x40,0xc0,0x20,0xa0,0x60,0xe0,
  208.     0x10,0x90,0x50,0xd0,0x30,0xb0,0x70,0xf0,
  209.     0x08,0x88,0x48,0xc8,0x28,0xa8,0x68,0xe8,
  210.     0x18,0x98,0x58,0xd8,0x38,0xb8,0x78,0xf8,
  211.     0x04,0x84,0x44,0xc4,0x24,0xa4,0x64,0xe4,
  212.     0x14,0x94,0x54,0xd4,0x34,0xb4,0x74,0xf4,
  213.     0x0c,0x8c,0x4c,0xcc,0x2c,0xac,0x6c,0xec,
  214.     0x1c,0x9c,0x5c,0xdc,0x3c,0xbc,0x7c,0xfc,
  215.     0x02,0x82,0x42,0xc2,0x22,0xa2,0x62,0xe2,
  216.     0x12,0x92,0x52,0xd2,0x32,0xb2,0x72,0xf2,
  217.     0x0a,0x8a,0x4a,0xca,0x2a,0xaa,0x6a,0xea,
  218.     0x1a,0x9a,0x5a,0xda,0x3a,0xba,0x7a,0xfa,
  219.     0x06,0x86,0x46,0xc6,0x26,0xa6,0x66,0xe6,
  220.     0x16,0x96,0x56,0xd6,0x36,0xb6,0x76,0xf6,
  221.     0x0e,0x8e,0x4e,0xce,0x2e,0xae,0x6e,0xee,
  222.     0x1e,0x9e,0x5e,0xde,0x3e,0xbe,0x7e,0xfe,
  223.     0x01,0x81,0x41,0xc1,0x21,0xa1,0x61,0xe1,
  224.     0x11,0x91,0x51,0xd1,0x31,0xb1,0x71,0xf1,
  225.     0x09,0x89,0x49,0xc9,0x29,0xa9,0x69,0xe9,
  226.     0x19,0x99,0x59,0xd9,0x39,0xb9,0x79,0xf9,
  227.     0x05,0x85,0x45,0xc5,0x25,0xa5,0x65,0xe5,
  228.     0x15,0x95,0x55,0xd5,0x35,0xb5,0x75,0xf5,
  229.     0x0d,0x8d,0x4d,0xcd,0x2d,0xad,0x6d,0xed,
  230.     0x1d,0x9d,0x5d,0xdd,0x3d,0xbd,0x7d,0xfd,
  231.     0x03,0x83,0x43,0xc3,0x23,0xa3,0x63,0xe3,
  232.     0x13,0x93,0x53,0xd3,0x33,0xb3,0x73,0xf3,
  233.     0x0b,0x8b,0x4b,0xcb,0x2b,0xab,0x6b,0xeb,
  234.     0x1b,0x9b,0x5b,0xdb,0x3b,0xbb,0x7b,0xfb,
  235.     0x07,0x87,0x47,0xc7,0x27,0xa7,0x67,0xe7,
  236.     0x17,0x97,0x57,0xd7,0x37,0xb7,0x77,0xf7,
  237.     0x0f,0x8f,0x4f,0xcf,0x2f,0xaf,0x6f,0xef,
  238.     0x1f,0x9f,0x5f,0xdf,0x3f,0xbf,0x7f,0xff,
  239.     };
  240.  
  241. static byte pair_swap [0x10] =
  242.     {
  243.     0x00,0x10,0x20,0x30,0x01,0x11,0x21,0x31,
  244.     0x02,0x12,0x22,0x32,0x03,0x13,0x23,0x33,
  245.     };
  246. /*...e*/
  247.  
  248. /*...sspr_qft:0:*/
  249. GBM_ERR spr_qft(GBMFT *gbmft)
  250.     {
  251.     *gbmft = spr_gbmft;
  252.     return ( GBM_ERR_OK );
  253.     }
  254. /*...e*/
  255. /*...sspr_rhdr:0:*/
  256. GBM_ERR spr_rhdr(char *fn, int fd, GBM *gbm, char *opt)
  257.     {
  258.     SPR_PRIV *spr_priv = (SPR_PRIV *) gbm -> priv;
  259.     char *index;
  260.     int i;
  261.     dword num_sprites, offset_sprite, pos_sprite;
  262.     dword dword_w, scans_h, first_bit, last_bit, bits_per_line;
  263.     dword offset_image, offset_mask, mode;
  264.  
  265.     fn=fn; /* Suppress 'unref arg' compiler warnings */
  266.  
  267.     lseek(fd, 0L, SEEK_SET);
  268.  
  269.     if ( (index = find_word_prefix(opt, "index=")) != NULL )
  270.         sscanf(index + 6, "%d", &i);
  271.     else
  272.         i = 0;
  273.  
  274.     read_dword(fd, &num_sprites);
  275.     if ( i >= num_sprites )
  276.         return ( GBM_ERR_SPR_OFFSET );
  277.     read_dword(fd, &offset_sprite);
  278.     pos_sprite = lseek(fd, offset_sprite - 4L, SEEK_SET);
  279.  
  280.     while ( i-- > 0 )
  281.         {
  282.         read_dword(fd, &offset_sprite);
  283.         pos_sprite = lseek(fd, pos_sprite + offset_sprite, SEEK_SET);
  284.         }
  285.  
  286.     lseek(fd, 16, SEEK_CUR);    /* Skip 4 byte next-ptr + 12 byte name */
  287.     read_dword(fd, &dword_w);    /* Width in dwords - 1 */
  288.     read_dword(fd, &scans_h);    /* Scan lines high - 1 */
  289.     read_dword(fd, &first_bit);    /* First bit used (left end of row) */
  290.     read_dword(fd, &last_bit);    /* Last bit used (right end of row) */
  291.     read_dword(fd, &offset_image);    /* Offset of image data */
  292.     read_dword(fd, &offset_mask);    /* Offset of mask plane or above if none */
  293.     read_dword(fd, &mode);        /* Mode sprite defined in */
  294.  
  295.     if ( first_bit & 7 )
  296.         return ( GBM_ERR_SPR_FIRST );
  297.     if ( mode >= N_MODES )
  298.         return ( GBM_ERR_SPR_MODE );
  299.     if ( (gbm -> bpp = spr_priv -> actual_bpp = bpp_of_mode [mode]) == -1 )
  300.         return ( GBM_ERR_SPR_MODE );
  301.  
  302.     gbm -> h = (int) (scans_h+1);
  303.     if ( gbm -> h < 0 || gbm -> h > 10000 )
  304.         return ( GBM_ERR_BAD_SIZE );
  305.  
  306.     if ( gbm -> bpp == 2 )
  307.         gbm -> bpp = 4;
  308.  
  309.     bits_per_line = ((dword_w+1) * 32) - first_bit - (32 - (last_bit+1));
  310.     gbm -> w = (int) (bits_per_line / spr_priv -> actual_bpp);
  311.     if ( gbm -> w < 0 || gbm -> w > 10000 )
  312.         return ( GBM_ERR_BAD_SIZE );
  313.  
  314.     spr_priv -> pos_palette    = tell(fd);
  315.     spr_priv -> pos_image      = (long) pos_sprite + offset_image;
  316.     spr_priv -> pos_mask       = (long) pos_sprite + offset_mask;
  317.     spr_priv -> bytes_per_line = (dword_w + 1) * 4;
  318.     spr_priv -> first_bit      = first_bit;
  319.     spr_priv -> last_bit       = last_bit;
  320.  
  321.     return ( GBM_ERR_OK );
  322.     }
  323. /*...e*/
  324. /*...sspr_rpal:0:*/
  325. /*...sread_pal:0:*/
  326. /* Palette entry is 2 dwords, which are same if no flashing */
  327. /* We will simply use first dword in each case */
  328.  
  329. static BOOLEAN read_pal(int fd, GBMRGB *gbmrgb)
  330.     {
  331.     byte pal [8];
  332.     if ( read(fd, pal, 8) != 8 )
  333.         return ( FALSE );
  334.     gbmrgb -> r = pal [1];
  335.     gbmrgb -> g = pal [2];
  336.     gbmrgb -> b = pal [3];
  337.     return ( TRUE );
  338.     }
  339. /*...e*/
  340.  
  341. /*...sgbmrgb_1bpp:0:*/
  342. /*
  343. I do not expect the palette to be missing from a file defined in a mode with 2
  344. colours because the Wimp uses 16 colours, and I am led to beleive it is the
  345. only thing that saves files without the palette. However, if I am wrong...
  346. */
  347.  
  348. static GBMRGB gbmrgb_1bpp [2] =
  349.     {
  350.     {0xff,0xff,0xff},    /* 0=White */
  351.     {0x00,0x00,0x00},    /* 1=black */
  352.     };
  353. /*...e*/
  354. /*...sgbmrgb_2bpp:0:*/
  355. /*
  356. I do not expect the palette to be missing from a file defined in a mode with 4
  357. colours because the Wimp uses 16 colours, and I am led to beleive it is the
  358. only thing that saves files without the palette. However, if I am wrong...
  359. */
  360.  
  361. static GBMRGB gbmrgb_2bpp [4] =
  362.     {
  363.     {0xff,0xff,0xff},
  364.     {0xaa,0xaa,0xaa},
  365.     {0x55,0x55,0x55},
  366.     {0x00,0x00,0x00},
  367.     };
  368. /*...e*/
  369. /*...sgbmrgb_4bpp:0:*/
  370. /*
  371. This is the default Wimp defined 16 colour palette.
  372. The exact r,g,b values are not known so some nice bold examples of each,
  373. according to their descriptions in the RiscOS books have been found manually.
  374. */
  375.  
  376. static GBMRGB gbmrgb_4bpp [16] =
  377.     {
  378.     {0xff,0xff,0xff},    /* 0=white */
  379.     {0xdb,0xdb,0xdb},    /* 1=grey */
  380.     {0xb6,0xb6,0xb6},    /* 2=grey */
  381.     {0x92,0x92,0x92},    /* 3=grey */
  382.     {0x6d,0x6d,0x6d},    /* 4=grey */
  383.     {0x49,0x49,0x49},    /* 5=grey */
  384.     {0x24,0x24,0x24},    /* 6=grey */
  385.     {0x00,0x00,0x00},    /* 7=black */
  386.     {0x00,0x00,0xff},    /* 8=dark blue */
  387.     {0xff,0xff,0x00},    /* 9=yellow */
  388.     {0x00,0xff,0x00},    /* a=green */
  389.     {0xff,0x00,0x00},    /* b=red */
  390.     {0xff,0xd8,0xd8},    /* c=cream */
  391.     {0x40,0x80,0x40},    /* d=army green */
  392.     {0xff,0x9c,0x00},    /* e=orange */
  393.     {0x00,0xb9,0xff},    /* f=light blue */
  394.     };
  395. /*...e*/
  396. /*...sexpand_0x10:0:*/
  397. /*
  398. The Archimedes does not have 0x100 palette registers, it has 0x10 VIDC registers.
  399. Given an 8 bit pixel :-
  400.     Bits 3-0 are bits 3-0 of palette index
  401.     Bit 4 overrides red bit 7
  402.     Bit 5 overrides green bit 6
  403.     Bit 6 overrides green bit 7
  404.     Bit 7 overrides blue bit 7
  405. So we duplicate the 0x10 values we have read, and make the others from them.
  406. */
  407.  
  408. static void expand_0x10(GBMRGB *gbmrgb)
  409.     {
  410.     int i, bank;
  411.  
  412.     for ( bank = 0x10; bank < 0x100; bank += 0x10 )
  413.         {
  414.         byte override_r = ((bank & 0x10) << 3);
  415.         byte override_g = ((bank & 0x60) << 1);
  416.         byte override_b =  (bank & 0x80)      ;
  417.         for ( i = 0; i < 0x10; i++ )
  418.             {
  419.             gbmrgb [bank + i].r = ((gbmrgb [i].r & 0x7f) | override_r);
  420.             gbmrgb [bank + i].g = ((gbmrgb [i].g & 0x3f) | override_g);
  421.             gbmrgb [bank + i].b = ((gbmrgb [i].b & 0x7f) | override_b);
  422.             }
  423.         }
  424.     }
  425. /*...e*/
  426. /*...sexpand_0x40:0:*/
  427. /*
  428. The Archimedes does not have 0x100 palette registers, it has 0x10.
  429. Planning for the future, files can be written with 0x40 palette entries.
  430. Given an 8 bit pixel :-
  431.     Bits 5-0 are bits 5-0 of palette index
  432.     Bit 6 overrides green bit 7
  433.     Bit 7 overrides blue bit 7
  434. So we duplicate the 0x40 values we have read, and make the others from them.
  435. Now, although we have seen files with 0x40 entries, when you take the first
  436. 0x10, and perform expand_0x10 on them, the result is the same as this routine.
  437. Clearly Acorn are looking forward to a day when the VIDC chip has 0x40
  438. registers.
  439. */
  440.  
  441. static void expand_0x40(GBMRGB *gbmrgb)
  442.     {
  443.     int i, bank;
  444.  
  445.     for ( bank = 0; bank < 0x100; bank += 0x40 )
  446.         {
  447.         byte override_g = ((bank & 0x40) << 1);
  448.         byte override_b =  (bank & 0x80)      ;
  449.         for ( i = 0; i < 0x40; i++ )
  450.             {
  451.             gbmrgb [bank + i].r =   gbmrgb [i].r;
  452.             gbmrgb [bank + i].g = ((gbmrgb [i].g & 0x7f) | override_g);
  453.             gbmrgb [bank + i].b = ((gbmrgb [i].b & 0x7f) | override_b);
  454.             }
  455.         }
  456.     }
  457. /*...e*/
  458.  
  459. GBM_ERR spr_rpal(int fd, GBM *gbm, GBMRGB *gbmrgb)
  460.     {
  461.     SPR_PRIV *spr_priv = (SPR_PRIV *) gbm -> priv;
  462.     int npal = (spr_priv -> pos_image - spr_priv -> pos_palette) / 8;
  463.  
  464.     if ( npal == 0 )
  465. /*...sno palette in file\44\ use the default Wimp one:16:*/
  466. switch ( spr_priv -> actual_bpp )
  467.     {
  468.     case 1: memcpy(gbmrgb, gbmrgb_1bpp, sizeof(gbmrgb_1bpp)); break;
  469.     case 2: memcpy(gbmrgb, gbmrgb_2bpp, sizeof(gbmrgb_2bpp)); break;
  470.     case 4: memcpy(gbmrgb, gbmrgb_4bpp, sizeof(gbmrgb_4bpp)); break;
  471.     case 8:
  472. /*...sdefault palette:32:*/
  473. {
  474. int i;
  475. for ( i = 0; i < 0x10; i++ )
  476.     {
  477.     byte tint = ((i & 0x03) << 4);
  478.     gbmrgb [i].r = tint + ((i & 0x04) << 4);
  479.     gbmrgb [i].g = tint;
  480.     gbmrgb [i].b = tint + ((i & 0x08) << 3);
  481.     }
  482. expand_0x10(gbmrgb);
  483. }
  484. /*...e*/
  485.         break;
  486.     }
  487.  
  488. /*...e*/
  489.     else
  490. /*...sread palette from disk:16:*/
  491. {
  492. int i;
  493. lseek(fd, spr_priv -> pos_palette, SEEK_SET);
  494. for ( i = 0; i < npal; i++ )
  495.     if ( !read_pal(fd, gbmrgb + i) )
  496.         return ( GBM_ERR_READ );
  497.  
  498. if ( gbm -> bpp == 8 )
  499.     /* Handle getting too few palette entries */
  500.     {
  501.     if ( npal == 0x40 )
  502.         expand_0x40(gbmrgb);
  503.     else if ( npal == 0x10 )
  504.         expand_0x10(gbmrgb);
  505.     else
  506.         return ( GBM_ERR_SPR_PAL8 );
  507.     }
  508. }
  509. /*...e*/
  510.  
  511.     return ( GBM_ERR_OK );
  512.     }
  513. /*...e*/
  514. /*...sspr_rdata:0:*/
  515. GBM_ERR spr_rdata(int fd, GBM *gbm, byte *data)
  516.     {
  517.     int stride = ((gbm -> bpp * gbm -> w + 31) / 32) * 4;
  518.     SPR_PRIV *spr_priv = (SPR_PRIV *) gbm -> priv;
  519.     int scan_stride = spr_priv -> bytes_per_line;
  520.     int scan_first = ((spr_priv -> first_bit) >> 3);
  521.     int scan_bytes, i, j;
  522.     byte *datal = data + (gbm -> h - 1) * stride;
  523.  
  524.     lseek(fd, spr_priv -> pos_image, SEEK_SET);
  525.  
  526.     switch ( spr_priv -> actual_bpp )
  527.         {
  528. /*...s8 \45\ read mapped pixels:16:*/
  529. case 8:
  530.     scan_bytes = gbm -> w;
  531.     for ( j = 0; j < gbm -> h; j++, datal -= stride )
  532.         {
  533.         lseek(fd, spr_priv -> pos_image + j * scan_stride + scan_first, SEEK_SET);
  534.         if ( read(fd, datal, scan_bytes) != scan_bytes )
  535.             return ( GBM_ERR_READ );
  536.         }
  537.     break;
  538. /*...e*/
  539. /*...s4 \45\ read pixels\44\ nibble swapping:16:*/
  540. case 4:
  541.     scan_bytes = ((gbm -> w + 1) >> 1);
  542.     for ( j = 0; j < gbm -> h; j++, datal -= stride )
  543.         {
  544.         lseek(fd, spr_priv -> pos_image + j * scan_stride + scan_first, SEEK_SET);
  545.         if ( read(fd, datal, scan_bytes) != scan_bytes )
  546.             return ( GBM_ERR_READ );
  547.         for ( i = 0; i < scan_bytes; i++ )
  548.             datal [i] = nibble_swap [datal [i]];
  549.         }
  550.     break;
  551. /*...e*/
  552. /*...s2 \45\ read pixels\44\ bit\45\pair reversing and expanding:16:*/
  553. /*
  554. Data is coming in a 2bpp, but we don't actually support this.
  555. So we will expand the data to 4bpp as we read it.
  556. We will do this inline, by reading into the second half.
  557. */
  558.  
  559. case 2:
  560.     scan_bytes = ((gbm -> w + 3) >> 2);
  561.     for ( j = 0; j < gbm -> h; j++, datal -= stride )
  562.         {
  563.         lseek(fd, spr_priv -> pos_image + j * scan_stride + scan_first, SEEK_SET);
  564.         if ( read(fd, datal + scan_bytes, scan_bytes) != scan_bytes )
  565.             return ( GBM_ERR_READ );
  566.         for ( i = 0; i < scan_bytes; i++ )
  567.             {
  568.             datal [i * 2    ] = pair_swap [datal [scan_bytes + i] & 0x0f];
  569.             datal [i * 2 + 1] = pair_swap [datal [scan_bytes + i] >> 4  ];
  570.             }
  571.         }
  572.     break;
  573. /*...e*/
  574. /*...s1 \45\ read pixels\44\ bit reversing:16:*/
  575. case 1:
  576.     scan_bytes = ((gbm -> w + 7) >> 3);
  577.     for ( j = 0; j < gbm -> h; j++, datal -= stride )
  578.         {
  579.         lseek(fd, spr_priv -> pos_image + j * scan_stride + scan_first, SEEK_SET);
  580.         if ( read(fd, datal, scan_bytes) != scan_bytes )
  581.             return ( GBM_ERR_READ );
  582.         for ( i = 0; i < scan_bytes; i++ )
  583.             datal [i] = bit_swap [datal [i]];
  584.         }
  585.     break;
  586. /*...e*/
  587.         }
  588.  
  589.     return ( GBM_ERR_OK );
  590.     }
  591. /*...e*/
  592. /*...sspr_w:0:*/
  593. /*
  594. We have a problem here for 256 colour modes.
  595. The 256 colours we are asked to write can be any colours and unrelated.
  596. There are only 16 VIDC palette registers, and the other 4 bits in an 8 bit
  597. byte override specific palette entry bits.
  598. We will ignore all but the top 4 bits of each colour component. ie: just 7-4.
  599. Therefore we will write a specifically fixed palette :-
  600.     Bits 1 to 0 will be bits 5 and 4 for all 3 guns.
  601.     Bit 2 will be red bit 6
  602.     Bit 3 will be blue bit 6
  603.     Bit 4 will be red bit 7
  604.     Bit 5 will be green bit 6
  605.     Bit 6 will be green bit 7
  606.     Bit 7 will be blue bit 7
  607. This is the default palette used by RiscOS.
  608. We will map all incoming palette entrys first, to give a quick lookup table.
  609. */
  610.  
  611. /*...swrite_pal:0:*/
  612. static BOOLEAN write_pal(int fd, GBMRGB gbmrgb)
  613.     {
  614.     byte pal [8];
  615.     int j;
  616.     pal [0] = pal [4] = 0x00;
  617.     pal [1] = pal [5] = (byte) (gbmrgb.r & 0xf0);
  618.     pal [2] = pal [6] = (byte) (gbmrgb.g & 0xf0); 
  619.     pal [3] = pal [7] = (byte) (gbmrgb.b & 0xf0); 
  620.     for ( j = 0; j < 8; j++ )
  621.         pal [j] += (pal [j] >> 4);
  622.     return ( write(fd, pal, 8) == 8 );
  623.     }
  624. /*...e*/
  625.  
  626. GBM_ERR spr_w(char *fn, int fd, GBM *gbm, GBMRGB *gbmrgb, byte *data, char *opt)
  627.     {
  628.     int stride = ((gbm -> bpp * gbm -> w + 31) / 32) * 4;
  629.     int i, j, npal = ( 1 << gbm -> bpp );
  630.     dword dword_w, last_bit, offset_image, mode;
  631.     char name [12];
  632.     byte qpal [0x100], *buf;
  633.     BOOLEAN ok;
  634.  
  635.     opt=opt; /* Suppress 'unref arg' warning */
  636.  
  637.     if ( gbm -> bpp == 24 )
  638.         return ( GBM_ERR_NOT_SUPP );
  639.  
  640.     if ( npal == 0x100 )
  641.         npal = 0x10;
  642.  
  643.     ok  = write_dword(fd, 1);        /* Number of sprites */
  644.     ok &= write_dword(fd, 12 + 4);        /* Offset to sprite */
  645.     ok &= write_dword(fd, (12 + 44 + npal * 8 + stride * gbm -> h) + 4); 
  646.                         /* Offset to free word (beyond sprites) */
  647.     ok &= write_dword(fd, 44 + npal * 8 + stride * gbm -> h);
  648.  
  649. /*...sbuild a name:8:*/
  650. /*
  651. We will use the supplied filename to build the name field.
  652. We will ignore the path part (if any present).
  653. Also we will chop of the file extension of .spr if present.
  654. (This change was by customer request).
  655. Also, map to lower case to keep RiscOS programs happy.
  656. This isn't documented, but appears to be the case.
  657. */
  658.  
  659. {
  660. char *p = fn, *q;
  661. if ( (q = strrchr(p, '\\')) != NULL )
  662.     p = q + 1;
  663. if ( (q = strrchr(p, '/')) != NULL )
  664.     p = q + 1;
  665. memset(name, 0, 12);
  666. strncpy(name, p, 11);
  667. if ( (q = strrchr(name, '.')) != NULL && same(q + 1, "spr", 4) )
  668.     memset(q, '\0', 4);
  669. for ( p = name; (p - name) < 12 && *p != '\0'; p++ )
  670.     *p = tolower(*p);
  671. }
  672. /*...e*/
  673.     ok &= ( write(fd, name, 12) == 12 );
  674.  
  675.     dword_w = ((gbm -> w * gbm -> bpp + 31) / 32) - 1;
  676.     ok &= write_dword(fd, dword_w);        /* Width in dwords - 1 */
  677.     ok &= write_dword(fd, gbm -> h - 1);    /* Scan lines high - 1 */
  678.     ok &= write_dword(fd, 0);        /* First bit used (left end of row) */
  679.     last_bit = ((gbm -> w * gbm -> bpp - 1) & 0x1f);
  680.     ok &= write_dword(fd, last_bit);    /* Last bit used (right end of row) */
  681.     offset_image = ( 44 + npal * 8 );
  682.     ok &= write_dword(fd, offset_image);    /* Offset of image data */
  683.     ok &= write_dword(fd, offset_image);    /* Offset of mask plane or above if none */
  684.     mode = mode_of_bpp [gbm -> bpp];
  685.     ok &= write_dword(fd, mode);        /* Mode sprite defined in */
  686.  
  687.     if ( !ok )
  688.         return ( GBM_ERR_WRITE );
  689.  
  690.     /* Write palette */
  691.  
  692.     switch ( gbm -> bpp )
  693.         {
  694. /*...s8 \45\ write RiscOS default palette\44\ and work out mapping:16:*/
  695. case 8:
  696.  
  697.     /* Write the fixed RiscOS default palette */
  698.     for ( i = 0; i < 0x10; i++ )
  699.         {
  700.         GBMRGB gbmrgb_def;
  701.         byte tint = ((i & 0x03) << 4);
  702.         gbmrgb_def.r = tint + ((i & 0x04) << 4);
  703.         gbmrgb_def.g = tint;
  704.         gbmrgb_def.b = tint + ((i & 0x08) << 3);
  705.         if ( !write_pal(fd, gbmrgb_def) )
  706.             return ( GBM_ERR_WRITE );
  707.         }
  708.  
  709.     /* Determine palette mapping */
  710.     for ( i = 0; i < 0x100; i++ )
  711.         {
  712.         byte r = gbmrgb [i].r;
  713.         byte g = gbmrgb [i].g;
  714.         byte b = gbmrgb [i].b;
  715.         byte k32 = ((((r & 0x30) + (g & 0x30) + (b & 0x30)) / 3) & 0x30);
  716.         qpal [i] =  (b & 0x80)       +
  717.                ((g & 0xc0) >> 1) +
  718.                ((r & 0x80) >> 3) +
  719.                ((b & 0x40) >> 3) +
  720.                ((r & 0x40) >> 4) +
  721.                (k32 >> 4);
  722.         }
  723.     break;
  724. /*...e*/
  725. /*...s4\44\1 \45\ write 16 or 2 entry palette:16:*/
  726. case 4:
  727. case 1:
  728.     /* Write the palette */
  729.     for ( i = 0; i < (1 << gbm -> bpp); i++ )
  730.         if ( !write_pal(fd, gbmrgb [i]) )
  731.             return ( GBM_ERR_WRITE );
  732.     break;
  733. /*...e*/
  734.         }
  735.  
  736.     /* Write data */
  737.  
  738.     if ( (buf = malloc(stride)) == NULL )
  739.         return ( GBM_ERR_MEM );
  740.     memset(buf, 0, stride);
  741.  
  742.     data += (gbm -> h - 1) * stride; /* Start at the top */
  743.     switch ( gbm -> bpp )
  744.         {
  745. /*...s8 \45\ write mapped pixels\44\ funny order:16:*/
  746. case 8:
  747.     for ( j = 0; j < gbm -> h; j++, data -= stride )
  748.         {
  749.         for ( i = 0; i < stride; i++ )
  750.             buf [i] = qpal [data [i]];
  751.         if ( write(fd, buf, stride) != stride )
  752.             {
  753.             free(buf);
  754.             return ( GBM_ERR_WRITE );
  755.             }
  756.         }
  757.     break;
  758. /*...e*/
  759. /*...s4 \45\ write pixels\44\ funny order:16:*/
  760. case 4:
  761.     for ( j = 0; j < gbm -> h; j++, data -= stride )
  762.         {
  763.         for ( i = 0; i < stride; i++ )
  764.             buf [i] = nibble_swap [data [i]];
  765.         if ( write(fd, buf, stride) != stride )
  766.             {
  767.             free(buf);
  768.             return ( GBM_ERR_WRITE );
  769.             }
  770.         }
  771.     break;
  772. /*...e*/
  773. /*...s1 \45\ write pixels\44\ funny order:16:*/
  774. case 1:
  775.     for ( j = 0; j < gbm -> h; j++, data -= stride )
  776.         {
  777.         for ( i = 0; i < stride; i++ )
  778.             buf [i] = bit_swap [data [i]];
  779.         if ( write(fd, buf, stride) != stride )
  780.             {
  781.             free(buf);
  782.             return ( GBM_ERR_WRITE );
  783.             }
  784.         }
  785.     break;
  786. /*...e*/
  787.         }
  788.  
  789.     free(buf);
  790.  
  791.     return ( GBM_ERR_OK );
  792.     }
  793. /*...e*/
  794. /*...sspr_err:0:*/
  795. char *spr_err(GBM_ERR rc)
  796.     {
  797.     switch ( (int) rc )
  798.         {
  799.         case GBM_ERR_SPR_FIRST:
  800.             return ( "sprite has first bit that is not a multiple of 8" );
  801.         case GBM_ERR_SPR_MODE:
  802.             return ( "sprite defined in unknown mode" );
  803.         case GBM_ERR_SPR_OFFSET:
  804.             return ( "less sprites in file than index requested" );
  805.         case GBM_ERR_SPR_PAL8:
  806.             return ( "8 bit file does not have 0, 16 or 64 palette entries in it" );
  807.         }
  808.     return ( NULL );
  809.     }
  810. /*...e*/
  811.