/*****************************************************************
   Flusi/Huba/Fedmain  (c)  Andre Borngräber & Marec Andreeßen 
   Dice 2.06.40
   PC-Version (c) Martin Borchard    Turbo C 2.0
*****************************************************************/   

#define VERSION "1.11a"

char Version[] = "$VER: Amiga-MFS "VERSION" ("__DATE__") © 1995 Andre Borngraeber";


/* Kanalbelegung:
1. li: D, S  r: H, Q
2. li: D, Q  r: H, S
3. li: H, Q  r: D, S
4. li  H, S  r: D, Q */


#include "math.h"
#include "stdio.h"
#include "graphics/rastport.h"
#include "intuition/screens.h"
#include "intuition/intuition.h"
#include "Areaextras.h"
#include "hardware/custom.h"
#include "graphics/gfxmacros.h"
#include "planesound.h"
#include "hardware/intbits.h"
#include "exec/types.h"
#include "exec/memory.h"
#include "input.c"
#include "readkey.c"
#include <time.h>

#define ax 0
#define ay 0
#define az 1000
#define ANZECKEN 15
#define ANZPOLY 50 

#define HOEHESENS 750000.0
#define QUERSENS  600000.0
#define DROSSELSENS 100.0
#define SEITENSENS  1000000.0

short *pot0dat=(short *)0xdff012;
short *pot1dat=(short *)0xdff014;

short Joy0x=0,Joy0y=0,Joy1x=0,Joy1y=0;

char *cia=(char *)0xbfe001;

APTR PotgoBase = 0;               
long gotpotgo = 0;                


short laut,frequenz;
int anzahl=0,st=1,punktnr;
struct ViewPort *thisview;


struct     intvec
   {
      short x;
      short y;
      short z;
  };

struct     Vec
   {
      float x;
      float y;
      float z;
  };

struct     Basis
  {
   struct  Vec a;
   struct  Vec b;
   struct  Vec c;
  };

struct TransStore
  {
   short a;
   short b;
  };

struct Basis     e={1,0,0, 0,1,0, 0,0,1}, sky, plane;
struct Vec     distToPlane={0,-200,500};
struct RastPort    *rp      =0;
struct Window    *window =0;
struct Screen    *screen =0;
struct Vec     Magic[ANZPOLY*ANZECKEN+9],Rotor[9][10];
struct TransStore  MagicStore[ANZPOLY*ANZECKEN+9],RotorStore[20];
struct BitMap    Map[2];
struct Vec     beweg={0,0,0};
struct View    *View;
struct ViewPort    *VPort;
struct UCopList    *CopList,*CopListMerk;
struct Custom    *Custom=0xdff000;
struct IntuiMessage *IntuiMessage;

short hoehe,quer,seite,PlaneNr=0,pix=160;
int tscheibe,ipitch,ihrot,igewicht;
float gesch=0.02,flugwinkel=0,reibung=0.0007,auftrieb=0.1,abtrieb=-25.0,pitch,gewicht;
float rpm=1,gamma=0,Beweg,hrot,rauf,runter,xReibung,floatdummy,xFrei;

short *joy=(short *)0xdff00c;
char *feuer=(char *) 0xbfe001;
short j,h=0;
BOOL bruch,fw,demo=FALSE;

struct Bild {
          int ppunkte;
          int pfarbe;
          int pinvfarbe;
          int ppx[ANZECKEN+1];
          int ppy[ANZECKEN+1];
          int ppz[ANZECKEN+1];
         };       

struct Bild polygon[ANZPOLY+1];

int polygone;

struct RGBFarbe {
           int rot;
           int gruen;
           int blau;
          };

struct RGBFarbe RGB[8];

int FWart,xGewicht,xMotor,xPower,xWiderstand,abriss;
int xBack,xQuer,xHoehe,xSeite,xDrossel,xSpeed,xSense;
int xAchs=0,xLaut=0,xPrg=0,xKnall=0,xKanal=1;
int xJoy=0,xKaefig=0;
int Joy0x0,Joy0y0,Joy1x0,Joy1y0;
int Knueppel[5], KanalHoehe=2, KanalQuer=1, KanalMotor=3, KanalSeite=4;
float HoeheFak, QuerFak, PowerFak, SeitenFak, xJoySens=1.0;
int xToggleLX=1,xToggleLY=1,xToggleRX=1,xToggleRY=1,xUhr=3;

