uses routines,playmods,map,polygons,laatta;

const vidseg = $a000;
      zf = 256;
      zc = 256;
      xc = 160;
      yc = 100;

      ylevel = 0;
      xlevel = 0;
      zlevel = 0;

      zmove = 1;
      ambient = 255;
      xinc = 32;
      yinc = 0;
      zinc = 0;

      sinsize = 255;
      xraja = 63;

      skip = 4;

var virseg : word;
    virscr : pointer;
    loop : word;
    ox,oy,oz : integer;
    stab,ctab : array[0..sinsize] of real;
    trans : array[1..points,1..3] of integer;
    pal : array[0..255,1..3] of byte;
    xphi,yphi,zphi : integer;
    palOK : boolean;
    frames : word;
    loppu : boolean;
    trackstatus : miscdata;
    status : miscdata;
    pphi : array[1..points] of word;

procedure rotate;

var x,y,z : integer;
    sinix,kosix,
    siniy,kosiy,
    siniz,kosiz : real;

begin
  sinix := stab[xphi shr 8];
  kosix := ctab[xphi shr 8];
  siniy := stab[yphi shr 8];
  kosiy := ctab[yphi shr 8];
  siniz := stab[zphi shr 8];
  kosiz := ctab[zphi shr 8];
  for loop:=1 to points do begin
    x := point[loop,1];
    y := point[loop,2];
    z := point[loop,3];
{
                   Ú                                      ¿
                   ³ cy*cz          cy*sz          -sy    ³
     [X]*[Y]*[Z] = ³ sx*sy*cz-cx*sz sx*sy*sz+cx*cz  sx*cy ³
                   ³ cx*sy*cz+sx*sz cx*sy*sz-sx*cz  cx*cy ³
                   À                                      Ù
}
    trans[loop,1]:=round((kosiy*kosiz*x)+((sinix*siniy*kosiz*y)-(kosix*siniz*y))+
                         ((kosix*siniy*kosiz*z)+(sinix*siniz*z)));
    trans[loop,2]:=round((kosiy*siniz*x)+((sinix*siniy*siniz*y)+(kosix*kosiz*y))+
                         ((kosix*siniy*siniz*z)-(sinix*kosiz*z)));
    trans[loop,3]:=round((-siniy*x)+(sinix*kosiy*y)+(kosix*kosiy*z));
  end;
  if xphi shr 8<xraja then xphi:=xphi+xinc else {xphi:=0};
  if yphi shr 8<sinsize then yphi:=yphi+yinc else yphi:=0;
  if zphi shr 8<sinsize then zphi:=zphi+zinc else zphi:=0;
end;

procedure DrawObj;
var f,p : word;
    dx,dy,dz : integer;
    sx,sy : array[1..3] of integer;
    c : array[1..3] of byte;

function inrange(value:integer):byte;
begin
  if value<0 then inrange:=0;
  if value>255 then inrange:=255;
end;

begin
  { ei tartte sorttia }
  for f:=1 to faces do begin
    for p:=1 to 3 do begin
{      gx = x * 256 / z + 160 ; keskipiste = ruudun keskipiste
       gy = y * 256 / z + 100 ; (320x200-tila) }
      dx:=ox+trans[face[f,p],1];
      dy:=oy+trans[face[f,p],2];
      dz:=oz+trans[face[f,p],3];
      if dz=256 then dz:=257; { aika n0l0 ;}
      sx[p]:=round(dx shl 8 / (zf-dz)) + xc;
      sy[p]:=round(dy shl 8 / (zf-dz)) + yc;
      c[p]:=inrange(255);
    end;
    if c[1]+c[2]+c[3]>0 then
    gouraud_poly_real(virseg,sx[1],sy[1],
                             sx[2],sy[2],
                             sx[3],sy[3],
                             c[1],c[2],c[3]);
  end;
end;

procedure NullObject;
var f,h,w,p:word;
begin
  xphi:=0;
  yphi:=0;
  zphi:=0;
  ox:=0; oy:=0;
  oz:=-1024;
end;

begin
  cls(vidseg);
  randomize;
  getmem(virscr,320*200);
  virseg:=seg(virscr^);

  for loop:=0 to sinsize do ctab[loop]:=cos(loop*pi/(sinsize div 2));
  for loop:=0 to sinsize do stab[loop]:=sin(loop*pi/(sinsize div 2));

  loppu:=false;
  mode($13);
  loadpal('pal1.pal');
  for loop:=0 to 255 do setcol(loop,63-(loop div 4),63,63-(loop div 4));
  nullObject;
  repeat
    rotate;
    if oz<0 then inc(oz,2);
    cls(virseg);
    drawobj;
    retrace;
    flip(virseg,vidseg);
  until (keypressed)or(loppu);
  freemem(virscr,320*200);
end.

