📄 jiim.c
字号:
/*
* JIIM.C
*
* Generates Inverse Julia in real time, lets move a cursor which determines
* the J-set.
*
* The J-set is generated in a fixed-size window, a third of the screen.
*
* This module is linked as an overlay, use ENTER_OVLY and EXIT_OVLY.
*
*
* The routines used to set/move the cursor and to save/restore the
* window were "borrowed" from editpal.c (TW - now we *use* the editpal code)
* (if you don't know how to write good code, look for someone who does)
*
* JJB [jbuhler@gidef.edu.ar]
* TIW Tim Wegner
* MS Michael Snyder
* KS Ken Shirriff
* Revision History:
*
* 7-28-92 JJB Initial release out of editpal.c
* 7-29-92 JJB Added SaveRect() & RestoreRect() - now the
* screen is restored after leaving.
* 7-30-92 JJB Now, if the cursor goes into the window, the
* window is moved to the other side of the screen.
* Worked from the first time!
* 10-09-92 TIW A major rewrite that merged cut routines duplicated
* in EDITPAL.C and added orbits feature.
* 11-02-92 KS Made cursor blink
* 11-18-92 MS Altered Inverse Julia to use MIIM method.
* 11-25-92 MS Modified MIIM support routines to better be
* shared with stand-alone inverse julia in
* LORENZ.C, and to use DISKVID for swap space.
* 05-05-93 TIW Boy this change file really got out of date.
* Added orbits capability, various commands, some
* of Dan Farmer's ideas like circles and lines
* connecting orbits points.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef XFRACT
#include <stdarg.h>
#include <dos.h> /* for FP_SEG & FP_OFF */
#else
#include <varargs.h>
#endif
#include <math.h>
#ifdef __TURBOC__
# include <mem.h> /* to get mem...() declarations */
#endif
#include "helpdefs.h"
#include "fractint.h" /* for overlay stuff */
#include "fractype.h"
#include "prototyp.h"
#define FAR_RESERVE 8192L /* amount of far mem we will leave avail. */
#define MAXRECT 1024 /* largest width of SaveRect/RestoreRect */
#define newx(size) mem_alloc(size)
#define delete(block)
enum stored_at_values
{
NOWHERE,
DISK,
MEMORY
} ;
/* borrowed from LORENZ.C */
struct affine
{
/* weird order so a,b,e and c,d,f are vectors */
double a;
double b;
double e;
double c;
double d;
double f;
};
extern int setup_convert_to_screen(struct affine *);
int show_numbers =0; /* toggle for display of coords */
int stored_at;
char far *memory = NULL; /* pointer to saved rectangle */
FILE *file;
int windows = 0; /* windows management system */
extern char scrnfile[]; /* file where screen portion is */
/* stored */
extern BYTE *line_buff; /* must be alloced!!! */
extern int sxdots; /* width of physical screen */
extern int sydots; /* depth of physical screen */
extern int sxoffs; /* start of logical screen */
extern int syoffs; /* start of logical screen */
extern int strlocn[]; /* 10K buffer to store classes in */
extern int colors; /* # colors avail. */
extern int using_jiim;
extern int viewwindow; /* 0 for full screen, 1 for window */
extern float viewreduction; /* window auto-sizing */
extern int viewcrop; /* nonzero to crop default coords */
extern float finalaspectratio; /* for view shape and rotation */
extern int viewxdots,viewydots; /* explicit view sizing */
extern double dxsize, dysize;
extern int xdots; /* width of logical screen */
extern int ydots; /* depth of logical screen */
extern double xxmax,xxmin; /* limits of the "window" */
extern double yymax,yymin; /* on the z-plane */
extern int color_bright; /* brightest color in palette */
extern int color_dark; /* darkest color in palette */
extern int color_medium; /* nearest to medbright gray color */
extern int lookatmouse; /* mouse mode for getakey(), etc */
extern int maxit; /* try this many iterations */
extern int fractype; /* fractal type */
extern _CMPLX old,new,init;
extern double tempsqrx,tempsqry;
static int xc, yc; /* corners of the window */
static int xd, yd; /* dots in the window */
extern void displayc(int x, int y, int fg, int bg, int ch);
extern float screenaspect;
double xcjul = BIG;
double ycjul = BIG;
extern int hasinverse;
void displays(int x, int y, int fg, int bg, char *str, int len)
{
int i;
for(i=0;i<len; i++)
displayc(x+i*8, y, fg, bg, str[i]);
}
/* circle routines from Dr. Dobbs June 1990 */
int xbase, ybase;
unsigned xAspect, yAspect;
void SetAspect(double aspect)
{
xAspect = 0;
yAspect = 0;
aspect = fabs(aspect);
if (aspect != 1.0)
if (aspect > 1.0)
yAspect = 65536.0 / aspect;
else
xAspect = 65536.0 * aspect;
}
void _fastcall c_putcolor(int x, int y, int color)
{
/* avoid writing outside window */
if ( x < xc || y < yc || x >= xc + xd || y >= yc + yd )
return ;
if(y >= sydots - show_numbers) /* avoid overwriting coords */
return;
if(windows == 2) /* avoid overwriting fractal */
if (0 <= x && x < xdots && 0 <= y && y < ydots)
return;
putcolor(x, y, color);
}
int c_getcolor(int x, int y)
{
/* avoid reading outside window */
if ( x < xc || y < yc || x >= xc + xd || y >= yc + yd )
return 1000;
if(y >= sydots - show_numbers) /* avoid overreading coords */
return 1000;
if(windows == 2) /* avoid overreading fractal */
if (0 <= x && x < xdots && 0 <= y && y < ydots)
return 1000;
return getcolor(x, y);
}
void circleplot(int x, int y, int color)
{
if (xAspect == 0)
if (yAspect == 0)
c_putcolor(x+xbase, y+ybase,color);
else
c_putcolor(x+xbase, (short)(ybase + (((long) y * (long) yAspect) >> 16)),color);
else
c_putcolor((int)(xbase + (((long) x * (long) xAspect) >> 16)), y+ybase, color);
}
void plot8(int x, int y, int color)
{
circleplot(x,y,color);
circleplot(-x,y,color);
circleplot(x,-y,color);
circleplot(-x,-y,color);
circleplot(y,x,color);
circleplot(-y,x,color);
circleplot(y,-x,color);
circleplot(-y,-x,color);
}
void circle(int radius, int color)
{
int x,y,sum;
x = 0;
y = radius << 1;
sum = 0;
while (x <= y)
{
if ( !(x & 1) ) /* plot if x is even */
plot8( x >> 1, (y+1) >> 1, color);
sum += (x << 1) + 1;
x++;
if (sum > 0)
{
sum -= (y << 1) - 1;
y--;
}
}
}
/*
* MIIM section:
*
* Global variables and service functions used for computing
* MIIM Julias will be grouped here (and shared by code in LORENZ.C)
*
*/
long ListFront, ListBack, ListSize; /* head, tail, size of MIIM Queue */
long lsize, lmax; /* how many in queue (now, ever) */
int maxhits = 1;
int OKtoMIIM;
int SecretExperimentalMode;
float luckyx = 0, luckyy = 0;
extern int debugflag;
extern int bitshift; /* bit shift for fudge */
extern long fudge; /* fudge factor (2**n) */
long lsqrt(long f)
{
int N;
unsigned long y0, z;
static long a=0, b=0, c=0; /* constant factors */
if (f == 0)
return f;
if (f < 0)
return 0;
if (a==0) /* one-time compute consts */
{
a = fudge * .41731;
b = fudge * .59016;
c = fudge * .7071067811;
}
N = 0;
while (f & 0xff000000L) /* shift arg f into the */
{ /* range: 0.5 <= f < 1 */
N++;
f /= 2;
}
while (!(f & 0xff800000L))
{
N--;
f *= 2;
}
y0 = a + multiply(b, f, bitshift); /* Newton's approximation */
z = y0 + divide (f, y0, bitshift);
y0 = (z>>2) + divide(f, z, bitshift);
if (N % 2)
{
N++;
y0 = multiply(c,y0, bitshift);
}
N /= 2;
if (N >= 0)
return y0 << N; /* correct for shift above */
else
return y0 >> -N;
}
#define SinCosFudge 0x10000L
LCMPLX
ComplexSqrtLong(long x, long y)
{
double mag, theta;
long maglong, thetalong;
LCMPLX result;
#if 1
mag = sqrt(sqrt(((double) multiply(x,x,bitshift))/fudge +
((double) multiply(y,y,bitshift))/ fudge));
maglong = mag * fudge;
#else
maglong = lsqrt(lsqrt(multiply(x,x,bitshift)+multiply(y,y,bitshift)));
#endif
theta = atan2((double) y/fudge, (double) x/fudge)/2;
thetalong = theta * SinCosFudge;
SinCos086(thetalong, &result.y, &result.x);
result.x = multiply(result.x << (bitshift - 16), maglong, bitshift);
result.y = multiply(result.y << (bitshift - 16), maglong, bitshift);
return result;
}
_CMPLX
ComplexSqrtFloat(double x, double y)
{
double mag = sqrt(sqrt(x*x + y*y));
double theta = atan2(y, x) / 2;
_CMPLX result;
FPUsincos(&theta, &result.y, &result.x);
result.x *= mag;
result.y *= mag;
return result;
}
extern char dstack[];
static void fillrect(int x, int y, int width, int depth, int color)
{
/* fast version of fillrect */
if(hasinverse == 0)
return;
memset(dstack, color % colors, width);
while (depth-- > 0)
{
if(keypressed()) /* we could do this less often when in fast modes */
return;
putrow(x, y++, width, dstack);
}
}
/*
* Queue/Stack Section:
*
* Defines a buffer that can be used as a FIFO queue or LIFO stack.
*/
int
QueueEmpty() /* True if NO points remain in queue */
{
return (ListFront == ListBack);
}
int
QueueFull() /* True if room for NO more points in queue */
{
return (((ListFront + 1) % ListSize) == ListBack);
}
int
QueueFullAlmost() /* True if room for ONE more point in queue */
{
return (((ListFront + 2) % ListSize) == ListBack);
}
void
ClearQueue()
{
ListFront = ListBack = lsize = lmax = 0;
}
/*
* Queue functions for MIIM julia:
* move to JIIM.C when done
*/
extern long ListSize, ListFront, ListBack, lsize, lmax;
extern float luckyx, luckyy;
int Init_Queue(unsigned long request)
{
extern int _fastcall common_startdisk(long, long, int);
extern unsigned int xmmlongest();
extern unsigned int xmmreallocate(unsigned int, unsigned int);
extern int dotmode;
unsigned int largest;
if (dotmode == 11)
{
static char far *nono = "Don't try this in disk video mode, kids...\n";
stopmsg(0, nono);
ListSize = 0;
return 0;
}
#if 0
if (xmmquery() && debugflag != 420) /* use LARGEST extended mem */
if ((largest = xmmlongest()) > request / 128)
request = (unsigned long) largest * 128L;
#endif
for (ListSize = request; ListSize > 1024; ListSize -= 512)
switch (common_startdisk(ListSize * 8, 1, 256))
{
case 0: /* success */
ListFront = ListBack = 0;
lsize = lmax = 0;
return 1;
case -1:
continue; /* try smaller queue size */
case -2:
ListSize = 0; /* cancelled by user */
return 0;
}
/* failed to get memory for MIIM Queue */
ListSize = 0;
return 0;
}
void
Free_Queue()
{
enddisk();
ListFront = ListBack = ListSize = lsize = lmax = 0;
}
extern int ToMemDisk (long, int, void far *);
extern int FromMemDisk(long, int, void far *);
int
PushLong(long x, long y)
{
if (((ListFront + 1) % ListSize) != ListBack)
{
if (ToMemDisk(8*ListFront, sizeof(x), &x) &&
ToMemDisk(8*ListFront +sizeof(x), sizeof(y), &y))
{
ListFront = (ListFront + 1) % ListSize;
if (++lsize > lmax)
{
lmax = lsize;
luckyx = x;
luckyy = y;
}
return 1;
}
}
return 0; /* fail */
}
int
PushFloat(float x, float y)
{
if (((ListFront + 1) % ListSize) != ListBack)
{
if (ToMemDisk(8*ListFront, sizeof(x), &x) &&
ToMemDisk(8*ListFront +sizeof(x), sizeof(y), &y))
{
ListFront = (ListFront + 1) % ListSize;
if (++lsize > lmax)
{
lmax = lsize;
luckyx = x;
luckyy = y;
}
return 1;
}
}
return 0; /* fail */
}
_CMPLX
PopFloat()
{
_CMPLX pop;
float popx, popy;
if (!QueueEmpty())
{
ListFront--;
if (ListFront < 0)
ListFront = ListSize - 1;
if (FromMemDisk(8*ListFront, sizeof(popx), &popx) &&
FromMemDisk(8*ListFront +sizeof(popx), sizeof(popy), &popy))
{
pop.x = popx;
pop.y = popy;
--lsize;
}
return pop;
}
pop.x = 0;
pop.y = 0;
return pop;
}
LCMPLX
PopLong()
{
LCMPLX pop;
if (!QueueEmpty())
{
ListFront--;
if (ListFront < 0)
ListFront = ListSize - 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -