#include <osbind.h>
#include <stdio.h>
#include "structs.h"
#include <vdibind.h>
#include <aesbind.h>

long block;
long makel();

int vhandle,orez;
long altscreen,orgscreen,oldscreen;
TEMPLATE * templist[20];
TOBJECT * objectlist[20];
PRIMIT primlist[100];
int NTEMPLATE;
long abst;
int primcnt;
long frame;

int otheta,ophi;

int tank;
long ox,oy,oz;
int phi,theta,rho;
int firetem;
int fobs[20];

extern int centerx,centery;
extern double scale;


void main()
{
int tem;
long ch;
char out[80];
int i;
int tem2;
int t;
Point3 testc;

for (i=0;i<20;i++)
        fobs[i]=0;
frame=0;


initscreen();
initmodem();

otheta=180;
ophi=0;

for (i=0;i<PLEND;i++)
      primlist[i].type=0;

makesintab();

testc.x=0;
testc.y=0;
testc.z=700;


tem=loadtemplate("ship2.tem");

firetem=loadtemplate("fire.tem");

tank=createobject(testc,tem);

printf("objects created\n");

centerx=160;
centery=100;
scale=1;


v_clrwk(vhandle);


Setscreen(oldscreen,altscreen,-1);
Vsync();


ox=0;
oy=0;
oz=0;


phi=theta=rho=0;
t=1;

dopal();

while(t)
{
t=doscr2();

}




done:
;

closedown();

}



doscr2()
{
extern int theta,phi,rho;
extern long ox,oy,oz;
int ch;
long rspeed=0;
Point3 speed;
char out[80];
int obj;
Point3 ct;

while(1)
{

background();
dofire();
dotank();

for (obj=0;obj<20;obj++)
        if (objectlist[obj])
        {
        objectviz(obj,ox,oy+40,oz,theta,phi,rho);
        if (objectlist[obj]->viz)
                {makeview(obj,ox,oy+40,oz,theta,phi,rho);
                makepic(obj);
                }
        }


findmidz();

vizpolys();

sortall();

drawall();

sprintf(out,"%ld",frame++);
v_gtext(vhandle,5,5,out);

pageflip();

if (Bconstat(2))
        ch=Bconin(2)&0x00ff;

switch(ch)
        {
        case 'x': return(0);
        break;
        case '8': phi-=15;
        break;
        case '2': phi+=15;
        break;
        case '4': theta+=15;
        break;
        case '6': theta-=15;
        break;
        case '+': rspeed+=10;
        break;
        case '-': rspeed-=10;
        break;
        case '7': rho-=15;
        break;
        case '9': rho+=15;
        break;
        case '0': rspeed=0;
        break;
        case '*': 
        ct.x=ox+50;
        ct.y=oy;
        ct.z=oz;
        fireit(ct,theta,phi);
        sendfire();
        break; 
        case 'i': oy+=30;
        break;
        case 'm': oy-=30;       
        break;
        case 's': scale-=0.10;
        break;
        case 'd': scale+=0.10;
	break;

        }

ch=0;
if (theta<0) theta+=360;
if (theta>360) theta-=360;
if (phi<0) phi+=360;
if (phi>360) phi-=360;
if (rho>360) rho-=360;
if (rho<0) rho+=360;


speed.x=ds2(rspeed,theta);
speed.z=dc2(rspeed,theta);
speed.y=ds2(rspeed,phi);
ox+=speed.x;
oz+=speed.z;
oy+=speed.y;

} /* while */

}





static int active[10];

void dofire()
{
Point3 *fpt;
int i;
int ft,fp;

for (i=0;i<10;i++)
        {
        if (active[i]>=2)
                {
                active[i]--;
                ft=objectlist[fobs[i]]->theta;
                fp=objectlist[fobs[i]]->phi;
                fpt=&objectlist[fobs[i]]->center;
                fpt->x+=ds2(100L,ft);
                fpt->z+=dc2(100L,ft);
                fpt->y+=ds2(100L,fp);
                }
        
        if (active[i]==1)
                {
                deleteobject(fobs[i]);
                active[i]=0;
                fobs[i]=0;
                }

        }

}


