unit ublob;

interface

procedure BLOB_INIT;
procedure BLOB_ACTION;
procedure BLOB_CLOSE;

implementation

uses
  video,grafix,crt,usm;

type
  TIBlob=array[0..16383] of byte;
  PIBlob=^TIBlob;
  Tbuffer=array[0..63999] of integer;
  PBuffer=^TBuffer;
  Tcredit=array[0..15999] of byte;
  Pcredit=^Tcredit;
  Tsint=array[0..719] of real;
  Psint=^Tsint;
  Pcost=^Tsint;

var
  Cdreamer,Ckid,Ccharlie,Cmrc,Czoom:Pcredit;
  Cmusic,Cgfx,Ccode,Ccodegfx:Pcredit;
  blob_buffer:Pbuffer;
  sint:psint;
  cost:pcost;
  IBlob:PIBlob;
  korder,vorder,aorder,row:byte;
  TERM:boolean;

procedure alloc;
begin
  new(blob_buffer);
  new(IBlob);
  new(sint);
  new(cost);
  new(Cdreamer);
  new(Cmrc);
  new(Ccharlie);
  new(Ckid);
  new(CZoom);
  new(Cmusic);
  new(Cgfx);
  new(Ccode);
  new(Ccodegfx);
end;

procedure dealloc;
begin
  dispose(blob_buffer);
  dispose(IBlob);
  dispose(sint);
  dispose(cost);
  dispose(Cdreamer);
  dispose(Cmrc);
  dispose(Ccharlie);
  dispose(Ckid);
  dispose(CZoom);
  dispose(Cmusic);
  dispose(Cgfx);
  dispose(Ccode);
  dispose(Ccodegfx);
end;

procedure maketables;
var
  a:word;
begin
  for a:=0 to 719 do begin
    sint^[a]:=sin(a*pi/180);
    cost^[a]:=cos(a*pi/180);
  end;
end;

{$i-}
procedure loadmaps;
var
  f:file;
  filename:string[12];

  procedure notfound;
  begin
    writeln('File ',filename,' not found');
    dealloc;
    halt;
  end;

  procedure fileerr;
  begin
    writeln('Error in file ',filename);
    dealloc;
    halt;
  end;

begin
  filename:='blob_blb.dat';
  assign(f,filename);
  reset(f,1);
  if ioresult<>0 then notfound;
  blockread(f,iblob^,16384);
  if ioresult<>0 then fileerr;
  close(f);
  filename:='blob_kid.dat';
  assign(f,filename);
  reset(f,1);
  if ioresult<>0 then notfound;
  blockread(f,Ckid^,12000);
  if ioresult<>0 then fileerr;
  close(f);
  filename:='blob_mrc.dat';
  assign(f,filename);
  reset(f,1);
  if ioresult<>0 then notfound;
  blockread(f,Cmrc^,12000);
  if ioresult<>0 then fileerr;
  close(f);
  filename:='blob_drm.dat';
  assign(f,filename);
  reset(f,1);
  if ioresult<>0 then notfound;
  blockread(f,Cdreamer^,12000);
  if ioresult<>0 then fileerr;
  close(f);
  filename:='blob_cha.dat';
  assign(f,filename);
  reset(f,1);
  if ioresult<>0 then notfound;
  blockread(f,Ccharlie^,12000);
  if ioresult<>0 then fileerr;
  close(f);
  filename:='blob_zom.dat';
  assign(f,filename);
  reset(f,1);
  if ioresult<>0 then notfound;
  blockread(f,CZoom^,12000);
  if ioresult<>0 then fileerr;
  close(f);
  filename:='blob_gfx.dat';
  assign(f,filename);
  reset(f,1);
  if ioresult<>0 then notfound;
  blockread(f,Cgfx^,12000);
  if ioresult<>0 then fileerr;
  close(f);
  filename:='blob_cod.dat';
  assign(f,filename);
  reset(f,1);
  if ioresult<>0 then notfound;
  blockread(f,Ccode^,12000);
  if ioresult<>0 then fileerr;
  close(f);
  filename:='blob_mus.dat';
  assign(f,filename);
  reset(f,1);
  if ioresult<>0 then notfound;
  blockread(f,Cmusic^,12000);
  if ioresult<>0 then fileerr;
  close(f);
  filename:='blob_cgf.dat';
  assign(f,filename);
  reset(f,1);
  if ioresult<>0 then notfound;
  blockread(f,Ccodegfx^,12000);
  if ioresult<>0 then fileerr;
  close(f);