long xScreenm=135168L;
int  xScreenh=256, xScreenw=320, xScreend=3;

struct Task *mytask;

struct IntuiMessage *imsg;
short code;
ULONG class;

time_t t;
long startzeit=-1,thiszeit=0;
long starttime=-1,thistime=0,frames=0;
float framesps=1.0;

char frametext[80]="still counting !";

/***********************************************************************/

ResetJoy()
{
      Joy0x0=(*pot0dat & 255);
      Joy0y0=(short)((*pot0dat & 65280)/256)-10;
      Joy1x0=(*pot1dat & 255);
      Joy1y0=(short)((*pot1dat & 65280)/256);
   WritePotgo(0x0001,0x0001); 
}

/*********************************************************************/

OpenAJoystick()
{
long AllocPotBits();
APTR OpenResource();

   PotgoBase = OpenResource((STRPTR)"potgo.resource");
   gotpotgo = AllocPotBits(0xff01);
   printf("gotpotgo: %i \n\n",gotpotgo);
   WritePotgo(0x0001,0xff01);
}                   

/*********************************************************************/

long CloseAJoystick()
{
   FreePotBits(gotpotgo);
   return 1;
}

/*********************************************************************/


ReadAJoystick()
{
      Knueppel[4]=xToggleLX*(Joy0x0-(*pot0dat & 255));
      Knueppel[3]=xToggleLY*(Joy0y0-(short)((*pot0dat & 65280)/256));
      Knueppel[1]=xToggleRX*(Joy1x0-(*pot1dat & 255));              
      Knueppel[2]=xToggleRY*(Joy1y0-(short)((*pot1dat & 65280)/256));
      WritePotgo(0x0001,0x0001);                      
}

/*********************************************************************/

GetThePower()
{
  mytask=FindTask(NULL);
  SetTaskPri(mytask,19);
}

/***********************************************************************/

MakeCopper()
{

    View = ViewAddress();
    VPort = &(screen->ViewPort); 

    CINIT(CopList,3);
    CWAIT(CopList,170+h,0);
    if ( h < 130 ) {CMOVE(CopList,Custom->color[0],0x8c8);}
    else {CMOVE(CopList,Custom->color[0],0x000);}
    CEND(CopList);
    VPort->UCopIns = CopList; 
    MakeVPort(View,VPort);
    MrgCop(View);
    LoadView(View);
}

/***********************************************************************/

FrameCount()
{
  frames++;
  if (frames<200)
  {
    if(starttime==-1)
    {
      starttime=clock();
      frames=0;
    }
    thistime=clock();
    if(thistime-starttime<0)
    {
      starttime=-1;
    }
    else
    {
    if(thistime-starttime!=0)
      {
        framesps=5.0*(float)frames/(float)(thistime-starttime);
        sprintf(frametext,"%7.1f Bilder/s",framesps*10.0);
        if (framesps==0.0) framesps=1.0;
      }
    }
  }
}
 
/***********************************************************************/

MakeBigCopper()
{

    View = ViewAddress();
    VPort = &(screen->ViewPort);

    CINIT(CopList,11);
    CWAIT(CopList,141+h,0);
    if ( h > 125 ) 
    {
      CMOVE(CopList,Custom->color[0],0x000);
    }
    else 
    {
      CMOVE(CopList,Custom->color[0],0x474);
      CWAIT(CopList,143+h,0);
      CMOVE(CopList,Custom->color[0],0x585);
      CWAIT(CopList,147+h,0);
      CMOVE(CopList,Custom->color[0],0x696);
      CWAIT(CopList,153+h,0);
      CMOVE(CopList,Custom->color[0],0x7a7);
      CWAIT(CopList,160+h,0);
      CMOVE(CopList,Custom->color[0],0x8b8);
      CWAIT(CopList,170+h,0);
      CMOVE(CopList,Custom->color[0],0x9c9); 
    }
    CEND(CopList);
    VPort->UCopIns = CopList;
    MakeVPort(View,VPort);
    MrgCop(View);
    LoadView(View);
}

