home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fred Fish Collection 1.5
/
ffcollection-1-5-1992-11.iso
/
ff_disks
/
001-099
/
ff005.lzh
/
MandelbrotSrc
/
mand1.c
< prev
next >
Wrap
C/C++ Source or Header
|
1986-01-11
|
11KB
|
448 lines
/*
MAND1.C - Graphics routines
Mandelbrot Self-Squared Dragon Generator
For the Commodore Amiga
Version 2.01
Copyright (C) 1985, Robert S. French
Vastly Enhanced by =RJ Mical= 1985/86
Copyright (C) 1986, =Robert J. Mical=
Placed in the Public Domain
This program may be distributed free of charge as long as the above
notice is retained.
*/
#include "mand.h"
extern int MathBase, MathTransBase;
extern struct Menu MainMenu[MENU_COUNT];
extern struct MenuItem OptionsItems[OPTIONS_COUNT];
extern SHORT Color0, Color1, Color2;
extern SHORT UserPalette[29];
/*----------------------*/
/* Graphics definitions */
extern struct GfxBase *GfxBase;
extern struct IntuitionBase *IntuitionBase;
extern struct RastPort *rp,*rp2;
extern struct ViewPort *vp;
extern struct Window *w,*w2, *ColorWindow;
extern struct Screen *screen;
extern struct IntuiMessage *message;
extern long last_color;
extern BOOL SettingCenter, SettingBoxSize, SetBoxProportional;
/*----------------------------------*/
/* Miscellaneous Global Definitions */
extern union kludge {
float f;
int i;
} start_r,end_r,start_i,end_i; /* Block bounds for set */
extern int max_x,max_y; /* Graphics window size */
extern int max_count,color_inc,color_offset,color_set,color_mode,color_div;
extern int color_inset,func_num;
extern int v_starty,max_mem;
extern long v_offset;
extern UWORD *color_table,*v_mand_store;
extern int modified,want_read;
extern FILE *console,*v_fp,*redir_fp;
extern SHORT ZoomCenterX, ZoomCenterY, ZoomBoxSizeX, ZoomBoxSizeY;
extern SHORT ZoomBoxStartX, ZoomBoxStartY;
/*----------------*/
/* Color routines */
init_colors()
{
switch (color_set) {
case 0: init_cincr(); break;
case 1: init_c7rot(); break;
case 2: copy_userpalette(); break;
}
}
init_cincr()
/* this routine initializes the color table with sequential values from
* 0 to 4095
*/
{
UWORD i;
for (i=0;i<4096;i++)
*(color_table + i) = i;
}
init_c7rot()
/* this routine initializes the color table with this pattern:
* 0 = 0
* 1-15 = unit steps of blue
* 16-30 = unit steps of green
* 31-45 = unit steps of red
* 46-60 = unit steps of sky sky blue (blue and green)
* 61-75 = unit steps of purple (blue and red)
* 76-90 = unit steps of yellow (green and red)
* 91-115 = unit steps of white (all colors)
*/
{
UWORD i,j,*base;
base = color_table;
*(base++) = 0;
for (j = 0; j < 39; j++) {
for (i = 1; i < 16; i++)
*(base++) = i; /* gimme the blues */
for (i = 1; i < 16; i++)
*(base++) = i << 4; /* these are the greens */
for (i = 1; i < 16; i++)
*(base++) = i << 8; /* the reds */
for (i = 1; i < 16; i++)
*(base++) = i | (i << 4); /* blue and green */
for (i = 1; i < 16; i++)
*(base++) = i | (i << 8); /* blue and red */
for (i = 1; i < 16; i++)
*(base++) = (i << 4) | (i << 8); /* green and red */
for (i = 1; i < 16; i++)
*(base++) = i | (i << 4) | (i << 8); /* all three */
}
}
copy_userpalette()
{
SHORT i;
for (i = 0; i <= 28; i++)
*(color_table + color_offset + (i + 1) * color_inc) = UserPalette[i];
}
gen_mand()
{
void write_out();
int x_coord,y_coord,count;
union kludge x_gap,y_gap,z_r,z_i,u_r,u_i,temp,temp2,temp3,const0;
union kludge const1,const2,const12;
ULONG class;
USHORT code;
int returncode;
int z_r_squared, z_i_squared;
/* if there was a display open, close it now */
CloseDisplay();
/* show the current settings! */
CurrentSettings();
/* reset the display variables: */
SettingCenter = SettingBoxSize = FALSE;
if (v_fp) {
fclose(v_fp);
v_fp = NULL;
}
v_fp = fopen("Mandelbrot.temp.file","w+");
if (v_fp == NULL) {
abort("Can't open temporary file!");
}
v_starty = 1;
v_offset = 0L;
modified = FALSE;
want_read = FALSE;
ZoomCenterX = (max_x >> 1);
ZoomCenterY = (max_y >> 1);
ZoomBoxSizeX = max_x;
ZoomBoxSizeY = max_y;
if (open_winds())
{
returncode = 1;
goto OPEN_W_RETURN;
}
x_gap.i = SPDiv(SPFlt(max_x),SPSub(start_r.i,end_r.i));
y_gap.i = SPDiv(SPFlt(max_y),SPSub(start_i.i,end_i.i));
const0.i = SPFlt(0);
const1.i = SPFlt(1);
const2.i = SPFlt(2);
const12.i = SPDiv(SPFlt(2),SPFlt(1));
for (y_coord = 0; y_coord < max_y; y_coord++)
{
last_color = 0xfff;
v_pos_line(y_coord);
modified = TRUE;
for (x_coord = 0; x_coord < max_x; x_coord++)
{
while (message = (struct IntuiMessage *)GetMsg(w->UserPort))
{
class = message->Class;
code = message->Code;
ReplyMsg(message);
if (class == MENUPICK)
{
/* the menu strip is hacked up to a minimal set during gen_m */
switch MENUNUM(code)
{
case 0:
switch ITEMNUM(code)
{
case 0:
returncode = 0;
goto OPEN_W_RETURN;
case 1:
CloseDisplay();
fclose(v_fp);
v_fp = NULL;
returncode = 1;
goto OPEN_W_RETURN;
}
break;
}
}
}
if (func_num == 0)
z_r.i = const0.i;
else
z_r.i = const12.i;
z_i.i = const0.i;
u_r.i = SPAdd(start_r.i,SPMul(SPFlt(x_coord),x_gap.i));
u_i.i = SPAdd(start_i.i,SPMul(SPFlt(max_y-y_coord-1),y_gap.i));
for (count = 0; count < max_count; count++)
{
/* By setting these variables and reusing the results below,
* we save approximately 10% execution time in this
* innermost of inner loops.
*/
z_r_squared = SPMul(z_r.i, z_r.i);
z_i_squared = SPMul(z_i.i, z_i.i);
if ( SPFix(SPAdd(z_r_squared, z_i_squared)) >= 4 ) break;
if (func_num == 0)
{ /* z = z^2-u */
temp.i = SPSub(u_r.i, SPSub(z_i_squared, z_r_squared));
z_i.i = SPSub(u_i.i, SPMul(SPMul(const2.i,z_r.i), z_i.i));
z_r = temp;
}
else if (func_num == 1)
{ /* z = uz(1-z) */
temp2.i = SPSub(z_r.i,const1.i);
temp3.i = SPNeg(z_i.i);
temp.i = SPSub(SPMul(temp3.i,z_i.i),SPMul(temp2.i,z_r.i));
z_i.i = SPAdd(SPMul(temp2.i,z_i.i),SPMul(temp3.i,z_r.i));
z_r = temp;
temp.i = SPSub(SPMul(z_i.i,u_i.i),SPMul(z_r.i,u_r.i));
z_i.i = SPAdd(SPMul(z_r.i,u_i.i),SPMul(z_i.i,u_r.i));
z_r = temp;
}
}
if (count >= max_count)
count = 0;
*(v_mand_store+(y_coord-v_starty)*max_x+x_coord) = count;
write_out(count,x_coord,y_coord);
}
}
/* successful return with window opened */
returncode = 0;
DisplayBeep(NULL); /* hey, we're done! */
/* Now that we're drawing the primary display,
* restore the entire menu system
*/
OPEN_W_RETURN:
if (returncode == 0)
{
MainMenu[MENU_OPTIONS].NextMenu = &MainMenu[MENU_ZOOM];
MainMenu[MENU_OPTIONS].FirstItem = &OptionsItems[0];
SetMenuStrip(w, &MainMenu[0]);
}
return(returncode);
}
disp_mand()
{
void write_out();
int x_coord,y_coord,count;
if (open_winds())
return (1);
want_read = TRUE;
for (y_coord=0;y_coord<max_y;y_coord++) {
last_color = 0xfff;
v_pos_line(y_coord);
for (x_coord=0;x_coord<max_x;x_coord++) {
count = *(v_mand_store+(y_coord-v_starty)*max_x+x_coord);
write_out(count,x_coord,y_coord);
}
}
return (0);
}
void write_out(count,x,y)
int count,x,y;
{
void ham_write();
SHORT modulus;
int color;
y += STARTY;
if (!(color_mode & NOT_HOLDANDMODIFY)) {
if (count == 0)
color = color_inset;
else
color = count * color_inc + color_offset;
ham_write(*(color_table+color),x,y);
}
else /* we're not hold-and-modify, so ... */ {
if (color_mode & HIRES_MODE) modulus = 13;
else modulus = 29;
if (count == 0) color = 2;
else color = (((count - 1) / color_div) % modulus) + 3;
SetAPen(rp, color);
WritePixel(rp, x, y);
}
}
void ham_write(color, x, y)
int color;
int x, y;
{
if ((color & 0xf00) != (last_color & 0xf00)) {
SetAPen(rp,((color & 0xf00) >> 8) + 0x20);
WritePixel(rp,x,y);
last_color = (last_color & 0xff) | (color & 0xf00);
return;
}
if ((color & 0xf0) != (last_color & 0xf0)) {
SetAPen(rp,((color & 0xf0) >> 4) + 0x30);
WritePixel(rp,x,y);
last_color = (last_color & 0xf0f) | (color & 0xf0);
return;
}
SetAPen(rp,(color & 0xf) + 0x10);
WritePixel(rp,x,y);
last_color = (last_color & 0xff0) | (color & 0xf);
return;
}
DrawZoomCenter()
{
DrawCross(ZoomCenterX, ZoomCenterY);
}
DrawDisplayCenter()
{
DrawCross(max_x >> 1, max_y >> 1);
}
DrawCross(x, y)
SHORT x, y;
{
SetDrMd(w->RPort, COMPLEMENT);
Move(w->RPort, 0, y);
Draw(w->RPort, max_x, y);
Move(w->RPort, x, 0);
Draw(w->RPort, x, max_y);
}
RecalcZoomBox()
{
ZoomBoxSizeY = (abs(w->MouseY - ZoomCenterY) << 1) + 1;
if (w->MouseY < ZoomCenterY) ZoomBoxStartY = w->MouseY;
else ZoomBoxStartY = ZoomCenterY - ((ZoomBoxSizeY - 1) >> 1);
/* if SetBoxProportional, size X proportional to Y */
if (SetBoxProportional)
{
ZoomBoxSizeX = (ZoomBoxSizeY * 8) / 5;
ZoomBoxStartX = ZoomCenterX - ((ZoomBoxSizeX - 1) >> 1);
}
else
{
ZoomBoxSizeX = (abs(w->MouseX - ZoomCenterX) << 1) + 1;
if (w->MouseX < ZoomCenterX) ZoomBoxStartX = w->MouseX;
else ZoomBoxStartX = ZoomCenterX - ((ZoomBoxSizeX - 1) >> 1);
}
}
DrawZoomBox()
{
SetDrMd(w->RPort, COMPLEMENT);
DrawBox(w->RPort, ZoomBoxStartX, ZoomBoxStartY,
ZoomBoxStartX + ZoomBoxSizeX - 1,
ZoomBoxStartY + ZoomBoxSizeY - 1);
}
CloseDisplay()
{
if (w) CloseWindow(w);
if (w2) CloseWindow(w2);
if (ColorWindow) CloseWindow(ColorWindow);
if (screen) CloseScreen(screen);
w = NULL;
screen = NULL;
}
DrawBox(rp, x1, y1, x2, y2)
struct RastPort *rp;
SHORT x1, y1, x2, y2;
/* draws a box without overlapping the edges (in case of complement mode) */
{
Move(rp, x1, y1 + SIGN(y2 - y1));
Draw(rp, x1, y2);
Move(rp, x1 + SIGN(x2 - x1), y2);
Draw(rp, x2, y2);
Move(rp, x2, y2 - SIGN(y2 - y1));
Draw(rp, x2, y1);
Move(rp, x2 - SIGN(x2 - x1), y1);
Draw(rp, x1, y1);
}