end;
{$i+}

procedure clearbuffer; assembler;
asm
  mov edi,[blob_buffer]
  mov eax,$800080
  mov ecx,32000
  rep stosd
end;

procedure copybuffer; assembler;
asm
  mov esi,[blob_buffer]
  mov edi,[video_SCREEN]
  mov ecx,64000
 @l0:
  lodsw
  cmp ax,$8000
  jb @nemneg
  mov eax,$ff00
  jmp @kirak
 @nemneg:
  cmp ax,256
  jb @nemsok
  mov eax,$ff00ff
  jmp @kirak
 @nemsok:
  cmp al,128
  jae @piros
  mov bl,127
  sub bl,al
  mov ah,bl
  shl ah,1
  xor al,al
  mov bx,ax
  ror eax,16
  mov ax,bx
  jmp @kirak
 @piros:
  mov bl,128
  sub al,bl
  shl al,1
  xor ah,ah
  mov bx,ax
  ror eax,16
  mov ax,bx
 @kirak:
  stosd
  loop @l0
end;

procedure convertimage(image:pointer;size:dword);
begin
  asm
    mov esi,[image]
    mov edi,[image]
    mov eax,4
    mov ebx,size
    dec ebx
    mul ebx
    add edi,eax
    mov eax,3
    mul ebx
    add esi,eax
    mov ecx,size
   @loop0:
    mov eax,[esi]
    mov bh,ah
    ror eax,16
    mov ah,bh
    mov [edi],eax
    sub esi,3
    sub edi,4
    loop @loop0
  end;
end;

procedure putimagea(x,y,sx,sy:longint;source:pointer;fade:byte);
label
  quit;
var
  x1,x2,y1,y2:longint;
{  i,j:longint;}
  r,g,b:byte;
begin
  if x>319 then goto quit;
  if y>199 then goto quit;
  if (sx+x)<0 then goto quit;
  if (sy+y)<0 then goto quit;
  if x<0 then x1:=0-x else x1:=0;
  if y<0 then y1:=0-y else y1:=0;
  if (x+sx)>319 then x2:=319-x else x2:=sx-1;
  if (y+sy)>199 then y2:=199-y else y2:=sy-1;
      asm
        mov edx,y1

       @loopy:
        mov ecx,x1
        push edx

        mov esi,[source]
        mov eax,edx
        mul sx
        add eax,ecx
        mov ebx,3
        mul ebx
        add esi,eax

        pop edx
        push edx
        mov edi,[Video_SCREEN]
        mov eax,320
        mov ebx,y
        add ebx,edx
        mul ebx
        add eax,x
        add eax,ecx
        shl eax,2
        add edi,eax

        pop edx
       @loopx:
        mov eax,[esi]
        add esi,3

        mov bl,fade
        sub al,bl
        jnc @ok0
        mov al,0
       @ok0:
        sub ah,bl
        jnc @ok1
        mov ah,0
       @ok1:
        mov bh,ah
        ror eax,16
        sub al,bl
        jnc @ok2
        mov al,0
       @ok2:
        mov ah,bh
        mov ebx,[edi]
        add al,bl
        jnc @ok3
        mov al,255
       @ok3:
        add ah,bh
        jnc @ok4
        mov ah,255
       @ok4:
        ror eax,16
        ror ebx,16
        add al,bl
        jnc @ok5
        mov al,255
       @ok5:
        ror eax,16
        stosd

        inc ecx
        cmp ecx,x2
        jbe @loopx

        inc edx
        cmp edx,y2
        jbe @loopy
      end;
  quit:
