unit title;

interface
uses playmods,routines,map;

const vidseg = $a000;
      points = 18;
      cam = 256;
      xsize = 32;
      ysize = 32;
      xrange = 50;
      yrange = 50;
      zwr = 12;
      gap = 128;
      skip = 4;

var virseg,flareseg,bgseg : word;
    virscr,flarescr,bgscr : pointer;
    loop : word;
    stab,ctab : array[0..255] of real;
    sd : real;
    phi,sphi : byte;
    point : array[1..points,1..3] of integer;
    trans : array[1..points,1..3] of integer;
    palloZ,palloX,palloY : integer;
    subbi : word;
    lphi : byte;
    zphi : byte;
    randx,randy : integer;
    pal : array[0..255,1..3] of byte;
    palOK : boolean;
    frames : word;
    loppu : boolean;
    trackstatus : miscdata;

procedure do_title(nosound:boolean);
implementation

procedure do_title(nosound:boolean);

procedure rotate;
const phi_inc = 1;

var x,y,z : integer;
    sini,kosi : real;

begin
  for loop:=1 to points do begin
    x := point[loop,1];
    y := point[loop,2];
    z := point[loop,3];
    sini := stab[phi];
    kosi := ctab[phi];
{
                   Ú                                      ¿
                   ³ 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 ³
                   À                                      Ù
               Ú          ¿   Ú          ¿   Ú                  ¿
               ³ 1  0  0  ³   ³ cy 0 -sy ³   ³ cy     0  -sy    ³
     [X]*[Y] = ³ 0  cx sx ³ * ³ 0  1  0  ³ = ³ sx*sy  cx  sx*cy ³
               ³ 0 -sx cx ³   ³ sy 0  cy ³   ³ cx*sy -sx  cx*cy ³
               À          Ù   À          Ù   À                  Ù
}

    trans[loop,1]:=round((kosi*x)+(sini*sini*y)+(kosi*sini*z));
    trans[loop,2]:=round((kosi*y)+(-sini*z));
    trans[loop,3]:=round((-sini*x)+(sini*kosi*y)+(kosi*kosi*z));
{
    trans[loop,1]:=round((kosi*kosi*x)+((sini*sini*kosi*y)-(kosi*sini*y))+
                         ((kosi*sini*kosi*z)+(sini*sini*z)));
    trans[loop,2]:=round((kosi*sini*x)+((sini*sini*sini*y)+(kosi*kosi*y))+
                         ((kosi*sini*sini*z)-(sini*kosi*z)));
    trans[loop,3]:=round((-sini*x)+(sini*kosi*y)+(kosi*kosi*z));
}
  end;
  if phi<255-phi_inc then inc(phi,phi_inc) else phi:=0;
end;

procedure piirraPallot(x,y,z:integer);
var sx,sy:integer;
    px,py,pz:integer;
    temp:integer;
    col:integer;
    p:byte;

begin
  for p:=1 to points do begin
    px:=trans[p,1];
    py:=trans[p,2];
    pz:=trans[p,3];
    if z-pz <> 0 then begin
      sx:=round(cam*px / (z-pz) + x);
      sy:=round(cam*py / (z-pz) + y);
      sprite(sx,sy);
    end;
  end;
end;

procedure motionblur; assembler;
    asm
      mov es,[virseg]
      xor ax,ax
      xor bx,bx
      mov di,320
      mov si,320*198
      @outer:

          mov al,[es:di+1]
          mov bl,[es:di-1]
          add ax,bx

          shr ax,1
{          cmp ax,1
          jl @jump1
          sub ax,1
          @jump1: }
          mov [es:di],al
          inc di

      dec si
      jne @outer
    end;

procedure wavez;
begin
  sphi:=round(sd*lphi) shr 2;
  zphi:=sphi shl 1;
  for loop:=1 to points do begin
    point[loop,3]:=round(stab[zphi]*zwr);
    sphi:=round(sphi+sd);
    zphi:=sphi shl 1;
    if sphi>255 then sphi:=0;
    if zphi>255 then zphi:=0;
  end;
end;

procedure fadein;
var r,g,b:byte;
    cols:byte;
begin
  cols:=0;
  for loop:=0 to 255 do begin
    port[$3c7]:=loop;
    r:=port[$3c9];
    g:=port[$3c9];
    b:=port[$3c9];
    if r>pal[loop,1] then dec(r);
    if g>pal[loop,2] then dec(g);
    if b>pal[loop,3] then dec(b);
    if (r<>pal[loop,1])or(g<>pal[loop,2])or(b<>pal[loop,3]) then inc(cols);
    port[$3c8]:=loop;
    port[$3c9]:=r;
    port[$3c9]:=g;
    port[$3c9]:=b;
  end;
  if cols=0 then palOK:=true;
end;

begin
  randomize;
  getmem(virscr,64000);
  virseg:=seg(virscr^);
  getmem(bgscr,64000);
  bgseg:=seg(bgscr^);
  loadMAP(bgseg,'godspeed.map');
  for loop:=0 to 255 do ctab[loop]:=cos(loop*pi/128);
  for loop:=0 to 255 do stab[loop]:=sin(loop*pi/128);
  sd := 255 / points;
  sphi:=0;
  zphi:=0;
  for loop:=1 to points do begin
    point[loop,1]:=round(ctab[sphi]*xrange);
    point[loop,2]:=round(stab[sphi]*yrange);
    point[loop,3]:=0;
    sphi:=round(sphi+sd);
  end;
  cls(vidseg);
  loadpal('pal1.pal');
  phi:=0;
  palloZ:=256;
  PalloX:=160;
  PalloY:=100;
  cls(virseg);
  subbi:=2;
  lphi:=0;
  for loop:=0 to 255 do
    begin
      port[$3c7]:=loop;
      pal[loop,1]:=port[$3c9];
      pal[loop,2]:=port[$3c9];
      pal[loop,3]:=port[$3c9];
    end;
  for loop:=0 to 255 do setcol(loop,63,63,63);
  frames:=0;
  palOK:=false;
  flip(bgseg,virseg);
  loppu:=false;
  nosound:=false;
  repeat
    wavez;
    rotate;
    motionblur;
    if nosound then begin
      if frames=gap then begin
        frames:=0;
        flip(bgseg,virseg);
      end;
    end else begin
      get_track_status(19,trackstatus);
      if trackstatus[7]=0 then flip(bgseg,virseg);
      if frames=skip then begin
        get_module_status(trackstatus);
        if trackstatus[0]=12 then loppu:=true;
        frames:=0;
      end;
    end;
    inc(frames);
    retrace;
    if not palOK then fadein;
    flip(virseg,vidseg);
  until (keypressed)or(loppu);
  freemem(virscr,64000);
  freemem(bgscr,64000);
end;

end.