unit bumpmap;
{
 enviromental bumpmapping, asm innerloop * quite stylish (IMO - hi bitnik ;)
}
interface
uses routines,playmods,map;

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

      envX = 128;
      envY = 128;

      sinsize = 360;

      gap = 360;
      skip = 4;
      fspeed = 4;

      blurtime : word = 640;
      txts = 2;
      txt : array[1..txts] of string = ('turpakii.map','aelaekys.map');

var spriteseg,envseg,picseg,virseg : word;
    spritescr,envscr,picscr,virscr : pointer;
    loop : word;
    phix,phiy : word;
    stab,ctab : array[0..sinsize] of real;
    lx,ly : integer;
    frames : word;
    feidi : word;
    fadein : word;
    loppu : boolean;
    load : word;
    trackstatus : miscdata;
    orderi : word;
    sframes : word;

procedure do_bumpmap(nosound:boolean);

implementation

procedure do_bumpmap(nosound:boolean);

procedure blursprite; assembler; { k3wl! }
    asm
      mov es,[spriteseg]
      mov di,2
      mov si,128*128-2
      @outer:

          xor ax,ax
          xor bx,bx
          mov al,[es:di+1]
          mov bl,[es:di-1]
          add ax,bx
          shr ax,1
          cmp ax,0
          jz @jump
          dec ax
          @jump:
          mov [es:di],al
          inc di

      dec si
      jne @outer
    end;

procedure bump(src,dest:word);
var vx,vy:integer;
    deltax,deltay:integer;
    nx,ny:integer;
    x,y:word;

begin
  asm
    xor di,di
    mov [y],1
    @y:
      mov [x],1
      add di,2
      @x:
        mov ax,src
        mov es,ax

        mov ax,[x]
        sub ax,[lx]
        mov [deltax],ax
        mov ax,[y]
        sub ax,[ly]
        mov [deltay],ax

        xor ax,ax
        xor bx,bx
        mov al,[es:di+1]
        mov bl,[es:di-1]
        sub ax,bx
        xor bx,bx
        xor cx,cx
        mov bl,[es:di+320]
        mov cl,[es:di-320]
        sub bx,cx

        sub ax,[deltax]
        add ax,64
        sub bx,[deltay]
        add bx,64

        cmp ax,0
        jg @x1
        xor ax,ax
      @x1:
        cmp ax,127
        jl @x2
        mov ax,127
      @x2:
        cmp bx,0
        jg @y1
        xor bx,bx
      @y1:
        cmp bx,127
        jl @y2
        mov bx,127
      @y2:

        shl bx,7
        add bx,ax
        mov ax,envseg { swap ES }
        mov es,ax
        mov al,byte ptr[es:bx]
        mov bx,dest
        mov es,bx
        mov byte ptr[es:di],al { draw to dest (dest:di) }

        inc di
        inc [x]
        cmp [x],319
        jb @x
        inc [y]
        cmp [y],199
        jb @y
  end;
end;

procedure sprite(dest:word;x,y:integer;col:word); assembler;
var sy,sx:integer;
asm
  push ds

  mov cx,[x] { ds:si = piste flaressa }
  mov dx,[y]
  sub cx,64
  sub dx,64 { spriten keskipiste = x,y }
  mov [sx],cx
  mov [sy],dx { es:di (sx,sy) = piste virsegiss„ }

  mov ax,[dest]
  mov es,ax
  mov ax,[spriteseg]
  mov ds,ax

  mov ax,dx { di = sy*320+sx }
  shl ax,6
  mov di,ax
  shl ax,2
  add di,ax
  add di,cx
  xor si,si { si = 0 }
  xor dx,dx { dx pit„„ kirjaa flare X:st„ }

@inner:
  xor bx,bx      { ynn„t„„n ruutu ja sprite-col }
  mov bl,[ds:si]
  sub bx,[col]
  cmp bx,0
  jg @cok
  xor bx,bx
@cok:
  mov al,[es:di]
  add ax,bx      { ax = v„ri }

  cmp ax,256
  jb @cok2
  mov ax,255
@cok2:
  mov [es:di],al

@noPixel:
  inc si { p„ivitet„„n indexit sun muut muuttujat }
  inc di
  inc dx
  inc [sx]
  cmp dx,128
  jnz @skip3 { jos rivi ei lopu viel„, hypp„„ @skip3 }

  xor dx,dx { jos dx = 64 (rivin loppu) niin... }
  mov ax,[x] { sx = x-64 }
  sub ax,64
  mov [sx],ax
  inc [sy]
  add di,320-128 { di hypp„„ rivin alasp„in }

@skip3:
  cmp si,128*128 { lopeta }
  jnz @inner

  pop ds
end;

begin
  cls(vidseg);
  randomize;
  getmem(virscr,320*200);
  virseg:=seg(virscr^);
  cls(virseg);
  getmem(picscr,320*200);
  picseg:=seg(picscr^);
  loadMAP(picseg,'g2.raw');
  getmem(envscr,envX*envY);
  envseg:=seg(envscr^);
  loadMAPe(envseg,'env.map',envX*envY);
  getmem(spritescr,128*128);
  spriteseg:=seg(spritescr^);

  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;

  cls(vidseg);
  loadpal('pal3.pal');
  phix:=0;
  phiy:=0;
  feidi:=0;
  load:=1;
  frames:=0;
  sframes:=0;
  loadMAPe(spriteseg,txt[load],128*128);
  fadein:=256;
  orderi:=$19;
  repeat
    lx:=160+round(stab[phix]*120);
    ly:=100+round(ctab[phiy]*60);
    if phix<sinsize then inc(phix,2) else phix:=0;
    if phiy<sinsize then inc(phiy,3) else phiy:=0;
    bump(picseg,virseg);
    sprite(virseg,xc,yc,fadein);
    if fadein>0 then dec(fadein,2);
  if nosound then begin
    if frames>gap then begin
      if feidi<blurtime then begin
        inc(feidi,fspeed);
        blursprite;
      end else begin
        if load<txts then inc(load) else loppu:=true;
        loadMAPe(spriteseg,txt[load],128*128);
        fadein:=256;
        feidi:=0;
        frames:=0;
      end;
    end;
  end else begin
    inc(sframes);
    if sframes=skip then begin
      get_module_status(trackstatus);
      sframes:=0;
    end;
    if trackstatus[0]=$1C then loppu:=true;
    if trackstatus[0]>=orderi then begin
      if feidi<blurtime then begin
        inc(feidi,fspeed);
        blursprite;
      end else begin
        if load<txts then inc(load);
        loadMAPe(spriteseg,txt[load],128*128);
        fadein:=256;
        feidi:=0;
        orderi:=$1A;
      end;
    end;
  end;
    inc(frames);
    retrace;
    flip(virseg,vidseg);
  until (keypressed)or(loppu);
  flushKB;
  freemem(virscr,320*200);
  freemem(picscr,320*200);
  freemem(envscr,envX*envY);
  freemem(spritescr,128*128);
end;

end.
