DEADSOFTWARE

headers describes that c-files implements
[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"
22 #include "game.h"
23 #include "sound.h"
24 #include "music.h"
26 // game
27 static vgaimg *scrnh[3]; // TITLEPIC INTERPIC ENDPIC
28 static vgaimg *ltn[2][2];
29 static void *cd_scr;
30 // smoke
31 static vgaimg *smk_spr[SMSN];
32 static vgaimg *smk_fspr[FLSN];
33 // fx
34 static vgaimg *fx_spr[15];
35 static char fx_sprd[15];
36 // weapons
37 static vgaimg *wp_spr[49*2];
38 static char wp_sprd[49*2];
39 // items
40 static vgaimg *item_spr[58];
41 static char item_sprd[58];
42 // player
43 static vgaimg *plr_spr[27*2];
44 static char plr_sprd[27*2];
45 static vgaimg *plr_wpn[11][6];
46 // monsters
47 static vgaimg *pl_spr[2];
48 static vgaimg *mn_spr[MN_TN][29*2];
49 static char mn_sprd[MN_TN][29*2];
50 static vgaimg *mn_fspr[8];
51 static vgaimg *mn_sgun[2];
52 // misc
53 #define MAXAIR 1091
54 static vgaimg *sth[22], *bfh[160 - '!'], *sfh[160 - '!'], *stone, *stone2, *keys[3];
55 static int prx = 0, pry = 0;
56 // menu
57 static vgaimg *msklh[2], *mbarl, *mbarm, *mbarr, *mbaro, *mslotl, *mslotm, *mslotr;
58 // low level
59 static int gammaa = 0;
60 static char main_pal[256][3];
61 static char std_pal[256][3];
62 static byte gamcor[5][64]={
63 #include "gamma.dat"
64 };
65 // walls
66 #define ANIT 5
67 static int WD, HT;
68 static int w_o, w_x, w_y;
69 static vgaimg *walp[256];
70 static int walh[256];
71 static byte walani[256];
72 static int anih[ANIT][5];
73 static byte anic[ANIT];
74 static int max_textures;
75 static vgaimg *horiz;
77 /* --- misc --- */
79 static void *Z_getspr (char n[4], int s, int d, char *dir) {
80 int h = F_getsprid(n, s, d);
81 if (dir) {
82 *dir = (h & 0x8000) ? 1 : 0;
83 }
84 return V_getvgaimg(h);
85 }
87 static void Z_putbfch (int c) {
88 vgaimg *p;
89 if (c > 32 && c < 160) {
90 p = bfh[c - '!'];
91 } else {
92 p = NULL;
93 }
94 if (p) {
95 V_spr(prx, pry, p);
96 prx += p->w - 1;
97 } else {
98 prx += 12;
99 }
102 static void Z_putsfch(int c) {
103 vgaimg *p;
104 if (c > 32 && c < 160) {
105 p = sfh[c - '!'];
106 } else {
107 p = NULL;
109 if (p) {
110 V_spr(prx, pry, p);
111 prx += p->w - 1;
112 } else {
113 prx += 7;
117 static void Z_gotoxy (int x, int y) {
118 prx = x;
119 pry = y;
122 static void Z_printbf(char *s, ...) {
123 int i;
124 va_list ap;
125 char buf[80];
126 va_start(ap, s);
127 vsprintf(buf, s, ap);
128 va_end(ap);
129 for (i = 0; buf[i]; ++i) {
130 switch (buf[i]) {
131 case '\n':
132 pry += 13;
133 case '\r':
134 prx = 0;
135 break;
136 default:
137 Z_putbfch((byte)buf[i]);
142 static void Z_printsf (char *s, ...) {
143 int i;
144 va_list ap;
145 char buf[80];
146 va_start(ap, s);
147 vsprintf(buf, s, ap);
148 va_end(ap);
149 for (i = 0; buf[i]; ++i) {
150 switch(buf[i]) {
151 case '\n':
152 pry += 8;
153 case '\r':
154 prx=0;
155 break;
156 default:
157 Z_putsfch((byte)buf[i]);
162 static void Z_drawspr (int x, int y, void *p, char d) {
163 if (d) {
164 V_spr2(x - w_x + WD / 2, y - w_y + HT / 2 + 1 + w_o, p);
165 } else {
166 V_spr(x - w_x + WD / 2, y - w_y + HT / 2 + 1 + w_o, p);
170 static void Z_clrst (void) {
171 V_pic(SCRW - 120, w_o, stone);
172 int y = ((vgaimg*)stone)->h;
173 while (y < HT) {
174 V_pic(SCRW - 120, w_o + y, stone2);
175 y += ((vgaimg*)stone)->h;
179 static void Z_drawstlives (char n) {
180 V_setrect(SCRW - 40, 30, w_o, 40);
181 V_spr(SCRW - 35, w_o + 17, sth[n]);
184 static void Z_drawstkeys (byte k) {
185 int x, n;
186 V_setrect(SCRW - 120, 70, w_o + 77, 23);
187 for (k >>= 4, n = 0, x = SCRW - 75; n < 3; ++n, k >>= 1, x += 9) {
188 if (k & 1) {
189 V_spr(x, w_o + 91, keys[n]);
194 static void Z_drawstair (int a) {
195 V_setrect(SCRW - 120, 120, w_o + 49, 2);
196 if (a > 0) {
197 if (a > MAXAIR) {
198 a = MAXAIR;
200 a = a * 100 / MAXAIR;
201 V_clr(SCRW - 110, a, w_o + 49, 2, 0xC8);
205 static void Z_drawstprcnt (int y, int n) {
206 char s[20];
207 int l, i, x, c;
208 V_setrect(SCRW - 120, 70, y * 19 + 7 + w_o, 19);
209 sprintf(s, "%3d%%", n);
210 l = strlen(s);
211 x = SCRW - 110;
212 for (i = 0; i < l; ++i, x += 14) {
213 if (s[i] >='0' && s[i] <= '9') {
214 c = s[i] - '0';
215 } else if (s[i] == '-') {
216 c = 10;
217 } else if (s[i] == '%') {
218 c = 11;
219 } else {
220 c = -1;
222 if (c >= 0) {
223 V_spr(x, y * 19 + 7 + w_o, sth[c]);
228 static void Z_drawstnum (int n) {
229 char s[20];
230 int l, i, x, c;
231 V_setrect(SCRW - 50, 50, w_o + 77, 23);
232 if (g_dm) {
233 sprintf(s, "%d", n);
234 l = strlen(s);
235 x = (115 - l * 14) + SCRW - 120;
236 for (i = 0; i < l; ++i, x += 14) {
237 if (s[i] >= '0' && s[i] <= '9') {
238 c = s[i] - '0';
239 } else if (s[i] == '-') {
240 c = 10;
241 } else if(s[i] == '%') {
242 c = 11;
243 } else {
244 c =- 1;
246 if (c >= 0) {
247 V_spr(x, w_o + 77 + 5, sth[c]);
253 static void Z_drawstwpn (int n, int a) {
254 char s[20];
255 int l, i, x, c;
256 i = n;
257 V_setrect(SCRW - 120, 120, w_o + 58, 23);
258 if (i >= 0) {
259 V_spr(SCRW - 88, w_o + 58 + 19, sth[i + 12]);
261 if (n >= 2) {
262 sprintf(s, "%d", a);
263 l = strlen(s);
264 x = SCRW - 10 - l * 14;
265 for (i = 0; i < l; ++i, x += 14) {
266 if (s[i] >= '0' && s[i] <= '9') {
267 c = s[i] - '0';
268 } else if (s[i] == '-') {
269 c = 10;
270 } else if (s[i] == '%') {
271 c = 11;
272 } else {
273 c = -1;
275 if (c >= 0) {
276 V_spr(x, w_o + 58 + 2, sth[c]);
282 static void Z_drawmanspr (int x, int y, void *p, char d, byte color) {
283 if (d) {
284 V_manspr2(x - w_x + WD / 2, y - w_y + HT / 2 + 1 + w_o, p, color);
285 } else {
286 V_manspr(x - w_x + WD / 2, y - w_y + HT / 2 + 1 + w_o, p, color);
290 static void Z_drawfld (byte *fld, int bg) {
291 byte *p = fld;
292 int x, y;
293 for (y = 0; y < FLDH; y++) {
294 for (x = 0; x < FLDW; x++) {
295 int sx = x * CELW - w_x + WD / 2;
296 int sy = y * CELH - w_y + HT / 2 + 1 + w_o;
297 int id = *p;
298 if (id) {
299 //intptr_t spc = (intptr_t) walp[id];
300 int spc = R_get_special_id(id);
301 if (spc >= 0 && spc <= 3) {
302 if (!bg) {
303 byte *cmap = clrmap + (spc + 7) * 256;
304 V_remap_rect(sx, sy, CELW, CELH, cmap);
306 } else {
307 V_pic(sx, sy, walp[id]);
310 p++;
315 /* --- menu --- */
317 static int gm_tm = 0; // ???
319 static vgaimg *PL_getspr (int s, int d) {
320 return plr_spr[(s - 'A') * 2 + d];
323 static int GM_draw (void) {
324 enum {MENU, MSG}; // copypasted from menu.c!
325 enum {
326 CANCEL, NEWGAME, LOADGAME, SAVEGAME, OPTIONS, QUITGAME, QUIT, ENDGAME, ENDGM,
327 PLR1, PLR2, COOP, DM, VOLUME, GAMMA, LOAD, SAVE, PLCOLOR, PLCEND, MUSIC, INTERP,
328 SVOLM, SVOLP, MVOLM, MVOLP, GAMMAM, GAMMAP, PL1CM, PL1CP, PL2CM, PL2CP
329 }; // copypasted from menu.c!
330 int i, j, k, y;
331 ++gm_tm;
332 V_setrect(0, SCRW, 0, SCRH);
333 if (!mnu && !gm_redraw) {
334 return 0;
336 gm_redraw = 0;
337 if (!mnu) {
338 return 1;
340 if (mnu->type == MENU) {
341 y = (200 - mnu -> n * 16 - 20) / 2;
342 Z_gotoxy(mnu->x, y - 10); Z_printbf(mnu->ttl);
343 for (i = 0; i < mnu->n; ++i) {
344 if (mnu->t[i] == LOAD || mnu->t[i] == SAVE) {
345 j = y + i * 16 + 29;
346 V_spr(mnu->x, j, mslotl);
347 for (k = 8; k < 184; k += 8) {
348 V_spr(mnu->x + k, j, mslotm);
350 V_spr(mnu->x+184,j,mslotr);
351 Z_gotoxy(mnu->x+4,j-8);
352 if (input && i == save_mnu.cur) {
353 Z_printsf("%s_", ibuf);
354 } else {
355 Z_printsf("%s", savname[i]);
357 } else {
358 Z_gotoxy(mnu->x + (mnu->t[i] >= SVOLM ? (mnu->t[i] >= PL1CM ? 50 : 152) : 0), y + i * 16 + 20);
359 Z_printbf(mnu->m[i]);
361 if (mnu->t[i] == MUSIC) {
362 Z_printbf(" '%.8s'",g_music);
363 } else if(mnu->t[i] == INTERP) {
364 Z_printbf("%s", fullscreen ? "ON" : "OFF");
365 } else if(mnu->t[i] >= PL1CM) {
366 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]);
367 } else if(mnu->t[i] >= SVOLM) {
368 j = y + i * 16 + 20;
369 V_spr(mnu->x, j, mbarl);
370 for (k = 8; k < 144; k += 8) {
371 V_spr(mnu->x + k, j, mbarm);
373 V_spr(mnu->x + 144, j, mbarr);
374 switch(mnu->t[i]) {
375 case SVOLM: k = snd_vol; break;
376 case MVOLM: k = mus_vol; break;
377 case GAMMAM: k = gammaa << 5; break;
379 V_spr(mnu->x + 8 + k, j, mbaro);
382 V_spr(mnu->x - 25, y + mnu->cur * 16 + 20 - 8, msklh[(gm_tm / 6) & 1]);
383 } else {
384 Z_gotoxy((320 - strlen(mnu->ttl) * 7) / 2, 90); Z_printsf(mnu->ttl);
385 Z_gotoxy(136, 100); Z_printsf("(Y/N)");
387 return 1;
390 /* --- dots --- */
392 static void DOT_draw (void) {
393 int i;
394 for (i = 0; i < MAXDOT; ++i) {
395 if (dot[i].t) {
396 V_dot(dot[i].o.x - w_x + WD / 2, dot[i].o.y - w_y + HT / 2 + 1 + w_o, dot[i].c);
401 /* --- items --- */
403 static void IT_draw (void) {
404 int i, s;
405 for (i = 0; i < MAXITEM; ++i) {
406 s = -1;
407 if (it[i].t && it[i].s >= 0) {
408 switch(it[i].t & 0x7FFF) {
409 case I_ARM1:
410 s = it[i].s / 9 + 18;
411 break;
412 case I_ARM2:
413 s = it[i].s / 9 + 20;
414 break;
415 case I_MEGA:
416 s = it[i].s / 2 + 22;
417 break;
418 case I_INVL:
419 s = it[i].s / 2 + 26;
420 break;
421 case I_SUPER:
422 case I_RTORCH:
423 case I_GTORCH:
424 case I_BTORCH:
425 s = it[i].s / 2 + (it[i].t - I_SUPER) * 4 + 35;
426 break;
427 case I_GOR1: case I_FCAN:
428 s = it[i].s / 2 + (it[i].t - I_GOR1) * 3 + 51;
429 break;
430 case I_AQUA:
431 s = 30;
432 break;
433 case I_SUIT:
434 s = 34;
435 break;
436 case I_KEYR:
437 case I_KEYG:
438 case I_KEYB:
439 s = (it[i].t & 0x7FFF) - I_KEYR + 31;
440 break;
441 case I_GUN2:
442 s = 57;
443 break;
444 default:
445 s = (it[i].t & 0x7FFF) - 1;
448 if (s >= 0) {
449 Z_drawspr(it[i].o.x, it[i].o.y, item_spr[s], item_sprd[s]);
454 /* --- player --- */
456 static int standspr (player_t *p) {
457 if (p->f & PLF_UP) {
458 return 'X';
459 } else if (p->f & PLF_DOWN) {
460 return 'Z';
461 } else {
462 return 'E';
466 static int wpnspr (player_t *p) {
467 if (p->f & PLF_UP) {
468 return 'C';
469 } else if(p->f & PLF_DOWN) {
470 return 'E';
471 } else {
472 return 'A';
476 static void PL_draw (player_t *p) {
477 enum {STAND, GO, DIE, SLOP, DEAD, MESS, OUT, FALL}; // copypasted from player.c!
478 static int wytab[] = {-1, -2, -1, 0};
479 int s = 'A';
480 int w = 0;
481 int wx = 0;
482 int wy = 0;
483 switch (p->st) {
484 case STAND:
485 if (p->f & PLF_FIRE) {
486 s = standspr(p) + 1;
487 w = wpnspr(p) + 1;
488 } else if (p->pain) {
489 s = 'G';
490 w = 'A';
491 wx = p->d ? 2 : -2;
492 wy = 1;
493 } else {
494 s = standspr(p);
495 w = wpnspr(p);
497 break;
498 case DEAD:
499 s = 'N';
500 break;
501 case MESS:
502 s = 'W';
503 break;
504 case GO:
505 if (p->pain) {
506 s = 'G';
507 w = 'A';
508 wx = p->d ? 2 : -2;
509 wy = 1;
510 } else {
511 s = plr_goanim[p->s / 8];
512 w = (p->f & PLF_FIRE) ? 'B' : 'A';
513 wx = p->d ? 2 : -2;
514 wy = 1 + wytab[s - 'A'];
516 break;
517 case DIE:
518 s = plr_dieanim[p->s];
519 break;
520 case SLOP:
521 s = plr_slopanim[p->s];
522 break;
523 case OUT:
524 s = 0;
525 break;
527 if (p->wpn == 0) {
528 w = 0;
530 if (w) {
531 Z_drawspr(p->o.x + wx, p->o.y + wy, plr_wpn[p->wpn][w - 'A'], p->d);
533 if (s) {
534 Z_drawmanspr(p->o.x, p->o.y, plr_spr[(s - 'A') * 2 + p->d], plr_sprd[(s - 'A') * 2 + p->d], p->color);
538 static void PL_drawst (player_t *p) {
539 int i;
540 V_setrect(WD, 120, w_o, HT);
541 Z_clrst();
542 if (p->drawst & PL_DRAWAIR) {
543 if (p->air < PL_AIR) {
544 Z_drawstair(p->air);
547 if (p->drawst & PL_DRAWLIFE) {
548 Z_drawstprcnt(0, p->life);
550 if (p->drawst & PL_DRAWARMOR) {
551 Z_drawstprcnt(1, p->armor);
553 if (p->drawst & PL_DRAWWPN) {
554 switch(p->wpn) {
555 case 2:
556 case 5:
557 i = p->ammo;
558 break;
559 case 3:
560 case 4:
561 case 9:
562 i = p->shel;
563 break;
564 case 6:
565 i = p->rock;
566 break;
567 case 10:
568 i = p->fuel;
569 break;
570 case 7:
571 case 8:
572 i = p->cell;
573 break;
575 Z_drawstwpn(p->wpn, i);
577 if (p->drawst & PL_DRAWFRAG) {
578 Z_drawstnum(p->frag);
580 if (p->drawst & PL_DRAWKEYS) {
581 Z_drawstkeys(p->keys);
583 if (!_2pl) {
584 if (p->drawst & PL_DRAWLIVES) {
585 Z_drawstlives(p->lives);
590 /* --- monster --- */
592 #define MANCOLOR 0xD0
594 static void MN_draw (void) {
595 enum {SLEEP, GO, RUN, CLIMB, DIE, DEAD, ATTACK, SHOOT, PAIN, WAIT, REVIVE, RUNOUT}; // copypasted from monster.c!
596 int i;
597 for (i = 0; i < MAXMN; ++i) {
598 if (mn[i].t) {
599 if (mn[i].t >= MN_PL_DEAD) {
600 Z_drawmanspr(mn[i].o.x, mn[i].o.y, pl_spr[mn[i].t - MN_PL_DEAD], 0, mn[i].d);
601 continue;
603 if ((mn[i].t != MN_SOUL && mn[i].t != MN_PAIN) || mn[i].st != DEAD) {
604 if (mn[i].t != MN_MAN) {
605 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]);
606 } else {
607 if (mn[i].ap[mn[i].ac] == 'E' || mn[i].ap[mn[i].ac] == 'F') {
608 Z_drawspr(mn[i].o.x, mn[i].o.y, mn_sgun[mn[i].ap[mn[i].ac] - 'E'], mn[i].d);
610 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);
613 if (mn[i].t == MN_VILE && mn[i].st == SHOOT) {
614 Z_drawspr(mn[i].tx, mn[i].ty, mn_fspr[mn[i].ac / 3], 0);
620 /* --- weapon --- */
622 static void WP_draw (void) {
623 enum {NONE, ROCKET, PLASMA, APLASMA, BALL1, BALL2, BALL7, BFGBALL, BFGHIT, MANF, REVF, FIRE}; // copypasted from weapons.c!
624 int i, s, d, x, y;
625 for (i = 0; i < MAXWPN; ++i) {
626 s = -1;
627 d = 0;
628 switch (wp[i].t) {
629 case NONE:
630 default:
631 break;
632 case REVF:
633 case ROCKET:
634 d = wp[i].s;
635 if (d < 2) {
636 d = wp[i].o.xv > 0 ? 1 : 0;
637 x = abs(wp[i].o.xv);
638 y = wp[i].o.yv;
639 s = 0;
640 if (y < 0) {
641 if (-y >= x) {
642 s = 30;
644 } else if (y > 0) {
645 if (y >= x / 2) {
646 s = 31;
649 } else {
650 s = (d - 2) / 2 + 1;
651 d = 0;
653 break;
654 case MANF:
655 s=wp[i].s;
656 if (s >= 2) {
657 s /= 2;
658 break;
660 case PLASMA:
661 case APLASMA:
662 case BALL1:
663 case BALL7:
664 case BALL2:
665 s = wp[i].s;
666 if (s >= 2) {
667 s = s / 2 + 1;
669 switch (wp[i].t) {
670 case PLASMA:
671 s += 4;
672 break;
673 case APLASMA:
674 s += 11;
675 break;
676 case BALL1:
677 s += 32;
678 break;
679 case BALL2:
680 s += 42;
681 break;
682 case BALL7:
683 s += 37;
684 d = wp[i].o.xv >= 0 ? 1 : 0;
685 break;
686 case MANF:
687 s += 47;
688 d=(wp[i].o.xv>=0)?1:0;break;
690 break;
691 case BFGBALL:
692 s = wp[i].s;
693 if (s >= 2) {
694 s = s / 2 + 1;
696 s += 18;
697 break;
698 case BFGHIT:
699 s = wp[i].s / 2 + 26;
700 break;
702 if (s >= 0) {
703 Z_drawspr(wp[i].o.x, wp[i].o.y, wp_spr[s * 2 + d], wp_sprd[s * 2 + d]);
708 /* --- smoke --- */
710 static void SMK_draw (void) {
711 int i, s;
712 for (i = 0; i < MAXSMOK; ++i) {
713 if (sm[i].t) {
714 switch (sm[i].s) {
715 case 0:
716 s = sm[i].t;
717 if (s >= (SMSN - 1) * 3) {
718 s = 0;
719 } else {
720 s = SMSN - 1 - s / 3;
722 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);
723 break;
724 case 1:
725 s = sm[i].t;
726 if (s >= FLSN - 1) {
727 s = 0;
728 } else {
729 s = FLSN - 1 - s;
731 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);
732 break;
738 /* --- fx --- */
740 static void FX_draw (void) {
741 enum {NONE, TFOG, IFOG, BUBL}; // copypasted from fx.c
742 int i, s;
743 for (i = 0; i < MAXFX; ++i) {
744 s = -1;
745 switch (fx[i].t) {
746 case TFOG:
747 s = fx[i].s / 2;
748 break;
749 case IFOG:
750 s = fx[i].s / 2 + 10;
751 break;
752 case BUBL:
753 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);
754 continue;
756 if (s >= 0) {
757 Z_drawspr(fx[i].x, fx[i].y, fx_spr[s], fx_sprd[s]);
762 /* --- view --- */
764 static void W_adjust (void) {
765 int MAXX = FLDW * CELW - WD / 2;
766 int MAXY = FLDH * CELH - HT / 2;
767 if (w_x < WD / 2) w_x = WD / 2;
768 if (w_y < HT / 2) w_y = HT / 2;
769 if (w_x > MAXX) w_x = MAXX;
770 if (w_y > MAXY) w_y = MAXY;
773 static void W_draw(void) {
774 W_adjust();
775 V_setrect(0, WD, w_o + 1, HT);
776 if (w_horiz) {
777 vgaimg *img = (vgaimg*)horiz;
778 int x = 0;
779 int d = 0;
780 do {
781 int y = w_o;
782 d &= ~2;
783 do {
784 V_rotspr(x, y, img, d);
785 y += img->h;
786 d ^= 2;
787 } while (y < HT + w_o);
788 x += img->w;
789 d ^= 1;
790 } while (x < WD);
791 if (sky_type == 2) {
792 if (lt_time < 0) {
793 if (!lt_side) {
794 V_spr(0, w_o + lt_ypos, ltn[lt_type][lt_time < -5 ? 0 : 1]);
795 } else {
796 V_spr2(WD - 1, w_o + lt_ypos, ltn[lt_type][lt_time < -5 ? 0 : 1]);
800 } else {
801 V_clr(0, WD, w_o + 1, HT, 0x97);
803 Z_drawfld((byte*)fldb, 1);
804 DOT_draw();
805 IT_draw();
806 PL_draw(&pl1);
807 if (_2pl) {
808 PL_draw(&pl2);
810 MN_draw();
811 WP_draw();
812 SMK_draw();
813 FX_draw();
814 Z_drawfld((byte*)fldf, 0);
815 if (sky_type == 2) {
816 if (lt_time == -4 || lt_time == -2) {
817 V_remap_rect(0, WD, w_o + 1, HT, clrmap + 256 * 11);
822 /* --- game --- */
824 #define PL_FLASH 90
826 static void drawview (player_t *p) {
827 if (p->looky < -SCRH / 4) {
828 p->looky = -SCRH / 4;
829 } else if (p->looky > SCRH / 4) {
830 p->looky = SCRH / 4;
832 w_x = p->o.x;
833 w_y = p->o.y - 12 + p->looky;
834 W_draw();
835 PL_drawst(p);
838 static int get_pu_st (int t) {
839 if (t >= PL_FLASH) {
840 return 1;
841 } else if((t / 9) & 1) {
842 return 0;
843 } else {
844 return 1;
848 static void pl_info (player_t *p, int y) {
849 dword t = p->kills * 10920 / g_time;
850 Z_gotoxy(25, y); Z_printbf("KILLS");
851 Z_gotoxy(25, y + 15); Z_printbf("KPM");
852 Z_gotoxy(25, y + 30); Z_printbf("SECRETS %u / %u", p->secrets, sw_secrets);
853 Z_gotoxy(255, y); Z_printbf("%u", p->kills);
854 Z_gotoxy(255, y + 15); Z_printbf("%u.%u", t / 10, t % 10);
857 static void W_act (void) {
858 int i, a;
859 if (g_time % 3 == 0) {
860 for (i = 1; i < 256; ++i) {
861 a = walani[i];
862 if (a != 0) {
863 anic[a]++;
864 if (anih[a][anic[a]] == -1) {
865 anic[a] = 0;
867 walp[i] = V_getvgaimg(anih[a][anic[a]]);
873 void R_draw (void) {
874 int h;
875 word hr, mn, sc;
876 W_act();
877 if (g_trans && !transdraw) {
878 return;
880 switch (g_st) {
881 case GS_ENDANIM:
882 case GS_END2ANIM:
883 case GS_DARKEN:
884 case GS_BVIDEO:
885 case GS_EVIDEO:
886 case GS_END3ANIM:
887 return;
888 case GS_TITLE:
889 V_center(1);
890 V_pic(0, 0, scrnh[0]);
891 V_center(0);
892 break;
893 case GS_ENDSCR:
894 V_center(1);
895 V_clr(0, SCRW, 0, SCRH, 0);
896 V_pic(0, 0, scrnh[2]);
897 V_center(0);
898 break;
899 case GS_INTER:
900 V_center(1);
901 V_clr(0, SCRW, 0, SCRH, 0);
902 V_pic(0, 0, scrnh[1]);
903 Z_gotoxy(60, 20);
904 Z_printbf("LEVEL COMPLETE");
905 Z_calc_time(g_time, &hr, &mn, &sc);
906 Z_gotoxy(115, 40);
907 Z_printbf("TIME %u:%02u:%02u", hr, mn, sc);
908 h = 60;
909 if (_2pl) {
910 Z_gotoxy(80, h);
911 Z_printbf("PLAYER ONE");
912 Z_gotoxy(80, h + 70);
913 Z_printbf("PLAYER TWO");
914 h += SCRH / 10;
916 pl_info(&pl1, h);
917 if (_2pl) {
918 pl_info(&pl2, h + 70);
920 V_center(0);
921 break;
923 V_center(1);
924 if (g_st != GS_GAME) {
925 if (g_trans) {
926 return;
928 GM_draw();
929 V_copytoscr(0, SCRW, 0, SCRH);
930 return;
932 V_center(0);
933 if (_2pl) {
934 w_o = 0;
935 WD = SCRW - 120;
936 HT = SCRH / 2 - 2;
937 drawview(&pl1);
938 w_o = SCRH / 2;
939 WD = SCRW - 120;
940 HT = SCRH / 2 - 2;
941 drawview(&pl2);
942 } else{
943 w_o = 0;
944 WD = SCRW - 120;
945 HT = SCRH - 2;
946 drawview(&pl1);
948 if (g_trans) {
949 return;
951 V_center(1);
952 if (GM_draw()) {
953 pl1.drawst = 0xFF;
954 pl2.drawst = 0xFF;
955 V_copytoscr(0,SCRW,0,SCRH);
956 return;
958 V_center(0);
959 if (pl1.invl) {
960 h = get_pu_st(pl1.invl) * 6;
961 } else if (pl1.pain < 15) {
962 h = 0;
963 } else if (pl1.pain < 35) {
964 h = 1;
965 } else if (pl1.pain < 55) {
966 h = 2;
967 } else if (pl1.pain < 75) {
968 h=3;
969 } else if (pl1.pain < 95) {
970 h=4;
971 } else {
972 h = 5;
974 if (h != 0) {
975 V_maptoscr(0, SCRW - 120, 1, _2pl ? SCRH / 2 - 2 : SCRH - 2, clrmap + h * 256);
976 } else {
977 V_copytoscr(0, SCRW - 120, 1, _2pl ? SCRH / 2 - 2 : SCRH - 2);
979 if (pl1.drawst) {
980 V_copytoscr(SCRW - 120, 120, 0, _2pl ? SCRH / 2 : SCRH);
982 pl1.drawst = 0xFF;
983 if (_2pl) {
984 if (pl2.invl) {
985 h = get_pu_st(pl2.invl) * 6;
986 } else if (pl2.pain < 15) {
987 h = 0;
988 } else if (pl2.pain < 35) {
989 h = 1;
990 } else if (pl2.pain < 55) {
991 h = 2;
992 } else if (pl2.pain < 75) {
993 h = 3;
994 } else if (pl2.pain < 95) {
995 h = 4;
996 } else {
997 h = 5;
999 if (h) {
1000 V_maptoscr(0, SCRW - 120, SCRH / 2 + 1, SCRH / 2 - 2, clrmap + h * 256);
1001 } else {
1002 V_copytoscr(0, SCRW - 120, SCRH / 2 + 1, SCRH / 2 - 2);
1004 if (pl2.drawst) {
1005 V_copytoscr(SCRW - 120, 120, SCRH / 2, SCRH / 2);
1007 pl2.drawst = 0xFF;
1011 void R_alloc (void) {
1012 int i, j, n;
1013 char s[10];
1014 logo("R_alloc: загрузка графики\n");
1015 // game
1016 scrnh[0] = V_loadvgaimg("TITLEPIC");
1017 scrnh[1] = V_loadvgaimg("INTERPIC");
1018 scrnh[2] = V_loadvgaimg("ENDPIC");
1019 cd_scr = M_lock(F_getresid("CD1PIC"));
1020 for (i = 0; i < 2; ++i) {
1021 sprintf(s, "LTN%c", i + '1');
1022 for (j = 0; j < 2; ++j) {
1023 ltn[i][j] = Z_getspr(s, j, 0, NULL);
1026 // smoke
1027 for (i = 0; i < SMSN; ++i) {
1028 smk_spr[i] = Z_getspr("SMOK", i, 0, NULL);
1030 for (i = 0; i < FLSN; ++i) {
1031 smk_fspr[i] = Z_getspr("FLAM", i, 0, NULL);
1033 // fx
1034 for (i = 0; i < 10; ++i) {
1035 fx_spr[i] = Z_getspr("TFOG", i, 0, fx_sprd + i);
1037 for (; i < 15; ++i) {
1038 fx_spr[i] = Z_getspr("IFOG", i - 10, 0, fx_sprd + i);
1040 // weapons
1041 for (i = 0; i < 4; ++i) {
1042 wp_spr[i * 2] = Z_getspr("MISL", i, 1, wp_sprd + i * 2);
1043 wp_spr[i * 2 + 1] = Z_getspr("MISL", i, 2, wp_sprd + i * 2 + 1);
1045 for (; i < 6; ++i) {
1046 wp_spr[i * 2] = Z_getspr("PLSS", i - 4, 1, wp_sprd + i * 2);
1047 wp_spr[i * 2 + 1] = Z_getspr("PLSS", i - 4, 2, wp_sprd + i * 2 + 1);
1049 for (; i < 11; ++i) {
1050 wp_spr[i * 2] = Z_getspr("PLSE", i - 6, 1, wp_sprd + i * 2);
1051 wp_spr[i * 2 + 1] = Z_getspr("PLSE", i - 6, 2, wp_sprd + i * 2 + 1);
1053 for (; i < 13; ++i) {
1054 wp_spr[i * 2] = Z_getspr("APLS", i - 11, 1, wp_sprd + i * 2);
1055 wp_spr[i * 2 + 1] = Z_getspr("APLS", i - 11, 2, wp_sprd + i * 2 + 1);
1057 for (; i < 18; ++i) {
1058 wp_spr[i * 2] = Z_getspr("APBX", i - 13, 1, wp_sprd + i * 2);
1059 wp_spr[i * 2 + 1] = Z_getspr("APBX", i - 13, 2, wp_sprd + i * 2 + 1);
1061 for(; i < 20; ++i) {
1062 wp_spr[i * 2] = Z_getspr("BFS1", i - 18, 1, wp_sprd + i * 2);
1063 wp_spr[i * 2 + 1] = Z_getspr("BFS1", i - 18, 2, wp_sprd + i * 2 + 1);
1065 for (; i < 26; ++i) {
1066 wp_spr[i * 2] = Z_getspr("BFE1", i - 20, 1, wp_sprd + i * 2);
1067 wp_spr[i * 2 + 1] = Z_getspr("BFE1", i - 20, 2, wp_sprd + i * 2 + 1);
1069 for (; i < 30; ++i) {
1070 wp_spr[i * 2] = Z_getspr("BFE2", i - 26, 1, wp_sprd + i * 2);
1071 wp_spr[i * 2 + 1] = Z_getspr("BFE2", i - 26, 2, wp_sprd + i * 2 + 1);
1073 for (; i < 32; ++i) {
1074 wp_spr[i * 2] = Z_getspr("MISL", i - 30 + 4, 1, wp_sprd + i * 2);
1075 wp_spr[i * 2 + 1] = Z_getspr("MISL", i - 30 + 4, 2, wp_sprd + i * 2 + 1);
1077 for (; i < 37; ++i) {
1078 wp_spr[i * 2] = Z_getspr("BAL1", i - 32, 1, wp_sprd + i * 2);
1079 wp_spr[i * 2 + 1] = Z_getspr("BAL1", i - 32, 2, wp_sprd + i * 2 + 1);
1081 for (; i < 42; ++i) {
1082 wp_spr[i * 2] = Z_getspr("BAL7", i - 37, 1, wp_sprd + i * 2);
1083 wp_spr[i * 2 + 1] = Z_getspr("BAL7", i - 37, 2, wp_sprd + i * 2 + 1);
1085 for (; i < 47; ++i) {
1086 wp_spr[i * 2] = Z_getspr("BAL2", i - 42, 1, wp_sprd + i * 2);
1087 wp_spr[i * 2 + 1] = Z_getspr("BAL2", i - 42, 2, wp_sprd + i * 2 + 1);
1089 for (; i < 49; ++i) {
1090 wp_spr[i * 2] = Z_getspr("MANF", i - 47, 1, wp_sprd + i * 2);
1091 wp_spr[i * 2 + 1] = Z_getspr("MANF", i - 47, 2, wp_sprd + i * 2 + 1);
1093 // items
1094 static char snm[18][4] = {
1095 "CLIP", "SHEL", "ROCK", "CELL", "AMMO", "SBOX", "BROK", "CELP",
1096 "STIM", "MEDI", "BPAK",
1097 "CSAW", "SHOT", "SGN2", "MGUN", "LAUN", "PLAS", "BFUG"
1098 };
1099 static char n4[4][4] = {
1100 "SOUL", "SMRT", "SMGT", "SMBT"
1101 };
1102 static char n3[2][4] = {
1103 "GOR1", "FCAN"
1104 };
1105 for (i = 0; i < 18; ++i) {
1106 item_spr[i] = Z_getspr(snm[i], 0, 0, item_sprd + i);
1108 for (; i < 20; ++i) {
1109 item_spr[i] = Z_getspr("ARM1", i - 18, 0, item_sprd + i);
1110 item_spr[i + 2] = Z_getspr("ARM2", i - 18, 0, item_sprd + i);
1112 i+=2;
1113 for (; i < 26; ++i) {
1114 item_spr[i] = Z_getspr("MEGA", i - 22, 0, item_sprd + i);
1116 for (; i < 30; ++i) {
1117 item_spr[i] = Z_getspr("PINV", i - 26, 0, item_sprd + i);
1119 item_spr[30] = Z_getspr("AQUA", 0, 0, item_sprd + 30);
1120 item_spr[31] = Z_getspr("KEYR", 0, 0, item_sprd + 31);
1121 item_spr[32] = Z_getspr("KEYG", 0, 0, item_sprd + 32);
1122 item_spr[33] = Z_getspr("KEYB", 0, 0, item_sprd + 33);
1123 item_spr[34] = Z_getspr("SUIT", 0, 0, item_sprd + 34);
1124 for (n = 35, j = 0; j < 4; ++j) {
1125 for (i = 0; i < 4; ++i, ++n) {
1126 item_spr[n] = Z_getspr(n4[j], i, 0, item_sprd + n);
1129 for (j = 0; j < 2; ++j) {
1130 for (i = 0; i < 3; ++i, ++n) {
1131 item_spr[n] = Z_getspr(n3[j], i, 0, item_sprd + n);
1134 item_spr[57] = Z_getspr("GUN2", 0, 0, item_sprd + 57);
1135 // player
1136 for (i = 0; i < 27; ++i) {
1137 plr_spr[i * 2] = Z_getspr("PLAY", i, 1, plr_sprd + i * 2);
1138 plr_spr[i * 2 + 1] = Z_getspr("PLAY", i, 2, plr_sprd + i * 2 + 1);
1140 strncpy(s, "PWPx", 4);
1141 for (i = 1; i < 11; ++i) {
1142 s[3] = (i < 10 ? '0' : 'A' - 10) + i;
1143 for (j = 0; j < 6; ++j) {
1144 plr_wpn[i][j] = Z_getspr(s, j, 1, NULL);
1147 // monsters
1148 static char msn[MN_TN][4] = {
1149 "SARG", "TROO", "POSS", "SPOS", "CYBR", "CPOS", "BOSS", "BOS2", "HEAD", "SKUL",
1150 "PAIN", "SPID", "BSPI", "FATT", "SKEL", "VILE", "FISH", "BAR1", "ROBO", "PLAY"
1151 };
1152 static int mms[MN_TN] = {
1153 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,
1154 20*2, 17*2, 29*2, 6*2, 2*2, 17*2, 23*2
1155 };
1156 mn_sgun[0] = Z_getspr("PWP4", 0, 1, NULL);
1157 mn_sgun[1] = Z_getspr("PWP4", 1, 1, NULL);
1158 for (j = 0; j < MN_TN; ++j) {
1159 for (i = 0; i < mms[j]; ++i) {
1160 mn_spr[j][i] = Z_getspr(msn[j], i / 2, (i & 1) + 1, &mn_sprd[j][i]);
1162 if (j == MN_BARREL - 1) {
1163 for (i = 4; i < 14; ++i) {
1164 mn_spr[j][i] = Z_getspr("BEXP", i / 2 - 2, (i & 1) + 1, &mn_sprd[j][i]);
1168 for (i = 0; i < 8; ++i) {
1169 mn_fspr[i] = Z_getspr("FIRE", i, 0, NULL);
1171 pl_spr[0] = Z_getspr("PLAY", 'N' - 'A', 0, NULL);
1172 pl_spr[1] = Z_getspr("PLAY", 'W' - 'A', 0, NULL);
1173 // misc
1174 static char mnm[22][8]={
1175 "STTNUM0","STTNUM1","STTNUM2","STTNUM3","STTNUM4",
1176 "STTNUM5","STTNUM6","STTNUM7","STTNUM8","STTNUM9",
1177 "STTMINUS","STTPRCNT",
1178 "FISTA0","CSAWA0","PISTA0","SHOTA0","SGN2A0","MGUNA0","LAUNA0",
1179 "PLASA0","BFUGA0","GUN2A0"
1180 };
1181 stone=V_loadvgaimg("STONE");
1182 stone2=V_loadvgaimg("STONE2");
1183 keys[0]=V_loadvgaimg("KEYRA0");
1184 keys[1]=V_loadvgaimg("KEYGA0");
1185 keys[2]=V_loadvgaimg("KEYBA0");
1186 for (i = 0; i < 22; ++i) {
1187 sth[i] = V_loadvgaimg(mnm[i]);
1189 strcpy(s, "STBF_*");
1190 for (i = '!'; i < 160; ++i) {
1191 s[5] = i;
1192 bfh[i - '!'] = V_getvgaimg(F_findres(s));
1194 for (i = '!'; i < 160; ++i) {
1195 sprintf(s, "STCFN%03d", i);
1196 sfh[i - '!'] = V_getvgaimg(F_findres(s));
1198 strcpy(s, "WINUM*");
1199 for (i = '0'; i <= '9'; ++i) {
1200 s[5] = i;
1201 bfh[i - '!'] = V_loadvgaimg(s);
1203 bfh[':' - '!'] = V_loadvgaimg("WICOLON");
1204 // menu
1205 msklh[0] = V_loadvgaimg("M_SKULL1");
1206 msklh[1] = V_loadvgaimg("M_SKULL2");
1207 mbarl = V_loadvgaimg("M_THERML");
1208 mbarm = V_loadvgaimg("M_THERMM");
1209 mbarr = V_loadvgaimg("M_THERMR");
1210 mbaro = V_loadvgaimg("M_THERMO");
1211 mslotl = V_loadvgaimg("M_LSLEFT");
1212 mslotm = V_loadvgaimg("M_LSCNTR");
1213 mslotr = V_loadvgaimg("M_LSRGHT");
1214 // walls
1215 static char *anm[ANIT - 1][5] = {
1216 {"WALL22_1", "WALL23_1", "WALL23_2", NULL, NULL},
1217 {"WALL58_1", "WALL58_2", "WALL58_3", NULL, NULL},
1218 {"W73A_1", "W73A_2", NULL, NULL, NULL},
1219 {"RP2_1", "RP2_2", "RP2_3", "RP2_4", NULL}
1220 };
1221 for (i = 1; i < ANIT; i++) {
1222 for (j = 0; anm[i - 1][j]; j++) {
1223 anih[i][j] = F_getresid(anm[i - 1][j]);
1225 for(; j < 5; j++) {
1226 anih[i][j] = -1;
1231 void R_get_name (int n, char s[8]) {
1232 if (walh[n] == -1) {
1233 memset(s, 0, 8);
1234 } else if (walh[n] == -2) {
1235 memcpy(s, "_WATER_", 8);
1236 s[7] = (char)((intptr_t)walp[n] - 1 + '0');
1237 } else {
1238 F_getresname(s, walh[n] & 0x7FFF);
1242 static short getani (char n[8]) {
1243 if (strncasecmp(n, "WALL22_1", 8) == 0) {
1244 return 1;
1245 } else if (strncasecmp(n, "WALL58_1", 8) == 0) {
1246 return 2;
1247 } else if (strncasecmp(n, "W73A_1", 8) == 0) {
1248 return 3;
1249 } else if (strncasecmp(n, "RP2_1", 8) == 0) {
1250 return 4;
1251 } else {
1252 return 0;
1256 int R_get_special_id (int n) {
1257 assert(n >= 0 && n < 256);
1258 intptr_t x = (intptr_t)walp[n];
1259 return x >= 0 && x <= 3 ? x : -1;
1262 void R_begin_load (void) {
1263 int i;
1264 for (i = 0; i < 256; i++) {
1265 if (walp[i] != NULL && walh[i] >= 0) {
1266 M_unlock(walp[i]);
1268 walh[i] = -1;
1269 walp[i] = NULL;
1270 walswp[i] = i;
1271 walani[i] = 0;
1273 memset(anic, 0, sizeof(anic));
1274 max_textures = 1;
1277 void R_load (char s[8], int f) {
1278 assert(max_textures < 256);
1279 if (!s[0]) {
1280 walh[max_textures] = -1;
1281 walp[max_textures] = NULL;
1282 } else {
1283 if (strncasecmp(s, "_WATER_", 7) == 0) {
1284 walh[max_textures] = -2;
1285 walp[max_textures] = (void*)((intptr_t)s[7] - '0' + 1);
1286 } else {
1287 walh[max_textures] = F_getresid(s);
1288 walp[max_textures] = V_getvgaimg(walh[max_textures]);
1289 if (f) {
1290 walh[max_textures] |= 0x8000;
1292 if (s[0] == 'S' && s[1] == 'W' && s[4] == '_') {
1293 walswp[max_textures] = 0;
1296 walani[max_textures] = getani(s);
1298 max_textures++;
1301 void R_end_load (void) {
1302 int i, j, k, g;
1303 char s[8];
1304 j = max_textures;
1305 for (i = 1; i < 256 && j < 256; i++) {
1306 if (walswp[i] == 0) {
1307 R_get_name(i, s);
1308 s[5] ^= 1;
1309 g = F_getresid(s) | (walh[i] & 0x8000);
1310 k = 1;
1311 while (k < 256 && walh[k] != g) {
1312 k += 1;
1314 if (k >= 256) {
1315 k = j;
1316 j += 1;
1317 walh[k] = g;
1318 walp[k] = V_getvgaimg(g);
1319 walf[k] = g & 0x8000 ? 1 : 0;
1321 walswp[i] = k;
1322 walswp[k] = i;
1327 void R_loadsky (int sky) {
1328 char s[6];
1329 strcpy(s, "RSKY1");
1330 s[4] = '0' + sky;
1331 M_unlock(horiz);
1332 horiz = V_loadvgaimg(s);
1335 void R_setgamma(int g) {
1336 int t;
1337 g = g < 0 ? 0 : (g > 4 ? 4 : g);
1338 gammaa = g;
1339 for (t = 0; t < 256; ++t) {
1340 std_pal[t][0]=gamcor[gammaa][main_pal[t][0]];
1341 std_pal[t][1]=gamcor[gammaa][main_pal[t][1]];
1342 std_pal[t][2]=gamcor[gammaa][main_pal[t][2]];
1344 VP_setall(std_pal);
1347 int R_getgamma (void) {
1348 return gammaa;
1351 void R_toggle_fullscreen (void) {
1352 fullscreen = !fullscreen;
1353 V_toggle();
1356 void R_init () {
1357 int i;
1358 F_loadres(F_getresid("PLAYPAL"), main_pal, 0, 768);
1359 for (i = 0; i < 256; ++i) {
1360 bright[i] = ((int) main_pal[i][0] + main_pal[i][1] + main_pal[i][2]) * 8 / (63 * 3);
1362 F_loadres(F_getresid("MIXMAP"), mixmap, 0, 0x10000);
1363 F_loadres(F_getresid("COLORMAP"), clrmap, 0, 256*12);
1364 logo("V_init: настройка видео\n");
1365 if (V_init() != 0) {
1366 ERR_failinit("Не могу установить видеорежим VGA");
1368 R_setgamma(gammaa);
1369 V_setrect(0, SCRW, 0, SCRH);
1370 // V_setscr(scrbuf);
1371 V_clr(0, SCRW, 0, SCRH, 0);
1372 R_alloc();
1375 void R_done (void) {
1376 V_done();