/*********************************************************************/

InitVars()
 {
  switch(xKanal)
  {
    case 2:  KanalHoehe=2; KanalQuer=4; KanalSeite=1; KanalMotor=3; break;
    case 3:  KanalHoehe=3; KanalQuer=4; KanalSeite=1; KanalMotor=2; break;
    case 4:  KanalHoehe=3; KanalQuer=1; KanalSeite=4; KanalMotor=2; break;
  }
  if(xAchs==1)  { KanalQuer=KanalSeite; QuerFak=SeitenFak; SeitenFak=0; } 
  sky = e;
  plane = e;
  RotSkyX();
  InitMagic();
  RefreshMagic();
 }

/***********************************************************************/

OpenAll()
 {
  struct  NewWindow NewWindow;
  int i;

  screen=(struct screen *) DBufferScreen();
  if (!screen) CloseAll();
  CopList = AllocMem(sizeof(struct UCopList),MEMF_CHIP|MEMF_CLEAR|MEMF_PUBLIC);
  MakeBigCopper(); 

  /*  NewWindow-Struktur initialisieren  */
  NewWindow.LeftEdge   = 0;
  NewWindow.TopEdge    = 0;
  NewWindow.Width   = 320;
  NewWindow.Height     = 256;
  NewWindow.BlockPen   = 1;
  NewWindow.DetailPen      = 0;
  NewWindow.Title   = NULL;
  NewWindow.Flags   = SIMPLE_REFRESH|ACTIVATE;
  NewWindow.IDCMPFlags     = RAWKEY;
  NewWindow.Type    = CUSTOMSCREEN;
  NewWindow.FirstGadget   = NULL;
  NewWindow.CheckMark      = NULL;
  NewWindow.Screen     = screen;
  NewWindow.BitMap     = NULL;
  NewWindow.MinWidth   = 1;
  NewWindow.MinHeight      = 1;
  NewWindow.MaxWidth   = 320;
  NewWindow.MaxHeight      = 256;

  /*  Das neue Fenster öffnen.      */
  window=(struct window *)OpenWindow(&NewWindow);
  if (!window) CloseAll();
  ActivateWindow(window);
  SetRast(rp,0);
  SwapDBufferScreen();
  SetRast(rp,0);
  rp=window->RPort;
  thisview = &((*screen).ViewPort);
  for(i=0; i<=7; i++)
  {
    SetRGB4(thisview,i,RGB[i].rot,RGB[i].gruen,RGB[i].blau);
  }
 }

/***********************************************************************/

CloseAll()
 {
  FreeVPortCopLists(VPort);
  if (window) CloseWindow(window);
  if (screen) CloseDBufferScreen();
 }

/***********************************************************************/

SwapDBufferScreen()
{
  screen->ViewPort.RasInfo->BitMap=&Map[PlaneNr];
  MakeScreen(screen);
  RethinkDisplay();
  PlaneNr=1-PlaneNr;
  rp->BitMap=&Map[PlaneNr];
  SetAPen(rp,1);
}

/***********************************************************************/

DBufferScreen()
{
struct     NewScreen NewScreen;
short i,j;

    for(i=0;i<=1;i++)
       {
    InitBitMap(&Map[i],3,320,256);
    for (j=0;j<=2;j++)
     {
       Map[i].Planes[j]=(PLANEPTR) AllocRaster(320,256);
     }
       }

     PlaneNr=0;

  /*  NewScreen-Struktur initialisieren.  */
  NewScreen.LeftEdge   = 0;
  NewScreen.TopEdge    = 0;
  NewScreen.Width   = 320;
  NewScreen.Height     = 256;
  NewScreen.Depth   = 3;
  NewScreen.DetailPen      = 0;
  NewScreen.BlockPen   = 1;
  NewScreen.ViewModes      = 0;
  NewScreen.Type    = CUSTOMSCREEN|CUSTOMBITMAP;
  NewScreen.Font    = NULL;
  NewScreen.DefaultTitle  = NULL;
  NewScreen.Gadgets    = NULL;
  NewScreen.CustomBitMap  = &Map[0];

  /*  Den neuen Screen öffnen.      */
  screen=(struct Screen *)OpenScreen(&NewScreen);

     rp=&screen->RastPort;
     SetRast(rp,0);
     SwapDBufferScreen();
     SetRast(rp,0);
     return(screen);
}

