#Option Strict
#Include <Include\Windows.inc>
 
Type BMPBLOB Align 2 // fake BITMAPINFOHEADER
  %biSize
  %biWidth
  %biHeight
  %biPlanes * 16
  %biBitCount * 16
  $biUnused * 24
End Type
 
Type FRACTAL
  !!x
  !!y
  !!rc
  !!ic
End Type
 
Dim sz = 800
Dim matrix[sz * sz] As FRACTAL
Dim %rd[sz * sz], %gr[sz * sz], %bl[sz * sz]
 
Dim bb As BMPBLOB
With bb
  .biSize = LenB(BMPBLOB)
  .biWidth = sz
  .biHeight = sz
  .biPlanes = 1
  .biBitCount = 32
End With
 
Dim button = FbslControl("button", ME, "Run", 1001, 400, 833, 100, 24, WS_CHILD BOr WS_VISIBLE, 0)
Dim canvas = FbslControl("SysAnimate32", ME, "", 1002, 50, 20, sz, sz, WS_CHILD BOr WS_VISIBLE BOr WS_BORDER)
 
StyleRemove(ME, WS_MAXIMIZEBOX BOr WS_MINIMIZEBOX BOr WS_THICKFRAME)
FbslSetText(ME, "Click 'Run' to start...")
Resize(ME, 0, 0, 900, 900): Center(ME)
 
Dim %pixels, hBmp = CreateDIBSection(NULL, @bb, 0, @pixels, NULL, 0)
Dim hDC = GetDC(canvas), memDC = CreateCompatibleDC(NULL)
Dim hOldBmp = SelectObject(memDC, hBmp)
 
Show(ME)
DoEvents
 
init_matrix()
 
Begin Events
  If CBMSG = WM_COMMAND Then
    If CBLPARAM = button Then
      DrawBrot()
      Return 0
    End If
  ElseIf CBMSG = WM_PAINT Then
    BitBlt(hDC, 0, 0, sz, sz, memDC, 0, 0, SRCCOPY)
  ElseIf CBMSG = WM_CLOSE Then
    DeleteObject(SelectObject(memDC, hOldBmp))
    DeleteDC(memDC)
    ReleaseDC(canvas, hDC)
  ElseIf CBMSG = WM_DESTROY Then
    ExitProcess(0)
  End If
End Events
 
Sub DrawBrot()
  RtlZeroMemory(@gr[0], LenB(gr)) // clear green array
  
  Dim start_time = GetTickCount()
  For Dim k = 1 To 94
    update_matrix(@matrix[0], sz)
    SelectObject(memDC, hOldBmp)
    plot_matrix(@matrix[0], @rd[0], @gr[0], @bl[0], pixels, sz)
    SelectObject(memDC, hBmp)
    BitBlt(hDC, 0, 0, sz, sz, memDC, 0, 0, SRCCOPY)
    FbslSetText(ME, (GetTickCount() - start_time) / 1000 & " sec, frame " & k & "/94")
    DoEvents
  Next
End Sub
 
Sub init_matrix()
  Dim ix, y, x = -2.0, dz = 3 / 800
  
  For Dim i = 0 To sz - 1
    x = x + dz: y = -1.5
    For Dim j = 0 To sz - 1
      y = y + dz: ix = i + j * sz
      With matrix[ix]
        Let(.x, .rc) = x
        Let(.y, .ic) = y
      End With
    Next
  Next
End Sub
 
DynC update_matrix(%mtx_ptr, %sz)
  typedef struct {
    double x, y, rc, ic;
  } FRACTAL, *LPFRACTAL;
  
  void main(FRACTAL matrix[], int sz)
  {
    int i;
    double p;
    LPFRACTAL f;
    
    for (i = 0; i < sz * sz; i++) {
      f = &matrix[i];
      p = f->x;
      f->x = p * p - f->y * f->y + f->rc;
      f->y = 2 * p * f->y + f->ic;
    }
  }
End DynC
 
DynC plot_matrix(%mtx_ptr, %r_ptr, %g_ptr, %b_ptr, %pxs_ptr, %sz)
  typedef struct {
    double x, y, rc, ic;
  } FRACTAL, *LPFRACTAL;
  
  void main(FRACTAL matrix[], int rd[], int gr[], int bl[], int* pixels, int sz)
  {
    int i, px, py, pxy;
    double p, q;
    LPFRACTAL f;
    
    for (i = 0; i < sz * sz; i++) {
      f = &matrix[i];
      p = f->y;
      q = f->x;
      if (p > 1000.0 || p < -1000.0 || q > 1000.0 || q < -1000.0) {
        memset(f, 0, sizeof(FRACTAL));
      }
      
      if (p > -2.0) {
        if (p < 1.0) {
          if (q < 1.5 && q > -1.5) {
            px = 266 * (p + 1.5);
            py = 266 * (q + 2.0);
            pxy = px + sz * py;
            if (pxy < 640000) {
              rd[pxy] += 3;
              gr[pxy] += 3;
              bl[pxy] += 1;
            }
          }
        }
      }
    }
    
    for (px = sz - 1; px >= 0; px--) {
      for (py = 0; py < sz; py++) {
        pxy = px * sz + py;
        *pixels++ = bl[pxy] | (gr[pxy] << 8) | (rd[pxy] << 16);
      }
    }
  }
End DynC