DEADSOFTWARE

fully separate render
[flatwaifu.git] / src / 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"
23 // game
24 static vgaimg *scrnh[3]; // TITLEPIC INTERPIC ENDPIC
25 static vgaimg *ltn[2][2];
26 static void *cd_scr;
27 // smoke
28 static vgaimg *smk_spr[SMSN];
29 static vgaimg *smk_fspr[FLSN];
30 // fx
31 static vgaimg *fx_spr[15];
32 static char fx_sprd[15];
33 // weapons
34 static vgaimg *wp_spr[49*2];
35 static char wp_sprd[49*2];
36 // items
37 static vgaimg *item_spr[58];
38 static char item_sprd[58];
39 // player
40 static vgaimg *plr_spr[27*2];
41 static char plr_sprd[27*2];
42 static vgaimg *plr_wpn[11][6];
43 // monsters
44 static vgaimg *pl_spr[2];
45 static vgaimg *mn_spr[MN_TN][29*2];
46 static char mn_sprd[MN_TN][29*2];
47 static vgaimg *mn_fspr[8];
48 static vgaimg *mn_sgun[2];
49 // misc
50 #define MAXAIR 1091
51 static vgaimg *sth[22], *bfh[160 - '!'], *sfh[160 - '!'], *stone, *stone2, *keys[3];
52 static int prx = 0, pry = 0;
53 // menu
54 static vgaimg *msklh[2], *mbarl, *mbarm, *mbarr, *mbaro, *mslotl, *mslotm, *mslotr;
55 // low level
56 static int gammaa = 0;
57 static char main_pal[256][3];
58 static char std_pal[256][3];
59 static byte gamcor[5][64]={
60 #include "gamma.dat"
61 };
62 // walls
63 #define ANIT 5
64 static vgaimg *walp[256];
65 static int walh[256];
66 static byte walani[256];
67 static int anih[ANIT][5];
68 static byte anic[ANIT];
69 static int max_textures;
70 static vgaimg *horiz;
72 extern byte bright[256]; // vga.c
73 extern byte mixmap[256][256]; // vga.c
74 extern byte clrmap[256*12]; // vga.c
76 extern int g_trans; // game.c
77 extern byte transdraw; // game.c
78 extern int sky_type; // view.c
79 extern int lt_time, lt_type, lt_side, lt_ypos, lt_force; // game.c
81 extern byte savname[7][24]; // files.c
82 extern char g_music[8]; // game.c
83 extern short snd_vol; // sound.c
84 extern short mus_vol; // music.c
86 /* --- misc --- */
88 static void *Z_getspr (char n[4], int s, int d, char *dir) {
89 int h = F_getsprid(n, s, d);
90 if (dir) {
91 *dir = (h & 0x8000) ? 1 : 0;
92 }
93 return V_getvgaimg(h);
94 }
96 static void Z_putbfch (int c) {
97 vgaimg *p;
98 if (c > 32 && c < 160) {
99 p = bfh[c - '!'];
100 } else {
101 p = NULL;
103 if (p) {
104 V_spr(prx, pry, p);
105 prx += p->w - 1;
106 } else {
107 prx += 12;
111 static void Z_putsfch(int c) {
112 vgaimg *p;
113 if (c > 32 && c < 160) {
114 p = sfh[c - '!'];
115 } else {
116 p = NULL;
118 if (p) {
119 V_spr(prx, pry, p);
120 prx += p->w - 1;
121 } else {
122 prx += 7;
126 static void Z_gotoxy (int x, int y) {
127 prx = x;
128 pry = y;
131 static void Z_printbf(char *s, ...) {
132 int i;
133 va_list ap;
134 char buf[80];
135 va_start(ap, s);
136 vsprintf(buf, s, ap);
137 va_end(ap);
138 for (i = 0; buf[i]; ++i) {
139 switch (buf[i]) {
140 case '\n':
141 pry += 13;
142 case '\r':
143 prx = 0;
144 break;
145 default:
146 Z_putbfch((byte)buf[i]);
151 static void Z_printsf (char *s, ...) {
152 int i;
153 va_list ap;
154 char buf[80];
155 va_start(ap, s);
156 vsprintf(buf, s, ap);
157 va_end(ap);
158 for (i = 0; buf[i]; ++i) {
159 switch(buf[i]) {
160 case '\n':
161 pry += 8;
162 case '\r':
163 prx=0;
164 break;
165 default:
166 Z_putsfch((byte)buf[i]);
171 static void Z_drawspr (int x, int y, void *p, char d) {
172 if (d) {
173 V_spr2(x - w_x + WD / 2, y - w_y + HT / 2 + 1 + w_o, p);
174 } else {
175 V_spr(x - w_x + WD / 2, y - w_y + HT / 2 + 1 + w_o, p);
179 static void Z_clrst (void) {
180 V_pic(SCRW - 120, w_o, stone);
181 int y = ((vgaimg*)stone)->h;
182 while (y < HT) {
183 V_pic(SCRW - 120, w_o + y, stone2);
184 y += ((vgaimg*)stone)->h;
188 static void Z_drawstlives (char n) {
189 V_setrect(SCRW - 40, 30, w_o, 40);
190 V_spr(SCRW - 35, w_o + 17, sth[n]);
193 static void Z_drawstkeys (byte k) {
194 int x, n;
195 V_setrect(SCRW - 120, 70, w_o + 77, 23);
196 for (k >>= 4, n = 0, x = SCRW - 75; n < 3; ++n, k >>= 1, x += 9) {
197 if (k & 1) {
198 V_spr(x, w_o + 91, keys[n]);
203 static void Z_drawstair (int a) {
204 V_setrect(SCRW - 120, 120, w_o + 49, 2);
205 if (a > 0) {
206 if (a > MAXAIR) {
207 a = MAXAIR;
209 a = a * 100 / MAXAIR;
210 V_clr(SCRW - 110, a, w_o + 49, 2, 0xC8);
214 static void Z_drawstprcnt (int y, int n) {
215 char s[20];
216 int l, i, x, c;
217 V_setrect(SCRW - 120, 70, y * 19 + 7 + w_o, 19);
218 sprintf(s, "%3d%%", n);
219 l = strlen(s);
220 x = SCRW - 110;
221 for (i = 0; i < l; ++i, x += 14) {
222 if (s[i] >='0' && s[i] <= '9') {
223 c = s[i] - '0';
224 } else if (s[i] == '-') {
225 c = 10;
226 } else if (s[i] == '%') {
227 c = 11;
228 } else {
229 c = -1;
231 if (c >= 0) {
232 V_spr(x, y * 19 + 7 + w_o, sth[c]);
237 static void Z_drawstnum (int n) {
238 char s[20];
239 int l, i, x, c;
240 V_setrect(SCRW - 50, 50, w_o + 77, 23);
241 if (g_dm) {
242 sprintf(s, "%d", n);
243 l = strlen(s);
244 x = (115 - l * 14) + SCRW - 120;
245 for (i = 0; i < l; ++i, x += 14) {
246 if (s[i] >= '0' && s[i] <= '9') {
247 c = s[i] - '0';
248 } else if (s[i] == '-') {
249 c = 10;
250 } else if(s[i] == '%') {
251 c = 11;
252 } else {
253 c =- 1;
255 if (c >= 0) {
256 V_spr(x, w_o + 77 + 5, sth[c]);
262 static void Z_drawstwpn (int n, int a) {
263 char s[20];
264 int l, i, x, c;
265 i = n;
266 V_setrect(SCRW - 120, 120, w_o + 58, 23);
267 if (i >= 0) {
268 V_spr(SCRW - 88, w_o + 58 + 19, sth[i + 12]);
270 if (n >= 2) {
271 sprintf(s, "%d", a);
272 l = strlen(s);
273 x = SCRW - 10 - l * 14;
274 for (i = 0; i < l; ++i, x += 14) {
275 if (s[i] >= '0' && s[i] <= '9') {
276 c = s[i] - '0';
277 } else if (s[i] == '-') {
278 c = 10;
279 } else if (s[i] == '%') {
280 c = 11;
281 } else {
282 c = -1;
284 if (c >= 0) {
285 V_spr(x, w_o + 58 + 2, sth[c]);
291 static void Z_drawmanspr (int x, int y, void *p, char d, byte color) {
292 if (d) {
293 V_manspr2(x - w_x + WD / 2, y - w_y + HT / 2 + 1 + w_o, p, color);
294 } else {
295 V_manspr(x - w_x + WD / 2, y - w_y + HT / 2 + 1 + w_o, p, color);
299 static void Z_drawfld (byte *fld, int bg) {
300 byte *p = fld;
301 int x, y;
302 for (y = 0; y < FLDH; y++) {
303 for (x = 0; x < FLDW; x++) {
304 int sx = x * CELW - w_x + WD / 2;
305 int sy = y * CELH - w_y + HT / 2 + 1 + w_o;
306 int id = *p;
307 if (id != 0) {
308 int spc = R_get_special_id(id);
309 if (spc <= 3) {
310 if (!bg) {
311 byte *cmap = clrmap + (spc + 7) * 256;
312 V_remap_rect(sx, sy, CELW, CELH, cmap);
314 } else {
315 V_pic(sx, sy, walp[id]);
318 p++;
323 /* --- menu --- */
325 static int gm_tm = 0; // ???
327 static vgaimg *PL_getspr (int s, int d) {
328 return plr_spr[(s - 'A') * 2 + d];
331 static int GM_draw (void) {
332 enum {MENU, MSG}; // copypasted from menu.c!
333 enum {
334 CANCEL, NEWGAME, LOADGAME, SAVEGAME, OPTIONS, QUITGAME, QUIT, ENDGAME, ENDGM,
335 PLR1, PLR2, COOP, DM, VOLUME, GAMMA, LOAD, SAVE, PLCOLOR, PLCEND, MUSIC, INTERP,
336 SVOLM, SVOLP, MVOLM, MVOLP, GAMMAM, GAMMAP, PL1CM, PL1CP, PL2CM, PL2CP
337 }; // copypasted from menu.c!
338 int i, j, k, y;
339 ++gm_tm;
340 V_setrect(0, SCRW, 0, SCRH);
341 if (!mnu && !gm_redraw) {
342 return 0;
344 gm_redraw = 0;
345 if (!mnu) {
346 return 1;
348 if (mnu->type == MENU) {
349 y = (200 - mnu -> n * 16 - 20) / 2;
350 Z_gotoxy(mnu->x, y - 10); Z_printbf(mnu->ttl);
351 for (i = 0; i < mnu->n; ++i) {
352 if (mnu->t[i] == LOAD || mnu->t[i] == SAVE) {
353 j = y + i * 16 + 29;
354 V_spr(mnu->x, j, mslotl);
355 for (k = 8; k < 184; k += 8) {
356 V_spr(mnu->x + k, j, mslotm);
358 V_spr(mnu->x+184,j,mslotr);
359 Z_gotoxy(mnu->x+4,j-8);
360 if (input && i == save_mnu.cur) {
361 Z_printsf("%s_", ibuf);
362 } else {
363 Z_printsf("%s", savname[i]);
365 } else {
366 Z_gotoxy(mnu->x + (mnu->t[i] >= SVOLM ? (mnu->t[i] >= PL1CM ? 50 : 152) : 0), y + i * 16 + 20);
367 Z_printbf(mnu->m[i]);
369 if (mnu->t[i] == MUSIC) {
370 Z_printbf(" '%.8s'",g_music);
371 } else if(mnu->t[i] == INTERP) {
372 Z_printbf("%s", fullscreen ? "ON" : "OFF");
373 } else if(mnu->t[i] >= PL1CM) {
374 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]);
375 } else if(mnu->t[i] >= SVOLM) {
376 j = y + i * 16 + 20;
377 V_spr(mnu->x, j, mbarl);
378 for (k = 8; k < 144; k += 8) {
379 V_spr(mnu->x + k, j, mbarm);
381 V_spr(mnu->x + 144, j, mbarr);
382 switch(mnu->t[i]) {
383 case SVOLM: k = snd_vol; break;
384 case MVOLM: k = mus_vol; break;
385 case GAMMAM: k = gammaa << 5; break;
387 V_spr(mnu->x + 8 + k, j, mbaro);
390 V_spr(mnu->x - 25, y + mnu->cur * 16 + 20 - 8, msklh[(gm_tm / 6) & 1]);
391 } else {
392 Z_gotoxy((320 - strlen(mnu->ttl) * 7) / 2, 90); Z_printsf(mnu->ttl);
393 Z_gotoxy(136, 100); Z_printsf("(Y/N)");
395 return 1;
398 /* --- dots --- */
400 static void DOT_draw (void) {
401 int i;
402 for (i = 0; i < MAXDOT; ++i) {
403 if (dot[i].t) {
404 V_dot(dot[i].o.x - w_x + WD / 2, dot[i].o.y - w_y + HT / 2 + 1 + w_o, dot[i].c);
409 /* --- items --- */
411 static void IT_draw (void) {
412 int i, s;
413 for (i = 0; i < MAXITEM; ++i) {
414 s = -1;
415 if (it[i].t && it[i].s >= 0) {
416 switch(it[i].t & 0x7FFF) {
417 case I_ARM1:
418 s = it[i].s / 9 + 18;
419 break;
420 case I_ARM2:
421 s = it[i].s / 9 + 20;
422 break;
423 case I_MEGA:
424 s = it[i].s / 2 + 22;
425 break;
426 case I_INVL:
427 s = it[i].s / 2 + 26;
428 break;
429 case I_SUPER:
430 case I_RTORCH:
431 case I_GTORCH:
432 case I_BTORCH:
433 s = it[i].s / 2 + (it[i].t - I_SUPER) * 4 + 35;
434 break;
435 case I_GOR1: case I_FCAN:
436 s = it[i].s / 2 + (it[i].t - I_GOR1) * 3 + 51;
437 break;
438 case I_AQUA:
439 s = 30;
440 break;
441 case I_SUIT:
442 s = 34;
443 break;
444 case I_KEYR:
445 case I_KEYG:
446 case I_KEYB:
447 s = (it[i].t & 0x7FFF) - I_KEYR + 31;
448 break;
449 case I_GUN2:
450 s = 57;
451 break;
452 default:
453 s = (it[i].t & 0x7FFF) - 1;
456 if (s >= 0) {
457 Z_drawspr(it[i].o.x, it[i].o.y, item_spr[s], item_sprd[s]);
462 /* --- player --- */
464 static int standspr (player_t *p) {
465 if (p->f & PLF_UP) {
466 return 'X';
467 } else if (p->f & PLF_DOWN) {
468 return 'Z';
469 } else {
470 return 'E';
474 static int wpnspr (player_t *p) {
475 if (p->f & PLF_UP) {
476 return 'C';
477 } else if(p->f & PLF_DOWN) {
478 return 'E';
479 } else {
480 return 'A';
484 static void PL_draw (player_t *p) {
485 enum {STAND, GO, DIE, SLOP, DEAD, MESS, OUT, FALL}; // copypasted from player.c!
486 static int wytab[] = {-1, -2, -1, 0};
487 int s = 'A';
488 int w = 0;
489 int wx = 0;
490 int wy = 0;
491 switch (p->st) {
492 case STAND:
493 if (p->f & PLF_FIRE) {
494 s = standspr(p) + 1;
495 w = wpnspr(p) + 1;
496 } else if (p->pain) {
497 s = 'G';
498 w = 'A';
499 wx = p->d ? 2 : -2;
500 wy = 1;
501 } else {
502 s = standspr(p);
503 w = wpnspr(p);
505 break;
506 case DEAD:
507 s = 'N';
508 break;
509 case MESS:
510 s = 'W';
511 break;
512 case GO:
513 if (p->pain) {
514 s = 'G';
515 w = 'A';
516 wx = p->d ? 2 : -2;
517 wy = 1;
518 } else {
519 s = plr_goanim[p->s / 8];
520 w = (p->f & PLF_FIRE) ? 'B' : 'A';
521 wx = p->d ? 2 : -2;
522 wy = 1 + wytab[s - 'A'];
524 break;
525 case DIE:
526 s = plr_dieanim[p->s];
527 break;
528 case SLOP:
529 s = plr_slopanim[p->s];
530 break;
531 case OUT:
532 s = 0;
533 break;
535 if (p->wpn == 0) {
536 w = 0;
538 if (w) {
539 Z_drawspr(p->o.x + wx, p->o.y + wy, plr_wpn[p->wpn][w - 'A'], p->d);
541 if (s) {
542 Z_drawmanspr(p->o.x, p->o.y, plr_spr[(s - 'A') * 2 + p->d], plr_sprd[(s - 'A') * 2 + p->d], p->color);
546 static void PL_drawst (player_t *p) {
547 int i;
548 V_setrect(WD, 120, w_o, HT);
549 Z_clrst();
550 if (p->drawst & PL_DRAWAIR) {
551 if (p->air < PL_AIR) {
552 Z_drawstair(p->air);
555 if (p->drawst & PL_DRAWLIFE) {
556 Z_drawstprcnt(0, p->life);
558 if (p->drawst & PL_DRAWARMOR) {
559 Z_drawstprcnt(1, p->armor);
561 if (p->drawst & PL_DRAWWPN) {
562 switch(p->wpn) {
563 case 2:
564 case 5:
565 i = p->ammo;
566 break;
567 case 3:
568 case 4:
569 case 9:
570 i = p->shel;
571 break;
572 case 6:
573 i = p->rock;
574 break;
575 case 10:
576 i = p->fuel;
577 break;
578 case 7:
579 case 8:
580 i = p->cell;
581 break;
583 Z_drawstwpn(p->wpn, i);
585 if (p->drawst & PL_DRAWFRAG) {
586 Z_drawstnum(p->frag);
588 if (p->drawst & PL_DRAWKEYS) {
589 Z_drawstkeys(p->keys);
591 if (!_2pl) {
592 if (p->drawst & PL_DRAWLIVES) {
593 Z_drawstlives(p->lives);
598 /* --- monster --- */
600 #define MANCOLOR 0xD0
602 static void MN_draw (void) {
603 enum {SLEEP, GO, RUN, CLIMB, DIE, DEAD, ATTACK, SHOOT, PAIN, WAIT, REVIVE, RUNOUT}; // copypasted from monster.c!
604 int i;
605 for (i = 0; i < MAXMN; ++i) {
606 if (mn[i].t) {
607 if (mn[i].t >= MN_PL_DEAD) {
608 Z_drawmanspr(mn[i].o.x, mn[i].o.y, pl_spr[mn[i].t - MN_PL_DEAD], 0, mn[i].d);
609 continue;
611 if ((mn[i].t != MN_SOUL && mn[i].t != MN_PAIN) || mn[i].st != DEAD) {
612 if (mn[i].t != MN_MAN) {
613 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]);
614 } else {
615 if (mn[i].ap[mn[i].ac] == 'E' || mn[i].ap[mn[i].ac] == 'F') {
616 Z_drawspr(mn[i].o.x, mn[i].o.y, mn_sgun[mn[i].ap[mn[i].ac] - 'E'], mn[i].d);
618 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);
621 if (mn[i].t == MN_VILE && mn[i].st == SHOOT) {
622 Z_drawspr(mn[i].tx, mn[i].ty, mn_fspr[mn[i].ac / 3], 0);
628 /* --- weapon --- */
630 static void WP_draw (void) {
631 enum {NONE, ROCKET, PLASMA, APLASMA, BALL1, BALL2, BALL7, BFGBALL, BFGHIT, MANF, REVF, FIRE}; // copypasted from weapons.c!
632 int i, s, d, x, y;
633 for (i = 0; i < MAXWPN; ++i) {
634 s = -1;
635 d = 0;
636 switch (wp[i].t) {
637 case NONE:
638 default:
639 break;
640 case REVF:
641 case ROCKET:
642 d = wp[i].s;
643 if (d < 2) {
644 d = wp[i].o.xv > 0 ? 1 : 0;
645 x = abs(wp[i].o.xv);
646 y = wp[i].o.yv;
647 s = 0;
648 if (y < 0) {
649 if (-y >= x) {
650 s = 30;
652 } else if (y > 0) {
653 if (y >= x / 2) {
654 s = 31;
657 } else {
658 s = (d - 2) / 2 + 1;
659 d = 0;
661 break;
662 case MANF:
663 s=wp[i].s;
664 if (s >= 2) {
665 s /= 2;
666 break;
668 case PLASMA:
669 case APLASMA:
670 case BALL1:
671 case BALL7:
672 case BALL2:
673 s = wp[i].s;
674 if (s >= 2) {
675 s = s / 2 + 1;
677 switch (wp[i].t) {
678 case PLASMA:
679 s += 4;
680 break;
681 case APLASMA:
682 s += 11;
683 break;
684 case BALL1:
685 s += 32;
686 break;
687 case BALL2:
688 s += 42;
689 break;
690 case BALL7:
691 s += 37;
692 d = wp[i].o.xv >= 0 ? 1 : 0;
693 break;
694 case MANF:
695 s += 47;
696 d=(wp[i].o.xv>=0)?1:0;break;
698 break;
699 case BFGBALL:
700 s = wp[i].s;
701 if (s >= 2) {
702 s = s / 2 + 1;
704 s += 18;
705 break;
706 case BFGHIT:
707 s = wp[i].s / 2 + 26;
708 break;
710 if (s >= 0) {
711 Z_drawspr(wp[i].o.x, wp[i].o.y, wp_spr[s * 2 + d], wp_sprd[s * 2 + d]);
716 /* --- smoke --- */
718 static void SMK_draw (void) {
719 int i, s;
720 for (i = 0; i < MAXSMOK; ++i) {
721 if (sm[i].t) {
722 switch (sm[i].s) {
723 case 0:
724 s = sm[i].t;
725 if (s >= (SMSN - 1) * 3) {
726 s = 0;
727 } else {
728 s = SMSN - 1 - s / 3;
730 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);
731 break;
732 case 1:
733 s = sm[i].t;
734 if (s >= FLSN - 1) {
735 s = 0;
736 } else {
737 s = FLSN - 1 - s;
739 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);
740 break;
746 /* --- fx --- */
748 static void FX_draw (void) {
749 enum {NONE, TFOG, IFOG, BUBL}; // copypasted from fx.c
750 int i, s;
751 for (i = 0; i < MAXFX; ++i) {
752 s = -1;
753 switch (fx[i].t) {
754 case TFOG:
755 s = fx[i].s / 2;
756 break;
757 case IFOG:
758 s = fx[i].s / 2 + 10;
759 break;
760 case BUBL:
761 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);
762 continue;
764 if (s >= 0) {
765 Z_drawspr(fx[i].x, fx[i].y, fx_spr[s], fx_sprd[s]);
770 /* --- view --- */
772 static void W_adjust (void) {
773 int MAXX = FLDW * CELW - WD / 2;
774 int MAXY = FLDH * CELH - HT / 2;
775 if (w_x < WD / 2) w_x = WD / 2;
776 if (w_y < HT / 2) w_y = HT / 2;
777 if (w_x > MAXX) w_x = MAXX;
778 if (w_y > MAXY) w_y = MAXY;
781 static void W_draw(void) {
782 W_adjust();
783 V_setrect(0, WD, w_o + 1, HT);
784 if (w_horiz) {
785 vgaimg *img = (vgaimg*)horiz;
786 int x = 0;
787 int d = 0;
788 do {
789 int y = w_o;
790 d &= ~2;
791 do {
792 V_rotspr(x, y, img, d);
793 y += img->h;
794 d ^= 2;
795 } while (y < HT + w_o);
796 x += img->w;
797 d ^= 1;
798 } while (x < WD);
799 if (sky_type == 2) {
800 if (lt_time < 0) {
801 if (!lt_side) {
802 V_spr(0, w_o + lt_ypos, ltn[lt_type][lt_time < -5 ? 0 : 1]);
803 } else {
804 V_spr2(WD - 1, w_o + lt_ypos, ltn[lt_type][lt_time < -5 ? 0 : 1]);
808 } else {
809 V_clr(0, WD, w_o + 1, HT, 0x97);
811 Z_drawfld((byte*)fldb, 1);
812 DOT_draw();
813 IT_draw();
814 PL_draw(&pl1);
815 if (_2pl) {
816 PL_draw(&pl2);
818 MN_draw();
819 WP_draw();
820 SMK_draw();
821 FX_draw();
822 Z_drawfld((byte*)fldf, 0);
823 if (sky_type == 2) {
824 if (lt_time == -4 || lt_time == -2) {
825 V_remap_rect(0, WD, w_o + 1, HT, clrmap + 256 * 11);
830 /* --- game --- */
832 #define PL_FLASH 90
834 static void drawview (player_t *p) {
835 if (p->looky < -SCRH / 4) {
836 p->looky = -SCRH / 4;
837 } else if (p->looky > SCRH / 4) {
838 p->looky = SCRH / 4;
840 w_x = p->o.x;
841 w_y = p->o.y - 12 + p->looky;
842 W_draw();
843 PL_drawst(p);
846 static int get_pu_st (int t) {
847 if (t >= PL_FLASH) {
848 return 1;
849 } else if((t / 9) & 1) {
850 return 0;
851 } else {
852 return 1;
856 static void pl_info (player_t *p, int y) {
857 dword t = p->kills * 10920 / g_time;
858 Z_gotoxy(25, y); Z_printbf("KILLS");
859 Z_gotoxy(25, y + 15); Z_printbf("KPM");
860 Z_gotoxy(25, y + 30); Z_printbf("SECRETS %u / %u", p->secrets, sw_secrets);
861 Z_gotoxy(255, y); Z_printbf("%u", p->kills);
862 Z_gotoxy(255, y + 15); Z_printbf("%u.%u", t / 10, t % 10);
865 static void W_act (void) {
866 int i, a;
867 if (g_time % 3 == 0) {
868 for (i = 1; i < 256; ++i) {
869 a = walani[i];
870 if (a != 0) {
871 anic[a]++;
872 if (anih[a][anic[a]] == -1) {
873 anic[a] = 0;
875 walp[i] = V_getvgaimg(anih[a][anic[a]]);
881 void R_draw (void) {
882 int h;
883 word hr, mn, sc;
884 W_act();
885 if (g_trans && !transdraw) {
886 return;
888 switch (g_st) {
889 case GS_ENDANIM:
890 case GS_END2ANIM:
891 case GS_DARKEN:
892 case GS_BVIDEO:
893 case GS_EVIDEO:
894 case GS_END3ANIM:
895 return;
896 case GS_TITLE:
897 V_center(1);
898 V_pic(0, 0, scrnh[0]);
899 V_center(0);
900 break;
901 case GS_ENDSCR:
902 V_center(1);
903 V_clr(0, SCRW, 0, SCRH, 0);
904 V_pic(0, 0, scrnh[2]);
905 V_center(0);
906 break;
907 case GS_INTER:
908 V_center(1);
909 V_clr(0, SCRW, 0, SCRH, 0);
910 V_pic(0, 0, scrnh[1]);
911 Z_gotoxy(60, 20);
912 Z_printbf("LEVEL COMPLETE");
913 Z_calc_time(g_time, &hr, &mn, &sc);
914 Z_gotoxy(115, 40);
915 Z_printbf("TIME %u:%02u:%02u", hr, mn, sc);
916 h = 60;
917 if (_2pl) {
918 Z_gotoxy(80, h);
919 Z_printbf("PLAYER ONE");
920 Z_gotoxy(80, h + 70);
921 Z_printbf("PLAYER TWO");
922 h += SCRH / 10;
924 pl_info(&pl1, h);
925 if (_2pl) {
926 pl_info(&pl2, h + 70);
928 V_center(0);
929 break;
931 V_center(1);
932 if (g_st != GS_GAME) {
933 if (g_trans) {
934 return;
936 GM_draw();
937 V_copytoscr(0, SCRW, 0, SCRH);
938 return;
940 V_center(0);
941 if (_2pl) {
942 w_o = 0;
943 WD = SCRW - 120;
944 HT = SCRH / 2 - 2;
945 drawview(&pl1);
946 w_o = SCRH / 2;
947 WD = SCRW - 120;
948 HT = SCRH / 2 - 2;
949 drawview(&pl2);
950 } else{
951 w_o = 0;
952 WD = SCRW - 120;
953 HT = SCRH - 2;
954 drawview(&pl1);
956 if (g_trans) {
957 return;
959 V_center(1);
960 if (GM_draw()) {
961 pl1.drawst = 0xFF;
962 pl2.drawst = 0xFF;
963 V_copytoscr(0,SCRW,0,SCRH);
964 return;
966 V_center(0);
967 if (pl1.invl) {
968 h = get_pu_st(pl1.invl) * 6;
969 } else if (pl1.pain < 15) {
970 h = 0;
971 } else if (pl1.pain < 35) {
972 h = 1;
973 } else if (pl1.pain < 55) {
974 h = 2;
975 } else if (pl1.pain < 75) {
976 h=3;
977 } else if (pl1.pain < 95) {
978 h=4;
979 } else {
980 h = 5;
982 if (h != 0) {
983 V_maptoscr(0, SCRW - 120, 1, _2pl ? SCRH / 2 - 2 : SCRH - 2, clrmap + h * 256);
984 } else {
985 V_copytoscr(0, SCRW - 120, 1, _2pl ? SCRH / 2 - 2 : SCRH - 2);
987 if (pl1.drawst) {
988 V_copytoscr(SCRW - 120, 120, 0, _2pl ? SCRH / 2 : SCRH);
990 pl1.drawst = 0xFF;
991 if (_2pl) {
992 if (pl2.invl) {
993 h = get_pu_st(pl2.invl) * 6;
994 } else if (pl2.pain < 15) {
995 h = 0;
996 } else if (pl2.pain < 35) {
997 h = 1;
998 } else if (pl2.pain < 55) {
999 h = 2;
1000 } else if (pl2.pain < 75) {
1001 h = 3;
1002 } else if (pl2.pain < 95) {
1003 h = 4;
1004 } else {
1005 h = 5;
1007 if (h) {
1008 V_maptoscr(0, SCRW - 120, SCRH / 2 + 1, SCRH / 2 - 2, clrmap + h * 256);
1009 } else {
1010 V_copytoscr(0, SCRW - 120, SCRH / 2 + 1, SCRH / 2 - 2);
1012 if (pl2.drawst) {
1013 V_copytoscr(SCRW - 120, 120, SCRH / 2, SCRH / 2);
1015 pl2.drawst = 0xFF;
1019 void R_alloc (void) {
1020 int i, j, n;
1021 char s[10];
1022 logo("R_alloc: загрузка графики\n");
1023 // game
1024 scrnh[0] = V_loadvgaimg("TITLEPIC");
1025 scrnh[1] = V_loadvgaimg("INTERPIC");
1026 scrnh[2] = V_loadvgaimg("ENDPIC");
1027 cd_scr = M_lock(F_getresid("CD1PIC"));
1028 for (i = 0; i < 2; ++i) {
1029 sprintf(s, "LTN%c", i + '1');
1030 for (j = 0; j < 2; ++j) {
1031 ltn[i][j] = Z_getspr(s, j, 0, NULL);
1034 // smoke
1035 for (i = 0; i < SMSN; ++i) {
1036 smk_spr[i] = Z_getspr("SMOK", i, 0, NULL);
1038 for (i = 0; i < FLSN; ++i) {
1039 smk_fspr[i] = Z_getspr("FLAM", i, 0, NULL);
1041 // fx
1042 for (i = 0; i < 10; ++i) {
1043 fx_spr[i] = Z_getspr("TFOG", i, 0, fx_sprd + i);
1045 for (; i < 15; ++i) {
1046 fx_spr[i] = Z_getspr("IFOG", i - 10, 0, fx_sprd + i);
1048 // weapons
1049 for (i = 0; i < 4; ++i) {
1050 wp_spr[i * 2] = Z_getspr("MISL", i, 1, wp_sprd + i * 2);
1051 wp_spr[i * 2 + 1] = Z_getspr("MISL", i, 2, wp_sprd + i * 2 + 1);
1053 for (; i < 6; ++i) {
1054 wp_spr[i * 2] = Z_getspr("PLSS", i - 4, 1, wp_sprd + i * 2);
1055 wp_spr[i * 2 + 1] = Z_getspr("PLSS", i - 4, 2, wp_sprd + i * 2 + 1);
1057 for (; i < 11; ++i) {
1058 wp_spr[i * 2] = Z_getspr("PLSE", i - 6, 1, wp_sprd + i * 2);
1059 wp_spr[i * 2 + 1] = Z_getspr("PLSE", i - 6, 2, wp_sprd + i * 2 + 1);
1061 for (; i < 13; ++i) {
1062 wp_spr[i * 2] = Z_getspr("APLS", i - 11, 1, wp_sprd + i * 2);
1063 wp_spr[i * 2 + 1] = Z_getspr("APLS", i - 11, 2, wp_sprd + i * 2 + 1);
1065 for (; i < 18; ++i) {
1066 wp_spr[i * 2] = Z_getspr("APBX", i - 13, 1, wp_sprd + i * 2);
1067 wp_spr[i * 2 + 1] = Z_getspr("APBX", i - 13, 2, wp_sprd + i * 2 + 1);
1069 for(; i < 20; ++i) {
1070 wp_spr[i * 2] = Z_getspr("BFS1", i - 18, 1, wp_sprd + i * 2);
1071 wp_spr[i * 2 + 1] = Z_getspr("BFS1", i - 18, 2, wp_sprd + i * 2 + 1);
1073 for (; i < 26; ++i) {
1074 wp_spr[i * 2] = Z_getspr("BFE1", i - 20, 1, wp_sprd + i * 2);
1075 wp_spr[i * 2 + 1] = Z_getspr("BFE1", i - 20, 2, wp_sprd + i * 2 + 1);
1077 for (; i < 30; ++i) {
1078 wp_spr[i * 2] = Z_getspr("BFE2", i - 26, 1, wp_sprd + i * 2);
1079 wp_spr[i * 2 + 1] = Z_getspr("BFE2", i - 26, 2, wp_sprd + i * 2 + 1);
1081 for (; i < 32; ++i) {
1082 wp_spr[i * 2] = Z_getspr("MISL", i - 30 + 4, 1, wp_sprd + i * 2);
1083 wp_spr[i * 2 + 1] = Z_getspr("MISL", i - 30 + 4, 2, wp_sprd + i * 2 + 1);
1085 for (; i < 37; ++i) {
1086 wp_spr[i * 2] = Z_getspr("BAL1", i - 32, 1, wp_sprd + i * 2);
1087 wp_spr[i * 2 + 1] = Z_getspr("BAL1", i - 32, 2, wp_sprd + i * 2 + 1);
1089 for (; i < 42; ++i) {
1090 wp_spr[i * 2] = Z_getspr("BAL7", i - 37, 1, wp_sprd + i * 2);
1091 wp_spr[i * 2 + 1] = Z_getspr("BAL7", i - 37, 2, wp_sprd + i * 2 + 1);
1093 for (; i < 47; ++i) {
1094 wp_spr[i * 2] = Z_getspr("BAL2", i - 42, 1, wp_sprd + i * 2);
1095 wp_spr[i * 2 + 1] = Z_getspr("BAL2", i - 42, 2, wp_sprd + i * 2 + 1);
1097 for (; i < 49; ++i) {
1098 wp_spr[i * 2] = Z_getspr("MANF", i - 47, 1, wp_sprd + i * 2);
1099 wp_spr[i * 2 + 1] = Z_getspr("MANF", i - 47, 2, wp_sprd + i * 2 + 1);
1101 // items
1102 static char snm[18][4] = {
1103 "CLIP", "SHEL", "ROCK", "CELL", "AMMO", "SBOX", "BROK", "CELP",
1104 "STIM", "MEDI", "BPAK",
1105 "CSAW", "SHOT", "SGN2", "MGUN", "LAUN", "PLAS", "BFUG"
1106 };
1107 static char n4[4][4] = {
1108 "SOUL", "SMRT", "SMGT", "SMBT"
1109 };
1110 static char n3[2][4] = {
1111 "GOR1", "FCAN"
1112 };
1113 for (i = 0; i < 18; ++i) {
1114 item_spr[i] = Z_getspr(snm[i], 0, 0, item_sprd + i);
1116 for (; i < 20; ++i) {
1117 item_spr[i] = Z_getspr("ARM1", i - 18, 0, item_sprd + i);
1118 item_spr[i + 2] = Z_getspr("ARM2", i - 18, 0, item_sprd + i);
1120 i+=2;
1121 for (; i < 26; ++i) {
1122 item_spr[i] = Z_getspr("MEGA", i - 22, 0, item_sprd + i);
1124 for (; i < 30; ++i) {
1125 item_spr[i] = Z_getspr("PINV", i - 26, 0, item_sprd + i);
1127 item_spr[30] = Z_getspr("AQUA", 0, 0, item_sprd + 30);
1128 item_spr[31] = Z_getspr("KEYR", 0, 0, item_sprd + 31);
1129 item_spr[32] = Z_getspr("KEYG", 0, 0, item_sprd + 32);
1130 item_spr[33] = Z_getspr("KEYB", 0, 0, item_sprd + 33);
1131 item_spr[34] = Z_getspr("SUIT", 0, 0, item_sprd + 34);
1132 for (n = 35, j = 0; j < 4; ++j) {
1133 for (i = 0; i < 4; ++i, ++n) {
1134 item_spr[n] = Z_getspr(n4[j], i, 0, item_sprd + n);
1137 for (j = 0; j < 2; ++j) {
1138 for (i = 0; i < 3; ++i, ++n) {
1139 item_spr[n] = Z_getspr(n3[j], i, 0, item_sprd + n);
1142 item_spr[57] = Z_getspr("GUN2", 0, 0, item_sprd + 57);
1143 // player
1144 for (i = 0; i < 27; ++i) {
1145 plr_spr[i * 2] = Z_getspr("PLAY", i, 1, plr_sprd + i * 2);
1146 plr_spr[i * 2 + 1] = Z_getspr("PLAY", i, 2, plr_sprd + i * 2 + 1);
1148 strncpy(s, "PWPx", 4);
1149 for (i = 1; i < 11; ++i) {
1150 s[3] = (i < 10 ? '0' : 'A' - 10) + i;
1151 for (j = 0; j < 6; ++j) {
1152 plr_wpn[i][j] = Z_getspr(s, j, 1, NULL);
1155 // monsters
1156 static char msn[MN_TN][4] = {
1157 "SARG", "TROO", "POSS", "SPOS", "CYBR", "CPOS", "BOSS", "BOS2", "HEAD", "SKUL",
1158 "PAIN", "SPID", "BSPI", "FATT", "SKEL", "VILE", "FISH", "BAR1", "ROBO", "PLAY"
1159 };
1160 static int mms[MN_TN] = {
1161 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,
1162 20*2, 17*2, 29*2, 6*2, 2*2, 17*2, 23*2
1163 };
1164 mn_sgun[0] = Z_getspr("PWP4", 0, 1, NULL);
1165 mn_sgun[1] = Z_getspr("PWP4", 1, 1, NULL);
1166 for (j = 0; j < MN_TN; ++j) {
1167 for (i = 0; i < mms[j]; ++i) {
1168 mn_spr[j][i] = Z_getspr(msn[j], i / 2, (i & 1) + 1, &mn_sprd[j][i]);
1170 if (j == MN_BARREL - 1) {
1171 for (i = 4; i < 14; ++i) {
1172 mn_spr[j][i] = Z_getspr("BEXP", i / 2 - 2, (i & 1) + 1, &mn_sprd[j][i]);
1176 for (i = 0; i < 8; ++i) {
1177 mn_fspr[i] = Z_getspr("FIRE", i, 0, NULL);
1179 pl_spr[0] = Z_getspr("PLAY", 'N' - 'A', 0, NULL);
1180 pl_spr[1] = Z_getspr("PLAY", 'W' - 'A', 0, NULL);
1181 // misc
1182 static char mnm[22][8]={
1183 "STTNUM0","STTNUM1","STTNUM2","STTNUM3","STTNUM4",
1184 "STTNUM5","STTNUM6","STTNUM7","STTNUM8","STTNUM9",
1185 "STTMINUS","STTPRCNT",
1186 "FISTA0","CSAWA0","PISTA0","SHOTA0","SGN2A0","MGUNA0","LAUNA0",
1187 "PLASA0","BFUGA0","GUN2A0"
1188 };
1189 stone=V_loadvgaimg("STONE");
1190 stone2=V_loadvgaimg("STONE2");
1191 keys[0]=V_loadvgaimg("KEYRA0");
1192 keys[1]=V_loadvgaimg("KEYGA0");
1193 keys[2]=V_loadvgaimg("KEYBA0");
1194 for (i = 0; i < 22; ++i) {
1195 sth[i] = V_loadvgaimg(mnm[i]);
1197 strcpy(s, "STBF_*");
1198 for (i = '!'; i < 160; ++i) {
1199 s[5] = i;
1200 bfh[i - '!'] = V_getvgaimg(F_findres(s));
1202 for (i = '!'; i < 160; ++i) {
1203 sprintf(s, "STCFN%03d", i);
1204 sfh[i - '!'] = V_getvgaimg(F_findres(s));
1206 strcpy(s, "WINUM*");
1207 for (i = '0'; i <= '9'; ++i) {
1208 s[5] = i;
1209 bfh[i - '!'] = V_loadvgaimg(s);
1211 bfh[':' - '!'] = V_loadvgaimg("WICOLON");
1212 // menu
1213 msklh[0] = V_loadvgaimg("M_SKULL1");
1214 msklh[1] = V_loadvgaimg("M_SKULL2");
1215 mbarl = V_loadvgaimg("M_THERML");
1216 mbarm = V_loadvgaimg("M_THERMM");
1217 mbarr = V_loadvgaimg("M_THERMR");
1218 mbaro = V_loadvgaimg("M_THERMO");
1219 mslotl = V_loadvgaimg("M_LSLEFT");
1220 mslotm = V_loadvgaimg("M_LSCNTR");
1221 mslotr = V_loadvgaimg("M_LSRGHT");
1222 // walls
1223 static char *anm[ANIT - 1][5] = {
1224 {"WALL22_1", "WALL23_1", "WALL23_2", NULL, NULL},
1225 {"WALL58_1", "WALL58_2", "WALL58_3", NULL, NULL},
1226 {"W73A_1", "W73A_2", NULL, NULL, NULL},
1227 {"RP2_1", "RP2_2", "RP2_3", "RP2_4", NULL}
1228 };
1229 for (i = 1; i < ANIT; i++) {
1230 for (j = 0; anm[i - 1][j]; j++) {
1231 anih[i][j] = F_getresid(anm[i - 1][j]);
1233 for(; j < 5; j++) {
1234 anih[i][j] = -1;
1239 void R_get_name (int n, char s[8]) {
1240 if (walh[n] == -1) {
1241 memset(s, 0, 8);
1242 } else if (walh[n] == -2) {
1243 memcpy(s, "_WATER_", 8);
1244 s[7] = (char)((intptr_t)walp[n] - 1 + '0');
1245 } else {
1246 F_getresname(s, walh[n] & 0x7FFF);
1250 static short getani (char n[8]) {
1251 if (strncasecmp(n, "WALL22_1", 8) == 0) {
1252 return 1;
1253 } else if (strncasecmp(n, "WALL58_1", 8) == 0) {
1254 return 2;
1255 } else if (strncasecmp(n, "W73A_1", 8) == 0) {
1256 return 3;
1257 } else if (strncasecmp(n, "RP2_1", 8) == 0) {
1258 return 4;
1259 } else {
1260 return 0;
1264 int R_get_special_id (int n) {
1265 assert(n >= 0 && n < 256);
1266 intptr_t x = (intptr_t)walp[n] - 1;
1267 return x > 0 && x <= 3 ? x : 0;
1270 void R_begin_load (void) {
1271 int i;
1272 for (i = 0; i < max_textures; i++) {
1273 // if (walp[i] != NULL && walh[i] >= 0) {
1274 // M_unlock(walp[i]);
1275 // }
1276 walh[i] = -1;
1277 walp[i] = NULL;
1278 walswp[i] = i;
1279 walani[i] = 0;
1281 memset(anic, 0, sizeof(anic));
1282 max_textures = 0;
1285 void R_load (char s[8], int f) {
1286 assert(max_textures < 256);
1287 if (!s[0]) {
1288 walh[max_textures] = -1;
1289 walp[max_textures] = NULL;
1290 } else {
1291 if (strncasecmp(s, "_WATER_", 7) == 0) {
1292 walh[max_textures] = -2;
1293 walp[max_textures] = (void*)((intptr_t)s[7] - '0' + 1);
1294 } else {
1295 walh[max_textures] = F_getresid(s);
1296 walp[max_textures] = V_getvgaimg(walh[max_textures]);
1297 if (f) {
1298 walh[max_textures] |= 0x8000;
1300 if (s[0] == 'S' && s[1] == 'W' && s[4] == '_') {
1301 walswp[max_textures] = 0;
1304 walani[max_textures] = getani(s);
1306 max_textures++;
1309 void R_end_load (void) {
1310 int i, j, k, g;
1311 char s[8];
1312 j = max_textures;
1313 for (i = 1; i < 256 && j < 256; i++) {
1314 if (walswp[i] == 0) {
1315 R_get_name(i, s);
1316 s[5] ^= 1;
1317 g = F_getresid(s) | (walh[i] & 0x8000);
1318 k = 1;
1319 while (k < 256 && walh[k] != g) {
1320 k += 1;
1322 if (k >= 256) {
1323 k = j;
1324 j += 1;
1325 walh[k] = g;
1326 walp[k] = V_getvgaimg(g);
1327 walf[k] = g & 0x8000 ? 1 : 0;
1329 walswp[i] = k;
1330 walswp[k] = i;
1335 void R_loadsky (int sky) {
1336 char s[6];
1337 strcpy(s, "RSKY1");
1338 s[4] = '0' + sky;
1339 M_unlock(horiz);
1340 horiz = V_loadvgaimg(s);
1343 void R_setgamma(int g) {
1344 int t;
1345 g = g < 0 ? 0 : (g > 4 ? 4 : g);
1346 gammaa = g;
1347 for (t = 0; t < 256; ++t) {
1348 std_pal[t][0]=gamcor[gammaa][main_pal[t][0]];
1349 std_pal[t][1]=gamcor[gammaa][main_pal[t][1]];
1350 std_pal[t][2]=gamcor[gammaa][main_pal[t][2]];
1352 VP_setall(std_pal);
1355 int R_getgamma (void) {
1356 return gammaa;
1359 void R_toggle_fullscreen (void) {
1360 fullscreen = !fullscreen;
1361 V_toggle();
1364 void R_init () {
1365 int i;
1366 F_loadres(F_getresid("PLAYPAL"), main_pal, 0, 768);
1367 for (i = 0; i < 256; ++i) {
1368 bright[i] = ((int) main_pal[i][0] + main_pal[i][1] + main_pal[i][2]) * 8 / (63 * 3);
1370 F_loadres(F_getresid("MIXMAP"), mixmap, 0, 0x10000);
1371 F_loadres(F_getresid("COLORMAP"), clrmap, 0, 256*12);
1372 logo("V_init: настройка видео\n");
1373 if (V_init() != 0) {
1374 ERR_failinit("Не могу установить видеорежим VGA");
1376 //R_setgamma(gammaa);
1377 V_setrect(0, SCRW, 0, SCRH);
1378 V_setscr(scrbuf);
1379 V_clr(0, SCRW, 0, SCRH, 0);
1380 R_alloc();
1383 void R_done (void) {
1384 V_done();