void fireit(cent,theta,phi)
Point3 cent;
int theta,phi;
{
int i;

for (i=0;i<10;i++)
        if (active[i]==0) goto found;

return;

found:
;

active[i]=20;
fobs[i]=createobject(cent,firetem);
objectlist[fobs[i]]->theta=theta;
objectlist[fobs[i]]->phi=phi;

}

void dotank()
{
extern int tank;
long x,y,z;
char out[20];
Point3 cent;

/*deltas();*/

x=objectlist[tank]->center.x;
z=objectlist[tank]->center.z;
y=objectlist[tank]->center.y;

x+=ds2(20,otheta);
z+=dc2(20,otheta);
y+=ds2(20,ophi);

if (rand()%100<10) otheta+=rand()%10-5;
if (rand()%100<10) ophi+=rand()%10-5;
if (rand()%100<5) {
	cent.x=x;cent.y=y;cent.z=z;
	fireit(cent,otheta,ophi);
	}

if (otheta>360) otheta-=360;
if (otheta<0) otheta+=360;
if (ophi>360) ophi-=360;
if (ophi<0) ophi+=360;

objectlist[tank]->center.x=x;
objectlist[tank]->center.y=y;
objectlist[tank]->center.z=z;
objectlist[tank]->theta=otheta;
objectlist[tank]->phi=ophi;

}


#define lhi2(a)    ( ((a) & 0xFF000000) >> 24 )
#define lhi(a)     (((a) & 0xFF0000) >> 16  )
#define lmed(a)    (((a) & 0xFF00) >> 8 )
#define llo(a)     ( (a) & 0xFF       )

#define ABSPOS 1
#define FIRED  2
#define DX   3
#define DY 4
#define DZ 5
#define DT 6
#define DP 7
#define DR 8


void sendpos()
{
unsigned char hi2,hi,med,lo;
long x;
char out[40];

Bconout(1,ABSPOS);

sendlong(ox);
sendlong(oy);
sendlong(oz);

sendint(theta);
sendint(phi);
sendint(rho);

x=ox;
hi2=lhi2(x);
hi=lhi(x);
med=lmed(x);
lo=llo(x);



hi=lmed(theta);
lo=llo(theta);


}


void sendfire()
{
Bconout(1,FIRED);
}


void sendlong(x)
long x;
{
unsigned char hi,hi2,med,lo;

hi2=lhi2(x);
hi=lhi(x);
med=lmed(x);
lo=llo(x);

Bconout(1,hi2);
Bconout(1,hi);
Bconout(1,med);
Bconout(1,lo);

}

void sendint(x)
int x;
{
unsigned char hi,lo;


hi=lmed(x);
lo=llo(x);

Bconout(1,hi);
Bconout(1,lo);

}

#define WAITFC 1
#define GETCOM  2

unsigned char packetbuf[20];
int curpack;
int status;
int bytenum;
int curbyte;


void initmodem()
{

Rsconf(4,0,-1,-1,-1,-1);
curpack=0;
curbyte=0;
bytenum=0;
status=WAITFC;

}

void modemthang()
{
unsigned char ch;
Point3 ct;

if (status==WAITFC)
        {
        ch=0;
        if (Cauxis()) {ch=Bconin(1);ch&=0xFF;}
switch(ch)
        {        
        case ABSPOS: 
                curpack=ABSPOS;status=GETCOM;bytenum=18;curbyte=0;
        break;
        case FIRED:
        ct.x=objectlist[tank]->center.x;
        ct.y=objectlist[tank]->center.y+40;
        ct.z=objectlist[tank]->center.z;
        fireit(ct,objectlist[tank]->theta,objectlist[tank]->phi);
        break;
        case DX:
        curpack=DX;status=GETCOM;bytenum=1;curbyte=0;
        break;
        case DY:
        curpack=DY;status=GETCOM;bytenum=1;curbyte=0;
        break;
         case DZ:
        curpack=DZ;status=GETCOM;bytenum=1;curbyte=0;
        break;
         case DT:
        curpack=DT;status=GETCOM;bytenum=1;curbyte=0;
        break;
         case DP:
        curpack=DP;status=GETCOM;bytenum=1;curbyte=0;
        break;
         case DR:
        curpack=DR;status=GETCOM;bytenum=1;curbyte=0;
        break;

        }
        }


if (status==GETCOM)
        {
        if (Cauxis()) {ch=Bconin(1);ch&=0xFF;
                        packetbuf[curbyte++]=ch;
                        }
        if (curbyte==bytenum) {status=WAITFC;docom(curpack);return;}
        }
}
       

