DEADSOFTWARE

254b87eb6b8e4f907778af90bcd372781adfc4bb
[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) {
308 //intptr_t spc = (intptr_t) walp[id];
309 int spc = R_get_special_id(id);
310 if (spc >= 0 && spc <= 3) {
311 if (!bg) {
312 byte *cmap = clrmap + (spc + 7) * 256;
313 V_remap_rect(sx, sy, CELW, CELH, cmap);
315 } else {
316 V_pic(sx, sy, walp[id]);
319 p++;
324 /* --- menu --- */
326 static int gm_tm = 0; // ???
328 static vgaimg *PL_getspr (int s, int d) {
329 return plr_spr[(s - 'A') * 2 + d];
332 static int GM_draw (void) {
333 enum {MENU, MSG}; // copypasted from menu.c!
334 enum {
335 CANCEL, NEWGAME, LOADGAME, SAVEGAME, OPTIONS, QUITGAME, QUIT, ENDGAME, ENDGM,
336 PLR1, PLR2, COOP, DM, VOLUME, GAMMA, LOAD, SAVE, PLCOLOR, PLCEND, MUSIC, INTERP,
337 SVOLM, SVOLP, MVOLM, MVOLP, GAMMAM, GAMMAP, PL1CM, PL1CP, PL2CM, PL2CP
338 }; // copypasted from menu.c!
339 int i, j, k, y;
340 ++gm_tm;
341 V_setrect(0, SCRW, 0, SCRH);
342 if (!mnu && !gm_redraw) {
343 return 0;
345 gm_redraw = 0;
346 if (!mnu) {
347 return 1;
349 if (mnu->type == MENU) {
350 y = (200 - mnu -> n * 16 - 20) / 2;
351 Z_gotoxy(mnu->x, y - 10); Z_printbf(mnu->ttl);
352 for (i = 0; i < mnu->n; ++i) {
353 if (mnu->t[i] == LOAD || mnu->t[i] == SAVE) {
354 j = y + i * 16 + 29;
355 V_spr(mnu->x, j, mslotl);
356 for (k = 8; k < 184; k += 8) {
357 V_spr(mnu->x + k, j, mslotm);
359 V_spr(mnu->x+184,j,mslotr);
360 Z_gotoxy(mnu->x+4,j-8);
361 if (input && i == save_mnu.cur) {
362 Z_printsf("%s_", ibuf);
363 } else {
364 Z_printsf("%s", savname[i]);
366 } else {
367 Z_gotoxy(mnu->x + (mnu->t[i] >= SVOLM ? (mnu->t[i] >= PL1CM ? 50 : 152) : 0), y + i * 16 + 20);
368 Z_printbf(mnu->m[i]);
370 if (mnu->t[i] == MUSIC) {
371 Z_printbf(" '%.8s'",g_music);
372 } else if(mnu->t[i] == INTERP) {
373 Z_printbf("%s", fullscreen ? "ON" : "OFF");
374 } else if(mnu->t[i] >= PL1CM) {
375 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]);
376 } else if(mnu->t[i] >= SVOLM) {
377 j = y + i * 16 + 20;
378 V_spr(mnu->x, j, mbarl);
379 for (k = 8; k < 144; k += 8) {
380 V_spr(mnu->x + k, j, mbarm);
382 V_spr(mnu->x + 144, j, mbarr);
383 switch(mnu->t[i]) {
384 case SVOLM: k = snd_vol; break;
385 case MVOLM: k = mus_vol; break;
386 case GAMMAM: k = gammaa << 5; break;
388 V_spr(mnu->x + 8 + k, j, mbaro);
391 V_spr(mnu->x - 25, y + mnu->cur * 16 + 20 - 8, msklh[(gm_tm / 6) & 1]);
392 } else {
393 Z_gotoxy((320 - strlen(mnu->ttl) * 7) / 2, 90); Z_printsf(mnu->ttl);
394 Z_gotoxy(136, 100); Z_printsf("(Y/N)");
396 return 1;
399 /* --- dots --- */
401 static void DOT_draw (void) {
402 int i;
403 for (i = 0; i < MAXDOT; ++i) {
404 if (dot[i].t) {
405 V_dot(dot[i].o.x - w_x + WD / 2, dot[i].o.y - w_y + HT / 2 + 1 + w_o, dot[i].c);
410 /* --- items --- */
412 static void IT_draw (void) {
413 int i, s;
414 for (i = 0; i < MAXITEM; ++i) {
415 s = -1;
416 if (it[i].t && it[i].s >= 0) {
417 switch(it[i].t & 0x7FFF) {
418 case I_ARM1:
419 s = it[i].s / 9 + 18;
420 break;
421 case I_ARM2:
422 s = it[i].s / 9 + 20;
423 break;
424 case I_MEGA:
425 s = it[i].s / 2 + 22;
426 break;
427 case I_INVL:
428 s = it[i].s / 2 + 26;
429 break;
430 case I_SUPER:
431 case I_RTORCH:
432 case I_GTORCH:
433 case I_BTORCH:
434 s = it[i].s / 2 + (it[i].t - I_SUPER) * 4 + 35;
435 break;
436 case I_GOR1: case I_FCAN:
437 s = it[i].s / 2 + (it[i].t - I_GOR1) * 3 + 51;
438 break;
439 case I_AQUA:
440 s = 30;
441 break;
442 case I_SUIT:
443 s = 34;
444 break;
445 case I_KEYR:
446 case I_KEYG:
447 case I_KEYB:
448 s = (it[i].t & 0x7FFF) - I_KEYR + 31;
449 break;
450 case I_GUN2:
451 s = 57;
452 break;
453 default:
454 s = (it[i].t & 0x7FFF) - 1;
457 if (s >= 0) {
458 Z_drawspr(it[i].o.x, it[i].o.y, item_spr[s], item_sprd[s]);
463 /* --- player --- */
465 static int standspr (player_t *p) {
466 if (p->f & PLF_UP) {
467 return 'X';
468 } else if (p->f & PLF_DOWN) {
469 return 'Z';
470 } else {
471 return 'E';
475 static int wpnspr (player_t *p) {
476 if (p->f & PLF_UP) {
477 return 'C';
478 } else if(p->f & PLF_DOWN) {
479 return 'E';
480 } else {
481 return 'A';
485 static void PL_draw (player_t *p) {
486 enum {STAND, GO, DIE, SLOP, DEAD, MESS, OUT, FALL}; // copypasted from player.c!
487 static int wytab[] = {-1, -2, -1, 0};
488 int s = 'A';
489 int w = 0;
490 int wx = 0;
491 int wy = 0;
492 switch (p->st) {
493 case STAND:
494 if (p->f & PLF_FIRE) {
495 s = standspr(p) + 1;
496 w = wpnspr(p) + 1;
497 } else if (p->pain) {
498 s = 'G';
499 w = 'A';
500 wx = p->d ? 2 : -2;
501 wy = 1;
502 } else {
503 s = standspr(p);
504 w = wpnspr(p);
506 break;
507 case DEAD:
508 s = 'N';
509 break;
510 case MESS:
511 s = 'W';
512 break;
513 case GO:
514 if (p->pain) {
515 s = 'G';
516 w = 'A';
517 wx = p->d ? 2 : -2;
518 wy = 1;
519 } else {
520 s = plr_goanim[p->s / 8];
521 w = (p->f & PLF_FIRE) ? 'B' : 'A';
522 wx = p->d ? 2 : -2;
523 wy = 1 + wytab[s - 'A'];
525 break;
526 case DIE:
527 s = plr_dieanim[p->s];
528 break;
529 case SLOP:
530 s = plr_slopanim[p->s];
531 break;
532 case OUT:
533 s = 0;
534 break;
536 if (p->wpn == 0) {
537 w = 0;
539 if (w) {
540 Z_drawspr(p->o.x + wx, p->o.y + wy, plr_wpn[p->wpn][w - 'A'], p->d);
542 if (s) {
543 Z_drawmanspr(p->o.x, p->o.y, plr_spr[(s - 'A') * 2 + p->d], plr_sprd[(s - 'A') * 2 + p->d], p->color);
547 static void PL_drawst (player_t *p) {
548 int i;
549 V_setrect(WD, 120, w_o, HT);
550 Z_clrst();
551 if (p->drawst & PL_DRAWAIR) {
552 if (p->air < PL_AIR) {
553 Z_drawstair(p->air);
556 if (p->drawst & PL_DRAWLIFE) {
557 Z_drawstprcnt(0, p->life);
559 if (p->drawst & PL_DRAWARMOR) {
560 Z_drawstprcnt(1, p->armor);
562 if (p->drawst & PL_DRAWWPN) {
563 switch(p->wpn) {
564 case 2:
565 case 5:
566 i = p->ammo;
567 break;
568 case 3:
569 case 4:
570 case 9:
571 i = p->shel;
572 break;
573 case 6:
574 i = p->rock;
575 break;
576 case 10:
577 i = p->fuel;
578 break;
579 case 7:
580 case 8:
581 i = p->cell;
582 break;
584 Z_drawstwpn(p->wpn, i);
586 if (p->drawst & PL_DRAWFRAG) {
587 Z_drawstnum(p->frag);
589 if (p->drawst & PL_DRAWKEYS) {
590 Z_drawstkeys(p->keys);
592 if (!_2pl) {
593 if (p->drawst & PL_DRAWLIVES) {
594 Z_drawstlives(p->lives);
599 /* --- monster --- */
601 #define MANCOLOR 0xD0
603 static void MN_draw (void) {
604 enum {SLEEP, GO, RUN, CLIMB, DIE, DEAD, ATTACK, SHOOT, PAIN, WAIT, REVIVE, RUNOUT}; // copypasted from monster.c!
605 int i;
606 for (i = 0; i < MAXMN; ++i) {
607 if (mn[i].t) {
608 if (mn[i].t >= MN_PL_DEAD) {
609 Z_drawmanspr(mn[i].o.x, mn[i].o.y, pl_spr[mn[i].t - MN_PL_DEAD], 0, mn[i].d);
610 continue;
612 if ((mn[i].t != MN_SOUL && mn[i].t != MN_PAIN) || mn[i].st != DEAD) {
613 if (mn[i].t != MN_MAN) {
614 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]);
615 } else {
616 if (mn[i].ap[mn[i].ac] == 'E' || mn[i].ap[mn[i].ac] == 'F') {
617 Z_drawspr(mn[i].o.x, mn[i].o.y, mn_sgun[mn[i].ap[mn[i].ac] - 'E'], mn[i].d);
619 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);
622 if (mn[i].t == MN_VILE && mn[i].st == SHOOT) {
623 Z_drawspr(mn[i].tx, mn[i].ty, mn_fspr[mn[i].ac / 3], 0);
629 /* --- weapon --- */
631 static void WP_draw (void) {
632 enum {NONE, ROCKET, PLASMA, APLASMA, BALL1, BALL2, BALL7, BFGBALL, BFGHIT, MANF, REVF, FIRE}; // copypasted from weapons.c!
633 int i, s, d, x, y;
634 for (i = 0; i < MAXWPN; ++i) {
635 s = -1;
636 d = 0;
637 switch (wp[i].t) {
638 case NONE:
639 default:
640 break;
641 case REVF:
642 case ROCKET:
643 d = wp[i].s;
644 if (d < 2) {
645 d = wp[i].o.xv > 0 ? 1 : 0;
646 x = abs(wp[i].o.xv);
647 y = wp[i].o.yv;
648 s = 0;
649 if (y < 0) {
650 if (-y >= x) {
651 s = 30;
653 } else if (y > 0) {
654 if (y >= x / 2) {
655 s = 31;
658 } else {
659 s = (d - 2) / 2 + 1;
660 d = 0;
662 break;
663 case MANF:
664 s=wp[i].s;
665 if (s >= 2) {
666 s /= 2;
667 break;
669 case PLASMA:
670 case APLASMA:
671 case BALL1:
672 case BALL7:
673 case BALL2:
674 s = wp[i].s;
675 if (s >= 2) {
676 s = s / 2 + 1;
678 switch (wp[i].t) {
679 case PLASMA:
680 s += 4;
681 break;
682 case APLASMA:
683 s += 11;
684 break;
685 case BALL1:
686 s += 32;
687 break;
688 case BALL2:
689 s += 42;
690 break;
691 case BALL7:
692 s += 37;
693 d = wp[i].o.xv >= 0 ? 1 : 0;
694 break;
695 case MANF:
696 s += 47;
697 d=(wp[i].o.xv>=0)?1:0;break;
699 break;
700 case BFGBALL:
701 s = wp[i].s;
702 if (s >= 2) {
703 s = s / 2 + 1;
705 s += 18;
706 break;
707 case BFGHIT:
708 s = wp[i].s / 2 + 26;
709 break;
711 if (s >= 0) {
712 Z_drawspr(wp[i].o.x, wp[i].o.y, wp_spr[s * 2 + d], wp_sprd[s * 2 + d]);
717 /* --- smoke --- */
719 static void SMK_draw (void) {
720 int i, s;
721 for (i = 0; i < MAXSMOK; ++i) {
722 if (sm[i].t) {
723 switch (sm[i].s) {
724 case 0:
725 s = sm[i].t;
726 if (s >= (SMSN - 1) * 3) {
727 s = 0;
728 } else {
729 s = SMSN - 1 - s / 3;
731 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);
732 break;
733 case 1:
734 s = sm[i].t;
735 if (s >= FLSN - 1) {
736 s = 0;
737 } else {
738 s = FLSN - 1 - s;
740 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);
741 break;
747 /* --- fx --- */
749 static void FX_draw (void) {
750 enum {NONE, TFOG, IFOG, BUBL}; // copypasted from fx.c
751 int i, s;
752 for (i = 0; i < MAXFX; ++i) {
753 s = -1;
754 switch (fx[i].t) {
755 case TFOG:
756 s = fx[i].s / 2;
757 break;
758 case IFOG:
759 s = fx[i].s / 2 + 10;
760 break;
761 case BUBL:
762 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);
763 continue;
765 if (s >= 0) {
766 Z_drawspr(fx[i].x, fx[i].y, fx_spr[s], fx_sprd[s]);
771 /* --- view --- */
773 static void W_adjust (void) {
774 int MAXX = FLDW * CELW - WD / 2;
775 int MAXY = FLDH * CELH - HT / 2;
776 if (w_x < WD / 2) w_x = WD / 2;
777 if (w_y < HT / 2) w_y = HT / 2;
778 if (w_x > MAXX) w_x = MAXX;
779 if (w_y > MAXY) w_y = MAXY;
782 static void W_draw(void) {
783 W_adjust();
784 V_setrect(0, WD, w_o + 1, HT);
785 if (w_horiz) {
786 vgaimg *img = (vgaimg*)horiz;
787 int x = 0;
788 int d = 0;
789 do {
790 int y = w_o;
791 d &= ~2;
792 do {
793 V_rotspr(x, y, img, d);
794 y += img->h;
795 d ^= 2;
796 } while (y < HT + w_o);
797 x += img->w;
798 d ^= 1;
799 } while (x < WD);
800 if (sky_type == 2) {
801 if (lt_time < 0) {
802 if (!lt_side) {
803 V_spr(0, w_o + lt_ypos, ltn[lt_type][lt_time < -5 ? 0 : 1]);
804 } else {
805 V_spr2(WD - 1, w_o + lt_ypos, ltn[lt_type][lt_time < -5 ? 0 : 1]);
809 } else {
810 V_clr(0, WD, w_o + 1, HT, 0x97);
812 Z_drawfld((byte*)fldb, 1);
813 DOT_draw();
814 IT_draw();
815 PL_draw(&pl1);
816 if (_2pl) {
817 PL_draw(&pl2);
819 MN_draw();
820 WP_draw();
821 SMK_draw();
822 FX_draw();
823 Z_drawfld((byte*)fldf, 0);
824 if (sky_type == 2) {
825 if (lt_time == -4 || lt_time == -2) {
826 V_remap_rect(0, WD, w_o + 1, HT, clrmap + 256 * 11);
831 /* --- game --- */
833 #define PL_FLASH 90
835 static void drawview (player_t *p) {
836 if (p->looky < -SCRH / 4) {
837 p->looky = -SCRH / 4;
838 } else if (p->looky > SCRH / 4) {
839 p->looky = SCRH / 4;
841 w_x = p->o.x;
842 w_y = p->o.y - 12 + p->looky;
843 W_draw();
844 PL_drawst(p);
847 static int get_pu_st (int t) {
848 if (t >= PL_FLASH) {
849 return 1;
850 } else if((t / 9) & 1) {
851 return 0;
852 } else {
853 return 1;
857 static void pl_info (player_t *p, int y) {
858 dword t = p->kills * 10920 / g_time;
859 Z_gotoxy(25, y); Z_printbf("KILLS");
860 Z_gotoxy(25, y + 15); Z_printbf("KPM");
861 Z_gotoxy(25, y + 30); Z_printbf("SECRETS %u / %u", p->secrets, sw_secrets);
862 Z_gotoxy(255, y); Z_printbf("%u", p->kills);
863 Z_gotoxy(255, y + 15); Z_printbf("%u.%u", t / 10, t % 10);
866 static void W_act (void) {
867 int i, a;
868 if (g_time % 3 == 0) {
869 for (i = 1; i < 256; ++i) {
870 a = walani[i];
871 if (a != 0) {
872 anic[a]++;
873 if (anih[a][anic[a]] == -1) {
874 anic[a] = 0;
876 walp[i] = V_getvgaimg(anih[a][anic[a]]);
882 void R_draw (void) {
883 int h;
884 word hr, mn, sc;
885 W_act();
886 if (g_trans && !transdraw) {
887 return;
889 switch (g_st) {
890 case GS_ENDANIM:
891 case GS_END2ANIM:
892 case GS_DARKEN:
893 case GS_BVIDEO:
894 case GS_EVIDEO:
895 case GS_END3ANIM:
896 return;
897 case GS_TITLE:
898 V_center(1);
899 V_pic(0, 0, scrnh[0]);
900 V_center(0);
901 break;
902 case GS_ENDSCR:
903 V_center(1);
904 V_clr(0, SCRW, 0, SCRH, 0);
905 V_pic(0, 0, scrnh[2]);
906 V_center(0);
907 break;
908 case GS_INTER:
909 V_center(1);
910 V_clr(0, SCRW, 0, SCRH, 0);
911 V_pic(0, 0, scrnh[1]);
912 Z_gotoxy(60, 20);
913 Z_printbf("LEVEL COMPLETE");
914 Z_calc_time(g_time, &hr, &mn, &sc);
915 Z_gotoxy(115, 40);
916 Z_printbf("TIME %u:%02u:%02u", hr, mn, sc);
917 h = 60;
918 if (_2pl) {
919 Z_gotoxy(80, h);
920 Z_printbf("PLAYER ONE");
921 Z_gotoxy(80, h + 70);
922 Z_printbf("PLAYER TWO");
923 h += SCRH / 10;
925 pl_info(&pl1, h);
926 if (_2pl) {
927 pl_info(&pl2, h + 70);
929 V_center(0);
930 break;
932 V_center(1);
933 if (g_st != GS_GAME) {
934 if (g_trans) {
935 return;
937 GM_draw();
938 V_copytoscr(0, SCRW, 0, SCRH);
939 return;
941 V_center(0);
942 if (_2pl) {
943 w_o = 0;
944 WD = SCRW - 120;
945 HT = SCRH / 2 - 2;
946 drawview(&pl1);
947 w_o = SCRH / 2;
948 WD = SCRW - 120;
949 HT = SCRH / 2 - 2;
950 drawview(&pl2);
951 } else{
952 w_o = 0;
953 WD = SCRW - 120;
954 HT = SCRH - 2;
955 drawview(&pl1);
957 if (g_trans) {
958 return;
960 V_center(1);
961 if (GM_draw()) {
962 pl1.drawst = 0xFF;
963 pl2.drawst = 0xFF;
964 V_copytoscr(0,SCRW,0,SCRH);
965 return;
967 V_center(0);
968 if (pl1.invl) {
969 h = get_pu_st(pl1.invl) * 6;
970 } else if (pl1.pain < 15) {
971 h = 0;
972 } else if (pl1.pain < 35) {
973 h = 1;
974 } else if (pl1.pain < 55) {
975 h = 2;
976 } else if (pl1.pain < 75) {
977 h=3;
978 } else if (pl1.pain < 95) {
979 h=4;
980 } else {
981 h = 5;
983 if (h != 0) {
984 V_maptoscr(0, SCRW - 120, 1, _2pl ? SCRH / 2 - 2 : SCRH - 2, clrmap + h * 256);
985 } else {
986 V_copytoscr(0, SCRW - 120, 1, _2pl ? SCRH / 2 - 2 : SCRH - 2);
988 if (pl1.drawst) {
989 V_copytoscr(SCRW - 120, 120, 0, _2pl ? SCRH / 2 : SCRH);
991 pl1.drawst = 0xFF;
992 if (_2pl) {
993 if (pl2.invl) {
994 h = get_pu_st(pl2.invl) * 6;
995 } else if (pl2.pain < 15) {
996 h = 0;
997 } else if (pl2.pain < 35) {
998 h = 1;
999 } else if (pl2.pain < 55) {
1000 h = 2;
1001 } else if (pl2.pain < 75) {
1002 h = 3;
1003 } else if (pl2.pain < 95) {
1004 h = 4;
1005 } else {
1006 h = 5;
1008 if (h) {
1009 V_maptoscr(0, SCRW - 120, SCRH / 2 + 1, SCRH / 2 - 2, clrmap + h * 256);
1010 } else {
1011 V_copytoscr(0, SCRW - 120, SCRH / 2 + 1, SCRH / 2 - 2);
1013 if (pl2.drawst) {
1014 V_copytoscr(SCRW - 120, 120, SCRH / 2, SCRH / 2);
1016 pl2.drawst = 0xFF;
1020 void R_alloc (void) {
1021 int i, j, n;
1022 char s[10];
1023 logo("R_alloc: загрузка графики\n");
1024 // game
1025 scrnh[0] = V_loadvgaimg("TITLEPIC");
1026 scrnh[1] = V_loadvgaimg("INTERPIC");
1027 scrnh[2] = V_loadvgaimg("ENDPIC");
1028 cd_scr = M_lock(F_getresid("CD1PIC"));
1029 for (i = 0; i < 2; ++i) {
1030 sprintf(s, "LTN%c", i + '1');
1031 for (j = 0; j < 2; ++j) {
1032 ltn[i][j] = Z_getspr(s, j, 0, NULL);
1035 // smoke
1036 for (i = 0; i < SMSN; ++i) {
1037 smk_spr[i] = Z_getspr("SMOK", i, 0, NULL);
1039 for (i = 0; i < FLSN; ++i) {
1040 smk_fspr[i] = Z_getspr("FLAM", i, 0, NULL);
1042 // fx
1043 for (i = 0; i < 10; ++i) {
1044 fx_spr[i] = Z_getspr("TFOG", i, 0, fx_sprd + i);
1046 for (; i < 15; ++i) {
1047 fx_spr[i] = Z_getspr("IFOG", i - 10, 0, fx_sprd + i);
1049 // weapons
1050 for (i = 0; i < 4; ++i) {
1051 wp_spr[i * 2] = Z_getspr("MISL", i, 1, wp_sprd + i * 2);
1052 wp_spr[i * 2 + 1] = Z_getspr("MISL", i, 2, wp_sprd + i * 2 + 1);
1054 for (; i < 6; ++i) {
1055 wp_spr[i * 2] = Z_getspr("PLSS", i - 4, 1, wp_sprd + i * 2);
1056 wp_spr[i * 2 + 1] = Z_getspr("PLSS", i - 4, 2, wp_sprd + i * 2 + 1);
1058 for (; i < 11; ++i) {
1059 wp_spr[i * 2] = Z_getspr("PLSE", i - 6, 1, wp_sprd + i * 2);
1060 wp_spr[i * 2 + 1] = Z_getspr("PLSE", i - 6, 2, wp_sprd + i * 2 + 1);
1062 for (; i < 13; ++i) {
1063 wp_spr[i * 2] = Z_getspr("APLS", i - 11, 1, wp_sprd + i * 2);
1064 wp_spr[i * 2 + 1] = Z_getspr("APLS", i - 11, 2, wp_sprd + i * 2 + 1);
1066 for (; i < 18; ++i) {
1067 wp_spr[i * 2] = Z_getspr("APBX", i - 13, 1, wp_sprd + i * 2);
1068 wp_spr[i * 2 + 1] = Z_getspr("APBX", i - 13, 2, wp_sprd + i * 2 + 1);
1070 for(; i < 20; ++i) {
1071 wp_spr[i * 2] = Z_getspr("BFS1", i - 18, 1, wp_sprd + i * 2);
1072 wp_spr[i * 2 + 1] = Z_getspr("BFS1", i - 18, 2, wp_sprd + i * 2 + 1);
1074 for (; i < 26; ++i) {
1075 wp_spr[i * 2] = Z_getspr("BFE1", i - 20, 1, wp_sprd + i * 2);
1076 wp_spr[i * 2 + 1] = Z_getspr("BFE1", i - 20, 2, wp_sprd + i * 2 + 1);
1078 for (; i < 30; ++i) {
1079 wp_spr[i * 2] = Z_getspr("BFE2", i - 26, 1, wp_sprd + i * 2);
1080 wp_spr[i * 2 + 1] = Z_getspr("BFE2", i - 26, 2, wp_sprd + i * 2 + 1);
1082 for (; i < 32; ++i) {
1083 wp_spr[i * 2] = Z_getspr("MISL", i - 30 + 4, 1, wp_sprd + i * 2);
1084 wp_spr[i * 2 + 1] = Z_getspr("MISL", i - 30 + 4, 2, wp_sprd + i * 2 + 1);
1086 for (; i < 37; ++i) {
1087 wp_spr[i * 2] = Z_getspr("BAL1", i - 32, 1, wp_sprd + i * 2);
1088 wp_spr[i * 2 + 1] = Z_getspr("BAL1", i - 32, 2, wp_sprd + i * 2 + 1);
1090 for (; i < 42; ++i) {
1091 wp_spr[i * 2] = Z_getspr("BAL7", i - 37, 1, wp_sprd + i * 2);
1092 wp_spr[i * 2 + 1] = Z_getspr("BAL7", i - 37, 2, wp_sprd + i * 2 + 1);
1094 for (; i < 47; ++i) {
1095 wp_spr[i * 2] = Z_getspr("BAL2", i - 42, 1, wp_sprd + i * 2);
1096 wp_spr[i * 2 + 1] = Z_getspr("BAL2", i - 42, 2, wp_sprd + i * 2 + 1);
1098 for (; i < 49; ++i) {
1099 wp_spr[i * 2] = Z_getspr("MANF", i - 47, 1, wp_sprd + i * 2);
1100 wp_spr[i * 2 + 1] = Z_getspr("MANF", i - 47, 2, wp_sprd + i * 2 + 1);
1102 // items
1103 static char snm[18][4] = {
1104 "CLIP", "SHEL", "ROCK", "CELL", "AMMO", "SBOX", "BROK", "CELP",
1105 "STIM", "MEDI", "BPAK",
1106 "CSAW", "SHOT", "SGN2", "MGUN", "LAUN", "PLAS", "BFUG"
1107 };
1108 static char n4[4][4] = {
1109 "SOUL", "SMRT", "SMGT", "SMBT"
1110 };
1111 static char n3[2][4] = {
1112 "GOR1", "FCAN"
1113 };
1114 for (i = 0; i < 18; ++i) {
1115 item_spr[i] = Z_getspr(snm[i], 0, 0, item_sprd + i);
1117 for (; i < 20; ++i) {
1118 item_spr[i] = Z_getspr("ARM1", i - 18, 0, item_sprd + i);
1119 item_spr[i + 2] = Z_getspr("ARM2", i - 18, 0, item_sprd + i);
1121 i+=2;
1122 for (; i < 26; ++i) {
1123 item_spr[i] = Z_getspr("MEGA", i - 22, 0, item_sprd + i);
1125 for (; i < 30; ++i) {
1126 item_spr[i] = Z_getspr("PINV", i - 26, 0, item_sprd + i);
1128 item_spr[30] = Z_getspr("AQUA", 0, 0, item_sprd + 30);
1129 item_spr[31] = Z_getspr("KEYR", 0, 0, item_sprd + 31);
1130 item_spr[32] = Z_getspr("KEYG", 0, 0, item_sprd + 32);
1131 item_spr[33] = Z_getspr("KEYB", 0, 0, item_sprd + 33);
1132 item_spr[34] = Z_getspr("SUIT", 0, 0, item_sprd + 34);
1133 for (n = 35, j = 0; j < 4; ++j) {
1134 for (i = 0; i < 4; ++i, ++n) {
1135 item_spr[n] = Z_getspr(n4[j], i, 0, item_sprd + n);
1138 for (j = 0; j < 2; ++j) {
1139 for (i = 0; i < 3; ++i, ++n) {
1140 item_spr[n] = Z_getspr(n3[j], i, 0, item_sprd + n);
1143 item_spr[57] = Z_getspr("GUN2", 0, 0, item_sprd + 57);
1144 // player
1145 for (i = 0; i < 27; ++i) {
1146 plr_spr[i * 2] = Z_getspr("PLAY", i, 1, plr_sprd + i * 2);
1147 plr_spr[i * 2 + 1] = Z_getspr("PLAY", i, 2, plr_sprd + i * 2 + 1);
1149 strncpy(s, "PWPx", 4);
1150 for (i = 1; i < 11; ++i) {
1151 s[3] = (i < 10 ? '0' : 'A' - 10) + i;
1152 for (j = 0; j < 6; ++j) {
1153 plr_wpn[i][j] = Z_getspr(s, j, 1, NULL);
1156 // monsters
1157 static char msn[MN_TN][4] = {
1158 "SARG", "TROO", "POSS", "SPOS", "CYBR", "CPOS", "BOSS", "BOS2", "HEAD", "SKUL",
1159 "PAIN", "SPID", "BSPI", "FATT", "SKEL", "VILE", "FISH", "BAR1", "ROBO", "PLAY"
1160 };
1161 static int mms[MN_TN] = {
1162 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,
1163 20*2, 17*2, 29*2, 6*2, 2*2, 17*2, 23*2
1164 };
1165 mn_sgun[0] = Z_getspr("PWP4", 0, 1, NULL);
1166 mn_sgun[1] = Z_getspr("PWP4", 1, 1, NULL);
1167 for (j = 0; j < MN_TN; ++j) {
1168 for (i = 0; i < mms[j]; ++i) {
1169 mn_spr[j][i] = Z_getspr(msn[j], i / 2, (i & 1) + 1, &mn_sprd[j][i]);
1171 if (j == MN_BARREL - 1) {
1172 for (i = 4; i < 14; ++i) {
1173 mn_spr[j][i] = Z_getspr("BEXP", i / 2 - 2, (i & 1) + 1, &mn_sprd[j][i]);
1177 for (i = 0; i < 8; ++i) {
1178 mn_fspr[i] = Z_getspr("FIRE", i, 0, NULL);
1180 pl_spr[0] = Z_getspr("PLAY", 'N' - 'A', 0, NULL);
1181 pl_spr[1] = Z_getspr("PLAY", 'W' - 'A', 0, NULL);
1182 // misc
1183 static char mnm[22][8]={
1184 "STTNUM0","STTNUM1","STTNUM2","STTNUM3","STTNUM4",
1185 "STTNUM5","STTNUM6","STTNUM7","STTNUM8","STTNUM9",
1186 "STTMINUS","STTPRCNT",
1187 "FISTA0","CSAWA0","PISTA0","SHOTA0","SGN2A0","MGUNA0","LAUNA0",
1188 "PLASA0","BFUGA0","GUN2A0"
1189 };
1190 stone=V_loadvgaimg("STONE");
1191 stone2=V_loadvgaimg("STONE2");
1192 keys[0]=V_loadvgaimg("KEYRA0");
1193 keys[1]=V_loadvgaimg("KEYGA0");
1194 keys[2]=V_loadvgaimg("KEYBA0");
1195 for (i = 0; i < 22; ++i) {
1196 sth[i] = V_loadvgaimg(mnm[i]);
1198 strcpy(s, "STBF_*");
1199 for (i = '!'; i < 160; ++i) {
1200 s[5] = i;
1201 bfh[i - '!'] = V_getvgaimg(F_findres(s));
1203 for (i = '!'; i < 160; ++i) {
1204 sprintf(s, "STCFN%03d", i);
1205 sfh[i - '!'] = V_getvgaimg(F_findres(s));
1207 strcpy(s, "WINUM*");
1208 for (i = '0'; i <= '9'; ++i) {
1209 s[5] = i;
1210 bfh[i - '!'] = V_loadvgaimg(s);
1212 bfh[':' - '!'] = V_loadvgaimg("WICOLON");
1213 // menu
1214 msklh[0] = V_loadvgaimg("M_SKULL1");
1215 msklh[1] = V_loadvgaimg("M_SKULL2");
1216 mbarl = V_loadvgaimg("M_THERML");
1217 mbarm = V_loadvgaimg("M_THERMM");
1218 mbarr = V_loadvgaimg("M_THERMR");
1219 mbaro = V_loadvgaimg("M_THERMO");
1220 mslotl = V_loadvgaimg("M_LSLEFT");
1221 mslotm = V_loadvgaimg("M_LSCNTR");
1222 mslotr = V_loadvgaimg("M_LSRGHT");
1223 // walls
1224 static char *anm[ANIT - 1][5] = {
1225 {"WALL22_1", "WALL23_1", "WALL23_2", NULL, NULL},
1226 {"WALL58_1", "WALL58_2", "WALL58_3", NULL, NULL},
1227 {"W73A_1", "W73A_2", NULL, NULL, NULL},
1228 {"RP2_1", "RP2_2", "RP2_3", "RP2_4", NULL}
1229 };
1230 for (i = 1; i < ANIT; i++) {
1231 for (j = 0; anm[i - 1][j]; j++) {
1232 anih[i][j] = F_getresid(anm[i - 1][j]);
1234 for(; j < 5; j++) {
1235 anih[i][j] = -1;
1240 void R_get_name (int n, char s[8]) {
1241 if (walh[n] == -1) {
1242 memset(s, 0, 8);
1243 } else if (walh[n] == -2) {
1244 memcpy(s, "_WATER_", 8);
1245 s[7] = (char)((intptr_t)walp[n] - 1 + '0');
1246 } else {
1247 F_getresname(s, walh[n] & 0x7FFF);
1251 static short getani (char n[8]) {
1252 if (strncasecmp(n, "WALL22_1", 8) == 0) {
1253 return 1;
1254 } else if (strncasecmp(n, "WALL58_1", 8) == 0) {
1255 return 2;
1256 } else if (strncasecmp(n, "W73A_1", 8) == 0) {
1257 return 3;
1258 } else if (strncasecmp(n, "RP2_1", 8) == 0) {
1259 return 4;
1260 } else {
1261 return 0;
1265 int R_get_special_id (int n) {
1266 assert(n >= 0 && n < 256);
1267 intptr_t x = (intptr_t)walp[n];
1268 return x >= 0 && x <= 3 ? x : -1;
1271 void R_begin_load (void) {
1272 int i;
1273 for (i = 0; i < 256; i++) {
1274 if (walp[i] != NULL && walh[i] >= 0) {
1275 M_unlock(walp[i]);
1277 walh[i] = -1;
1278 walp[i] = NULL;
1279 walswp[i] = i;
1280 walani[i] = 0;
1282 memset(anic, 0, sizeof(anic));
1283 max_textures = 1;
1286 void R_load (char s[8], int f) {
1287 assert(max_textures < 256);
1288 if (!s[0]) {
1289 walh[max_textures] = -1;
1290 walp[max_textures] = NULL;
1291 } else {
1292 if (strncasecmp(s, "_WATER_", 7) == 0) {
1293 walh[max_textures] = -2;
1294 walp[max_textures] = (void*)((intptr_t)s[7] - '0' + 1);
1295 } else {
1296 walh[max_textures] = F_getresid(s);
1297 walp[max_textures] = V_getvgaimg(walh[max_textures]);
1298 if (f) {
1299 walh[max_textures] |= 0x8000;
1301 if (s[0] == 'S' && s[1] == 'W' && s[4] == '_') {
1302 walswp[max_textures] = 0;
1305 walani[max_textures] = getani(s);
1307 max_textures++;
1310 void R_end_load (void) {
1311 int i, j, k, g;
1312 char s[8];
1313 j = max_textures;
1314 for (i = 1; i < 256 && j < 256; i++) {
1315 if (walswp[i] == 0) {
1316 R_get_name(i, s);
1317 s[5] ^= 1;
1318 g = F_getresid(s) | (walh[i] & 0x8000);
1319 k = 1;
1320 while (k < 256 && walh[k] != g) {
1321 k += 1;
1323 if (k >= 256) {
1324 k = j;
1325 j += 1;
1326 walh[k] = g;
1327 walp[k] = V_getvgaimg(g);
1328 walf[k] = g & 0x8000 ? 1 : 0;
1330 walswp[i] = k;
1331 walswp[k] = i;
1336 void R_loadsky (int sky) {
1337 char s[6];
1338 strcpy(s, "RSKY1");
1339 s[4] = '0' + sky;
1340 M_unlock(horiz);
1341 horiz = V_loadvgaimg(s);
1344 void R_setgamma(int g) {
1345 int t;
1346 g = g < 0 ? 0 : (g > 4 ? 4 : g);
1347 gammaa = g;
1348 for (t = 0; t < 256; ++t) {
1349 std_pal[t][0]=gamcor[gammaa][main_pal[t][0]];
1350 std_pal[t][1]=gamcor[gammaa][main_pal[t][1]];
1351 std_pal[t][2]=gamcor[gammaa][main_pal[t][2]];
1353 VP_setall(std_pal);
1356 int R_getgamma (void) {
1357 return gammaa;
1360 void R_toggle_fullscreen (void) {
1361 fullscreen = !fullscreen;
1362 V_toggle();
1365 void R_init () {
1366 int i;
1367 F_loadres(F_getresid("PLAYPAL"), main_pal, 0, 768);
1368 for (i = 0; i < 256; ++i) {
1369 bright[i] = ((int) main_pal[i][0] + main_pal[i][1] + main_pal[i][2]) * 8 / (63 * 3);
1371 F_loadres(F_getresid("MIXMAP"), mixmap, 0, 0x10000);
1372 F_loadres(F_getresid("COLORMAP"), clrmap, 0, 256*12);
1373 logo("V_init: настройка видео\n");
1374 if (V_init() != 0) {
1375 ERR_failinit("Не могу установить видеорежим VGA");
1377 R_setgamma(gammaa);
1378 V_setrect(0, SCRW, 0, SCRH);
1379 V_setscr(scrbuf);
1380 V_clr(0, SCRW, 0, SCRH, 0);
1381 R_alloc();
1384 void R_done (void) {
1385 V_done();