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

interface

procedure scene_iferenc;

implementation

uses rubik, smalcube, global, screen, crosfade, memory, palette, math2, 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);

colors1:array[0..30] of byte =(
7, 0, 12, 5, 9, 3, 14, 11, 16, 13, 18, 15, 19, 17, 21, 23,
251, 8, 253, 2, 10, 255, 4, 1, 254, 6, 20, 25, 252, 24, 22
);

colors2:array[0..30] of byte =(
74, 67, 79, 72, 76, 70, 81, 78, 83, 80, 85, 82, 86, 84, 88,
90, 62, 71, 75, 64, 73, 69, 77, 66, 68, 65, 87, 92, 63, 91, 89
);



procedure interference(x1,y1, x2,y2, x3,y3, x4,y4:byte; tex1, tex2, where:word);
var
l1,l2,l3,l4:byte;
o1,o2,o3,o4:word;
begin
  {call count lines for switch segment}
  l1:=byte(128-y1);
  l2:=byte(128-y2);
  l3:=byte(128-y3);
  l4:=byte(128-y4);
  {call offset quad 1}
  o1:=word( y1 shl 9 + x1);
  o2:=word((y2 shl 9 + x2) - o1);
  o3:=word((y3 shl 9 + x3) - o1);
  o4:=word((y4 shl 9 + x4) - o1);

 asm
  mov     es, where
  mov     ax, tex1
  db      $8e,$e0 {mov fs, ax}
  mov     ax, tex2
  db      $8e,$e8 {mov gs, ax}

  xor     di, di

  mov bl, l1
  mov bh, l2
  mov dl, l3
  mov dh, l4

  mov si, o1

  {---------------self-modify---------------}
  mov ax, o2
  mov cs:[offset @m2+4], ax
  mov ax, o3
  mov cs:[offset @m3+4], ax
  mov ax, o4
  mov cs:[offset @m4+4], ax
  mov byte ptr cs:[offset @m1], 64h
  mov byte ptr cs:[offset @m2], 64h
  mov byte ptr cs:[offset @m3], 64h
  mov byte ptr cs:[offset @m4], 64h
  jmp @clear_prefetch; @clear_prefetch:
  {-----------------------------------------}
  push bp
  xor bp, bp
  cld
  mov ch, 100 { count screen line}
@mainloop:

  cmp bl, 0
  je  @switch_segment1
  cmp bh, 0
  je  @switch_segment2
  cmp dl, 0
  je  @switch_segment3
  cmp dh, 0
  je  @switch_segment4

  {-------------self-modify-----------------}
  db $65,$66; mov ax, [bp+65504]
  db $66; mov word ptr cs:[offset @dither1+2], ax
  db $65,$66; mov ax, [bp+65504+4]
  db $66; mov word ptr cs:[offset @dither2+2], ax
  jmp @clear_prefetch2; @clear_prefetch2:
  {-----------------------------------------}

  mov cl, 80
    @inerloop:
       @m1: db $64,$66; mov ax, [si]
       @m2: db $64,$66; add ax, [si+1111h]
       @m3: db $64,$66; add ax, [si+1111h]
       @m4: db $64,$66; add ax, [si+1111h]

       @dither1: db $66; add ax, 1234h; dw $5678; {dither}
       db $66; mov es:[di], ax

       @dither2: db $66; add ax, 1234h; dw $5678; {dither}
       db $66; mov es:[di+320], ax

       add di, 4
       add si, 4
       dec cl
    jnz @inerloop

  add bp, 8
  and bp, 15

  add di, 320
  add si, 192
  dec bl
  dec bh
  dec dl
  dec dh

  dec ch
  jnz @mainloop
  jmp @exit

@switch_segment1:
    mov byte ptr cs:[offset @m1], 65h
    mov bl, 255
    jmp @mainloop
@switch_segment2:
    mov byte ptr cs:[offset @m2], 65h
    mov bh, 255
    jmp @mainloop
@switch_segment3:
    mov byte ptr cs:[offset @m3], 65h
    mov dl, 255
    jmp @mainloop