void docom(com)
int com;
{
long x,y,z;
int t,p,r;
char out[40];
int i ;

switch(com)
        {
        case ABSPOS:
        x=makel(&packetbuf[0]);
        objectlist[tank]->center.x=x;
        y=makel(&packetbuf[4]);
        objectlist[tank]->center.y=y;
        z=makel(&packetbuf[8]);
        objectlist[tank]->center.z=z;
        t=makei(&packetbuf[12]);
        objectlist[tank]->theta=t;
        p=makei(&packetbuf[14]);
        objectlist[tank]->phi=p;
        r=makei(&packetbuf[16]);
        objectlist[tank]->rho=r;
        break;
        case DX:
        x=(long) packetbuf[0];
        if (x>127) x-=256L;
        objectlist[tank]->center.x+=x;
        break;
        case DY:
        x=(long) packetbuf[0];
        if (x>127) x-=256L;
        objectlist[tank]->center.y+=x;
        break;
        case DZ:
        x=(long) packetbuf[0];
        if (x>127) x-=256L;
        objectlist[tank]->center.z+=x;
        break;
        case DT:
        t=(int)packetbuf[0];
        if (t>127) t-=256;
        objectlist[tank]->theta+=t;
        break;

        case DP:
        t=(int)packetbuf[0];
        if (t>127) t-=256;
        objectlist[tank]->phi+=t;
        break;
        case DR:
        t=(int)packetbuf[0];
        if (t>127) t-=256;
        objectlist[tank]->rho+=t;
        break;
        }


}

        




long makel(adr)
char *adr;
{
long result;
unsigned long mover;
unsigned long hi2,hi,med,lo;

char out[40];

hi2=(*adr)*16777216;
hi=*(adr+1)*65536;
med=*(adr+2)*256;
lo=*(adr+3);
mover=hi2+hi+med+lo;

if (mover>2147483648) {mover+=65536;
                result=4294967295-mover;
                        result=-result;
                        }

 else result=mover; 


return result;
}

makei(adr)
char *adr;
{
unsigned int res1;
int result;

res1=(*(adr)*256);
res1+=*(adr+1);

if (res1>32767) result=res1-65536;
else result=res1;

return result;
}



void deltas()
{
static long dx,dy,dz;
static int dt,dp,dr;

if (dx!=ox) {sendc(DX,ox-dx);dx=ox;}
if (dy!=oy) {sendc(DY,oy-dy);dy=oy;}
if (dz!=oz) {sendc(DZ,oz-dz);dz=oz;}


if (dt!=theta) {senda(DT,theta-dt);dt=theta;}


if (dp!=phi)   {senda(DP,phi-dp);  dp=phi;}


if (dr!=rho)    {senda(DR,rho-dr);  dr=rho;}

}


void sendc(what,delta)
int what;
long delta;
{
char dif;

dif=(char)delta;

switch (what)
        {
        case DX: Bconout(1,DX);
        Bconout(1,dif);
        break;
        case DY: Bconout(1,DY);
        Bconout(1,dif);
        break;
        case DZ: Bconout(1,DZ);
        Bconout(1,dif);
        break;
        }
}
                
void senda(what,delta)
int what,delta;
{
char dif;
dif=(char)delta;

switch(what)
        {
        case DT: Bconout(1,DT);
        Bconout(1,dif);
        break;
        case DP: Bconout(1,DP);
        Bconout(1,dif);
        break;
        case DR: Bconout(1,DR);
        Bconout(1,dif);
        break;
        }
}