end;

{procedure putimagea(x,y,sx,sy:longint;source:pointer;fade:byte);
label
  quit;
var
  x1,x2,y1,y2:longint;
begin
  if x>319 then goto quit;
  if y>199 then goto quit;
  if (sx+x)<0 then goto quit;
  if (sy+y)<0 then goto quit;
  if x<0 then x1:=0-x else x1:=0;
  if y<0 then y1:=0-y else y1:=0;
  if (x+sx)>319 then x2:=319-x else x2:=sx-1;
  if (y+sy)>199 then y2:=199-y else y2:=sy-1;
      asm
        pushad
        mov ebx,y1
        mov ecx,x1
        mov esi,[source]
        mov eax,sx
        mul ebx
        add eax,ecx
        shl eax,2
        add esi,eax

        mov edi,[video_SCREEN]
        mov eax,320
        add ebx,Y
        mul ebx
        add eax,ecx
        add eax,X
        shl eax,2
        add edi,eax

        mov edx,y1
        mov ecx,x2
        SUB ECX,X1
        INC ECX
        MOV EBX,ECX
       @loopx:
        lodsd
        mov bl,fade
        sub al,bl
        jnc @ok0
        mov al,0
       @ok0:
        sub ah,bl
        jnc @ok1
        mov ah,0
       @ok1:
        ror eax,16
        sub al,bl
        jnc @ok2
        mov al,0
       @ok2:
        ror eax,16
        mov ebx,[edi]
        add al,bl
        jnc @ok3
        mov al,255
       @ok3:
        add ah,bh
        jnc @ok4
        mov ah,255
       @ok4:
        ror eax,16
        ror ebx,16
        add al,bl
        jnc @ok5
        mov al,255
       @ok5:
        ror eax,16
        stosd
        LOOP @LOOPX

        mov ecx,x2
        SUB ECX,X1
        INC ECX
        MOV EAX,320
        SUB EAX,EcX
        SHL EAX,2
        ADD EDI,EAX

        inc edx
        cmp edx,y2
        jbe @loopX

        popad
      end;
  quit:
end;}

procedure putblob(x,y:longint;source:pointer;sign:boolean);
label
  quit;
var
  x1,x2,y1,y2:longint;
  i,j:longint;
  sx,sy:longint;
begin
  sx:=128;
  sy:=128;
  if x>319 then goto quit;
  if y>199 then goto quit;
  if (sx+x)<0 then goto quit;
  if (sy+y)<0 then goto quit;
  if x<0 then x1:=0-x else x1:=0;
  if y<0 then y1:=0-y else y1:=0;
  if (x+sx)>319 then x2:=319-x else x2:=sx-1;
  if (y+sy)>199 then y2:=199-y else y2:=sy-1;
  if sign=false then
    asm
        mov edx,y1

       @loopy:
        mov ecx,x1
        push edx

        mov edi,[blob_buffer]
        mov eax,320
        mov ebx,y
        add ebx,edx
        mul ebx
        add eax,x
        add eax,ecx
        shl eax,1
        add edi,eax

        pop edx
        push edx
        mov esi,[source]
        mov eax,edx
        mov ebx,sx
        mul ebx
        add eax,ecx
        add esi,eax

        pop edx
       @loopx:
        lodsb
        shr al,1
        xor ah,ah
        mov bx,[edi]
        add ax,bx
        stosw

        inc ecx
        cmp ecx,x2
        jbe @loopx

        inc edx
        cmp edx,y2
        jbe @loopy
    end else
    asm
        mov edx,y1

       @loopy:
        mov ecx,x1
        push edx

        mov edi,[blob_buffer]
        mov eax,320
        mov ebx,y
        add ebx,edx
        mul ebx
        add eax,x
        add eax,ecx
        shl eax,1
        add edi,eax

        pop edx
        push edx
        mov esi,[source]
        mov eax,edx
        mov ebx,sx
        mul ebx
        add eax,ecx
        add esi,eax

        pop edx
       @loopx:
        lodsb
        shr al,1
        xor ah,ah
        mov bx,[edi]
        sub bx,ax
        mov ax,bx
        stosw

        inc ecx
        cmp ecx,x2
        jbe @loopx

        inc edx
        cmp edx,y2
        jbe @loopy
    end;
  quit:
