{$N+,A+,G+,F+,D-,E-,L-,R-,S-,Q-,Y-}
unit plasma;

interface

procedure scene_plasma;

implementation

Uses global, rubik, smalcube, math2, screen, palette, crosfade, memory, resource;

CONST
pattern: array[0..4*4-1] of byte =
(0,8,2,10, 12,4,14,6, 3,11,1,9, 15,7,13,5);



var
Aantal, T1: word;
start_time, old_time:word;
elapsed_time:word;

XAnswer,YAnswer,Position, X,Y: Integer;
n:integer;
yy,xx, dx1,dx2,dx3:integer;
dy1,dy2,dy3:integer;
q,qq, qsub, SinX:word;
output_mode, triger, stage:byte;

history_buf, buf_160:word;
cubes_x,cubes_y:single;
x_cube,y_cube, half:integer;


procedure DrawPlasma(output:word);
begin
 For Y := 0 to 99 do begin

   YAnswer := dy1 * memw[vaddr3:((Y  + qq      )            and 511) shl 1]+
              dy2 * memw[vaddr3:((Y  + qq shl 2)            and 511) shl 1]+
              dy3 * memw[vaddr3:((Y shl 1   + qq shr 1 +yy) and 511) shl 1];
    asm
    mov es, output
    mov ax, vaddr2
    db $8E,$E0 {mov fs, ax}
    mov di, position
    mov ax, YAnswer
    mov dx, ax
    db $66; shl dx, 16
    mov dx, ax

    mov bx, y
    add bx, bx
    mov si, bx
    add si, si
    and si, 3
    shl si, 2
    db $64, $66; mov si, [si] {dither pattern for current line}

    {---------------self-modify---------------}
    inc bx
    and bx, 3
    shl bx, 2
    db $64, $66; mov bx, [bx] {dither pattern for current line}
    db $66; mov cs:[offset @dither2+3], bx
    jmp @clear_prefetch; @clear_prefetch:
    {-----------------------------------------}

    xor bx, bx

    push ds
    mov ds, SinX

    push bp
    mov bp, 80
    @x:
           db $66; mov ax, ds:[bx+4]
           db $66; add ax, dx
           db $66; shr ax, 8
           mov ah, al
           db $66; shl ax, 8

           db $66; mov cx, ds:[bx]
           db $66; add cx, dx
           mov al, ch
           db $66; shr cx, 16
           mov ah, ch
           db $66; mov cx, ax
           db $66; add ax, si {dither}
           @dither2: db $66; add cx, 1234h; dw 5678h

           db $66; mov es:[di], ax
           db $66; mov es:[di+320], cx

           add di, 4
           add bx, 8
    dec bp
    jnz @x

    pop bp
    pop ds
    add word ptr position, 640
    end;
 end;
end;


procedure Scene_plasma;
Begin
Clear(179, 64000, vga);

LoadBin('plasma.pal', seg_palitra,  ofs_palitra+palette1);
Midas_WaitVR;
setpalette_from_memW(palette1,seg_palitra,ofs_palitra);
palette_process[0]:=0;
set_border_color(0);


DitherFadeInit(vaddr);

LoadBin('plas_op.bin',  vaddr+4000,  0);
LoadBin('plas2_cl.bin',  vaddr+4010,  0);

SinX:=vaddr2+4000;

{create dither patter-buffer}
for x:=0 to 15 do mem[vaddr2:x]:= pattern[x];

{Now to create our sine array}
For X := 0 to 511 Do begin
   memw[vaddr3:X shl 1] := Trunc(Sin_(Rad(X*2)*2/512*360)*512);
end;

buf_160:=vaddr3+2688;
history_buf:=vaddr3+2688+1010;
set_rubik_buffers(vaddr,buf_160,  history_buf);
set_rubik_colors(0,0,10,  1,  9, 254);
set_rubik_mode(1);

{------small_cube parameters------}
cube_size:=20;
face_size:=cube_size*2+1; {2 byte for x1,x2, +1 byte color}
frame_size:=face_size*3;  {maximum 3 faces visible}

history_size:=32;{(65536-frame_size) div frame_size;}
f:=0;

for n:=0 to history_size do Clear_Frame(n, frame_size, HISTORY_BUF);
{---------------------------------}


triger:=255;
stage:=0;
output_mode:=1; {1 - draw to frame-buffer}


Aantal:=0; T1:=mTimer;
old_time:=mtimer;
start_time:=mtimer;

repeat
q:=mtimer-start_time;
elapsed_time:=(mtimer-old_time);
old_time:=mtimer;

qq:=q+220;

if (elapsed_time>0) or (aantal=0) then begin
MP^.GetInformation(@info);
if (stage=0) and (triger=0) then begin stage:=1; qsub:=q; output_mode:=1; end;
if (stage=1) and music_pos(39,37) then
             begin stage:=2; qsub:=q; output_mode:=2; end;

end;

Position := 0;

dx1:=24;
dx2:=32;
dx3:=40;

dy1:=25;
dy2:=35;
dy3:=20;

xx:=round(cos_(qq/56)*300);
yy:=round(sin_(qq/56)*300);

{-------------------------small cube render -------------------------}
if (output_mode=2) then begin
        q_cubes:=q_cubes+elapsed_time;
        cubes_x:=cos_(q_cubes/50)*100-90;
        cubes_y:=sin_(q_cubes/70)*100-90;

        Clear_Frame(f, frame_size, HISTORY_BUF);
        Small_rotateCubic(-cubes_y/20, 2, cubes_x/20, -5,  cube_size div 4);
        Small_drawcubic(2, cube_size div 2, face_size, f*frame_size, HISTORY_BUF);

        {small-cubic frame history var}
        inc(f); if f>history_size then f:=0;{}

        Clear(0, 16000, BUF_160);
        for y:=0 to 14 do for x:=0 to 17 do begin
            x_cube:=round(x*cube_size+cubes_x);
            y_cube:=round(y*cube_size+cubes_y);
            half:=cube_size shr 1;
            if (y_cube<99  +half) and (y_cube > -half) and
            (x_cube<159 +half) and (x_cube > -half) then
            DrawCube_160((x*4+y*4) and 31, x_cube, y_cube, 1, HISTORY_BUF, BUF_160);{}
            end;
end;
{-------------------------------------------------------------------}



For X := 0 to 319 do begin {precals x-table for current frame}

memw[SinX:X shl 1] :=   dx1 * memw[vaddr3:((X shr 1   + qq)             and 511) shl 1]+
                        dx2 * memw[vaddr3:((X         + qq shl 1)       and 511) shl 1]+
                        dx3 * memw[vaddr3:((X shr 1   + qq shr 2 + xx)  and 511) shl 1];
end;

if output_mode<>0 then DrawPlasma(vaddr);

if (stage=0) then triger:=DitherFade2((q-qsub)*2, 179, vaddr+4000, vaddr);
{if (stage=2) then triger:=DitherFade2(-(q-qsub)*3+320, 0, vaddr+4010, vaddr);}

if Vsync_mode=1 then Midas_WaitVR;{}

case output_mode of
     0: DrawPlasma(vga);
     1: FlipScreen(vaddr, vga);
     2: triger:=mosaik((q-qsub)*3, 0, vaddr+4010, vga);
end;

Inc(Aantal);
if FPS_Mode=1 then WriteFps(100, mtimer, T1, Aantal, vga);

until (esc_test) or ((stage=2) and (triger=0));

q_cubes:=q_cubes+(mtimer-old_time);


end;

End.