@switch_segment4:
    mov byte ptr cs:[offset @m4], 65h
    mov dh, 255
    jmp @mainloop

@exit:
pop bp
end;
end;


(*
Procedure Ifer_Table1(size, x0,y0,y_start:word; c0:byte; buf:word);
var
n,p:word;
x,y:integer;
c:integer;
color:byte;
begin
     n:=0; x:=0; y:=y_start;
     for p:=0 to size{(512*128)-2} do
       begin
          c:=round(cos_(sqrt_((y-y0)*(y-y0)+(x / 2-x0)*(x / 2-x0))/6)*30+30)+c0;{}
          if (c>255) then color := abs(255-c) else color := c;
          mem[buf:n]:=color;
          x:=x+1;
          if (x=512) then
             begin
               x:=0;
               y:=y+1;
             end;
        n:=n+1;
       end;
end;

Procedure Ifer_Table2(size, x0,y0,y_start:word; c0:byte; buf:word);
var
n,p:word;
x,y:integer;
c:integer;
color:byte;
a:single;
begin
     n:=0; x:=0; y:=y_start;
     for p:=0 to size{(512*128)-2} do
       begin
          if (x/2-x0>0) and (y-y0>=0) then a:=arctan((y-y0) / (x/2-x0));
          if (x/2-x0=0) and (y-y0>=0) then a:=1.57;
          if (x/2-x0>0) and (y-y0<0)  then a:=arctan((y-y0) / (x/2-x0))+2*pi;
          if (x/2-x0=0) and (y-y0<0)  then a:=-1.57 +2*pi;
          if (x/2-x0<0) then a:=arctan((y-y0) / (x/2-x0))+pi;
          a:=a / (2*pi);

          c:=integer(round(a*256));
          c:=c+round(sin_(sqrt_((y-y0)*(y-y0)+(x/2-x0)*(x/2-x0))/16)*38+38);{}

          if (c>255) then color := abs(255-c) else color := c;
          mem[buf:n]:=color;
          x:=x+1;
          if (x=512) then
             begin
               x:=0;
               y:=y+1;
             end;
        n:=n+1;
       end;
end;

Procedure Ifer_table3(size, x0,y0,y_start:word; c0:byte; buf:word);
var
n,p:word;
x,y:integer;
c:integer;
color:byte;
begin
     n:=0; x:=0; y:=y_start;
     for p:=0 to size do
       begin
          c:=round(sin_(sqrt_((y-y0)*(y-y0)+(x / 2-x0)*(x/2-x0))/18)*48);{}
          if (c>255) then color := abs(255-c) else color := c;
          mem[buf:n]:=color;
          x:=x+1;
          if (x=512) then
             begin
               x:=0;
               y:=y+1;
             end;
        n:=n+1;
       end;
end;
*)

procedure load_dither_pattern(sub, min,max, divider:shortint; offs, where:word);
var
n, b:shortint;
begin
for n:=0 to 15 do begin
b:=shortint(( pattern[n] -sub) div divider);
if b>max then b:=max;
if b<min then b:=min;
mem[where:word(n+offs)]:= shortint(b);
end;
end;


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

speed_palette, qsub, q,n:word;
skip_render, output_mode, triger, type_movement, b,stage:byte;
x,y, x1,y1,x2,y2,x3,y3,x4,y4:integer;
o, roll:single;
x_const,y_const:single;

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

test:byte;

procedure Scene_iferenc;
begin
old_time:=mtimer;

