Metropoli BBS
VIEWER: animate.c MODE: TEXT (ASCII)
/* ***********************************************************************
   *									 *
   *			 Graphics Animation Program			 *
   *									 *
   *				     By					 *
   *									 *
   *				Larry Sharp				 *
   *                                                                     *
   *									 *
   *  (c) 1991 Larry Sharp						 *
   *                                                                     *
   *                                                                     *
   * Original Turbo Pascal version (c) 1991,1992  Christopher D. Watkins *
   *    								 *
   ***********************************************************************

		       Compile using Large memory model

		   Maximum of 30 Cels per Animation Sequence
			    at 160 x 100 resolution
*/

#include "stdio.h"
#include "dos.h"
#include "string.h"
#include "malloc.h"
#include "mem.h"
#include "conio.h"
#include "defs.h"

union  REGS reg;                        /* Global Variables */
struct SREGS inreg;

char File_Name[81];
Byte n, y, key, B_Col;
Byte Num_Cels;
int Direction, Flip, CP;
int  D_Rate, Old_D_Rate;
Word Cel_Off[3000];
Word Cel_Seg[3000];
Word Window_Offsets[100];
Word Screen_Offsets[200];
Palette_Register Pal_Array;
static Byte far *Screen;
static Byte far *Cel_Buf;

/* ***********************************************************************
   *									 *
   *			    Graphics Routines				 *
   *									 *
   ***********************************************************************
*/

void Set_Mode(Byte Mode)
{
  reg.h.ah=0;
  reg.h.al=Mode;
  int86(0x10,&reg,&reg);
}

void Init_Screen()
{
  Byte y;

  for(y=0; y<200; y++)
    Screen_Offsets[y]=320*y;
}

void Plot(int x, int y, Byte color)
{
  Word Offset, Page;
  char far *address;

  if(!((x<0) || (y<0) || (x>(319)) || (y>(200))))
  {
    Offset = Screen_Offsets[y] + x;
    address = (char far *)  (0xA0000000L + Offset);
    *address = color;
  }
}

void Set_Palette(Palette_Register Hue)
{
  reg.x.ax=0x1012;
  segread(&inreg);
  inreg.es=inreg.ds;
  reg.x.bx=0;
  reg.x.cx=256;
  reg.x.dx=(int)&Hue[0];
  int86x(0x10,&reg,&reg,&inreg);
}

void Init_Graphics()
{
  Init_Screen();
  Set_Mode(19);
  Set_Palette(Pal_Array);
}

void Exit_Graphics()
{
  sound(1000);
  delay(500);
  nosound();
  Set_Mode(3);
}

void Set_Text_Screen(int tc, int tb)
{
  textcolor(tc);
  textbackground(tb);
  clrscr();
}

/* ***********************************************************************
   *									 *
   *			  	Memory Routines				 *
   *									 *
   ***********************************************************************
*/

void Allocate_Memory()
{
  if((Cel_Buf=farcalloc(32, 16000))==NULL)
  {
    printf("Not enough memory!\n\nHit any key to exit....");
    getch();
    exit(1);
  }
}

void Free_Memory()
{
  farfree(Cel_Buf);
}

Word Max(Word n1, Word n2)
{
    return((n1>n2) ? n1 : n2);
}

Byte Get_Key()
{
  Byte k;

  key=getch();
  return(key);
}

void Get_ANI_File_Name()
{
  Byte x, y;

  textcolor(YELLOW);
  textbackground(BLUE);
  gotoxy(1, 8);
  cprintf("Enter File Name -> ");
  x=wherex();
  y=wherey();
  textcolor(WHITE+BLINK);
  cprintf("%s", "SPHRPLAN");
  textcolor(YELLOW);
  gotoxy(x, y);
  while(!(kbhit()));
  cprintf("            ");
  gotoxy(x, y);
  gets(File_Name);
  if(!(strcmp(File_Name, "")))
    strcpy(File_Name, "SPHRPLAN");
  strupr(File_Name);
  strcat(File_Name, ".ANI");
  gotoxy(1, 8);
  printf("                               ");
  textcolor(WHITE+BLINK);
  gotoxy(1, 8);
  cprintf("Loading ");
  textcolor(YELLOW);
  cprintf("%s", File_Name);
}

void Init_Cels()
{
  DWord tmp, NCel_Buf;
  Word n, y, Seg;

  tmp=NCel_Buf=(DWord) Cel_Buf;
  Seg=(Word)((tmp>>16)&65535);
  for(n=0; n<30; n++)
  {
    for(y=0; y<100; y++)
    {
      tmp=(DWord) NCel_Buf;
      tmp+=(DWord)((n*16000)+(y*160));
      Cel_Off[(n*100)+y]=(Word)(tmp&65535);
      if((Cel_Off[(n*100)+y]+160)<Cel_Off[(n*100)+y])
      {
	tmp+=160;
	NCel_Buf+=160;
	Cel_Off[(n*100)+y]=(Word)(tmp&65535);
	Seg+=0x1000;
      }
      Cel_Seg[(n*100)+y]=Seg;
    }
  }
}