end;

{procedure putblob(x,y:longint;source:pointer;sign:boolean); assembler;
asm
        mov esi,[source]
        mov edi,[blob_buffer]
        mov eax,320
        mul y
        add eax,x
        shl eax,1
        add edi,eax
        xor edx,edx
        xor eax,eax
        mov al,sign
        cmp al,0
        jne @loopsor01
       @loopsor0:
        mov ecx,128
       @loopsor:
        lodsb
        shr al,1
        add [edi],ax
        add edi,2
        loop @loopsor
        add edi,384
        inc edx
        cmp edx,128
        jb @loopsor0
        jmp @exit
       @loopsor01:
        mov ecx,128
       @loopsor1:
        lodsb
        shr al,1
        sub [edi],ax
        add edi,2
        loop @loopsor1
        add edi,384
        inc edx
        cmp edx,128
        jb @loopsor01
       @exit:
end;
 }
procedure render;
var
  o:longint;
begin
  clearbuffer;
  o:=counter mod 360;
  putblob(96+round(cost^[o]*90),36+round(sint^[o]*25),iblob,true);
  putblob(105-round(cost^[o+100]*40),20+round(sint^[o]*50),iblob,true);
  putblob(80+round(cost^[o]*70),39-round(sint^[o]*30),iblob,true);
  putblob(80-round(cost^[o+150]*50),40-round(sint^[o+200]*25),iblob,true);
  putblob(110+round(cost^[o+200]*70),44+round(sint^[o]*25),iblob,false);
  putblob(100+round(cost^[o]*80),40-round(sint^[o+150]*20),iblob,false);
  putblob(105-round(cost^[o]*60),50-round(sint^[o]*20),iblob,false);
  putblob(90+round(cost^[o+90]*80),45-round(sint^[o]*20),iblob,false);
  copybuffer;
  if counter<128 then fadeup(255-counter*2);
  if (counter>=520) and (counter<648) then fadeup(127-(counter-520));
  if (counter>=1124) and (counter<1380) then fadedown(counter-1124);

  if (counter>=170) and (counter<230) then
    putimagea(-160+round(sin((counter-170)*1.5*pi/180)*240),70,160,25,Cmrc,0);
  if (counter>=230) and (counter<290) then
    putimagea(80,70,160,25,Cmrc,0);
  if (counter>=290) and (counter<350) then
    putimagea(80+round(sin((counter-290)*1.5*pi/180)*240),70,160,25,Cmrc,0);

  if (counter>=220) and (counter<280) then
    putimagea(-160+round(sin((counter-220)*1.5*pi/180)*240),100,160,25,Ccodegfx,0);
  if (counter>=280) and (counter<310) then
    putimagea(80,100,160,25,Ccodegfx,0);
  if (counter>=310) and (counter<370) then
    putimagea(80+round(sin((counter-310)*1.5*pi/180)*240),100,160,25,Ccodegfx,0);

  if (counter>=350) and (counter<410) then
    putimagea(-160+round(sin((counter-350)*1.5*pi/180)*240),70,160,25,Ccharlie,0);
  if (counter>=410) and (counter<470) then
    putimagea(80,70,160,25,Ccharlie,0);
  if (counter>=470) and (counter<530) then
    putimagea(80+round(sin((counter-470)*1.5*pi/180)*240),70,160,25,Ccharlie,0);

  if (counter>=400) and (counter<460) then
    putimagea(-160+round(sin((counter-400)*1.5*pi/180)*240),100,160,25,Ccode,0);
  if (counter>=460) and (counter<490) then
    putimagea(80,100,160,25,Ccode,0);
  if (counter>=490) and (counter<550) then
    putimagea(80+round(sin((counter-490)*1.5*pi/180)*240),100,160,25,Ccode,0);

  if (counter>=690) and (counter<750) then
    putimagea(-160+round(sin((counter-690)*1.5*pi/180)*240),70,160,25,Cdreamer,0);
  if (counter>=750) and (counter<810) then
    putimagea(80,70,160,25,Cdreamer,0);
  if (counter>=810) and (counter<870) then
    putimagea(80+round(sin((counter-810)*1.5*pi/180)*240),70,160,25,Cdreamer,0);

  if (counter>=740) and (counter<800) then
    putimagea(-160+round(sin((counter-740)*1.5*pi/180)*240),100,160,25,Cmusic,0);
  if (counter>=800) and (counter<830) then
    putimagea(80,100,160,25,Cmusic,0);
  if (counter>=830) and (counter<890) then
    putimagea(80+round(sin((counter-830)*1.5*pi/180)*240),100,160,25,Cmusic,0);

  if (counter>=870) and (counter<930) then
    putimagea(-160+round(sin((counter-870)*1.5*pi/180)*240),70,160,25,Ckid,0);
  if (counter>=930) and (counter<990) then
    putimagea(80,70,160,25,Ckid,0);
  if (counter>=990) and (counter<1050) then
    putimagea(80+round(sin((counter-990)*1.5*pi/180)*240),70,160,25,Ckid,0);

  if (counter>=920) and (counter<980) then
    putimagea(-160+round(sin((counter-920)*1.5*pi/180)*240),100,160,25,Cgfx,0);
  if (counter>=980) and (counter<1010) then
    putimagea(80,100,160,25,Cgfx,0);
  if (counter>=1010) and (counter<1070) then
    putimagea(80+round(sin((counter-1010)*1.5*pi/180)*240),100,160,25,Cgfx,0);

  if (counter>=1030) and (counter<1090) then
    putimagea(-160+round(sin((counter-1030)*1.5*pi/180)*240),70,160,25,Czoom,0);
  if (counter>=1090) and (counter<1150) then
    putimagea(80,70,160,25,Czoom,0);
  if (counter>=1150) and (counter<1210) then
    putimagea(80+round(sin((counter-1150)*1.5*pi/180)*240),70,160,25,Czoom,0);

  if (counter>=1080) and (counter<1140) then
    putimagea(-160+round(sin((counter-1080)*1.5*pi/180)*240),100,160,25,Cgfx,0);
  if (counter>=1140) and (counter<1170) then
    putimagea(80,100,160,25,Cgfx,0);
  if (counter>=1170) and (counter<1230) then
    putimagea(80+round(sin((counter-1170)*1.5*pi/180)*240),100,160,25,Cgfx,0);
  video_copy;
end;

procedure BLOB_INIT;
begin
  alloc;
  loadmaps;
  maketables;
{  convertimage(Ccharlie,4000);
  convertimage(Cmrc,4000);
  convertimage(Cdreamer,4000);
  convertimage(Ckid,4000);
  convertimage(Czoom,4000);
  convertimage(Cgfx,4000);
  convertimage(Ccodegfx,4000);
  convertimage(Cmusic,4000);
  convertimage(Ccode,4000);}
end;

procedure newint;
begin
  inc(counter);
end;

procedure BLOB_ACTION;
begin
  asm
   mov al,[_order]
   mov korder,al
  end;
  vorder:=korder+4;
  TERM:=false;
  counter:=0;
  USS_SetTimer(@newint,timerspeed div 60);
  repeat
    render;
    asm
     mov al,[_order]
     mov aorder,al
    end;
    if (aorder=vorder) then term:=true;
    if TerminateDemo Then Begin USS_StopTimer(@newint); ExitDemo; End;
  until{ (keypressed) or }(TERM);
  while keypressed do readkey;
  USS_StopTimer(@newint);
end;

procedure BLOB_CLOSE;
begin
  dealloc;
end;

begin
end.
