head 1.1; access ; symbols ; locks ; comment @ * @; 1.1 date 89.06.23.16.32.58; author pkern; state Exp; branches ; next ; desc @from _Computing Now!_ magazine @ 1.1 log @Initial revision @ text @/* MandelHandle (c) 1986 Steve Rimmer A simple implementation of the Mandelbrot microsope in Datalight C for the IBM PC Modified for TI Pro in Turbo C. */ #include #include #include #include "gfxti.h" int far *gbank[3] = { BANK_A, BANK_B, BANK_C }; int far *pltt[3] = { L_BLU, L_GRN, L_RED }; #define frac_size 240 /* size of picture */ #define frac_rsize 700 /* size of real axis */ #define frac_top 30 /* location of picture */ #define frac_left 10 #define frac_bottom frac_top + frac_size #define frac_right 710 #define f1 0x3b00 /* function keys */ #define f2 0x3c00 #define f3 0x3d00 #define f4 0x3e00 #define f5 0x3f00 #define f6 0x4000 #define f7 0x4100 #define f8 0x4200 #define f9 0x4300 #define f10 0x4400 #define up_arrow 0x4800 #define down_arrow 0x5000 #define left_arrow 0x4b00 #define right_arrow 0x4d00 #define ScaleLim 7 /* number of useful colours */ typedef struct { int top, left, bottom, right; } RECT; /* rectangle */ typedef struct { double real, imag; } COMPLEX; /* complex # */ int MaxCount = 16; /* highest count */ int CellSize = 1; /* initial cell size */ float LowReal = -2; /* limits of view */ float HighReal = 0.5; float LowImag = -1.25; float HighImag = 1.25; float rScale, iScale; /* scale factors */ char scrap[64]; /* scrap buffer */ int alive = 1; /* flag to keep boogying */ main() { graphics_mode(); draw_menu(); do { clear_tube(); plot_fractal(); } while (alive); text_mode(); flush_console(); /* empty keyboard buffer */ } draw_menu() { c_string("MandelHandle", 3, 3, 0); c_string("F1 Zoom In ", 4, 25, 4); c_string("F2 Zoom Out ", 4, 25, 5); c_string("F3 Inc Count ", 4, 25, 6); c_string("F4 Dec Count ", 4, 25, 7); c_string("F5 Inc Size ", 4, 25, 8); c_string("F6 Dec Size ", 4, 25, 9); c_string("F10 Get Lost ", 4, 25, 10); c_string("view position ", 4, 25, 12); c_string(" 8 ", 4, 25, 14); c_string(" 4 6 ", 4, 25, 15); c_string(" 2 ", 4, 25, 16); } plot_fractal() { int x, y, z; double r, i; COMPLEX n; RECT f; f.top = frac_top - 1; f.left = frac_left - 1; f.bottom = frac_bottom + (2 + CellSize); f.right = frac_right + (2 + CellSize); FrameRect(f); /* draw the fractal frame */ sprintf(scrap, "%3.4f", LowImag); c_string(scrap, 4, 16, 5); /* show the parameters */ sprintf(scrap, "%3.4f", HighImag); c_string(scrap, 4, 16, 17); sprintf(scrap, "%3.4f", LowReal); c_string(scrap, 4, (frac_left/8), (frac_top/8)-1); sprintf(scrap, "%3.4f", HighReal); c_string(scrap, 4, (frac_right/8)-8, (frac_top/8)-1); sprintf(scrap, "High count: %2d Cell size: %2d ", MaxCount, CellSize); c_string(scrap, 3, 0, 22); rScale = (HighReal - LowReal) / frac_rsize; iScale = (HighImag - LowImag) / frac_size; /* calculate scale */ flush_console(); y = 0; while (y <= frac_size && (z = check_keyboard()) == 0) { if (y == 2) /* wipe out last message after a while */ c_string(" ", 7, 0, 23); for (x=0; x <= frac_rsize; x += CellSize) { n.real = LowReal + (rScale * x); n.imag = HighImag - (iScale * y); frac_point(n, x, y); ++x; } y += CellSize; } if (z==0) { c_string("Zap any key ", 7, 0, 23); while (check_keyboard() == 0) ; } } frac_point(n, x, y) /* test and plot the point at x, y */ COMPLEX n; int x, y; { double t, normalize(); int c = 0; COMPLEX l; RECT r; l.real = l.imag = 0; while (c < MaxCount && normalize(l) <= 2.0) { t = (l.real * l.real) - (l.imag * l.imag) + n.real; l.imag = 2.0 * l.real * l.imag + n.imag; l.real = t; ++c; } if (CellSize == 1) /* just plot the dot if size is 1 */ plot_dot(frac_left + x, frac_top + y, (c * ScaleLim) / MaxCount ); else { /* or fill in a rectangle for bigger cells */ r.top = frac_top + y; r.left = frac_left + x; r.bottom = frac_top + y + CellSize; r.right = frac_left + x + CellSize; FillRect(r, (c * ScaleLim) / MaxCount); } } double normalize(n) /* normalize the imaginary number */ COMPLEX n; { double sqrt(); return(sqrt((n.real * n.real) + (n.imag * n.imag))); } FrameRect(r) /* draw a box given in struct r */ RECT r; { int i; /* * for (i=r.left; i <= r.right; i++) { /* draw top and bottom ** * plot_dot(i, r.top, 7); * plot_dot(i, r.bottom, 7); * } */ horzline(r.left,r.top,r.right-r.left+1,7); horzline(r.left,r.bottom,r.right-r.left+1,7); for (i=r.top; i <= r.bottom; i++) { /* draw left and right */ plot_dot(r.left, i, 7); plot_dot(r.right, i, 7); } } FillRect(r, c) /* fill box r with colour c */ RECT r; int c; { int i, j; for (j=r.top; j <= r.bottom; j++) /* * for (i=r.left; i <= r.right; i++) * plot_dot(i, j, c); */ horzline(r.left,j,r.right-r.left+1,c); } gotoxy(x, y) /* position cursor at x, y */ int x, y; { union REGS r; r.h.ah = 2; r.x.dx = y + (x << 8); int86(0x49, &r, &r); } text_mode() /* set normal DOS text mode */ { gotoxy(1,24,7); } graphics_mode() /* initialize graphics palette */ { union REGS r; r.h.ah = 0x13; int86(0x49, &r, &r); r.h.ah = 0x14; int86(0x49, &r, &r); *(L_BLU) = 0xaa; *(L_RED) = 0xcc; *(L_GRN) = 0xf0; } plot_dot(x, y, c) /* plot dot at x, y, colour c */ int x, y, c; { gfxormsk(OFFS(x,y), BITMSK(x), c); } get_char() /* get keyboard char */ { union REGS r; r.h.ah = 0; int86(0x4a, &r, &r); /* get char */ return(r.x.ax); } constat() /* return 0 if no keyboard character available */ { /* * union REGS r; * * r.h.ah = 1; * int86(0x4a, &r, &r); * return(r.x.flags & 0x40); */ return(bdos(0xb,0,0) & 0xff); } flush_console() /* empty keyboard buffer */ { while (constat()) get_char(); } c_string(s, c, x, y) /* print string s in colour c at x, y */ char *s; int c, x, y; { int i; while((i = *s++) != 0) { gotoxy(x, y); c_char(i, c); ++x; } } c_char(b, c) /* print byte b in colour c */ { union REGS r; r.x.cx = 1; r.x.bx = c | 0x8; r.x.ax = (0x9 << 8) + b; int86(0x49, &r, &r); } check_keyboard() /* handle keyboard commands */ { int c, f; double t; f = 0; if (constat()) { c = get_char(); if (c > 0xff) { switch (c) { case f1: c_string("Zoom in ", 4, 0, 23); t = CellSize * (HighImag - LowImag) / frac_size; LowImag += t; HighImag -= t; t = CellSize * (HighReal - LowReal) / frac_rsize; LowReal += t; HighReal -= t; f = 1; break; case f2: c_string("Zoom out ", 4, 0, 23); t = CellSize * (HighImag - LowImag) / frac_size; LowImag -= t; HighImag += t; t = CellSize * (HighReal - LowReal) / frac_rsize; LowReal -= t; HighReal += t; f = 1; break; case f3: if (MaxCount < 128) { c_string("Inc count ", 4, 0, 23); MaxCount = MaxCount * 2; f = 1; } else f = 0; break; case f4: if (MaxCount > 0) { c_string("Dec count ", 4, 0, 23); MaxCount = MaxCount / 2; f = 1; } else f = 0; break; case f5: if (CellSize < 8) { c_string("Inc size ", 4, 0, 23); CellSize = CellSize * 2; f = 1; } else f = 0; break; case f6: if (CellSize > 0) { c_string("Dec size ", 4, 0, 23); CellSize = CellSize / 2; f = 1; } else f = 0; break; case f10: alive = 0; c_string("Zap any key ", 7, 0, 23); f = 1; break; case up_arrow: c_string("Shift north", 4, 0, 23); t = (CellSize * CellSize) * (HighImag - LowImag) / frac_size; LowImag += t; HighImag += t; f = 1; break; case down_arrow: c_string("Shift south", 4, 0, 23); t = (CellSize * CellSize) * (HighImag - LowImag) / frac_rsize; LowImag -= t; HighImag -= t; f = 1; break; case right_arrow: c_string("Shift east ", 4, 0, 23); t = (CellSize * CellSize) * (HighReal - LowReal) / frac_rsize; LowReal += t; HighReal += t; f = 1; break; case left_arrow: c_string("Shift west ", 4, 0, 23); t = (CellSize * CellSize) * (HighReal - LowReal) / frac_rsize; LowReal -= t; HighReal -= t; f = 1; break; default: f = 0; break; } } } return(f); } clear_tube() /* wipe out old fractal */ { /* * int i; * * for(i=5; i <= 19; i++) { * gotoxy(0, i); * puts(" "); /* 16 blanks ** * } */ union REGS r; r.h.ah = 0x14; int86(0x49, &r, &r); } /* that's all folks */ @