#include <conio.h>

int CenterX, CenterY, W, H, SizeX, SizeY;
double CX, CY;

void InitData( void )
{
  CenterX = 512;
  CenterY = 384;
  W = 8;
  H = 6;
  CX = 0.36;
  CY = 0.36;
  SizeX = 275;
  SizeY = 230;
}

void SetMode( int mode )
{
  _asm {
     mov AX, 0x4F02
     mov BX, mode
     int 0x10
  }
}

int Pause( void )
{
  _asm {
     xor AX, AX
     int 0x16
  }
  return _AX;
}

void SetPal( int c, unsigned char r, unsigned char g, unsigned char b)
{
  outp(0x3C8, c);
  outp(0x3C9, r);
  outp(0x3C9, g);
  outp(0x3C9, b);
}

void SetPallete( void )
{
  int i, r = 0, g = 0, b = 0;

  for (i = 0; i < 64; i++)
    SetPal(i, r++, g, b);
  for (i = 64; i < 128; i++)
    SetPal(i, r--, g, b++);
  for (i = 128; i < 192; i++)
    SetPal(i, r, g++, b--);
  for (i = 192; i < 256; i++)
    SetPal(i, r, g--, b);
}

void SetBank( int NewBank )
{
  static int OldBank = -1;

  if (OldBank == NewBank)
    return;
  OldBank = NewBank;
  asm {
    mov AX, 0x4F05
    xor BX, BX
    mov DX, NewBank
    int 0x10
  }
}

void PutPixel( int x, int y, unsigned char color )
{
  long addr = (y << 10) + x;

  *(unsigned char *)(0xA0000000ul + (addr & 0xFFFFul)) = color;
}

unsigned char GetColor( double x0, double y0, double cx, double cy )
{
  double x = x0, y = y0, x1, y1;
  unsigned char color;

  while (color++ < 255 && x * x + y * y <= 4)
  {
    x1 = x * x - y * y + cx;
    y1 = x * y * 2 + cy;
    x = x1;
    y = y1;
  }
  return color;
}

void MandelbrotFractal( int xx, int yy, double c1 )
{
  double X, Y;
  int x, y;

  for (y = yy; y < 768 - yy; y++)
  {
    SetBank(y >> 6);
    for (x = xx; x < 1024 - xx; x++)
    {
      X = (double)(x - CenterX) / 1024 * W;
      Y = (double)(y - CenterY) / 768 * H;
      PutPixel(x, y, GetColor(X, Y, X, Y) / c1);
    }
  }
}

void JuliaFractal( int xx, int yy, double cx, double cy, double c1 )
{
  double X, Y;
  int x, y;

  for (y = yy; y < 768 - yy; y++)
  {
    SetBank(y >> 6);
    for (x = xx; x < 1024 - xx; x++)
    {
      X = (double)(x - CenterX) / 1024 * W;
      Y = (double)(y - CenterY) / 768 * H;
      PutPixel(x, y, GetColor(X, Y, cx, cy) * c1);
    }
  }
}

int main( void )
{
  InitData();
  SetMode(0x105);
  SetPallete();
  MandelbrotFractal(SizeX, SizeY, (double)1 * 1.8);
  Pause();
  JuliaFractal(SizeX, SizeY, CX, CY, (double)1 / 1.8);
  Pause();
  SetMode(3);
  return 0;
}