/*
* Seven Kingdoms: Ancient Adversaries
*
* Copyright 1997,1998 Enlight Software Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
// Filename : OFLAME.CPP
// Description: class Flame
// Onwership : Gilbert
// Frank Jan Sorensen Alias:Frank Patxi (fjs@lab.jt.dk) for the
// fireroutine.
#include
#include
#include
#include
//-------------- Begin Function Flame::Flame ----------//
Flame::Flame()
{
heat_map = 0;
bitmap = 0;
}
//-------------- End Function Flame::Flame ----------//
//-------------- Begin Function Flame::Flame ----------//
Flame::Flame(short width, short height, short flameWidth, FlameType flameType)
{
heat_map = 0;
bitmap = 0;
init( width, height, flameWidth, flameType);
}
//-------------- End Function Flame::Flame ----------//
//-------------- Begin Function Flame::~Flame ----------//
Flame::~Flame()
{
deinit();
}
//-------------- End Function Flame::~Flame ----------//
//-------------- Begin Function Flame::init ----------//
//
// width width of the bitmap
// height height of the bitmap
// flameWdith length of flame source at base line
// flameType determine how flame source is generated at base line
//
void Flame::init(short width, short height, short flameWidth, FlameType flameType)
{
map_width = width;
map_height = height;
seed = (width * height + flameWidth) | 1;
// allocated more space for overflowing during rise()
heat_map = (unsigned char *) mem_resize(heat_map, width * height + 4);
memset(heat_map, 0, width*height);
bitmap = (unsigned char *) mem_resize(bitmap, width*height + 2*sizeof(short) );
memset(bitmap+2*sizeof(short), width*height, 255);
*(short *)bitmap = width;
*(((short *)bitmap)+1) = height;
smooth = 16;
shade_base = -1;
decay = 800/ height;
if( decay < 2)
decay = 2;
// ---------- put flame sources
switch(flameType)
{
case FLAME_CENTRE_POINT:
{
short i = width/2;
heat_map[i] = 250;
//-------- smoothing around
for( short j = 1 ; j < smooth; ++j)
{
unsigned char k = 250 * (smooth-j)/smooth;
if( i-j >= 0)
heat_map[i-j] = k;
if( i+j < width)
heat_map[i+j] = k;
}
}
break;
case FLAME_RANDOM_POINTS:
{
for(short n = flameWidth*4/smooth; n > 0; --n)
{
short i = (width-flameWidth)/2+random(flameWidth) ;
heat_map[i] = 250;
//-------- smoothing around
for( short j = 1 ; j < smooth; ++j)
{
unsigned char k = 250 * (smooth-j)/smooth;
if( i-j >= 0 && k>heat_map[i-j])
heat_map[i-j] = k;
if( i+j < width && k>heat_map[i+j])
heat_map[i+j] = k;
}
}
}
break;
case FLAME_WIDE:
{
short left = (width - flameWidth)/2;
short right = left + flameWidth;
memset(heat_map+left, 250, flameWidth);
for( short j = 1; j < smooth; ++j)
{
unsigned char k = 250 * (smooth-j)/smooth;
if( left-j >= 0)
heat_map[left-j] = k;
if( right+j <= width)
heat_map[right+j-1] = k;
}
}
break;
default:
err_now("undefined FlameType");
}
}
//-------------- End Function Flame::init ----------//
//-------------- Begin Function Flame::deinit ----------//
void Flame::deinit()
{
if(heat_map)
{
mem_del(heat_map);
heat_map=NULL;
}
if(bitmap)
{
mem_del(bitmap);
bitmap=NULL;
}
}
//-------------- End Function Flame::deinit ----------//
//-------------- Begin Function Flame::operator= ----------//
Flame& Flame::operator= (Flame &f)
{
if(heat_map && f.heat_map && map_width*map_height == f.map_width*f.map_height)
{
memcpy(heat_map, f.heat_map, f.map_width*f.map_height);
}
else
{
if(heat_map)
{
mem_del(heat_map);
heat_map = NULL;
}
if(f.heat_map)
{
heat_map = (unsigned char *) mem_add(f.map_width*f.map_height+4);
memcpy(heat_map, f.heat_map, f.map_width*f.map_height);
}
}
if(bitmap && f.bitmap && map_width*map_height == f.map_width*f.map_height)
{
memcpy(bitmap, f.bitmap, f.map_width*f.map_height + 2*sizeof(short));
}
else
{
if(bitmap)
{
mem_del(bitmap);
bitmap = NULL;
}
if(f.bitmap)
{
bitmap = (unsigned char *) mem_add(f.map_width*f.map_height+2*sizeof(short));
memcpy(bitmap, f.bitmap, f.map_width*f.map_height + 2*sizeof(short));
}
}
seed = f.seed;
map_width = f.map_width;
map_height = f.map_height;
decay = f.decay;
smooth = f.smooth;
shade_base = f.shade_base;
return(*this);
}
//-------------- End Function Flame::operator= ----------//
//-------------- Begin Function Flame::heat_up ----------//
void Flame::heat_up(short h)
{
decay = h;
}
//-------------- End Function Flame::heat_up ----------//
//-------------- Begin Function Flame::rise ----------//
//
// change heat_map to next pattern
// wind -1 = blow left (west), 0 = center, +1 = blow right
//
void Flame::rise(short wind)
{
// rise of each particle of frame
unsigned char *p; // pointer to heat_map
short x,y;
/*
// 1st version, left to right, top to bottom
for( x=0; x < map_width; ++x)
{
y = map_height-2;
p = heat_map + y*map_width + x;
for( ; y >= 0; --y, p-=map_width )
{
unsigned char v = *p;
if( v < decay || x <= 0 || x >= map_width-1)
{
p[map_width] = 0; // the pixel just above
}
else
{
// draw a point on the buffer
p[map_width -random(3)+1 + wind*random(2)] =
v - random(decay);
}
}
}
*/
// 2nd version top to bottom, left to center and right to center
for( y = map_height-2; y >= 0; --y)
{
// left to center
p = heat_map + y * map_width;
for( x = 0; x <= map_width/2; ++x, ++p)
{
unsigned char v = *p;
if( v < decay || x <= 0)
{
p[map_width] = 0; // the pixel just above
}
else
{
// draw a point on the buffer
p[map_width -random(3)+1 + wind*random(2)] =
v - random(decay);
}
}
// right to center
p = heat_map + y * map_width + map_width-1;
for( x = map_width; x > map_width/2; --x, --p)
{
unsigned char v = *p;
if( v < decay || x >= map_width-1)
{
p[map_width] = 0; // the pixel just above
}
else
{
// draw a point on the buffer
p[map_width -random(3)+1 + wind*random(2)] =
v - random(decay);
}
}
}
#if 0
// 2nd version assembly version
const unsigned int BALANCE_PERIOD = 11;
const unsigned int WIND_PERIOD = 13;
const unsigned int DECAY_PERIOD = 17;
char balanceRnd[BALANCE_PERIOD];
char *bRnd = balanceRnd;
char windRnd[WIND_PERIOD];
char *wRnd = windRnd;
char decayRnd[DECAY_PERIOD];
char *dRnd = decayRnd;
unsigned balanceN;
for(balanceN = 0; balanceN < BALANCE_PERIOD; ++balanceN)
{
int r = random(4);
if(r >= 3)
r = 2;
balanceRnd[balanceN] = r-1;
}
unsigned windN;
for(windN = 0; windN < WIND_PERIOD; ++windN)
windRnd[windN] = wind*random(2);
unsigned decayN;
for(decayN = 0; decayN < DECAY_PERIOD; ++decayN)
decayRnd[decayN] = random(decay);
balanceN = 0;
windN = 0;
decayN = 0;
int mapWidth = map_width;
int mapHeight = map_height;
int leftLen = map_width/2;
int rightLen = map_width - leftLen;
p = heat_map + (map_height-2)*map_width;
unsigned char Decay = (unsigned char) decay;
/* Original Visual C++ assembly code for reference
_asm
{
mov ecx, mapHeight
dec ecx
mov esi, p
rise_1:
push ecx
mov ecx, leftLen
; exclude left most dot
dec ecx
mov ebx, mapWidth
mov byte ptr [esi+ebx],0
inc esi
cld
rise_2:
mov edi, esi
lodsb
cmp al, Decay
jnb rise_2a
mov ebx, mapWidth
mov [edi+ebx], 0
jmp rise_2b
rise_2a:
xor ebx, ebx
mov edx, windN
mov bl, windRnd[edx]
mov edx, balanceN
add bl, balanceRnd[edx]
mov edx, decayN
sub al, decayRnd[edx]
movsx ebx, bl
add ebx, mapWidth
mov [edi+ebx], al
; balanceN = (balanceN + 1) % BALANCE_PERIOD
mov edx, balanceN
inc edx
cmp edx, BALANCE_PERIOD
jb rise_2c
xor edx,edx
rise_2c:
mov balanceN, edx
mov edx, windN
inc edx
cmp edx, WIND_PERIOD
jb rise_2d
xor edx,edx
rise_2d:
mov windN, edx
mov edx, decayN
inc edx
cmp edx, DECAY_PERIOD
jb rise_2e
xor edx, edx
rise_2e:
mov decayN, edx
rise_2b:
loop rise_2
mov ecx, rightLen
; ignore rightmost dot
dec ecx
add esi, rightLen
dec esi
mov ebx, mapWidth
mov byte ptr [esi+ebx],0
dec esi
std
rise_3:
mov edi, esi
lodsb
cmp al, Decay
jnb rise_3a
mov ebx, mapWidth
mov [edi+ebx], 0
jmp rise_3b
rise_3a:
xor ebx, ebx
mov edx, windN
mov bl, windRnd[edx]
mov edx, balanceN
sub bl, balanceRnd[edx]
mov edx, decayN
sub al, decayRnd[edx]
movsx ebx, bl
add ebx, mapWidth
mov [edi+ebx], al
; balanceN = (balanceN + 1) % BALANCE_PERIOD
mov edx, balanceN
inc edx
cmp edx, BALANCE_PERIOD
jb rise_3c
xor edx,edx
rise_3c:
mov balanceN, edx
mov edx, windN
inc edx
cmp edx, WIND_PERIOD
jb rise_3d
xor edx, edx
rise_3d:
mov windN, edx
mov edx, decayN
inc edx
cmp edx, DECAY_PERIOD
jb rise_3e
xor edx, edx
rise_3e:
mov decayN, edx
rise_3b:
loop rise_3
pop ecx
sub esi, leftLen
inc esi
sub esi, mapWidth
dec ecx
jz rise_4
jmp rise_1
rise_4:
cld
}
*/
__asm__ __volatile__ (
"movl %0, %%ecx\n\t"
"decl %%ecx\n\t"
"movl %1, %%esi\n\t"
"decl %%ecx\n"
"rise_1:\n\t"
"pushl %%ecx\n\t"
"movl %2, %%ecx\n\t"
"# exclude left most dot\n\t"
"decl %%ecx\n\t"
"movl %3, %%ebx\n\t"
"movb $0, (%%esi, %%ebx)\n\t"
"incl %%esi\n\t"
"cld\n"
"rise_2:\n\t"
"movl %%esi, %%edi\n\t"
"lodsb\n\t"
"cmpb %4, %%al\n\t"
"jnb rise_2a\n\t"
"movl %3, %%ebx\n\t"
"movl $0, (%%edi, %%ebx)\n\t"
"jmp rise_2b\n"
"rise_2a:\n\t"
"xorl %%ebx, %%ebx\n\t"
"movl %5, %%edx\n\t"
"pushl %%edi\n\t"
"leal %6, %%edi\n\t"
"movb (%%edi,%%edx), %%bl\n\t"
"movl %7, %%edx\n\t"
"leal %8, %%edi\n\t"
"addb (%%edi,%%edx), %%bl\n\t"
"movl %9, %%edx\n\t"
"leal %10, %%edi\n\t"
"subb (%%edi,%%edx), %%al\n\t"
"popl %%edi\n\t"
"movsbl %%bl, %%ebx\n\t"
"addl %3, %%ebx\n\t"
"movb %%al, (%%edi,%%ebx)\n\t"
"# balanceN = (balanceN + 1) %% BALANCE_PERIOD\n\t"
"movl %7, %%edx\n\t"
"incl %%edx\n\t"
"cmpl %11, %%edx\n\t"
"jb rise_2c\n\t"
"xorl %%edx, %%edx\n"
"rise_2c:\n\t"
"movl %%edx, %7\n\t"
"movl %5, %%edx\n\t"
"incl %%edx\n\t"
"cmpl %12, %%edx\n\t"
"jb rise_2d\n\t"
"xorl %%edx, %%edx\n"
"rise_2d:\n\t"
"movl %%edx, %5\n\t"
"movl %9, %%edx\n\t"
"incl %%edx\n\t"
"cmpl %13, %%edx\n\t"
"jb rise_2e\n\t"
"xorl %%edx, %%edx\n"
"rise_2e:\n\t"
"movl %%edx, %9\n"
"rise_2b:\n\t"
"loop rise_2\n\t"
"movl %14, %%ecx\n\t"
"# ignore rightmost dot\n\t"
"decl %%ecx\n\t"
"addl %14, %%esi\n\t"
"decl %%esi\n\t"
"movl %3, %%ebx\n\t"
"movb $0, (%%esi,%%ebx)\n\t"
"decl %%esi\n\t"
"std\n"
"rise_3:\n\t"
"movl %%esi, %%edi\n\t"
"lodsb\n\t"
"cmpb %4, %%al\n\t"
"jnb rise_3a\n\t"
"movl %3, %%ebx\n\t"
"movl $0, (%%edi,%%ebx)\n\t"
"jmp rise_3b\n"
"rise_3a:\n\t"
"xorl %%ebx, %%ebx\n\t"
"movl %5, %%edx\n\t"
"pushl %%edi\n\t"
"leal %6, %%edi\n\t"
"movb (%%edi,%%edx), %%bl\n\t"
"movl %7, %%edx\n\t"
"leal %8, %%edi\n\t"
"subb (%%edi,%%edx), %%bl\n\t"
"movl %9, %%edx\n\t"
"leal %10, %%edi\n\t"
"subb (%%edi,%%edx), %%al\n\t"
"popl %%edi\n\t"
"movsbl %%bl, %%ebx\n\t"
"addl %3, %%ebx\n\t"
"movb %%al, (%%edi, %%ebx)\n\t"
"# balanceN = (balanceN + 1) %% BALANCE_PERIOD\n\t"
"movl %7, %%edx\n\t"
"incl %%edx\n\t"
"cmpl %11, %%edx\n\t"
"jb rise_3c\n\t"
"xorl %%edx, %%edx\n"
"rise_3c:\n\t"
"movl %%edx, %7\n\t"
"movl %5, %%edx\n\t"
"incl %%edx\n\t"
"cmpl %12, %%edx\n\t"
"jb rise_3d\n\t"
"xorl %%edx, %%edx\n"
"rise_3d:\n\t"
"movl %%edx, %5\n\t"
"movl %9, %%edx\n\t"
"incl %%edx\n\t"
"cmpl %13, %%edx\n\t"
"jb rise_3e\n\t"
"xor %%edx, %%edx\n"
"rise_3e:\n\t"
"movl %%edx, %9\n"
"rise_3b:\n\t"
"loop rise_3\n\t"
"popl %%ecx\n\t"
"subl %2, %%esi\n\t"
"incl %%esi\n\t"
"subl %3, %%esi\n\t"
"decl %%ecx\n\t"
"jz rise_4\n\t"
"jmp rise_1\n"
"rise_4:\n\t"
"cld\n\t"
:
: "c"(mapHeight),"S"(p),"m"(leftLen),"m"(mapWidth),"m"(Decay),"m"(windN),"m"(wRnd),
"m"(balanceN),"m"(bRnd),"m"(decayN),"m"(dRnd),"i"(BALANCE_PERIOD),
"i"(WIND_PERIOD),"i"(DECAY_PERIOD),"m"(rightLen)
: "%eax","%ebx","%edx","%edi","memory"
);
#endif
}
//-------------- End Function Flame::rise ----------//
//-------------- Begin Function Flame::gen_bitmap ----------//
//
// convert heat_map to transparent bitmap
// to be blt to vgabuf by put_bitmap_trans or put_bitmap_area_trans
//
// [unsigned char] shadeColor first (and brightest) color of the color scale
// (default: 0x10 for yellow-to-red flame)
//
void Flame::gen_bitmap(unsigned char shadeColor)
{
// generate color code
static unsigned char lastShadeBase = 0;
static unsigned char colorTable[256] __asm__("_colorTable");
/* static unsigned char colorTable[256] =
{
TRANSPARENT_CODE, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1,
0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1,
0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1,
0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1,
0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2,
0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2,
0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2,
0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2,
0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2,
0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82,
0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82,
0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82,
0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82,
0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82,
0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82,
0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a,
0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a,
0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a,
0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a,
0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
};
*/
shade_base = shadeColor;
if( shade_base != lastShadeBase )
{
lastShadeBase = (unsigned char)shade_base;
unsigned char *ct = colorTable;
*ct = TRANSPARENT_CODE;
ct++;
for(int b = 1; b <= 255; ++b, ct++)
{
*ct = shadeColor + (b >> 5);
}
}
unsigned char *b = bitmap+2*sizeof(short);
unsigned char *p = heat_map+(map_height-1)*map_width;
short mapHeight = map_height;
short mapWidth = map_width;
/* Original Visual C++ assembly code for reference
_asm
{
mov edi, b
mov esi, p
cld
movzx ecx, mapHeight
movzx edx, mapWidth
lea ebx, colorTable
gen_bitmap_loop2:
push ecx
mov ecx, edx
gen_bitmap_loop3:
lodsb
xlatb [ebx]
stosb
loop gen_bitmap_loop3
sub esi, edx
sub esi, edx
pop ecx
loop gen_bitmap_loop2
}
*/
__asm__ (
"cld\n\t"
"movzb %2, %%ecx\n\t"
"movzb %3, %%edx\n\t"
"leal _colorTable, %%ebx\n\t"
"gen_bitmap_loop2:\n\t"
"pushl %%ecx\n\t"
"movl %%edx, %%ecx\n\t"
"gen_bitmap_loop3:\n\t"
"lodsb\n\t"
"xlatb (%%ebx)\n\t"
"stosb\n\t"
"loop gen_bitmap_loop3\n\t"
"subl %%edx, %%esi\n\t"
"subl %%edx, %%esi\n\t"
"popl %%ecx\n\t"
"loop gen_bitmap_loop2\n\t"
:
: "D"(b),"S"(p),"m"(mapHeight),"m"(mapWidth)
: "%ebx","%ecx","%edx"
);
}
//-------------- End Function Flame::gen_bitmap ----------//
//-------------- Begin Function Flame::mask_bottom ----------//
//
// call after gen_bitmap,
// to round the bottom of bitmap
//
void Flame::mask_bottom()
{
for( short x = 0; x < map_width; ++x)
{
short dx = x - map_width/2;
short y;
// fit a parabola
// h = map_height/4 * (dx / (map_width/2))^2
int h = map_height * dx * dx / (map_width * map_width);
// modify it randomly
if( h > 0)
h += random(3)-1; // -1 to +1
else
h += random(16)/8; // 0 or +1;
unsigned char *p = bitmap+2*sizeof(short)+(map_height-1)*map_width+x;
for(y = 0; y < h; ++y)
{
*p = TRANSPARENT_CODE;
p -= map_width;
}
}
}
//-------------- End Function Flame::mask_bottom ----------//
//-------------- Begin Function Flame::mask_transparent ----------//
//
// call after gen_bitmap,
// mask bitmap out every one out of two points to tranparent
//
void Flame::mask_transparent()
{
unsigned char *b = bitmap + 2*sizeof(short);
if( map_width & 1)
{
// odd number
/*
for( short y = 0; y < map_height; ++y)
for( short x = y & 1; x < map_width; x += 2)
{
*b = 255;
b += 2;
}
*/
int len = map_height * map_width /2;
/* Original Visual C++ assembly code for reference
_asm
{
mov al, TRANSPARENT_CODE
mov edi, b
mov ecx, len
cld
mask_trans_loop1:
stosb
inc edi
loop mask_trans_loop1
}
*/
__asm__ (
"cld\n"
"mask_trans_loop1:\n\t"
"stosb\n\t"
"inc %%edi\n\t"
"loop mask_trans_loop1\n\t"
:
: "a"(TRANSPARENT_CODE),"D"(b),"c"(len)
);
}
else
{
// even number
/*
for( short y = 0; y < map_height; ++y)
{
b+= y & 1; // shift one byte on odd line
for( short x = y & 1; x < map_width; x += 2)
{
*b = 255;
b += 2;
}
b-= y & 1; // shift back to even dot.
}
*/
int mapHeight = map_height, mapWidth = map_width/2;
/* Original Visual C++ assembly code for reference
_asm
{
mov ecx, mapHeight
mov edi, b
mov al, TRANSPARENT_CODE
mov edx,0
mask_trans_loop2:
push ecx
add edi, edx
mov ecx, mapWidth
mask_trans_loop3:
stosb
inc edi
loop mask_trans_loop3
sub edi, edx
pop ecx
xor edx,1
loop mask_trans_loop2
}
*/
__asm__ (
"xorl %%edx,%%edx\n"
"mask_trans_loop2:\n\t"
"pushl %%ecx\n\t"
"addl %%edx,%%edi\n\t"
"movl %3, %%ecx\n"
"mask_trans_loop3:\n\t"
"stosb\n\t"
"incl %%edi\n\t"
"loop mask_trans_loop3\n\t"
"subl %%edx, %%edi\n\t"
"popl %%ecx\n\t"
"xorl $1, %%edx\n\t"
"loop mask_trans_loop2\n\t"
:
: "a"(TRANSPARENT_CODE),"c"(mapHeight),"D"(b),"m"(mapWidth)
: "%edx"
);
}
}
//-------------- End Function Flame::mask_transparent ----------//
//-------------- Begin Function Flame::draw_step ----------//
void Flame::draw_step(short left, short bottom, VgaBuf *vgabuf, short wind)
{
// rise of each particle of frame
unsigned char *p; // pointer to heat_map
unsigned char *d; // pointer to vgabuf
short x,y;
for( x=0; x < map_width; ++x)
{
y = map_height-2;
p = heat_map + y*map_width + x;
d = (unsigned char *)vgabuf->buf_ptr() +
(bottom-y)*vgabuf->buf_pitch() + left + x;
for( ; y >= 0; --y, p-=map_width, d+=vgabuf->buf_pitch() )
{
unsigned char v = *p;
if( /* v == 0 || */ v < decay || x <= 0 || x >= map_width-1)
{
p[map_width] = 0; // the pixel just above
}
else
{
unsigned char n = v - random(decay);
p[map_width -random(3)+1 + wind*random(2)] = n;
// draw a point on the buffer
*d = shade_base + 0x0f - ( n >> 4);
}
}
}
}
//-------------- End Function Flame::mask_transparent ----------//
//-------------- Begin Function Flame::flush_point ---------//
void Flame::flush_point(short x, short y)
{
if( x < 0)
x = random(map_width/2) + random(map_width/2);
if( y < 1)
y = 1 + random(map_height/4);
unsigned char *center = heat_map + y*map_width + x;
*center >>= 3;
center[-1] >>= 2; // left
if( x-2 >= 0)
center[-2] >>= 1;
center[1] >>= 2; // right
if( x+2 < map_width)
center[2] >>= 1;
center[map_width] >>= 2; // top
center[map_width-1] >>= 1;
center[map_width+1] >>= 1;
}
//-------------- End Function Flame::flush_point ---------//
//-------------- Begin Function Flame::random ---------//
unsigned Flame::random(unsigned bound)
{
#define MULTIPLIER 0x015a4e35L
#define INCREMENT 1
seed = MULTIPLIER * seed + INCREMENT;
return seed % bound;
}
//-------------- End Function Flame::random ---------//