void Init_Window()
{
  long tmp;

  Screen=0xA0000000L;
  for(y=50; y<150; y++)
  {
    tmp=(y*320)+80;
    Window_Offsets[y-50]=tmp;
  }
}

void Do_Title()
{
  Byte i, j;
  int B_Colors[3]={RED, WHITE, BLUE};
  int F_Colors[3]={LIGHTGRAY, MAGENTA, YELLOW};

  for(i=0; i<3; i++)
  {
    for(j=0; j<80; j++)
    {
      textcolor(F_Colors[i]);
      textbackground(B_Colors[i]);
      cprintf(" ");
    }
  }
  textcolor(F_Colors[0]);
  textbackground(B_Colors[0]);
  for(i=1; i<32; i++)
  {
    gotoxy(i, 1);
    cprintf(" Animation Software");
    delay(15);
  }
  textcolor(F_Colors[1]);
  textbackground(B_Colors[1]);
  for(i=77; i>38; i--)
  {
    gotoxy(i, 2);
    cprintf("by ");
    delay(15);
  }
  textcolor(F_Colors[2]);
  textbackground(B_Colors[2]);
  for(i=23; i>2; i--)
  {
    gotoxy(34, i);
    cprintf("Larry Sharp");
    gotoxy(34, i+1);
    cprintf("           ");
    delay(15);
  }
  textcolor(LIGHTGRAY);
  gotoxy(35, 17);
  cprintf("DIRECTION");
  gotoxy(37, 20);
  cprintf("SPEED");
  gotoxy(33, 23);
  cprintf("FRAME ADVANCE");
  textbackground(BLACK);
  textcolor(LIGHTRED);
  gotoxy(16, 18);
  cprintf("     Fwd       Rvs       Flip Up       Flip Down ");
  gotoxy(16, 21);
  cprintf("   Speed Up    Slow Down    <10    >10      Quit ");
  gotoxy(16, 24);
  cprintf("   Forward Advance   Reverse Advance       Pause ");
  textcolor(WHITE);
  gotoxy(17, 18);
  cprintf("Rgt");
  gotoxy(27, 18);
  cprintf("Lft");
  gotoxy(38, 18);
  cprintf("Up");
  gotoxy(51, 18);
  cprintf("Dwn");
  gotoxy(17, 21);
  cprintf("+");
  gotoxy(29, 21);
  cprintf("-");
  gotoxy(42, 21);
  cprintf("*");
  gotoxy(49, 21);
  cprintf("/");
  gotoxy(56, 21);
  cprintf("Esc");
  gotoxy(17, 24);
  cprintf(">");
  gotoxy(35, 24);
  cprintf("<");
  gotoxy(53, 24);
  cprintf("Space");
}

void Find_Brightest_Color()
{
  Word h1, h2, h3, i;
  Byte c;

  c=0;
  h3=h1=(Pal_Array[0].Red+Pal_Array[0].Grn+Pal_Array[0].Blu);
  for(i=1; i<256; i++)
  {
    h2=(Pal_Array[i].Red+Pal_Array[i].Grn+Pal_Array[i].Blu);
    h3=Max(h1, h2);
    if(h3==h2)
    {
      c=i;
      h1=h2;
    }
  }
  B_Col=c;
}

void H_Line(Word x1, Word x2, Byte y1, Byte c)
{
  Word i;

  for(i=x1; i<=x2; i++)
  {
    Plot(i, y1, c);
  }
}

void V_Line(Word x1, Byte y1, Byte y2, Byte c)
{
  Word i;

  for(i=y1; i<=y2; i++)
  {
    Plot(x1, i, c);
  }
}

void Draw_Window_Frame()
{
  H_Line(79, 240, 49, B_Col);
  H_Line(79, 240, 150, B_Col);
  V_Line(79, 49, 150, B_Col);
  V_Line(240, 49, 150, B_Col);
}

void Draw_D_Meter()
{
  H_Line(32, 289, 189, B_Col);			/* Draw Rectangular Meter */
  H_Line(32, 289, 199, B_Col);
  V_Line(32, 189, 199, B_Col);
  V_Line(289, 189, 199, B_Col);
  V_Line(32, 183, 187, B_Col); 			/* Draw '+' */
  H_Line(30, 34, 185, B_Col);
  H_Line(287, 291, 185, B_Col);                 /* Draw '-' */
}

void Update_D_Meter(int D_Rate)
{
  Word i;

  if(Old_D_Rate>D_Rate)
  {
    for(i=Old_D_Rate; i>D_Rate; i--)
      V_Line((i+33), 190, 198, 0);
  }
  else
  {
    for(i=Old_D_Rate; i<=D_Rate; i++)
      V_Line((i+33), 190, 198, 24);
  }
}