/***********************************************************************/

CloseDBufferScreen()
{

short  j,i;

  CloseScreen(screen);
  for (j=0;j<=1;j++)
    {
      for(i=0;i<=2;i++)
   {
     if (Map[j].Planes[i])  FreeRaster(Map[j].Planes[i],screen->Width,screen->Height);
   }
    }
}



/***********************************************************************/

BasisVecProduct(b,r,res)
 struct Basis b;
 struct Vec r,*res;
 {
   res->x = b.a.x*r.x+b.b.x*r.y+b.c.x*r.z;
   res->y = b.a.y*r.x+b.b.y*r.y+b.c.y*r.z;
   res->z = b.a.z*r.x+b.b.z*r.y+b.c.z*r.z;
 }


/***********************************************************************/

VecAdd(a,b,res)
 struct Vec a,b,*res;
 {
   res->x=a.x+b.x;
   res->y=a.y+b.y;
   res->z=a.z+b.z;
 }

/***********************************************************************/

RotX(r,alpha)
 struct Vec *r;
 float alpha;
 {
 float h;
   h   =r->y*fcos(alpha) - r->z*fsin(alpha);
   r->z=r->y*fsin(alpha) + r->z*fcos(alpha);
   r->y=h;
 }

/***********************************************************************/

RotZ(r,alpha)
 struct Vec *r;
 float alpha;
 {
 float h;
   h   =r->x*fcos(alpha) - r->y*fsin(alpha);
   r->y=r->x*fsin(alpha) + r->y*fcos(alpha);
   r->x=h;
 }

/***********************************************************************/

RotY(r,alpha)
 struct Vec *r;
 float alpha;
 {
 float h;
   h   =r->x*fcos(alpha) - r->z*fsin(alpha);
   r->z=r->x*fsin(alpha) + r->z*fcos(alpha);
   r->x=h;
 }

/***********************************************************************/

Transform(r,a,b)
struct Vec r;
short *a,*b;
 {
/*
   *a=(short) 160 + r.x;
   *b=(short) 128 - r.y;
*/
*a=(short) 160 + ( (int) (500*r.x) / (int)(r.z));
*b=(short) 128 - ( (int) (500*r.y)  / (int)(r.z));

 }

/***********************************************************************/

SkyToWindow(r,a,b)
struct Vec r;
short *a,*b;
 {
   BasisVecProduct(sky,r,&r);
   Transform(r,a,b);
 }


/***********************************************************************/

PlaneToWindow(r,a,b)
struct Vec r;
short *a,*b;
 {
   BasisVecProduct(plane,r,&r);
   VecAdd(distToPlane,r,&r);
   Transform(r,a,b);
 }

/***********************************************************************/

RotSkyX()
 {
  RotX(&sky.b,0.523);
  RotX(&sky.c,0.523);
 }

/***********************************************************************/

RotSkyY()
 {
  RotY(&sky.b,0.523);
  RotY(&sky.c,0.523);
 }

/***********************************************************************/

RotPlane()
 {
   RotY(&distToPlane,0.055);
   RotY(&plane.a,0.055);
   RotY(&plane.b,0.055);
   RotY(&plane.c,0.055);
 }

/***********************************************************************/

DrawPlane()
 {
 struct Vec dist,h;
 short a0,b0,a,b;

   SkyToWindow(distToPlane,&a0,&b0);

   VecAdd(distToPlane,plane.a,&h);
   Move(rp,a0,b0);
   SkyToWindow(h,&a,&b);
   Draw(rp,a,b);

   VecAdd(distToPlane,plane.b,&h);
   Move(rp,a0,b0);
   SkyToWindow(h,&a,&b);
   Draw(rp,a,b);

   VecAdd(distToPlane,plane.c,&h);
   Move(rp,a0,b0);
   SkyToWindow(h,&a,&b);
   Draw(rp,a,b);
 }


