uses playmods,routines,map;

const vidseg = $a000;
      maps : array[0..1] of string =('kilobite','escape2k');
      treshold : word = 16;
      nosound : boolean = true;

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

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]
  cmp al,0
  jz @jumpPixel
  cmp al,127
  jb @over
  mov es,[virseg]
  mov [es:di],al
  jmp @jumpPixel
@over:

  mov es,[virseg]
  mov ax,[lx]
  sub ax,[x]
  cmp ax,0
  jg @jump1
  neg ax
@jump1:
  mov [deltax],ax
  cmp ax,63
  ja @jumpPixel

  mov ax,[ly]
  sub ax,[y]
  cmp ax,0
  jg @jump2
  neg ax
@jump2:
  mov [deltay],ax
  cmp ax,63
  ja @jumpPixel

  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 }
  cmp bx,255
  jb @jump3
  mov bx,255 { bx < 256 }
@jump3:

  xor ax,ax
  mov es,[picseg] { nopee ES vaihto }
  mov al,byte ptr[es:di]
  mov es,[virseg]
  sub ax,bx
  cmp ax,0
  jg @jump4
  xor ax,ax
@jump4:
  mov [es:di],al
  jmp @pixel
@jumpPixel:
  xor ax,ax
  mov [es:di],al
@pixel:

  inc di
  inc [x]
  cmp [x],320
  jb @jump5
  mov [x],0
  inc [y]
@jump5:
  cmp [y],199
  jb @inner
end;

procedure edges; assembler;
asm
  xor di,di
  mov cx,64000
@inner:
  mov es,[picseg]
  mov bl,[es:di]
  cmp bl,255
  jnz @jumpPixel
  mov es,[fireseg]
  mov al,[es:di]
  add al,128
  mov es,[virseg]
  mov [es:di],al
@jumpPixel:
  inc di
  dec cx
  jne @inner
end;

procedure fire;
begin
    for x:=6 to 314 do
      pixelw((320*140)+x,random(127),fireseg);
    for x:=6 to 314 do
      pixelw((320*141)+x,random(127),fireseg);
    asm
      mov es,[fireseg]
      xor ax,ax
      xor bx,bx
      mov di,320*80
      mov si,320*60
      @inner:
          mov al,[es:di+319]
          mov bl,[es:di+320]
          add ax,bx
          mov bl,[es:di+321]
          add ax,bx
          mov bl,[es:di+640]
          add ax,bx

          shr ax,2        { div by 4 - average of pixels }
          cmp ax,1
          jb @jump
          dec ax
          @jump:
          mov [es:di],al  { set the pixel }
          inc di          { increase the offset }

      dec si
      jne @inner
    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 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^);
  getmem(firescr,64000);
  fireseg:=seg(firescr^);
  cls(virseg);
  cls(vidseg);
  cls(fireseg);
  load:=0;
  mode($13);
  loadMAP(picseg,maps[load]+'.map');
  loadPAL(maps[load]+'.pal');
  for loop:=0 to 255 do ctab[loop]:=cos(loop*pi/128);
  for loop:=0 to 255 do stab[loop]:=sin(loop*pi/128);
  xphi:=0; yphi:=0;
  rounds:=0;
  loppu:=false;
  palOK:=false;
  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;
  repeat
    fire;
    lightx:=160+round(stab[xphi]*195);
    lighty:=100+round(ctab[yphi]*40);
    inc(yphi,3);
    inc(xphi);
    light(lightx,lighty);
    edges;
    if nosound then begin
      if xphi=0 then inc(rounds);
      if (rounds=1)and(xphi>127) then fadeout;
      if rounds=2 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=5 then loppu:=true;
    end;
    retrace;
    if not palOK then fadein;
    flip(virseg,vidseg);
  until (keypressed)or(loppu);
  mode(3);
  freemem(virscr,64000);
  freemem(picscr,64000);
  freemem(firescr,64000);
end.