/* ***********************************************************************
* *
* 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,®,®);
}
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,®,®,&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 */
}