unit alku;

interface
uses playmods,routines,map;

const vidseg = $a000;
      maps : array[0..1] of string =('kilobite','escape2k');
      skip = 4;
      sinsize = 360;

var picseg,virseg : word;
    picscr,virscr : pointer;
    loop : word;
    lightx,lighty : word;
    intensity : word;
    stab,ctab : array[0..sinsize] of real;
    xphi,yphi : word;
    rounds : byte;
    loppu : boolean;
    load : byte;
    pal : array[0..255,1..3] of byte;
    palOK : boolean;
    nosound : boolean;
    status : miscdata;
    frames : word;

procedure do_alku(nosound:boolean);

implementation
procedure do_alku(nosound:boolean);

{ hifi mega-procedure does >100 functions to virseg at once :/ }
procedure light(lx,ly:word); assembler;
var deltax,deltay:word;
    x,y:word;

asm
  xor di,di
  mov [x],0
  mov [y],0

@inner:
  mov es,[picseg]
  mov al,[es:di]
  { if color = 0 tahi 128 (musta) then jump handleri ja piirr„ v„ri 0 }
  cmp al,0
  jz @zeroPixel
  cmp al,127
  ja @zeroPixel

  mov es,[virseg]
  mov ax,[lx]
  sub ax,[x]
  cmp ax,0
  jg @posX
  neg ax
@posX:
  mov [deltax],ax
  cmp ax,63
  ja @zeroPixel { jos deltax > 63, piirr„ 0 }

  mov ax,[ly]
  sub ax,[y]
  cmp ax,0
  jg @posY
  neg ax
@posY:
  mov [deltay],ax
  cmp ax,63 { sama -> deltay }
  ja @zeroPixel

  mul ax { mullit hidastaa, muttei liiqaa }
  mov bx,ax
  mov ax,[deltax]
  mul ax
  add bx,ax { bx = deltax'2 + deltay'2 }
  shr bx,4  { neli”juuri on v*tun hidas, t„„ toimii }
  cmp bx,255
  jb @byteL
  mov bx,255 { bx < 256 }
@byteL:

  xor ax,ax
  mov es,[picseg] { nopee ES vaihto }
  mov al,byte ptr[es:di]
  mov es,[virseg]
  sub ax,bx { picsegin pixeli - valo }
  cmp ax,0
  jg @pixel
  xor ax,ax
@pixel: { draw what's in al to es }
  mov [es:di],al
  jmp @pixelDrawn

@zeroPixel:
  xor ax,ax
  mov [es:di],al

@pixelDrawn:
  inc di
  inc [x]
  cmp [x],320
  jb @noLineChange
  mov [x],0
  inc [y]
@noLineChange:
  cmp [y],199
  jb @inner
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 inc(r);
    if g<pal[loop,2] then inc(g);
    if b<pal[loop,3] then inc(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;

procedure fadeout;
var r,g,b:byte;
    cols:byte;
begin
  for loop:=0 to 255 do begin
    port[$3c7]:=loop;
    r:=port[$3c9];
    g:=port[$3c9];
    b:=port[$3c9];
    if r>0 then dec(r);
    if g>0 then dec(g);
    if b>0 then dec(b);
    port[$3c8]:=loop;
    port[$3c9]:=r;
    port[$3c9]:=g;
    port[$3c9]:=b;
  end;
end;

begin
  randomize;
  getmem(virscr,64000);
  virseg:=seg(virscr^);
  getmem(picscr,64000);
  picseg:=seg(picscr^);
  cls(virseg);
  cls(vidseg);
  load:=0;
  loadMAP(picseg,maps[load]+'.map');
  loadPAL(maps[load]+'.pal');
  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));
  xphi:=0; yphi:=0;
  rounds:=0;
  loppu:=false;
  palOK:=false;
  frames:=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,0,0,0);
{  for loop:=0 to 40 do fire; { pre-fire }
  repeat
    lightx:=160+round(stab[xphi]*160);
    lighty:=100+round(ctab[yphi]*100);
    if yphi<sinsize then inc(yphi) else yphi:=0;
    if xphi<sinsize then inc(xphi,2) else xphi:=0;
    light(lightx,lighty);

    if nosound then begin
      if xphi=0 then inc(rounds);
      if (rounds=3)and(xphi>127) then fadeout;
      if (rounds=7)and(xphi>127) then fadeout;
      if rounds=4 then begin
        inc(load);
        cls(vidseg);
        cls(virseg);
        loadMAP(picseg,maps[load]+'.map');
        loadPAL(maps[load]+'.pal');
        inc(rounds);
        for loop:=0 to 255 do setcol(loop,0,0,0);
        palOK:=false;
      end;
      if rounds=8 then loppu:=true;

    end else if frames=skip then begin
      frames:=0;
      get_module_status(status);
      if (status[0]=4)and(load=0) then begin
        inc(load);
        cls(vidseg);
        cls(virseg);
        loadMAP(picseg,maps[load]+'.map');
        for loop:=0 to 255 do setcol(loop,0,0,0);
        palOK:=false;
      end;
      if status[0]=3 then fadeout;
      if status[0]=7 then fadeout;
      if status[0]=8 then loppu:=true;
    end;
    inc(frames);

    retrace;
    if not palOK then fadein;
    flip(virseg,vidseg);
  until (keypressed)or(loppu);
  flushKB;
  freemem(virscr,64000);
  freemem(picscr,64000);
end;

end.