1 /* Copyright (C) 1996-1997 Aleksey Volynskov
2 * Copyright (C) 2011 Rambo
3 * Copyright (C) 2020 SovietPony
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, version 3 of the License ONLY.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include <stdlib.h> // abs()
45 #include "common/cp866.h"
48 typedef struct rgb_t
{
54 static vgaimg
*scrnh
[3]; // TITLEPIC INTERPIC ENDPIC
55 static vgaimg
*ltn
[2][2];
58 static vgaimg
*smk_spr
[SMSN
];
59 static vgaimg
*smk_fspr
[FLSN
];
61 static vgaimg
*fx_spr
[15];
62 static char fx_sprd
[15];
64 static vgaimg
*wp_spr
[49*2];
65 static char wp_sprd
[49*2];
67 static vgaimg
*item_spr
[58];
68 static char item_sprd
[58];
70 static vgaimg
*plr_spr
[27*2];
71 static char plr_sprd
[27*2];
72 static vgaimg
*plr_wpn
[11][6];
74 static vgaimg
*pl_spr
[2];
75 static vgaimg
*mn_spr
[MN_TN
][29*2];
76 static char mn_sprd
[MN_TN
][29*2];
77 static vgaimg
*mn_fspr
[8];
78 static vgaimg
*mn_sgun
[2];
81 static vgaimg
*sth
[22], *bfh
[160 - '!'], *sfh
[160 - '!'], *stone
, *stone2
, *keys
[3];
82 static int prx
= 0, pry
= 0;
84 static vgaimg
*msklh
[2], *mbarl
, *mbarm
, *mbarr
, *mbaro
, *mslotl
, *mslotm
, *mslotr
;
86 static int gammaa
= 0;
87 static rgb_t
*main_pal
;
88 static byte std_pal
[256][3];
89 static byte gamcor
[5][64]={
95 static int w_o
, w_x
, w_y
;
96 static vgaimg
*walp
[256];
98 static byte walani
[256];
99 static byte walswp
[256];
100 static int anih
[ANIT
][5];
101 static byte anic
[ANIT
];
102 static int max_textures
;
103 static byte w_horiz
= 1;
104 static vgaimg
*horiz
;
106 static int init_screen_width
= 0;
107 static int init_screen_height
= 0;
108 static byte init_screen_full
= 0xFF;
109 static int init_screen_gammaa
= -1;
113 static void *Z_getspr (char n
[4], int s
, int d
, char *dir
) {
114 int h
= F_getsprid(n
, s
, d
, dir
);
115 return V_getvgaimg(h
);
118 static vgaimg
*Z_get_char_image (vgaimg
**img
, int ch
) {
119 ch
= cp866_toupper(ch
);
120 return ch
> 32 && ch
< 160 ? img
[ch
- '!'] : NULL
;
123 static int Z_get_char_width_generic (vgaimg
**img
, int off
, int ch
) {
124 vgaimg
*p
= Z_get_char_image(img
, ch
);
125 return p
== NULL
? off
: p
->w
- 1;
128 static int Z_putch_generic (vgaimg
**img
, int off
, int ch
) {
129 vgaimg
*p
= Z_get_char_image(img
, ch
);
130 int w
= p
== NULL
? off
: p
->w
- 1;
138 static int Z_get_string_width_generic (vgaimg
**img
, int off
, const char *fmt
, va_list ap
) {
141 vsprintf(buf
, fmt
, ap
);
142 for (i
= w
= ww
= 0; buf
[i
]; ++i
) {
150 w
+= Z_get_char_width_generic(img
, off
, (byte
)buf
[i
]);
156 static int Z_printf_generic (vgaimg
**img
, int off
, const char *fmt
, va_list ap
) {
159 vsprintf(buf
, fmt
, ap
);
160 for (i
= w
= ww
= 0; buf
[i
]; ++i
) {
170 w
+= Z_putch_generic(img
, off
, (byte
)buf
[i
]);
176 static void Z_gotoxy (int x
, int y
) {
181 static int Z_get_big_string_width (const char *fmt
, ...) {
184 int w
= Z_get_string_width_generic(bfh
, 12, fmt
, a
);
189 static int Z_printbf (const char *fmt
, ...) {
192 int w
= Z_printf_generic(bfh
, 12, fmt
, a
);
197 static int Z_get_small_string_width (const char *fmt
, ...) {
200 int w
= Z_get_string_width_generic(sfh
, 7, fmt
, a
);
205 static int Z_printsf (const char *fmt
, ...) {
208 int w
=Z_printf_generic(sfh
, 7, fmt
, a
);
213 static void Z_drawspr (int x
, int y
, void *p
, char d
) {
215 V_spr2(x
- w_x
+ WD
/ 2, y
- w_y
+ HT
/ 2 + 1 + w_o
, p
);
217 V_spr(x
- w_x
+ WD
/ 2, y
- w_y
+ HT
/ 2 + 1 + w_o
, p
);
221 static void Z_clrst (void) {
222 V_pic(SCRW
- 120, w_o
, stone
);
223 int y
= ((vgaimg
*)stone
)->h
;
225 V_pic(SCRW
- 120, w_o
+ y
, stone2
);
226 y
+= ((vgaimg
*)stone
)->h
;
230 static void Z_drawstlives (char n
) {
231 V_setrect(SCRW
- 40, 30, w_o
, 40);
232 V_spr(SCRW
- 35, w_o
+ 17, sth
[n
]);
235 static void Z_drawstkeys (byte k
) {
237 V_setrect(SCRW
- 120, 70, w_o
+ 77, 23);
238 for (k
>>= 4, n
= 0, x
= SCRW
- 75; n
< 3; ++n
, k
>>= 1, x
+= 9) {
240 V_spr(x
, w_o
+ 91, keys
[n
]);
245 static void Z_drawstair (int a
) {
246 V_setrect(SCRW
- 120, 120, w_o
+ 49, 2);
251 a
= a
* 100 / MAXAIR
;
252 V_clr(SCRW
- 110, a
, w_o
+ 49, 2, 0xC8);
256 static void Z_drawstprcnt (int y
, int n
) {
259 V_setrect(SCRW
- 120, 70, y
* 19 + 7 + w_o
, 19);
260 sprintf(s
, "%3d%%", n
);
263 for (i
= 0; i
< l
; ++i
, x
+= 14) {
264 if (s
[i
] >='0' && s
[i
] <= '9') {
266 } else if (s
[i
] == '-') {
268 } else if (s
[i
] == '%') {
274 V_spr(x
, y
* 19 + 7 + w_o
, sth
[c
]);
279 static void Z_drawstnum (int n
) {
282 V_setrect(SCRW
- 50, 50, w_o
+ 77, 23);
286 x
= (115 - l
* 14) + SCRW
- 120;
287 for (i
= 0; i
< l
; ++i
, x
+= 14) {
288 if (s
[i
] >= '0' && s
[i
] <= '9') {
290 } else if (s
[i
] == '-') {
292 } else if(s
[i
] == '%') {
298 V_spr(x
, w_o
+ 77 + 5, sth
[c
]);
304 static void Z_drawstwpn (int n
, int a
) {
308 V_setrect(SCRW
- 120, 120, w_o
+ 58, 23);
310 V_spr(SCRW
- 88, w_o
+ 58 + 19, sth
[i
+ 12]);
315 x
= SCRW
- 10 - l
* 14;
316 for (i
= 0; i
< l
; ++i
, x
+= 14) {
317 if (s
[i
] >= '0' && s
[i
] <= '9') {
319 } else if (s
[i
] == '-') {
321 } else if (s
[i
] == '%') {
327 V_spr(x
, w_o
+ 58 + 2, sth
[c
]);
333 static void Z_drawmanspr (int x
, int y
, void *p
, char d
, byte color
) {
335 V_manspr2(x
- w_x
+ WD
/ 2, y
- w_y
+ HT
/ 2 + 1 + w_o
, p
, color
);
337 V_manspr(x
- w_x
+ WD
/ 2, y
- w_y
+ HT
/ 2 + 1 + w_o
, p
, color
);
341 static void Z_drawfld (byte
*fld
, int bg
) {
344 for (y
= 0; y
< FLDH
; y
++) {
345 for (x
= 0; x
< FLDW
; x
++) {
346 int sx
= x
* CELW
- w_x
+ WD
/ 2;
347 int sy
= y
* CELH
- w_y
+ HT
/ 2 + 1 + w_o
;
350 //intptr_t spc = (intptr_t) walp[id];
351 int spc
= R_get_special_id(id
);
352 if (spc
>= 0 && spc
<= 3) {
354 byte
*cmap
= clrmap
+ (spc
+ 7) * 256;
355 V_remap_rect(sx
, sy
, CELW
, CELH
, cmap
);
358 V_pic(sx
, sy
, walp
[id
]);
368 static int gm_tm
= 0; // ???
370 #define SCROLLER_MIDDLE 10
371 #define TEXTFIELD_MIDDLE 2
373 static void get_entry_size (const menu_t
*m
, int i
, int *w
, int *h
) {
382 msg
.type
= GM_GETENTRY
;
383 if (GM_send(m
, i
, &msg
)) {
384 type
= msg
.integer
.i
;
389 case GM_TEXTFIELD_BUTTON
:
390 msg
.type
= GM_GETCAPTION
;
391 if (GM_send(m
, i
, &msg
)) {
392 x
= Z_get_big_string_width("%.*s", msg
.string
.maxlen
, msg
.string
.s
);
395 case GM_SMALL_BUTTON
:
396 msg
.type
= GM_GETCAPTION
;
397 if (GM_send(m
, i
, &msg
)) {
398 x
= Z_get_small_string_width("%.*s", msg
.string
.maxlen
, msg
.string
.s
);
406 msg
.type
= GM_GETSTR
;
407 if (GM_send(m
, i
, &msg
)) {
408 x
+= Z_get_big_string_width("%.*s", msg
.string
.maxlen
, msg
.string
.s
);
412 case GM_SMALL_BUTTON
:
413 msg
.type
= GM_GETSTR
;
414 if (GM_send(m
, i
, &msg
)) {
415 x
+= Z_get_big_string_width("%.*s", msg
.string
.maxlen
, msg
.string
.s
);
420 x
+= (SCROLLER_MIDDLE
+ 2) * 8;
424 case GM_TEXTFIELD_BUTTON
:
425 msg
.type
= GM_GETSTR
;
426 if (GM_send(m
, i
, &msg
)) {
427 x
+= (msg
.string
.maxlen
+ 2) * 8;
429 x
+= (TEXTFIELD_MIDDLE
+ 2) * 8;
441 static void get_menu_size (const menu_t
*m
, int *w
, int *h
) {
445 int i
, n
, x
, y
, xx
, yy
, type
;
448 if (GM_send_this(m
, &msg
)) {
450 type
= msg
.integer
.s
;
453 msg
.type
= GM_GETTITLE
;
454 if (GM_send_this(m
, &msg
)) {
456 case GM_BIG
: x
= Z_get_big_string_width("%.*s", msg
.string
.maxlen
, msg
.string
.s
); break;
457 case GM_SMALL
: x
= Z_get_small_string_width("%.*s", msg
.string
.maxlen
, msg
.string
.s
); break;
461 for (i
= 0; i
< n
; i
++) {
462 get_entry_size(m
, i
, &xx
, &yy
);
474 static int GM_draw (void) {
475 int i
, j
, n
, x
, y
, xoff
, yoff
, cur
, w
, type
, recv
;
476 const menu_t
*m
= GM_get();
479 get_menu_size(m
, &x
, &y
);
480 x
= SCRW
/ 2 - x
/ 2;
481 y
= SCRH
/ 2 - y
/ 2;
484 if (GM_send_this(m
, &msg
)) {
487 type
= msg
.integer
.s
;
488 msg
.type
= GM_GETTITLE
;
489 if (GM_send_this(m
, &msg
)) {
492 case GM_SMALL
: yoff
= 8; Z_printsf("%.*s", msg
.string
.maxlen
, msg
.string
.s
); break;
493 case GM_BIG
: yoff
= 20; Z_printbf("%.*s", msg
.string
.maxlen
, msg
.string
.s
); break;
499 for (i
= 0; i
< n
; i
++) {
500 msg
.type
= GM_GETENTRY
;
501 if (GM_send(m
, i
, &msg
)) {
502 type
= msg
.integer
.i
;
504 if (type
== GM_SMALL_BUTTON
) {
505 Z_gotoxy(x
- 8, y
+ yoff
);
508 V_spr(x
- 25, y
+ yoff
- 8, msklh
[(gm_tm
/ 6) & 1]);
511 msg
.type
= GM_GETCAPTION
;
512 if (GM_send(m
, i
, &msg
)) {
513 Z_gotoxy(x
, y
+ yoff
);
514 if (type
== GM_SMALL_BUTTON
) {
515 xoff
= Z_printsf("%.*s", msg
.string
.maxlen
, msg
.string
.s
);
517 xoff
= Z_printbf("%.*s", msg
.string
.maxlen
, msg
.string
.s
);
524 case GM_SMALL_BUTTON
:
525 msg
.type
= GM_GETSTR
;
526 if (GM_send(m
, i
, &msg
)) {
527 Z_gotoxy(x
+ xoff
, y
+ yoff
);
528 if (type
== GM_SMALL_BUTTON
) {
529 Z_printsf("%.*s", msg
.string
.maxlen
, msg
.string
.s
);
531 Z_printbf("%.*s", msg
.string
.maxlen
, msg
.string
.s
);
534 yoff
+= type
== GM_BUTTON
? 16 : 12;
537 case GM_TEXTFIELD_BUTTON
:
539 msg
.type
= GM_GETSTR
;
540 recv
= GM_send(m
, i
, &msg
);
541 w
= recv
? msg
.string
.maxlen
: TEXTFIELD_MIDDLE
;
542 V_spr(x
+ xoff
, y
+ yoff
, mslotl
);
543 for (j
= 1; j
<= w
; j
++) {
544 V_spr(x
+ xoff
+ j
* 8, y
+ yoff
, mslotm
);
546 V_spr(x
+ xoff
+ j
* 8, y
+ yoff
, mslotr
);
547 Z_gotoxy(x
+ xoff
+ 4, y
+ yoff
- 7);
548 if (input
&& i
== cur
) {
549 Z_printsf("%.*s_", imax
, ibuf
);
551 Z_printsf("%.*s", msg
.string
.maxlen
, msg
.string
.s
);
556 V_spr(x
+ xoff
, y
+ yoff
, mbarl
);
557 for (j
= 1; j
< SCROLLER_MIDDLE
; j
++) {
558 V_spr(x
+ xoff
+ j
* 8, y
+ yoff
, mbarm
);
560 V_spr(x
+ xoff
+ j
* 8, y
+ yoff
, mbarr
);
561 msg
.type
= GM_GETINT
;
562 if (GM_send(m
, i
, &msg
)) {
563 int lev
= (msg
.integer
.i
- msg
.integer
.a
) * ((SCROLLER_MIDDLE
- 2) * 8) / msg
.integer
.b
;
564 V_spr(x
+ xoff
+ lev
+ 8, y
+ yoff
, mbaro
);
580 static void DOT_draw (void) {
582 for (i
= 0; i
< MAXDOT
; i
++) {
584 V_dot(dot
[i
].o
.x
- w_x
+ WD
/ 2, dot
[i
].o
.y
- w_y
+ HT
/ 2 + 1 + w_o
, dot
[i
].c
);
591 static void IT_draw (void) {
593 for (i
= 0; i
< MAXITEM
; ++i
) {
595 if (it
[i
].t
&& it
[i
].s
>= 0) {
596 switch(it
[i
].t
& 0x7FFF) {
598 s
= it
[i
].s
/ 9 + 18;
601 s
= it
[i
].s
/ 9 + 20;
604 s
= it
[i
].s
/ 2 + 22;
607 s
= it
[i
].s
/ 2 + 26;
613 s
= it
[i
].s
/ 2 + (it
[i
].t
- I_SUPER
) * 4 + 35;
615 case I_GOR1
: case I_FCAN
:
616 s
= it
[i
].s
/ 2 + (it
[i
].t
- I_GOR1
) * 3 + 51;
627 s
= (it
[i
].t
& 0x7FFF) - I_KEYR
+ 31;
633 s
= (it
[i
].t
& 0x7FFF) - 1;
637 Z_drawspr(it
[i
].o
.x
, it
[i
].o
.y
, item_spr
[s
], item_sprd
[s
]);
644 static int standspr (player_t
*p
) {
647 } else if (p
->f
& PLF_DOWN
) {
654 static int wpnspr (player_t
*p
) {
657 } else if(p
->f
& PLF_DOWN
) {
664 static void PL_draw (player_t
*p
) {
665 enum {STAND
, GO
, DIE
, SLOP
, DEAD
, MESS
, OUT
, FALL
}; // copypasted from player.c!
666 static int wytab
[] = {-1, -2, -1, 0};
673 if (p
->f
& PLF_FIRE
) {
676 } else if (p
->pain
) {
699 s
= plr_goanim
[p
->s
/ 8];
700 w
= (p
->f
& PLF_FIRE
) ? 'B' : 'A';
702 wy
= 1 + wytab
[s
- 'A'];
706 s
= plr_dieanim
[p
->s
];
709 s
= plr_slopanim
[p
->s
];
719 Z_drawspr(p
->o
.x
+ wx
, p
->o
.y
+ wy
, plr_wpn
[p
->wpn
][w
- 'A'], p
->d
);
722 Z_drawmanspr(p
->o
.x
, p
->o
.y
, plr_spr
[(s
- 'A') * 2 + p
->d
], plr_sprd
[(s
- 'A') * 2 + p
->d
], p
->color
);
726 static void PL_drawst (player_t
*p
) {
728 V_setrect(WD
, 120, w_o
, HT
);
730 if (p
->drawst
& PL_DRAWAIR
) {
731 if (p
->air
< PL_AIR
) {
735 if (p
->drawst
& PL_DRAWLIFE
) {
736 Z_drawstprcnt(0, p
->life
);
738 if (p
->drawst
& PL_DRAWARMOR
) {
739 Z_drawstprcnt(1, p
->armor
);
741 if (p
->drawst
& PL_DRAWWPN
) {
763 Z_drawstwpn(p
->wpn
, i
);
765 if (p
->drawst
& PL_DRAWFRAG
) {
766 Z_drawstnum(p
->frag
);
768 if (p
->drawst
& PL_DRAWKEYS
) {
769 Z_drawstkeys(p
->keys
);
772 if (p
->drawst
& PL_DRAWLIVES
) {
773 Z_drawstlives(p
->lives
);
778 /* --- monster --- */
780 #define MANCOLOR 0xD0
782 static void MN_draw (void) {
783 enum {SLEEP
, GO
, RUN
, CLIMB
, DIE
, DEAD
, ATTACK
, SHOOT
, PAIN
, WAIT
, REVIVE
, RUNOUT
}; // copypasted from monster.c!
785 for (i
= 0; i
< MAXMN
; i
++) {
787 if (mn
[i
].t
>= MN_PL_DEAD
) {
788 Z_drawmanspr(mn
[i
].o
.x
, mn
[i
].o
.y
, pl_spr
[mn
[i
].t
- MN_PL_DEAD
], 0, mn
[i
].d
);
791 if ((mn
[i
].t
!= MN_SOUL
&& mn
[i
].t
!= MN_PAIN
) || mn
[i
].st
!= DEAD
) {
792 if (mn
[i
].t
!= MN_MAN
) {
793 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
]);
795 if (mn
[i
].ap
[mn
[i
].ac
] == 'E' || mn
[i
].ap
[mn
[i
].ac
] == 'F') {
796 Z_drawspr(mn
[i
].o
.x
, mn
[i
].o
.y
, mn_sgun
[mn
[i
].ap
[mn
[i
].ac
] - 'E'], mn
[i
].d
);
798 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
);
801 if (mn
[i
].t
== MN_VILE
&& mn
[i
].st
== SHOOT
) {
802 Z_drawspr(mn
[i
].tx
, mn
[i
].ty
, mn_fspr
[mn
[i
].ac
/ 3], 0);
810 static void WP_draw (void) {
811 enum {NONE
, ROCKET
, PLASMA
, APLASMA
, BALL1
, BALL2
, BALL7
, BFGBALL
, BFGHIT
, MANF
, REVF
, FIRE
}; // copypasted from weapons.c!
813 for (i
= 0; i
< MAXWPN
; ++i
) {
824 d
= wp
[i
].o
.xv
> 0 ? 1 : 0;
872 d
= wp
[i
].o
.xv
>= 0 ? 1 : 0;
876 d
= wp
[i
].o
.xv
>=0 ? 1 : 0;
888 s
= wp
[i
].s
/ 2 + 26;
892 Z_drawspr(wp
[i
].o
.x
, wp
[i
].o
.y
, wp_spr
[s
* 2 + d
], wp_sprd
[s
* 2 + d
]);
899 static void SMK_draw (void) {
901 for (i
= 0; i
< MAXSMOK
; ++i
) {
906 if (s
>= (SMSN
- 1) * 3) {
909 s
= SMSN
- 1 - s
/ 3;
911 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
);
920 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
);
929 static void FX_draw (void) {
930 enum {NONE
, TFOG
, IFOG
, BUBL
}; // copypasted from fx.c
932 for (i
= 0; i
< MAXFX
; ++i
) {
939 s
= fx
[i
].s
/ 2 + 10;
942 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
);
946 Z_drawspr(fx
[i
].x
, fx
[i
].y
, fx_spr
[s
], fx_sprd
[s
]);
953 static void W_adjust (void) {
954 int MAXX
= FLDW
* CELW
- WD
/ 2;
955 int MAXY
= FLDH
* CELH
- HT
/ 2;
956 if (w_x
< WD
/ 2) w_x
= WD
/ 2;
957 if (w_y
< HT
/ 2) w_y
= HT
/ 2;
958 if (w_x
> MAXX
) w_x
= MAXX
;
959 if (w_y
> MAXY
) w_y
= MAXY
;
962 static void W_draw(void) {
964 V_setrect(0, WD
, w_o
+ 1, HT
);
966 vgaimg
*img
= (vgaimg
*)horiz
;
973 V_rotspr(x
, y
, img
, d
);
976 } while (y
< HT
+ w_o
);
983 V_spr(0, w_o
+ lt_ypos
, ltn
[lt_type
][lt_time
< -5 ? 0 : 1]);
985 V_spr2(WD
- 1, w_o
+ lt_ypos
, ltn
[lt_type
][lt_time
< -5 ? 0 : 1]);
990 V_clr(0, WD
, w_o
+ 1, HT
, 0x97);
992 Z_drawfld((byte
*)fldb
, 1);
1003 Z_drawfld((byte
*)fldf
, 0);
1004 if (sky_type
== 2) {
1005 if (lt_time
== -4 || lt_time
== -2) {
1006 V_remap_rect(0, WD
, w_o
+ 1, HT
, clrmap
+ 256 * 11);
1015 static void drawview (player_t
*p
) {
1016 if (p
->looky
< -SCRH
/ 4) {
1017 p
->looky
= -SCRH
/ 4;
1018 } else if (p
->looky
> SCRH
/ 4) {
1019 p
->looky
= SCRH
/ 4;
1022 w_y
= p
->o
.y
- 12 + p
->looky
;
1027 static int get_pu_st (int t
) {
1028 if (t
>= PL_FLASH
) {
1030 } else if((t
/ 9) & 1) {
1037 static void pl_info (player_t
*p
, int y
) {
1038 dword t
= p
->kills
* 10920 / g_time
;
1039 Z_gotoxy(25, y
); Z_printbf("KILLS");
1040 Z_gotoxy(25, y
+ 15); Z_printbf("KPM");
1041 Z_gotoxy(25, y
+ 30); Z_printbf("SECRETS %u / %u", p
->secrets
, sw_secrets
);
1042 Z_gotoxy(255, y
); Z_printbf("%u", p
->kills
);
1043 Z_gotoxy(255, y
+ 15); Z_printbf("%u.%u", t
/ 10, t
% 10);
1046 static void W_act (void) {
1048 if (g_time
% 3 == 0) {
1049 for (i
= 1; i
< 256; i
++) {
1053 if (anih
[a
][anic
[a
]] == -1) {
1056 walp
[i
] = V_getvgaimg(anih
[a
][anic
[a
]]);
1062 void R_draw (void) {
1076 V_pic(0, 0, scrnh
[0]);
1081 V_clr(0, SCRW
, 0, SCRH
, 0);
1082 V_pic(0, 0, scrnh
[2]);
1087 V_clr(0, SCRW
, 0, SCRH
, 0);
1088 V_pic(0, 0, scrnh
[1]);
1090 Z_printbf("LEVEL COMPLETE");
1091 Z_calc_time(g_time
, &hr
, &mn
, &sc
);
1093 Z_printbf("TIME %u:%02u:%02u", hr
, mn
, sc
);
1097 Z_printbf("PLAYER ONE");
1098 Z_gotoxy(80, h
+ 70);
1099 Z_printbf("PLAYER TWO");
1104 pl_info(&pl2
, h
+ 70);
1110 if (g_st
== GS_GAME
) {
1127 h
= get_pu_st(pl1
.invl
) * 6;
1128 } else if (pl1
.pain
< 15) {
1130 } else if (pl1
.pain
< 35) {
1132 } else if (pl1
.pain
< 55) {
1134 } else if (pl1
.pain
< 75) {
1136 } else if (pl1
.pain
< 95) {
1142 V_maptoscr(0, SCRW
- 120, 1, _2pl
? SCRH
/ 2 - 2 : SCRH
- 2, clrmap
+ h
* 256);
1146 h
= get_pu_st(pl2
.invl
) * 6;
1147 } else if (pl2
.pain
< 15) {
1149 } else if (pl2
.pain
< 35) {
1151 } else if (pl2
.pain
< 55) {
1153 } else if (pl2
.pain
< 75) {
1155 } else if (pl2
.pain
< 95) {
1161 V_maptoscr(0, SCRW
- 120, SCRH
/ 2 + 1, SCRH
/ 2 - 2, clrmap
+ h
* 256);
1166 V_setrect(0, SCRW
, 0, SCRH
);
1168 V_copytoscr(0, SCRW
, 0, SCRH
);
1171 void R_alloc (void) {
1174 logo("R_alloc: load graphics\n");
1176 scrnh
[0] = V_loadvgaimg("TITLEPIC");
1177 scrnh
[1] = V_loadvgaimg("INTERPIC");
1178 scrnh
[2] = V_loadvgaimg("ENDPIC");
1179 cd_scr
= M_lock(F_getresid("CD1PIC"));
1180 for (i
= 0; i
< 2; ++i
) {
1181 sprintf(s
, "LTN%c", i
+ '1');
1182 for (j
= 0; j
< 2; ++j
) {
1183 ltn
[i
][j
] = Z_getspr(s
, j
, 0, NULL
);
1187 for (i
= 0; i
< SMSN
; ++i
) {
1188 smk_spr
[i
] = Z_getspr("SMOK", i
, 0, NULL
);
1190 for (i
= 0; i
< FLSN
; ++i
) {
1191 smk_fspr
[i
] = Z_getspr("FLAM", i
, 0, NULL
);
1194 for (i
= 0; i
< 10; ++i
) {
1195 fx_spr
[i
] = Z_getspr("TFOG", i
, 0, fx_sprd
+ i
);
1197 for (; i
< 15; ++i
) {
1198 fx_spr
[i
] = Z_getspr("IFOG", i
- 10, 0, fx_sprd
+ i
);
1201 for (i
= 0; i
< 4; ++i
) {
1202 wp_spr
[i
* 2] = Z_getspr("MISL", i
, 1, wp_sprd
+ i
* 2);
1203 wp_spr
[i
* 2 + 1] = Z_getspr("MISL", i
, 2, wp_sprd
+ i
* 2 + 1);
1205 for (; i
< 6; ++i
) {
1206 wp_spr
[i
* 2] = Z_getspr("PLSS", i
- 4, 1, wp_sprd
+ i
* 2);
1207 wp_spr
[i
* 2 + 1] = Z_getspr("PLSS", i
- 4, 2, wp_sprd
+ i
* 2 + 1);
1209 for (; i
< 11; ++i
) {
1210 wp_spr
[i
* 2] = Z_getspr("PLSE", i
- 6, 1, wp_sprd
+ i
* 2);
1211 wp_spr
[i
* 2 + 1] = Z_getspr("PLSE", i
- 6, 2, wp_sprd
+ i
* 2 + 1);
1213 for (; i
< 13; ++i
) {
1214 wp_spr
[i
* 2] = Z_getspr("APLS", i
- 11, 1, wp_sprd
+ i
* 2);
1215 wp_spr
[i
* 2 + 1] = Z_getspr("APLS", i
- 11, 2, wp_sprd
+ i
* 2 + 1);
1217 for (; i
< 18; ++i
) {
1218 wp_spr
[i
* 2] = Z_getspr("APBX", i
- 13, 1, wp_sprd
+ i
* 2);
1219 wp_spr
[i
* 2 + 1] = Z_getspr("APBX", i
- 13, 2, wp_sprd
+ i
* 2 + 1);
1221 for(; i
< 20; ++i
) {
1222 wp_spr
[i
* 2] = Z_getspr("BFS1", i
- 18, 1, wp_sprd
+ i
* 2);
1223 wp_spr
[i
* 2 + 1] = Z_getspr("BFS1", i
- 18, 2, wp_sprd
+ i
* 2 + 1);
1225 for (; i
< 26; ++i
) {
1226 wp_spr
[i
* 2] = Z_getspr("BFE1", i
- 20, 1, wp_sprd
+ i
* 2);
1227 wp_spr
[i
* 2 + 1] = Z_getspr("BFE1", i
- 20, 2, wp_sprd
+ i
* 2 + 1);
1229 for (; i
< 30; ++i
) {
1230 wp_spr
[i
* 2] = Z_getspr("BFE2", i
- 26, 1, wp_sprd
+ i
* 2);
1231 wp_spr
[i
* 2 + 1] = Z_getspr("BFE2", i
- 26, 2, wp_sprd
+ i
* 2 + 1);
1233 for (; i
< 32; ++i
) {
1234 wp_spr
[i
* 2] = Z_getspr("MISL", i
- 30 + 4, 1, wp_sprd
+ i
* 2);
1235 wp_spr
[i
* 2 + 1] = Z_getspr("MISL", i
- 30 + 4, 2, wp_sprd
+ i
* 2 + 1);
1237 for (; i
< 37; ++i
) {
1238 wp_spr
[i
* 2] = Z_getspr("BAL1", i
- 32, 1, wp_sprd
+ i
* 2);
1239 wp_spr
[i
* 2 + 1] = Z_getspr("BAL1", i
- 32, 2, wp_sprd
+ i
* 2 + 1);
1241 for (; i
< 42; ++i
) {
1242 wp_spr
[i
* 2] = Z_getspr("BAL7", i
- 37, 1, wp_sprd
+ i
* 2);
1243 wp_spr
[i
* 2 + 1] = Z_getspr("BAL7", i
- 37, 2, wp_sprd
+ i
* 2 + 1);
1245 for (; i
< 47; ++i
) {
1246 wp_spr
[i
* 2] = Z_getspr("BAL2", i
- 42, 1, wp_sprd
+ i
* 2);
1247 wp_spr
[i
* 2 + 1] = Z_getspr("BAL2", i
- 42, 2, wp_sprd
+ i
* 2 + 1);
1249 for (; i
< 49; ++i
) {
1250 wp_spr
[i
* 2] = Z_getspr("MANF", i
- 47, 1, wp_sprd
+ i
* 2);
1251 wp_spr
[i
* 2 + 1] = Z_getspr("MANF", i
- 47, 2, wp_sprd
+ i
* 2 + 1);
1254 static char snm
[18][4] = {
1255 "CLIP", "SHEL", "ROCK", "CELL", "AMMO", "SBOX", "BROK", "CELP",
1256 "STIM", "MEDI", "BPAK",
1257 "CSAW", "SHOT", "SGN2", "MGUN", "LAUN", "PLAS", "BFUG"
1259 static char n4
[4][4] = {
1260 "SOUL", "SMRT", "SMGT", "SMBT"
1262 static char n3
[2][4] = {
1265 for (i
= 0; i
< 18; ++i
) {
1266 item_spr
[i
] = Z_getspr(snm
[i
], 0, 0, item_sprd
+ i
);
1268 for (; i
< 20; ++i
) {
1269 item_spr
[i
] = Z_getspr("ARM1", i
- 18, 0, item_sprd
+ i
);
1270 item_spr
[i
+ 2] = Z_getspr("ARM2", i
- 18, 0, item_sprd
+ i
);
1273 for (; i
< 26; ++i
) {
1274 item_spr
[i
] = Z_getspr("MEGA", i
- 22, 0, item_sprd
+ i
);
1276 for (; i
< 30; ++i
) {
1277 item_spr
[i
] = Z_getspr("PINV", i
- 26, 0, item_sprd
+ i
);
1279 item_spr
[30] = Z_getspr("AQUA", 0, 0, item_sprd
+ 30);
1280 item_spr
[31] = Z_getspr("KEYR", 0, 0, item_sprd
+ 31);
1281 item_spr
[32] = Z_getspr("KEYG", 0, 0, item_sprd
+ 32);
1282 item_spr
[33] = Z_getspr("KEYB", 0, 0, item_sprd
+ 33);
1283 item_spr
[34] = Z_getspr("SUIT", 0, 0, item_sprd
+ 34);
1284 for (n
= 35, j
= 0; j
< 4; ++j
) {
1285 for (i
= 0; i
< 4; ++i
, ++n
) {
1286 item_spr
[n
] = Z_getspr(n4
[j
], i
, 0, item_sprd
+ n
);
1289 for (j
= 0; j
< 2; ++j
) {
1290 for (i
= 0; i
< 3; ++i
, ++n
) {
1291 item_spr
[n
] = Z_getspr(n3
[j
], i
, 0, item_sprd
+ n
);
1294 item_spr
[57] = Z_getspr("GUN2", 0, 0, item_sprd
+ 57);
1296 for (i
= 0; i
< 27; ++i
) {
1297 plr_spr
[i
* 2] = Z_getspr("PLAY", i
, 1, plr_sprd
+ i
* 2);
1298 plr_spr
[i
* 2 + 1] = Z_getspr("PLAY", i
, 2, plr_sprd
+ i
* 2 + 1);
1300 strncpy(s
, "PWPx", 4);
1301 for (i
= 1; i
< 11; ++i
) {
1302 s
[3] = (i
< 10 ? '0' : 'A' - 10) + i
;
1303 for (j
= 0; j
< 6; ++j
) {
1304 plr_wpn
[i
][j
] = Z_getspr(s
, j
, 1, NULL
);
1308 static char msn
[MN_TN
][4] = {
1309 "SARG", "TROO", "POSS", "SPOS", "CYBR", "CPOS", "BOSS", "BOS2", "HEAD", "SKUL",
1310 "PAIN", "SPID", "BSPI", "FATT", "SKEL", "VILE", "FISH", "BAR1", "ROBO", "PLAY"
1312 static int mms
[MN_TN
] = {
1313 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,
1314 20*2, 17*2, 29*2, 6*2, 2*2, 17*2, 23*2
1316 mn_sgun
[0] = Z_getspr("PWP4", 0, 1, NULL
);
1317 mn_sgun
[1] = Z_getspr("PWP4", 1, 1, NULL
);
1318 for (j
= 0; j
< MN_TN
; ++j
) {
1319 for (i
= 0; i
< mms
[j
]; ++i
) {
1320 mn_spr
[j
][i
] = Z_getspr(msn
[j
], i
/ 2, (i
& 1) + 1, &mn_sprd
[j
][i
]);
1322 if (j
== MN_BARREL
- 1) {
1323 for (i
= 4; i
< 14; ++i
) {
1324 mn_spr
[j
][i
] = Z_getspr("BEXP", i
/ 2 - 2, (i
& 1) + 1, &mn_sprd
[j
][i
]);
1328 for (i
= 0; i
< 8; ++i
) {
1329 mn_fspr
[i
] = Z_getspr("FIRE", i
, 0, NULL
);
1331 pl_spr
[0] = Z_getspr("PLAY", 'N' - 'A', 0, NULL
);
1332 pl_spr
[1] = Z_getspr("PLAY", 'W' - 'A', 0, NULL
);
1334 static char mnm
[22][8]={
1335 "STTNUM0","STTNUM1","STTNUM2","STTNUM3","STTNUM4",
1336 "STTNUM5","STTNUM6","STTNUM7","STTNUM8","STTNUM9",
1337 "STTMINUS","STTPRCNT",
1338 "FISTA0","CSAWA0","PISTA0","SHOTA0","SGN2A0","MGUNA0","LAUNA0",
1339 "PLASA0","BFUGA0","GUN2A0"
1341 stone
=V_loadvgaimg("STONE");
1342 stone2
=V_loadvgaimg("STONE2");
1343 keys
[0]=V_loadvgaimg("KEYRA0");
1344 keys
[1]=V_loadvgaimg("KEYGA0");
1345 keys
[2]=V_loadvgaimg("KEYBA0");
1346 for (i
= 0; i
< 22; ++i
) {
1347 sth
[i
] = V_loadvgaimg(mnm
[i
]);
1349 strcpy(s
, "STBF_*");
1350 for (i
= '!'; i
< 160; ++i
) {
1352 bfh
[i
- '!'] = V_getvgaimg(F_findres(s
));
1354 for (i
= '!'; i
< 160; ++i
) {
1355 sprintf(s
, "STCFN%03d", i
);
1356 sfh
[i
- '!'] = V_getvgaimg(F_findres(s
));
1358 strcpy(s
, "WINUM*");
1359 for (i
= '0'; i
<= '9'; ++i
) {
1361 bfh
[i
- '!'] = V_loadvgaimg(s
);
1363 bfh
[':' - '!'] = V_loadvgaimg("WICOLON");
1365 msklh
[0] = V_loadvgaimg("M_SKULL1");
1366 msklh
[1] = V_loadvgaimg("M_SKULL2");
1367 mbarl
= V_loadvgaimg("M_THERML");
1368 mbarm
= V_loadvgaimg("M_THERMM");
1369 mbarr
= V_loadvgaimg("M_THERMR");
1370 mbaro
= V_loadvgaimg("M_THERMO");
1371 mslotl
= V_loadvgaimg("M_LSLEFT");
1372 mslotm
= V_loadvgaimg("M_LSCNTR");
1373 mslotr
= V_loadvgaimg("M_LSRGHT");
1375 static char *anm
[ANIT
- 1][5] = {
1376 {"WALL22_1", "WALL23_1", "WALL23_2", NULL
, NULL
},
1377 {"WALL58_1", "WALL58_2", "WALL58_3", NULL
, NULL
},
1378 {"W73A_1", "W73A_2", NULL
, NULL
, NULL
},
1379 {"RP2_1", "RP2_2", "RP2_3", "RP2_4", NULL
}
1381 for (i
= 1; i
< ANIT
; i
++) {
1382 for (j
= 0; anm
[i
- 1][j
]; j
++) {
1383 anih
[i
][j
] = F_getresid(anm
[i
- 1][j
]);
1391 void R_get_name (int n
, char s
[8]) {
1392 if (walh
[n
] == -1) {
1394 } else if (walh
[n
] == -2) {
1395 memcpy(s
, "_WATER_", 8);
1396 s
[7] = (char)((intptr_t)walp
[n
] - 1 + '0');
1398 F_getresname(s
, walh
[n
] & 0x7FFF);
1402 static short getani (char n
[8]) {
1403 if (cp866_strncasecmp(n
, "WALL22_1", 8) == 0) {
1405 } else if (cp866_strncasecmp(n
, "WALL58_1", 8) == 0) {
1407 } else if (cp866_strncasecmp(n
, "W73A_1", 8) == 0) {
1409 } else if (cp866_strncasecmp(n
, "RP2_1", 8) == 0) {
1416 int R_get_special_id (int n
) {
1417 assert(n
>= 0 && n
< 256);
1418 intptr_t x
= (intptr_t)walp
[n
];
1419 return x
>= 0 && x
<= 3 ? x
: -1;
1422 void R_begin_load (void) {
1424 for (i
= 0; i
< 256; i
++) {
1425 if (walp
[i
] != NULL
&& walh
[i
] >= 0) {
1433 memset(anic
, 0, sizeof(anic
));
1437 void R_load (char s
[8]) {
1438 assert(max_textures
< 256);
1440 walh
[max_textures
] = -1;
1441 walp
[max_textures
] = NULL
;
1443 if (cp866_strncasecmp(s
, "_WATER_", 7) == 0) {
1444 walh
[max_textures
] = -2;
1445 walp
[max_textures
] = (void*)((intptr_t)s
[7] - '0' + 1);
1447 walh
[max_textures
] = F_getresid(s
);
1448 walp
[max_textures
] = V_getvgaimg(walh
[max_textures
]);
1449 if (s
[0] == 'S' && s
[1] == 'W' && s
[4] == '_') {
1450 walswp
[max_textures
] = 0;
1453 walani
[max_textures
] = getani(s
);
1458 void R_end_load (void) {
1462 for (i
= 1; i
< 256 && j
< 256; i
++) {
1463 if (walswp
[i
] == 0) {
1468 while (k
< 256 && walh
[k
] != g
) {
1475 walp
[k
] = V_getvgaimg(g
);
1484 void R_loadsky (int sky
) {
1489 horiz
= V_loadvgaimg(s
);
1492 void R_setgamma(int g
) {
1494 g
= g
< 0 ? 0 : (g
> 4 ? 4 : g
);
1496 for (t
= 0; t
< 256; ++t
) {
1497 std_pal
[t
][0] = gamcor
[gammaa
][main_pal
[t
].r
];
1498 std_pal
[t
][1] = gamcor
[gammaa
][main_pal
[t
].g
];
1499 std_pal
[t
][2] = gamcor
[gammaa
][main_pal
[t
].b
];
1501 Y_set_vga_palette(&std_pal
[0][0]);
1504 int R_getgamma (void) {
1508 void R_set_videomode (int w
, int h
, int fullscreen
) {
1511 int was
= Y_videomode_setted();
1512 int res
= Y_set_videomode_software(w
, h
, fullscreen
);
1515 ERR_failinit("Unable to set video mode");
1518 Y_get_videomode(&SCRW
, &SCRH
);
1524 void R_toggle_fullscreen (void) {
1525 Y_set_fullscreen(!Y_get_fullscreen());
1526 fullscreen
= Y_get_fullscreen();
1527 Y_get_videomode(&SCRW
, &SCRH
);
1532 static int video_menu_handler (menu_msg_t
*msg
, const menu_t
*m
, int i
) {
1534 static int w
, h
, fullscreen
;
1535 static char buf
[16];
1538 const videomode_t
*v
;
1539 enum { VIDEOMODE
, FULLSCREEN
, APPLY
, __NUM__
};
1540 static const simple_menu_t sm
= {
1541 GM_BIG
, "Video", NULL
,
1544 { "Fullscreen: ", NULL
},
1548 if (msg
->type
== GM_ENTER
) {
1549 Y_get_videomode(&w
, &h
);
1550 fullscreen
= Y_get_fullscreen();
1551 v
= Y_get_videomode_list_opengl(fullscreen
);
1553 while (vmode
< v
->n
&& v
->modes
[vmode
].w
!= w
&& v
->modes
[vmode
].h
!= h
) {
1557 w
= v
->modes
[vmode
].w
;
1558 h
= v
->modes
[vmode
].h
;
1560 snprintf(buf
, 16, "%ix%i", w
, h
);
1561 buflen
= strlen(buf
);
1564 if (i
== VIDEOMODE
) {
1565 switch (msg
->type
) {
1566 case GM_GETSTR
: return GM_init_str(msg
, buf
, buflen
);
1568 v
= Y_get_videomode_list_opengl(fullscreen
);
1569 vmode
= vmode
+ 1 >= v
->n
? 0 : vmode
+ 1;
1571 w
= v
->modes
[vmode
].w
;
1572 h
= v
->modes
[vmode
].h
;
1574 Y_get_videomode(&w
, &h
);
1576 snprintf(buf
, 16, "%ix%i", w
, h
);
1577 buflen
= strlen(buf
);
1580 } else if (i
== FULLSCREEN
) {
1581 switch (msg
->type
) {
1582 case GM_GETSTR
: return GM_init_str(msg
, fullscreen
? "Yes" : "No ", 3);
1583 case GM_SELECT
: fullscreen
= !fullscreen
; return 1;
1585 } else if (i
== APPLY
) {
1586 switch (msg
->type
) {
1587 case GM_SELECT
: R_set_videomode(w
, h
, fullscreen
); return 1;
1590 return simple_menu_handler(msg
, i
, __NUM__
, &sm
, &cur
);
1593 const menu_t
*R_menu (void) {
1594 static const menu_t m
= { video_menu_handler
};
1598 const cfg_t
*R_args (void) {
1599 static const cfg_t args
[] = {
1600 { "fullscr", &init_screen_full
, Y_SW_ON
},
1601 { "window", &init_screen_full
, Y_SW_OFF
},
1602 { "width", &init_screen_width
, Y_DWORD
},
1603 { "height", &init_screen_height
, Y_DWORD
},
1604 { "gamma", &init_screen_gammaa
, Y_DWORD
},
1605 { NULL
, NULL
, 0 } // end
1610 const cfg_t
*R_conf (void) {
1611 static const cfg_t conf
[] = {
1612 { "sky", &w_horiz
, Y_SW_ON
},
1613 { "fullscreen", &fullscreen
, Y_SW_ON
},
1614 { "screen_width", &SCRW
, Y_DWORD
},
1615 { "screen_height", &SCRH
, Y_DWORD
},
1616 { "gamma", &gammaa
, Y_DWORD
},
1617 { NULL
, NULL
, 0 } // end
1622 static void *R_load_fixed (char *name
, int size
) {
1623 int id
= F_getresid(name
);
1624 if (F_getreslen(id
) < size
) {
1625 ERR_fatal("invalid %s (%i)", name
, F_getreslen(id
));
1632 logo("R_init: initialize software render\n");
1633 main_pal
= R_load_fixed("PLAYPAL", 256 * 3);
1634 clrmap
= R_load_fixed("COLORMAP", 256 * 12);
1635 mixmap
= R_load_fixed("MIXMAP", 256 * 256);
1636 for (i
= 0; i
< 256; ++i
) {
1637 bright
[i
] = ((int)main_pal
[i
].r
+ main_pal
[i
].g
+ main_pal
[i
].b
) * 8 / (63 * 3);
1639 SCRW
= init_screen_width
> 0 ? init_screen_width
: SCRW
;
1640 SCRH
= init_screen_height
> 0 ? init_screen_height
: SCRH
;
1641 fullscreen
= init_screen_full
!= 0xFF ? init_screen_full
: fullscreen
;
1642 gammaa
= init_screen_gammaa
>= 0 ? init_screen_gammaa
: gammaa
;
1643 R_set_videomode(SCRW
, SCRH
, fullscreen
);
1644 V_setrect(0, SCRW
, 0, SCRH
);
1645 V_clr(0, SCRW
, 0, SCRH
, 0);
1649 void R_done (void) {
1654 Y_unset_videomode();
1657 void R_switch_texture (int x
, int y
) {
1658 assert(x
>= 0 && x
< FLDW
);
1659 assert(y
>= 0 && y
< FLDH
);
1660 fldb
[y
][x
] = walswp
[fldb
[y
][x
]];
1663 int R_get_swp (int n
) {
1664 assert(n
>= 0 && n
< 256);