void Init_D_Meter()
{
  D_Rate=50;			  	/* Initial Delay Rate */
  Old_D_Rate=0;
  Find_Brightest_Color();
  Draw_Window_Frame();
  Draw_D_Meter();
  Update_D_Meter(D_Rate);
  Old_D_Rate=D_Rate;
}

void Animate()
{
  Byte n, y, k, tmp, NC, Nl;
  Word Del;
  Word l1;
  int LP;

  NC=Num_Cels-1;
  CP=0;
  Nl=99;
  LP=0;
  while(key!=27)			/* Animate until Escape key hit */
  {
    for(n=0; n<Num_Cels; n++)
    {
      for(y=0; y<100; y++)
      {
	_fmemcpy((Screen+(Window_Offsets[y])),
		   MK_FP(Cel_Seg[(CP*100)+LP],
		       Cel_Off[(CP*100)+LP]),
					160);
	if(Flip)
	{
	  --LP;
	  if(LP<0)
	    LP=Nl;
	}
	else
	{
	  ++LP;
	  if(LP>Nl)
	    LP=0;
	}
      }
      if(Direction)
      {
	++CP;
	if(CP>NC)
	  CP=0;
      }
      else
      {
	--CP;
	if(CP<0)
	  CP=NC;
      }
      for(Del=0; Del<(D_Rate*200); Del++);
      for(Del=0; Del<(D_Rate*200); Del++);
      if(kbhit())				/* Check for key stroke */
      {
	k=Get_Key();				/* Get key stroke */
	switch(toupper(k))
	{
	  case '+' : Old_D_Rate=D_Rate;		/* Faster by 1 */
		     --D_Rate;
		     if(D_Rate<0)
		       D_Rate=0;
		     Update_D_Meter(D_Rate);
		     break;

	  case '-' : Old_D_Rate=D_Rate;		/* Slower by 1 */
		     ++D_Rate;
		     if(D_Rate>255)
		       D_Rate=255;
		     Update_D_Meter(D_Rate);
		     break;

	  case '*' : Old_D_Rate=D_Rate;		/* Faster by 10 */
		     D_Rate-=10;
		     if(D_Rate<0)
		       D_Rate=0;
		     Update_D_Meter(D_Rate);
		     break;

	  case '/' : Old_D_Rate=D_Rate;		/* Slower by 10 */
		     D_Rate+=10;
		     if(D_Rate>255)
		       D_Rate=255;
		     Update_D_Meter(D_Rate);
		     break;

	  case 'M' : if(!Direction)		/* Forward */
		     {
		       Direction=1;
		       n=NC-n;
		     }
		     break;

	  case 'K' : if(Direction)		/* Reverse */
		     {
		       Direction=0;
		       n=NC-n;
		     }
		     break;

	  case 'H' : if(Flip)  	        	/* Forward */
		     {
		       Flip=0;
		       LP=0;
		     }
		     break;

	  case 'P' : if(!Flip)		        /* Reverse */
		     {
		       Flip=1;
		       LP=Nl;
		     }
		     break;
	}
	k=0;					/* Set key back to 0 */
      }
    }
  }
}

void Load_Cels()
{
  FILE *In_File;

  if((In_File=fopen(File_Name,"rb"))==NULL) 	/* Open animation file */
  {
    Exit_Graphics();
    printf("Can't open Animation File %s!\n\nHit any key to exit....", File_Name);
    getch();
    Free_Memory();
    exit(1);
  }
  Num_Cels=getc(In_File);		/* Get # of Cels in sequence */
  printf("\n\nThere are %u Cels in this Animation sequence.\n", Num_Cels);
  if(Num_Cels>30)			/* Maximum of 30 Cels */
  {
    printf("\nTruncating to 30 Cels....\n");
    Num_Cels=30;
  }
  fread(Pal_Array, 1, 768, In_File);	/* Load Palette for animation */
  for(n=0; n<Num_Cels; n++)		/* Load Cels */
  {
    for(y=0; y<100; y++)
      fread(MK_FP(Cel_Seg[(n*100)+y], Cel_Off[(n*100)+y]), 160, 1, In_File);
  }
  Direction=1;				/* Go Forward to start animation */
  Flip=0;
  fclose(In_File);
}

void main()
{
  Allocate_Memory();			/* Get memory for Cels           */
  Set_Text_Screen(YELLOW, BLUE);	/* Set Text Screen colors        */
  Do_Title();				/* Opening Display and Title     */
  Get_ANI_File_Name();			/* Get the name of the .ANI file */
  Init_Cels();				/* Initialize Cel offsets        */
  Init_Window();			/* Initialize Window offsets     */
  Load_Cels();                          /* Load Cels from .ANI file      */
  Init_Graphics();                      /* Initialize Graphics Screen    */
  Init_D_Meter();			/* Initialize Delay Meter        */
  Animate();				/* Animate!                      */
  Exit_Graphics();			/* Stop animation and exit       */
  Free_Memory();			/* Free up far memory            */
}
[ RETURN TO DIRECTORY ]