d6f021de16a267021e347dfc8cda8b4c3b6eb76f
1 /* Copyright (C) 2020 SovietPony
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, version 3 of the License ONLY.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
38 #include "switch.h" // sw_secrets
43 # include <OpenGL/gl.h>
52 #define VGA_TRANSPARENT_COLOR 0
53 #define DEFAULT_SKY_COLOR 0x97
55 #define PLAYER_COLOR_OFFSET 7
61 typedef struct vgaimg
{
78 struct node
*left
, *right
;
84 typedef struct cache
{
90 typedef struct image
{
100 static float screen_scale
;
101 static int screen_width
= 320;
102 static int screen_height
= 200;
103 static byte screen_full
= 0;
104 static int init_screen_width
= 0;
105 static int init_screen_height
= 0;
106 static byte init_screen_full
= 0xFF;
107 static rgb playpal
[256];
108 static byte bright
[256];
109 static GLuint lastTexture
;
113 static image scrnh
[3]; // TITLEPIC INTERPIC ENDPIC
114 static image ltn
[2][2];
117 static image smk_spr
[SMSN
];
118 static image smk_fspr
[FLSN
];
121 static image fx_spr
[15];
122 static char fx_sprd
[15];
125 static image wp_spr
[49*2];
126 static char wp_sprd
[49*2];
129 static image item_spr
[58];
130 static char item_sprd
[58];
133 static image plr_spr
[27*2];
134 static image plr_msk
[27*2];
135 static char plr_sprd
[27*2];
136 static image plr_wpn
[11][6];
139 static image pl_spr
[2];
140 static image pl_msk
[2];
141 static image mn_spr
[MN_TN
][29*2];
142 static image mn_man_msk
[29*2];
143 static char mn_sprd
[MN_TN
][29*2];
144 static image mn_fspr
[8];
145 static image mn_sgun
[2];
148 static image sth
[22];
149 static image bfh
[160 - '!'];
150 static image sfh
[160 - '!'];
153 static image keys
[3];
159 static image msklh
[2];
169 static const char *anm
[ANIT
- 1][5] = {
170 {"WALL22_1", "WALL23_1", "WALL23_2", NULL
, NULL
},
171 {"WALL58_1", "WALL58_2", "WALL58_3", NULL
, NULL
},
172 {"W73A_1", "W73A_2", NULL
, NULL
, NULL
},
173 {"RP2_1", "RP2_2", "RP2_3", "RP2_4", NULL
}
175 static byte w_horiz
= 1;
176 static int max_wall_width
;
177 static int max_wall_height
;
178 static int max_textures
;
179 static image walp
[256];
180 static byte walswp
[256];
181 static byte walani
[256];
182 static image anip
[ANIT
][5];
183 static byte anic
[ANIT
];
188 // https://blackpawn.com/texts/lightmaps/
189 static node
*R_node_alloc (node
*p
, int w
, int h
) {
195 node
*n
= R_node_alloc(p
->left
, w
, h
);
196 return n
? n
: R_node_alloc(p
->right
, w
, h
);
198 int pw
= p
->r
- p
->l
+ 1;
199 int ph
= p
->b
- p
->t
+ 1;
200 if (p
->leaf
|| pw
< w
|| ph
< h
) {
202 } else if (pw
== w
&& ph
== h
) {
206 p
->left
= malloc(sizeof(node
));
207 p
->right
= malloc(sizeof(node
));
208 if (pw
- w
> ph
- h
) {
239 return R_node_alloc(p
->left
, w
, h
);
244 static int R_node_have_leaf (node
*n
) {
245 return n
&& (n
->leaf
|| R_node_have_leaf(n
->left
) || R_node_have_leaf(n
->right
));
248 static void R_node_free_recursive (node
*n
) {
250 R_node_free_recursive(n
->left
);
251 R_node_free_recursive(n
->right
);
256 static void R_node_free (node
*n
) {
258 //logo("free node %p {%i:%i:%i:%i}\n", n, n->l, n->t, n->r, n->b);
260 assert(n
->left
== NULL
);
261 assert(n
->right
== NULL
);
266 assert(p
->leaf
== 0);
269 if (R_node_have_leaf(p
) == 0) {
270 R_node_free_recursive(p
->left
);
272 R_node_free_recursive(p
->right
);
282 static void R_cache_get_max_texture_size (int *w
, int *h
) {
284 glGetIntegerv(GL_MAX_TEXTURE_SIZE
, &size
);
285 size
= min(max(size
, 0), 512); // more can be buggy on older hardware
290 static void R_gl_bind_texture (GLuint id
) {
291 if (id
!= lastTexture
) {
292 glBindTexture(GL_TEXTURE_2D
, id
);
296 static cache
*R_cache_new (void) {
300 R_cache_get_max_texture_size(&w
, &h
);
302 glGenTextures(1, &id
);
304 R_gl_bind_texture(id
);
305 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
306 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
307 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, w
, h
, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, NULL
);
308 c
= malloc(sizeof(cache
));
316 glDeleteTextures(1, &id
);
320 //logo("new cache %p\n", c);
324 static void R_cache_free (cache
*root
, int freetexture
) {
329 R_node_free_recursive(c
->root
.left
);
330 R_node_free_recursive(c
->root
.right
);
331 if (freetexture
&& c
->id
!= 0) {
332 glDeleteTextures(1, &c
->id
);
339 static node
*R_cache_alloc (cache
*root
, int w
, int h
) {
341 assert(w
> 0 && h
> 0);
346 R_cache_get_max_texture_size(&maxw
, &maxh
);
347 if (w
<= maxw
&& h
<= maxh
) {
349 n
= R_node_alloc(&c
->root
, w
, h
);
361 n
= R_node_alloc(&c
->root
, w
, h
);
370 //logo("new node %p {%i:%i:%i:%i}\n", n, n->l, n->t, n->r, n->b);
372 logo("new node failed {%i:%i}\n", w
, h
);
377 static void R_cache_update (node
*n
, const void *data
, int x
, int y
, int w
, int h
) {
384 assert(n
->l
+ x
+ w
- 1 <= n
->r
);
385 assert(n
->t
+ y
+ h
- 1 <= n
->b
);
386 R_gl_bind_texture(n
->base
->id
);
387 glTexSubImage2D(GL_TEXTURE_2D
, 0, n
->l
+ x
, n
->t
+ y
, w
, h
, GL_RGBA
, GL_UNSIGNED_BYTE
, data
);
390 /* Generic helpers */
392 static void R_init_playpal (void) {
394 byte
*vgapal
= M_lock(F_getresid("PLAYPAL"));
395 for (i
= 0; i
< 256; i
++) {
397 .r
= vgapal
[i
* 3 + 0] * 255 / 63,
398 .g
= vgapal
[i
* 3 + 1] * 255 / 63,
399 .b
= vgapal
[i
* 3 + 2] * 255 / 63,
401 bright
[i
] = ((int)vgapal
[i
* 3 + 0] + vgapal
[i
* 3 + 1] + vgapal
[i
* 3 + 2]) * 8 / (63 * 3);
406 static vgaimg
*R_getvga (int id
) {
407 int loaded
= M_was_locked(id
);
408 vgaimg
*v
= M_lock(id
);
409 if (v
!= NULL
&& !loaded
) {
410 v
->w
= short2host(v
->w
);
411 v
->h
= short2host(v
->h
);
412 v
->x
= short2host(v
->x
);
413 v
->y
= short2host(v
->y
);
418 static rgba
*R_extract_flame_spr (vgaimg
*v
) {
419 static const byte flametab
[16] = {
420 0xBC, 0xBA, 0xB8, 0xB6, 0xB4, 0xB2, 0xB0, 0xD5,
421 0xD6, 0xD7, 0xA1, 0xA0, 0xE3, 0xE2, 0xE1, 0xE0
424 rgba
*s
= malloc(v
->w
* v
->h
* sizeof(rgba
));
426 for (j
= 0; j
< v
->h
; j
++) {
427 for (i
= 0; i
< v
->w
; i
++) {
428 int k
= j
* v
->w
+ i
;
429 byte c
= v
->data
[k
] + bright
[DEFAULT_SKY_COLOR
];
431 .r
= playpal
[flametab
[c
]].r
,
432 .g
= playpal
[flametab
[c
]].g
,
433 .b
= playpal
[flametab
[c
]].b
,
434 .a
= v
->data
[k
] == VGA_TRANSPARENT_COLOR
? 0x00 : 0xFF,
442 static rgba
*R_extract_smoke_spr (vgaimg
*v
) {
444 rgba
*s
= malloc(v
->w
* v
->h
* sizeof(rgba
));
446 for (j
= 0; j
< v
->h
; j
++) {
447 for (i
= 0; i
< v
->w
; i
++) {
448 int k
= j
* v
->w
+ i
;
449 byte c
= ((v
->data
[k
] + bright
[DEFAULT_SKY_COLOR
]) + 0x60) ^ 0x0F;
450 byte a
= 0xFF - ((int)playpal
[c
].r
+ playpal
[c
].g
+ playpal
[c
].b
) / 3;
455 .a
= v
->data
[k
] == VGA_TRANSPARENT_COLOR
? 0x00 : a
,
463 static rgba
*R_extract_mask_spr (vgaimg
*v
) {
465 rgba
*s
= malloc(v
->w
* v
->h
* sizeof(rgba
));
467 for (j
= 0; j
< v
->h
; j
++) {
468 for (i
= 0; i
< v
->w
; i
++) {
469 int k
= j
* v
->w
+ i
;
471 if (c
>= 0x70 && c
<= 0x7F) {
472 byte mask
= c
- 0x70;
473 mask
= 0xFF - ((mask
<< 4) | mask
);
494 static rgba
*R_extract_rgba_spr (vgaimg
*v
) {
496 rgba
*s
= malloc(v
->w
* v
->h
* sizeof(rgba
));
498 for (j
= 0; j
< v
->h
; j
++) {
499 for (i
= 0; i
< v
->w
; i
++) {
500 int k
= j
* v
->w
+ i
;
506 .a
= c
== VGA_TRANSPARENT_COLOR
? 0x00 : 0xFF,
516 static image
R_gl_create_image (const rgba
*buf
, int w
, int h
) {
517 node
*n
= R_cache_alloc(root
, w
, h
);
519 R_cache_update(n
, buf
, 0, 0, w
, h
);
529 static image
R_gl_get_special_image (int id
, rgba
*(*fn
)(vgaimg
*)) {
532 //F_getresname(name, id);
533 //logo("load image: %.8s\n", name);
534 vgaimg
*v
= R_getvga(id
);
536 rgba
*buf
= (*fn
)(v
);
537 img
= R_gl_create_image(buf
, v
->w
, v
->h
);
551 static image
R_gl_getimage (int id
) {
552 return R_gl_get_special_image(id
, &R_extract_rgba_spr
);
555 static image
R_gl_loadimage (const char name
[8]) {
556 return R_gl_getimage(F_getresid(name
));
559 static image
R_gl_get_special_spr (const char n
[4], int s
, int d
, rgba
*(*fn
)(vgaimg
*)) {
560 return R_gl_get_special_image(F_getsprid(n
, s
, d
, NULL
), fn
);
563 static void R_gl_free_image (image
*img
) {
564 if (img
->n
!= NULL
&& img
->res
>= 0) {
571 static void R_gl_draw_quad (int x
, int y
, int w
, int h
) {
573 glVertex2i(x
+ w
, y
);
575 glVertex2i(x
, y
+ h
);
576 glVertex2i(x
+ w
, y
+ h
);
580 static void R_gl_draw_textured (image
*img
, int x
, int y
, int w
, int h
, int flip
) {
582 GLfloat nw
= img
->n
->base
->root
.r
+ 1;
583 GLfloat nh
= img
->n
->base
->root
.b
+ 1;
584 GLfloat ax
= (flip
? img
->n
->l
: img
->n
->r
+ 1) / nw
;
585 GLfloat bx
= (flip
? img
->n
->r
+ 1 : img
->n
->l
) / nh
;
586 GLfloat ay
= (img
->n
->t
) / nw
;
587 GLfloat by
= (img
->n
->b
+ 1) / nh
;
588 R_gl_bind_texture(img
->n
->base
->id
);
589 glEnable(GL_TEXTURE_2D
);
591 glTexCoord2f(ax
, ay
); glVertex2i(x
+ w
, y
);
592 glTexCoord2f(bx
, ay
); glVertex2i(x
, y
);
593 glTexCoord2f(bx
, by
); glVertex2i(x
, y
+ h
);
594 glTexCoord2f(ax
, by
); glVertex2i(x
+ w
, y
+ h
);
597 glColor3ub(255, 0, 0);
599 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
600 glDisable(GL_TEXTURE_2D
);
601 R_gl_draw_quad(x
, y
, w
, h
);
605 /* fit image into rectangle without applying offset and transparency */
606 static void R_gl_draw_image_ext (image
*img
, int x
, int y
, int w
, int h
) {
608 glColor3ub(255, 255, 255);
609 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
610 R_gl_draw_textured(img
, x
, y
, w
, h
, 0);
613 /* draw sprite with offset and coloring */
614 static void R_gl_draw_image_color (image
*img
, int x
, int y
, int flip
) {
615 int xx
= flip
? x
- img
->w
+ img
->x
: x
- img
->x
;
617 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
618 R_gl_draw_textured(img
, xx
, y
- img
->y
, img
->w
, img
->h
, flip
);
621 /* draw sprite with offset */
622 static void R_gl_draw_image (image
*img
, int x
, int y
, int flip
) {
623 glColor3ub(255, 255, 255);
624 R_gl_draw_image_color(img
, x
, y
, flip
);
627 static void R_gl_set_color (byte c
) {
628 glColor3ub(playpal
[c
].r
, playpal
[c
].g
, playpal
[c
].b
);
631 static void R_gl_setclip (int x
, int y
, int w
, int h
) {
632 glScissor(x
* screen_scale
, (SCRH
- h
- y
) * screen_scale
, w
* screen_scale
, h
* screen_scale
);
635 static void R_gl_setmatrix (void) {
636 SCRW
= screen_width
/ screen_scale
;
637 SCRH
= screen_height
/ screen_scale
;
638 glScissor(0, 0, screen_width
, screen_height
);
639 glViewport(0, 0, screen_width
, screen_height
);
640 glMatrixMode(GL_PROJECTION
);
642 glOrtho(0, SCRW
, SCRH
, 0, 0, 1);
643 glMatrixMode(GL_MODELVIEW
);
649 static image
Z_getspr (const char n
[4], int s
, int d
, char *dir
) {
650 int h
= F_getsprid(n
, s
, d
, dir
);
651 return R_gl_getimage(h
);
654 static image
*Z_get_char_image (image
*img
, int ch
) {
656 ch
= cp866_toupper(ch
);
657 if (ch
> 32 && ch
< 160) {
663 static int Z_get_char_width_generic (image
*img
, int off
, int ch
) {
664 image
*p
= Z_get_char_image(img
, ch
);
665 return p
== NULL
? off
: p
->w
- 1;
668 static int Z_putch_generic (image
*img
, int off
, int ch
) {
669 image
*p
= Z_get_char_image(img
, ch
);
670 int w
= p
== NULL
? off
: p
->w
- 1;
671 if (p
!= NULL
&& p
->n
!= NULL
) {
672 R_gl_draw_image(p
, prx
, pry
, 0);
678 static int Z_get_string_width_generic (image
*img
, int off
, const char *fmt
, va_list ap
) {
681 vsprintf(buf
, fmt
, ap
);
682 for (i
= w
= ww
= 0; buf
[i
]; ++i
) {
690 w
+= Z_get_char_width_generic(img
, off
, (byte
)buf
[i
]);
696 static int Z_printf_generic (image
*img
, int off
, const char *fmt
, va_list ap
) {
699 vsprintf(buf
, fmt
, ap
);
700 for (i
= w
= ww
= 0; buf
[i
]; ++i
) {
710 w
+= Z_putch_generic(img
, off
, (byte
)buf
[i
]);
716 static void Z_gotoxy (int x
, int y
) {
721 static int Z_get_big_string_width (const char *fmt
, ...) {
724 int w
= Z_get_string_width_generic(bfh
, 12, fmt
, a
);
729 static int Z_printbf (const char *fmt
, ...) {
732 int w
= Z_printf_generic(bfh
, 12, fmt
, a
);
737 static int Z_get_small_string_width (const char *fmt
, ...) {
740 int w
= Z_get_string_width_generic(sfh
, 7, fmt
, a
);
745 static int Z_printsf (const char *fmt
, ...) {
748 int w
=Z_printf_generic(sfh
, 7, fmt
, a
);
753 static void Z_printhf (const char *fmt
, ...) {
758 vsprintf(buf
, fmt
, a
);
760 for (i
= 0; buf
[i
]; ++i
) {
791 R_gl_draw_image(&sth
[c
], prx
, pry
, 0);
799 static image
*PL_getspr (int s
, int d
, int msk
) {
800 int i
= (s
- 'A') * 2 + d
;
801 return msk
? &plr_msk
[i
] : &plr_spr
[i
];
804 #define SCROLLER_MIDDLE 10
805 #define TEXTFIELD_MIDDLE 2
807 static void get_entry_size (const menu_t
*m
, int i
, int *w
, int *h
) {
816 msg
.type
= GM_GETENTRY
;
817 if (GM_send(m
, i
, &msg
)) {
818 type
= msg
.integer
.i
;
823 case GM_TEXTFIELD_BUTTON
:
824 msg
.type
= GM_GETCAPTION
;
825 if (GM_send(m
, i
, &msg
)) {
826 x
= Z_get_big_string_width("%.*s", msg
.string
.maxlen
, msg
.string
.s
);
829 case GM_SMALL_BUTTON
:
830 msg
.type
= GM_GETCAPTION
;
831 if (GM_send(m
, i
, &msg
)) {
832 x
= Z_get_small_string_width("%.*s", msg
.string
.maxlen
, msg
.string
.s
);
840 msg
.type
= GM_GETSTR
;
841 if (GM_send(m
, i
, &msg
)) {
842 x
+= Z_get_big_string_width("%.*s", msg
.string
.maxlen
, msg
.string
.s
);
846 case GM_SMALL_BUTTON
:
847 msg
.type
= GM_GETSTR
;
848 if (GM_send(m
, i
, &msg
)) {
849 x
+= Z_get_big_string_width("%.*s", msg
.string
.maxlen
, msg
.string
.s
);
854 x
+= (SCROLLER_MIDDLE
+ 2) * 8;
858 case GM_TEXTFIELD_BUTTON
:
859 msg
.type
= GM_GETSTR
;
860 if (GM_send(m
, i
, &msg
)) {
861 x
+= (msg
.string
.maxlen
+ 2) * 8;
863 x
+= (TEXTFIELD_MIDDLE
+ 2) * 8;
875 static void get_menu_size (const menu_t
*m
, int *w
, int *h
) {
879 int i
, n
, x
, y
, xx
, yy
, type
;
882 if (GM_send_this(m
, &msg
)) {
884 type
= msg
.integer
.s
;
887 msg
.type
= GM_GETTITLE
;
888 if (GM_send_this(m
, &msg
)) {
890 case GM_BIG
: x
= Z_get_big_string_width("%.*s", msg
.string
.maxlen
, msg
.string
.s
); break;
891 case GM_SMALL
: x
= Z_get_small_string_width("%.*s", msg
.string
.maxlen
, msg
.string
.s
); break;
895 for (i
= 0; i
< n
; i
++) {
896 get_entry_size(m
, i
, &xx
, &yy
);
908 static int GM_draw (void) {
909 int i
, j
, n
, x
, y
, xoff
, yoff
, cur
, w
, type
, recv
;
910 const menu_t
*m
= GM_get();
913 get_menu_size(m
, &x
, &y
);
914 x
= SCRW
/ 2 - x
/ 2;
915 y
= SCRH
/ 2 - y
/ 2;
918 if (GM_send_this(m
, &msg
)) {
921 type
= msg
.integer
.s
;
922 msg
.type
= GM_GETTITLE
;
923 if (GM_send_this(m
, &msg
)) {
926 case GM_SMALL
: yoff
= 8; Z_printsf("%.*s", msg
.string
.maxlen
, msg
.string
.s
); break;
927 case GM_BIG
: yoff
= 20; Z_printbf("%.*s", msg
.string
.maxlen
, msg
.string
.s
); break;
933 for (i
= 0; i
< n
; i
++) {
934 msg
.type
= GM_GETENTRY
;
935 if (GM_send(m
, i
, &msg
)) {
936 type
= msg
.integer
.i
;
938 if (type
== GM_SMALL_BUTTON
) {
939 Z_gotoxy(x
- 8, y
+ yoff
);
942 R_gl_draw_image(&msklh
[(gm_tm
/ 6) & 1], x
- 25, y
+ yoff
- 8, 0);
945 msg
.type
= GM_GETCAPTION
;
946 if (GM_send(m
, i
, &msg
)) {
947 Z_gotoxy(x
, y
+ yoff
);
948 if (type
== GM_SMALL_BUTTON
) {
949 xoff
= Z_printsf("%.*s", msg
.string
.maxlen
, msg
.string
.s
);
951 xoff
= Z_printbf("%.*s", msg
.string
.maxlen
, msg
.string
.s
);
958 case GM_SMALL_BUTTON
:
959 msg
.type
= GM_GETSTR
;
960 if (GM_send(m
, i
, &msg
)) {
961 Z_gotoxy(x
+ xoff
, y
+ yoff
);
962 if (type
== GM_SMALL_BUTTON
) {
963 Z_printsf("%.*s", msg
.string
.maxlen
, msg
.string
.s
);
965 Z_printbf("%.*s", msg
.string
.maxlen
, msg
.string
.s
);
968 yoff
+= type
== GM_BUTTON
? 16 : 12;
971 case GM_TEXTFIELD_BUTTON
:
973 msg
.type
= GM_GETSTR
;
974 recv
= GM_send(m
, i
, &msg
);
975 w
= recv
? msg
.string
.maxlen
: TEXTFIELD_MIDDLE
;
976 R_gl_draw_image(&mslotl
, x
+ xoff
, y
+ yoff
, 0);
977 for (j
= 1; j
<= w
; j
++) {
978 R_gl_draw_image(&mslotm
, x
+ xoff
+ j
* 8, y
+ yoff
, 0);
980 R_gl_draw_image(&mslotr
, x
+ xoff
+ j
* 8, y
+ yoff
, 0);
981 Z_gotoxy(x
+ xoff
+ 4, y
+ yoff
- 7);
982 if (input
&& i
== cur
) {
983 Z_printsf("%.*s_", imax
, ibuf
);
985 Z_printsf("%.*s", msg
.string
.maxlen
, msg
.string
.s
);
990 R_gl_draw_image(&mbarl
, x
+ xoff
, y
+ yoff
, 0);
991 for (j
= 1; j
< SCROLLER_MIDDLE
; j
++) {
992 R_gl_draw_image(&mbarm
, x
+ xoff
+ j
* 8, y
+ yoff
, 0);
994 R_gl_draw_image(&mbarr
, x
+ xoff
+ j
* 8, y
+ yoff
, 0);
995 msg
.type
= GM_GETINT
;
996 if (GM_send(m
, i
, &msg
)) {
997 int lev
= (msg
.integer
.i
- msg
.integer
.a
) * ((SCROLLER_MIDDLE
- 2) * 8) / msg
.integer
.b
;
998 R_gl_draw_image(&mbaro
, x
+ xoff
+ lev
+ 8, y
+ yoff
, 0);
1014 static void R_draw_fld (byte
*fld
, int minx
, int miny
, int maxx
, int maxy
, int fg
) {
1016 assert(minx
>= 0 && minx
<= FLDW
);
1017 assert(miny
>= 0 && miny
<= FLDH
);
1018 assert(maxx
>= 0 && maxx
<= FLDW
);
1019 assert(maxy
>= 0 && maxy
<= FLDH
);
1020 for (j
= miny
; j
< maxy
; j
++) {
1021 for (i
= minx
; i
< maxx
; i
++) {
1022 byte id
= fld
[j
* FLDW
+ i
];
1024 if (walp
[id
].res
< 0) {
1026 switch (R_get_special_id(id
)) {
1028 glColor4ub(0, 0, 255, 127);
1031 glColor4ub(0, 127, 0, 127);
1034 glColor4ub(127, 0, 0, 127);
1037 glColor4ub(0, 0, 0, 127);
1041 glBlendFunc(GL_DST_COLOR
, GL_SRC_COLOR
);
1042 glDisable(GL_TEXTURE_2D
);
1043 R_gl_draw_quad(i
* CELW
, j
* CELW
, CELW
, CELH
);
1046 R_gl_draw_image(&walp
[id
], i
* CELW
, j
* CELH
, 0);
1053 static void R_draw_dots (void) {
1055 glDisable(GL_BLEND
);
1056 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
1057 glDisable(GL_TEXTURE_2D
);
1059 for (i
= 0; i
< MAXDOT
; i
++) {
1060 if (dot
[i
].t
!= 0) {
1063 R_gl_set_color(dot
[i
].c
); glVertex2i(x
+ 1, y
);
1064 R_gl_set_color(dot
[i
].c
); glVertex2i(x
, y
);
1065 R_gl_set_color(dot
[i
].c
); glVertex2i(x
, y
+ 1);
1066 R_gl_set_color(dot
[i
].c
); glVertex2i(x
+ 1, y
+ 1);
1072 static void R_draw_items (void) {
1074 for (i
= 0; i
< MAXITEM
; ++i
) {
1076 if (it
[i
].t
&& it
[i
].s
>= 0) {
1077 switch (it
[i
].t
& 0x7FFF) {
1079 s
= it
[i
].s
/ 9 + 18;
1082 s
= it
[i
].s
/ 9 + 20;
1085 s
= it
[i
].s
/ 2 + 22;
1088 s
= it
[i
].s
/ 2 + 26;
1094 s
= it
[i
].s
/ 2 + (it
[i
].t
- I_SUPER
) * 4 + 35;
1096 case I_GOR1
: case I_FCAN
:
1097 s
= it
[i
].s
/ 2 + (it
[i
].t
- I_GOR1
) * 3 + 51;
1108 s
= (it
[i
].t
& 0x7FFF) - I_KEYR
+ 31;
1114 s
= (it
[i
].t
& 0x7FFF) - 1;
1118 R_gl_draw_image(&item_spr
[s
], it
[i
].o
.x
, it
[i
].o
.y
, item_sprd
[s
]);
1123 static int standspr (player_t
*p
) {
1124 if (p
->f
& PLF_UP
) {
1126 } else if (p
->f
& PLF_DOWN
) {
1133 static int wpnspr (player_t
*p
) {
1134 if (p
->f
& PLF_UP
) {
1136 } else if(p
->f
& PLF_DOWN
) {
1143 static void R_draw_player (player_t
*p
) {
1144 enum {STAND
, GO
, DIE
, SLOP
, DEAD
, MESS
, OUT
, FALL
}; // copypasted from player.c!
1145 static const int wytab
[] = {-1, -2, -1, 0};
1152 if (p
->f
& PLF_FIRE
) {
1153 s
= standspr(p
) + 1;
1155 } else if (p
->pain
) {
1178 s
= plr_goanim
[p
->s
/ 8];
1179 w
= (p
->f
& PLF_FIRE
) ? 'B' : 'A';
1181 wy
= 1 + wytab
[s
- 'A'];
1185 s
= plr_dieanim
[p
->s
];
1188 s
= plr_slopanim
[p
->s
];
1198 R_gl_draw_image(&plr_wpn
[(int)p
->wpn
][w
-'A'], p
->o
.x
+ wx
, p
->o
.y
+ wy
, p
->d
);
1201 R_gl_draw_image(&plr_spr
[(s
- 'A') * 2 + p
->d
], p
->o
.x
, p
->o
.y
, plr_sprd
[(s
- 'A') * 2 + p
->d
]);
1202 R_gl_set_color(p
->color
+ PLAYER_COLOR_OFFSET
);
1203 R_gl_draw_image_color(&plr_msk
[(s
- 'A') * 2 + p
->d
], p
->o
.x
, p
->o
.y
, plr_sprd
[(s
- 'A') * 2 + p
->d
]);
1207 static void R_draw_monsters (void) {
1208 enum {SLEEP
, GO
, RUN
, CLIMB
, DIE
, DEAD
, ATTACK
, SHOOT
, PAIN
, WAIT
, REVIVE
, RUNOUT
}; // copypasted from monster.c!
1210 for (i
= 0; i
< MAXMN
; i
++) {
1211 if (mn
[i
].t
!= MN_NONE
) {
1214 if (mn
[i
].t
< MN__LAST
) {
1215 if ((mn
[i
].t
!= MN_SOUL
&& mn
[i
].t
!= MN_PAIN
) || mn
[i
].st
!= DEAD
) {
1216 int ap
= mn
[i
].ap
[mn
[i
].ac
];
1217 int d
= (ap
- 'A') * 2 + mn
[i
].d
;
1218 int dir
= mn_sprd
[mn
[i
].t
- 1][d
];
1219 if (mn
[i
].t
== MN_MAN
&& (ap
== 'E' || ap
== 'F')) {
1220 R_gl_draw_image(&mn_sgun
[ap
- 'E'], x
, y
, mn
[i
].d
);
1222 R_gl_draw_image(&mn_spr
[mn
[i
].t
- 1][d
], x
, y
, dir
);
1223 if (mn
[i
].t
== MN_MAN
) {
1224 R_gl_set_color(MANCOLOR
+ PLAYER_COLOR_OFFSET
);
1225 R_gl_draw_image_color(&mn_man_msk
[d
], x
, y
, dir
);
1228 if (mn
[i
].t
== MN_VILE
&& mn
[i
].st
== SHOOT
) {
1229 R_gl_draw_image(&mn_fspr
[mn
[i
].ac
/ 3], mn
[i
].tx
, mn
[i
].ty
, 0);
1231 } else if (mn
[i
].t
== MN_PL_DEAD
|| mn
[i
].t
== MN_PL_MESS
) {
1232 int type
= mn
[i
].t
- MN_PL_DEAD
;
1233 R_gl_draw_image(&pl_spr
[type
], x
, y
, 0);
1234 R_gl_set_color(mn
[i
].d
);
1235 R_gl_draw_image_color(&pl_msk
[type
], x
, y
, 0);
1241 static void R_draw_weapons (void) {
1242 enum {NONE
, ROCKET
, PLASMA
, APLASMA
, BALL1
, BALL2
, BALL7
, BFGBALL
, BFGHIT
, MANF
, REVF
, FIRE
}; // copypasted from weapons.c!
1244 for (i
= 0; i
< MAXWPN
; ++i
) {
1252 d
= wp
[i
].o
.xv
> 0 ? 1 : 0;
1253 x
= abs(wp
[i
].o
.xv
);
1266 s
= (d
- 2) / 2 + 1;
1300 d
= wp
[i
].o
.xv
>= 0 ? 1 : 0;
1304 d
= wp
[i
].o
.xv
>=0 ? 1 : 0;
1316 s
= wp
[i
].s
/ 2 + 26;
1320 R_gl_draw_image(&wp_spr
[s
* 2 + d
], wp
[i
].o
.x
, wp
[i
].o
.y
, wp_sprd
[s
* 2 + d
]);
1325 static void R_draw_smoke (void) {
1327 for (i
= 0; i
< MAXSMOK
; ++i
) {
1332 if (s
>= (SMSN
- 1) * 3) {
1335 s
= SMSN
- 1 - s
/ 3;
1337 R_gl_draw_image(&smk_spr
[s
], sm
[i
].x
>> 8, (sm
[i
].y
>> 8) + 1, 0);
1341 if (s
>= FLSN
- 1) {
1346 R_gl_draw_image(&smk_fspr
[s
], sm
[i
].x
>> 8, (sm
[i
].y
>> 8) + 1, 0);
1353 static void R_draw_effects (void) {
1354 enum {NONE
, TFOG
, IFOG
, BUBL
}; // copypasted from fx.c
1356 for (i
= 0; i
< MAXFX
; ++i
) {
1360 R_gl_draw_image(&fx_spr
[s
], fx
[i
].x
, fx
[i
].y
, fx_sprd
[s
]);
1363 s
= fx
[i
].s
/ 2 + 10;
1364 R_gl_draw_image(&fx_spr
[s
], fx
[i
].x
, fx
[i
].y
, fx_sprd
[s
]);
1367 glDisable(GL_BLEND
);
1368 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
1369 glDisable(GL_TEXTURE_2D
);
1370 R_gl_set_color(0xC0 + fx
[i
].s
);
1371 R_gl_draw_quad(fx
[i
].x
>> 8, fx
[i
].y
>> 8, 1, 1);
1377 static int get_pu_st (int t
) {
1378 if (t
>= PL_FLASH
) {
1380 } else if((t
/ 9) & 1) {
1387 static void R_draw_view (int x
, int y
, int w
, int h
, int camx
, int camy
) {
1389 R_gl_setclip(x
, y
, w
, h
);
1390 glTranslatef(x
, y
, 0);
1391 if (w_horiz
&& horiz
.n
!= NULL
) {
1392 R_gl_draw_image_ext(&horiz
, 0, 0, w
, h
);
1393 if (sky_type
== 2 && lt_time
< 0) {
1394 image
*tanderbolt
= <n
[lt_type
][lt_time
< -5 ? 0 : 1];
1396 R_gl_draw_image(tanderbolt
, 0, lt_ypos
, 0);
1398 R_gl_draw_image(tanderbolt
, w
- 1, lt_ypos
, 1);
1402 glDisable(GL_BLEND
);
1403 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
1404 glDisable(GL_TEXTURE_2D
);
1405 R_gl_set_color(DEFAULT_SKY_COLOR
);
1406 R_gl_draw_quad(0, 0, w
, h
);
1408 int maxx
= min((camx
+ w
) / CELW
+ 1, FLDW
);
1409 int maxy
= min((camy
+ h
) / CELH
+ 1, FLDH
);
1410 int minx
= max((camx
- max_wall_width
) / CELW
, 0);
1411 int miny
= max((camy
- max_wall_height
) / CELH
, 0);
1412 glTranslatef(-camx
, -camy
, 0);
1413 R_draw_fld((byte
*)fldb
, minx
, miny
, maxx
, maxy
, 0);
1416 R_draw_player(&pl1
);
1418 R_draw_player(&pl2
);
1424 R_draw_fld((byte
*)fldf
, minx
, miny
, maxx
, maxy
, 1);
1425 glTranslatef(camx
, camy
, 0);
1426 if (sky_type
== 2 && (lt_time
== -4 || lt_time
== -2)) {
1427 glColor4ub(255, 255, 255, 255);
1429 glBlendFunc(GL_DST_COLOR
, GL_SRC_COLOR
);
1430 glDisable(GL_TEXTURE_2D
);
1431 R_gl_draw_quad(0, 0, w
, h
);
1436 static void R_draw_player_view (player_t
*p
, int x
, int y
, int w
, int h
) {
1437 p
->looky
= min(max(p
->looky
, -SCRH
/ 4), SCRH
/ 4); // TODO remove writeback
1440 int cx
= min(max(p
->o
.x
, cw
/ 2), FLDW
* CELW
- cw
/ 2);
1441 int cy
= min(max(p
->o
.y
- 12 + p
->looky
, h
/ 2), FLDH
* CELH
- h
/ 2);
1442 int camx
= max(cx
- cw
/ 2, 0);
1443 int camy
= max(cy
- h
/ 2, 0);
1445 R_draw_view(x
, y
+ 1, cw
, h
- 2, camx
, camy
);
1446 glTranslatef(x
, y
, 0);
1448 if (get_pu_st(p
->invl
)) {
1450 glBlendFunc(GL_ONE_MINUS_DST_COLOR
, GL_ZERO
);
1451 glDisable(GL_TEXTURE_2D
);
1452 glColor4ub(191, 191, 191, 255);
1453 R_gl_draw_quad(0, 0, cw
, h
);
1456 if (p
->suit
&& get_pu_st(p
->suit
)) {
1458 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
1459 glDisable(GL_TEXTURE_2D
);
1460 glColor4ub(0, 255, 0, 192);
1461 R_gl_draw_quad(0, 0, cw
, h
);
1463 int f
= min(max(p
->pain
* 3, 0), 255);
1466 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
1467 glDisable(GL_TEXTURE_2D
);
1468 glColor4ub(255, 0, 0, f
);
1469 R_gl_draw_quad(0, 0, cw
, h
);
1472 R_gl_setclip(x
, y
, w
, h
);
1473 glTranslatef(-x
+ cw
, 0, 0);
1474 R_gl_draw_image(&stone
, 0, 0, 0);
1477 R_gl_draw_image(&stone2
, 0, i
, 0);
1480 if (p
->drawst
& PL_DRAWAIR
) {
1481 if (p
->air
< PL_AIR
) {
1482 int a
= min(max(p
->air
, 0), MAXAIR
) * 100 / MAXAIR
;
1483 glDisable(GL_BLEND
);
1484 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
1485 glDisable(GL_TEXTURE_2D
);
1486 R_gl_set_color(0xC8);
1487 R_gl_draw_quad(10, 49, a
, 2);
1490 if (p
->drawst
& PL_DRAWLIFE
) {
1492 Z_printhf("%3d%%", p
->life
);
1494 if (p
->drawst
& PL_DRAWARMOR
) {
1495 Z_gotoxy(10, 7 + 19);
1496 Z_printhf("%3d%%", p
->armor
);
1498 if (p
->drawst
& PL_DRAWWPN
) {
1525 R_gl_draw_image(&sth
[12 + p
->wpn
], st
- 88, 58 + 19, 0);
1529 Z_gotoxy(st
- 10 - 5 * 14, 58 + 2);
1530 Z_printhf("%5d", i
);
1533 if (p
->drawst
& PL_DRAWFRAG
&& g_dm
) {
1534 Z_gotoxy(st
- 5 - 5 * 14, 77 + 5);
1535 Z_printhf("%5d", p
->frag
);
1537 if (p
->drawst
& PL_DRAWKEYS
) {
1539 for (k
= p
->keys
>> 4, n
= 0, x
= st
- 75; n
< 3; n
++, k
>>= 1, x
+= 9) {
1541 R_gl_draw_image(&keys
[n
], x
, 91, 0);
1545 if (p
->drawst
& PL_DRAWLIVES
&& !_2pl
) {
1546 Z_gotoxy(st
- 35, 17);
1547 Z_printhf("%d", p
->lives
);
1554 static void pl_info (player_t
*p
, int x
, int y
) {
1555 dword t
= p
->kills
* 10920 / g_time
;
1556 Z_gotoxy(x
+ 25, y
); Z_printbf("KILLS");
1557 Z_gotoxy(x
+ 25, y
+ 15); Z_printbf("KPM");
1558 Z_gotoxy(x
+ 25, y
+ 30); Z_printbf("SECRETS %u / %u", p
->secrets
, sw_secrets
);
1559 Z_gotoxy(x
+ 255, y
); Z_printbf("%u", p
->kills
);
1560 Z_gotoxy(x
+ 255, y
+ 15); Z_printbf("%u.%u", t
/ 10, t
% 10);
1563 static void R_draw_intermission (void) {
1566 Z_gotoxy(cx
- 14*12/2, 20);
1567 Z_printbf("LEVEL COMPLETE");
1568 Z_calc_time(g_time
, &hr
, &mn
, &sc
);
1569 Z_gotoxy(cx
- 12*12/2, 40);
1570 Z_printbf("TIME %u:%02u:%02u", hr
, mn
, sc
);
1573 Z_gotoxy(cx
- 10*12/2, h
);
1574 Z_printbf("PLAYER ONE");
1577 pl_info(&pl1
, cx
- 160, h
);
1579 h
+= 30 + SCRH
/ 10;
1580 Z_gotoxy(cx
- 10*12/2, h
);
1581 Z_printbf("PLAYER TWO");
1583 pl_info(&pl2
, cx
- 160, h
);
1587 static void W_act (void) {
1589 if (g_time
% 3 == 0) {
1590 for (i
= 1; i
< max_textures
; i
++) {
1594 if (anip
[a
][anic
[a
]].res
== -1) {
1597 walp
[i
] = anip
[a
][anic
[a
]];
1603 void R_draw (void) {
1605 glClearColor(0, 0, 0, 1);
1606 glClear(GL_COLOR_BUFFER_BIT
);
1607 glEnable(GL_SCISSOR_TEST
);
1618 R_gl_draw_image_ext(&scrnh
[0], 0, 0, SCRW
, SCRH
);
1621 R_gl_draw_image_ext(&scrnh
[1], 0, 0, SCRW
, SCRH
);
1622 R_draw_intermission();
1625 R_gl_draw_image_ext(&scrnh
[2], 0, 0, SCRW
, SCRH
);
1629 R_draw_player_view(&pl1
, 0, 0, SCRW
, SCRH
/ 2);
1630 R_draw_player_view(&pl2
, 0, SCRH
/ 2, SCRW
, SCRH
/ 2);
1632 R_draw_player_view(&pl1
, 0, 0, SCRW
, SCRH
);
1634 R_gl_setclip(0, 0, SCRW
, SCRH
);
1641 static void R_alloc (void) {
1644 logo("R_alloc: load graphics\n");
1646 scrnh
[0] = R_gl_loadimage("TITLEPIC");
1647 scrnh
[1] = R_gl_loadimage("INTERPIC");
1648 scrnh
[2] = R_gl_loadimage("ENDPIC");
1649 for (i
= 0; i
< 2; i
++) {
1650 sprintf(s
, "LTN%c", '1' + i
);
1651 for (j
= 0; j
< 2; j
++) {
1652 ltn
[i
][j
] = Z_getspr(s
, j
, 0, NULL
);
1656 for (i
= 0; i
< SMSN
; i
++) {
1657 smk_spr
[i
] = R_gl_get_special_spr("SMOK", i
, 0, &R_extract_smoke_spr
);
1659 for (i
= 0; i
< FLSN
; i
++) {
1660 smk_fspr
[i
] = R_gl_get_special_spr("SMOK", i
, 0, &R_extract_flame_spr
);
1663 for (i
= 0; i
< 10; i
++) {
1664 fx_spr
[i
] = Z_getspr("TFOG", i
, 0, fx_sprd
+ i
);
1666 for (; i
< 15; i
++) {
1667 fx_spr
[i
] = Z_getspr("IFOG", i
- 10, 0, fx_sprd
+ i
);
1670 for (i
= 0; i
< 4; i
++) {
1671 wp_spr
[i
* 2] = Z_getspr("MISL", i
, 1, wp_sprd
+ i
* 2);
1672 wp_spr
[i
* 2 + 1] = Z_getspr("MISL", i
, 2, wp_sprd
+ i
* 2 + 1);
1674 for (; i
< 6; i
++) {
1675 wp_spr
[i
* 2] = Z_getspr("PLSS", i
- 4, 1, wp_sprd
+ i
* 2);
1676 wp_spr
[i
* 2 + 1] = Z_getspr("PLSS", i
- 4, 2, wp_sprd
+ i
* 2 + 1);
1678 for (; i
< 11; i
++) {
1679 wp_spr
[i
* 2] = Z_getspr("PLSE", i
- 6, 1, wp_sprd
+ i
* 2);
1680 wp_spr
[i
* 2 + 1] = Z_getspr("PLSE", i
- 6, 2, wp_sprd
+ i
* 2 + 1);
1682 for (; i
< 13; i
++) {
1683 wp_spr
[i
* 2] = Z_getspr("APLS", i
- 11, 1, wp_sprd
+ i
* 2);
1684 wp_spr
[i
* 2 + 1] = Z_getspr("APLS", i
- 11, 2, wp_sprd
+ i
* 2 + 1);
1686 for (; i
< 18; i
++) {
1687 wp_spr
[i
* 2] = Z_getspr("APBX", i
- 13, 1, wp_sprd
+ i
* 2);
1688 wp_spr
[i
* 2 + 1] = Z_getspr("APBX", i
- 13, 2, wp_sprd
+ i
* 2 + 1);
1690 for(; i
< 20; i
++) {
1691 wp_spr
[i
* 2] = Z_getspr("BFS1", i
- 18, 1, wp_sprd
+ i
* 2);
1692 wp_spr
[i
* 2 + 1] = Z_getspr("BFS1", i
- 18, 2, wp_sprd
+ i
* 2 + 1);
1694 for (; i
< 26; i
++) {
1695 wp_spr
[i
* 2] = Z_getspr("BFE1", i
- 20, 1, wp_sprd
+ i
* 2);
1696 wp_spr
[i
* 2 + 1] = Z_getspr("BFE1", i
- 20, 2, wp_sprd
+ i
* 2 + 1);
1698 for (; i
< 30; i
++) {
1699 wp_spr
[i
* 2] = Z_getspr("BFE2", i
- 26, 1, wp_sprd
+ i
* 2);
1700 wp_spr
[i
* 2 + 1] = Z_getspr("BFE2", i
- 26, 2, wp_sprd
+ i
* 2 + 1);
1702 for (; i
< 32; i
++) {
1703 wp_spr
[i
* 2] = Z_getspr("MISL", i
- 30 + 4, 1, wp_sprd
+ i
* 2);
1704 wp_spr
[i
* 2 + 1] = Z_getspr("MISL", i
- 30 + 4, 2, wp_sprd
+ i
* 2 + 1);
1706 for (; i
< 37; i
++) {
1707 wp_spr
[i
* 2] = Z_getspr("BAL1", i
- 32, 1, wp_sprd
+ i
* 2);
1708 wp_spr
[i
* 2 + 1] = Z_getspr("BAL1", i
- 32, 2, wp_sprd
+ i
* 2 + 1);
1710 for (; i
< 42; i
++) {
1711 wp_spr
[i
* 2] = Z_getspr("BAL7", i
- 37, 1, wp_sprd
+ i
* 2);
1712 wp_spr
[i
* 2 + 1] = Z_getspr("BAL7", i
- 37, 2, wp_sprd
+ i
* 2 + 1);
1714 for (; i
< 47; i
++) {
1715 wp_spr
[i
* 2] = Z_getspr("BAL2", i
- 42, 1, wp_sprd
+ i
* 2);
1716 wp_spr
[i
* 2 + 1] = Z_getspr("BAL2", i
- 42, 2, wp_sprd
+ i
* 2 + 1);
1718 for (; i
< 49; i
++) {
1719 wp_spr
[i
* 2] = Z_getspr("MANF", i
- 47, 1, wp_sprd
+ i
* 2);
1720 wp_spr
[i
* 2 + 1] = Z_getspr("MANF", i
- 47, 2, wp_sprd
+ i
* 2 + 1);
1723 static const char snm
[18][4] = {
1724 "CLIP", "SHEL", "ROCK", "CELL", "AMMO", "SBOX", "BROK", "CELP",
1725 "STIM", "MEDI", "BPAK",
1726 "CSAW", "SHOT", "SGN2", "MGUN", "LAUN", "PLAS", "BFUG"
1728 static const char n4
[4][4] = {
1729 "SOUL", "SMRT", "SMGT", "SMBT"
1731 static const char n3
[2][4] = {
1734 for (i
= 0; i
< 18; i
++) {
1735 item_spr
[i
] = Z_getspr(snm
[i
], 0, 0, item_sprd
+ i
);
1737 for (; i
< 20; i
++) {
1738 item_spr
[i
] = Z_getspr("ARM1", i
- 18, 0, item_sprd
+ i
);
1739 item_spr
[i
+ 2] = Z_getspr("ARM2", i
- 18, 0, item_sprd
+ i
);
1742 for (; i
< 26; i
++) {
1743 item_spr
[i
] = Z_getspr("MEGA", i
- 22, 0, item_sprd
+ i
);
1745 for (; i
< 30; i
++) {
1746 item_spr
[i
] = Z_getspr("PINV", i
- 26, 0, item_sprd
+ i
);
1748 item_spr
[30] = Z_getspr("AQUA", 0, 0, item_sprd
+ 30);
1749 item_spr
[31] = Z_getspr("KEYR", 0, 0, item_sprd
+ 31);
1750 item_spr
[32] = Z_getspr("KEYG", 0, 0, item_sprd
+ 32);
1751 item_spr
[33] = Z_getspr("KEYB", 0, 0, item_sprd
+ 33);
1752 item_spr
[34] = Z_getspr("SUIT", 0, 0, item_sprd
+ 34);
1753 for (n
= 35, j
= 0; j
< 4; j
++) {
1754 for (i
= 0; i
< 4; i
++, n
++) {
1755 item_spr
[n
] = Z_getspr(n4
[j
], i
, 0, item_sprd
+ n
);
1758 for (j
= 0; j
< 2; j
++) {
1759 for (i
= 0; i
< 3; i
++, n
++) {
1760 item_spr
[n
] = Z_getspr(n3
[j
], i
, 0, item_sprd
+ n
);
1763 item_spr
[57] = Z_getspr("GUN2", 0, 0, item_sprd
+ 57);
1765 for (i
= 0; i
< 27; i
++) {
1766 plr_spr
[i
* 2] = Z_getspr("PLAY", i
, 1, plr_sprd
+ i
* 2);
1767 plr_msk
[i
* 2] = R_gl_get_special_spr("PLAY", i
, 1, &R_extract_mask_spr
);
1768 plr_spr
[i
* 2 + 1] = Z_getspr("PLAY", i
, 2, plr_sprd
+ i
* 2 + 1);
1769 plr_msk
[i
* 2 + 1] = R_gl_get_special_spr("PLAY", i
, 2, &R_extract_mask_spr
);
1771 strncpy(s
, "PWPx", 4);
1772 for (i
= 1; i
< 11; i
++) {
1773 s
[3] = (i
< 10 ? '0' : 'A' - 10) + i
;
1774 for (j
= 0; j
< 6; j
++) {
1775 plr_wpn
[i
][j
] = Z_getspr(s
, j
, 1, NULL
);
1779 static const char msn
[MN_TN
][4] = {
1780 "SARG", "TROO", "POSS", "SPOS", "CYBR", "CPOS", "BOSS", "BOS2", "HEAD", "SKUL",
1781 "PAIN", "SPID", "BSPI", "FATT", "SKEL", "VILE", "FISH", "BAR1", "ROBO", "PLAY"
1783 static const int mms
[MN_TN
] = {
1784 14*2, 21*2, 21*2, 21*2, 16*2, 20*2, 15*2, 15*2, 12*2, 11*2,
1785 13*2, 19*2, 16*2, 20*2, 17*2, 29*2, 6*2, 2*2, 17*2, 23*2
1787 mn_sgun
[0] = Z_getspr("PWP4", 0, 1, NULL
);
1788 mn_sgun
[1] = Z_getspr("PWP4", 1, 1, NULL
);
1789 for (j
= 0; j
< MN_TN
; j
++) {
1790 for (i
= 0; i
< mms
[j
]; i
++) {
1791 mn_spr
[j
][i
] = Z_getspr(msn
[j
], i
/ 2, (i
& 1) + 1, &mn_sprd
[j
][i
]);
1792 if (j
== MN_MAN
- 1) {
1793 mn_man_msk
[i
] = R_gl_get_special_spr(msn
[j
], i
/ 2, (i
& 1) + 1, &R_extract_mask_spr
);
1796 if (j
== MN_BARREL
- 1) {
1797 for (i
= 4; i
< 14; i
++) {
1798 mn_spr
[j
][i
] = Z_getspr("BEXP", i
/ 2 - 2, (i
& 1) + 1, &mn_sprd
[j
][i
]);
1802 for (i
= 0; i
< 8; i
++) {
1803 mn_fspr
[i
] = Z_getspr("FIRE", i
, 0, NULL
);
1805 pl_spr
[0] = Z_getspr("PLAY", 'N' - 'A', 0, NULL
);
1806 pl_msk
[0] = R_gl_get_special_spr("PLAY", 'N' - 'A', 0, &R_extract_mask_spr
);
1807 pl_spr
[1] = Z_getspr("PLAY", 'W' - 'A', 0, NULL
);
1808 pl_msk
[1] = R_gl_get_special_spr("PLAY", 'W' - 'A', 0, &R_extract_mask_spr
);
1810 static const char mnm
[22][8]={
1811 "STTNUM0", "STTNUM1", "STTNUM2", "STTNUM3", "STTNUM4",
1812 "STTNUM5", "STTNUM6", "STTNUM7", "STTNUM8", "STTNUM9",
1813 "STTMINUS", "STTPRCNT",
1814 "FISTA0", "CSAWA0", "PISTA0", "SHOTA0", "SGN2A0", "MGUNA0", "LAUNA0",
1815 "PLASA0", "BFUGA0", "GUN2A0"
1817 stone
= R_gl_loadimage("STONE");
1818 stone2
= R_gl_loadimage("STONE2");
1819 keys
[0] = R_gl_loadimage("KEYRA0");
1820 keys
[1] = R_gl_loadimage("KEYGA0");
1821 keys
[2] = R_gl_loadimage("KEYBA0");
1822 for (i
= 0; i
< 22; i
++) {
1823 sth
[i
] = R_gl_loadimage(mnm
[i
]);
1825 strcpy(s
, "STBF_*");
1826 for (i
= '!'; i
< 160; i
++) {
1828 bfh
[i
- '!'] = R_gl_getimage(F_findres(s
));
1830 for (i
= '!'; i
< 160; i
++) {
1831 sprintf(s
, "STCFN%03d", i
);
1832 sfh
[i
- '!'] = R_gl_getimage(F_findres(s
));
1834 strcpy(s
, "WINUM*");
1835 for (i
= '0'; i
<= '9'; i
++) {
1837 bfh
[i
- '!'] = R_gl_loadimage(s
);
1839 bfh
[':' - '!'] = R_gl_loadimage("WICOLON");
1841 msklh
[0] = R_gl_loadimage("M_SKULL1");
1842 msklh
[1] = R_gl_loadimage("M_SKULL2");
1843 mbarl
= R_gl_loadimage("M_THERML");
1844 mbarm
= R_gl_loadimage("M_THERMM");
1845 mbarr
= R_gl_loadimage("M_THERMR");
1846 mbaro
= R_gl_loadimage("M_THERMO");
1847 mslotl
= R_gl_loadimage("M_LSLEFT");
1848 mslotm
= R_gl_loadimage("M_LSCNTR");
1849 mslotr
= R_gl_loadimage("M_LSRGHT");
1851 for (i
= 1; i
< ANIT
; i
++) {
1852 for (j
= 0; j
< 5 && anm
[i
- 1][j
]; j
++) {
1853 anip
[i
][j
] = R_gl_loadimage(anm
[i
- 1][j
]);
1856 anip
[i
][j
] = (image
) {
1866 static void R_reload_textures (void);
1868 void R_set_videomode (int w
, int h
, int fullscreen
) {
1871 int was
= Y_videomode_setted();
1873 R_cache_free(root
, 0);
1876 int res
= Y_set_videomode_opengl(w
, h
, fullscreen
);
1879 ERR_failinit("Unable to set video mode\n");
1882 Y_get_videomode(&screen_width
, &screen_height
);
1883 screen_full
= Y_get_fullscreen();
1884 screen_scale
= max(1, screen_width
/ 320);
1885 root
= R_cache_new();
1888 R_reload_textures();
1891 static int video_menu_handler (menu_msg_t
*msg
, const menu_t
*m
, int i
) {
1893 static int w
, h
, fullscreen
;
1894 static char buf
[16];
1897 const videomode_t
*v
;
1898 enum { VIDEOMODE
, FULLSCREEN
, APPLY
, __NUM__
};
1899 static const simple_menu_t sm
= {
1900 GM_BIG
, "Video", NULL
,
1903 { "Fullscreen: ", NULL
},
1907 if (msg
->type
== GM_ENTER
) {
1908 Y_get_videomode(&w
, &h
);
1909 fullscreen
= Y_get_fullscreen();
1910 v
= Y_get_videomode_list_opengl(fullscreen
);
1912 while (vmode
< v
->n
&& v
->modes
[vmode
].w
!= w
&& v
->modes
[vmode
].h
!= h
) {
1916 w
= v
->modes
[vmode
].w
;
1917 h
= v
->modes
[vmode
].h
;
1919 snprintf(buf
, 16, "%ix%i", w
, h
);
1920 buflen
= strlen(buf
);
1923 if (i
== VIDEOMODE
) {
1924 switch (msg
->type
) {
1925 case GM_GETSTR
: return GM_init_str(msg
, buf
, buflen
);
1927 v
= Y_get_videomode_list_opengl(fullscreen
);
1928 vmode
= vmode
+ 1 >= v
->n
? 0 : vmode
+ 1;
1930 w
= v
->modes
[vmode
].w
;
1931 h
= v
->modes
[vmode
].h
;
1933 Y_get_videomode(&w
, &h
);
1935 snprintf(buf
, 16, "%ix%i", w
, h
);
1936 buflen
= strlen(buf
);
1939 } else if (i
== FULLSCREEN
) {
1940 switch (msg
->type
) {
1941 case GM_GETSTR
: return GM_init_str(msg
, fullscreen
? "Yes" : "No ", 3);
1942 case GM_SELECT
: fullscreen
= !fullscreen
; return 1;
1944 } else if (i
== APPLY
) {
1945 switch (msg
->type
) {
1946 case GM_SELECT
: R_set_videomode(w
, h
, fullscreen
); return 1;
1949 return simple_menu_handler(msg
, i
, __NUM__
, &sm
, &cur
);
1952 const menu_t
*R_menu (void) {
1953 static const menu_t m
= { video_menu_handler
};
1957 const cfg_t
*R_args (void) {
1958 static const cfg_t args
[] = {
1959 { "fullscr", &init_screen_full
, Y_SW_ON
},
1960 { "window", &init_screen_full
, Y_SW_OFF
},
1961 { "width", &init_screen_width
, Y_DWORD
},
1962 { "height", &init_screen_height
, Y_DWORD
},
1963 { NULL
, NULL
, 0 } // end
1968 const cfg_t
*R_conf (void) {
1969 static const cfg_t conf
[] = {
1970 { "sky", &w_horiz
, Y_SW_ON
},
1971 { "fullscreen", &screen_full
, Y_SW_ON
},
1972 { "screen_width", &screen_width
, Y_DWORD
},
1973 { "screen_height", &screen_height
, Y_DWORD
},
1974 { NULL
, NULL
, 0 } // end
1979 void R_init (void) {
1980 logo("R_init: intialize opengl render\n");
1982 init_screen_width
= init_screen_width
> 0 ? init_screen_width
: screen_width
;
1983 init_screen_height
= init_screen_height
> 0 ? init_screen_height
: screen_height
;
1984 init_screen_full
= init_screen_full
!= 0xFF ? init_screen_full
: screen_full
;
1985 R_set_videomode(init_screen_width
, init_screen_height
, init_screen_full
);
1988 void R_done (void) {
1989 R_cache_free(root
, 1);
1990 Y_unset_videomode();
1994 void R_get_name (int n
, char s
[8]) {
1995 assert(n
>= 0 && n
< 256);
1996 if (walp
[n
].res
== -1) {
1998 } else if (walp
[n
].res
== -2) {
1999 memcpy(s
, "_WATER_", 8);
2000 s
[7] = '0' + (intptr_t)walp
[n
].n
- 1;
2001 } else if (walani
[n
] > 0) {
2002 memcpy(s
, anm
[walani
[n
] - 1][0], 8);
2004 F_getresname(s
, walp
[n
].res
& 0x7FFF);
2008 static short getani (char n
[8]) {
2010 while (i
< ANIT
- 1 && strncasecmp(n
, anm
[i
][0], 8) != 0) {
2013 return i
< ANIT
- 1 ? i
+ 1 : 0;
2016 int R_get_special_id (int n
) {
2017 assert(n
>= 0 && n
<= 256);
2018 return walp
[n
].res
== -2 ? (intptr_t)walp
[n
].n
: -1;
2021 static void R_reload_textures (void) {
2024 for (i
= 0; i
< max_textures
; i
++) {
2026 if (walp
[i
].res
>= 0) {
2027 walp
[i
] = R_gl_getimage(walp
[i
].res
);
2031 horiz
= R_gl_getimage(horiz
.res
);
2035 void R_begin_load (void) {
2037 for (i
= 0; i
< 256; i
++) {
2038 if (walp
[i
].n
!= NULL
&& walp
[i
].res
>= 0 && walani
[i
] == 0) {
2039 R_gl_free_image(&walp
[i
]);
2041 memset(&walp
[i
], 0, sizeof(image
));
2046 memset(anic
, 0, sizeof(anic
));
2048 max_wall_height
= 0;
2052 void R_load (char s
[8]) {
2053 assert(max_textures
< 256);
2055 walp
[max_textures
] = (image
) {
2063 } else if (strncasecmp(s
, "_WATER_", 7) == 0) {
2064 walp
[max_textures
] = (image
) {
2065 .n
= (void*)((intptr_t)s
[7] - '0' + 1),
2073 walp
[max_textures
] = R_gl_loadimage(s
);
2074 if (s
[0] == 'S' && s
[1] == 'W' && s
[4] == '_') {
2075 walswp
[max_textures
] = 0;
2077 walani
[max_textures
] = getani(s
);
2079 max_wall_width
= max(max_wall_width
, walp
[max_textures
].w
);
2080 max_wall_height
= max(max_wall_height
, walp
[max_textures
].h
);
2084 void R_end_load (void) {
2088 for (i
= 1; i
< 256 && j
< 256; i
++) {
2089 if (walswp
[i
] == 0) {
2094 while (k
< 256 && walp
[k
].res
!= g
) {
2101 walp
[k
] = R_gl_getimage(g
);
2110 void R_loadsky (int sky
) {
2114 R_gl_free_image(&horiz
);
2115 horiz
= R_gl_loadimage(s
);
2118 void R_switch_texture (int x
, int y
) {
2119 assert(x
>= 0 && x
< FLDW
);
2120 assert(y
>= 0 && y
< FLDH
);
2121 fldb
[y
][x
] = walswp
[fldb
[y
][x
]];
2124 int R_get_swp (int n
) {
2125 assert(n
>= 0 && n
< 256);