DEADSOFTWARE

render: remove dependency on sdl 1.2
[flatwaifu.git] / src / soft / render.c
1 #include <string.h>
2 #include <stdarg.h>
3 #include <stdlib.h> // abs()
4 #include <assert.h>
5 #include "glob.h"
6 #include "render.h"
7 #include "view.h"
8 #include "player.h"
9 #include "switch.h"
10 #include "vga.h"
11 #include "menu.h"
12 #include "misc.h"
13 #include "dots.h"
14 #include "items.h"
15 #include "monster.h"
16 #include "weapons.h"
17 #include "smoke.h"
18 #include "fx.h"
19 #include "memory.h"
20 #include "files.h"
21 #include "error.h"
22 #include "game.h"
23 #include "sound.h"
24 #include "music.h"
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;
689 break;
691 break;
692 case BFGBALL:
693 s = wp[i].s;
694 if (s >= 2) {
695 s = s / 2 + 1;
697 s += 18;
698 break;
699 case BFGHIT:
700 s = wp[i].s / 2 + 26;
701 break;
703 if (s >= 0) {
704 Z_drawspr(wp[i].o.x, wp[i].o.y, wp_spr[s * 2 + d], wp_sprd[s * 2 + d]);
709 /* --- smoke --- */
711 static void SMK_draw (void) {
712 int i, s;
713 for (i = 0; i < MAXSMOK; ++i) {
714 if (sm[i].t) {
715 switch (sm[i].s) {
716 case 0:
717 s = sm[i].t;
718 if (s >= (SMSN - 1) * 3) {
719 s = 0;
720 } else {
721 s = SMSN - 1 - s / 3;
723 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);
724 break;
725 case 1:
726 s = sm[i].t;
727 if (s >= FLSN - 1) {
728 s = 0;
729 } else {
730 s = FLSN - 1 - s;
732 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);
733 break;
739 /* --- fx --- */
741 static void FX_draw (void) {
742 enum {NONE, TFOG, IFOG, BUBL}; // copypasted from fx.c
743 int i, s;
744 for (i = 0; i < MAXFX; ++i) {
745 s = -1;
746 switch (fx[i].t) {
747 case TFOG:
748 s = fx[i].s / 2;
749 break;
750 case IFOG:
751 s = fx[i].s / 2 + 10;
752 break;
753 case BUBL:
754 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);
755 continue;
757 if (s >= 0) {
758 Z_drawspr(fx[i].x, fx[i].y, fx_spr[s], fx_sprd[s]);
763 /* --- view --- */
765 static void W_adjust (void) {
766 int MAXX = FLDW * CELW - WD / 2;
767 int MAXY = FLDH * CELH - HT / 2;
768 if (w_x < WD / 2) w_x = WD / 2;
769 if (w_y < HT / 2) w_y = HT / 2;
770 if (w_x > MAXX) w_x = MAXX;
771 if (w_y > MAXY) w_y = MAXY;
774 static void W_draw(void) {
775 W_adjust();
776 V_setrect(0, WD, w_o + 1, HT);
777 if (w_horiz) {
778 vgaimg *img = (vgaimg*)horiz;
779 int x = 0;
780 int d = 0;
781 do {
782 int y = w_o;
783 d &= ~2;
784 do {
785 V_rotspr(x, y, img, d);
786 y += img->h;
787 d ^= 2;
788 } while (y < HT + w_o);
789 x += img->w;
790 d ^= 1;
791 } while (x < WD);
792 if (sky_type == 2) {
793 if (lt_time < 0) {
794 if (!lt_side) {
795 V_spr(0, w_o + lt_ypos, ltn[lt_type][lt_time < -5 ? 0 : 1]);
796 } else {
797 V_spr2(WD - 1, w_o + lt_ypos, ltn[lt_type][lt_time < -5 ? 0 : 1]);
801 } else {
802 V_clr(0, WD, w_o + 1, HT, 0x97);
804 Z_drawfld((byte*)fldb, 1);
805 DOT_draw();
806 IT_draw();
807 PL_draw(&pl1);
808 if (_2pl) {
809 PL_draw(&pl2);
811 MN_draw();
812 WP_draw();
813 SMK_draw();
814 FX_draw();
815 Z_drawfld((byte*)fldf, 0);
816 if (sky_type == 2) {
817 if (lt_time == -4 || lt_time == -2) {
818 V_remap_rect(0, WD, w_o + 1, HT, clrmap + 256 * 11);
823 /* --- game --- */
825 #define PL_FLASH 90
827 static void drawview (player_t *p) {
828 if (p->looky < -SCRH / 4) {
829 p->looky = -SCRH / 4;
830 } else if (p->looky > SCRH / 4) {
831 p->looky = SCRH / 4;
833 w_x = p->o.x;
834 w_y = p->o.y - 12 + p->looky;
835 W_draw();
836 PL_drawst(p);
839 static int get_pu_st (int t) {
840 if (t >= PL_FLASH) {
841 return 1;
842 } else if((t / 9) & 1) {
843 return 0;
844 } else {
845 return 1;
849 static void pl_info (player_t *p, int y) {
850 dword t = p->kills * 10920 / g_time;
851 Z_gotoxy(25, y); Z_printbf("KILLS");
852 Z_gotoxy(25, y + 15); Z_printbf("KPM");
853 Z_gotoxy(25, y + 30); Z_printbf("SECRETS %u / %u", p->secrets, sw_secrets);
854 Z_gotoxy(255, y); Z_printbf("%u", p->kills);
855 Z_gotoxy(255, y + 15); Z_printbf("%u.%u", t / 10, t % 10);
858 static void W_act (void) {
859 int i, a;
860 if (g_time % 3 == 0) {
861 for (i = 1; i < 256; i++) {
862 a = walani[i];
863 if (a != 0) {
864 anic[a]++;
865 if (anih[a][anic[a]] == -1) {
866 anic[a] = 0;
868 walp[i] = V_getvgaimg(anih[a][anic[a]]);
874 void R_draw (void) {
875 int h;
876 word hr, mn, sc;
877 W_act();
878 if (g_trans && !transdraw) {
879 return;
881 switch (g_st) {
882 case GS_ENDANIM:
883 case GS_END2ANIM:
884 case GS_DARKEN:
885 case GS_BVIDEO:
886 case GS_EVIDEO:
887 case GS_END3ANIM:
888 return;
889 case GS_TITLE:
890 V_center(1);
891 V_pic(0, 0, scrnh[0]);
892 V_center(0);
893 break;
894 case GS_ENDSCR:
895 V_center(1);
896 V_clr(0, SCRW, 0, SCRH, 0);
897 V_pic(0, 0, scrnh[2]);
898 V_center(0);
899 break;
900 case GS_INTER:
901 V_center(1);
902 V_clr(0, SCRW, 0, SCRH, 0);
903 V_pic(0, 0, scrnh[1]);
904 Z_gotoxy(60, 20);
905 Z_printbf("LEVEL COMPLETE");
906 Z_calc_time(g_time, &hr, &mn, &sc);
907 Z_gotoxy(115, 40);
908 Z_printbf("TIME %u:%02u:%02u", hr, mn, sc);
909 h = 60;
910 if (_2pl) {
911 Z_gotoxy(80, h);
912 Z_printbf("PLAYER ONE");
913 Z_gotoxy(80, h + 70);
914 Z_printbf("PLAYER TWO");
915 h += SCRH / 10;
917 pl_info(&pl1, h);
918 if (_2pl) {
919 pl_info(&pl2, h + 70);
921 V_center(0);
922 break;
924 V_center(1);
925 if (g_st != GS_GAME) {
926 if (g_trans) {
927 return;
929 GM_draw();
930 V_copytoscr(0, SCRW, 0, SCRH);
931 return;
933 V_center(0);
934 if (_2pl) {
935 w_o = 0;
936 WD = SCRW - 120;
937 HT = SCRH / 2 - 2;
938 drawview(&pl1);
939 w_o = SCRH / 2;
940 WD = SCRW - 120;
941 HT = SCRH / 2 - 2;
942 drawview(&pl2);
943 } else{
944 w_o = 0;
945 WD = SCRW - 120;
946 HT = SCRH - 2;
947 drawview(&pl1);
949 if (g_trans) {
950 return;
952 V_center(1);
953 if (GM_draw()) {
954 pl1.drawst = 0xFF;
955 pl2.drawst = 0xFF;
956 V_copytoscr(0,SCRW,0,SCRH);
957 return;
959 V_center(0);
960 if (pl1.invl) {
961 h = get_pu_st(pl1.invl) * 6;
962 } else if (pl1.pain < 15) {
963 h = 0;
964 } else if (pl1.pain < 35) {
965 h = 1;
966 } else if (pl1.pain < 55) {
967 h = 2;
968 } else if (pl1.pain < 75) {
969 h=3;
970 } else if (pl1.pain < 95) {
971 h=4;
972 } else {
973 h = 5;
975 if (h != 0) {
976 V_maptoscr(0, SCRW - 120, 1, _2pl ? SCRH / 2 - 2 : SCRH - 2, clrmap + h * 256);
977 } else {
978 V_copytoscr(0, SCRW - 120, 1, _2pl ? SCRH / 2 - 2 : SCRH - 2);
980 if (pl1.drawst) {
981 V_copytoscr(SCRW - 120, 120, 0, _2pl ? SCRH / 2 : SCRH);
983 pl1.drawst = 0xFF;
984 if (_2pl) {
985 if (pl2.invl) {
986 h = get_pu_st(pl2.invl) * 6;
987 } else if (pl2.pain < 15) {
988 h = 0;
989 } else if (pl2.pain < 35) {
990 h = 1;
991 } else if (pl2.pain < 55) {
992 h = 2;
993 } else if (pl2.pain < 75) {
994 h = 3;
995 } else if (pl2.pain < 95) {
996 h = 4;
997 } else {
998 h = 5;
1000 if (h) {
1001 V_maptoscr(0, SCRW - 120, SCRH / 2 + 1, SCRH / 2 - 2, clrmap + h * 256);
1002 } else {
1003 V_copytoscr(0, SCRW - 120, SCRH / 2 + 1, SCRH / 2 - 2);
1005 if (pl2.drawst) {
1006 V_copytoscr(SCRW - 120, 120, SCRH / 2, SCRH / 2);
1008 pl2.drawst = 0xFF;
1012 void R_alloc (void) {
1013 int i, j, n;
1014 char s[10];
1015 logo("R_alloc: загрузка графики\n");
1016 // game
1017 scrnh[0] = V_loadvgaimg("TITLEPIC");
1018 scrnh[1] = V_loadvgaimg("INTERPIC");
1019 scrnh[2] = V_loadvgaimg("ENDPIC");
1020 cd_scr = M_lock(F_getresid("CD1PIC"));
1021 for (i = 0; i < 2; ++i) {
1022 sprintf(s, "LTN%c", i + '1');
1023 for (j = 0; j < 2; ++j) {
1024 ltn[i][j] = Z_getspr(s, j, 0, NULL);
1027 // smoke
1028 for (i = 0; i < SMSN; ++i) {
1029 smk_spr[i] = Z_getspr("SMOK", i, 0, NULL);
1031 for (i = 0; i < FLSN; ++i) {
1032 smk_fspr[i] = Z_getspr("FLAM", i, 0, NULL);
1034 // fx
1035 for (i = 0; i < 10; ++i) {
1036 fx_spr[i] = Z_getspr("TFOG", i, 0, fx_sprd + i);
1038 for (; i < 15; ++i) {
1039 fx_spr[i] = Z_getspr("IFOG", i - 10, 0, fx_sprd + i);
1041 // weapons
1042 for (i = 0; i < 4; ++i) {
1043 wp_spr[i * 2] = Z_getspr("MISL", i, 1, wp_sprd + i * 2);
1044 wp_spr[i * 2 + 1] = Z_getspr("MISL", i, 2, wp_sprd + i * 2 + 1);
1046 for (; i < 6; ++i) {
1047 wp_spr[i * 2] = Z_getspr("PLSS", i - 4, 1, wp_sprd + i * 2);
1048 wp_spr[i * 2 + 1] = Z_getspr("PLSS", i - 4, 2, wp_sprd + i * 2 + 1);
1050 for (; i < 11; ++i) {
1051 wp_spr[i * 2] = Z_getspr("PLSE", i - 6, 1, wp_sprd + i * 2);
1052 wp_spr[i * 2 + 1] = Z_getspr("PLSE", i - 6, 2, wp_sprd + i * 2 + 1);
1054 for (; i < 13; ++i) {
1055 wp_spr[i * 2] = Z_getspr("APLS", i - 11, 1, wp_sprd + i * 2);
1056 wp_spr[i * 2 + 1] = Z_getspr("APLS", i - 11, 2, wp_sprd + i * 2 + 1);
1058 for (; i < 18; ++i) {
1059 wp_spr[i * 2] = Z_getspr("APBX", i - 13, 1, wp_sprd + i * 2);
1060 wp_spr[i * 2 + 1] = Z_getspr("APBX", i - 13, 2, wp_sprd + i * 2 + 1);
1062 for(; i < 20; ++i) {
1063 wp_spr[i * 2] = Z_getspr("BFS1", i - 18, 1, wp_sprd + i * 2);
1064 wp_spr[i * 2 + 1] = Z_getspr("BFS1", i - 18, 2, wp_sprd + i * 2 + 1);
1066 for (; i < 26; ++i) {
1067 wp_spr[i * 2] = Z_getspr("BFE1", i - 20, 1, wp_sprd + i * 2);
1068 wp_spr[i * 2 + 1] = Z_getspr("BFE1", i - 20, 2, wp_sprd + i * 2 + 1);
1070 for (; i < 30; ++i) {
1071 wp_spr[i * 2] = Z_getspr("BFE2", i - 26, 1, wp_sprd + i * 2);
1072 wp_spr[i * 2 + 1] = Z_getspr("BFE2", i - 26, 2, wp_sprd + i * 2 + 1);
1074 for (; i < 32; ++i) {
1075 wp_spr[i * 2] = Z_getspr("MISL", i - 30 + 4, 1, wp_sprd + i * 2);
1076 wp_spr[i * 2 + 1] = Z_getspr("MISL", i - 30 + 4, 2, wp_sprd + i * 2 + 1);
1078 for (; i < 37; ++i) {
1079 wp_spr[i * 2] = Z_getspr("BAL1", i - 32, 1, wp_sprd + i * 2);
1080 wp_spr[i * 2 + 1] = Z_getspr("BAL1", i - 32, 2, wp_sprd + i * 2 + 1);
1082 for (; i < 42; ++i) {
1083 wp_spr[i * 2] = Z_getspr("BAL7", i - 37, 1, wp_sprd + i * 2);
1084 wp_spr[i * 2 + 1] = Z_getspr("BAL7", i - 37, 2, wp_sprd + i * 2 + 1);
1086 for (; i < 47; ++i) {
1087 wp_spr[i * 2] = Z_getspr("BAL2", i - 42, 1, wp_sprd + i * 2);
1088 wp_spr[i * 2 + 1] = Z_getspr("BAL2", i - 42, 2, wp_sprd + i * 2 + 1);
1090 for (; i < 49; ++i) {
1091 wp_spr[i * 2] = Z_getspr("MANF", i - 47, 1, wp_sprd + i * 2);
1092 wp_spr[i * 2 + 1] = Z_getspr("MANF", i - 47, 2, wp_sprd + i * 2 + 1);
1094 // items
1095 static char snm[18][4] = {
1096 "CLIP", "SHEL", "ROCK", "CELL", "AMMO", "SBOX", "BROK", "CELP",
1097 "STIM", "MEDI", "BPAK",
1098 "CSAW", "SHOT", "SGN2", "MGUN", "LAUN", "PLAS", "BFUG"
1099 };
1100 static char n4[4][4] = {
1101 "SOUL", "SMRT", "SMGT", "SMBT"
1102 };
1103 static char n3[2][4] = {
1104 "GOR1", "FCAN"
1105 };
1106 for (i = 0; i < 18; ++i) {
1107 item_spr[i] = Z_getspr(snm[i], 0, 0, item_sprd + i);
1109 for (; i < 20; ++i) {
1110 item_spr[i] = Z_getspr("ARM1", i - 18, 0, item_sprd + i);
1111 item_spr[i + 2] = Z_getspr("ARM2", i - 18, 0, item_sprd + i);
1113 i+=2;
1114 for (; i < 26; ++i) {
1115 item_spr[i] = Z_getspr("MEGA", i - 22, 0, item_sprd + i);
1117 for (; i < 30; ++i) {
1118 item_spr[i] = Z_getspr("PINV", i - 26, 0, item_sprd + i);
1120 item_spr[30] = Z_getspr("AQUA", 0, 0, item_sprd + 30);
1121 item_spr[31] = Z_getspr("KEYR", 0, 0, item_sprd + 31);
1122 item_spr[32] = Z_getspr("KEYG", 0, 0, item_sprd + 32);
1123 item_spr[33] = Z_getspr("KEYB", 0, 0, item_sprd + 33);
1124 item_spr[34] = Z_getspr("SUIT", 0, 0, item_sprd + 34);
1125 for (n = 35, j = 0; j < 4; ++j) {
1126 for (i = 0; i < 4; ++i, ++n) {
1127 item_spr[n] = Z_getspr(n4[j], i, 0, item_sprd + n);
1130 for (j = 0; j < 2; ++j) {
1131 for (i = 0; i < 3; ++i, ++n) {
1132 item_spr[n] = Z_getspr(n3[j], i, 0, item_sprd + n);
1135 item_spr[57] = Z_getspr("GUN2", 0, 0, item_sprd + 57);
1136 // player
1137 for (i = 0; i < 27; ++i) {
1138 plr_spr[i * 2] = Z_getspr("PLAY", i, 1, plr_sprd + i * 2);
1139 plr_spr[i * 2 + 1] = Z_getspr("PLAY", i, 2, plr_sprd + i * 2 + 1);
1141 strncpy(s, "PWPx", 4);
1142 for (i = 1; i < 11; ++i) {
1143 s[3] = (i < 10 ? '0' : 'A' - 10) + i;
1144 for (j = 0; j < 6; ++j) {
1145 plr_wpn[i][j] = Z_getspr(s, j, 1, NULL);
1148 // monsters
1149 static char msn[MN_TN][4] = {
1150 "SARG", "TROO", "POSS", "SPOS", "CYBR", "CPOS", "BOSS", "BOS2", "HEAD", "SKUL",
1151 "PAIN", "SPID", "BSPI", "FATT", "SKEL", "VILE", "FISH", "BAR1", "ROBO", "PLAY"
1152 };
1153 static int mms[MN_TN] = {
1154 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,
1155 20*2, 17*2, 29*2, 6*2, 2*2, 17*2, 23*2
1156 };
1157 mn_sgun[0] = Z_getspr("PWP4", 0, 1, NULL);
1158 mn_sgun[1] = Z_getspr("PWP4", 1, 1, NULL);
1159 for (j = 0; j < MN_TN; ++j) {
1160 for (i = 0; i < mms[j]; ++i) {
1161 mn_spr[j][i] = Z_getspr(msn[j], i / 2, (i & 1) + 1, &mn_sprd[j][i]);
1163 if (j == MN_BARREL - 1) {
1164 for (i = 4; i < 14; ++i) {
1165 mn_spr[j][i] = Z_getspr("BEXP", i / 2 - 2, (i & 1) + 1, &mn_sprd[j][i]);
1169 for (i = 0; i < 8; ++i) {
1170 mn_fspr[i] = Z_getspr("FIRE", i, 0, NULL);
1172 pl_spr[0] = Z_getspr("PLAY", 'N' - 'A', 0, NULL);
1173 pl_spr[1] = Z_getspr("PLAY", 'W' - 'A', 0, NULL);
1174 // misc
1175 static char mnm[22][8]={
1176 "STTNUM0","STTNUM1","STTNUM2","STTNUM3","STTNUM4",
1177 "STTNUM5","STTNUM6","STTNUM7","STTNUM8","STTNUM9",
1178 "STTMINUS","STTPRCNT",
1179 "FISTA0","CSAWA0","PISTA0","SHOTA0","SGN2A0","MGUNA0","LAUNA0",
1180 "PLASA0","BFUGA0","GUN2A0"
1181 };
1182 stone=V_loadvgaimg("STONE");
1183 stone2=V_loadvgaimg("STONE2");
1184 keys[0]=V_loadvgaimg("KEYRA0");
1185 keys[1]=V_loadvgaimg("KEYGA0");
1186 keys[2]=V_loadvgaimg("KEYBA0");
1187 for (i = 0; i < 22; ++i) {
1188 sth[i] = V_loadvgaimg(mnm[i]);
1190 strcpy(s, "STBF_*");
1191 for (i = '!'; i < 160; ++i) {
1192 s[5] = i;
1193 bfh[i - '!'] = V_getvgaimg(F_findres(s));
1195 for (i = '!'; i < 160; ++i) {
1196 sprintf(s, "STCFN%03d", i);
1197 sfh[i - '!'] = V_getvgaimg(F_findres(s));
1199 strcpy(s, "WINUM*");
1200 for (i = '0'; i <= '9'; ++i) {
1201 s[5] = i;
1202 bfh[i - '!'] = V_loadvgaimg(s);
1204 bfh[':' - '!'] = V_loadvgaimg("WICOLON");
1205 // menu
1206 msklh[0] = V_loadvgaimg("M_SKULL1");
1207 msklh[1] = V_loadvgaimg("M_SKULL2");
1208 mbarl = V_loadvgaimg("M_THERML");
1209 mbarm = V_loadvgaimg("M_THERMM");
1210 mbarr = V_loadvgaimg("M_THERMR");
1211 mbaro = V_loadvgaimg("M_THERMO");
1212 mslotl = V_loadvgaimg("M_LSLEFT");
1213 mslotm = V_loadvgaimg("M_LSCNTR");
1214 mslotr = V_loadvgaimg("M_LSRGHT");
1215 // walls
1216 static char *anm[ANIT - 1][5] = {
1217 {"WALL22_1", "WALL23_1", "WALL23_2", NULL, NULL},
1218 {"WALL58_1", "WALL58_2", "WALL58_3", NULL, NULL},
1219 {"W73A_1", "W73A_2", NULL, NULL, NULL},
1220 {"RP2_1", "RP2_2", "RP2_3", "RP2_4", NULL}
1221 };
1222 for (i = 1; i < ANIT; i++) {
1223 for (j = 0; anm[i - 1][j]; j++) {
1224 anih[i][j] = F_getresid(anm[i - 1][j]);
1226 for(; j < 5; j++) {
1227 anih[i][j] = -1;
1232 void R_get_name (int n, char s[8]) {
1233 if (walh[n] == -1) {
1234 memset(s, 0, 8);
1235 } else if (walh[n] == -2) {
1236 memcpy(s, "_WATER_", 8);
1237 s[7] = (char)((intptr_t)walp[n] - 1 + '0');
1238 } else {
1239 F_getresname(s, walh[n] & 0x7FFF);
1243 static short getani (char n[8]) {
1244 if (strncasecmp(n, "WALL22_1", 8) == 0) {
1245 return 1;
1246 } else if (strncasecmp(n, "WALL58_1", 8) == 0) {
1247 return 2;
1248 } else if (strncasecmp(n, "W73A_1", 8) == 0) {
1249 return 3;
1250 } else if (strncasecmp(n, "RP2_1", 8) == 0) {
1251 return 4;
1252 } else {
1253 return 0;
1257 int R_get_special_id (int n) {
1258 assert(n >= 0 && n < 256);
1259 intptr_t x = (intptr_t)walp[n];
1260 return x >= 0 && x <= 3 ? x : -1;
1263 void R_begin_load (void) {
1264 int i;
1265 for (i = 0; i < 256; i++) {
1266 if (walp[i] != NULL && walh[i] >= 0) {
1267 M_unlock(walp[i]);
1269 walh[i] = -1;
1270 walp[i] = NULL;
1271 walswp[i] = i;
1272 walani[i] = 0;
1274 memset(anic, 0, sizeof(anic));
1275 max_textures = 1;
1278 void R_load (char s[8], int f) {
1279 assert(max_textures < 256);
1280 if (!s[0]) {
1281 walh[max_textures] = -1;
1282 walp[max_textures] = NULL;
1283 } else {
1284 if (strncasecmp(s, "_WATER_", 7) == 0) {
1285 walh[max_textures] = -2;
1286 walp[max_textures] = (void*)((intptr_t)s[7] - '0' + 1);
1287 } else {
1288 walh[max_textures] = F_getresid(s);
1289 walp[max_textures] = V_getvgaimg(walh[max_textures]);
1290 if (f) {
1291 walh[max_textures] |= 0x8000;
1293 if (s[0] == 'S' && s[1] == 'W' && s[4] == '_') {
1294 walswp[max_textures] = 0;
1297 walani[max_textures] = getani(s);
1299 max_textures++;
1302 void R_end_load (void) {
1303 int i, j, k, g;
1304 char s[8];
1305 j = max_textures;
1306 for (i = 1; i < 256 && j < 256; i++) {
1307 if (walswp[i] == 0) {
1308 R_get_name(i, s);
1309 s[5] ^= 1;
1310 g = F_getresid(s) | (walh[i] & 0x8000);
1311 k = 1;
1312 while (k < 256 && walh[k] != g) {
1313 k += 1;
1315 if (k >= 256) {
1316 k = j;
1317 j += 1;
1318 walh[k] = g;
1319 walp[k] = V_getvgaimg(g);
1320 walf[k] = g & 0x8000 ? 1 : 0;
1322 walswp[i] = k;
1323 walswp[k] = i;
1328 void R_loadsky (int sky) {
1329 char s[6];
1330 strcpy(s, "RSKY1");
1331 s[4] = '0' + sky;
1332 M_unlock(horiz);
1333 horiz = V_loadvgaimg(s);
1336 void R_setgamma(int g) {
1337 int t;
1338 g = g < 0 ? 0 : (g > 4 ? 4 : g);
1339 gammaa = g;
1340 for (t = 0; t < 256; ++t) {
1341 std_pal[t][0]=gamcor[gammaa][main_pal[t][0]];
1342 std_pal[t][1]=gamcor[gammaa][main_pal[t][1]];
1343 std_pal[t][2]=gamcor[gammaa][main_pal[t][2]];
1345 Y_set_vga_palette(std_pal);
1348 int R_getgamma (void) {
1349 return gammaa;
1352 void R_toggle_fullscreen (void) {
1353 fullscreen = !fullscreen;
1354 V_toggle();
1357 void R_init () {
1358 int i;
1359 F_loadres(F_getresid("PLAYPAL"), main_pal, 0, 768);
1360 for (i = 0; i < 256; ++i) {
1361 bright[i] = ((int) main_pal[i][0] + main_pal[i][1] + main_pal[i][2]) * 8 / (63 * 3);
1363 F_loadres(F_getresid("MIXMAP"), mixmap, 0, 0x10000);
1364 F_loadres(F_getresid("COLORMAP"), clrmap, 0, 256*12);
1365 logo("V_init: настройка видео\n");
1366 if (V_init() != 0) {
1367 ERR_failinit("Не могу установить видеорежим VGA");
1369 R_setgamma(gammaa);
1370 V_setrect(0, SCRW, 0, SCRH);
1371 // V_setscr(scrbuf);
1372 V_clr(0, SCRW, 0, SCRH, 0);
1373 R_alloc();
1376 void R_done (void) {
1377 V_done();