OFLAME.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943
  1. /*
  2. * Seven Kingdoms: Ancient Adversaries
  3. *
  4. * Copyright 1997,1998 Enlight Software Ltd.
  5. *
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. *
  19. */
  20. // Filename : OFLAME.CPP
  21. // Description: class Flame
  22. // Onwership : Gilbert
  23. // Frank Jan Sorensen Alias:Frank Patxi (fjs@lab.jt.dk) for the
  24. // fireroutine.
  25. #include <OFLAME.h>
  26. #include <OVGABUF.h>
  27. #include <ALL.h>
  28. #include <COLCODE.h>
  29. //-------------- Begin Function Flame::Flame ----------//
  30. Flame::Flame()
  31. {
  32. heat_map = 0;
  33. bitmap = 0;
  34. }
  35. //-------------- End Function Flame::Flame ----------//
  36. //-------------- Begin Function Flame::Flame ----------//
  37. Flame::Flame(short width, short height, short flameWidth, FlameType flameType)
  38. {
  39. heat_map = 0;
  40. bitmap = 0;
  41. init( width, height, flameWidth, flameType);
  42. }
  43. //-------------- End Function Flame::Flame ----------//
  44. //-------------- Begin Function Flame::~Flame ----------//
  45. Flame::~Flame()
  46. {
  47. deinit();
  48. }
  49. //-------------- End Function Flame::~Flame ----------//
  50. //-------------- Begin Function Flame::init ----------//
  51. //
  52. // <short> width width of the bitmap
  53. // <short> height height of the bitmap
  54. // <short> flameWdith length of flame source at base line
  55. // <FlameType> flameType determine how flame source is generated at base line
  56. //
  57. void Flame::init(short width, short height, short flameWidth, FlameType flameType)
  58. {
  59. map_width = width;
  60. map_height = height;
  61. seed = (width * height + flameWidth) | 1;
  62. // allocated more space for overflowing during rise()
  63. heat_map = (unsigned char *) mem_resize(heat_map, width * height + 4);
  64. memset(heat_map, 0, width*height);
  65. bitmap = (unsigned char *) mem_resize(bitmap, width*height + 2*sizeof(short) );
  66. memset(bitmap+2*sizeof(short), width*height, 255);
  67. *(short *)bitmap = width;
  68. *(((short *)bitmap)+1) = height;
  69. smooth = 16;
  70. shade_base = -1;
  71. decay = 800/ height;
  72. if( decay < 2)
  73. decay = 2;
  74. // ---------- put flame sources
  75. switch(flameType)
  76. {
  77. case FLAME_CENTRE_POINT:
  78. {
  79. short i = width/2;
  80. heat_map[i] = 250;
  81. //-------- smoothing around
  82. for( short j = 1 ; j < smooth; ++j)
  83. {
  84. unsigned char k = 250 * (smooth-j)/smooth;
  85. if( i-j >= 0)
  86. heat_map[i-j] = k;
  87. if( i+j < width)
  88. heat_map[i+j] = k;
  89. }
  90. }
  91. break;
  92. case FLAME_RANDOM_POINTS:
  93. {
  94. for(short n = flameWidth*4/smooth; n > 0; --n)
  95. {
  96. short i = (width-flameWidth)/2+random(flameWidth) ;
  97. heat_map[i] = 250;
  98. //-------- smoothing around
  99. for( short j = 1 ; j < smooth; ++j)
  100. {
  101. unsigned char k = 250 * (smooth-j)/smooth;
  102. if( i-j >= 0 && k>heat_map[i-j])
  103. heat_map[i-j] = k;
  104. if( i+j < width && k>heat_map[i+j])
  105. heat_map[i+j] = k;
  106. }
  107. }
  108. }
  109. break;
  110. case FLAME_WIDE:
  111. {
  112. short left = (width - flameWidth)/2;
  113. short right = left + flameWidth;
  114. memset(heat_map+left, 250, flameWidth);
  115. for( short j = 1; j < smooth; ++j)
  116. {
  117. unsigned char k = 250 * (smooth-j)/smooth;
  118. if( left-j >= 0)
  119. heat_map[left-j] = k;
  120. if( right+j <= width)
  121. heat_map[right+j-1] = k;
  122. }
  123. }
  124. break;
  125. default:
  126. err_now("undefined FlameType");
  127. }
  128. }
  129. //-------------- End Function Flame::init ----------//
  130. //-------------- Begin Function Flame::deinit ----------//
  131. void Flame::deinit()
  132. {
  133. if(heat_map)
  134. {
  135. mem_del(heat_map);
  136. heat_map=NULL;
  137. }
  138. if(bitmap)
  139. {
  140. mem_del(bitmap);
  141. bitmap=NULL;
  142. }
  143. }
  144. //-------------- End Function Flame::deinit ----------//
  145. //-------------- Begin Function Flame::operator= ----------//
  146. Flame& Flame::operator= (Flame &f)
  147. {
  148. if(heat_map && f.heat_map && map_width*map_height == f.map_width*f.map_height)
  149. {
  150. memcpy(heat_map, f.heat_map, f.map_width*f.map_height);
  151. }
  152. else
  153. {
  154. if(heat_map)
  155. {
  156. mem_del(heat_map);
  157. heat_map = NULL;
  158. }
  159. if(f.heat_map)
  160. {
  161. heat_map = (unsigned char *) mem_add(f.map_width*f.map_height+4);
  162. memcpy(heat_map, f.heat_map, f.map_width*f.map_height);
  163. }
  164. }
  165. if(bitmap && f.bitmap && map_width*map_height == f.map_width*f.map_height)
  166. {
  167. memcpy(bitmap, f.bitmap, f.map_width*f.map_height + 2*sizeof(short));
  168. }
  169. else
  170. {
  171. if(bitmap)
  172. {
  173. mem_del(bitmap);
  174. bitmap = NULL;
  175. }
  176. if(f.bitmap)
  177. {
  178. bitmap = (unsigned char *) mem_add(f.map_width*f.map_height+2*sizeof(short));
  179. memcpy(bitmap, f.bitmap, f.map_width*f.map_height + 2*sizeof(short));
  180. }
  181. }
  182. seed = f.seed;
  183. map_width = f.map_width;
  184. map_height = f.map_height;
  185. decay = f.decay;
  186. smooth = f.smooth;
  187. shade_base = f.shade_base;
  188. return(*this);
  189. }
  190. //-------------- End Function Flame::operator= ----------//
  191. //-------------- Begin Function Flame::heat_up ----------//
  192. void Flame::heat_up(short h)
  193. {
  194. decay = h;
  195. }
  196. //-------------- End Function Flame::heat_up ----------//
  197. //-------------- Begin Function Flame::rise ----------//
  198. //
  199. // change heat_map to next pattern
  200. // <short> wind -1 = blow left (west), 0 = center, +1 = blow right
  201. //
  202. void Flame::rise(short wind)
  203. {
  204. // rise of each particle of frame
  205. unsigned char *p; // pointer to heat_map
  206. short x,y;
  207. /*
  208. // 1st version, left to right, top to bottom
  209. for( x=0; x < map_width; ++x)
  210. {
  211. y = map_height-2;
  212. p = heat_map + y*map_width + x;
  213. for( ; y >= 0; --y, p-=map_width )
  214. {
  215. unsigned char v = *p;
  216. if( v < decay || x <= 0 || x >= map_width-1)
  217. {
  218. p[map_width] = 0; // the pixel just above
  219. }
  220. else
  221. {
  222. // draw a point on the buffer
  223. p[map_width -random(3)+1 + wind*random(2)] =
  224. v - random(decay);
  225. }
  226. }
  227. }
  228. */
  229. // 2nd version top to bottom, left to center and right to center
  230. for( y = map_height-2; y >= 0; --y)
  231. {
  232. // left to center
  233. p = heat_map + y * map_width;
  234. for( x = 0; x <= map_width/2; ++x, ++p)
  235. {
  236. unsigned char v = *p;
  237. if( v < decay || x <= 0)
  238. {
  239. p[map_width] = 0; // the pixel just above
  240. }
  241. else
  242. {
  243. // draw a point on the buffer
  244. p[map_width -random(3)+1 + wind*random(2)] =
  245. v - random(decay);
  246. }
  247. }
  248. // right to center
  249. p = heat_map + y * map_width + map_width-1;
  250. for( x = map_width; x > map_width/2; --x, --p)
  251. {
  252. unsigned char v = *p;
  253. if( v < decay || x >= map_width-1)
  254. {
  255. p[map_width] = 0; // the pixel just above
  256. }
  257. else
  258. {
  259. // draw a point on the buffer
  260. p[map_width -random(3)+1 + wind*random(2)] =
  261. v - random(decay);
  262. }
  263. }
  264. }
  265. #if 0
  266. // 2nd version assembly version
  267. const unsigned int BALANCE_PERIOD = 11;
  268. const unsigned int WIND_PERIOD = 13;
  269. const unsigned int DECAY_PERIOD = 17;
  270. char balanceRnd[BALANCE_PERIOD];
  271. char *bRnd = balanceRnd;
  272. char windRnd[WIND_PERIOD];
  273. char *wRnd = windRnd;
  274. char decayRnd[DECAY_PERIOD];
  275. char *dRnd = decayRnd;
  276. unsigned balanceN;
  277. for(balanceN = 0; balanceN < BALANCE_PERIOD; ++balanceN)
  278. {
  279. int r = random(4);
  280. if(r >= 3)
  281. r = 2;
  282. balanceRnd[balanceN] = r-1;
  283. }
  284. unsigned windN;
  285. for(windN = 0; windN < WIND_PERIOD; ++windN)
  286. windRnd[windN] = wind*random(2);
  287. unsigned decayN;
  288. for(decayN = 0; decayN < DECAY_PERIOD; ++decayN)
  289. decayRnd[decayN] = random(decay);
  290. balanceN = 0;
  291. windN = 0;
  292. decayN = 0;
  293. int mapWidth = map_width;
  294. int mapHeight = map_height;
  295. int leftLen = map_width/2;
  296. int rightLen = map_width - leftLen;
  297. p = heat_map + (map_height-2)*map_width;
  298. unsigned char Decay = (unsigned char) decay;
  299. /* Original Visual C++ assembly code for reference
  300. _asm
  301. {
  302. mov ecx, mapHeight
  303. dec ecx
  304. mov esi, p
  305. rise_1:
  306. push ecx
  307. mov ecx, leftLen
  308. ; exclude left most dot
  309. dec ecx
  310. mov ebx, mapWidth
  311. mov byte ptr [esi+ebx],0
  312. inc esi
  313. cld
  314. rise_2:
  315. mov edi, esi
  316. lodsb
  317. cmp al, Decay
  318. jnb rise_2a
  319. mov ebx, mapWidth
  320. mov [edi+ebx], 0
  321. jmp rise_2b
  322. rise_2a:
  323. xor ebx, ebx
  324. mov edx, windN
  325. mov bl, windRnd[edx]
  326. mov edx, balanceN
  327. add bl, balanceRnd[edx]
  328. mov edx, decayN
  329. sub al, decayRnd[edx]
  330. movsx ebx, bl
  331. add ebx, mapWidth
  332. mov [edi+ebx], al
  333. ; balanceN = (balanceN + 1) % BALANCE_PERIOD
  334. mov edx, balanceN
  335. inc edx
  336. cmp edx, BALANCE_PERIOD
  337. jb rise_2c
  338. xor edx,edx
  339. rise_2c:
  340. mov balanceN, edx
  341. mov edx, windN
  342. inc edx
  343. cmp edx, WIND_PERIOD
  344. jb rise_2d
  345. xor edx,edx
  346. rise_2d:
  347. mov windN, edx
  348. mov edx, decayN
  349. inc edx
  350. cmp edx, DECAY_PERIOD
  351. jb rise_2e
  352. xor edx, edx
  353. rise_2e:
  354. mov decayN, edx
  355. rise_2b:
  356. loop rise_2
  357. mov ecx, rightLen
  358. ; ignore rightmost dot
  359. dec ecx
  360. add esi, rightLen
  361. dec esi
  362. mov ebx, mapWidth
  363. mov byte ptr [esi+ebx],0
  364. dec esi
  365. std
  366. rise_3:
  367. mov edi, esi
  368. lodsb
  369. cmp al, Decay
  370. jnb rise_3a
  371. mov ebx, mapWidth
  372. mov [edi+ebx], 0
  373. jmp rise_3b
  374. rise_3a:
  375. xor ebx, ebx
  376. mov edx, windN
  377. mov bl, windRnd[edx]
  378. mov edx, balanceN
  379. sub bl, balanceRnd[edx]
  380. mov edx, decayN
  381. sub al, decayRnd[edx]
  382. movsx ebx, bl
  383. add ebx, mapWidth
  384. mov [edi+ebx], al
  385. ; balanceN = (balanceN + 1) % BALANCE_PERIOD
  386. mov edx, balanceN
  387. inc edx
  388. cmp edx, BALANCE_PERIOD
  389. jb rise_3c
  390. xor edx,edx
  391. rise_3c:
  392. mov balanceN, edx
  393. mov edx, windN
  394. inc edx
  395. cmp edx, WIND_PERIOD
  396. jb rise_3d
  397. xor edx, edx
  398. rise_3d:
  399. mov windN, edx
  400. mov edx, decayN
  401. inc edx
  402. cmp edx, DECAY_PERIOD
  403. jb rise_3e
  404. xor edx, edx
  405. rise_3e:
  406. mov decayN, edx
  407. rise_3b:
  408. loop rise_3
  409. pop ecx
  410. sub esi, leftLen
  411. inc esi
  412. sub esi, mapWidth
  413. dec ecx
  414. jz rise_4
  415. jmp rise_1
  416. rise_4:
  417. cld
  418. }
  419. */
  420. __asm__ __volatile__ (
  421. "movl %0, %%ecx\n\t"
  422. "decl %%ecx\n\t"
  423. "movl %1, %%esi\n\t"
  424. "decl %%ecx\n"
  425. "rise_1:\n\t"
  426. "pushl %%ecx\n\t"
  427. "movl %2, %%ecx\n\t"
  428. "# exclude left most dot\n\t"
  429. "decl %%ecx\n\t"
  430. "movl %3, %%ebx\n\t"
  431. "movb $0, (%%esi, %%ebx)\n\t"
  432. "incl %%esi\n\t"
  433. "cld\n"
  434. "rise_2:\n\t"
  435. "movl %%esi, %%edi\n\t"
  436. "lodsb\n\t"
  437. "cmpb %4, %%al\n\t"
  438. "jnb rise_2a\n\t"
  439. "movl %3, %%ebx\n\t"
  440. "movl $0, (%%edi, %%ebx)\n\t"
  441. "jmp rise_2b\n"
  442. "rise_2a:\n\t"
  443. "xorl %%ebx, %%ebx\n\t"
  444. "movl %5, %%edx\n\t"
  445. "pushl %%edi\n\t"
  446. "leal %6, %%edi\n\t"
  447. "movb (%%edi,%%edx), %%bl\n\t"
  448. "movl %7, %%edx\n\t"
  449. "leal %8, %%edi\n\t"
  450. "addb (%%edi,%%edx), %%bl\n\t"
  451. "movl %9, %%edx\n\t"
  452. "leal %10, %%edi\n\t"
  453. "subb (%%edi,%%edx), %%al\n\t"
  454. "popl %%edi\n\t"
  455. "movsbl %%bl, %%ebx\n\t"
  456. "addl %3, %%ebx\n\t"
  457. "movb %%al, (%%edi,%%ebx)\n\t"
  458. "# balanceN = (balanceN + 1) %% BALANCE_PERIOD\n\t"
  459. "movl %7, %%edx\n\t"
  460. "incl %%edx\n\t"
  461. "cmpl %11, %%edx\n\t"
  462. "jb rise_2c\n\t"
  463. "xorl %%edx, %%edx\n"
  464. "rise_2c:\n\t"
  465. "movl %%edx, %7\n\t"
  466. "movl %5, %%edx\n\t"
  467. "incl %%edx\n\t"
  468. "cmpl %12, %%edx\n\t"
  469. "jb rise_2d\n\t"
  470. "xorl %%edx, %%edx\n"
  471. "rise_2d:\n\t"
  472. "movl %%edx, %5\n\t"
  473. "movl %9, %%edx\n\t"
  474. "incl %%edx\n\t"
  475. "cmpl %13, %%edx\n\t"
  476. "jb rise_2e\n\t"
  477. "xorl %%edx, %%edx\n"
  478. "rise_2e:\n\t"
  479. "movl %%edx, %9\n"
  480. "rise_2b:\n\t"
  481. "loop rise_2\n\t"
  482. "movl %14, %%ecx\n\t"
  483. "# ignore rightmost dot\n\t"
  484. "decl %%ecx\n\t"
  485. "addl %14, %%esi\n\t"
  486. "decl %%esi\n\t"
  487. "movl %3, %%ebx\n\t"
  488. "movb $0, (%%esi,%%ebx)\n\t"
  489. "decl %%esi\n\t"
  490. "std\n"
  491. "rise_3:\n\t"
  492. "movl %%esi, %%edi\n\t"
  493. "lodsb\n\t"
  494. "cmpb %4, %%al\n\t"
  495. "jnb rise_3a\n\t"
  496. "movl %3, %%ebx\n\t"
  497. "movl $0, (%%edi,%%ebx)\n\t"
  498. "jmp rise_3b\n"
  499. "rise_3a:\n\t"
  500. "xorl %%ebx, %%ebx\n\t"
  501. "movl %5, %%edx\n\t"
  502. "pushl %%edi\n\t"
  503. "leal %6, %%edi\n\t"
  504. "movb (%%edi,%%edx), %%bl\n\t"
  505. "movl %7, %%edx\n\t"
  506. "leal %8, %%edi\n\t"
  507. "subb (%%edi,%%edx), %%bl\n\t"
  508. "movl %9, %%edx\n\t"
  509. "leal %10, %%edi\n\t"
  510. "subb (%%edi,%%edx), %%al\n\t"
  511. "popl %%edi\n\t"
  512. "movsbl %%bl, %%ebx\n\t"
  513. "addl %3, %%ebx\n\t"
  514. "movb %%al, (%%edi, %%ebx)\n\t"
  515. "# balanceN = (balanceN + 1) %% BALANCE_PERIOD\n\t"
  516. "movl %7, %%edx\n\t"
  517. "incl %%edx\n\t"
  518. "cmpl %11, %%edx\n\t"
  519. "jb rise_3c\n\t"
  520. "xorl %%edx, %%edx\n"
  521. "rise_3c:\n\t"
  522. "movl %%edx, %7\n\t"
  523. "movl %5, %%edx\n\t"
  524. "incl %%edx\n\t"
  525. "cmpl %12, %%edx\n\t"
  526. "jb rise_3d\n\t"
  527. "xorl %%edx, %%edx\n"
  528. "rise_3d:\n\t"
  529. "movl %%edx, %5\n\t"
  530. "movl %9, %%edx\n\t"
  531. "incl %%edx\n\t"
  532. "cmpl %13, %%edx\n\t"
  533. "jb rise_3e\n\t"
  534. "xor %%edx, %%edx\n"
  535. "rise_3e:\n\t"
  536. "movl %%edx, %9\n"
  537. "rise_3b:\n\t"
  538. "loop rise_3\n\t"
  539. "popl %%ecx\n\t"
  540. "subl %2, %%esi\n\t"
  541. "incl %%esi\n\t"
  542. "subl %3, %%esi\n\t"
  543. "decl %%ecx\n\t"
  544. "jz rise_4\n\t"
  545. "jmp rise_1\n"
  546. "rise_4:\n\t"
  547. "cld\n\t"
  548. :
  549. : "c"(mapHeight),"S"(p),"m"(leftLen),"m"(mapWidth),"m"(Decay),"m"(windN),"m"(wRnd),
  550. "m"(balanceN),"m"(bRnd),"m"(decayN),"m"(dRnd),"i"(BALANCE_PERIOD),
  551. "i"(WIND_PERIOD),"i"(DECAY_PERIOD),"m"(rightLen)
  552. : "%eax","%ebx","%edx","%edi","memory"
  553. );
  554. #endif
  555. }
  556. //-------------- End Function Flame::rise ----------//
  557. //-------------- Begin Function Flame::gen_bitmap ----------//
  558. //
  559. // convert heat_map to transparent bitmap
  560. // to be blt to vgabuf by put_bitmap_trans or put_bitmap_area_trans
  561. //
  562. // [unsigned char] shadeColor first (and brightest) color of the color scale
  563. // (default: 0x10 for yellow-to-red flame)
  564. //
  565. void Flame::gen_bitmap(unsigned char shadeColor)
  566. {
  567. // generate color code
  568. static unsigned char lastShadeBase = 0;
  569. static unsigned char colorTable[256] __asm__("_colorTable");
  570. /* static unsigned char colorTable[256] =
  571. {
  572. TRANSPARENT_CODE, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
  573. 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
  574. 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
  575. 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
  576. 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1,
  577. 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1,
  578. 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1,
  579. 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1,
  580. 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2,
  581. 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2,
  582. 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2,
  583. 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2,
  584. 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2,
  585. 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82,
  586. 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82,
  587. 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82,
  588. 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82,
  589. 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82,
  590. 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82,
  591. 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a,
  592. 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a,
  593. 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a,
  594. 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a,
  595. 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a,
  596. 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
  597. 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
  598. 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
  599. 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
  600. 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
  601. 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
  602. 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
  603. 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
  604. };
  605. */
  606. shade_base = shadeColor;
  607. if( shade_base != lastShadeBase )
  608. {
  609. lastShadeBase = (unsigned char)shade_base;
  610. unsigned char *ct = colorTable;
  611. *ct = TRANSPARENT_CODE;
  612. ct++;
  613. for(int b = 1; b <= 255; ++b, ct++)
  614. {
  615. *ct = shadeColor + (b >> 5);
  616. }
  617. }
  618. unsigned char *b = bitmap+2*sizeof(short);
  619. unsigned char *p = heat_map+(map_height-1)*map_width;
  620. short mapHeight = map_height;
  621. short mapWidth = map_width;
  622. /* Original Visual C++ assembly code for reference
  623. _asm
  624. {
  625. mov edi, b
  626. mov esi, p
  627. cld
  628. movzx ecx, mapHeight
  629. movzx edx, mapWidth
  630. lea ebx, colorTable
  631. gen_bitmap_loop2:
  632. push ecx
  633. mov ecx, edx
  634. gen_bitmap_loop3:
  635. lodsb
  636. xlatb [ebx]
  637. stosb
  638. loop gen_bitmap_loop3
  639. sub esi, edx
  640. sub esi, edx
  641. pop ecx
  642. loop gen_bitmap_loop2
  643. }
  644. */
  645. __asm__ (
  646. "cld\n\t"
  647. "movzb %2, %%ecx\n\t"
  648. "movzb %3, %%edx\n\t"
  649. "leal _colorTable, %%ebx\n\t"
  650. "gen_bitmap_loop2:\n\t"
  651. "pushl %%ecx\n\t"
  652. "movl %%edx, %%ecx\n\t"
  653. "gen_bitmap_loop3:\n\t"
  654. "lodsb\n\t"
  655. "xlatb (%%ebx)\n\t"
  656. "stosb\n\t"
  657. "loop gen_bitmap_loop3\n\t"
  658. "subl %%edx, %%esi\n\t"
  659. "subl %%edx, %%esi\n\t"
  660. "popl %%ecx\n\t"
  661. "loop gen_bitmap_loop2\n\t"
  662. :
  663. : "D"(b),"S"(p),"m"(mapHeight),"m"(mapWidth)
  664. : "%ebx","%ecx","%edx"
  665. );
  666. }
  667. //-------------- End Function Flame::gen_bitmap ----------//
  668. //-------------- Begin Function Flame::mask_bottom ----------//
  669. //
  670. // call after gen_bitmap,
  671. // to round the bottom of bitmap
  672. //
  673. void Flame::mask_bottom()
  674. {
  675. for( short x = 0; x < map_width; ++x)
  676. {
  677. short dx = x - map_width/2;
  678. short y;
  679. // fit a parabola
  680. // h = map_height/4 * (dx / (map_width/2))^2
  681. int h = map_height * dx * dx / (map_width * map_width);
  682. // modify it randomly
  683. if( h > 0)
  684. h += random(3)-1; // -1 to +1
  685. else
  686. h += random(16)/8; // 0 or +1;
  687. unsigned char *p = bitmap+2*sizeof(short)+(map_height-1)*map_width+x;
  688. for(y = 0; y < h; ++y)
  689. {
  690. *p = TRANSPARENT_CODE;
  691. p -= map_width;
  692. }
  693. }
  694. }
  695. //-------------- End Function Flame::mask_bottom ----------//
  696. //-------------- Begin Function Flame::mask_transparent ----------//
  697. //
  698. // call after gen_bitmap,
  699. // mask bitmap out every one out of two points to tranparent
  700. //
  701. void Flame::mask_transparent()
  702. {
  703. unsigned char *b = bitmap + 2*sizeof(short);
  704. if( map_width & 1)
  705. {
  706. // odd number
  707. /*
  708. for( short y = 0; y < map_height; ++y)
  709. for( short x = y & 1; x < map_width; x += 2)
  710. {
  711. *b = 255;
  712. b += 2;
  713. }
  714. */
  715. int len = map_height * map_width /2;
  716. /* Original Visual C++ assembly code for reference
  717. _asm
  718. {
  719. mov al, TRANSPARENT_CODE
  720. mov edi, b
  721. mov ecx, len
  722. cld
  723. mask_trans_loop1:
  724. stosb
  725. inc edi
  726. loop mask_trans_loop1
  727. }
  728. */
  729. __asm__ (
  730. "cld\n"
  731. "mask_trans_loop1:\n\t"
  732. "stosb\n\t"
  733. "inc %%edi\n\t"
  734. "loop mask_trans_loop1\n\t"
  735. :
  736. : "a"(TRANSPARENT_CODE),"D"(b),"c"(len)
  737. );
  738. }
  739. else
  740. {
  741. // even number
  742. /*
  743. for( short y = 0; y < map_height; ++y)
  744. {
  745. b+= y & 1; // shift one byte on odd line
  746. for( short x = y & 1; x < map_width; x += 2)
  747. {
  748. *b = 255;
  749. b += 2;
  750. }
  751. b-= y & 1; // shift back to even dot.
  752. }
  753. */
  754. int mapHeight = map_height, mapWidth = map_width/2;
  755. /* Original Visual C++ assembly code for reference
  756. _asm
  757. {
  758. mov ecx, mapHeight
  759. mov edi, b
  760. mov al, TRANSPARENT_CODE
  761. mov edx,0
  762. mask_trans_loop2:
  763. push ecx
  764. add edi, edx
  765. mov ecx, mapWidth
  766. mask_trans_loop3:
  767. stosb
  768. inc edi
  769. loop mask_trans_loop3
  770. sub edi, edx
  771. pop ecx
  772. xor edx,1
  773. loop mask_trans_loop2
  774. }
  775. */
  776. __asm__ (
  777. "xorl %%edx,%%edx\n"
  778. "mask_trans_loop2:\n\t"
  779. "pushl %%ecx\n\t"
  780. "addl %%edx,%%edi\n\t"
  781. "movl %3, %%ecx\n"
  782. "mask_trans_loop3:\n\t"
  783. "stosb\n\t"
  784. "incl %%edi\n\t"
  785. "loop mask_trans_loop3\n\t"
  786. "subl %%edx, %%edi\n\t"
  787. "popl %%ecx\n\t"
  788. "xorl $1, %%edx\n\t"
  789. "loop mask_trans_loop2\n\t"
  790. :
  791. : "a"(TRANSPARENT_CODE),"c"(mapHeight),"D"(b),"m"(mapWidth)
  792. : "%edx"
  793. );
  794. }
  795. }
  796. //-------------- End Function Flame::mask_transparent ----------//
  797. //-------------- Begin Function Flame::draw_step ----------//
  798. void Flame::draw_step(short left, short bottom, VgaBuf *vgabuf, short wind)
  799. {
  800. // rise of each particle of frame
  801. unsigned char *p; // pointer to heat_map
  802. unsigned char *d; // pointer to vgabuf
  803. short x,y;
  804. for( x=0; x < map_width; ++x)
  805. {
  806. y = map_height-2;
  807. p = heat_map + y*map_width + x;
  808. d = (unsigned char *)vgabuf->buf_ptr() +
  809. (bottom-y)*vgabuf->buf_pitch() + left + x;
  810. for( ; y >= 0; --y, p-=map_width, d+=vgabuf->buf_pitch() )
  811. {
  812. unsigned char v = *p;
  813. if( /* v == 0 || */ v < decay || x <= 0 || x >= map_width-1)
  814. {
  815. p[map_width] = 0; // the pixel just above
  816. }
  817. else
  818. {
  819. unsigned char n = v - random(decay);
  820. p[map_width -random(3)+1 + wind*random(2)] = n;
  821. // draw a point on the buffer
  822. *d = shade_base + 0x0f - ( n >> 4);
  823. }
  824. }
  825. }
  826. }
  827. //-------------- End Function Flame::mask_transparent ----------//
  828. //-------------- Begin Function Flame::flush_point ---------//
  829. void Flame::flush_point(short x, short y)
  830. {
  831. if( x < 0)
  832. x = random(map_width/2) + random(map_width/2);
  833. if( y < 1)
  834. y = 1 + random(map_height/4);
  835. unsigned char *center = heat_map + y*map_width + x;
  836. *center >>= 3;
  837. center[-1] >>= 2; // left
  838. if( x-2 >= 0)
  839. center[-2] >>= 1;
  840. center[1] >>= 2; // right
  841. if( x+2 < map_width)
  842. center[2] >>= 1;
  843. center[map_width] >>= 2; // top
  844. center[map_width-1] >>= 1;
  845. center[map_width+1] >>= 1;
  846. }
  847. //-------------- End Function Flame::flush_point ---------//
  848. //-------------- Begin Function Flame::random ---------//
  849. unsigned Flame::random(unsigned bound)
  850. {
  851. #define MULTIPLIER 0x015a4e35L
  852. #define INCREMENT 1
  853. seed = MULTIPLIER * seed + INCREMENT;
  854. return seed % bound;
  855. }
  856. //-------------- End Function Flame::random ---------//