A lot of updates
This commit is contained in:
302
zsnes/src/burn.c
Normal file
302
zsnes/src/burn.c
Normal file
@@ -0,0 +1,302 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifndef M_PI
|
||||
#ifndef PI
|
||||
#define M_PI 3.1415926535897932384626433832795
|
||||
#else
|
||||
#define M_PI PI
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
||||
Hi guys, try this, use it in your code, but please credit
|
||||
|
||||
Frank Jan Sorensen Alias:Frank Patxi (fjs@lab.jt.dk) for the
|
||||
fireroutine.
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
Hi again, guys!
|
||||
|
||||
If you use this code, please also credit me, Joachim Fenkes, 'cause I added
|
||||
the following speedups:
|
||||
|
||||
-Replaced one tiny loop with a faster Move(...) (not much speedup)
|
||||
-Wrote the main display loop in 100% assembler, including a faster random
|
||||
number generator (the RNG is only a more or less optimized version of
|
||||
Borland's generator (see MEGARAND.ASM), but with the advantage of the
|
||||
ultimate crash if you call it normally :-)
|
||||
-Changed version number into 1.10 (this isn't a speedup, but necessary :-)
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
Bcoz of the knowledge that reading from videocards is much slower than
|
||||
writing to them, I changed some things to write and read from/to a pointer
|
||||
and put the result with 32-Bit moves to the screen
|
||||
|
||||
Also I added now a much more faster randommer.
|
||||
|
||||
The result of this change is more than 3 times fast than before
|
||||
Stefan Goehler
|
||||
Please credit me!
|
||||
...
|
||||
to JF: your bug is fixed!
|
||||
*/
|
||||
|
||||
/*
|
||||
Oops, silly me, I removed all of the assembly code, so I can let the compiler
|
||||
have at it. Also makes it more portable... even though I am doing this to add
|
||||
to a project that is very non-portable.
|
||||
*/
|
||||
|
||||
#define BUF_WIDTH 288
|
||||
#define BUF_HEIGHT 224
|
||||
|
||||
const int rootrand = 20; /* Max/Min decrease of the root of the flames */
|
||||
const int decay = 5; /* How far should the flames go up on the screen? */
|
||||
/* This MUST be positive - JF */
|
||||
const int miny = 0; /* Startingline of the flame routine.
|
||||
(should be adjusted along with MinY above) */
|
||||
const int smooth = 1; /* How descrete can the flames be?*/
|
||||
const int minfire = 50; /* limit between the "starting to burn" and
|
||||
the "is burning" routines */
|
||||
const int xstart = 0; /* Startingpos on the screen, should be divideable by 4 without remain!*/
|
||||
const int xend = 287; /* Guess! */
|
||||
const int width = 1 + 287; /* +xend-xstart; Well- */
|
||||
const int maxcolor = 110; /* Constant for the MakePal procedure */
|
||||
const int fireincrease = 3; /*3 = Wood, 90 = Gazolin*/
|
||||
|
||||
typedef struct colorvalue
|
||||
{
|
||||
unsigned char r, g, b;
|
||||
} colorvalue;
|
||||
typedef colorvalue vgapalettetype[256];
|
||||
|
||||
void hsi2rgb(double h, double s, double i, struct colorvalue *c)
|
||||
/*Convert (Hue, Saturation, Intensity) -> (RGB)*/
|
||||
{
|
||||
double t;
|
||||
double rv, gv, bv;
|
||||
|
||||
t = h;
|
||||
rv = 1 + s * sin(t - 2 * M_PI / 3);
|
||||
gv = 1 + s * sin(t);
|
||||
bv = 1 + s * sin(t + 2 * M_PI / 3);
|
||||
t = 255.999 * i / 2;
|
||||
{
|
||||
c->r = floor(rv * t);
|
||||
c->g = floor(gv * t);
|
||||
c->b = floor(bv * t);
|
||||
}
|
||||
}
|
||||
|
||||
void genpal()
|
||||
{
|
||||
int i;
|
||||
vgapalettetype pal;
|
||||
|
||||
memset(pal, 0, 3);
|
||||
for( i=1; i <= maxcolor; i ++)
|
||||
hsi2rgb(4.6-1.5*i/maxcolor,(double)(i)/maxcolor,(double)(i)/maxcolor,&pal[i]);
|
||||
for( i=maxcolor; i <= 255; i ++)
|
||||
{
|
||||
pal[i]=pal[i-1];
|
||||
{
|
||||
struct colorvalue *with = &pal[i];
|
||||
|
||||
if (with->r<255) with->r += 1;
|
||||
if (with->r<255) with->r += 1;
|
||||
if ((~i & 1) && (with->g<215)) with->g += 1;
|
||||
if ((~i & 1) && (with->b<255)) with->b += 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int started = 0;
|
||||
|
||||
#if 0 // emulating Turbo Pascal
|
||||
|
||||
unsigned int randseed;
|
||||
const unsigned modulus = 2147483647;
|
||||
const unsigned factor = 397204094;
|
||||
|
||||
void Randomize()
|
||||
{
|
||||
randseed = time(NULL);
|
||||
}
|
||||
|
||||
unsigned int randint(unsigned range)
|
||||
{
|
||||
randseed = randseed * factor % modulus;
|
||||
return range ? randseed % range : 0;
|
||||
}
|
||||
|
||||
double randreal()
|
||||
{
|
||||
randseed = randseed * factor % modulus;
|
||||
return (double)randseed / modulus;
|
||||
}
|
||||
|
||||
int rand1(int r) /* Return a random number between -R And R*/
|
||||
{
|
||||
int result;
|
||||
result=randint(r*2+1)-r;
|
||||
return result;
|
||||
}
|
||||
#else
|
||||
#define Randomize()
|
||||
#define randint(a) (rand() % (a))
|
||||
#define randreal() (((double)rand()) / ((double)RAND_MAX))
|
||||
#define rand1(a) ((randint(a*2+1))-a)
|
||||
#endif
|
||||
|
||||
unsigned char flamearray[BUF_WIDTH];
|
||||
int morefire;
|
||||
extern unsigned char *vidbuffer;
|
||||
|
||||
/* damn, this seems like such a waste */
|
||||
static unsigned char pt[BUF_WIDTH * BUF_HEIGHT];
|
||||
|
||||
#if 0
|
||||
|
||||
int burn_init()
|
||||
{
|
||||
int i;
|
||||
|
||||
if (flamearray) return 1;
|
||||
|
||||
flamearray = (unsigned char *) malloc(BUF_WIDTH);
|
||||
|
||||
for( i=xstart; i <= xend; i++)
|
||||
flamearray[i]=0;
|
||||
|
||||
Randomize();
|
||||
|
||||
morefire=1;
|
||||
genpal();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void burn_shutdown()
|
||||
{
|
||||
if (flamearray)
|
||||
{
|
||||
free(flamearray);
|
||||
flamearray = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void DrawBurn()
|
||||
{
|
||||
int i,j;
|
||||
int x,p;
|
||||
int v;
|
||||
|
||||
if (!started)
|
||||
{
|
||||
started = 1;
|
||||
|
||||
for( i=xstart; i <= xend; i++)
|
||||
flamearray[i]=0;
|
||||
|
||||
Randomize();
|
||||
|
||||
morefire=1;
|
||||
|
||||
memset(pt, 0, BUF_HEIGHT * BUF_WIDTH);
|
||||
/* genpal(); */
|
||||
}
|
||||
|
||||
/*
|
||||
for (x=0; x < BUF_WIDTH*BUF_HEIGHT; x++)
|
||||
{
|
||||
i = pt[x];
|
||||
j = vidbuffer[x] << 2;
|
||||
|
||||
if (i > j) pt[x] = i;
|
||||
else pt[x] = (i + j) >> 1;
|
||||
}
|
||||
*/
|
||||
|
||||
/* Put the values from FlameArray on the bottom line of the screen */
|
||||
memcpy(pt+((BUF_HEIGHT-1)*BUF_WIDTH)+xstart,flamearray, width);
|
||||
|
||||
/* This loop makes the actual flames */
|
||||
|
||||
for( i=xstart; i <= xend; i++)
|
||||
for( j=miny; j <= (BUF_HEIGHT-1); j ++)
|
||||
{
|
||||
v = pt[j*BUF_WIDTH + i];
|
||||
if ((v==0) ||
|
||||
(v<decay) ||
|
||||
(i<=xstart) ||
|
||||
(i>=xend))
|
||||
pt[(j-1)*BUF_WIDTH + i] = 0;
|
||||
else
|
||||
pt[((j-1)*BUF_WIDTH) + (i-(randint(3)-1))] = v - randint(decay);
|
||||
}
|
||||
|
||||
/*Match?*/
|
||||
if (randint(150)==0)
|
||||
memset(flamearray + xstart + randint(xend-xstart-5),255,5);
|
||||
|
||||
/*This loop controls the "root" of the
|
||||
flames ie. the values in FlameArray.*/
|
||||
for( i=xstart; i <= xend; i++)
|
||||
{
|
||||
x=flamearray[i];
|
||||
|
||||
if (x<minfire) /* Increase by the "burnability"*/
|
||||
{
|
||||
/*Starting to burn:*/
|
||||
if (x>10) x += randint(fireincrease);
|
||||
}
|
||||
else
|
||||
/* Otherwise randomize and increase by intensity (is burning)*/
|
||||
x += rand1(rootrand)+morefire;
|
||||
if (x>255) x=255; /* X Too large ?*/
|
||||
flamearray[i]=x;
|
||||
}
|
||||
|
||||
|
||||
/* Pour a little water on both sides of
|
||||
the fire to make it look nice on the sides*/
|
||||
/*
|
||||
for( i=1; i <= width / 8; i ++)
|
||||
{
|
||||
x=floor(sqrt(randreal())*width/8);
|
||||
flamearray[xstart+x]=0;
|
||||
flamearray[xend-x]=0;
|
||||
}
|
||||
*/
|
||||
|
||||
/*Smoothen the values of FrameArray to avoid "descrete" flames*/
|
||||
p=0;
|
||||
for( i=xstart+smooth; i <= xend-smooth; i++)
|
||||
{
|
||||
x=0;
|
||||
for( j=-smooth; j <= smooth; j++) x += flamearray[i+j];
|
||||
flamearray[i] = x / ((smooth << 1) + 1);
|
||||
}
|
||||
|
||||
for (x=0; x < BUF_WIDTH*BUF_HEIGHT; x++)
|
||||
{
|
||||
i = vidbuffer[x];
|
||||
j = pt[x] >> 3;
|
||||
|
||||
if (j > i) vidbuffer[x] = j;
|
||||
else vidbuffer[x] = ((i + j) >> 1) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user