/***********************************************************************/

Loop(arg)
float arg;
{
 struct Vec ey,ez;
 ey=e.b;
 ez=e.c;
 RotX(&ey,arg);
 RotX(&ez,arg);
 BasisVecProduct(plane,ey,&ey);
 BasisVecProduct(plane,ez,&ez);
 plane.b=ey;
 plane.c=ez;
}

/***********************************************************************/

Roll(arg)
float arg;
{
 struct Vec ex,ey;
 ex=e.a;
 ey=e.b;
 RotZ(&ex,arg);
 RotZ(&ey,arg);
 BasisVecProduct(plane,ex,&ex);
 BasisVecProduct(plane,ey,&ey);
 plane.a=ex;
 plane.b=ey;
}

/***********************************************************************/

Turn(arg)
float arg;
{
 struct Vec ex,ez;
 ex=e.a;
 ez=e.c;
 RotY(&ex,arg);
 RotY(&ez,arg);
 BasisVecProduct(plane,ex,&ex);
 BasisVecProduct(plane,ez,&ez);
 plane.a=ex;
 plane.c=ez;
}


/***********************************************************************/

lesen()
{
     FILE *weser;   /* Deskriptor-Zeiger */
     char text[80];
     int i,j,tester;

     weser=fopen("ram:flug.dat", "r");
     if(!weser)
     {
        printf("***** MFS-Fehler: Keine gültige Flugzeugdefinition ! *****\n");
        exit(50);
     }

                                             /*  Ersma den Kram aus MFS.cfg ! */ 
     fgets(text, 80, weser);
     sscanf(text,"%d",&xScreenm);

     fgets(text, 80, weser);
     sscanf(text,"%d",&xScreenh);

     fgets(text, 80, weser);
     sscanf(text,"%d",&xScreenw);

     fgets(text, 80, weser);
     sscanf(text,"%d",&xScreend);
 
     fgets(text, 80, weser);
     sscanf(text,"%d",&xUhr);
                              
     fgets(text, 80, weser);
     sscanf(text,"%d",&xSense); 
     xJoySens=(float)xSense/100.0;
     printf("xJoysense : %d \n",xSense);

     fgets(text, 80, weser);
     sscanf(text,"%d",&xKanal);

     fgets(text, 80, weser);
     sscanf(text,"%d",&xKaefig);

     fgets(text, 80, weser);
     sscanf(text,"%d",&xJoy); 

     for(i=0; i<=7; i++)
     {
       fgets(text, 80, weser);
       fgets(text, 80, weser);
       sscanf(text,"%d",&RGB[i].rot);
       fgets(text, 80, weser);
       sscanf(text,"%d",&RGB[i].gruen);
       fgets(text, 80, weser);
       sscanf(text,"%d",&RGB[i].blau);
     }

     fgets(text, 80, weser);
     sscanf(text,"%d",&xToggleLX);

     fgets(text, 80, weser);
     sscanf(text,"%d",&xToggleLY);

     fgets(text, 80, weser);
     sscanf(text,"%d",&xToggleRX);

     fgets(text, 80, weser);
     sscanf(text,"%d",&xToggleRY);

                                     /* Es folgt die normale Flusi-Datei ! */
      fgets(text, 80, weser);
      fgets(text, 80, weser);
      sscanf(text,"%d",&xFrei);

      fgets(text, 80, weser);
      fgets(text, 80, weser);
      sscanf(text,"%d",&xFrei);

      fgets(text, 80, weser);
      fgets(text, 80, weser);
      sscanf(text,"%d",&xFrei);

      fgets(text, 80, weser);
      fgets(text, 80, weser);
      sscanf(text,"%d",&xFrei);

      fgets(text, 80, weser);
      fgets(text, 80, weser);
      sscanf(text,"%d",&xFrei);

      fgets(text, 80, weser);
      fgets(text, 80, weser);
      sscanf(text,"%d",&xFrei);

      fgets(text, 80, weser);
      fgets(text, 80, weser);
      sscanf(text,"%d",&xFrei); 

      fgets(text, 80, weser);
      fgets(text, 80, weser);
      sscanf(text,"%d",&xFrei);

      fgets(text, 80, weser);
      fgets(text, 80, weser);
      sscanf(text,"%d",&xFrei);

      fgets(text, 80, weser);
      fgets(text, 80, weser);
      sscanf(text,"%d",&xFrei);

      fgets(text, 80, weser);
      fgets(text, 80, weser);
      sscanf(text,"%d",&xPrg);

      fgets(text, 80, weser);
      fgets(text, 80, weser);
      sscanf(text,"%d",&xLaut);

      fgets(text, 80, weser);
      fgets(text, 80, weser);
      sscanf(text,"%d",&xKnall);

      fgets(text, 80, weser);
      fgets(text, 80, weser);
      sscanf(text,"%d",&xAchs);

      fgets(text, 80, weser);
      fgets(text, 80, weser);
      sscanf(text,"%d",&xSpeed);

      fgets(text, 80, weser);
      fgets(text, 80, weser);
      sscanf(text,"%d",&xBack);

      fgets(text, 80, weser);
      fgets(text, 80, weser);
      sscanf(text,"%d",&xQuer);

      fgets(text, 80, weser);
      fgets(text, 80, weser);
      sscanf(text,"%d",&xHoehe);

      fgets(text, 80, weser);
      fgets(text, 80, weser);
      sscanf(text,"%d",&xSeite);

      fgets(text, 80, weser);
      fgets(text, 80, weser);
      sscanf(text,"%d",&xDrossel);

      fgets(text, 80, weser);
      fgets(text, 80, weser);
      sscanf(text,"%d",&xMotor);

      fgets(text, 80, weser);
      fgets(text, 80, weser);
      sscanf(text,"%d",&xGewicht);
      abtrieb= ((float)-xGewicht);

      fgets(text, 80, weser);
      fgets(text, 80, weser);
      sscanf(text,"%d",&xPower);

      HoeheFak  = xHoehe / HOEHESENS   * xJoySens;
      QuerFak   = xQuer  / QUERSENS    * xJoySens;
      PowerFak  = xPower / DROSSELSENS * xJoySens;
      SeitenFak = xSeite / SEITENSENS  * xJoySens;

      fgets(text, 80, weser);
      fgets(text, 80, weser);
      sscanf(text,"%d",&xWiderstand);
      xReibung=0.00001*(float)xWiderstand;
      reibung = xReibung;

      fgets(text, 80, weser);
      fgets(text, 80, weser);
      sscanf(text,"%d",&FWart);

      fgets(text, 80, weser);
      fgets(text, 80, weser);
      sscanf(text,"%d",&abriss);

/* Farben einlesen : */
     for(i=0; i<=7; i++)
      {
          fgets(text, 80, weser);
          fgets(text, 80, weser);
          sscanf(text,"%d",&RGB[i].rot);
          fgets(text, 80, weser);
          sscanf(text,"%d",&RGB[i].gruen);
          fgets(text, 80, weser);
          sscanf(text,"%d",&RGB[i].blau);
      }

     fgets(text, 80, weser);
     fgets(text, 80, weser);
     sscanf(text,"%d",&polygone);


/* fr Anzahl der Polygone : */
     for(i=1; i<=polygone; i++)
      {
      fgets(text, 80, weser);
      fgets(text, 80, weser);
      sscanf(text,"%d",&polygon[i].ppunkte);

      fgets(text, 80, weser);
      fgets(text, 80, weser);
      sscanf(text,"%d",&polygon[i].pfarbe);

      fgets(text, 80, weser);
      fgets(text, 80, weser);
      sscanf(text,"%d",&polygon[i].pinvfarbe);

      /* fr Anzahl der Polygonpunkte : */
      for(j=1; j<=polygon[i].ppunkte; j++)
          {
          fgets(text, 80, weser);
          fgets(text, 80, weser);
          sscanf(text,"%d",&polygon[i].ppx[j]);

          fgets(text, 80, weser);
          fgets(text, 80, weser);
          sscanf(text,"%d",&polygon[i].ppy[j]);

          fgets(text, 80, weser);
          fgets(text, 80, weser);
          sscanf(text,"%d",&polygon[i].ppz[j]);
          }
      }

     fclose(weser);

}


