mode13 graphics
In mode 13 things are very simple. You have an arrary thats 320x200
and each byte is a pixel.

Sprites

A sprite is just a small bitmap that you draw over and over, moving a
bit each time to make it move.

Making a sprite.
Draw it in your favorite paint program, and save it. Then you have
to convert the saved file to a plain linear bitmap. Once the saved
art is in the same format as the mode13 screen, you just copy it to
the screen mem to display it.

Drawing a sprite without messing up the background.

Before you draw the sprite you get the area beneath were the sprite
is to be drawn and save it. At the start of the next frame replace
this saved bitmap before drawing your sprite at its new location.
When drawing a lot of sprites it is best to write a routine that
saves all the 'saved bitmaps' in a list, then you have to put them
back in reverse order to prevent any garbage from appearing.

Flicker

If you just draw straight to the screen, drawing large bitmaps will
cause flicker, and shearing. There are a number of methods to prevent
this and here is a simple one.

Draw everything to an off-screen buffer. This is just 64k that you
malloc and draw to as if it was the screen. When you have drawn
everything for one frame, copy this offscreen buffer to the video
mem. BUT wait for the vertical re-trace before copying it over. This
way you will be changing the screen mem while the hardware is moving
the 'scan-line' back to the top of the screen, and you won't get any
flicker.


BGI
Borland includes a BGI graphics lib, it is easy to use but DEAD SLOW.
The init_graph() (or whatever it called) can be used to get into
320x200 256 mode, I think they callit MCGA mode.

Here is some code to get you started.

/*

   mode13.h

   copyright 1993, Alec Russell, ALL rights reserved

   320x200, 256 color mode routines, BIOS mode 0x13

*/

#ifndef DEF_MODE13
#define DEF_MODE13 1

#define USHORT unsigned short;

// dead simple sprite struct
typedef struct
   {
   USHORT width, height;
   BYTE far *bitmap;
   }
shape_t;

typedef unsigned char far * FARPTR;

#define INPUT_STATUS_1  03dah   //Input Status 1 register
#define INPUT_STATUS_0  03dah   //Input status 0 register

#endif

/* ----------------------- end of file ------------------------------- */

// start of blit13.c---------------------------------------------------

/*
   Copyright 1993, Alec Russell, ALL rights reserved
   Permission granted to use this as you wish.

   FILE :13blit.c

         mode 13 blit stuff  --- MODE 13 !!! 320x200 x 256 colurs


   HISTORY:
      created :  may 19, 1993
      updates :

*/

#pragma inline


/*
   draws to the screen directly.

   x, y, width, height all in pixels, mode 0x13 ONLY

   MAX width and height is 255!!!!!

   buffer pointer to a width by height array of bytes that are a bitmap

   x, y is position to display at, NO checking done for valid
   co-ords etc...

   WIDTH MUST BE EVEN!!!!


*/
/* ---------------------- put_blit() --------------------- March 23,1993 */
void put_blit(FARPTR buffer, short x, short y, short width, short height)
{
   asm   {
         push  ds
         push  di

         /* calc start address in vido mem */
         mov   ax, y
         mov   bx, x
         xchg  ah, al
         add   bx, ax
         shr   ax, 1
         shr   ax, 1
         add   bx, ax

         /* set up address registers for movsw */
         mov   ax, 0xa000
         mov   es, ax
         mov   di, bx
         lds   si, buffer

         /* set up width and adjustment for fast blat */
         mov   dx, width
         shr   dx, 1
         mov   bx, 320
         sub   bx, width
         mov   ax, height
         }

         /* blast each line */
l1:
   asm   {
         mov   cx, dx
         rep   movsw
         add   di, bx
         dec   ax
         jnz   l1

         /* all done */
         pop   di
         pop   ds
         }   
}



/*
   draws to any buffer that is 320x200 in size

   x, y, width, height all in pixels, mode 0x13 ONLY

   MAX width and height is 255!!!!!

   buffer pointer to a width by height array of bytes that are a bitmap

   x, y is position to display at, NO checking done for valid
   co-ords etc...

   WIDTH MUST BE EVEN!!!!

*/
/* ---------------------- put_blit2() --------------------- March 23,1993 */
void put_blit2(FARPTR buffer, short x, short y,
              short width, short height,
              FARPTR dest)
{
   asm   {
         push  ds
         push  di

         /* calc start address in vido mem */
         mov   ax, y
         mov   bx, x
         xchg  ah, al
         add   bx, ax
         shr   ax, 1
         shr   ax, 1
         add   bx, ax

         /* set up address registers for movsw */
         les   di, dest  // es:di points to start dest
         add   di, bx    // make es:di point to x,y in dest

         lds   si, buffer

         /* set up width and adjustment for fast blat */
         mov   dx, width
         shr   dx, 1
         mov   bx, 320
         sub   bx, width
         mov   ax, height
         }

         /* blast each line */
l1:
   asm   {
         mov   cx, dx
         rep   movsw
         add   di, bx
         dec   ax
         jnz   l1

         /* all done */
         pop   di
         pop   ds
         }   
}


