DEADSOFTWARE

renders: fix software render
[flatwaifu.git] / src / soft / render.c
1 #include <string.h>
2 #include <stdarg.h>
3 #include <stdlib.h> // abs()
4 #include <assert.h>
5 #include "glob.h"
6 #include "render.h"
7 #include "view.h"
8 #include "player.h"
9 #include "switch.h"
10 #include "vga.h"
11 #include "menu.h"
12 #include "misc.h"
13 #include "dots.h"
14 #include "items.h"
15 #include "monster.h"
16 #include "weapons.h"
17 #include "smoke.h"
18 #include "fx.h"
19 #include "memory.h"
20 #include "files.h"
21 #include "error.h"
22 #include "game.h"
23 #include "sound.h"
24 #include "music.h"
25 #include "system.h"
27 #include "cp866.h"
29 // game
30 static vgaimg *scrnh[3]; // TITLEPIC INTERPIC ENDPIC
31 static vgaimg *ltn[2][2];
32 static void *cd_scr;
33 // smoke
34 static vgaimg *smk_spr[SMSN];
35 static vgaimg *smk_fspr[FLSN];
36 // fx
37 static vgaimg *fx_spr[15];
38 static char fx_sprd[15];
39 // weapons
40 static vgaimg *wp_spr[49*2];
41 static char wp_sprd[49*2];
42 // items
43 static vgaimg *item_spr[58];
44 static char item_sprd[58];
45 // player
46 static vgaimg *plr_spr[27*2];
47 static char plr_sprd[27*2];
48 static vgaimg *plr_wpn[11][6];
49 // monsters
50 static vgaimg *pl_spr[2];
51 static vgaimg *mn_spr[MN_TN][29*2];
52 static char mn_sprd[MN_TN][29*2];
53 static vgaimg *mn_fspr[8];
54 static vgaimg *mn_sgun[2];
55 // misc
56 #define MAXAIR 1091
57 static vgaimg *sth[22], *bfh[160 - '!'], *sfh[160 - '!'], *stone, *stone2, *keys[3];
58 static int prx = 0, pry = 0;
59 // menu
60 static vgaimg *msklh[2], *mbarl, *mbarm, *mbarr, *mbaro, *mslotl, *mslotm, *mslotr;
61 // low level
62 static int gammaa = 0;
63 static char main_pal[256][3];
64 static char std_pal[256][3];
65 static byte gamcor[5][64]={
66 #include "gamma.dat"
67 };
68 // walls
69 #define ANIT 5
70 static int WD, HT;
71 static int w_o, w_x, w_y;
72 static vgaimg *walp[256];
73 static int walh[256];
74 static byte walani[256];
75 static int anih[ANIT][5];
76 static byte anic[ANIT];
77 static int max_textures;
78 static vgaimg *horiz;
80 /* --- misc --- */
82 static void *Z_getspr (char n[4], int s, int d, char *dir) {
83 int h = F_getsprid(n, s, d);
84 if (dir) {
85 *dir = (h & 0x8000) ? 1 : 0;
86 }
87 return V_getvgaimg(h);
88 }
90 static vgaimg *Z_get_char_image (vgaimg **img, int ch) {
91 ch = cp866_toupper(ch);
92 return ch > 32 && ch < 160 ? img[ch - '!'] : NULL;
93 }
95 static int Z_get_char_width_generic (vgaimg **img, int off, int ch) {
96 vgaimg *p = Z_get_char_image(img, ch);
97 return p == NULL ? off : p->w - 1;
98 }
100 static int Z_putch_generic (vgaimg **img, int off, int ch) {
101 vgaimg *p = Z_get_char_image(img, ch);
102 int w = p == NULL ? off : p->w - 1;
103 if (p != NULL) {
104 V_spr(prx, pry, p);
106 prx += w;
107 return w;
110 static int Z_get_string_width_generic (vgaimg **img, int off, const char *fmt, va_list ap) {
111 int i, w, ww;
112 char buf[80];
113 vsprintf(buf, fmt, ap);
114 for (i = w = ww = 0; buf[i]; ++i) {
115 switch (buf[i]) {
116 case '\n':
117 case '\r':
118 ww = max(w, ww);
119 w = 0;
120 break;
121 default:
122 w += Z_get_char_width_generic(img, off, (byte)buf[i]);
125 return max(w, ww);
128 static int Z_printf_generic (vgaimg **img, int off, const char *fmt, va_list ap) {
129 int i, w, ww;
130 char buf[80];
131 vsprintf(buf, fmt, ap);
132 for (i = w = ww = 0; buf[i]; ++i) {
133 switch (buf[i]) {
134 case '\n':
135 pry += off + 1;
136 case '\r':
137 w = max(w, ww);
138 prx = 0;
139 w = 0;
140 break;
141 default:
142 w += Z_putch_generic(img, off, (byte)buf[i]);
145 return w;
148 static void Z_gotoxy (int x, int y) {
149 prx = x;
150 pry = y;
153 static int Z_get_big_string_width (const char *fmt, ...) {
154 va_list a;
155 va_start(a, fmt);
156 int w = Z_get_string_width_generic(bfh, 12, fmt, a);
157 va_end(a);
158 return w;
161 static int Z_printbf (const char *fmt, ...) {
162 va_list a;
163 va_start(a, fmt);
164 int w = Z_printf_generic(bfh, 12, fmt, a);
165 va_end(a);
166 return w;
169 static int Z_get_small_string_width (const char *fmt, ...) {
170 va_list a;
171 va_start(a, fmt);
172 int w = Z_get_string_width_generic(sfh, 7, fmt, a);
173 va_end(a);
174 return w;
177 static int Z_printsf (const char *fmt, ...) {
178 va_list a;
179 va_start(a, fmt);
180 int w =Z_printf_generic(sfh, 7, fmt, a);
181 va_end(a);
182 return w;
185 static void Z_drawspr (int x, int y, void *p, char d) {
186 if (d) {
187 V_spr2(x - w_x + WD / 2, y - w_y + HT / 2 + 1 + w_o, p);
188 } else {
189 V_spr(x - w_x + WD / 2, y - w_y + HT / 2 + 1 + w_o, p);
193 static void Z_clrst (void) {
194 V_pic(SCRW - 120, w_o, stone);
195 int y = ((vgaimg*)stone)->h;
196 while (y < HT) {
197 V_pic(SCRW - 120, w_o + y, stone2);
198 y += ((vgaimg*)stone)->h;
202 static void Z_drawstlives (char n) {
203 V_setrect(SCRW - 40, 30, w_o, 40);
204 V_spr(SCRW - 35, w_o + 17, sth[n]);
207 static void Z_drawstkeys (byte k) {
208 int x, n;
209 V_setrect(SCRW - 120, 70, w_o + 77, 23);
210 for (k >>= 4, n = 0, x = SCRW - 75; n < 3; ++n, k >>= 1, x += 9) {
211 if (k & 1) {
212 V_spr(x, w_o + 91, keys[n]);
217 static void Z_drawstair (int a) {
218 V_setrect(SCRW - 120, 120, w_o + 49, 2);
219 if (a > 0) {
220 if (a > MAXAIR) {
221 a = MAXAIR;
223 a = a * 100 / MAXAIR;
224 V_clr(SCRW - 110, a, w_o + 49, 2, 0xC8);
228 static void Z_drawstprcnt (int y, int n) {
229 char s[20];
230 int l, i, x, c;
231 V_setrect(SCRW - 120, 70, y * 19 + 7 + w_o, 19);
232 sprintf(s, "%3d%%", n);
233 l = strlen(s);
234 x = SCRW - 110;
235 for (i = 0; i < l; ++i, x += 14) {
236 if (s[i] >='0' && s[i] <= '9') {
237 c = s[i] - '0';
238 } else if (s[i] == '-') {
239 c = 10;
240 } else if (s[i] == '%') {
241 c = 11;
242 } else {
243 c = -1;
245 if (c >= 0) {
246 V_spr(x, y * 19 + 7 + w_o, sth[c]);
251 static void Z_drawstnum (int n) {
252 char s[20];
253 int l, i, x, c;
254 V_setrect(SCRW - 50, 50, w_o + 77, 23);
255 if (g_dm) {
256 sprintf(s, "%d", n);
257 l = strlen(s);
258 x = (115 - l * 14) + SCRW - 120;
259 for (i = 0; i < l; ++i, x += 14) {
260 if (s[i] >= '0' && s[i] <= '9') {
261 c = s[i] - '0';
262 } else if (s[i] == '-') {
263 c = 10;
264 } else if(s[i] == '%') {
265 c = 11;
266 } else {
267 c =- 1;
269 if (c >= 0) {
270 V_spr(x, w_o + 77 + 5, sth[c]);
276 static void Z_drawstwpn (int n, int a) {
277 char s[20];
278 int l, i, x, c;
279 i = n;
280 V_setrect(SCRW - 120, 120, w_o + 58, 23);
281 if (i >= 0) {
282 V_spr(SCRW - 88, w_o + 58 + 19, sth[i + 12]);
284 if (n >= 2) {
285 sprintf(s, "%d", a);
286 l = strlen(s);
287 x = SCRW - 10 - l * 14;
288 for (i = 0; i < l; ++i, x += 14) {
289 if (s[i] >= '0' && s[i] <= '9') {
290 c = s[i] - '0';
291 } else if (s[i] == '-') {
292 c = 10;
293 } else if (s[i] == '%') {
294 c = 11;
295 } else {
296 c = -1;
298 if (c >= 0) {
299 V_spr(x, w_o + 58 + 2, sth[c]);
305 static void Z_drawmanspr (int x, int y, void *p, char d, byte color) {
306 if (d) {
307 V_manspr2(x - w_x + WD / 2, y - w_y + HT / 2 + 1 + w_o, p, color);
308 } else {
309 V_manspr(x - w_x + WD / 2, y - w_y + HT / 2 + 1 + w_o, p, color);
313 static void Z_drawfld (byte *fld, int bg) {
314 byte *p = fld;
315 int x, y;
316 for (y = 0; y < FLDH; y++) {
317 for (x = 0; x < FLDW; x++) {
318 int sx = x * CELW - w_x + WD / 2;
319 int sy = y * CELH - w_y + HT / 2 + 1 + w_o;
320 int id = *p;
321 if (id) {
322 //intptr_t spc = (intptr_t) walp[id];
323 int spc = R_get_special_id(id);
324 if (spc >= 0 && spc <= 3) {
325 if (!bg) {
326 byte *cmap = clrmap + (spc + 7) * 256;
327 V_remap_rect(sx, sy, CELW, CELH, cmap);
329 } else {
330 V_pic(sx, sy, walp[id]);
333 p++;
338 /* --- menu --- */
340 static int gm_tm = 0; // ???
342 #define SCROLLER_MIDDLE 10
343 #define TEXTFIELD_MIDDLE 2
345 static void get_entry_size (const menu_t *m, int i, int *w, int *h) {
346 assert(m != NULL);
347 assert(i >= 0);
348 assert(w != NULL);
349 assert(h != NULL);
350 int x = 0;
351 int y = 0;
352 int type = 0;
353 menu_msg_t msg;
354 msg.type = GM_GETENTRY;
355 assert(GM_send(m, i, &msg));
356 type = msg.integer.i;
357 switch (type) {
358 case GM_BUTTON:
359 case GM_SCROLLER:
360 case GM_TEXTFIELD:
361 case GM_TEXTFIELD_BUTTON:
362 msg.type = GM_GETCAPTION;
363 if (GM_send(m, i, &msg)) {
364 x = Z_get_big_string_width("%.*s", msg.string.maxlen, msg.string.s);
366 break;
367 case GM_SMALL_BUTTON:
368 msg.type = GM_GETCAPTION;
369 if (GM_send(m, i, &msg)) {
370 x = Z_get_small_string_width("%.*s", msg.string.maxlen, msg.string.s);
372 break;
373 default:
374 assert(0);
376 switch (type) {
377 case GM_BUTTON:
378 msg.type = GM_GETSTR;
379 if (GM_send(m, i, &msg)) {
380 x += Z_get_big_string_width("%.*s", msg.string.maxlen, msg.string.s);
382 y = 16;
383 break;
384 case GM_SMALL_BUTTON:
385 msg.type = GM_GETSTR;
386 if (GM_send(m, i, &msg)) {
387 x += Z_get_big_string_width("%.*s", msg.string.maxlen, msg.string.s);
389 y = 12;
390 break;
391 case GM_SCROLLER:
392 x += (SCROLLER_MIDDLE + 2) * 8;
393 y = 16;
394 break;
395 case GM_TEXTFIELD:
396 case GM_TEXTFIELD_BUTTON:
397 msg.type = GM_GETSTR;
398 if (GM_send(m, i, &msg)) {
399 x += (msg.string.maxlen + 2) * 8;
400 } else {
401 x += (TEXTFIELD_MIDDLE + 2) * 8;
403 y = 16;
404 break;
405 default:
406 assert(0);
408 *w = x;
409 *h = y;
412 static void get_menu_size (const menu_t *m, int *w, int *h) {
413 assert(m != NULL);
414 assert(w != NULL);
415 assert(h != NULL);
416 int i, n, x, y, xx, yy, type;
417 menu_msg_t msg;
418 msg.type = GM_QUERY;
419 if (GM_send_this(m, &msg)) {
420 n = msg.integer.b;
421 type = msg.integer.s;
422 x = 0;
423 y = 0;
424 msg.type = GM_GETTITLE;
425 if (GM_send_this(m, &msg)) {
426 switch (type) {
427 case GM_BIG: x = Z_get_big_string_width("%.*s", msg.string.maxlen, msg.string.s); break;
428 case GM_SMALL: x = Z_get_small_string_width("%.*s", msg.string.maxlen, msg.string.s); break;
429 default: assert(0);
432 for (i = 0; i < n; i++) {
433 get_entry_size(m, i, &xx, &yy);
434 x = max(x, xx);
435 y += yy;
437 *w = x;
438 *h = y;
439 } else {
440 *w = 0;
441 *h = 0;
445 static int GM_draw (void) {
446 int i, j, n, x, y, xoff, yoff, cur, w, type, recv;
447 const menu_t *m = GM_get();
448 menu_msg_t msg;
449 if (m != NULL) {
450 get_menu_size(m, &x, &y);
451 x = SCRW / 2 - x / 2;
452 y = SCRH / 2 - y / 2;
453 // --- title ---
454 msg.type = GM_QUERY;
455 if (GM_send_this(m, &msg)) {
456 cur = msg.integer.i;
457 n = msg.integer.a;
458 type = msg.integer.s;
459 msg.type = GM_GETTITLE;
460 if (GM_send_this(m, &msg)) {
461 Z_gotoxy(x, y - 10);
462 switch (type) {
463 case GM_SMALL: yoff = 8; Z_printsf("%.*s", msg.string.maxlen, msg.string.s); break;
464 case GM_BIG: yoff = 20; Z_printbf("%.*s", msg.string.maxlen, msg.string.s); break;
465 default: assert(0);
467 } else {
468 yoff = 0;
470 for (i = 0; i < n; i++) {
471 msg.type = GM_GETENTRY;
472 if (GM_send(m, i, &msg)) {
473 type = msg.integer.i;
474 if (i == cur) {
475 if (type == GM_SMALL_BUTTON) {
476 Z_gotoxy(x - 8, y + yoff);
477 Z_printsf(">");
478 } else {
479 V_spr(x - 25, y + yoff - 8, msklh[(gm_tm / 6) & 1]);
482 msg.type = GM_GETCAPTION;
483 if (GM_send(m, i, &msg)) {
484 Z_gotoxy(x, y + yoff);
485 if (type == GM_SMALL_BUTTON) {
486 xoff = Z_printsf("%.*s", msg.string.maxlen, msg.string.s);
487 } else {
488 xoff = Z_printbf("%.*s", msg.string.maxlen, msg.string.s);
490 } else {
491 xoff = 0;
493 switch (type) {
494 case GM_BUTTON:
495 case GM_SMALL_BUTTON:
496 msg.type = GM_GETSTR;
497 if (GM_send(m, i, &msg)) {
498 Z_gotoxy(x + xoff, y + yoff);
499 if (type == GM_SMALL_BUTTON) {
500 Z_printsf("%.*s", msg.string.maxlen, msg.string.s);
501 } else {
502 Z_printbf("%.*s", msg.string.maxlen, msg.string.s);
505 yoff += type == GM_BUTTON ? 16 : 12;
506 break;
507 case GM_TEXTFIELD:
508 case GM_TEXTFIELD_BUTTON:
509 yoff += 9;
510 msg.type = GM_GETSTR;
511 recv = GM_send(m, i, &msg);
512 w = recv ? msg.string.maxlen : TEXTFIELD_MIDDLE;
513 V_spr(x + xoff, y + yoff, mslotl);
514 for (j = 1; j <= w; j++) {
515 V_spr(x + xoff + j * 8, y + yoff, mslotm);
517 V_spr(x + xoff + j * 8, y + yoff, mslotr);
518 Z_gotoxy(x + xoff + 4, y + yoff - 7);
519 if (input && i == cur) {
520 Z_printsf("%.*s_", imax, ibuf);
521 } else if (recv) {
522 Z_printsf("%.*s", msg.string.maxlen, msg.string.s);
524 yoff += 7;
525 break;
526 case GM_SCROLLER:
527 V_spr(x + xoff, y + yoff, mbarl);
528 for (j = 1; j < SCROLLER_MIDDLE; j++) {
529 V_spr(x + xoff + j * 8, y + yoff, mbarm);
531 V_spr(x + xoff + j * 8, y + yoff, mbarr);
532 msg.type = GM_GETINT;
533 if (GM_send(m, i, &msg)) {
534 int lev = (msg.integer.i - msg.integer.a) * ((SCROLLER_MIDDLE - 2) * 8) / msg.integer.b;
535 V_spr(x + xoff + lev + 8, y + yoff, mbaro);
537 yoff += 16;
538 break;
539 default:
540 assert(0);
546 return m != NULL;
549 /* --- dots --- */
551 static void DOT_draw (void) {
552 int i;
553 for (i = 0; i < MAXDOT; i++) {
554 if (dot[i].t) {
555 V_dot(dot[i].o.x - w_x + WD / 2, dot[i].o.y - w_y + HT / 2 + 1 + w_o, dot[i].c);
560 /* --- items --- */
562 static void IT_draw (void) {
563 int i, s;
564 for (i = 0; i < MAXITEM; ++i) {
565 s = -1;
566 if (it[i].t && it[i].s >= 0) {
567 switch(it[i].t & 0x7FFF) {
568 case I_ARM1:
569 s = it[i].s / 9 + 18;
570 break;
571 case I_ARM2:
572 s = it[i].s / 9 + 20;
573 break;
574 case I_MEGA:
575 s = it[i].s / 2 + 22;
576 break;
577 case I_INVL:
578 s = it[i].s / 2 + 26;
579 break;
580 case I_SUPER:
581 case I_RTORCH:
582 case I_GTORCH:
583 case I_BTORCH:
584 s = it[i].s / 2 + (it[i].t - I_SUPER) * 4 + 35;
585 break;
586 case I_GOR1: case I_FCAN:
587 s = it[i].s / 2 + (it[i].t - I_GOR1) * 3 + 51;
588 break;
589 case I_AQUA:
590 s = 30;
591 break;
592 case I_SUIT:
593 s = 34;
594 break;
595 case I_KEYR:
596 case I_KEYG:
597 case I_KEYB:
598 s = (it[i].t & 0x7FFF) - I_KEYR + 31;
599 break;
600 case I_GUN2:
601 s = 57;
602 break;
603 default:
604 s = (it[i].t & 0x7FFF) - 1;
607 if (s >= 0) {
608 Z_drawspr(it[i].o.x, it[i].o.y, item_spr[s], item_sprd[s]);
613 /* --- player --- */
615 static int standspr (player_t *p) {
616 if (p->f & PLF_UP) {
617 return 'X';
618 } else if (p->f & PLF_DOWN) {
619 return 'Z';
620 } else {
621 return 'E';
625 static int wpnspr (player_t *p) {
626 if (p->f & PLF_UP) {
627 return 'C';
628 } else if(p->f & PLF_DOWN) {
629 return 'E';
630 } else {
631 return 'A';
635 static void PL_draw (player_t *p) {
636 enum {STAND, GO, DIE, SLOP, DEAD, MESS, OUT, FALL}; // copypasted from player.c!
637 static int wytab[] = {-1, -2, -1, 0};
638 int s = 'A';
639 int w = 0;
640 int wx = 0;
641 int wy = 0;
642 switch (p->st) {
643 case STAND:
644 if (p->f & PLF_FIRE) {
645 s = standspr(p) + 1;
646 w = wpnspr(p) + 1;
647 } else if (p->pain) {
648 s = 'G';
649 w = 'A';
650 wx = p->d ? 2 : -2;
651 wy = 1;
652 } else {
653 s = standspr(p);
654 w = wpnspr(p);
656 break;
657 case DEAD:
658 s = 'N';
659 break;
660 case MESS:
661 s = 'W';
662 break;
663 case GO:
664 if (p->pain) {
665 s = 'G';
666 w = 'A';
667 wx = p->d ? 2 : -2;
668 wy = 1;
669 } else {
670 s = plr_goanim[p->s / 8];
671 w = (p->f & PLF_FIRE) ? 'B' : 'A';
672 wx = p->d ? 2 : -2;
673 wy = 1 + wytab[s - 'A'];
675 break;
676 case DIE:
677 s = plr_dieanim[p->s];
678 break;
679 case SLOP:
680 s = plr_slopanim[p->s];
681 break;
682 case OUT:
683 s = 0;
684 break;
686 if (p->wpn == 0) {
687 w = 0;
689 if (w) {
690 Z_drawspr(p->o.x + wx, p->o.y + wy, plr_wpn[p->wpn][w - 'A'], p->d);
692 if (s) {
693 Z_drawmanspr(p->o.x, p->o.y, plr_spr[(s - 'A') * 2 + p->d], plr_sprd[(s - 'A') * 2 + p->d], p->color);
697 static void PL_drawst (player_t *p) {
698 int i;
699 V_setrect(WD, 120, w_o, HT);
700 Z_clrst();
701 if (p->drawst & PL_DRAWAIR) {
702 if (p->air < PL_AIR) {
703 Z_drawstair(p->air);
706 if (p->drawst & PL_DRAWLIFE) {
707 Z_drawstprcnt(0, p->life);
709 if (p->drawst & PL_DRAWARMOR) {
710 Z_drawstprcnt(1, p->armor);
712 if (p->drawst & PL_DRAWWPN) {
713 switch(p->wpn) {
714 case 2:
715 case 5:
716 i = p->ammo;
717 break;
718 case 3:
719 case 4:
720 case 9:
721 i = p->shel;
722 break;
723 case 6:
724 i = p->rock;
725 break;
726 case 10:
727 i = p->fuel;
728 break;
729 case 7:
730 case 8:
731 i = p->cell;
732 break;
734 Z_drawstwpn(p->wpn, i);
736 if (p->drawst & PL_DRAWFRAG) {
737 Z_drawstnum(p->frag);
739 if (p->drawst & PL_DRAWKEYS) {
740 Z_drawstkeys(p->keys);
742 if (!_2pl) {
743 if (p->drawst & PL_DRAWLIVES) {
744 Z_drawstlives(p->lives);
749 /* --- monster --- */
751 #define MANCOLOR 0xD0
753 static void MN_draw (void) {
754 enum {SLEEP, GO, RUN, CLIMB, DIE, DEAD, ATTACK, SHOOT, PAIN, WAIT, REVIVE, RUNOUT}; // copypasted from monster.c!
755 int i;
756 for (i = 0; i < MAXMN; i++) {
757 if (mn[i].t) {
758 if (mn[i].t >= MN_PL_DEAD) {
759 Z_drawmanspr(mn[i].o.x, mn[i].o.y, pl_spr[mn[i].t - MN_PL_DEAD], 0, mn[i].d);
760 continue;
762 if ((mn[i].t != MN_SOUL && mn[i].t != MN_PAIN) || mn[i].st != DEAD) {
763 if (mn[i].t != MN_MAN) {
764 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]);
765 } else {
766 if (mn[i].ap[mn[i].ac] == 'E' || mn[i].ap[mn[i].ac] == 'F') {
767 Z_drawspr(mn[i].o.x, mn[i].o.y, mn_sgun[mn[i].ap[mn[i].ac] - 'E'], mn[i].d);
769 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);
772 if (mn[i].t == MN_VILE && mn[i].st == SHOOT) {
773 Z_drawspr(mn[i].tx, mn[i].ty, mn_fspr[mn[i].ac / 3], 0);
779 /* --- weapon --- */
781 static void WP_draw (void) {
782 enum {NONE, ROCKET, PLASMA, APLASMA, BALL1, BALL2, BALL7, BFGBALL, BFGHIT, MANF, REVF, FIRE}; // copypasted from weapons.c!
783 int i, s, d, x, y;
784 for (i = 0; i < MAXWPN; ++i) {
785 s = -1;
786 d = 0;
787 switch (wp[i].t) {
788 case NONE:
789 default:
790 break;
791 case REVF:
792 case ROCKET:
793 d = wp[i].s;
794 if (d < 2) {
795 d = wp[i].o.xv > 0 ? 1 : 0;
796 x = abs(wp[i].o.xv);
797 y = wp[i].o.yv;
798 s = 0;
799 if (y < 0) {
800 if (-y >= x) {
801 s = 30;
803 } else if (y > 0) {
804 if (y >= x / 2) {
805 s = 31;
808 } else {
809 s = (d - 2) / 2 + 1;
810 d = 0;
812 break;
813 case MANF:
814 s=wp[i].s;
815 if (s >= 2) {
816 s /= 2;
817 break;
819 case PLASMA:
820 case APLASMA:
821 case BALL1:
822 case BALL7:
823 case BALL2:
824 s = wp[i].s;
825 if (s >= 2) {
826 s = s / 2 + 1;
828 switch (wp[i].t) {
829 case PLASMA:
830 s += 4;
831 break;
832 case APLASMA:
833 s += 11;
834 break;
835 case BALL1:
836 s += 32;
837 break;
838 case BALL2:
839 s += 42;
840 break;
841 case BALL7:
842 s += 37;
843 d = wp[i].o.xv >= 0 ? 1 : 0;
844 break;
845 case MANF:
846 s += 47;
847 d= wp[i].o.xv>=0 ? 1 : 0;
848 break;
850 break;
851 case BFGBALL:
852 s = wp[i].s;
853 if (s >= 2) {
854 s = s / 2 + 1;
856 s += 18;
857 break;
858 case BFGHIT:
859 s = wp[i].s / 2 + 26;
860 break;
862 if (s >= 0) {
863 Z_drawspr(wp[i].o.x, wp[i].o.y, wp_spr[s * 2 + d], wp_sprd[s * 2 + d]);
868 /* --- smoke --- */
870 static void SMK_draw (void) {
871 int i, s;
872 for (i = 0; i < MAXSMOK; ++i) {
873 if (sm[i].t) {
874 switch (sm[i].s) {
875 case 0:
876 s = sm[i].t;
877 if (s >= (SMSN - 1) * 3) {
878 s = 0;
879 } else {
880 s = SMSN - 1 - s / 3;
882 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);
883 break;
884 case 1:
885 s = sm[i].t;
886 if (s >= FLSN - 1) {
887 s = 0;
888 } else {
889 s = FLSN - 1 - s;
891 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);
892 break;
898 /* --- fx --- */
900 static void FX_draw (void) {
901 enum {NONE, TFOG, IFOG, BUBL}; // copypasted from fx.c
902 int i, s;
903 for (i = 0; i < MAXFX; ++i) {
904 s = -1;
905 switch (fx[i].t) {
906 case TFOG:
907 s = fx[i].s / 2;
908 break;
909 case IFOG:
910 s = fx[i].s / 2 + 10;
911 break;
912 case BUBL:
913 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);
914 continue;
916 if (s >= 0) {
917 Z_drawspr(fx[i].x, fx[i].y, fx_spr[s], fx_sprd[s]);
922 /* --- view --- */
924 static void W_adjust (void) {
925 int MAXX = FLDW * CELW - WD / 2;
926 int MAXY = FLDH * CELH - HT / 2;
927 if (w_x < WD / 2) w_x = WD / 2;
928 if (w_y < HT / 2) w_y = HT / 2;
929 if (w_x > MAXX) w_x = MAXX;
930 if (w_y > MAXY) w_y = MAXY;
933 static void W_draw(void) {
934 W_adjust();
935 V_setrect(0, WD, w_o + 1, HT);
936 if (w_horiz) {
937 vgaimg *img = (vgaimg*)horiz;
938 int x = 0;
939 int d = 0;
940 do {
941 int y = w_o;
942 d &= ~2;
943 do {
944 V_rotspr(x, y, img, d);
945 y += img->h;
946 d ^= 2;
947 } while (y < HT + w_o);
948 x += img->w;
949 d ^= 1;
950 } while (x < WD);
951 if (sky_type == 2) {
952 if (lt_time < 0) {
953 if (!lt_side) {
954 V_spr(0, w_o + lt_ypos, ltn[lt_type][lt_time < -5 ? 0 : 1]);
955 } else {
956 V_spr2(WD - 1, w_o + lt_ypos, ltn[lt_type][lt_time < -5 ? 0 : 1]);
960 } else {
961 V_clr(0, WD, w_o + 1, HT, 0x97);
963 Z_drawfld((byte*)fldb, 1);
964 DOT_draw();
965 IT_draw();
966 PL_draw(&pl1);
967 if (_2pl) {
968 PL_draw(&pl2);
970 MN_draw();
971 WP_draw();
972 SMK_draw();
973 FX_draw();
974 Z_drawfld((byte*)fldf, 0);
975 if (sky_type == 2) {
976 if (lt_time == -4 || lt_time == -2) {
977 V_remap_rect(0, WD, w_o + 1, HT, clrmap + 256 * 11);
982 /* --- game --- */
984 #define PL_FLASH 90
986 static void drawview (player_t *p) {
987 if (p->looky < -SCRH / 4) {
988 p->looky = -SCRH / 4;
989 } else if (p->looky > SCRH / 4) {
990 p->looky = SCRH / 4;
992 w_x = p->o.x;
993 w_y = p->o.y - 12 + p->looky;
994 W_draw();
995 PL_drawst(p);
998 static int get_pu_st (int t) {
999 if (t >= PL_FLASH) {
1000 return 1;
1001 } else if((t / 9) & 1) {
1002 return 0;
1003 } else {
1004 return 1;
1008 static void pl_info (player_t *p, int y) {
1009 dword t = p->kills * 10920 / g_time;
1010 Z_gotoxy(25, y); Z_printbf("KILLS");
1011 Z_gotoxy(25, y + 15); Z_printbf("KPM");
1012 Z_gotoxy(25, y + 30); Z_printbf("SECRETS %u / %u", p->secrets, sw_secrets);
1013 Z_gotoxy(255, y); Z_printbf("%u", p->kills);
1014 Z_gotoxy(255, y + 15); Z_printbf("%u.%u", t / 10, t % 10);
1017 static void W_act (void) {
1018 int i, a;
1019 if (g_time % 3 == 0) {
1020 for (i = 1; i < 256; i++) {
1021 a = walani[i];
1022 if (a != 0) {
1023 anic[a]++;
1024 if (anih[a][anic[a]] == -1) {
1025 anic[a] = 0;
1027 walp[i] = V_getvgaimg(anih[a][anic[a]]);
1033 void R_draw (void) {
1034 int h;
1035 word hr, mn, sc;
1036 W_act();
1037 switch (g_st) {
1038 case GS_ENDANIM:
1039 case GS_END2ANIM:
1040 case GS_DARKEN:
1041 case GS_BVIDEO:
1042 case GS_EVIDEO:
1043 case GS_END3ANIM:
1044 return;
1045 case GS_TITLE:
1046 V_center(1);
1047 V_pic(0, 0, scrnh[0]);
1048 V_center(0);
1049 break;
1050 case GS_ENDSCR:
1051 V_center(1);
1052 V_clr(0, SCRW, 0, SCRH, 0);
1053 V_pic(0, 0, scrnh[2]);
1054 V_center(0);
1055 break;
1056 case GS_INTER:
1057 V_center(1);
1058 V_clr(0, SCRW, 0, SCRH, 0);
1059 V_pic(0, 0, scrnh[1]);
1060 Z_gotoxy(60, 20);
1061 Z_printbf("LEVEL COMPLETE");
1062 Z_calc_time(g_time, &hr, &mn, &sc);
1063 Z_gotoxy(115, 40);
1064 Z_printbf("TIME %u:%02u:%02u", hr, mn, sc);
1065 h = 60;
1066 if (_2pl) {
1067 Z_gotoxy(80, h);
1068 Z_printbf("PLAYER ONE");
1069 Z_gotoxy(80, h + 70);
1070 Z_printbf("PLAYER TWO");
1071 h += SCRH / 10;
1073 pl_info(&pl1, h);
1074 if (_2pl) {
1075 pl_info(&pl2, h + 70);
1077 V_center(0);
1078 break;
1080 V_center(0);
1081 if (g_st == GS_GAME) {
1082 if (_2pl) {
1083 w_o = 0;
1084 WD = SCRW - 120;
1085 HT = SCRH / 2 - 2;
1086 drawview(&pl1);
1087 w_o = SCRH / 2;
1088 WD = SCRW - 120;
1089 HT = SCRH / 2 - 2;
1090 drawview(&pl2);
1091 } else{
1092 w_o = 0;
1093 WD = SCRW - 120;
1094 HT = SCRH - 2;
1095 drawview(&pl1);
1097 if (pl1.invl) {
1098 h = get_pu_st(pl1.invl) * 6;
1099 } else if (pl1.pain < 15) {
1100 h = 0;
1101 } else if (pl1.pain < 35) {
1102 h = 1;
1103 } else if (pl1.pain < 55) {
1104 h = 2;
1105 } else if (pl1.pain < 75) {
1106 h=3;
1107 } else if (pl1.pain < 95) {
1108 h=4;
1109 } else {
1110 h = 5;
1112 if (h != 0) {
1113 V_maptoscr(0, SCRW - 120, 1, _2pl ? SCRH / 2 - 2 : SCRH - 2, clrmap + h * 256);
1115 if (_2pl) {
1116 if (pl2.invl) {
1117 h = get_pu_st(pl2.invl) * 6;
1118 } else if (pl2.pain < 15) {
1119 h = 0;
1120 } else if (pl2.pain < 35) {
1121 h = 1;
1122 } else if (pl2.pain < 55) {
1123 h = 2;
1124 } else if (pl2.pain < 75) {
1125 h = 3;
1126 } else if (pl2.pain < 95) {
1127 h = 4;
1128 } else {
1129 h = 5;
1131 if (h) {
1132 V_maptoscr(0, SCRW - 120, SCRH / 2 + 1, SCRH / 2 - 2, clrmap + h * 256);
1136 V_center(0);
1137 V_setrect(0, SCRW, 0, SCRH);
1138 GM_draw();
1139 V_copytoscr(0, SCRW, 0, SCRH);
1142 void R_alloc (void) {
1143 int i, j, n;
1144 char s[10];
1145 logo("R_alloc: загрузка графики\n");
1146 // game
1147 scrnh[0] = V_loadvgaimg("TITLEPIC");
1148 scrnh[1] = V_loadvgaimg("INTERPIC");
1149 scrnh[2] = V_loadvgaimg("ENDPIC");
1150 cd_scr = M_lock(F_getresid("CD1PIC"));
1151 for (i = 0; i < 2; ++i) {
1152 sprintf(s, "LTN%c", i + '1');
1153 for (j = 0; j < 2; ++j) {
1154 ltn[i][j] = Z_getspr(s, j, 0, NULL);
1157 // smoke
1158 for (i = 0; i < SMSN; ++i) {
1159 smk_spr[i] = Z_getspr("SMOK", i, 0, NULL);
1161 for (i = 0; i < FLSN; ++i) {
1162 smk_fspr[i] = Z_getspr("FLAM", i, 0, NULL);
1164 // fx
1165 for (i = 0; i < 10; ++i) {
1166 fx_spr[i] = Z_getspr("TFOG", i, 0, fx_sprd + i);
1168 for (; i < 15; ++i) {
1169 fx_spr[i] = Z_getspr("IFOG", i - 10, 0, fx_sprd + i);
1171 // weapons
1172 for (i = 0; i < 4; ++i) {
1173 wp_spr[i * 2] = Z_getspr("MISL", i, 1, wp_sprd + i * 2);
1174 wp_spr[i * 2 + 1] = Z_getspr("MISL", i, 2, wp_sprd + i * 2 + 1);
1176 for (; i < 6; ++i) {
1177 wp_spr[i * 2] = Z_getspr("PLSS", i - 4, 1, wp_sprd + i * 2);
1178 wp_spr[i * 2 + 1] = Z_getspr("PLSS", i - 4, 2, wp_sprd + i * 2 + 1);
1180 for (; i < 11; ++i) {
1181 wp_spr[i * 2] = Z_getspr("PLSE", i - 6, 1, wp_sprd + i * 2);
1182 wp_spr[i * 2 + 1] = Z_getspr("PLSE", i - 6, 2, wp_sprd + i * 2 + 1);
1184 for (; i < 13; ++i) {
1185 wp_spr[i * 2] = Z_getspr("APLS", i - 11, 1, wp_sprd + i * 2);
1186 wp_spr[i * 2 + 1] = Z_getspr("APLS", i - 11, 2, wp_sprd + i * 2 + 1);
1188 for (; i < 18; ++i) {
1189 wp_spr[i * 2] = Z_getspr("APBX", i - 13, 1, wp_sprd + i * 2);
1190 wp_spr[i * 2 + 1] = Z_getspr("APBX", i - 13, 2, wp_sprd + i * 2 + 1);
1192 for(; i < 20; ++i) {
1193 wp_spr[i * 2] = Z_getspr("BFS1", i - 18, 1, wp_sprd + i * 2);
1194 wp_spr[i * 2 + 1] = Z_getspr("BFS1", i - 18, 2, wp_sprd + i * 2 + 1);
1196 for (; i < 26; ++i) {
1197 wp_spr[i * 2] = Z_getspr("BFE1", i - 20, 1, wp_sprd + i * 2);
1198 wp_spr[i * 2 + 1] = Z_getspr("BFE1", i - 20, 2, wp_sprd + i * 2 + 1);
1200 for (; i < 30; ++i) {
1201 wp_spr[i * 2] = Z_getspr("BFE2", i - 26, 1, wp_sprd + i * 2);
1202 wp_spr[i * 2 + 1] = Z_getspr("BFE2", i - 26, 2, wp_sprd + i * 2 + 1);
1204 for (; i < 32; ++i) {
1205 wp_spr[i * 2] = Z_getspr("MISL", i - 30 + 4, 1, wp_sprd + i * 2);
1206 wp_spr[i * 2 + 1] = Z_getspr("MISL", i - 30 + 4, 2, wp_sprd + i * 2 + 1);
1208 for (; i < 37; ++i) {
1209 wp_spr[i * 2] = Z_getspr("BAL1", i - 32, 1, wp_sprd + i * 2);
1210 wp_spr[i * 2 + 1] = Z_getspr("BAL1", i - 32, 2, wp_sprd + i * 2 + 1);
1212 for (; i < 42; ++i) {
1213 wp_spr[i * 2] = Z_getspr("BAL7", i - 37, 1, wp_sprd + i * 2);
1214 wp_spr[i * 2 + 1] = Z_getspr("BAL7", i - 37, 2, wp_sprd + i * 2 + 1);
1216 for (; i < 47; ++i) {
1217 wp_spr[i * 2] = Z_getspr("BAL2", i - 42, 1, wp_sprd + i * 2);
1218 wp_spr[i * 2 + 1] = Z_getspr("BAL2", i - 42, 2, wp_sprd + i * 2 + 1);
1220 for (; i < 49; ++i) {
1221 wp_spr[i * 2] = Z_getspr("MANF", i - 47, 1, wp_sprd + i * 2);
1222 wp_spr[i * 2 + 1] = Z_getspr("MANF", i - 47, 2, wp_sprd + i * 2 + 1);
1224 // items
1225 static char snm[18][4] = {
1226 "CLIP", "SHEL", "ROCK", "CELL", "AMMO", "SBOX", "BROK", "CELP",
1227 "STIM", "MEDI", "BPAK",
1228 "CSAW", "SHOT", "SGN2", "MGUN", "LAUN", "PLAS", "BFUG"
1229 };
1230 static char n4[4][4] = {
1231 "SOUL", "SMRT", "SMGT", "SMBT"
1232 };
1233 static char n3[2][4] = {
1234 "GOR1", "FCAN"
1235 };
1236 for (i = 0; i < 18; ++i) {
1237 item_spr[i] = Z_getspr(snm[i], 0, 0, item_sprd + i);
1239 for (; i < 20; ++i) {
1240 item_spr[i] = Z_getspr("ARM1", i - 18, 0, item_sprd + i);
1241 item_spr[i + 2] = Z_getspr("ARM2", i - 18, 0, item_sprd + i);
1243 i+=2;
1244 for (; i < 26; ++i) {
1245 item_spr[i] = Z_getspr("MEGA", i - 22, 0, item_sprd + i);
1247 for (; i < 30; ++i) {
1248 item_spr[i] = Z_getspr("PINV", i - 26, 0, item_sprd + i);
1250 item_spr[30] = Z_getspr("AQUA", 0, 0, item_sprd + 30);
1251 item_spr[31] = Z_getspr("KEYR", 0, 0, item_sprd + 31);
1252 item_spr[32] = Z_getspr("KEYG", 0, 0, item_sprd + 32);
1253 item_spr[33] = Z_getspr("KEYB", 0, 0, item_sprd + 33);
1254 item_spr[34] = Z_getspr("SUIT", 0, 0, item_sprd + 34);
1255 for (n = 35, j = 0; j < 4; ++j) {
1256 for (i = 0; i < 4; ++i, ++n) {
1257 item_spr[n] = Z_getspr(n4[j], i, 0, item_sprd + n);
1260 for (j = 0; j < 2; ++j) {
1261 for (i = 0; i < 3; ++i, ++n) {
1262 item_spr[n] = Z_getspr(n3[j], i, 0, item_sprd + n);
1265 item_spr[57] = Z_getspr("GUN2", 0, 0, item_sprd + 57);
1266 // player
1267 for (i = 0; i < 27; ++i) {
1268 plr_spr[i * 2] = Z_getspr("PLAY", i, 1, plr_sprd + i * 2);
1269 plr_spr[i * 2 + 1] = Z_getspr("PLAY", i, 2, plr_sprd + i * 2 + 1);
1271 strncpy(s, "PWPx", 4);
1272 for (i = 1; i < 11; ++i) {
1273 s[3] = (i < 10 ? '0' : 'A' - 10) + i;
1274 for (j = 0; j < 6; ++j) {
1275 plr_wpn[i][j] = Z_getspr(s, j, 1, NULL);
1278 // monsters
1279 static char msn[MN_TN][4] = {
1280 "SARG", "TROO", "POSS", "SPOS", "CYBR", "CPOS", "BOSS", "BOS2", "HEAD", "SKUL",
1281 "PAIN", "SPID", "BSPI", "FATT", "SKEL", "VILE", "FISH", "BAR1", "ROBO", "PLAY"
1282 };
1283 static int mms[MN_TN] = {
1284 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,
1285 20*2, 17*2, 29*2, 6*2, 2*2, 17*2, 23*2
1286 };
1287 mn_sgun[0] = Z_getspr("PWP4", 0, 1, NULL);
1288 mn_sgun[1] = Z_getspr("PWP4", 1, 1, NULL);
1289 for (j = 0; j < MN_TN; ++j) {
1290 for (i = 0; i < mms[j]; ++i) {
1291 mn_spr[j][i] = Z_getspr(msn[j], i / 2, (i & 1) + 1, &mn_sprd[j][i]);
1293 if (j == MN_BARREL - 1) {
1294 for (i = 4; i < 14; ++i) {
1295 mn_spr[j][i] = Z_getspr("BEXP", i / 2 - 2, (i & 1) + 1, &mn_sprd[j][i]);
1299 for (i = 0; i < 8; ++i) {
1300 mn_fspr[i] = Z_getspr("FIRE", i, 0, NULL);
1302 pl_spr[0] = Z_getspr("PLAY", 'N' - 'A', 0, NULL);
1303 pl_spr[1] = Z_getspr("PLAY", 'W' - 'A', 0, NULL);
1304 // misc
1305 static char mnm[22][8]={
1306 "STTNUM0","STTNUM1","STTNUM2","STTNUM3","STTNUM4",
1307 "STTNUM5","STTNUM6","STTNUM7","STTNUM8","STTNUM9",
1308 "STTMINUS","STTPRCNT",
1309 "FISTA0","CSAWA0","PISTA0","SHOTA0","SGN2A0","MGUNA0","LAUNA0",
1310 "PLASA0","BFUGA0","GUN2A0"
1311 };
1312 stone=V_loadvgaimg("STONE");
1313 stone2=V_loadvgaimg("STONE2");
1314 keys[0]=V_loadvgaimg("KEYRA0");
1315 keys[1]=V_loadvgaimg("KEYGA0");
1316 keys[2]=V_loadvgaimg("KEYBA0");
1317 for (i = 0; i < 22; ++i) {
1318 sth[i] = V_loadvgaimg(mnm[i]);
1320 strcpy(s, "STBF_*");
1321 for (i = '!'; i < 160; ++i) {
1322 s[5] = i;
1323 bfh[i - '!'] = V_getvgaimg(F_findres(s));
1325 for (i = '!'; i < 160; ++i) {
1326 sprintf(s, "STCFN%03d", i);
1327 sfh[i - '!'] = V_getvgaimg(F_findres(s));
1329 strcpy(s, "WINUM*");
1330 for (i = '0'; i <= '9'; ++i) {
1331 s[5] = i;
1332 bfh[i - '!'] = V_loadvgaimg(s);
1334 bfh[':' - '!'] = V_loadvgaimg("WICOLON");
1335 // menu
1336 msklh[0] = V_loadvgaimg("M_SKULL1");
1337 msklh[1] = V_loadvgaimg("M_SKULL2");
1338 mbarl = V_loadvgaimg("M_THERML");
1339 mbarm = V_loadvgaimg("M_THERMM");
1340 mbarr = V_loadvgaimg("M_THERMR");
1341 mbaro = V_loadvgaimg("M_THERMO");
1342 mslotl = V_loadvgaimg("M_LSLEFT");
1343 mslotm = V_loadvgaimg("M_LSCNTR");
1344 mslotr = V_loadvgaimg("M_LSRGHT");
1345 // walls
1346 static char *anm[ANIT - 1][5] = {
1347 {"WALL22_1", "WALL23_1", "WALL23_2", NULL, NULL},
1348 {"WALL58_1", "WALL58_2", "WALL58_3", NULL, NULL},
1349 {"W73A_1", "W73A_2", NULL, NULL, NULL},
1350 {"RP2_1", "RP2_2", "RP2_3", "RP2_4", NULL}
1351 };
1352 for (i = 1; i < ANIT; i++) {
1353 for (j = 0; anm[i - 1][j]; j++) {
1354 anih[i][j] = F_getresid(anm[i - 1][j]);
1356 for(; j < 5; j++) {
1357 anih[i][j] = -1;
1362 void R_get_name (int n, char s[8]) {
1363 if (walh[n] == -1) {
1364 memset(s, 0, 8);
1365 } else if (walh[n] == -2) {
1366 memcpy(s, "_WATER_", 8);
1367 s[7] = (char)((intptr_t)walp[n] - 1 + '0');
1368 } else {
1369 F_getresname(s, walh[n] & 0x7FFF);
1373 static short getani (char n[8]) {
1374 if (strncasecmp(n, "WALL22_1", 8) == 0) {
1375 return 1;
1376 } else if (strncasecmp(n, "WALL58_1", 8) == 0) {
1377 return 2;
1378 } else if (strncasecmp(n, "W73A_1", 8) == 0) {
1379 return 3;
1380 } else if (strncasecmp(n, "RP2_1", 8) == 0) {
1381 return 4;
1382 } else {
1383 return 0;
1387 int R_get_special_id (int n) {
1388 assert(n >= 0 && n < 256);
1389 intptr_t x = (intptr_t)walp[n];
1390 return x >= 0 && x <= 3 ? x : -1;
1393 void R_begin_load (void) {
1394 int i;
1395 for (i = 0; i < 256; i++) {
1396 if (walp[i] != NULL && walh[i] >= 0) {
1397 M_unlock(walp[i]);
1399 walh[i] = -1;
1400 walp[i] = NULL;
1401 walswp[i] = i;
1402 walani[i] = 0;
1404 memset(anic, 0, sizeof(anic));
1405 max_textures = 1;
1408 void R_load (char s[8], int f) {
1409 assert(max_textures < 256);
1410 if (!s[0]) {
1411 walh[max_textures] = -1;
1412 walp[max_textures] = NULL;
1413 } else {
1414 if (strncasecmp(s, "_WATER_", 7) == 0) {
1415 walh[max_textures] = -2;
1416 walp[max_textures] = (void*)((intptr_t)s[7] - '0' + 1);
1417 } else {
1418 walh[max_textures] = F_getresid(s);
1419 walp[max_textures] = V_getvgaimg(walh[max_textures]);
1420 if (f) {
1421 walh[max_textures] |= 0x8000;
1423 if (s[0] == 'S' && s[1] == 'W' && s[4] == '_') {
1424 walswp[max_textures] = 0;
1427 walani[max_textures] = getani(s);
1429 max_textures++;
1432 void R_end_load (void) {
1433 int i, j, k, g;
1434 char s[8];
1435 j = max_textures;
1436 for (i = 1; i < 256 && j < 256; i++) {
1437 if (walswp[i] == 0) {
1438 R_get_name(i, s);
1439 s[5] ^= 1;
1440 g = F_getresid(s) | (walh[i] & 0x8000);
1441 k = 1;
1442 while (k < 256 && walh[k] != g) {
1443 k += 1;
1445 if (k >= 256) {
1446 k = j;
1447 j += 1;
1448 walh[k] = g;
1449 walp[k] = V_getvgaimg(g);
1450 walf[k] = g & 0x8000 ? 1 : 0;
1452 walswp[i] = k;
1453 walswp[k] = i;
1458 void R_loadsky (int sky) {
1459 char s[6];
1460 strcpy(s, "RSKY1");
1461 s[4] = '0' + sky;
1462 M_unlock(horiz);
1463 horiz = V_loadvgaimg(s);
1466 void R_setgamma(int g) {
1467 int t;
1468 g = g < 0 ? 0 : (g > 4 ? 4 : g);
1469 gammaa = g;
1470 for (t = 0; t < 256; ++t) {
1471 std_pal[t][0]=gamcor[gammaa][main_pal[t][0]];
1472 std_pal[t][1]=gamcor[gammaa][main_pal[t][1]];
1473 std_pal[t][2]=gamcor[gammaa][main_pal[t][2]];
1475 Y_set_vga_palette(std_pal);
1478 int R_getgamma (void) {
1479 return gammaa;
1482 void R_set_videomode (int w, int h, int fullscreen) {
1483 assert(w > 0);
1484 assert(h > 0);
1485 int was = Y_videomode_setted();
1486 int res = Y_set_videomode_software(w, h, fullscreen);
1487 if (res == 0) {
1488 if (was == 0) {
1489 ERR_failinit("Unable to set video mode");
1491 } else {
1492 Y_get_videomode(&SCRW, &SCRH);
1493 V_update_buffer();
1494 R_setgamma(gammaa);
1498 void R_toggle_fullscreen (void) {
1499 Y_set_fullscreen(!Y_get_fullscreen());
1500 fullscreen = Y_get_fullscreen();
1501 Y_get_videomode(&SCRW, &SCRH);
1502 V_update_buffer();
1503 R_setgamma(gammaa);
1506 static int video_menu_handler (menu_msg_t *msg, const menu_t *m, void *data, int i) {
1507 static int cur;
1508 static int w, h, fullscreen;
1509 static char buf[16];
1510 static int buflen;
1511 static int vmode;
1512 const videomode_t *v;
1513 enum { VIDEOMODE, FULLSCREEN, APPLY, __NUM__ };
1514 static const simple_menu_t sm = {
1515 GM_BIG, "Video", NULL,
1517 { "Mode: ", NULL },
1518 { "Fullscreen: ", NULL },
1519 { "Apply ", NULL },
1521 };
1522 if (msg->type == GM_ENTER) {
1523 Y_get_videomode(&w, &h);
1524 fullscreen = Y_get_fullscreen();
1525 v = Y_get_videomode_list_opengl(fullscreen);
1526 vmode = 0;
1527 while (vmode < v->n && v->modes[vmode].w != w && v->modes[vmode].h != h) {
1528 vmode += 1;
1530 if (vmode < v->n) {
1531 w = v->modes[vmode].w;
1532 h = v->modes[vmode].h;
1534 snprintf(buf, 16, "%ix%i", w, h);
1535 buflen = strlen(buf);
1536 return 1;
1538 if (i == VIDEOMODE) {
1539 switch (msg->type) {
1540 case GM_GETSTR: return GM_init_str(msg, buf, buflen);
1541 case GM_SELECT:
1542 v = Y_get_videomode_list_opengl(fullscreen);
1543 vmode = vmode + 1 >= v->n ? 0 : vmode + 1;
1544 if (v->n > 0) {
1545 w = v->modes[vmode].w;
1546 h = v->modes[vmode].h;
1547 } else {
1548 Y_get_videomode(&w, &h);
1550 snprintf(buf, 16, "%ix%i", w, h);
1551 buflen = strlen(buf);
1552 return 1;
1554 } else if (i == FULLSCREEN) {
1555 switch (msg->type) {
1556 case GM_GETSTR: return GM_init_str(msg, fullscreen ? "Yes" : "No ", 3);
1557 case GM_SELECT: fullscreen = !fullscreen; return 1;
1559 } else if (i == APPLY) {
1560 switch (msg->type) {
1561 case GM_SELECT: R_set_videomode(w, h, fullscreen); return 1;
1564 return simple_menu_handler(msg, i, __NUM__, &sm, &cur);
1567 static const menu_t video_menu = {
1568 NULL, &video_menu_handler
1569 };
1571 const menu_t *R_menu (void) {
1572 return &video_menu;
1575 void R_init () {
1576 int i;
1577 logo("R_init: initialize software render\n");
1578 F_loadres(F_getresid("PLAYPAL"), main_pal, 0, 768);
1579 for (i = 0; i < 256; ++i) {
1580 bright[i] = ((int) main_pal[i][0] + main_pal[i][1] + main_pal[i][2]) * 8 / (63 * 3);
1582 F_loadres(F_getresid("MIXMAP"), mixmap, 0, 0x10000);
1583 F_loadres(F_getresid("COLORMAP"), clrmap, 0, 256*12);
1584 R_set_videomode(SCRW, SCRH, fullscreen);
1585 V_setrect(0, SCRW, 0, SCRH);
1586 V_clr(0, SCRW, 0, SCRH, 0);
1587 R_alloc();
1590 void R_done (void) {
1591 buffer = NULL;
1592 buf_w = 0;
1593 buf_h = 0;
1594 pitch = 0;
1595 Y_unset_videomode();