DEADSOFTWARE

software: fix crashes on buffer resize
[flatwaifu.git] / src / soft / render.c
1 #include <string.h>
2 #include <stdarg.h>
3 #include <stdlib.h> // abs()
4 #include <assert.h>
5 #include "glob.h"
6 #include "render.h"
7 #include "view.h"
8 #include "player.h"
9 #include "switch.h"
10 #include "vga.h"
11 #include "menu.h"
12 #include "misc.h"
13 #include "dots.h"
14 #include "items.h"
15 #include "monster.h"
16 #include "weapons.h"
17 #include "smoke.h"
18 #include "fx.h"
19 #include "memory.h"
20 #include "files.h"
21 #include "error.h"
22 #include "game.h"
23 #include "sound.h"
24 #include "music.h"
25 #include "system.h"
27 // game
28 static vgaimg *scrnh[3]; // TITLEPIC INTERPIC ENDPIC
29 static vgaimg *ltn[2][2];
30 static void *cd_scr;
31 // smoke
32 static vgaimg *smk_spr[SMSN];
33 static vgaimg *smk_fspr[FLSN];
34 // fx
35 static vgaimg *fx_spr[15];
36 static char fx_sprd[15];
37 // weapons
38 static vgaimg *wp_spr[49*2];
39 static char wp_sprd[49*2];
40 // items
41 static vgaimg *item_spr[58];
42 static char item_sprd[58];
43 // player
44 static vgaimg *plr_spr[27*2];
45 static char plr_sprd[27*2];
46 static vgaimg *plr_wpn[11][6];
47 // monsters
48 static vgaimg *pl_spr[2];
49 static vgaimg *mn_spr[MN_TN][29*2];
50 static char mn_sprd[MN_TN][29*2];
51 static vgaimg *mn_fspr[8];
52 static vgaimg *mn_sgun[2];
53 // misc
54 #define MAXAIR 1091
55 static vgaimg *sth[22], *bfh[160 - '!'], *sfh[160 - '!'], *stone, *stone2, *keys[3];
56 static int prx = 0, pry = 0;
57 // menu
58 static vgaimg *msklh[2], *mbarl, *mbarm, *mbarr, *mbaro, *mslotl, *mslotm, *mslotr;
59 // low level
60 static int gammaa = 0;
61 static char main_pal[256][3];
62 static char std_pal[256][3];
63 static byte gamcor[5][64]={
64 #include "gamma.dat"
65 };
66 // walls
67 #define ANIT 5
68 static int WD, HT;
69 static int w_o, w_x, w_y;
70 static vgaimg *walp[256];
71 static int walh[256];
72 static byte walani[256];
73 static int anih[ANIT][5];
74 static byte anic[ANIT];
75 static int max_textures;
76 static vgaimg *horiz;
78 /* --- misc --- */
80 static void *Z_getspr (char n[4], int s, int d, char *dir) {
81 int h = F_getsprid(n, s, d);
82 if (dir) {
83 *dir = (h & 0x8000) ? 1 : 0;
84 }
85 return V_getvgaimg(h);
86 }
88 static void Z_putbfch (int c) {
89 vgaimg *p;
90 if (c > 32 && c < 160) {
91 p = bfh[c - '!'];
92 } else {
93 p = NULL;
94 }
95 if (p) {
96 V_spr(prx, pry, p);
97 prx += p->w - 1;
98 } else {
99 prx += 12;
103 static void Z_putsfch (int c) {
104 vgaimg *p;
105 if (c > 32 && c < 160) {
106 p = sfh[c - '!'];
107 } else {
108 p = NULL;
110 if (p) {
111 V_spr(prx, pry, p);
112 prx += p->w - 1;
113 } else {
114 prx += 7;
118 static void Z_gotoxy (int x, int y) {
119 prx = x;
120 pry = y;
123 static void Z_printbf (char *s, ...) {
124 int i;
125 va_list ap;
126 char buf[80];
127 va_start(ap, s);
128 vsprintf(buf, s, ap);
129 va_end(ap);
130 for (i = 0; buf[i]; ++i) {
131 switch (buf[i]) {
132 case '\n':
133 pry += 13;
134 case '\r':
135 prx = 0;
136 break;
137 default:
138 Z_putbfch((byte)buf[i]);
143 static void Z_printsf (char *s, ...) {
144 int i;
145 va_list ap;
146 char buf[80];
147 va_start(ap, s);
148 vsprintf(buf, s, ap);
149 va_end(ap);
150 for (i = 0; buf[i]; ++i) {
151 switch(buf[i]) {
152 case '\n':
153 pry += 8;
154 case '\r':
155 prx=0;
156 break;
157 default:
158 Z_putsfch((byte)buf[i]);
163 static void Z_drawspr (int x, int y, void *p, char d) {
164 if (d) {
165 V_spr2(x - w_x + WD / 2, y - w_y + HT / 2 + 1 + w_o, p);
166 } else {
167 V_spr(x - w_x + WD / 2, y - w_y + HT / 2 + 1 + w_o, p);
171 static void Z_clrst (void) {
172 V_pic(SCRW - 120, w_o, stone);
173 int y = ((vgaimg*)stone)->h;
174 while (y < HT) {
175 V_pic(SCRW - 120, w_o + y, stone2);
176 y += ((vgaimg*)stone)->h;
180 static void Z_drawstlives (char n) {
181 V_setrect(SCRW - 40, 30, w_o, 40);
182 V_spr(SCRW - 35, w_o + 17, sth[n]);
185 static void Z_drawstkeys (byte k) {
186 int x, n;
187 V_setrect(SCRW - 120, 70, w_o + 77, 23);
188 for (k >>= 4, n = 0, x = SCRW - 75; n < 3; ++n, k >>= 1, x += 9) {
189 if (k & 1) {
190 V_spr(x, w_o + 91, keys[n]);
195 static void Z_drawstair (int a) {
196 V_setrect(SCRW - 120, 120, w_o + 49, 2);
197 if (a > 0) {
198 if (a > MAXAIR) {
199 a = MAXAIR;
201 a = a * 100 / MAXAIR;
202 V_clr(SCRW - 110, a, w_o + 49, 2, 0xC8);
206 static void Z_drawstprcnt (int y, int n) {
207 char s[20];
208 int l, i, x, c;
209 V_setrect(SCRW - 120, 70, y * 19 + 7 + w_o, 19);
210 sprintf(s, "%3d%%", n);
211 l = strlen(s);
212 x = SCRW - 110;
213 for (i = 0; i < l; ++i, x += 14) {
214 if (s[i] >='0' && s[i] <= '9') {
215 c = s[i] - '0';
216 } else if (s[i] == '-') {
217 c = 10;
218 } else if (s[i] == '%') {
219 c = 11;
220 } else {
221 c = -1;
223 if (c >= 0) {
224 V_spr(x, y * 19 + 7 + w_o, sth[c]);
229 static void Z_drawstnum (int n) {
230 char s[20];
231 int l, i, x, c;
232 V_setrect(SCRW - 50, 50, w_o + 77, 23);
233 if (g_dm) {
234 sprintf(s, "%d", n);
235 l = strlen(s);
236 x = (115 - l * 14) + SCRW - 120;
237 for (i = 0; i < l; ++i, x += 14) {
238 if (s[i] >= '0' && s[i] <= '9') {
239 c = s[i] - '0';
240 } else if (s[i] == '-') {
241 c = 10;
242 } else if(s[i] == '%') {
243 c = 11;
244 } else {
245 c =- 1;
247 if (c >= 0) {
248 V_spr(x, w_o + 77 + 5, sth[c]);
254 static void Z_drawstwpn (int n, int a) {
255 char s[20];
256 int l, i, x, c;
257 i = n;
258 V_setrect(SCRW - 120, 120, w_o + 58, 23);
259 if (i >= 0) {
260 V_spr(SCRW - 88, w_o + 58 + 19, sth[i + 12]);
262 if (n >= 2) {
263 sprintf(s, "%d", a);
264 l = strlen(s);
265 x = SCRW - 10 - l * 14;
266 for (i = 0; i < l; ++i, x += 14) {
267 if (s[i] >= '0' && s[i] <= '9') {
268 c = s[i] - '0';
269 } else if (s[i] == '-') {
270 c = 10;
271 } else if (s[i] == '%') {
272 c = 11;
273 } else {
274 c = -1;
276 if (c >= 0) {
277 V_spr(x, w_o + 58 + 2, sth[c]);
283 static void Z_drawmanspr (int x, int y, void *p, char d, byte color) {
284 if (d) {
285 V_manspr2(x - w_x + WD / 2, y - w_y + HT / 2 + 1 + w_o, p, color);
286 } else {
287 V_manspr(x - w_x + WD / 2, y - w_y + HT / 2 + 1 + w_o, p, color);
291 static void Z_drawfld (byte *fld, int bg) {
292 byte *p = fld;
293 int x, y;
294 for (y = 0; y < FLDH; y++) {
295 for (x = 0; x < FLDW; x++) {
296 int sx = x * CELW - w_x + WD / 2;
297 int sy = y * CELH - w_y + HT / 2 + 1 + w_o;
298 int id = *p;
299 if (id) {
300 //intptr_t spc = (intptr_t) walp[id];
301 int spc = R_get_special_id(id);
302 if (spc >= 0 && spc <= 3) {
303 if (!bg) {
304 byte *cmap = clrmap + (spc + 7) * 256;
305 V_remap_rect(sx, sy, CELW, CELH, cmap);
307 } else {
308 V_pic(sx, sy, walp[id]);
311 p++;
316 /* --- menu --- */
318 static int gm_tm = 0; // ???
320 static vgaimg *PL_getspr (int s, int d) {
321 return plr_spr[(s - 'A') * 2 + d];
324 static int GM_draw (void) {
325 enum {MENU, MSG}; // copypasted from menu.c!
326 enum {
327 CANCEL, NEWGAME, LOADGAME, SAVEGAME, OPTIONS, QUITGAME, QUIT, ENDGAME, ENDGM,
328 PLR1, PLR2, COOP, DM, VOLUME, GAMMA, LOAD, SAVE, PLCOLOR, PLCEND, MUSIC, INTERP,
329 SVOLM, SVOLP, MVOLM, MVOLP, GAMMAM, GAMMAP, PL1CM, PL1CP, PL2CM, PL2CP
330 }; // copypasted from menu.c!
331 int i, j, k, y;
332 ++gm_tm;
333 V_setrect(0, SCRW, 0, SCRH);
334 if (!mnu && !gm_redraw) {
335 return 0;
337 gm_redraw = 0;
338 if (!mnu) {
339 return 1;
341 if (mnu->type == MENU) {
342 y = (200 - mnu -> n * 16 - 20) / 2;
343 Z_gotoxy(mnu->x, y - 10); Z_printbf(mnu->ttl);
344 for (i = 0; i < mnu->n; ++i) {
345 if (mnu->t[i] == LOAD || mnu->t[i] == SAVE) {
346 j = y + i * 16 + 29;
347 V_spr(mnu->x, j, mslotl);
348 for (k = 8; k < 184; k += 8) {
349 V_spr(mnu->x + k, j, mslotm);
351 V_spr(mnu->x + 184, j, mslotr);
352 Z_gotoxy(mnu->x + 4, j - 8);
353 if (input && i == save_mnu.cur) {
354 Z_printsf("%s_", ibuf);
355 } else {
356 Z_printsf("%s", savname[i]);
358 } else {
359 Z_gotoxy(mnu->x + (mnu->t[i] >= SVOLM ? (mnu->t[i] >= PL1CM ? 50 : 152) : 0), y + i * 16 + 20);
360 Z_printbf(mnu->m[i]);
362 if (mnu->t[i] == MUSIC) {
363 Z_printbf(" '%.8s'", g_music);
364 } else if(mnu->t[i] == INTERP) {
365 Z_printbf("%s", fullscreen ? "ON" : "OFF");
366 } else if(mnu->t[i] >= PL1CM) {
367 V_manspr(mnu->x + (mnu->t[i] == PL1CM ? 15 : 35), y + i * 16 + 20 + 14, PL_getspr(*panimp, 0), pcolortab[(mnu->t[i] == PL1CM) ? p1color : p2color]);
368 } else if(mnu->t[i] >= SVOLM) {
369 j = y + i * 16 + 20;
370 V_spr(mnu->x, j, mbarl);
371 for (k = 8; k < 144; k += 8) {
372 V_spr(mnu->x + k, j, mbarm);
374 V_spr(mnu->x + 144, j, mbarr);
375 switch(mnu->t[i]) {
376 case SVOLM: k = snd_vol; break;
377 case MVOLM: k = mus_vol; break;
378 case GAMMAM: k = gammaa << 5; break;
380 V_spr(mnu->x + 8 + k, j, mbaro);
383 V_spr(mnu->x - 25, y + mnu->cur * 16 + 20 - 8, msklh[(gm_tm / 6) & 1]);
384 } else {
385 Z_gotoxy((320 - strlen(mnu->ttl) * 7) / 2, 90); Z_printsf(mnu->ttl);
386 Z_gotoxy(136, 100); Z_printsf("(Y/N)");
388 return 1;
391 /* --- dots --- */
393 static void DOT_draw (void) {
394 int i;
395 for (i = 0; i < MAXDOT; i++) {
396 if (dot[i].t) {
397 V_dot(dot[i].o.x - w_x + WD / 2, dot[i].o.y - w_y + HT / 2 + 1 + w_o, dot[i].c);
402 /* --- items --- */
404 static void IT_draw (void) {
405 int i, s;
406 for (i = 0; i < MAXITEM; ++i) {
407 s = -1;
408 if (it[i].t && it[i].s >= 0) {
409 switch(it[i].t & 0x7FFF) {
410 case I_ARM1:
411 s = it[i].s / 9 + 18;
412 break;
413 case I_ARM2:
414 s = it[i].s / 9 + 20;
415 break;
416 case I_MEGA:
417 s = it[i].s / 2 + 22;
418 break;
419 case I_INVL:
420 s = it[i].s / 2 + 26;
421 break;
422 case I_SUPER:
423 case I_RTORCH:
424 case I_GTORCH:
425 case I_BTORCH:
426 s = it[i].s / 2 + (it[i].t - I_SUPER) * 4 + 35;
427 break;
428 case I_GOR1: case I_FCAN:
429 s = it[i].s / 2 + (it[i].t - I_GOR1) * 3 + 51;
430 break;
431 case I_AQUA:
432 s = 30;
433 break;
434 case I_SUIT:
435 s = 34;
436 break;
437 case I_KEYR:
438 case I_KEYG:
439 case I_KEYB:
440 s = (it[i].t & 0x7FFF) - I_KEYR + 31;
441 break;
442 case I_GUN2:
443 s = 57;
444 break;
445 default:
446 s = (it[i].t & 0x7FFF) - 1;
449 if (s >= 0) {
450 Z_drawspr(it[i].o.x, it[i].o.y, item_spr[s], item_sprd[s]);
455 /* --- player --- */
457 static int standspr (player_t *p) {
458 if (p->f & PLF_UP) {
459 return 'X';
460 } else if (p->f & PLF_DOWN) {
461 return 'Z';
462 } else {
463 return 'E';
467 static int wpnspr (player_t *p) {
468 if (p->f & PLF_UP) {
469 return 'C';
470 } else if(p->f & PLF_DOWN) {
471 return 'E';
472 } else {
473 return 'A';
477 static void PL_draw (player_t *p) {
478 enum {STAND, GO, DIE, SLOP, DEAD, MESS, OUT, FALL}; // copypasted from player.c!
479 static int wytab[] = {-1, -2, -1, 0};
480 int s = 'A';
481 int w = 0;
482 int wx = 0;
483 int wy = 0;
484 switch (p->st) {
485 case STAND:
486 if (p->f & PLF_FIRE) {
487 s = standspr(p) + 1;
488 w = wpnspr(p) + 1;
489 } else if (p->pain) {
490 s = 'G';
491 w = 'A';
492 wx = p->d ? 2 : -2;
493 wy = 1;
494 } else {
495 s = standspr(p);
496 w = wpnspr(p);
498 break;
499 case DEAD:
500 s = 'N';
501 break;
502 case MESS:
503 s = 'W';
504 break;
505 case GO:
506 if (p->pain) {
507 s = 'G';
508 w = 'A';
509 wx = p->d ? 2 : -2;
510 wy = 1;
511 } else {
512 s = plr_goanim[p->s / 8];
513 w = (p->f & PLF_FIRE) ? 'B' : 'A';
514 wx = p->d ? 2 : -2;
515 wy = 1 + wytab[s - 'A'];
517 break;
518 case DIE:
519 s = plr_dieanim[p->s];
520 break;
521 case SLOP:
522 s = plr_slopanim[p->s];
523 break;
524 case OUT:
525 s = 0;
526 break;
528 if (p->wpn == 0) {
529 w = 0;
531 if (w) {
532 Z_drawspr(p->o.x + wx, p->o.y + wy, plr_wpn[p->wpn][w - 'A'], p->d);
534 if (s) {
535 Z_drawmanspr(p->o.x, p->o.y, plr_spr[(s - 'A') * 2 + p->d], plr_sprd[(s - 'A') * 2 + p->d], p->color);
539 static void PL_drawst (player_t *p) {
540 int i;
541 V_setrect(WD, 120, w_o, HT);
542 Z_clrst();
543 if (p->drawst & PL_DRAWAIR) {
544 if (p->air < PL_AIR) {
545 Z_drawstair(p->air);
548 if (p->drawst & PL_DRAWLIFE) {
549 Z_drawstprcnt(0, p->life);
551 if (p->drawst & PL_DRAWARMOR) {
552 Z_drawstprcnt(1, p->armor);
554 if (p->drawst & PL_DRAWWPN) {
555 switch(p->wpn) {
556 case 2:
557 case 5:
558 i = p->ammo;
559 break;
560 case 3:
561 case 4:
562 case 9:
563 i = p->shel;
564 break;
565 case 6:
566 i = p->rock;
567 break;
568 case 10:
569 i = p->fuel;
570 break;
571 case 7:
572 case 8:
573 i = p->cell;
574 break;
576 Z_drawstwpn(p->wpn, i);
578 if (p->drawst & PL_DRAWFRAG) {
579 Z_drawstnum(p->frag);
581 if (p->drawst & PL_DRAWKEYS) {
582 Z_drawstkeys(p->keys);
584 if (!_2pl) {
585 if (p->drawst & PL_DRAWLIVES) {
586 Z_drawstlives(p->lives);
591 /* --- monster --- */
593 #define MANCOLOR 0xD0
595 static void MN_draw (void) {
596 enum {SLEEP, GO, RUN, CLIMB, DIE, DEAD, ATTACK, SHOOT, PAIN, WAIT, REVIVE, RUNOUT}; // copypasted from monster.c!
597 int i;
598 for (i = 0; i < MAXMN; i++) {
599 if (mn[i].t) {
600 if (mn[i].t >= MN_PL_DEAD) {
601 Z_drawmanspr(mn[i].o.x, mn[i].o.y, pl_spr[mn[i].t - MN_PL_DEAD], 0, mn[i].d);
602 continue;
604 if ((mn[i].t != MN_SOUL && mn[i].t != MN_PAIN) || mn[i].st != DEAD) {
605 if (mn[i].t != MN_MAN) {
606 Z_drawspr(mn[i].o.x, mn[i].o.y, mn_spr[mn[i].t - 1][(mn[i].ap[mn[i].ac] - 'A') * 2 + mn[i].d], mn_sprd[mn[i].t - 1][(mn[i].ap[mn[i].ac] - 'A') * 2 + mn[i].d]);
607 } else {
608 if (mn[i].ap[mn[i].ac] == 'E' || mn[i].ap[mn[i].ac] == 'F') {
609 Z_drawspr(mn[i].o.x, mn[i].o.y, mn_sgun[mn[i].ap[mn[i].ac] - 'E'], mn[i].d);
611 Z_drawmanspr(mn[i].o.x, mn[i].o.y, mn_spr[mn[i].t - 1][(mn[i].ap[mn[i].ac] - 'A') * 2 + mn[i].d], mn_sprd[mn[i].t - 1][(mn[i].ap[mn[i].ac] - 'A') * 2 + mn[i].d], MANCOLOR);
614 if (mn[i].t == MN_VILE && mn[i].st == SHOOT) {
615 Z_drawspr(mn[i].tx, mn[i].ty, mn_fspr[mn[i].ac / 3], 0);
621 /* --- weapon --- */
623 static void WP_draw (void) {
624 enum {NONE, ROCKET, PLASMA, APLASMA, BALL1, BALL2, BALL7, BFGBALL, BFGHIT, MANF, REVF, FIRE}; // copypasted from weapons.c!
625 int i, s, d, x, y;
626 for (i = 0; i < MAXWPN; ++i) {
627 s = -1;
628 d = 0;
629 switch (wp[i].t) {
630 case NONE:
631 default:
632 break;
633 case REVF:
634 case ROCKET:
635 d = wp[i].s;
636 if (d < 2) {
637 d = wp[i].o.xv > 0 ? 1 : 0;
638 x = abs(wp[i].o.xv);
639 y = wp[i].o.yv;
640 s = 0;
641 if (y < 0) {
642 if (-y >= x) {
643 s = 30;
645 } else if (y > 0) {
646 if (y >= x / 2) {
647 s = 31;
650 } else {
651 s = (d - 2) / 2 + 1;
652 d = 0;
654 break;
655 case MANF:
656 s=wp[i].s;
657 if (s >= 2) {
658 s /= 2;
659 break;
661 case PLASMA:
662 case APLASMA:
663 case BALL1:
664 case BALL7:
665 case BALL2:
666 s = wp[i].s;
667 if (s >= 2) {
668 s = s / 2 + 1;
670 switch (wp[i].t) {
671 case PLASMA:
672 s += 4;
673 break;
674 case APLASMA:
675 s += 11;
676 break;
677 case BALL1:
678 s += 32;
679 break;
680 case BALL2:
681 s += 42;
682 break;
683 case BALL7:
684 s += 37;
685 d = wp[i].o.xv >= 0 ? 1 : 0;
686 break;
687 case MANF:
688 s += 47;
689 d= wp[i].o.xv>=0 ? 1 : 0;
690 break;
692 break;
693 case BFGBALL:
694 s = wp[i].s;
695 if (s >= 2) {
696 s = s / 2 + 1;
698 s += 18;
699 break;
700 case BFGHIT:
701 s = wp[i].s / 2 + 26;
702 break;
704 if (s >= 0) {
705 Z_drawspr(wp[i].o.x, wp[i].o.y, wp_spr[s * 2 + d], wp_sprd[s * 2 + d]);
710 /* --- smoke --- */
712 static void SMK_draw (void) {
713 int i, s;
714 for (i = 0; i < MAXSMOK; ++i) {
715 if (sm[i].t) {
716 switch (sm[i].s) {
717 case 0:
718 s = sm[i].t;
719 if (s >= (SMSN - 1) * 3) {
720 s = 0;
721 } else {
722 s = SMSN - 1 - s / 3;
724 V_sprf((sm[i].x >> 8) - w_x + WD / 2, (sm[i].y >> 8) - w_y + HT / 2 + 1 + w_o, smk_spr[s], &smoke_sprf);
725 break;
726 case 1:
727 s = sm[i].t;
728 if (s >= FLSN - 1) {
729 s = 0;
730 } else {
731 s = FLSN - 1 - s;
733 V_sprf((sm[i].x >> 8) - w_x + WD / 2, (sm[i].y >> 8) - w_y + HT / 2 + 1 + w_o, smk_fspr[s], &flame_sprf);
734 break;
740 /* --- fx --- */
742 static void FX_draw (void) {
743 enum {NONE, TFOG, IFOG, BUBL}; // copypasted from fx.c
744 int i, s;
745 for (i = 0; i < MAXFX; ++i) {
746 s = -1;
747 switch (fx[i].t) {
748 case TFOG:
749 s = fx[i].s / 2;
750 break;
751 case IFOG:
752 s = fx[i].s / 2 + 10;
753 break;
754 case BUBL:
755 V_dot((fx[i].x >> 8) - w_x + WD / 2, (fx[i].y >> 8) - w_y + HT / 2 + 1 + w_o, 0xC0 + fx[i].s);
756 continue;
758 if (s >= 0) {
759 Z_drawspr(fx[i].x, fx[i].y, fx_spr[s], fx_sprd[s]);
764 /* --- view --- */
766 static void W_adjust (void) {
767 int MAXX = FLDW * CELW - WD / 2;
768 int MAXY = FLDH * CELH - HT / 2;
769 if (w_x < WD / 2) w_x = WD / 2;
770 if (w_y < HT / 2) w_y = HT / 2;
771 if (w_x > MAXX) w_x = MAXX;
772 if (w_y > MAXY) w_y = MAXY;
775 static void W_draw(void) {
776 W_adjust();
777 V_setrect(0, WD, w_o + 1, HT);
778 if (w_horiz) {
779 vgaimg *img = (vgaimg*)horiz;
780 int x = 0;
781 int d = 0;
782 do {
783 int y = w_o;
784 d &= ~2;
785 do {
786 V_rotspr(x, y, img, d);
787 y += img->h;
788 d ^= 2;
789 } while (y < HT + w_o);
790 x += img->w;
791 d ^= 1;
792 } while (x < WD);
793 if (sky_type == 2) {
794 if (lt_time < 0) {
795 if (!lt_side) {
796 V_spr(0, w_o + lt_ypos, ltn[lt_type][lt_time < -5 ? 0 : 1]);
797 } else {
798 V_spr2(WD - 1, w_o + lt_ypos, ltn[lt_type][lt_time < -5 ? 0 : 1]);
802 } else {
803 V_clr(0, WD, w_o + 1, HT, 0x97);
805 Z_drawfld((byte*)fldb, 1);
806 DOT_draw();
807 IT_draw();
808 PL_draw(&pl1);
809 if (_2pl) {
810 PL_draw(&pl2);
812 MN_draw();
813 WP_draw();
814 SMK_draw();
815 FX_draw();
816 Z_drawfld((byte*)fldf, 0);
817 if (sky_type == 2) {
818 if (lt_time == -4 || lt_time == -2) {
819 V_remap_rect(0, WD, w_o + 1, HT, clrmap + 256 * 11);
824 /* --- game --- */
826 #define PL_FLASH 90
828 static void drawview (player_t *p) {
829 if (p->looky < -SCRH / 4) {
830 p->looky = -SCRH / 4;
831 } else if (p->looky > SCRH / 4) {
832 p->looky = SCRH / 4;
834 w_x = p->o.x;
835 w_y = p->o.y - 12 + p->looky;
836 W_draw();
837 PL_drawst(p);
840 static int get_pu_st (int t) {
841 if (t >= PL_FLASH) {
842 return 1;
843 } else if((t / 9) & 1) {
844 return 0;
845 } else {
846 return 1;
850 static void pl_info (player_t *p, int y) {
851 dword t = p->kills * 10920 / g_time;
852 Z_gotoxy(25, y); Z_printbf("KILLS");
853 Z_gotoxy(25, y + 15); Z_printbf("KPM");
854 Z_gotoxy(25, y + 30); Z_printbf("SECRETS %u / %u", p->secrets, sw_secrets);
855 Z_gotoxy(255, y); Z_printbf("%u", p->kills);
856 Z_gotoxy(255, y + 15); Z_printbf("%u.%u", t / 10, t % 10);
859 static void W_act (void) {
860 int i, a;
861 if (g_time % 3 == 0) {
862 for (i = 1; i < 256; i++) {
863 a = walani[i];
864 if (a != 0) {
865 anic[a]++;
866 if (anih[a][anic[a]] == -1) {
867 anic[a] = 0;
869 walp[i] = V_getvgaimg(anih[a][anic[a]]);
875 void R_draw (void) {
876 int h;
877 word hr, mn, sc;
878 W_act();
879 if (g_trans && !transdraw) {
880 return;
882 switch (g_st) {
883 case GS_ENDANIM:
884 case GS_END2ANIM:
885 case GS_DARKEN:
886 case GS_BVIDEO:
887 case GS_EVIDEO:
888 case GS_END3ANIM:
889 return;
890 case GS_TITLE:
891 V_center(1);
892 V_pic(0, 0, scrnh[0]);
893 V_center(0);
894 break;
895 case GS_ENDSCR:
896 V_center(1);
897 V_clr(0, SCRW, 0, SCRH, 0);
898 V_pic(0, 0, scrnh[2]);
899 V_center(0);
900 break;
901 case GS_INTER:
902 V_center(1);
903 V_clr(0, SCRW, 0, SCRH, 0);
904 V_pic(0, 0, scrnh[1]);
905 Z_gotoxy(60, 20);
906 Z_printbf("LEVEL COMPLETE");
907 Z_calc_time(g_time, &hr, &mn, &sc);
908 Z_gotoxy(115, 40);
909 Z_printbf("TIME %u:%02u:%02u", hr, mn, sc);
910 h = 60;
911 if (_2pl) {
912 Z_gotoxy(80, h);
913 Z_printbf("PLAYER ONE");
914 Z_gotoxy(80, h + 70);
915 Z_printbf("PLAYER TWO");
916 h += SCRH / 10;
918 pl_info(&pl1, h);
919 if (_2pl) {
920 pl_info(&pl2, h + 70);
922 V_center(0);
923 break;
925 V_center(1);
926 if (g_st != GS_GAME) {
927 if (g_trans) {
928 return;
930 GM_draw();
931 V_copytoscr(0, SCRW, 0, SCRH);
932 return;
934 V_center(0);
935 if (_2pl) {
936 w_o = 0;
937 WD = SCRW - 120;
938 HT = SCRH / 2 - 2;
939 drawview(&pl1);
940 w_o = SCRH / 2;
941 WD = SCRW - 120;
942 HT = SCRH / 2 - 2;
943 drawview(&pl2);
944 } else{
945 w_o = 0;
946 WD = SCRW - 120;
947 HT = SCRH - 2;
948 drawview(&pl1);
950 if (g_trans) {
951 return;
953 V_center(1);
954 if (GM_draw()) {
955 pl1.drawst = 0xFF;
956 pl2.drawst = 0xFF;
957 V_copytoscr(0,SCRW,0,SCRH);
958 return;
960 V_center(0);
961 if (pl1.invl) {
962 h = get_pu_st(pl1.invl) * 6;
963 } else if (pl1.pain < 15) {
964 h = 0;
965 } else if (pl1.pain < 35) {
966 h = 1;
967 } else if (pl1.pain < 55) {
968 h = 2;
969 } else if (pl1.pain < 75) {
970 h=3;
971 } else if (pl1.pain < 95) {
972 h=4;
973 } else {
974 h = 5;
976 if (h != 0) {
977 V_maptoscr(0, SCRW - 120, 1, _2pl ? SCRH / 2 - 2 : SCRH - 2, clrmap + h * 256);
978 } else {
979 V_copytoscr(0, SCRW - 120, 1, _2pl ? SCRH / 2 - 2 : SCRH - 2);
981 if (pl1.drawst) {
982 V_copytoscr(SCRW - 120, 120, 0, _2pl ? SCRH / 2 : SCRH);
984 pl1.drawst = 0xFF;
985 if (_2pl) {
986 if (pl2.invl) {
987 h = get_pu_st(pl2.invl) * 6;
988 } else if (pl2.pain < 15) {
989 h = 0;
990 } else if (pl2.pain < 35) {
991 h = 1;
992 } else if (pl2.pain < 55) {
993 h = 2;
994 } else if (pl2.pain < 75) {
995 h = 3;
996 } else if (pl2.pain < 95) {
997 h = 4;
998 } else {
999 h = 5;
1001 if (h) {
1002 V_maptoscr(0, SCRW - 120, SCRH / 2 + 1, SCRH / 2 - 2, clrmap + h * 256);
1003 } else {
1004 V_copytoscr(0, SCRW - 120, SCRH / 2 + 1, SCRH / 2 - 2);
1006 if (pl2.drawst) {
1007 V_copytoscr(SCRW - 120, 120, SCRH / 2, SCRH / 2);
1009 pl2.drawst = 0xFF;
1013 void R_alloc (void) {
1014 int i, j, n;
1015 char s[10];
1016 logo("R_alloc: загрузка графики\n");
1017 // game
1018 scrnh[0] = V_loadvgaimg("TITLEPIC");
1019 scrnh[1] = V_loadvgaimg("INTERPIC");
1020 scrnh[2] = V_loadvgaimg("ENDPIC");
1021 cd_scr = M_lock(F_getresid("CD1PIC"));
1022 for (i = 0; i < 2; ++i) {
1023 sprintf(s, "LTN%c", i + '1');
1024 for (j = 0; j < 2; ++j) {
1025 ltn[i][j] = Z_getspr(s, j, 0, NULL);
1028 // smoke
1029 for (i = 0; i < SMSN; ++i) {
1030 smk_spr[i] = Z_getspr("SMOK", i, 0, NULL);
1032 for (i = 0; i < FLSN; ++i) {
1033 smk_fspr[i] = Z_getspr("FLAM", i, 0, NULL);
1035 // fx
1036 for (i = 0; i < 10; ++i) {
1037 fx_spr[i] = Z_getspr("TFOG", i, 0, fx_sprd + i);
1039 for (; i < 15; ++i) {
1040 fx_spr[i] = Z_getspr("IFOG", i - 10, 0, fx_sprd + i);
1042 // weapons
1043 for (i = 0; i < 4; ++i) {
1044 wp_spr[i * 2] = Z_getspr("MISL", i, 1, wp_sprd + i * 2);
1045 wp_spr[i * 2 + 1] = Z_getspr("MISL", i, 2, wp_sprd + i * 2 + 1);
1047 for (; i < 6; ++i) {
1048 wp_spr[i * 2] = Z_getspr("PLSS", i - 4, 1, wp_sprd + i * 2);
1049 wp_spr[i * 2 + 1] = Z_getspr("PLSS", i - 4, 2, wp_sprd + i * 2 + 1);
1051 for (; i < 11; ++i) {
1052 wp_spr[i * 2] = Z_getspr("PLSE", i - 6, 1, wp_sprd + i * 2);
1053 wp_spr[i * 2 + 1] = Z_getspr("PLSE", i - 6, 2, wp_sprd + i * 2 + 1);
1055 for (; i < 13; ++i) {
1056 wp_spr[i * 2] = Z_getspr("APLS", i - 11, 1, wp_sprd + i * 2);
1057 wp_spr[i * 2 + 1] = Z_getspr("APLS", i - 11, 2, wp_sprd + i * 2 + 1);
1059 for (; i < 18; ++i) {
1060 wp_spr[i * 2] = Z_getspr("APBX", i - 13, 1, wp_sprd + i * 2);
1061 wp_spr[i * 2 + 1] = Z_getspr("APBX", i - 13, 2, wp_sprd + i * 2 + 1);
1063 for(; i < 20; ++i) {
1064 wp_spr[i * 2] = Z_getspr("BFS1", i - 18, 1, wp_sprd + i * 2);
1065 wp_spr[i * 2 + 1] = Z_getspr("BFS1", i - 18, 2, wp_sprd + i * 2 + 1);
1067 for (; i < 26; ++i) {
1068 wp_spr[i * 2] = Z_getspr("BFE1", i - 20, 1, wp_sprd + i * 2);
1069 wp_spr[i * 2 + 1] = Z_getspr("BFE1", i - 20, 2, wp_sprd + i * 2 + 1);
1071 for (; i < 30; ++i) {
1072 wp_spr[i * 2] = Z_getspr("BFE2", i - 26, 1, wp_sprd + i * 2);
1073 wp_spr[i * 2 + 1] = Z_getspr("BFE2", i - 26, 2, wp_sprd + i * 2 + 1);
1075 for (; i < 32; ++i) {
1076 wp_spr[i * 2] = Z_getspr("MISL", i - 30 + 4, 1, wp_sprd + i * 2);
1077 wp_spr[i * 2 + 1] = Z_getspr("MISL", i - 30 + 4, 2, wp_sprd + i * 2 + 1);
1079 for (; i < 37; ++i) {
1080 wp_spr[i * 2] = Z_getspr("BAL1", i - 32, 1, wp_sprd + i * 2);
1081 wp_spr[i * 2 + 1] = Z_getspr("BAL1", i - 32, 2, wp_sprd + i * 2 + 1);
1083 for (; i < 42; ++i) {
1084 wp_spr[i * 2] = Z_getspr("BAL7", i - 37, 1, wp_sprd + i * 2);
1085 wp_spr[i * 2 + 1] = Z_getspr("BAL7", i - 37, 2, wp_sprd + i * 2 + 1);
1087 for (; i < 47; ++i) {
1088 wp_spr[i * 2] = Z_getspr("BAL2", i - 42, 1, wp_sprd + i * 2);
1089 wp_spr[i * 2 + 1] = Z_getspr("BAL2", i - 42, 2, wp_sprd + i * 2 + 1);
1091 for (; i < 49; ++i) {
1092 wp_spr[i * 2] = Z_getspr("MANF", i - 47, 1, wp_sprd + i * 2);
1093 wp_spr[i * 2 + 1] = Z_getspr("MANF", i - 47, 2, wp_sprd + i * 2 + 1);
1095 // items
1096 static char snm[18][4] = {
1097 "CLIP", "SHEL", "ROCK", "CELL", "AMMO", "SBOX", "BROK", "CELP",
1098 "STIM", "MEDI", "BPAK",
1099 "CSAW", "SHOT", "SGN2", "MGUN", "LAUN", "PLAS", "BFUG"
1100 };
1101 static char n4[4][4] = {
1102 "SOUL", "SMRT", "SMGT", "SMBT"
1103 };
1104 static char n3[2][4] = {
1105 "GOR1", "FCAN"
1106 };
1107 for (i = 0; i < 18; ++i) {
1108 item_spr[i] = Z_getspr(snm[i], 0, 0, item_sprd + i);
1110 for (; i < 20; ++i) {
1111 item_spr[i] = Z_getspr("ARM1", i - 18, 0, item_sprd + i);
1112 item_spr[i + 2] = Z_getspr("ARM2", i - 18, 0, item_sprd + i);
1114 i+=2;
1115 for (; i < 26; ++i) {
1116 item_spr[i] = Z_getspr("MEGA", i - 22, 0, item_sprd + i);
1118 for (; i < 30; ++i) {
1119 item_spr[i] = Z_getspr("PINV", i - 26, 0, item_sprd + i);
1121 item_spr[30] = Z_getspr("AQUA", 0, 0, item_sprd + 30);
1122 item_spr[31] = Z_getspr("KEYR", 0, 0, item_sprd + 31);
1123 item_spr[32] = Z_getspr("KEYG", 0, 0, item_sprd + 32);
1124 item_spr[33] = Z_getspr("KEYB", 0, 0, item_sprd + 33);
1125 item_spr[34] = Z_getspr("SUIT", 0, 0, item_sprd + 34);
1126 for (n = 35, j = 0; j < 4; ++j) {
1127 for (i = 0; i < 4; ++i, ++n) {
1128 item_spr[n] = Z_getspr(n4[j], i, 0, item_sprd + n);
1131 for (j = 0; j < 2; ++j) {
1132 for (i = 0; i < 3; ++i, ++n) {
1133 item_spr[n] = Z_getspr(n3[j], i, 0, item_sprd + n);
1136 item_spr[57] = Z_getspr("GUN2", 0, 0, item_sprd + 57);
1137 // player
1138 for (i = 0; i < 27; ++i) {
1139 plr_spr[i * 2] = Z_getspr("PLAY", i, 1, plr_sprd + i * 2);
1140 plr_spr[i * 2 + 1] = Z_getspr("PLAY", i, 2, plr_sprd + i * 2 + 1);
1142 strncpy(s, "PWPx", 4);
1143 for (i = 1; i < 11; ++i) {
1144 s[3] = (i < 10 ? '0' : 'A' - 10) + i;
1145 for (j = 0; j < 6; ++j) {
1146 plr_wpn[i][j] = Z_getspr(s, j, 1, NULL);
1149 // monsters
1150 static char msn[MN_TN][4] = {
1151 "SARG", "TROO", "POSS", "SPOS", "CYBR", "CPOS", "BOSS", "BOS2", "HEAD", "SKUL",
1152 "PAIN", "SPID", "BSPI", "FATT", "SKEL", "VILE", "FISH", "BAR1", "ROBO", "PLAY"
1153 };
1154 static int mms[MN_TN] = {
1155 14*2, 21*2, 21*2, 21*2, 16*2, 20*2, 15*2, 15*2, 12*2, 11*2, 13*2, 19*2, 16*2,
1156 20*2, 17*2, 29*2, 6*2, 2*2, 17*2, 23*2
1157 };
1158 mn_sgun[0] = Z_getspr("PWP4", 0, 1, NULL);
1159 mn_sgun[1] = Z_getspr("PWP4", 1, 1, NULL);
1160 for (j = 0; j < MN_TN; ++j) {
1161 for (i = 0; i < mms[j]; ++i) {
1162 mn_spr[j][i] = Z_getspr(msn[j], i / 2, (i & 1) + 1, &mn_sprd[j][i]);
1164 if (j == MN_BARREL - 1) {
1165 for (i = 4; i < 14; ++i) {
1166 mn_spr[j][i] = Z_getspr("BEXP", i / 2 - 2, (i & 1) + 1, &mn_sprd[j][i]);
1170 for (i = 0; i < 8; ++i) {
1171 mn_fspr[i] = Z_getspr("FIRE", i, 0, NULL);
1173 pl_spr[0] = Z_getspr("PLAY", 'N' - 'A', 0, NULL);
1174 pl_spr[1] = Z_getspr("PLAY", 'W' - 'A', 0, NULL);
1175 // misc
1176 static char mnm[22][8]={
1177 "STTNUM0","STTNUM1","STTNUM2","STTNUM3","STTNUM4",
1178 "STTNUM5","STTNUM6","STTNUM7","STTNUM8","STTNUM9",
1179 "STTMINUS","STTPRCNT",
1180 "FISTA0","CSAWA0","PISTA0","SHOTA0","SGN2A0","MGUNA0","LAUNA0",
1181 "PLASA0","BFUGA0","GUN2A0"
1182 };
1183 stone=V_loadvgaimg("STONE");
1184 stone2=V_loadvgaimg("STONE2");
1185 keys[0]=V_loadvgaimg("KEYRA0");
1186 keys[1]=V_loadvgaimg("KEYGA0");
1187 keys[2]=V_loadvgaimg("KEYBA0");
1188 for (i = 0; i < 22; ++i) {
1189 sth[i] = V_loadvgaimg(mnm[i]);
1191 strcpy(s, "STBF_*");
1192 for (i = '!'; i < 160; ++i) {
1193 s[5] = i;
1194 bfh[i - '!'] = V_getvgaimg(F_findres(s));
1196 for (i = '!'; i < 160; ++i) {
1197 sprintf(s, "STCFN%03d", i);
1198 sfh[i - '!'] = V_getvgaimg(F_findres(s));
1200 strcpy(s, "WINUM*");
1201 for (i = '0'; i <= '9'; ++i) {
1202 s[5] = i;
1203 bfh[i - '!'] = V_loadvgaimg(s);
1205 bfh[':' - '!'] = V_loadvgaimg("WICOLON");
1206 // menu
1207 msklh[0] = V_loadvgaimg("M_SKULL1");
1208 msklh[1] = V_loadvgaimg("M_SKULL2");
1209 mbarl = V_loadvgaimg("M_THERML");
1210 mbarm = V_loadvgaimg("M_THERMM");
1211 mbarr = V_loadvgaimg("M_THERMR");
1212 mbaro = V_loadvgaimg("M_THERMO");
1213 mslotl = V_loadvgaimg("M_LSLEFT");
1214 mslotm = V_loadvgaimg("M_LSCNTR");
1215 mslotr = V_loadvgaimg("M_LSRGHT");
1216 // walls
1217 static char *anm[ANIT - 1][5] = {
1218 {"WALL22_1", "WALL23_1", "WALL23_2", NULL, NULL},
1219 {"WALL58_1", "WALL58_2", "WALL58_3", NULL, NULL},
1220 {"W73A_1", "W73A_2", NULL, NULL, NULL},
1221 {"RP2_1", "RP2_2", "RP2_3", "RP2_4", NULL}
1222 };
1223 for (i = 1; i < ANIT; i++) {
1224 for (j = 0; anm[i - 1][j]; j++) {
1225 anih[i][j] = F_getresid(anm[i - 1][j]);
1227 for(; j < 5; j++) {
1228 anih[i][j] = -1;
1233 void R_get_name (int n, char s[8]) {
1234 if (walh[n] == -1) {
1235 memset(s, 0, 8);
1236 } else if (walh[n] == -2) {
1237 memcpy(s, "_WATER_", 8);
1238 s[7] = (char)((intptr_t)walp[n] - 1 + '0');
1239 } else {
1240 F_getresname(s, walh[n] & 0x7FFF);
1244 static short getani (char n[8]) {
1245 if (strncasecmp(n, "WALL22_1", 8) == 0) {
1246 return 1;
1247 } else if (strncasecmp(n, "WALL58_1", 8) == 0) {
1248 return 2;
1249 } else if (strncasecmp(n, "W73A_1", 8) == 0) {
1250 return 3;
1251 } else if (strncasecmp(n, "RP2_1", 8) == 0) {
1252 return 4;
1253 } else {
1254 return 0;
1258 int R_get_special_id (int n) {
1259 assert(n >= 0 && n < 256);
1260 intptr_t x = (intptr_t)walp[n];
1261 return x >= 0 && x <= 3 ? x : -1;
1264 void R_begin_load (void) {
1265 int i;
1266 for (i = 0; i < 256; i++) {
1267 if (walp[i] != NULL && walh[i] >= 0) {
1268 M_unlock(walp[i]);
1270 walh[i] = -1;
1271 walp[i] = NULL;
1272 walswp[i] = i;
1273 walani[i] = 0;
1275 memset(anic, 0, sizeof(anic));
1276 max_textures = 1;
1279 void R_load (char s[8], int f) {
1280 assert(max_textures < 256);
1281 if (!s[0]) {
1282 walh[max_textures] = -1;
1283 walp[max_textures] = NULL;
1284 } else {
1285 if (strncasecmp(s, "_WATER_", 7) == 0) {
1286 walh[max_textures] = -2;
1287 walp[max_textures] = (void*)((intptr_t)s[7] - '0' + 1);
1288 } else {
1289 walh[max_textures] = F_getresid(s);
1290 walp[max_textures] = V_getvgaimg(walh[max_textures]);
1291 if (f) {
1292 walh[max_textures] |= 0x8000;
1294 if (s[0] == 'S' && s[1] == 'W' && s[4] == '_') {
1295 walswp[max_textures] = 0;
1298 walani[max_textures] = getani(s);
1300 max_textures++;
1303 void R_end_load (void) {
1304 int i, j, k, g;
1305 char s[8];
1306 j = max_textures;
1307 for (i = 1; i < 256 && j < 256; i++) {
1308 if (walswp[i] == 0) {
1309 R_get_name(i, s);
1310 s[5] ^= 1;
1311 g = F_getresid(s) | (walh[i] & 0x8000);
1312 k = 1;
1313 while (k < 256 && walh[k] != g) {
1314 k += 1;
1316 if (k >= 256) {
1317 k = j;
1318 j += 1;
1319 walh[k] = g;
1320 walp[k] = V_getvgaimg(g);
1321 walf[k] = g & 0x8000 ? 1 : 0;
1323 walswp[i] = k;
1324 walswp[k] = i;
1329 void R_loadsky (int sky) {
1330 char s[6];
1331 strcpy(s, "RSKY1");
1332 s[4] = '0' + sky;
1333 M_unlock(horiz);
1334 horiz = V_loadvgaimg(s);
1337 void R_setgamma(int g) {
1338 int t;
1339 g = g < 0 ? 0 : (g > 4 ? 4 : g);
1340 gammaa = g;
1341 for (t = 0; t < 256; ++t) {
1342 std_pal[t][0]=gamcor[gammaa][main_pal[t][0]];
1343 std_pal[t][1]=gamcor[gammaa][main_pal[t][1]];
1344 std_pal[t][2]=gamcor[gammaa][main_pal[t][2]];
1346 Y_set_vga_palette(std_pal);
1349 int R_getgamma (void) {
1350 return gammaa;
1353 void R_set_videomode (int w, int h, int fullscreen) {
1354 assert(w > 0);
1355 assert(h > 0);
1356 int was = Y_videomode_setted();
1357 int res = Y_set_videomode_software(w, h, fullscreen);
1358 if (res == 0) {
1359 if (was == 0) {
1360 ERR_failinit("Unable to set video mode");
1362 } else {
1363 Y_get_videomode(&SCRW, &SCRH);
1364 V_update_buffer();
1365 R_setgamma(gammaa);
1369 void R_toggle_fullscreen (void) {
1370 Y_set_fullscreen(!Y_get_fullscreen());
1371 fullscreen = Y_get_fullscreen();
1372 Y_get_videomode(&SCRW, &SCRH);
1373 V_update_buffer();
1374 R_setgamma(gammaa);
1377 void R_init () {
1378 int i;
1379 logo("R_init: initialize software render\n");
1380 F_loadres(F_getresid("PLAYPAL"), main_pal, 0, 768);
1381 for (i = 0; i < 256; ++i) {
1382 bright[i] = ((int) main_pal[i][0] + main_pal[i][1] + main_pal[i][2]) * 8 / (63 * 3);
1384 F_loadres(F_getresid("MIXMAP"), mixmap, 0, 0x10000);
1385 F_loadres(F_getresid("COLORMAP"), clrmap, 0, 256*12);
1386 R_set_videomode(SCRW, SCRH, fullscreen);
1387 V_setrect(0, SCRW, 0, SCRH);
1388 V_clr(0, SCRW, 0, SCRH, 0);
1389 R_alloc();
1392 void R_done (void) {
1393 buffer = NULL;
1394 buf_w = 0;
1395 buf_h = 0;
1396 pitch = 0;
1397 Y_unset_videomode();