/* wait for vertical sync */
/* ---------------------- wait_vert() -------------------- March 27,1993 */
void wait_vert(void)
{
   asm   {
         mov     dx,INPUT_STATUS_1
         }
WaitVS:
   asm   {
         in      al,dx
         test    al,08h
         jz      WaitVS  /* vertical sync is active high (1 = active) */
         }
}


/*

    pcx.c

    Internet: alexad3@icebox.iceonline.com
    Copyright 1995, April 6 by Alec Russell, ALL rights reserved
    Permission granted to use this code as anyone wishes.

    Created - 1995/4/6

    History:
        New file

    Originally programmed for medium mem model, thus the liberal
    lacing of FAR * throughout the code.

*/

#include <stdio.h>
#include <string.h>

#include <xfileio.h>
#include <gmalloc.h>


// for all pcx files (far as I know)
typedef struct
   {
   char manu; /// usually 10
   char version;
   char encoding;
   char bits_per_pixel;
   int xmin, ymin, xmax, ymax;
   int hres, yres;
   char palette[48];  // not used by 256 color pcx
   char reserved;
   char color_planes;
   int bytes_per_line;
   int palette_type;
   char spare[58];
   }
pcx_head_t;


#define PAL_SIZE 768
#define PCX_HD_SIZE 128

/* for 256 color PC images ONLY, works with dpaint images
   Make sure b is big enough for unpacked image.
   Don't use this to get ideas for compression as
   there are much better ways to do even simple RLE encoding.
*/
/* ---------------------- unpack_pcx() ------------------ January 4,1995 */
int unpack_pcx(char *fname, unsigned char far *b, unsigned char *pal,
               int *p_width, int *p_height)
{
   int err=0, i;
   unsigned int size;
   pcx_head_t pcx;
   unsigned char far *t1, far *raw;

   raw=far_load(fname);  // load the whole file into mem,
                         // an easy function to write

   size=load_size;       // load_size is a global set by far_load()
                         // if not obvious load_size is file size
   if ( raw )
      {
      if ( size > PCX_HD_SIZE )
         {
         _fmemcpy(&pcx, raw, PCX_HD_SIZE);  // far memcpy
#if 0
// debug stuff
pr2("manu %d", pcx.manu);
pr2("ver  %d", pcx.version);
pr2("enc  %d", pcx.encoding);
pr2("bits %d", pcx.bits_per_pixel);
pr2("xmin %d ymin %d xmax %d ymax %d",
    pcx.xmin, pcx.ymin, pcx.xmax, pcx.ymax);
pr2("hres %d yres %d", pcx.hres, pcx.yres);
pr2("rsv %d", pcx.reserved);
pr2("planes %d", pcx.color_planes);
pr2("bytes/line %d", pcx.bytes_per_line);
pr2("pal type %d", pcx.palette_type);
#endif
         // get width and height
         *p_width =pcx.xmax - pcx.xmin + 1;
         *p_height=pcx.ymax - pcx.ymin + 1;
         // get palette
         // the palette is just tacked onto the end of the file
         _fmemcpy(pal, raw+size-PAL_SIZE, PAL_SIZE);
         for ( i=0, t1=pal; i < PAL_SIZE; i++, t1++ )
            *t1>>=2;

         // this type of de-compression is common to most pcx files

         t1=raw+PCX_HD_SIZE; // skip header
         // decompress raw into b
         size-=PCX_HD_SIZE; // skip header
         size-=PAL_SIZE; // don't include palette at end
         while ( size )
            {
            if ( (*t1 & 0xc0) == 0xc0 ) // are the two high bits set?
               {
               // hi bits set, its a run
               i=*t1 & 0x3f;    // mask with 00111111 to get size of run
               t1++;            // next byte is color to repeat
               size--;
               while ( i-- )
                  *b++=*t1;
               t1++;
               size--;
               }
            else
               {
               *b++=*t1++;  // not a run, copy one byte
               size--;
               }
            }

         gfree(raw, "raw");  // like a free()
         }
      else
         err=2;
      }
   else
      err=1;

   return(err);
}


/* ------------------------------ end of file ------------------------- */