{for n:=0 to 255 do
SetOneColor2memw(n,round(cos_(n/20)*31+32),round(cos_(n/25+1)*31+32),
round(cos_(n/30+2)*21+42), palette2, seg_palitra, ofs_palitra);{}
LoadBin('iferens1.pal', seg_palitra,  ofs_palitra+palette2);

{for n:=0 to 31 do
setonecolor_memW2memW(byte(n+60),byte(n-8), palette2,palette1,  seg_palitra,ofs_palitra);}

for n:=0 to 31 do
setonecolor_memW2memW(byte(n+60),byte(n-8), palette1,palette1,  seg_palitra,ofs_palitra);

{setpalette_from_memW(palette1,seg_palitra,ofs_palitra);}

{mem2mem(seg_palitra,ofs_palitra+palette2,  seg_palitra,ofs_palitra+palette1, 1536);}

init_pal2pal(seg_palitra,ofs_palitra);
palette_process[0]:=1;
speed_palette:=4;


Clear(50, 65535, vaddr);
LoadBin('plas2_cl.bin',  vaddr+4000,  0);
LoadBin('plas3_cl.bin',  vaddr+4010,  0);
LoadBin('plas3_op.bin',  vaddr+4020,  0);

DitherFadeInit(vaddr);


LoadBin('ifer_2_1.bin',  vaddr2,  0);
LoadBin('ifer_2_2.bin',  vaddr3,  0);
load_dither_pattern(0, 0, 16, 2,  65504, vaddr3);

speed_column:=30;
buf_160:=vaddr3+2688;
history_buf:=vaddr3+2688+1010;
set_rubik_buffers(vaddr,buf_160,  history_buf);
set_rubik_colors(0,50,190,  50,  76, 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;}
{-----------------------------------}

x_const:=0.64543324;
y_const:=0.38457832;

type_movement:=0;
stage:=0;
triger:=255;
output_mode:=4; {draw result in screen-buffer(1) or direct to A000h (0)?  }
qsub:=0;
skip_render:=1;


q_cubes:=q_cubes+(mtimer-old_time);


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

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

roll:=q*0.02;

if (elapsed_time>0) or (aantal=0) then MP^.GetInformation(@info);

{-----------------------------events--------------------------------------}
if (stage=0) and (triger=1) then begin
                 stage:=1; output_mode:=0;
                 set_border_color(50);
                 end;

if (stage=1) and music_pos(41,25) then
      begin
      stage:=2; qsub:=q; triger:=0;
      output_mode:=4; set_rubik_mode(0);
      end;

if (stage=2) and (triger=1) then begin stage:=3; end;

if (stage=3) then
      begin
      stage:=4;
      type_movement:=1;
      output_mode:=2;
      set_rubik_colors(0,50,190,  50,  137, 254);
      LoadBin('iferens2.pal', seg_palitra,  ofs_palitra+palette2);
      for n:=0 to 31 do setonecolor_memW2memW(byte(n+121),byte(n+60), palette1,palette1,  seg_palitra,ofs_palitra);
      init_pal2pal(seg_palitra,ofs_palitra);
      palette_process[0]:=1;

      LoadBin('ifer_1_1.bin',  vaddr2,  0);
      LoadBin('ifer_1_2.bin',  vaddr3,  0);
      load_dither_pattern(5, 0, 15, 1, 65504, vaddr3);

      qsub:=q;
      triger:=0;
      skip_render:=1;
      end;

if (stage=4) and (triger=1) then begin
             stage:=5; output_mode:=0;
             end;

if (stage=5) and music_pos(44,0) then begin
             stage:=6; qsub:=q; output_mode:=5; triger:=255;
             end;

if (stage=6) and (triger=0) then begin stage:=7; end;

if (stage=7) then begin
      stage:=8;
      type_movement:=2;
      output_mode:=6;
      set_rubik_colors(0,50,190,  50,  76, 254);
      LoadBin('iferens3.pal', seg_palitra,  ofs_palitra+palette2);
      for n:=0 to 31 do setonecolor_memW2memW(byte(n+60),byte(n+121), palette1,palette1,  seg_palitra,ofs_palitra);
      init_pal2pal(seg_palitra,ofs_palitra);
      palette_process[0]:=1;

      LoadBin('ifer_3_1.bin',  vaddr2,  0);
      LoadBin('ifer_3_2.bin',  vaddr3,  0);
      load_dither_pattern(8, 0, 15, 1, 65504, vaddr3);

      qsub:=q;
      triger:=0;
      skip_render:=1;
end;

if (stage=8) and (triger=1) then begin stage:=9; output_mode:=0; end;

if (stage=9) and music_pos(45,10) then begin
       stage:=10;
       qsub:=q;
       triger:=0;
       output_mode:=7;
       set_rubik_mode(0);
       set_rubik_colors(0,70,80,  200,  76, 128);
       Clear(20, 16000, BUF_160);
       end;


{------------------------------------------------------------------------}

if type_movement=0 then begin
   x1 := round(cos(roll)*96+96);
   y1 := round(sin(roll*2)*56+56);
   x2 := round(-cos(roll)*96+96);
   y2 := round(cos(roll)*56+56);
   x3 := round(-cos(roll+2)*96+96);
   y3 := round(sin(roll*4)*56+56);
   x4 := round(cos(roll*2)*96+96);
   y4 := round(cos(roll+2)*56+56);
end;
if type_movement=1 then begin
   o:=1.8;
   x1:=round(sin(o+roll*2.5 * x_const)*96+96);
   y1:=round(cos(o+roll*2.5 * y_const)*56+56);
   x2:=round(sin(o+roll*2.5+2 * x_const)*96+96);
   y2:=round(cos(o+roll*2.5+2 * y_const)*56+56);
   x3:=round(cos(o+roll*2.5 * x_const)*96+96);
   y3:=round(sin(o+roll*2.5 * y_const)*56+56);
   x4:=round(cos(o+roll*2.5+3 * x_const)*96+96);
   y4:=round(sin(o+roll*2.5+3 * y_const)*56+56);
end;
if type_movement=2 then begin
   o:=1;
   x1:=round(sin(o+roll*4 * x_const)*96+96);
   y1:=round(cos(o+roll*4 * y_const)*56+56);
   x2:=round(sin(o+roll*4+2 * x_const)*96+96);
   y2:=round(cos(o+roll+4+2 * y_const)*56+56);
   x3:=round(cos(o+roll*1.5 * x_const)*96+96);
   y3:=round(sin(o+roll*3 * y_const)*56+56);
   x4:=round(-cos(o+roll*1.5+2 * x_const)*96+96);
   y4:=round(sin(o+roll*3+2 * y_const)*56+56);
end;
{----------------------------------------------------------------------}

{-------------------------small cube render -------------------------}
if (output_mode<>0) and (output_mode<>1) and (stage<9) 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;
{-------------------------------------------------------------------}




{draw effect to buffer}
if output_mode <> 0 then
    if skip_render=0 then Interference(x1,y1, x2,y2, x3,y3, x4,y4, vaddr2, vaddr3, vaddr);{}


if (Vsync_mode=1) or (skip_render=1) then Midas_WaitVR;

if palette_process[0]=1 then Pal2Pal_asm(palette_process[0], 0, 255, elapsed_time*speed_palette, seg_palitra,ofs_palitra);

if aantal=0 then set_border_color(68);
if (stage=4) and (skip_render=1) then set_border_color(121);
if (stage=8) and (skip_render=1) then set_border_color(60);


case output_mode of
     0: if skip_render=0 then Interference(x1,y1, x2,y2, x3,y3, x4,y4, vaddr2, vaddr3, vga);
     1: FlipScreen(vaddr, vga);
     2: triger:=mosaik(290-(q-qsub)*2, 1, vaddr+4020, vga);
     3: triger:=mosaik((q-qsub)*2, 1, vaddr+4010, vga);
     4: triger:=columns(q-qsub, 4, 80, 25, 250, vga);
     5: triger:=mosaik((q-qsub)*3, 1, vaddr+4000, vga);
     6: triger:=mosaik(290-(q-qsub)*2, 0, vaddr+4010, vga);
     7: begin
        if speed_column>16 then speed_column:=speed_column-elapsed_time/16;
        triger:=columns(q-qsub, 5, 65, round(speed_column), 250, vga);{}
        end;
end;


skip_render:=0;



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

until (esc_test) or (stage=10) and (triger=1);
end;

end.
