draw.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903
  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. int i;
  86. draw_chars = W_GetLumpName ("conchars");
  87. draw_disc = W_GetLumpName ("disc");
  88. draw_backtile = W_GetLumpName ("backtile");
  89. r_rectdesc.width = draw_backtile->width;
  90. r_rectdesc.height = draw_backtile->height;
  91. r_rectdesc.ptexbytes = draw_backtile->data;
  92. r_rectdesc.rowbytes = draw_backtile->width;
  93. }
  94. /*
  95. ================
  96. Draw_Character
  97. Draws one 8*8 graphics character with 0 being transparent.
  98. It can be clipped to the top of the screen to allow the console to be
  99. smoothly scrolled off.
  100. ================
  101. */
  102. void Draw_Character (int x, int y, int num)
  103. {
  104. byte *dest;
  105. byte *source;
  106. unsigned short *pusdest;
  107. int drawline;
  108. int row, col;
  109. num &= 255;
  110. if (y <= -8)
  111. return; // totally off screen
  112. #ifdef PARANOID
  113. if (y > vid.height - 8 || x < 0 || x > vid.width - 8)
  114. Sys_Error ("Con_DrawCharacter: (%i, %i)", x, y);
  115. if (num < 0 || num > 255)
  116. Sys_Error ("Con_DrawCharacter: char %i", num);
  117. #endif
  118. row = num>>4;
  119. col = num&15;
  120. source = draw_chars + (row<<10) + (col<<3);
  121. if (y < 0)
  122. { // clipped
  123. drawline = 8 + y;
  124. source -= 128*y;
  125. y = 0;
  126. }
  127. else
  128. drawline = 8;
  129. if (r_pixbytes == 1)
  130. {
  131. dest = vid.conbuffer + y*vid.conrowbytes + x;
  132. while (drawline--)
  133. {
  134. if (source[0])
  135. dest[0] = source[0];
  136. if (source[1])
  137. dest[1] = source[1];
  138. if (source[2])
  139. dest[2] = source[2];
  140. if (source[3])
  141. dest[3] = source[3];
  142. if (source[4])
  143. dest[4] = source[4];
  144. if (source[5])
  145. dest[5] = source[5];
  146. if (source[6])
  147. dest[6] = source[6];
  148. if (source[7])
  149. dest[7] = source[7];
  150. source += 128;
  151. dest += vid.conrowbytes;
  152. }
  153. }
  154. else
  155. {
  156. // FIXME: pre-expand to native format?
  157. pusdest = (unsigned short *)
  158. ((byte *)vid.conbuffer + y*vid.conrowbytes + (x<<1));
  159. while (drawline--)
  160. {
  161. if (source[0])
  162. pusdest[0] = d_8to16table[source[0]];
  163. if (source[1])
  164. pusdest[1] = d_8to16table[source[1]];
  165. if (source[2])
  166. pusdest[2] = d_8to16table[source[2]];
  167. if (source[3])
  168. pusdest[3] = d_8to16table[source[3]];
  169. if (source[4])
  170. pusdest[4] = d_8to16table[source[4]];
  171. if (source[5])
  172. pusdest[5] = d_8to16table[source[5]];
  173. if (source[6])
  174. pusdest[6] = d_8to16table[source[6]];
  175. if (source[7])
  176. pusdest[7] = d_8to16table[source[7]];
  177. source += 128;
  178. pusdest += (vid.conrowbytes >> 1);
  179. }
  180. }
  181. }
  182. /*
  183. ================
  184. Draw_String
  185. ================
  186. */
  187. void Draw_String (int x, int y, char *str)
  188. {
  189. while (*str)
  190. {
  191. Draw_Character (x, y, *str);
  192. str++;
  193. x += 8;
  194. }
  195. }
  196. /*
  197. ================
  198. Draw_DebugChar
  199. Draws a single character directly to the upper right corner of the screen.
  200. This is for debugging lockups by drawing different chars in different parts
  201. of the code.
  202. ================
  203. */
  204. void Draw_DebugChar (char num)
  205. {
  206. byte *dest;
  207. byte *source;
  208. int drawline;
  209. extern byte *draw_chars;
  210. int row, col;
  211. if (!vid.direct)
  212. return; // don't have direct FB access, so no debugchars...
  213. drawline = 8;
  214. row = num>>4;
  215. col = num&15;
  216. source = draw_chars + (row<<10) + (col<<3);
  217. dest = vid.direct + 312;
  218. while (drawline--)
  219. {
  220. dest[0] = source[0];
  221. dest[1] = source[1];
  222. dest[2] = source[2];
  223. dest[3] = source[3];
  224. dest[4] = source[4];
  225. dest[5] = source[5];
  226. dest[6] = source[6];
  227. dest[7] = source[7];
  228. source += 128;
  229. dest += 320;
  230. }
  231. }
  232. /*
  233. =============
  234. Draw_Pic
  235. =============
  236. */
  237. void Draw_Pic (int x, int y, qpic_t *pic)
  238. {
  239. byte *dest, *source;
  240. unsigned short *pusdest;
  241. int v, u;
  242. if ((x < 0) ||
  243. (x + pic->width > vid.width) ||
  244. (y < 0) ||
  245. (y + pic->height > vid.height))
  246. {
  247. Sys_Error ("Draw_Pic: bad coordinates");
  248. }
  249. source = pic->data;
  250. if (r_pixbytes == 1)
  251. {
  252. dest = vid.buffer + y * vid.rowbytes + x;
  253. for (v=0 ; v<pic->height ; v++)
  254. {
  255. Q_memcpy (dest, source, pic->width);
  256. dest += vid.rowbytes;
  257. source += pic->width;
  258. }
  259. }
  260. else
  261. {
  262. // FIXME: pretranslate at load time?
  263. pusdest = (unsigned short *)vid.buffer + y * (vid.rowbytes >> 1) + x;
  264. for (v=0 ; v<pic->height ; v++)
  265. {
  266. for (u=0 ; u<pic->width ; u++)
  267. {
  268. pusdest[u] = d_8to16table[source[u]];
  269. }
  270. pusdest += vid.rowbytes >> 1;
  271. source += pic->width;
  272. }
  273. }
  274. }
  275. /*
  276. =============
  277. Draw_TransPic
  278. =============
  279. */
  280. void Draw_TransPic (int x, int y, qpic_t *pic)
  281. {
  282. byte *dest, *source, tbyte;
  283. unsigned short *pusdest;
  284. int v, u;
  285. if (x < 0 || (unsigned)(x + pic->width) > vid.width || y < 0 ||
  286. (unsigned)(y + pic->height) > vid.height)
  287. {
  288. Sys_Error ("Draw_TransPic: bad coordinates");
  289. }
  290. source = pic->data;
  291. if (r_pixbytes == 1)
  292. {
  293. dest = vid.buffer + y * vid.rowbytes + x;
  294. if (pic->width & 7)
  295. { // general
  296. for (v=0 ; v<pic->height ; v++)
  297. {
  298. for (u=0 ; u<pic->width ; u++)
  299. if ( (tbyte=source[u]) != TRANSPARENT_COLOR)
  300. dest[u] = tbyte;
  301. dest += vid.rowbytes;
  302. source += pic->width;
  303. }
  304. }
  305. else
  306. { // unwound
  307. for (v=0 ; v<pic->height ; v++)
  308. {
  309. for (u=0 ; u<pic->width ; u+=8)
  310. {
  311. if ( (tbyte=source[u]) != TRANSPARENT_COLOR)
  312. dest[u] = tbyte;
  313. if ( (tbyte=source[u+1]) != TRANSPARENT_COLOR)
  314. dest[u+1] = tbyte;
  315. if ( (tbyte=source[u+2]) != TRANSPARENT_COLOR)
  316. dest[u+2] = tbyte;
  317. if ( (tbyte=source[u+3]) != TRANSPARENT_COLOR)
  318. dest[u+3] = tbyte;
  319. if ( (tbyte=source[u+4]) != TRANSPARENT_COLOR)
  320. dest[u+4] = tbyte;
  321. if ( (tbyte=source[u+5]) != TRANSPARENT_COLOR)
  322. dest[u+5] = tbyte;
  323. if ( (tbyte=source[u+6]) != TRANSPARENT_COLOR)
  324. dest[u+6] = tbyte;
  325. if ( (tbyte=source[u+7]) != TRANSPARENT_COLOR)
  326. dest[u+7] = tbyte;
  327. }
  328. dest += vid.rowbytes;
  329. source += pic->width;
  330. }
  331. }
  332. }
  333. else
  334. {
  335. // FIXME: pretranslate at load time?
  336. pusdest = (unsigned short *)vid.buffer + y * (vid.rowbytes >> 1) + x;
  337. for (v=0 ; v<pic->height ; v++)
  338. {
  339. for (u=0 ; u<pic->width ; u++)
  340. {
  341. tbyte = source[u];
  342. if (tbyte != TRANSPARENT_COLOR)
  343. {
  344. pusdest[u] = d_8to16table[tbyte];
  345. }
  346. }
  347. pusdest += vid.rowbytes >> 1;
  348. source += pic->width;
  349. }
  350. }
  351. }
  352. /*
  353. =============
  354. Draw_TransPicTranslate
  355. =============
  356. */
  357. void Draw_TransPicTranslate (int x, int y, qpic_t *pic, byte *translation)
  358. {
  359. byte *dest, *source, tbyte;
  360. unsigned short *pusdest;
  361. int v, u;
  362. if (x < 0 || (unsigned)(x + pic->width) > vid.width || y < 0 ||
  363. (unsigned)(y + pic->height) > vid.height)
  364. {
  365. Sys_Error ("Draw_TransPic: bad coordinates");
  366. }
  367. source = pic->data;
  368. if (r_pixbytes == 1)
  369. {
  370. dest = vid.buffer + y * vid.rowbytes + x;
  371. if (pic->width & 7)
  372. { // general
  373. for (v=0 ; v<pic->height ; v++)
  374. {
  375. for (u=0 ; u<pic->width ; u++)
  376. if ( (tbyte=source[u]) != TRANSPARENT_COLOR)
  377. dest[u] = translation[tbyte];
  378. dest += vid.rowbytes;
  379. source += pic->width;
  380. }
  381. }
  382. else
  383. { // unwound
  384. for (v=0 ; v<pic->height ; v++)
  385. {
  386. for (u=0 ; u<pic->width ; u+=8)
  387. {
  388. if ( (tbyte=source[u]) != TRANSPARENT_COLOR)
  389. dest[u] = translation[tbyte];
  390. if ( (tbyte=source[u+1]) != TRANSPARENT_COLOR)
  391. dest[u+1] = translation[tbyte];
  392. if ( (tbyte=source[u+2]) != TRANSPARENT_COLOR)
  393. dest[u+2] = translation[tbyte];
  394. if ( (tbyte=source[u+3]) != TRANSPARENT_COLOR)
  395. dest[u+3] = translation[tbyte];
  396. if ( (tbyte=source[u+4]) != TRANSPARENT_COLOR)
  397. dest[u+4] = translation[tbyte];
  398. if ( (tbyte=source[u+5]) != TRANSPARENT_COLOR)
  399. dest[u+5] = translation[tbyte];
  400. if ( (tbyte=source[u+6]) != TRANSPARENT_COLOR)
  401. dest[u+6] = translation[tbyte];
  402. if ( (tbyte=source[u+7]) != TRANSPARENT_COLOR)
  403. dest[u+7] = translation[tbyte];
  404. }
  405. dest += vid.rowbytes;
  406. source += pic->width;
  407. }
  408. }
  409. }
  410. else
  411. {
  412. // FIXME: pretranslate at load time?
  413. pusdest = (unsigned short *)vid.buffer + y * (vid.rowbytes >> 1) + x;
  414. for (v=0 ; v<pic->height ; v++)
  415. {
  416. for (u=0 ; u<pic->width ; u++)
  417. {
  418. tbyte = source[u];
  419. if (tbyte != TRANSPARENT_COLOR)
  420. {
  421. pusdest[u] = d_8to16table[tbyte];
  422. }
  423. }
  424. pusdest += vid.rowbytes >> 1;
  425. source += pic->width;
  426. }
  427. }
  428. }
  429. void Draw_CharToConback (int num, byte *dest)
  430. {
  431. int row, col;
  432. byte *source;
  433. int drawline;
  434. int x;
  435. row = num>>4;
  436. col = num&15;
  437. source = draw_chars + (row<<10) + (col<<3);
  438. drawline = 8;
  439. while (drawline--)
  440. {
  441. for (x=0 ; x<8 ; x++)
  442. if (source[x])
  443. dest[x] = 0x60 + source[x];
  444. source += 128;
  445. dest += 320;
  446. }
  447. }
  448. /*
  449. ================
  450. Draw_ConsoleBackground
  451. ================
  452. */
  453. void Draw_ConsoleBackground (int lines)
  454. {
  455. int x, y, v;
  456. byte *src, *dest;
  457. unsigned short *pusdest;
  458. int f, fstep;
  459. qpic_t *conback;
  460. char ver[100];
  461. conback = Draw_CachePic ("gfx/conback.lmp");
  462. // hack the version number directly into the pic
  463. #ifdef _WIN32
  464. sprintf (ver, "(WinQuake) %4.2f", (float)VERSION);
  465. dest = conback->data + 320*186 + 320 - 11 - 8*strlen(ver);
  466. #elif defined(X11)
  467. sprintf (ver, "(X11 Quake %2.2f) %4.2f", (float)X11_VERSION, (float)VERSION);
  468. dest = conback->data + 320*186 + 320 - 11 - 8*strlen(ver);
  469. #elif defined(__linux__)
  470. sprintf (ver, "(Linux Quake %2.2f) %4.2f", (float)LINUX_VERSION, (float)VERSION);
  471. dest = conback->data + 320*186 + 320 - 11 - 8*strlen(ver);
  472. #else
  473. dest = conback->data + 320 - 43 + 320*186;
  474. sprintf (ver, "%4.2f", VERSION);
  475. #endif
  476. for (x=0 ; x<strlen(ver) ; x++)
  477. Draw_CharToConback (ver[x], dest+(x<<3));
  478. // draw the pic
  479. if (r_pixbytes == 1)
  480. {
  481. dest = vid.conbuffer;
  482. for (y=0 ; y<lines ; y++, dest += vid.conrowbytes)
  483. {
  484. v = (vid.conheight - lines + y)*200/vid.conheight;
  485. src = conback->data + v*320;
  486. if (vid.conwidth == 320)
  487. memcpy (dest, src, vid.conwidth);
  488. else
  489. {
  490. f = 0;
  491. fstep = 320*0x10000/vid.conwidth;
  492. for (x=0 ; x<vid.conwidth ; x+=4)
  493. {
  494. dest[x] = src[f>>16];
  495. f += fstep;
  496. dest[x+1] = src[f>>16];
  497. f += fstep;
  498. dest[x+2] = src[f>>16];
  499. f += fstep;
  500. dest[x+3] = src[f>>16];
  501. f += fstep;
  502. }
  503. }
  504. }
  505. }
  506. else
  507. {
  508. pusdest = (unsigned short *)vid.conbuffer;
  509. for (y=0 ; y<lines ; y++, pusdest += (vid.conrowbytes >> 1))
  510. {
  511. // FIXME: pre-expand to native format?
  512. // FIXME: does the endian switching go away in production?
  513. v = (vid.conheight - lines + y)*200/vid.conheight;
  514. src = conback->data + v*320;
  515. f = 0;
  516. fstep = 320*0x10000/vid.conwidth;
  517. for (x=0 ; x<vid.conwidth ; x+=4)
  518. {
  519. pusdest[x] = d_8to16table[src[f>>16]];
  520. f += fstep;
  521. pusdest[x+1] = d_8to16table[src[f>>16]];
  522. f += fstep;
  523. pusdest[x+2] = d_8to16table[src[f>>16]];
  524. f += fstep;
  525. pusdest[x+3] = d_8to16table[src[f>>16]];
  526. f += fstep;
  527. }
  528. }
  529. }
  530. }
  531. /*
  532. ==============
  533. R_DrawRect8
  534. ==============
  535. */
  536. void R_DrawRect8 (vrect_t *prect, int rowbytes, byte *psrc,
  537. int transparent)
  538. {
  539. byte t;
  540. int i, j, srcdelta, destdelta;
  541. byte *pdest;
  542. pdest = vid.buffer + (prect->y * vid.rowbytes) + prect->x;
  543. srcdelta = rowbytes - prect->width;
  544. destdelta = vid.rowbytes - prect->width;
  545. if (transparent)
  546. {
  547. for (i=0 ; i<prect->height ; i++)
  548. {
  549. for (j=0 ; j<prect->width ; j++)
  550. {
  551. t = *psrc;
  552. if (t != TRANSPARENT_COLOR)
  553. {
  554. *pdest = t;
  555. }
  556. psrc++;
  557. pdest++;
  558. }
  559. psrc += srcdelta;
  560. pdest += destdelta;
  561. }
  562. }
  563. else
  564. {
  565. for (i=0 ; i<prect->height ; i++)
  566. {
  567. memcpy (pdest, psrc, prect->width);
  568. psrc += rowbytes;
  569. pdest += vid.rowbytes;
  570. }
  571. }
  572. }
  573. /*
  574. ==============
  575. R_DrawRect16
  576. ==============
  577. */
  578. void R_DrawRect16 (vrect_t *prect, int rowbytes, byte *psrc,
  579. int transparent)
  580. {
  581. byte t;
  582. int i, j, srcdelta, destdelta;
  583. unsigned short *pdest;
  584. // FIXME: would it be better to pre-expand native-format versions?
  585. pdest = (unsigned short *)vid.buffer +
  586. (prect->y * (vid.rowbytes >> 1)) + prect->x;
  587. srcdelta = rowbytes - prect->width;
  588. destdelta = (vid.rowbytes >> 1) - prect->width;
  589. if (transparent)
  590. {
  591. for (i=0 ; i<prect->height ; i++)
  592. {
  593. for (j=0 ; j<prect->width ; j++)
  594. {
  595. t = *psrc;
  596. if (t != TRANSPARENT_COLOR)
  597. {
  598. *pdest = d_8to16table[t];
  599. }
  600. psrc++;
  601. pdest++;
  602. }
  603. psrc += srcdelta;
  604. pdest += destdelta;
  605. }
  606. }
  607. else
  608. {
  609. for (i=0 ; i<prect->height ; i++)
  610. {
  611. for (j=0 ; j<prect->width ; j++)
  612. {
  613. *pdest = d_8to16table[*psrc];
  614. psrc++;
  615. pdest++;
  616. }
  617. psrc += srcdelta;
  618. pdest += destdelta;
  619. }
  620. }
  621. }
  622. /*
  623. =============
  624. Draw_TileClear
  625. This repeats a 64*64 tile graphic to fill the screen around a sized down
  626. refresh window.
  627. =============
  628. */
  629. void Draw_TileClear (int x, int y, int w, int h)
  630. {
  631. int width, height, tileoffsetx, tileoffsety;
  632. byte *psrc;
  633. vrect_t vr;
  634. r_rectdesc.rect.x = x;
  635. r_rectdesc.rect.y = y;
  636. r_rectdesc.rect.width = w;
  637. r_rectdesc.rect.height = h;
  638. vr.y = r_rectdesc.rect.y;
  639. height = r_rectdesc.rect.height;
  640. tileoffsety = vr.y % r_rectdesc.height;
  641. while (height > 0)
  642. {
  643. vr.x = r_rectdesc.rect.x;
  644. width = r_rectdesc.rect.width;
  645. if (tileoffsety != 0)
  646. vr.height = r_rectdesc.height - tileoffsety;
  647. else
  648. vr.height = r_rectdesc.height;
  649. if (vr.height > height)
  650. vr.height = height;
  651. tileoffsetx = vr.x % r_rectdesc.width;
  652. while (width > 0)
  653. {
  654. if (tileoffsetx != 0)
  655. vr.width = r_rectdesc.width - tileoffsetx;
  656. else
  657. vr.width = r_rectdesc.width;
  658. if (vr.width > width)
  659. vr.width = width;
  660. psrc = r_rectdesc.ptexbytes +
  661. (tileoffsety * r_rectdesc.rowbytes) + tileoffsetx;
  662. if (r_pixbytes == 1)
  663. {
  664. R_DrawRect8 (&vr, r_rectdesc.rowbytes, psrc, 0);
  665. }
  666. else
  667. {
  668. R_DrawRect16 (&vr, r_rectdesc.rowbytes, psrc, 0);
  669. }
  670. vr.x += vr.width;
  671. width -= vr.width;
  672. tileoffsetx = 0; // only the left tile can be left-clipped
  673. }
  674. vr.y += vr.height;
  675. height -= vr.height;
  676. tileoffsety = 0; // only the top tile can be top-clipped
  677. }
  678. }
  679. /*
  680. =============
  681. Draw_Fill
  682. Fills a box of pixels with a single color
  683. =============
  684. */
  685. void Draw_Fill (int x, int y, int w, int h, int c)
  686. {
  687. byte *dest;
  688. unsigned short *pusdest;
  689. unsigned uc;
  690. int u, v;
  691. if (r_pixbytes == 1)
  692. {
  693. dest = vid.buffer + y*vid.rowbytes + x;
  694. for (v=0 ; v<h ; v++, dest += vid.rowbytes)
  695. for (u=0 ; u<w ; u++)
  696. dest[u] = c;
  697. }
  698. else
  699. {
  700. uc = d_8to16table[c];
  701. pusdest = (unsigned short *)vid.buffer + y * (vid.rowbytes >> 1) + x;
  702. for (v=0 ; v<h ; v++, pusdest += (vid.rowbytes >> 1))
  703. for (u=0 ; u<w ; u++)
  704. pusdest[u] = uc;
  705. }
  706. }
  707. //=============================================================================
  708. /*
  709. ================
  710. Draw_FadeScreen
  711. ================
  712. */
  713. void Draw_FadeScreen (void)
  714. {
  715. int x,y;
  716. byte *pbuf;
  717. VID_UnlockBuffer ();
  718. S_ExtraUpdate ();
  719. VID_LockBuffer ();
  720. for (y=0 ; y<vid.height ; y++)
  721. {
  722. int t;
  723. pbuf = (byte *)(vid.buffer + vid.rowbytes*y);
  724. t = (y & 1) << 1;
  725. for (x=0 ; x<vid.width ; x++)
  726. {
  727. if ((x & 3) != t)
  728. pbuf[x] = 0;
  729. }
  730. }
  731. VID_UnlockBuffer ();
  732. S_ExtraUpdate ();
  733. VID_LockBuffer ();
  734. }
  735. //=============================================================================
  736. /*
  737. ================
  738. Draw_BeginDisc
  739. Draws the little blue disc in the corner of the screen.
  740. Call before beginning any disc IO.
  741. ================
  742. */
  743. void Draw_BeginDisc (void)
  744. {
  745. D_BeginDirectRect (vid.width - 24, 0, draw_disc->data, 24, 24);
  746. }
  747. /*
  748. ================
  749. Draw_EndDisc
  750. Erases the disc icon.
  751. Call after completing any disc IO
  752. ================
  753. */
  754. void Draw_EndDisc (void)
  755. {
  756. D_EndDirectRect (vid.width - 24, 0, 24, 24);
  757. }