Plot any sprite, in any screen mode

Prerequestite libraries: OSlib

spritefile.h

/* By Johnathan Coxhead - released onto the net 23/7/96 */
   #ifndef spritefile_H
   #define spritefile_H

   #ifndef types_H
   #include "types.h"
   #endif

   #ifndef os_H
   #include "os.h"
   #endif

   #ifndef osspriteop_H
   #include "osspriteop.h"
   #endif

   #define spritefile_NARROW_ENTRIES 0x1u

   /*************************
    * Function declarations *
    *************************/

   #ifdef __cplusplus
      extern "C" {
   #endif

   /* ------------------------------------------------------------------------
    * Function:      spritefile_render()
    */

   extern void spritefile_render (bits flags,
	 osspriteop_header const *sprite,
	 int size,
	 os_trfm const *trfm,
	 os_box const *clip);

   /* ------------------------------------------------------------------------
    * Function:      spritefile_bbox()
    */

   extern void spritefile_bbox (bits flags,
	 osspriteop_header const *sprite,
	 int size,
	 os_trfm const *trfm,
	 os_box *bbox);

   /* ------------------------------------------------------------------------
    * Function:      spritefile_declare_fonts()
    */

   extern void spritefile_declare_fonts (bits flags,
	 osspriteop_header const *sprite,
	 int size);

   #ifdef __cplusplus
      }
   #endif

   #endif

spritefile.c

/* By Johnathan Coxhead - released onto the net 23/7/96 */
   #include "colourtrans.h"
   #include "draw.h"
   #include "os.h"
   #include "osspriteop.h"
   #include "wimp.h"

   #include "x.h"
   #include "spritefile.h"
   #include "trfm.h"

   x_LOCAL_ERROR (Bad_Mode, 1, "Bad mode")

   void spritefile_render (bits flags, osspriteop_header const *sprite,
	 int size, os_trfm const *trfm, os_box const *clip)

   {  osspriteop_trans_tab *table;
      bool narrow_entries = (flags & spritefile_NARROW_ENTRIES) != NONE;
      os_PALETTE (20) palette;
      int log2_bpp;

      if ((sprite->image - sizeof (osspriteop_header))/sizeof (os_colour_pair)
	    == 0)
      {  if ((os_read_mode_variable (sprite->mode, os_MODEVAR_LOG2_BPP,
	       &log2_bpp) & _C) != NONE)
	    x_THROW (Bad_Mode);

	 if (log2_bpp < 3)
	    wimp_read_true_palette ((os_palette *) &palette);

	 switch (log2_bpp)
	 {  case 0:
	       palette.entries [1] = palette.entries [7];
	    break;

	    case 1:
	       palette.entries [1] = palette.entries [2];
	       palette.entries [2] = palette.entries [4];
	       palette.entries [3] = palette.entries [7];
	    break;
	 }

	 colourtrans_generate_table
	 (  sprite->mode,
	    log2_bpp < 3?
		  (os_palette *) &palette:
		  colourtrans_CURRENT_PALETTE,
	    colourtrans_CURRENT_MODE,
	    colourtrans_CURRENT_PALETTE,
	    table = x_ALLOC
	    (  colourtrans_generate_table
	       (  sprite->mode,
		  log2_bpp < 3?
			(os_palette *) &palette:
			colourtrans_CURRENT_PALETTE,
		  colourtrans_CURRENT_MODE,
		  colourtrans_CURRENT_PALETTE,
		  NULL,
		  colourtrans_GIVEN_SPRITE |
			(narrow_entries? NONE: colourtrans_RETURN_WIDE_ENTRIES),
		  SKIP,
		  SKIP
	       )
	    ),
	    colourtrans_GIVEN_SPRITE |
		  (narrow_entries? NONE: colourtrans_RETURN_WIDE_ENTRIES),
	    SKIP,
	    SKIP
	 );
      }
      else
	 colourtrans_generate_table_for_sprite
	 (  osspriteop_UNSPECIFIED,
	    (osspriteop_id) sprite,
	    colourtrans_CURRENT_MODE,
	    colourtrans_CURRENT_PALETTE,
	    table = x_ALLOC
	    (  colourtrans_generate_table_for_sprite
	       (  osspriteop_UNSPECIFIED,
		  (osspriteop_id) sprite,
		  colourtrans_CURRENT_MODE,
		  colourtrans_CURRENT_PALETTE,
		  NULL,
		  colourtrans_GIVEN_SPRITE |
			(narrow_entries? NONE: colourtrans_RETURN_WIDE_ENTRIES),
		  SKIP,
		  SKIP
	       )
	    ),
	    colourtrans_GIVEN_SPRITE |
		  (narrow_entries? NONE: colourtrans_RETURN_WIDE_ENTRIES),
	    SKIP,
	    SKIP
	 );

      osspriteop_put_sprite_trfm (osspriteop_PTR, osspriteop_UNSPECIFIED,
	    (osspriteop_id) sprite, NONE, NULL,
	    os_ACTION_USE_MASK |
		 (narrow_entries? NONE: osspriteop_GIVEN_WIDE_ENTRIES),
	    trfm, table);

      x_FREE (table, 0);
   }

   void spritefile_bbox (bits flags, osspriteop_header const *sprite,
	 int size, os_trfm const *trfm, os_box *bbox)

   {  os_box box;
      os_mode mode;
      int width, height, xeig, yeig;

      /*Get bbox of sprite into box.*/
      osspriteop_read_sprite_size (osspriteop_PTR, osspriteop_UNSPECIFIED,
	    (osspriteop_id) sprite, &width, &height, NULL, &mode);

      if ((os_read_mode_variable (mode, os_MODEVAR_XEIG_FACTOR, &xeig) &
	    _C) != NONE || (os_read_mode_variable (mode,
	    os_MODEVAR_YEIG_FACTOR, &yeig) & _C) != NONE)
	 x_THROW (Bad_Mode);

      box.x0 = box.y0 = 0;
      box.x1 = (width << xeig)*draw_OS_UNIT;
      box.y1 = (height << yeig)*draw_OS_UNIT;

      trfm_box (bbox, trfm, &box);
   }

   void spritefile_declare_fonts (bits flags,
	 osspriteop_header const *sprite, int size)

   {  NOT_USED (flags)
      NOT_USED (sprite)
      NOT_USED (size)
   }
   ----------------------------------------------------------------------------
      Trfm_box() just transforms a box and rebounds it:
   ----------------------------------------------------------------------------
   void trfm_box (os_box *b, os_trfm const *m, os_box const *b1)

      /*set |b| to the bbox of |b1| after transformation by |m|.*/

   {  os_coord c [4], c1 [4];
      int i;

      /*Get the four corners of |b1|.*/
      c1 [0].x = b1->x0, c1 [0].y = b1->y0;
      c1 [1].x = b1->x1, c1 [1].y = b1->y0;
      c1 [2].x = b1->x1, c1 [2].y = b1->y1;
      c1 [3].x = b1->x0, c1 [3].y = b1->y1;

      /*Transform them all.*/
      for (i = 0; i < 4; i++)
	 trfm_point (&c [i], m, &c1 [i]);

      /*Bound the four new points.*/
      b->x0 = b->y0 = INT_MAX;
      b->x1 = b->y1 =-INT_MAX;

      for (i = 0; i < 4; i++)
      {  (void) MINAB (b->x0, c [i].x);
	 (void) MINAB (b->y0, c [i].y);
	 (void) MAXAB (b->x1, c [i].x);
	 (void) MAXAB (b->y1, c [i].y);
   }  }