draw.c 19 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021
  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3. This program is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU General Public License
  5. as published by the Free Software Foundation; either version 2
  6. of the License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. See the GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  14. */
  15. // draw.c -- this is the only file outside the refresh that touches the
  16. // vid buffer
  17. #include "quakedef.h"
  18. typedef struct {
  19. vrect_t rect;
  20. int width;
  21. int height;
  22. byte *ptexbytes;
  23. int rowbytes;
  24. } rectdesc_t;
  25. static rectdesc_t r_rectdesc;
  26. byte *draw_chars; // 8*8 graphic characters
  27. qpic_t *draw_disc;
  28. qpic_t *draw_backtile;
  29. //=============================================================================
  30. /* Support Routines */
  31. typedef struct cachepic_s
  32. {
  33. char name[MAX_QPATH];
  34. cache_user_t cache;
  35. } cachepic_t;
  36. #define MAX_CACHED_PICS 128
  37. cachepic_t menu_cachepics[MAX_CACHED_PICS];
  38. int menu_numcachepics;
  39. qpic_t *Draw_PicFromWad (char *name)
  40. {
  41. return W_GetLumpName (name);
  42. }
  43. /*
  44. ================
  45. Draw_CachePic
  46. ================
  47. */
  48. qpic_t *Draw_CachePic (char *path)
  49. {
  50. cachepic_t *pic;
  51. int i;
  52. qpic_t *dat;
  53. for (pic=menu_cachepics, i=0 ; i<menu_numcachepics ; pic++, i++)
  54. if (!strcmp (path, pic->name))
  55. break;
  56. if (i == menu_numcachepics)
  57. {
  58. if (menu_numcachepics == MAX_CACHED_PICS)
  59. Sys_Error ("menu_numcachepics == MAX_CACHED_PICS");
  60. menu_numcachepics++;
  61. strcpy (pic->name, path);
  62. }
  63. dat = Cache_Check (&pic->cache);
  64. if (dat)
  65. return dat;
  66. //
  67. // load the pic from disk
  68. //
  69. COM_LoadCacheFile (path, &pic->cache);
  70. dat = (qpic_t *)pic->cache.data;
  71. if (!dat)
  72. {
  73. Sys_Error ("Draw_CachePic: failed to load %s", path);
  74. }
  75. SwapPic (dat);
  76. return dat;
  77. }
  78. /*
  79. ===============
  80. Draw_Init
  81. ===============
  82. */
  83. void Draw_Init (void)
  84. {
  85. draw_chars = W_GetLumpName ("conchars");
  86. draw_disc = W_GetLumpName ("disc");
  87. draw_backtile = W_GetLumpName ("backtile");
  88. r_rectdesc.width = draw_backtile->width;
  89. r_rectdesc.height = draw_backtile->height;
  90. r_rectdesc.ptexbytes = draw_backtile->data;
  91. r_rectdesc.rowbytes = draw_backtile->width;
  92. }
  93. /*
  94. ================
  95. Draw_Character
  96. Draws one 8*8 graphics character with 0 being transparent.
  97. It can be clipped to the top of the screen to allow the console to be
  98. smoothly scrolled off.
  99. ================
  100. */
  101. void Draw_Character (int x, int y, int num)
  102. {
  103. byte *dest;
  104. byte *source;
  105. unsigned short *pusdest;
  106. int drawline;
  107. int row, col;
  108. num &= 255;
  109. if (y <= -8)
  110. return; // totally off screen
  111. if (y > vid.height - 8 || x < 0 || x > vid.width - 8)
  112. return;
  113. if (num < 0 || num > 255)
  114. return;
  115. row = num>>4;
  116. col = num&15;
  117. source = draw_chars + (row<<10) + (col<<3);
  118. if (y < 0)
  119. { // clipped
  120. drawline = 8 + y;
  121. source -= 128*y;
  122. y = 0;
  123. }
  124. else
  125. drawline = 8;
  126. if (r_pixbytes == 1)
  127. {
  128. dest = vid.conbuffer + y*vid.conrowbytes + x;
  129. while (drawline--)
  130. {
  131. if (source[0])
  132. dest[0] = source[0];
  133. if (source[1])
  134. dest[1] = source[1];
  135. if (source[2])
  136. dest[2] = source[2];
  137. if (source[3])
  138. dest[3] = source[3];
  139. if (source[4])
  140. dest[4] = source[4];
  141. if (source[5])
  142. dest[5] = source[5];
  143. if (source[6])
  144. dest[6] = source[6];
  145. if (source[7])
  146. dest[7] = source[7];
  147. source += 128;
  148. dest += vid.conrowbytes;
  149. }
  150. }
  151. else
  152. {
  153. // FIXME: pre-expand to native format?
  154. pusdest = (unsigned short *)
  155. ((byte *)vid.conbuffer + y*vid.conrowbytes + (x<<1));
  156. while (drawline--)
  157. {
  158. if (source[0])
  159. pusdest[0] = d_8to16table[source[0]];
  160. if (source[1])
  161. pusdest[1] = d_8to16table[source[1]];
  162. if (source[2])
  163. pusdest[2] = d_8to16table[source[2]];
  164. if (source[3])
  165. pusdest[3] = d_8to16table[source[3]];
  166. if (source[4])
  167. pusdest[4] = d_8to16table[source[4]];
  168. if (source[5])
  169. pusdest[5] = d_8to16table[source[5]];
  170. if (source[6])
  171. pusdest[6] = d_8to16table[source[6]];
  172. if (source[7])
  173. pusdest[7] = d_8to16table[source[7]];
  174. source += 128;
  175. pusdest += (vid.conrowbytes >> 1);
  176. }
  177. }
  178. }
  179. /*
  180. ================
  181. Draw_String
  182. ================
  183. */
  184. void Draw_String (int x, int y, char *str)
  185. {
  186. while (*str)
  187. {
  188. Draw_Character (x, y, *str);
  189. str++;
  190. x += 8;
  191. }
  192. }
  193. /*
  194. ================
  195. Draw_Alt_String
  196. ================
  197. */
  198. void Draw_Alt_String (int x, int y, char *str)
  199. {
  200. while (*str)
  201. {
  202. Draw_Character (x, y, (*str) | 0x80);
  203. str++;
  204. x += 8;
  205. }
  206. }
  207. void Draw_Pixel(int x, int y, byte color)
  208. {
  209. byte *dest;
  210. unsigned short *pusdest;
  211. if (r_pixbytes == 1)
  212. {
  213. dest = vid.conbuffer + y*vid.conrowbytes + x;
  214. *dest = color;
  215. }
  216. else
  217. {
  218. // FIXME: pre-expand to native format?
  219. pusdest = (unsigned short *)
  220. ((byte *)vid.conbuffer + y*vid.conrowbytes + (x<<1));
  221. *pusdest = d_8to16table[color];
  222. }
  223. }
  224. void Draw_Crosshair(void)
  225. {
  226. int x, y;
  227. extern cvar_t crosshair, cl_crossx, cl_crossy, crosshaircolor;
  228. extern vrect_t scr_vrect;
  229. byte c = (byte)crosshaircolor.value;
  230. if (crosshair.value == 2) {
  231. x = scr_vrect.x + scr_vrect.width/2 + cl_crossx.value;
  232. y = scr_vrect.y + scr_vrect.height/2 + cl_crossy.value;
  233. Draw_Pixel(x - 1, y, c);
  234. Draw_Pixel(x - 3, y, c);
  235. Draw_Pixel(x + 1, y, c);
  236. Draw_Pixel(x + 3, y, c);
  237. Draw_Pixel(x, y - 1, c);
  238. Draw_Pixel(x, y - 3, c);
  239. Draw_Pixel(x, y + 1, c);
  240. Draw_Pixel(x, y + 3, c);
  241. } else if (crosshair.value)
  242. Draw_Character (
  243. scr_vrect.x + scr_vrect.width/2-4 + cl_crossx.value,
  244. scr_vrect.y + scr_vrect.height/2-4 + cl_crossy.value,
  245. '+');
  246. }
  247. /*
  248. ================
  249. Draw_DebugChar
  250. Draws a single character directly to the upper right corner of the screen.
  251. This is for debugging lockups by drawing different chars in different parts
  252. of the code.
  253. ================
  254. */
  255. void Draw_DebugChar (char num)
  256. {
  257. byte *dest;
  258. byte *source;
  259. int drawline;
  260. extern byte *draw_chars;
  261. int row, col;
  262. if (!vid.direct)
  263. return; // don't have direct FB access, so no debugchars...
  264. drawline = 8;
  265. row = num>>4;
  266. col = num&15;
  267. source = draw_chars + (row<<10) + (col<<3);
  268. dest = vid.direct + 312;
  269. while (drawline--)
  270. {
  271. dest[0] = source[0];
  272. dest[1] = source[1];
  273. dest[2] = source[2];
  274. dest[3] = source[3];
  275. dest[4] = source[4];
  276. dest[5] = source[5];
  277. dest[6] = source[6];
  278. dest[7] = source[7];
  279. source += 128;
  280. dest += 320;
  281. }
  282. }
  283. /*
  284. =============
  285. Draw_Pic
  286. =============
  287. */
  288. void Draw_Pic (int x, int y, qpic_t *pic)
  289. {
  290. byte *dest, *source;
  291. unsigned short *pusdest;
  292. int v, u;
  293. if ((x < 0) ||
  294. (x + pic->width > vid.width) ||
  295. (y < 0) ||
  296. (y + pic->height > vid.height))
  297. {
  298. Sys_Error ("Draw_Pic: bad coordinates");
  299. }
  300. source = pic->data;
  301. if (r_pixbytes == 1)
  302. {
  303. dest = vid.buffer + y * vid.rowbytes + x;
  304. for (v=0 ; v<pic->height ; v++)
  305. {
  306. Q_memcpy (dest, source, pic->width);
  307. dest += vid.rowbytes;
  308. source += pic->width;
  309. }
  310. }
  311. else
  312. {
  313. // FIXME: pretranslate at load time?
  314. pusdest = (unsigned short *)vid.buffer + y * (vid.rowbytes >> 1) + x;
  315. for (v=0 ; v<pic->height ; v++)
  316. {
  317. for (u=0 ; u<pic->width ; u++)
  318. {
  319. pusdest[u] = d_8to16table[source[u]];
  320. }
  321. pusdest += vid.rowbytes >> 1;
  322. source += pic->width;
  323. }
  324. }
  325. }
  326. /*
  327. =============
  328. Draw_SubPic
  329. =============
  330. */
  331. void Draw_SubPic(int x, int y, qpic_t *pic, int srcx, int srcy, int width, int height)
  332. {
  333. byte *dest, *source;
  334. unsigned short *pusdest;
  335. int v, u;
  336. if ((x < 0) ||
  337. (x + width > vid.width) ||
  338. (y < 0) ||
  339. (y + height > vid.height))
  340. {
  341. Sys_Error ("Draw_Pic: bad coordinates");
  342. }
  343. source = pic->data + srcy * pic->width + srcx;
  344. if (r_pixbytes == 1)
  345. {
  346. dest = vid.buffer + y * vid.rowbytes + x;
  347. for (v=0 ; v<height ; v++)
  348. {
  349. Q_memcpy (dest, source, width);
  350. dest += vid.rowbytes;
  351. source += pic->width;
  352. }
  353. }
  354. else
  355. {
  356. // FIXME: pretranslate at load time?
  357. pusdest = (unsigned short *)vid.buffer + y * (vid.rowbytes >> 1) + x;
  358. for (v=0 ; v<height ; v++)
  359. {
  360. for (u=srcx ; u<(srcx+width) ; u++)
  361. {
  362. pusdest[u] = d_8to16table[source[u]];
  363. }
  364. pusdest += vid.rowbytes >> 1;
  365. source += pic->width;
  366. }
  367. }
  368. }
  369. /*
  370. =============
  371. Draw_TransPic
  372. =============
  373. */
  374. void Draw_TransPic (int x, int y, qpic_t *pic)
  375. {
  376. byte *dest, *source, tbyte;
  377. unsigned short *pusdest;
  378. int v, u;
  379. if (x < 0 || (unsigned)(x + pic->width) > vid.width || y < 0 ||
  380. (unsigned)(y + pic->height) > vid.height)
  381. {
  382. Sys_Error ("Draw_TransPic: bad coordinates");
  383. }
  384. source = pic->data;
  385. if (r_pixbytes == 1)
  386. {
  387. dest = vid.buffer + y * vid.rowbytes + x;
  388. if (pic->width & 7)
  389. { // general
  390. for (v=0 ; v<pic->height ; v++)
  391. {
  392. for (u=0 ; u<pic->width ; u++)
  393. if ( (tbyte=source[u]) != TRANSPARENT_COLOR)
  394. dest[u] = tbyte;
  395. dest += vid.rowbytes;
  396. source += pic->width;
  397. }
  398. }
  399. else
  400. { // unwound
  401. for (v=0 ; v<pic->height ; v++)
  402. {
  403. for (u=0 ; u<pic->width ; u+=8)
  404. {
  405. if ( (tbyte=source[u]) != TRANSPARENT_COLOR)
  406. dest[u] = tbyte;
  407. if ( (tbyte=source[u+1]) != TRANSPARENT_COLOR)
  408. dest[u+1] = tbyte;
  409. if ( (tbyte=source[u+2]) != TRANSPARENT_COLOR)
  410. dest[u+2] = tbyte;
  411. if ( (tbyte=source[u+3]) != TRANSPARENT_COLOR)
  412. dest[u+3] = tbyte;
  413. if ( (tbyte=source[u+4]) != TRANSPARENT_COLOR)
  414. dest[u+4] = tbyte;
  415. if ( (tbyte=source[u+5]) != TRANSPARENT_COLOR)
  416. dest[u+5] = tbyte;
  417. if ( (tbyte=source[u+6]) != TRANSPARENT_COLOR)
  418. dest[u+6] = tbyte;
  419. if ( (tbyte=source[u+7]) != TRANSPARENT_COLOR)
  420. dest[u+7] = tbyte;
  421. }
  422. dest += vid.rowbytes;
  423. source += pic->width;
  424. }
  425. }
  426. }
  427. else
  428. {
  429. // FIXME: pretranslate at load time?
  430. pusdest = (unsigned short *)vid.buffer + y * (vid.rowbytes >> 1) + x;
  431. for (v=0 ; v<pic->height ; v++)
  432. {
  433. for (u=0 ; u<pic->width ; u++)
  434. {
  435. tbyte = source[u];
  436. if (tbyte != TRANSPARENT_COLOR)
  437. {
  438. pusdest[u] = d_8to16table[tbyte];
  439. }
  440. }
  441. pusdest += vid.rowbytes >> 1;
  442. source += pic->width;
  443. }
  444. }
  445. }
  446. /*
  447. =============
  448. Draw_TransPicTranslate
  449. =============
  450. */
  451. void Draw_TransPicTranslate (int x, int y, qpic_t *pic, byte *translation)
  452. {
  453. byte *dest, *source, tbyte;
  454. unsigned short *pusdest;
  455. int v, u;
  456. if (x < 0 || (unsigned)(x + pic->width) > vid.width || y < 0 ||
  457. (unsigned)(y + pic->height) > vid.height)
  458. {
  459. Sys_Error ("Draw_TransPic: bad coordinates");
  460. }
  461. source = pic->data;
  462. if (r_pixbytes == 1)
  463. {
  464. dest = vid.buffer + y * vid.rowbytes + x;
  465. if (pic->width & 7)
  466. { // general
  467. for (v=0 ; v<pic->height ; v++)
  468. {
  469. for (u=0 ; u<pic->width ; u++)
  470. if ( (tbyte=source[u]) != TRANSPARENT_COLOR)
  471. dest[u] = translation[tbyte];
  472. dest += vid.rowbytes;
  473. source += pic->width;
  474. }
  475. }
  476. else
  477. { // unwound
  478. for (v=0 ; v<pic->height ; v++)
  479. {
  480. for (u=0 ; u<pic->width ; u+=8)
  481. {
  482. if ( (tbyte=source[u]) != TRANSPARENT_COLOR)
  483. dest[u] = translation[tbyte];
  484. if ( (tbyte=source[u+1]) != TRANSPARENT_COLOR)
  485. dest[u+1] = translation[tbyte];
  486. if ( (tbyte=source[u+2]) != TRANSPARENT_COLOR)
  487. dest[u+2] = translation[tbyte];
  488. if ( (tbyte=source[u+3]) != TRANSPARENT_COLOR)
  489. dest[u+3] = translation[tbyte];
  490. if ( (tbyte=source[u+4]) != TRANSPARENT_COLOR)
  491. dest[u+4] = translation[tbyte];
  492. if ( (tbyte=source[u+5]) != TRANSPARENT_COLOR)
  493. dest[u+5] = translation[tbyte];
  494. if ( (tbyte=source[u+6]) != TRANSPARENT_COLOR)
  495. dest[u+6] = translation[tbyte];
  496. if ( (tbyte=source[u+7]) != TRANSPARENT_COLOR)
  497. dest[u+7] = translation[tbyte];
  498. }
  499. dest += vid.rowbytes;
  500. source += pic->width;
  501. }
  502. }
  503. }
  504. else
  505. {
  506. // FIXME: pretranslate at load time?
  507. pusdest = (unsigned short *)vid.buffer + y * (vid.rowbytes >> 1) + x;
  508. for (v=0 ; v<pic->height ; v++)
  509. {
  510. for (u=0 ; u<pic->width ; u++)
  511. {
  512. tbyte = source[u];
  513. if (tbyte != TRANSPARENT_COLOR)
  514. {
  515. pusdest[u] = d_8to16table[tbyte];
  516. }
  517. }
  518. pusdest += vid.rowbytes >> 1;
  519. source += pic->width;
  520. }
  521. }
  522. }
  523. void Draw_CharToConback (int num, byte *dest)
  524. {
  525. int row, col;
  526. byte *source;
  527. int drawline;
  528. int x;
  529. row = num>>4;
  530. col = num&15;
  531. source = draw_chars + (row<<10) + (col<<3);
  532. drawline = 8;
  533. while (drawline--)
  534. {
  535. for (x=0 ; x<8 ; x++)
  536. if (source[x])
  537. dest[x] = 0x60 + source[x];
  538. source += 128;
  539. dest += 320;
  540. }
  541. }
  542. /*
  543. ================
  544. Draw_ConsoleBackground
  545. ================
  546. */
  547. void Draw_ConsoleBackground (int lines)
  548. {
  549. int x, y, v;
  550. byte *src, *dest;
  551. unsigned short *pusdest;
  552. int f, fstep;
  553. qpic_t *conback;
  554. char ver[100];
  555. static char saveback[320*8];
  556. conback = Draw_CachePic ("gfx/conback.lmp");
  557. // hack the version number directly into the pic
  558. //sprintf (ver, "start commands with a \\ character %4.2f", VERSION);
  559. if (cls.download) {
  560. sprintf (ver, "%4.2f", VERSION);
  561. dest = conback->data + 320 + 320*186 - 11 - 8*strlen(ver);
  562. } else {
  563. #if defined(__linux__)
  564. sprintf (ver, "Linux (%4.2f) QuakeWorld %4.2f", LINUX_VERSION, VERSION);
  565. #else
  566. sprintf (ver, "QuakeWorld %4.2f", VERSION);
  567. #endif
  568. dest = conback->data + 320 - (strlen(ver)*8 + 11) + 320*186;
  569. }
  570. memcpy(saveback, conback->data + 320*186, 320*8);
  571. for (x=0 ; x<strlen(ver) ; x++)
  572. Draw_CharToConback (ver[x], dest+(x<<3));
  573. // draw the pic
  574. if (r_pixbytes == 1)
  575. {
  576. dest = vid.conbuffer;
  577. for (y=0 ; y<lines ; y++, dest += vid.conrowbytes)
  578. {
  579. v = (vid.conheight - lines + y)*200/vid.conheight;
  580. src = conback->data + v*320;
  581. if (vid.conwidth == 320)
  582. memcpy (dest, src, vid.conwidth);
  583. else
  584. {
  585. f = 0;
  586. fstep = 320*0x10000/vid.conwidth;
  587. for (x=0 ; x<vid.conwidth ; x+=4)
  588. {
  589. dest[x] = src[f>>16];
  590. f += fstep;
  591. dest[x+1] = src[f>>16];
  592. f += fstep;
  593. dest[x+2] = src[f>>16];
  594. f += fstep;
  595. dest[x+3] = src[f>>16];
  596. f += fstep;
  597. }
  598. }
  599. }
  600. }
  601. else
  602. {
  603. pusdest = (unsigned short *)vid.conbuffer;
  604. for (y=0 ; y<lines ; y++, pusdest += (vid.conrowbytes >> 1))
  605. {
  606. // FIXME: pre-expand to native format?
  607. // FIXME: does the endian switching go away in production?
  608. v = (vid.conheight - lines + y)*200/vid.conheight;
  609. src = conback->data + v*320;
  610. f = 0;
  611. fstep = 320*0x10000/vid.conwidth;
  612. for (x=0 ; x<vid.conwidth ; x+=4)
  613. {
  614. pusdest[x] = d_8to16table[src[f>>16]];
  615. f += fstep;
  616. pusdest[x+1] = d_8to16table[src[f>>16]];
  617. f += fstep;
  618. pusdest[x+2] = d_8to16table[src[f>>16]];
  619. f += fstep;
  620. pusdest[x+3] = d_8to16table[src[f>>16]];
  621. f += fstep;
  622. }
  623. }
  624. }
  625. // put it back
  626. memcpy(conback->data + 320*186, saveback, 320*8);
  627. }
  628. /*
  629. ==============
  630. R_DrawRect8
  631. ==============
  632. */
  633. void R_DrawRect8 (vrect_t *prect, int rowbytes, byte *psrc,
  634. int transparent)
  635. {
  636. byte t;
  637. int i, j, srcdelta, destdelta;
  638. byte *pdest;
  639. pdest = vid.buffer + (prect->y * vid.rowbytes) + prect->x;
  640. srcdelta = rowbytes - prect->width;
  641. destdelta = vid.rowbytes - prect->width;
  642. if (transparent)
  643. {
  644. for (i=0 ; i<prect->height ; i++)
  645. {
  646. for (j=0 ; j<prect->width ; j++)
  647. {
  648. t = *psrc;
  649. if (t != TRANSPARENT_COLOR)
  650. {
  651. *pdest = t;
  652. }
  653. psrc++;
  654. pdest++;
  655. }
  656. psrc += srcdelta;
  657. pdest += destdelta;
  658. }
  659. }
  660. else
  661. {
  662. for (i=0 ; i<prect->height ; i++)
  663. {
  664. memcpy (pdest, psrc, prect->width);
  665. psrc += rowbytes;
  666. pdest += vid.rowbytes;
  667. }
  668. }
  669. }
  670. /*
  671. ==============
  672. R_DrawRect16
  673. ==============
  674. */
  675. void R_DrawRect16 (vrect_t *prect, int rowbytes, byte *psrc,
  676. int transparent)
  677. {
  678. byte t;
  679. int i, j, srcdelta, destdelta;
  680. unsigned short *pdest;
  681. // FIXME: would it be better to pre-expand native-format versions?
  682. pdest = (unsigned short *)vid.buffer +
  683. (prect->y * (vid.rowbytes >> 1)) + prect->x;
  684. srcdelta = rowbytes - prect->width;
  685. destdelta = (vid.rowbytes >> 1) - prect->width;
  686. if (transparent)
  687. {
  688. for (i=0 ; i<prect->height ; i++)
  689. {
  690. for (j=0 ; j<prect->width ; j++)
  691. {
  692. t = *psrc;
  693. if (t != TRANSPARENT_COLOR)
  694. {
  695. *pdest = d_8to16table[t];
  696. }
  697. psrc++;
  698. pdest++;
  699. }
  700. psrc += srcdelta;
  701. pdest += destdelta;
  702. }
  703. }
  704. else
  705. {
  706. for (i=0 ; i<prect->height ; i++)
  707. {
  708. for (j=0 ; j<prect->width ; j++)
  709. {
  710. *pdest = d_8to16table[*psrc];
  711. psrc++;
  712. pdest++;
  713. }
  714. psrc += srcdelta;
  715. pdest += destdelta;
  716. }
  717. }
  718. }
  719. /*
  720. =============
  721. Draw_TileClear
  722. This repeats a 64*64 tile graphic to fill the screen around a sized down
  723. refresh window.
  724. =============
  725. */
  726. void Draw_TileClear (int x, int y, int w, int h)
  727. {
  728. int width, height, tileoffsetx, tileoffsety;
  729. byte *psrc;
  730. vrect_t vr;
  731. r_rectdesc.rect.x = x;
  732. r_rectdesc.rect.y = y;
  733. r_rectdesc.rect.width = w;
  734. r_rectdesc.rect.height = h;
  735. vr.y = r_rectdesc.rect.y;
  736. height = r_rectdesc.rect.height;
  737. tileoffsety = vr.y % r_rectdesc.height;
  738. while (height > 0)
  739. {
  740. vr.x = r_rectdesc.rect.x;
  741. width = r_rectdesc.rect.width;
  742. if (tileoffsety != 0)
  743. vr.height = r_rectdesc.height - tileoffsety;
  744. else
  745. vr.height = r_rectdesc.height;
  746. if (vr.height > height)
  747. vr.height = height;
  748. tileoffsetx = vr.x % r_rectdesc.width;
  749. while (width > 0)
  750. {
  751. if (tileoffsetx != 0)
  752. vr.width = r_rectdesc.width - tileoffsetx;
  753. else
  754. vr.width = r_rectdesc.width;
  755. if (vr.width > width)
  756. vr.width = width;
  757. psrc = r_rectdesc.ptexbytes +
  758. (tileoffsety * r_rectdesc.rowbytes) + tileoffsetx;
  759. if (r_pixbytes == 1)
  760. {
  761. R_DrawRect8 (&vr, r_rectdesc.rowbytes, psrc, 0);
  762. }
  763. else
  764. {
  765. R_DrawRect16 (&vr, r_rectdesc.rowbytes, psrc, 0);
  766. }
  767. vr.x += vr.width;
  768. width -= vr.width;
  769. tileoffsetx = 0; // only the left tile can be left-clipped
  770. }
  771. vr.y += vr.height;
  772. height -= vr.height;
  773. tileoffsety = 0; // only the top tile can be top-clipped
  774. }
  775. }
  776. /*
  777. =============
  778. Draw_Fill
  779. Fills a box of pixels with a single color
  780. =============
  781. */
  782. void Draw_Fill (int x, int y, int w, int h, int c)
  783. {
  784. byte *dest;
  785. unsigned short *pusdest;
  786. unsigned uc;
  787. int u, v;
  788. if (x < 0 || x + w > vid.width ||
  789. y < 0 || y + h > vid.height) {
  790. Con_Printf("Bad Draw_Fill(%d, %d, %d, %d, %c)\n",
  791. x, y, w, h, c);
  792. return;
  793. }
  794. if (r_pixbytes == 1)
  795. {
  796. dest = vid.buffer + y*vid.rowbytes + x;
  797. for (v=0 ; v<h ; v++, dest += vid.rowbytes)
  798. for (u=0 ; u<w ; u++)
  799. dest[u] = c;
  800. }
  801. else
  802. {
  803. uc = d_8to16table[c];
  804. pusdest = (unsigned short *)vid.buffer + y * (vid.rowbytes >> 1) + x;
  805. for (v=0 ; v<h ; v++, pusdest += (vid.rowbytes >> 1))
  806. for (u=0 ; u<w ; u++)
  807. pusdest[u] = uc;
  808. }
  809. }
  810. //=============================================================================
  811. /*
  812. ================
  813. Draw_FadeScreen
  814. ================
  815. */
  816. void Draw_FadeScreen (void)
  817. {
  818. int x,y;
  819. byte *pbuf;
  820. VID_UnlockBuffer ();
  821. S_ExtraUpdate ();
  822. VID_LockBuffer ();
  823. for (y=0 ; y<vid.height ; y++)
  824. {
  825. int t;
  826. pbuf = (byte *)(vid.buffer + vid.rowbytes*y);
  827. t = (y & 1) << 1;
  828. for (x=0 ; x<vid.width ; x++)
  829. {
  830. if ((x & 3) != t)
  831. pbuf[x] = 0;
  832. }
  833. }
  834. VID_UnlockBuffer ();
  835. S_ExtraUpdate ();
  836. VID_LockBuffer ();
  837. }
  838. //=============================================================================
  839. /*
  840. ================
  841. Draw_BeginDisc
  842. Draws the little blue disc in the corner of the screen.
  843. Call before beginning any disc IO.
  844. ================
  845. */
  846. void Draw_BeginDisc (void)
  847. {
  848. D_BeginDirectRect (vid.width - 24, 0, draw_disc->data, 24, 24);
  849. }
  850. /*
  851. ================
  852. Draw_EndDisc
  853. Erases the disc icon.
  854. Call after completing any disc IO
  855. ================
  856. */
  857. void Draw_EndDisc (void)
  858. {
  859. D_EndDirectRect (vid.width - 24, 0, 24, 24);
  860. }