14 #include "sound.h" // snd_vol
15 #include "music.h" // mus_vol
23 #include "switch.h" // sw_secrets
26 # include <OpenGL/gl.h>
36 #define VGA_TRANSPARENT_COLOR 0
37 #define DEFAULT_SKY_COLOR 0x97
39 #define PLAYER_COLOR_OFFSET 7
45 typedef struct vgaimg
{
62 struct node
*left
, *right
;
68 typedef struct cache
{
74 typedef struct image
{
82 int SCRW
= 320; // public
83 int SCRH
= 200; // public
85 static int fullscreen
;
86 static rgb playpal
[256];
87 static byte bright
[256];
88 static GLuint lastTexture
;
92 static image scrnh
[3]; // TITLEPIC INTERPIC ENDPIC
93 static image ltn
[2][2];
96 static image smk_spr
[SMSN
];
97 static image smk_fspr
[FLSN
];
100 static image fx_spr
[15];
101 static char fx_sprd
[15];
104 static image wp_spr
[49*2];
105 static char wp_sprd
[49*2];
108 static image item_spr
[58];
109 static char item_sprd
[58];
112 static image plr_spr
[27*2];
113 static image plr_msk
[27*2];
114 static char plr_sprd
[27*2];
115 static image plr_wpn
[11][6];
118 static image pl_spr
[2];
119 static image pl_msk
[2];
120 static image mn_spr
[MN_TN
][29*2];
121 static image mn_man_msk
[29*2];
122 static char mn_sprd
[MN_TN
][29*2];
123 static image mn_fspr
[8];
124 static image mn_sgun
[2];
127 static image sth
[22];
128 static image bfh
[160 - '!'];
129 static image sfh
[160 - '!'];
132 static image keys
[3];
138 static image msklh
[2];
148 static const char *anm
[ANIT
- 1][5] = {
149 {"WALL22_1", "WALL23_1", "WALL23_2", NULL
, NULL
},
150 {"WALL58_1", "WALL58_2", "WALL58_3", NULL
, NULL
},
151 {"W73A_1", "W73A_2", NULL
, NULL
, NULL
},
152 {"RP2_1", "RP2_2", "RP2_3", "RP2_4", NULL
}
154 static int max_wall_width
;
155 static int max_wall_height
;
156 static int max_textures
;
157 static image walp
[256];
158 static byte walani
[256];
159 static image anip
[ANIT
][5];
160 static byte anic
[ANIT
];
165 // https://blackpawn.com/texts/lightmaps/
166 static node
*R_node_alloc (node
*p
, int w
, int h
) {
172 node
*n
= R_node_alloc(p
->left
, w
, h
);
173 return n
? n
: R_node_alloc(p
->right
, w
, h
);
175 int pw
= p
->r
- p
->l
+ 1;
176 int ph
= p
->b
- p
->t
+ 1;
177 if (p
->leaf
|| pw
< w
|| ph
< h
) {
179 } else if (pw
== w
&& ph
== h
) {
183 p
->left
= malloc(sizeof(node
));
184 p
->right
= malloc(sizeof(node
));
185 if (pw
- w
> ph
- h
) {
216 return R_node_alloc(p
->left
, w
, h
);
221 static int R_node_have_leaf (node
*n
) {
222 return n
&& (n
->leaf
|| R_node_have_leaf(n
->left
) || R_node_have_leaf(n
->right
));
225 static void R_node_free_recursive (node
*n
) {
227 R_node_free_recursive(n
->left
);
228 R_node_free_recursive(n
->right
);
233 static void R_node_free (node
*n
) {
235 //logo("free node %p {%i:%i:%i:%i}\n", n, n->l, n->t, n->r, n->b);
237 assert(n
->left
== NULL
);
238 assert(n
->right
== NULL
);
243 assert(p
->leaf
== 0);
246 if (R_node_have_leaf(p
) == 0) {
247 R_node_free_recursive(p
->left
);
249 R_node_free_recursive(p
->right
);
259 static void R_cache_get_max_texture_size (int *w
, int *h
) {
261 glGetIntegerv(GL_MAX_TEXTURE_SIZE
, &size
);
262 size
= min(max(size
, 0), 512); // more can be buggy on older hardware
267 static void R_gl_bind_texture (GLuint id
) {
268 if (id
!= lastTexture
) {
269 glBindTexture(GL_TEXTURE_2D
, id
);
273 static cache
*R_cache_new (void) {
277 R_cache_get_max_texture_size(&w
, &h
);
279 glGenTextures(1, &id
);
281 R_gl_bind_texture(id
);
282 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
283 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
284 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, w
, h
, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, NULL
);
285 c
= malloc(sizeof(cache
));
293 glDeleteTextures(1, &id
);
297 //logo("new cache %p\n", c);
301 static void R_cache_free (cache
*root
, int freetexture
) {
306 R_node_free_recursive(c
->root
.left
);
307 R_node_free_recursive(c
->root
.right
);
308 if (freetexture
&& c
->id
!= 0) {
309 glDeleteTextures(1, &c
->id
);
316 static node
*R_cache_alloc (cache
*root
, int w
, int h
) {
318 assert(w
> 0 && h
> 0);
323 R_cache_get_max_texture_size(&maxw
, &maxh
);
324 if (w
<= maxw
&& h
<= maxh
) {
326 n
= R_node_alloc(&c
->root
, w
, h
);
338 n
= R_node_alloc(&c
->root
, w
, h
);
347 //logo("new node %p {%i:%i:%i:%i}\n", n, n->l, n->t, n->r, n->b);
349 logo("new node failed {%i:%i}\n", w
, h
);
354 static void R_cache_update (node
*n
, const void *data
, int x
, int y
, int w
, int h
) {
361 assert(n
->l
+ x
+ w
- 1 <= n
->r
);
362 assert(n
->t
+ y
+ h
- 1 <= n
->b
);
363 R_gl_bind_texture(n
->base
->id
);
364 glTexSubImage2D(GL_TEXTURE_2D
, 0, n
->l
+ x
, n
->t
+ y
, w
, h
, GL_RGBA
, GL_UNSIGNED_BYTE
, data
);
367 /* Generic helpers */
369 static void R_init_playpal (void) {
371 byte
*vgapal
= M_lock(F_getresid("PLAYPAL"));
372 for (i
= 0; i
< 256; i
++) {
374 .r
= vgapal
[i
* 3 + 0] * 255 / 63,
375 .g
= vgapal
[i
* 3 + 1] * 255 / 63,
376 .b
= vgapal
[i
* 3 + 2] * 255 / 63,
378 bright
[i
] = ((int)vgapal
[i
* 3 + 0] + vgapal
[i
* 3 + 1] + vgapal
[i
* 3 + 2]) * 8 / (63 * 3);
383 static vgaimg
*R_getvga (int id
) {
384 int loaded
= M_was_locked(id
);
385 vgaimg
*v
= M_lock(id
);
386 if (v
!= NULL
&& !loaded
) {
387 v
->w
= short2host(v
->w
);
388 v
->h
= short2host(v
->h
);
389 v
->x
= short2host(v
->x
);
390 v
->y
= short2host(v
->y
);
395 static rgba
*R_extract_flame_spr (vgaimg
*v
) {
396 static const byte flametab
[16] = {
397 0xBC, 0xBA, 0xB8, 0xB6, 0xB4, 0xB2, 0xB0, 0xD5,
398 0xD6, 0xD7, 0xA1, 0xA0, 0xE3, 0xE2, 0xE1, 0xE0
401 rgba
*s
= malloc(v
->w
* v
->h
* sizeof(rgba
));
403 for (j
= 0; j
< v
->h
; j
++) {
404 for (i
= 0; i
< v
->w
; i
++) {
405 int k
= j
* v
->w
+ i
;
406 byte c
= v
->data
[k
] + bright
[DEFAULT_SKY_COLOR
];
408 .r
= playpal
[flametab
[c
]].r
,
409 .g
= playpal
[flametab
[c
]].g
,
410 .b
= playpal
[flametab
[c
]].b
,
411 .a
= v
->data
[k
] == VGA_TRANSPARENT_COLOR
? 0x00 : 0xFF,
419 static rgba
*R_extract_smoke_spr (vgaimg
*v
) {
421 rgba
*s
= malloc(v
->w
* v
->h
* sizeof(rgba
));
423 for (j
= 0; j
< v
->h
; j
++) {
424 for (i
= 0; i
< v
->w
; i
++) {
425 int k
= j
* v
->w
+ i
;
426 byte c
= ((v
->data
[k
] + bright
[DEFAULT_SKY_COLOR
]) + 0x60) ^ 0x0F;
427 byte a
= 0xFF - ((int)playpal
[c
].r
+ playpal
[c
].g
+ playpal
[c
].b
) / 3;
432 .a
= v
->data
[k
] == VGA_TRANSPARENT_COLOR
? 0x00 : a
,
440 static rgba
*R_extract_mask_spr (vgaimg
*v
) {
442 rgba
*s
= malloc(v
->w
* v
->h
* sizeof(rgba
));
444 for (j
= 0; j
< v
->h
; j
++) {
445 for (i
= 0; i
< v
->w
; i
++) {
446 int k
= j
* v
->w
+ i
;
448 if (c
>= 0x70 && c
<= 0x7F) {
449 byte mask
= c
- 0x70;
450 mask
= 0xFF - ((mask
<< 4) | mask
);
471 static rgba
*R_extract_rgba_spr (vgaimg
*v
) {
473 rgba
*s
= malloc(v
->w
* v
->h
* sizeof(rgba
));
475 for (j
= 0; j
< v
->h
; j
++) {
476 for (i
= 0; i
< v
->w
; i
++) {
477 int k
= j
* v
->w
+ i
;
483 .a
= c
== VGA_TRANSPARENT_COLOR
? 0x00 : 0xFF,
493 static image
R_gl_create_image (const rgba
*buf
, int w
, int h
) {
494 node
*n
= R_cache_alloc(root
, w
, h
);
496 R_cache_update(n
, buf
, 0, 0, w
, h
);
506 static image
R_gl_get_special_image (int id
, rgba
*(*fn
)(vgaimg
*)) {
509 //F_getresname(name, id);
510 //logo("load image: %.8s\n", name);
511 vgaimg
*v
= R_getvga(id
);
513 rgba
*buf
= (*fn
)(v
);
514 img
= R_gl_create_image(buf
, v
->w
, v
->h
);
528 static image
R_gl_getimage (int id
) {
529 return R_gl_get_special_image(id
, &R_extract_rgba_spr
);
532 static image
R_gl_loadimage (const char name
[8]) {
533 return R_gl_getimage(F_getresid(name
));
536 static image
R_gl_get_special_spr (const char n
[4], int s
, int d
, rgba
*(*fn
)(vgaimg
*)) {
537 return R_gl_get_special_image(F_getsprid(n
, s
, d
), fn
);
540 static void R_gl_free_image (image
*img
) {
541 if (img
->n
!= NULL
&& img
->res
>= 0) {
548 static void R_gl_draw_quad (int x
, int y
, int w
, int h
) {
550 glVertex2i(x
+ w
, y
);
552 glVertex2i(x
, y
+ h
);
553 glVertex2i(x
+ w
, y
+ h
);
557 static void R_gl_draw_textured (image
*img
, int x
, int y
, int w
, int h
, int flip
) {
559 GLfloat nw
= img
->n
->base
->root
.r
+ 1;
560 GLfloat nh
= img
->n
->base
->root
.b
+ 1;
561 GLfloat ax
= (flip
? img
->n
->l
: img
->n
->r
+ 1) / nw
;
562 GLfloat bx
= (flip
? img
->n
->r
+ 1 : img
->n
->l
) / nh
;
563 GLfloat ay
= (img
->n
->t
) / nw
;
564 GLfloat by
= (img
->n
->b
+ 1) / nh
;
565 R_gl_bind_texture(img
->n
->base
->id
);
566 glEnable(GL_TEXTURE_2D
);
568 glTexCoord2f(ax
, ay
); glVertex2i(x
+ w
, y
);
569 glTexCoord2f(bx
, ay
); glVertex2i(x
, y
);
570 glTexCoord2f(bx
, by
); glVertex2i(x
, y
+ h
);
571 glTexCoord2f(ax
, by
); glVertex2i(x
+ w
, y
+ h
);
574 glColor3ub(255, 0, 0);
576 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
577 glDisable(GL_TEXTURE_2D
);
578 R_gl_draw_quad(x
, y
, w
, h
);
582 /* fit image into rectangle without applying offset and transparency */
583 static void R_gl_draw_image_ext (image
*img
, int x
, int y
, int w
, int h
) {
585 glColor3ub(255, 255, 255);
586 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
587 R_gl_draw_textured(img
, x
, y
, w
, h
, 0);
590 /* draw sprite with offset and coloring */
591 static void R_gl_draw_image_color (image
*img
, int x
, int y
, int flip
) {
592 int xx
= flip
? x
- img
->w
+ img
->x
: x
- img
->x
;
594 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
595 R_gl_draw_textured(img
, xx
, y
- img
->y
, img
->w
, img
->h
, flip
);
598 /* draw sprite with offset */
599 static void R_gl_draw_image (image
*img
, int x
, int y
, int flip
) {
600 glColor3ub(255, 255, 255);
601 R_gl_draw_image_color(img
, x
, y
, flip
);
604 static void R_gl_set_color (byte c
) {
605 glColor3ub(playpal
[c
].r
, playpal
[c
].g
, playpal
[c
].b
);
608 static void R_gl_setclip (int x
, int y
, int w
, int h
) {
609 glScissor(x
, SCRH
- h
- y
, w
, h
);
612 static void R_gl_setmatrix (void) {
613 glScissor(0, 0, SCRW
, SCRH
);
614 glViewport(0, 0, SCRW
, SCRH
);
615 glMatrixMode(GL_PROJECTION
);
617 glOrtho(0, SCRW
, SCRH
, 0, 0, 1);
618 glMatrixMode(GL_MODELVIEW
);
624 static image
Z_getspr (const char n
[4], int s
, int d
, char *dir
) {
625 int h
= F_getsprid(n
, s
, d
);
627 *dir
= (h
& 0x8000) ? 1 : 0;
629 return R_gl_getimage(h
);
632 static void Z_putch_generic (image img
[], int off
, int ch
) {
634 if (ch
> 32 && ch
< 160) {
637 p
= &img
[toupper(ch
) - '!'];
640 if (p
!= NULL
&& p
->n
!= NULL
) {
641 R_gl_draw_image(p
, prx
, pry
, 0);
648 static void Z_printf_generic (image img
[], int off
, const char *fmt
, va_list ap
) {
651 vsprintf(buf
, fmt
, ap
);
652 for (i
= 0; buf
[i
]; ++i
) {
660 Z_putch_generic(img
, off
, (byte
)buf
[i
]);
665 static void Z_gotoxy (int x
, int y
) {
670 static void Z_printbf (const char *fmt
, ...) {
673 Z_printf_generic(bfh
, 12, fmt
, a
);
677 static void Z_printsf (const char *fmt
, ...) {
680 Z_printf_generic(sfh
, 7, fmt
, a
);
684 static void Z_printhf (const char *fmt
, ...) {
689 vsprintf(buf
, fmt
, a
);
691 for (i
= 0; buf
[i
]; ++i
) {
722 R_gl_draw_image(&sth
[c
], prx
, pry
, 0);
730 static image
*PL_getspr (int s
, int d
, int msk
) {
731 int i
= (s
- 'A') * 2 + d
;
732 return msk
? &plr_msk
[i
] : &plr_spr
[i
];
735 static int count_menu_entries (const new_menu_t
*m
) {
738 while (m
->entries
[i
].type
!= 0) {
744 static int count_menu_xoff (const new_menu_t
*m
, int sz
) {
748 // TODO change sz with real pixel width
749 int x
= strlen(m
->title
) * (sz
+ 1);
750 int n
= count_menu_entries(m
);
751 for (i
= 0; i
< n
; i
++) {
752 switch (m
->entries
[i
].type
) {
755 len
= 24 * 8; // TODO get real maxlen
757 default: len
= strlen(m
->entries
[i
].caption
) * (sz
+ 1); break;
764 static int GM_draw (void) {
765 int i
, j
, xoff
, yoff
, n
, x
, y
, cx
, cy
, cur
, curoff
, curmod
;
766 const new_menu_t
*m
= GM_get();
771 n
= count_menu_entries(m
);
772 y
= cy
- (n
* 16 - 20) / 2;
778 x
= cx
- count_menu_xoff(m
, 12) / 2;
780 Z_printbf("%s", m
->title
);
784 x
= cx
- count_menu_xoff(m
, 7) / 2;
786 Z_printsf("%s", m
->title
);
794 for (i
= 0; i
< n
; i
++) {
797 curmod
= m
->entries
[i
].type
== GM_SMALL_BUTTON
? 1 : 0;
799 switch (m
->entries
[i
].type
) {
801 Z_gotoxy(x
, y
+ yoff
);
802 Z_printbf("%s", m
->entries
[i
].caption
);
805 case GM_SMALL_BUTTON
:
806 Z_gotoxy(x
, y
+ yoff
);
807 Z_printsf("%s", m
->entries
[i
].caption
);
811 case GM_TEXTFIELD_BUTTON
:
812 Z_gotoxy(x
, y
+ yoff
);
813 Z_printbf("%s", m
->entries
[i
].caption
);
814 xoff
= strlen(m
->entries
[i
].caption
) * 19;
816 R_gl_draw_image(&mslotl
, x
+ xoff
, y
+ yoff
, 0);
817 for (j
= 1; j
< 23; j
++) {
818 R_gl_draw_image(&mslotm
, x
+ xoff
+ j
* 8, y
+ yoff
, 0);
820 R_gl_draw_image(&mslotr
, x
+ xoff
+ j
* 8, y
+ yoff
, 0);
821 Z_gotoxy(x
+ xoff
+ 4, y
+ yoff
- 7);
822 if (input
&& i
== cur
) {
823 Z_printsf("%.*s", GM_MAX_INPUT
, ibuf
);
824 Z_gotoxy(x
+ xoff
+ 4 + 8 * icur
, y
+ yoff
- 7);
827 msg
.type
= GM_GETSTR
;
828 if (GM_send(m
, i
, &msg
)) {
829 Z_printsf("%.*s", msg
.string
.maxlen
, msg
.string
.s
);
835 Z_gotoxy(x
, y
+ yoff
);
836 Z_printbf("%s", m
->entries
[i
].caption
);
837 xoff
= strlen(m
->entries
[i
].caption
) * 19;
838 R_gl_draw_image(&mbarl
, x
+ xoff
, y
+ yoff
, 0);
839 for (j
= 1; j
< 9; j
++) {
840 R_gl_draw_image(&mbarm
, x
+ xoff
+ j
* 8, y
+ yoff
, 0);
842 R_gl_draw_image(&mbarr
, x
+ xoff
+ j
* 8, y
+ yoff
, 0);
843 msg
.type
= GM_GETINT
;
844 if (GM_send(m
, i
, &msg
)) {
845 int lev
= (msg
.integer
.i
- msg
.integer
.a
) * (7 * 8) / msg
.integer
.b
;
846 R_gl_draw_image(&mbaro
, x
+ xoff
+ lev
+ 8, y
+ yoff
, 0);
856 Z_gotoxy(x
- 8, y
+ curoff
);
859 R_gl_draw_image(&msklh
[(gm_tm
/ 6) & 1], x
- 25, y
+ curoff
- 8, 0);
866 static void GM_draw (void) {
867 enum {MENU, MSG}; // copypasted from menu.c!
869 CANCEL, NEWGAME, LOADGAME, SAVEGAME, OPTIONS, QUITGAME, QUIT, ENDGAME, ENDGM,
870 PLR1, PLR2, COOP, DM, VOLUME, GAMMA, LOAD, SAVE, PLCOLOR, PLCEND, MUSIC, INTERP,
871 SVOLM, SVOLP, MVOLM, MVOLP, GAMMAM, GAMMAP, PL1CM, PL1CP, PL2CM, PL2CP
872 }; // copypasted from menu.c!
873 int i, j, k, x, y, cx, cy;
879 if (mnu->type == MENU) {
880 y = cy - (mnu->n * 16 - 20) / 2;
881 Z_gotoxy(cx - mnu->x, y - 10); Z_printbf("%s", mnu->ttl);
882 for (i = 0; i < mnu->n; i++) {
883 if (mnu->t[i] == LOAD || mnu->t[i] == SAVE) {
885 R_gl_draw_image(&mslotl, cx - mnu->x, j, 0);
886 for (k = 8; k < 184; k += 8) {
887 R_gl_draw_image(&mslotm, cx - mnu->x + k, j, 0);
889 R_gl_draw_image(&mslotr, cx - mnu->x + 184, j, 0);
890 Z_gotoxy(cx - mnu->x + 4, j - 8);
891 if (input && i == save_mnu.cur) {
892 Z_printsf("%s_", ibuf);
894 Z_printsf("%s", savname[i]);
897 x = mnu->t[i] >= SVOLM ? (mnu->t[i] >= PL1CM ? 50 : 152) : 0;
898 Z_gotoxy(cx - mnu->x + x, y + i * 16 + 20);
899 Z_printbf("%s", mnu->m[i]);
902 Z_printbf(" '%s'", g_music);
905 Z_printbf("%s", fullscreen ? "ON" : "OFF");
911 img = PL_getspr(*panimp, 0, 0);
912 R_gl_draw_image(img, cx - mnu->x + (mnu->t[i] == PL1CM ? 15 : 35), y + i * 16 + 20 + 14, 0);
913 img = PL_getspr(*panimp, 0, 1);
914 R_gl_set_color(pcolortab[(mnu->t[i] == PL1CM) ? p1color : p2color] + PLAYER_COLOR_OFFSET);
915 R_gl_draw_image_color(img, cx - mnu->x + (mnu->t[i] == PL1CM ? 15 : 35), y + i * 16 + 20 + 14, 0);
924 R_gl_draw_image(&mbarl, cx - mnu->x, j, 0);
925 for (k = 8; k < 144; k += 8) {
926 R_gl_draw_image(&mbarm, cx - mnu->x + k, j, 0);
928 R_gl_draw_image(&mbarr, cx - mnu->x + 144, j, 0);
943 R_gl_draw_image(&mbaro, cx - mnu->x + 8 + k, j, 0);
948 R_gl_draw_image(&msklh[(gm_tm / 6) & 1], cx - mnu->x - 25, y + mnu->cur * 16 + 20 - 8, 0);
949 } else if (mnu->type == MSG) {
950 Z_gotoxy(cx - strlen(mnu->ttl) * 7 / 2, cy - 10); Z_printsf(mnu->ttl);
951 Z_gotoxy(cx - 24, SCRH / 2); Z_printsf("(Y/N)");
953 ERR_fatal("Unknown menu type %i\n", mnu->type);
961 static void R_draw_fld (byte
*fld
, int minx
, int miny
, int maxx
, int maxy
, int fg
) {
963 assert(minx
>= 0 && minx
<= FLDW
);
964 assert(miny
>= 0 && miny
<= FLDH
);
965 assert(maxx
>= 0 && maxx
<= FLDW
);
966 assert(maxy
>= 0 && maxy
<= FLDH
);
967 for (j
= miny
; j
< maxy
; j
++) {
968 for (i
= minx
; i
< maxx
; i
++) {
969 byte id
= fld
[j
* FLDW
+ i
];
971 if (walp
[id
].res
< 0) {
973 switch (R_get_special_id(id
)) {
975 glColor4ub(0, 0, 255, 127);
978 glColor4ub(0, 127, 0, 127);
981 glColor4ub(127, 0, 0, 127);
984 glColor4ub(0, 0, 0, 127);
988 glBlendFunc(GL_DST_COLOR
, GL_SRC_COLOR
);
989 glDisable(GL_TEXTURE_2D
);
990 R_gl_draw_quad(i
* CELW
, j
* CELW
, CELW
, CELH
);
993 R_gl_draw_image(&walp
[id
], i
* CELW
, j
* CELH
, 0);
1000 static void R_draw_dots (void) {
1002 glDisable(GL_BLEND
);
1003 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
1004 glDisable(GL_TEXTURE_2D
);
1006 for (i
= 0; i
< MAXDOT
; i
++) {
1007 if (dot
[i
].t
!= 0) {
1008 R_gl_set_color(dot
[i
].c
);
1009 glVertex2i(dot
[i
].o
.x
, dot
[i
].o
.y
+ 1);
1015 static void R_draw_items (void) {
1017 for (i
= 0; i
< MAXITEM
; ++i
) {
1019 if (it
[i
].t
&& it
[i
].s
>= 0) {
1020 switch (it
[i
].t
& 0x7FFF) {
1022 s
= it
[i
].s
/ 9 + 18;
1025 s
= it
[i
].s
/ 9 + 20;
1028 s
= it
[i
].s
/ 2 + 22;
1031 s
= it
[i
].s
/ 2 + 26;
1037 s
= it
[i
].s
/ 2 + (it
[i
].t
- I_SUPER
) * 4 + 35;
1039 case I_GOR1
: case I_FCAN
:
1040 s
= it
[i
].s
/ 2 + (it
[i
].t
- I_GOR1
) * 3 + 51;
1051 s
= (it
[i
].t
& 0x7FFF) - I_KEYR
+ 31;
1057 s
= (it
[i
].t
& 0x7FFF) - 1;
1061 R_gl_draw_image(&item_spr
[s
], it
[i
].o
.x
, it
[i
].o
.y
, item_sprd
[s
]);
1066 static int standspr (player_t
*p
) {
1067 if (p
->f
& PLF_UP
) {
1069 } else if (p
->f
& PLF_DOWN
) {
1076 static int wpnspr (player_t
*p
) {
1077 if (p
->f
& PLF_UP
) {
1079 } else if(p
->f
& PLF_DOWN
) {
1086 static void R_draw_player (player_t
*p
) {
1087 enum {STAND
, GO
, DIE
, SLOP
, DEAD
, MESS
, OUT
, FALL
}; // copypasted from player.c!
1088 static const int wytab
[] = {-1, -2, -1, 0};
1095 if (p
->f
& PLF_FIRE
) {
1096 s
= standspr(p
) + 1;
1098 } else if (p
->pain
) {
1121 s
= plr_goanim
[p
->s
/ 8];
1122 w
= (p
->f
& PLF_FIRE
) ? 'B' : 'A';
1124 wy
= 1 + wytab
[s
- 'A'];
1128 s
= plr_dieanim
[p
->s
];
1131 s
= plr_slopanim
[p
->s
];
1141 R_gl_draw_image(&plr_wpn
[(int)p
->wpn
][w
-'A'], p
->o
.x
+ wx
, p
->o
.y
+ wy
, p
->d
);
1144 R_gl_draw_image(&plr_spr
[(s
- 'A') * 2 + p
->d
], p
->o
.x
, p
->o
.y
, plr_sprd
[(s
- 'A') * 2 + p
->d
]);
1145 R_gl_set_color(p
->color
+ PLAYER_COLOR_OFFSET
);
1146 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
]);
1150 static void R_draw_monsters (void) {
1151 enum {SLEEP
, GO
, RUN
, CLIMB
, DIE
, DEAD
, ATTACK
, SHOOT
, PAIN
, WAIT
, REVIVE
, RUNOUT
}; // copypasted from monster.c!
1153 for (i
= 0; i
< MAXMN
; i
++) {
1154 if (mn
[i
].t
!= MN_NONE
) {
1157 if (mn
[i
].t
< MN__LAST
) {
1158 if ((mn
[i
].t
!= MN_SOUL
&& mn
[i
].t
!= MN_PAIN
) || mn
[i
].st
!= DEAD
) {
1159 int ap
= mn
[i
].ap
[mn
[i
].ac
];
1160 int d
= (ap
- 'A') * 2 + mn
[i
].d
;
1161 int dir
= mn_sprd
[mn
[i
].t
- 1][d
];
1162 if (mn
[i
].t
== MN_MAN
&& (ap
== 'E' || ap
== 'F')) {
1163 R_gl_draw_image(&mn_sgun
[ap
- 'E'], x
, y
, mn
[i
].d
);
1165 R_gl_draw_image(&mn_spr
[mn
[i
].t
- 1][d
], x
, y
, dir
);
1166 if (mn
[i
].t
== MN_MAN
) {
1167 R_gl_set_color(MANCOLOR
+ PLAYER_COLOR_OFFSET
);
1168 R_gl_draw_image_color(&mn_man_msk
[d
], x
, y
, dir
);
1171 if (mn
[i
].t
== MN_VILE
&& mn
[i
].st
== SHOOT
) {
1172 R_gl_draw_image(&mn_fspr
[mn
[i
].ac
/ 3], mn
[i
].tx
, mn
[i
].ty
, 0);
1174 } else if (mn
[i
].t
== MN_PL_DEAD
|| mn
[i
].t
== MN_PL_MESS
) {
1175 int type
= mn
[i
].t
- MN_PL_DEAD
;
1176 R_gl_draw_image(&pl_spr
[type
], x
, y
, 0);
1177 R_gl_set_color(mn
[i
].d
);
1178 R_gl_draw_image_color(&pl_msk
[type
], x
, y
, 0);
1184 static void R_draw_weapons (void) {
1185 enum {NONE
, ROCKET
, PLASMA
, APLASMA
, BALL1
, BALL2
, BALL7
, BFGBALL
, BFGHIT
, MANF
, REVF
, FIRE
}; // copypasted from weapons.c!
1187 for (i
= 0; i
< MAXWPN
; ++i
) {
1195 d
= wp
[i
].o
.xv
> 0 ? 1 : 0;
1196 x
= abs(wp
[i
].o
.xv
);
1209 s
= (d
- 2) / 2 + 1;
1243 d
= wp
[i
].o
.xv
>= 0 ? 1 : 0;
1247 d
= wp
[i
].o
.xv
>=0 ? 1 : 0;
1259 s
= wp
[i
].s
/ 2 + 26;
1263 R_gl_draw_image(&wp_spr
[s
* 2 + d
], wp
[i
].o
.x
, wp
[i
].o
.y
, wp_sprd
[s
* 2 + d
]);
1268 static void R_draw_smoke (void) {
1270 for (i
= 0; i
< MAXSMOK
; ++i
) {
1275 if (s
>= (SMSN
- 1) * 3) {
1278 s
= SMSN
- 1 - s
/ 3;
1280 R_gl_draw_image(&smk_spr
[s
], sm
[i
].x
>> 8, (sm
[i
].y
>> 8) + 1, 0);
1284 if (s
>= FLSN
- 1) {
1289 R_gl_draw_image(&smk_fspr
[s
], sm
[i
].x
>> 8, (sm
[i
].y
>> 8) + 1, 0);
1296 static void R_draw_effects (void) {
1297 enum {NONE
, TFOG
, IFOG
, BUBL
}; // copypasted from fx.c
1299 for (i
= 0; i
< MAXFX
; ++i
) {
1303 R_gl_draw_image(&fx_spr
[s
], fx
[i
].x
, fx
[i
].y
, fx_sprd
[s
]);
1306 s
= fx
[i
].s
/ 2 + 10;
1307 R_gl_draw_image(&fx_spr
[s
], fx
[i
].x
, fx
[i
].y
, fx_sprd
[s
]);
1310 glDisable(GL_BLEND
);
1311 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
1312 glDisable(GL_TEXTURE_2D
);
1314 R_gl_set_color(0xC0 + fx
[i
].s
);
1315 glVertex2i(fx
[i
].x
>> 8, (fx
[i
].y
>> 8) + 1);
1322 static int get_pu_st (int t
) {
1323 if (t
>= PL_FLASH
) {
1325 } else if((t
/ 9) & 1) {
1332 static void R_draw_view (int x
, int y
, int w
, int h
, int camx
, int camy
) {
1334 R_gl_setclip(x
, y
, w
, h
);
1335 glTranslatef(x
, y
, 0);
1336 if (w_horiz
&& horiz
.n
!= NULL
) {
1337 R_gl_draw_image_ext(&horiz
, 0, 0, w
, h
);
1338 if (sky_type
== 2 && lt_time
< 0) {
1339 image
*tanderbolt
= <n
[lt_type
][lt_time
< -5 ? 0 : 1];
1341 R_gl_draw_image(tanderbolt
, 0, lt_ypos
, 0);
1343 R_gl_draw_image(tanderbolt
, w
- 1, lt_ypos
, 1);
1347 glDisable(GL_BLEND
);
1348 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
1349 glDisable(GL_TEXTURE_2D
);
1350 R_gl_set_color(DEFAULT_SKY_COLOR
);
1351 R_gl_draw_quad(0, 0, w
, h
);
1353 int maxx
= min((camx
+ w
) / CELW
+ 1, FLDW
);
1354 int maxy
= min((camy
+ h
) / CELH
+ 1, FLDH
);
1355 int minx
= max((camx
- max_wall_width
) / CELW
, 0);
1356 int miny
= max((camy
- max_wall_height
) / CELH
, 0);
1357 glTranslatef(-camx
, -camy
, 0);
1358 R_draw_fld((byte
*)fldb
, minx
, miny
, maxx
, maxy
, 0);
1361 R_draw_player(&pl1
);
1363 R_draw_player(&pl2
);
1369 R_draw_fld((byte
*)fldf
, minx
, miny
, maxx
, maxy
, 1);
1370 glTranslatef(camx
, camy
, 0);
1371 if (sky_type
== 2 && (lt_time
== -4 || lt_time
== -2)) {
1372 glColor4ub(255, 255, 255, 255);
1374 glBlendFunc(GL_DST_COLOR
, GL_SRC_COLOR
);
1375 glDisable(GL_TEXTURE_2D
);
1376 R_gl_draw_quad(0, 0, w
, h
);
1381 static void R_draw_player_view (player_t
*p
, int x
, int y
, int w
, int h
) {
1382 p
->looky
= min(max(p
->looky
, -SCRH
/ 4), SCRH
/ 4); // TODO remove writeback
1385 int cx
= min(max(p
->o
.x
, cw
/ 2), FLDW
* CELW
- cw
/ 2);
1386 int cy
= min(max(p
->o
.y
- 12 + p
->looky
, h
/ 2), FLDH
* CELH
- h
/ 2);
1387 int camx
= max(cx
- cw
/ 2, 0);
1388 int camy
= max(cy
- h
/ 2, 0);
1390 R_draw_view(x
, y
+ 1, cw
, h
- 2, camx
, camy
);
1391 glTranslatef(x
, y
, 0);
1393 if (get_pu_st(p
->invl
)) {
1395 glBlendFunc(GL_ONE_MINUS_DST_COLOR
, GL_ZERO
);
1396 glDisable(GL_TEXTURE_2D
);
1397 glColor4ub(191, 191, 191, 255);
1398 R_gl_draw_quad(0, 0, cw
, h
);
1401 if (p
->suit
&& get_pu_st(p
->suit
)) {
1403 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
1404 glDisable(GL_TEXTURE_2D
);
1405 glColor4ub(0, 255, 0, 192);
1406 R_gl_draw_quad(0, 0, cw
, h
);
1408 int f
= min(max(p
->pain
* 3, 0), 255);
1411 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
1412 glDisable(GL_TEXTURE_2D
);
1413 glColor4ub(255, 0, 0, f
);
1414 R_gl_draw_quad(0, 0, cw
, h
);
1417 R_gl_setclip(x
, y
, w
, h
);
1418 glTranslatef(-x
+ cw
, 0, 0);
1419 R_gl_draw_image(&stone
, 0, 0, 0);
1422 R_gl_draw_image(&stone2
, 0, i
, 0);
1425 if (p
->drawst
& PL_DRAWAIR
) {
1426 if (p
->air
< PL_AIR
) {
1427 int a
= min(max(p
->air
, 0), MAXAIR
) * 100 / MAXAIR
;
1428 glDisable(GL_BLEND
);
1429 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
1430 glDisable(GL_TEXTURE_2D
);
1431 R_gl_set_color(0xC8);
1432 R_gl_draw_quad(10, 49, a
, 2);
1435 if (p
->drawst
& PL_DRAWLIFE
) {
1437 Z_printhf("%3d%%", p
->life
);
1439 if (p
->drawst
& PL_DRAWARMOR
) {
1440 Z_gotoxy(10, 7 + 19);
1441 Z_printhf("%3d%%", p
->armor
);
1443 if (p
->drawst
& PL_DRAWWPN
) {
1470 R_gl_draw_image(&sth
[12 + p
->wpn
], st
- 88, 58 + 19, 0);
1474 Z_gotoxy(st
- 10 - 5 * 14, 58 + 2);
1475 Z_printhf("%5d", i
);
1478 if (p
->drawst
& PL_DRAWFRAG
&& g_dm
) {
1479 Z_gotoxy(st
- 5 - 5 * 14, 77 + 5);
1480 Z_printhf("%5d", p
->frag
);
1482 if (p
->drawst
& PL_DRAWKEYS
) {
1484 for (k
= p
->keys
>> 4, n
= 0, x
= st
- 75; n
< 3; n
++, k
>>= 1, x
+= 9) {
1486 R_gl_draw_image(&keys
[n
], x
, 91, 0);
1490 if (p
->drawst
& PL_DRAWLIVES
&& !_2pl
) {
1491 Z_gotoxy(st
- 35, 17);
1492 Z_printhf("%d", p
->lives
);
1499 static void pl_info (player_t
*p
, int x
, int y
) {
1500 dword t
= p
->kills
* 10920 / g_time
;
1501 Z_gotoxy(x
+ 25, y
); Z_printbf("KILLS");
1502 Z_gotoxy(x
+ 25, y
+ 15); Z_printbf("KPM");
1503 Z_gotoxy(x
+ 25, y
+ 30); Z_printbf("SECRETS %u / %u", p
->secrets
, sw_secrets
);
1504 Z_gotoxy(x
+ 255, y
); Z_printbf("%u", p
->kills
);
1505 Z_gotoxy(x
+ 255, y
+ 15); Z_printbf("%u.%u", t
/ 10, t
% 10);
1508 static void R_draw_intermission (void) {
1511 Z_gotoxy(cx
- 14*12/2, 20);
1512 Z_printbf("LEVEL COMPLETE");
1513 Z_calc_time(g_time
, &hr
, &mn
, &sc
);
1514 Z_gotoxy(cx
- 12*12/2, 40);
1515 Z_printbf("TIME %u:%02u:%02u", hr
, mn
, sc
);
1518 Z_gotoxy(cx
- 10*12/2, h
);
1519 Z_printbf("PLAYER ONE");
1522 pl_info(&pl1
, cx
- 160, h
);
1524 h
+= 30 + SCRH
/ 10;
1525 Z_gotoxy(cx
- 10*12/2, h
);
1526 Z_printbf("PLAYER TWO");
1528 pl_info(&pl2
, cx
- 160, h
);
1532 static void W_act (void) {
1534 if (g_time
% 3 == 0) {
1535 for (i
= 1; i
< max_textures
; i
++) {
1539 if (anip
[a
][anic
[a
]].res
== -1) {
1542 walp
[i
] = anip
[a
][anic
[a
]];
1548 void R_draw (void) {
1550 glClearColor(0, 0, 0, 1);
1551 glClear(GL_COLOR_BUFFER_BIT
);
1552 glEnable(GL_SCISSOR_TEST
);
1563 R_gl_draw_image_ext(&scrnh
[0], 0, 0, SCRW
, SCRH
);
1566 R_gl_draw_image_ext(&scrnh
[1], 0, 0, SCRW
, SCRH
);
1567 R_draw_intermission();
1570 R_gl_draw_image_ext(&scrnh
[2], 0, 0, SCRW
, SCRH
);
1574 R_draw_player_view(&pl1
, 0, 0, SCRW
, SCRH
/ 2);
1575 R_draw_player_view(&pl2
, 0, SCRH
/ 2, SCRW
, SCRH
/ 2);
1577 R_draw_player_view(&pl1
, 0, 0, SCRW
, SCRH
);
1579 R_gl_setclip(0, 0, SCRW
, SCRH
);
1586 void R_alloc (void) {
1589 logo("R_alloc: load graphics\n");
1591 scrnh
[0] = R_gl_loadimage("TITLEPIC");
1592 scrnh
[1] = R_gl_loadimage("INTERPIC");
1593 scrnh
[2] = R_gl_loadimage("ENDPIC");
1594 for (i
= 0; i
< 2; i
++) {
1595 sprintf(s
, "LTN%c", '1' + i
);
1596 for (j
= 0; j
< 2; j
++) {
1597 ltn
[i
][j
] = Z_getspr(s
, j
, 0, NULL
);
1601 for (i
= 0; i
< SMSN
; i
++) {
1602 smk_spr
[i
] = R_gl_get_special_spr("SMOK", i
, 0, &R_extract_smoke_spr
);
1604 for (i
= 0; i
< FLSN
; i
++) {
1605 smk_fspr
[i
] = R_gl_get_special_spr("SMOK", i
, 0, &R_extract_flame_spr
);
1608 for (i
= 0; i
< 10; i
++) {
1609 fx_spr
[i
] = Z_getspr("TFOG", i
, 0, fx_sprd
+ i
);
1611 for (; i
< 15; i
++) {
1612 fx_spr
[i
] = Z_getspr("IFOG", i
- 10, 0, fx_sprd
+ i
);
1615 for (i
= 0; i
< 4; i
++) {
1616 wp_spr
[i
* 2] = Z_getspr("MISL", i
, 1, wp_sprd
+ i
* 2);
1617 wp_spr
[i
* 2 + 1] = Z_getspr("MISL", i
, 2, wp_sprd
+ i
* 2 + 1);
1619 for (; i
< 6; i
++) {
1620 wp_spr
[i
* 2] = Z_getspr("PLSS", i
- 4, 1, wp_sprd
+ i
* 2);
1621 wp_spr
[i
* 2 + 1] = Z_getspr("PLSS", i
- 4, 2, wp_sprd
+ i
* 2 + 1);
1623 for (; i
< 11; i
++) {
1624 wp_spr
[i
* 2] = Z_getspr("PLSE", i
- 6, 1, wp_sprd
+ i
* 2);
1625 wp_spr
[i
* 2 + 1] = Z_getspr("PLSE", i
- 6, 2, wp_sprd
+ i
* 2 + 1);
1627 for (; i
< 13; i
++) {
1628 wp_spr
[i
* 2] = Z_getspr("APLS", i
- 11, 1, wp_sprd
+ i
* 2);
1629 wp_spr
[i
* 2 + 1] = Z_getspr("APLS", i
- 11, 2, wp_sprd
+ i
* 2 + 1);
1631 for (; i
< 18; i
++) {
1632 wp_spr
[i
* 2] = Z_getspr("APBX", i
- 13, 1, wp_sprd
+ i
* 2);
1633 wp_spr
[i
* 2 + 1] = Z_getspr("APBX", i
- 13, 2, wp_sprd
+ i
* 2 + 1);
1635 for(; i
< 20; i
++) {
1636 wp_spr
[i
* 2] = Z_getspr("BFS1", i
- 18, 1, wp_sprd
+ i
* 2);
1637 wp_spr
[i
* 2 + 1] = Z_getspr("BFS1", i
- 18, 2, wp_sprd
+ i
* 2 + 1);
1639 for (; i
< 26; i
++) {
1640 wp_spr
[i
* 2] = Z_getspr("BFE1", i
- 20, 1, wp_sprd
+ i
* 2);
1641 wp_spr
[i
* 2 + 1] = Z_getspr("BFE1", i
- 20, 2, wp_sprd
+ i
* 2 + 1);
1643 for (; i
< 30; i
++) {
1644 wp_spr
[i
* 2] = Z_getspr("BFE2", i
- 26, 1, wp_sprd
+ i
* 2);
1645 wp_spr
[i
* 2 + 1] = Z_getspr("BFE2", i
- 26, 2, wp_sprd
+ i
* 2 + 1);
1647 for (; i
< 32; i
++) {
1648 wp_spr
[i
* 2] = Z_getspr("MISL", i
- 30 + 4, 1, wp_sprd
+ i
* 2);
1649 wp_spr
[i
* 2 + 1] = Z_getspr("MISL", i
- 30 + 4, 2, wp_sprd
+ i
* 2 + 1);
1651 for (; i
< 37; i
++) {
1652 wp_spr
[i
* 2] = Z_getspr("BAL1", i
- 32, 1, wp_sprd
+ i
* 2);
1653 wp_spr
[i
* 2 + 1] = Z_getspr("BAL1", i
- 32, 2, wp_sprd
+ i
* 2 + 1);
1655 for (; i
< 42; i
++) {
1656 wp_spr
[i
* 2] = Z_getspr("BAL7", i
- 37, 1, wp_sprd
+ i
* 2);
1657 wp_spr
[i
* 2 + 1] = Z_getspr("BAL7", i
- 37, 2, wp_sprd
+ i
* 2 + 1);
1659 for (; i
< 47; i
++) {
1660 wp_spr
[i
* 2] = Z_getspr("BAL2", i
- 42, 1, wp_sprd
+ i
* 2);
1661 wp_spr
[i
* 2 + 1] = Z_getspr("BAL2", i
- 42, 2, wp_sprd
+ i
* 2 + 1);
1663 for (; i
< 49; i
++) {
1664 wp_spr
[i
* 2] = Z_getspr("MANF", i
- 47, 1, wp_sprd
+ i
* 2);
1665 wp_spr
[i
* 2 + 1] = Z_getspr("MANF", i
- 47, 2, wp_sprd
+ i
* 2 + 1);
1668 static const char snm
[18][4] = {
1669 "CLIP", "SHEL", "ROCK", "CELL", "AMMO", "SBOX", "BROK", "CELP",
1670 "STIM", "MEDI", "BPAK",
1671 "CSAW", "SHOT", "SGN2", "MGUN", "LAUN", "PLAS", "BFUG"
1673 static const char n4
[4][4] = {
1674 "SOUL", "SMRT", "SMGT", "SMBT"
1676 static const char n3
[2][4] = {
1679 for (i
= 0; i
< 18; i
++) {
1680 item_spr
[i
] = Z_getspr(snm
[i
], 0, 0, item_sprd
+ i
);
1682 for (; i
< 20; i
++) {
1683 item_spr
[i
] = Z_getspr("ARM1", i
- 18, 0, item_sprd
+ i
);
1684 item_spr
[i
+ 2] = Z_getspr("ARM2", i
- 18, 0, item_sprd
+ i
);
1687 for (; i
< 26; i
++) {
1688 item_spr
[i
] = Z_getspr("MEGA", i
- 22, 0, item_sprd
+ i
);
1690 for (; i
< 30; i
++) {
1691 item_spr
[i
] = Z_getspr("PINV", i
- 26, 0, item_sprd
+ i
);
1693 item_spr
[30] = Z_getspr("AQUA", 0, 0, item_sprd
+ 30);
1694 item_spr
[31] = Z_getspr("KEYR", 0, 0, item_sprd
+ 31);
1695 item_spr
[32] = Z_getspr("KEYG", 0, 0, item_sprd
+ 32);
1696 item_spr
[33] = Z_getspr("KEYB", 0, 0, item_sprd
+ 33);
1697 item_spr
[34] = Z_getspr("SUIT", 0, 0, item_sprd
+ 34);
1698 for (n
= 35, j
= 0; j
< 4; j
++) {
1699 for (i
= 0; i
< 4; i
++, n
++) {
1700 item_spr
[n
] = Z_getspr(n4
[j
], i
, 0, item_sprd
+ n
);
1703 for (j
= 0; j
< 2; j
++) {
1704 for (i
= 0; i
< 3; i
++, n
++) {
1705 item_spr
[n
] = Z_getspr(n3
[j
], i
, 0, item_sprd
+ n
);
1708 item_spr
[57] = Z_getspr("GUN2", 0, 0, item_sprd
+ 57);
1710 for (i
= 0; i
< 27; i
++) {
1711 plr_spr
[i
* 2] = Z_getspr("PLAY", i
, 1, plr_sprd
+ i
* 2);
1712 plr_msk
[i
* 2] = R_gl_get_special_spr("PLAY", i
, 1, &R_extract_mask_spr
);
1713 plr_spr
[i
* 2 + 1] = Z_getspr("PLAY", i
, 2, plr_sprd
+ i
* 2 + 1);
1714 plr_msk
[i
* 2 + 1] = R_gl_get_special_spr("PLAY", i
, 2, &R_extract_mask_spr
);
1716 strncpy(s
, "PWPx", 4);
1717 for (i
= 1; i
< 11; i
++) {
1718 s
[3] = (i
< 10 ? '0' : 'A' - 10) + i
;
1719 for (j
= 0; j
< 6; j
++) {
1720 plr_wpn
[i
][j
] = Z_getspr(s
, j
, 1, NULL
);
1724 static const char msn
[MN_TN
][4] = {
1725 "SARG", "TROO", "POSS", "SPOS", "CYBR", "CPOS", "BOSS", "BOS2", "HEAD", "SKUL",
1726 "PAIN", "SPID", "BSPI", "FATT", "SKEL", "VILE", "FISH", "BAR1", "ROBO", "PLAY"
1728 static const int mms
[MN_TN
] = {
1729 14*2, 21*2, 21*2, 21*2, 16*2, 20*2, 15*2, 15*2, 12*2, 11*2,
1730 13*2, 19*2, 16*2, 20*2, 17*2, 29*2, 6*2, 2*2, 17*2, 23*2
1732 mn_sgun
[0] = Z_getspr("PWP4", 0, 1, NULL
);
1733 mn_sgun
[1] = Z_getspr("PWP4", 1, 1, NULL
);
1734 for (j
= 0; j
< MN_TN
; j
++) {
1735 for (i
= 0; i
< mms
[j
]; i
++) {
1736 mn_spr
[j
][i
] = Z_getspr(msn
[j
], i
/ 2, (i
& 1) + 1, &mn_sprd
[j
][i
]);
1737 if (j
== MN_MAN
- 1) {
1738 mn_man_msk
[i
] = R_gl_get_special_spr(msn
[j
], i
/ 2, (i
& 1) + 1, &R_extract_mask_spr
);
1741 if (j
== MN_BARREL
- 1) {
1742 for (i
= 4; i
< 14; i
++) {
1743 mn_spr
[j
][i
] = Z_getspr("BEXP", i
/ 2 - 2, (i
& 1) + 1, &mn_sprd
[j
][i
]);
1747 for (i
= 0; i
< 8; i
++) {
1748 mn_fspr
[i
] = Z_getspr("FIRE", i
, 0, NULL
);
1750 pl_spr
[0] = Z_getspr("PLAY", 'N' - 'A', 0, NULL
);
1751 pl_msk
[0] = R_gl_get_special_spr("PLAY", 'N' - 'A', 0, &R_extract_mask_spr
);
1752 pl_spr
[1] = Z_getspr("PLAY", 'W' - 'A', 0, NULL
);
1753 pl_msk
[1] = R_gl_get_special_spr("PLAY", 'W' - 'A', 0, &R_extract_mask_spr
);
1755 static const char mnm
[22][8]={
1756 "STTNUM0", "STTNUM1", "STTNUM2", "STTNUM3", "STTNUM4",
1757 "STTNUM5", "STTNUM6", "STTNUM7", "STTNUM8", "STTNUM9",
1758 "STTMINUS", "STTPRCNT",
1759 "FISTA0", "CSAWA0", "PISTA0", "SHOTA0", "SGN2A0", "MGUNA0", "LAUNA0",
1760 "PLASA0", "BFUGA0", "GUN2A0"
1762 stone
= R_gl_loadimage("STONE");
1763 stone2
= R_gl_loadimage("STONE2");
1764 keys
[0] = R_gl_loadimage("KEYRA0");
1765 keys
[1] = R_gl_loadimage("KEYGA0");
1766 keys
[2] = R_gl_loadimage("KEYBA0");
1767 for (i
= 0; i
< 22; i
++) {
1768 sth
[i
] = R_gl_loadimage(mnm
[i
]);
1770 strcpy(s
, "STBF_*");
1771 for (i
= '!'; i
< 160; i
++) {
1773 bfh
[i
- '!'] = R_gl_getimage(F_findres(s
));
1775 for (i
= '!'; i
< 160; i
++) {
1776 sprintf(s
, "STCFN%03d", i
);
1777 sfh
[i
- '!'] = R_gl_getimage(F_findres(s
));
1779 strcpy(s
, "WINUM*");
1780 for (i
= '0'; i
<= '9'; i
++) {
1782 bfh
[i
- '!'] = R_gl_loadimage(s
);
1784 bfh
[':' - '!'] = R_gl_loadimage("WICOLON");
1786 msklh
[0] = R_gl_loadimage("M_SKULL1");
1787 msklh
[1] = R_gl_loadimage("M_SKULL2");
1788 mbarl
= R_gl_loadimage("M_THERML");
1789 mbarm
= R_gl_loadimage("M_THERMM");
1790 mbarr
= R_gl_loadimage("M_THERMR");
1791 mbaro
= R_gl_loadimage("M_THERMO");
1792 mslotl
= R_gl_loadimage("M_LSLEFT");
1793 mslotm
= R_gl_loadimage("M_LSCNTR");
1794 mslotr
= R_gl_loadimage("M_LSRGHT");
1796 for (i
= 1; i
< ANIT
; i
++) {
1797 for (j
= 0; j
< 5 && anm
[i
- 1][j
]; j
++) {
1798 anip
[i
][j
] = R_gl_loadimage(anm
[i
- 1][j
]);
1801 anip
[i
][j
] = (image
) {
1811 static void R_reload_textures (void);
1813 void R_set_videomode (int w
, int h
, int fullscreen
) {
1816 int was
= Y_videomode_setted();
1818 R_cache_free(root
, 0);
1821 int res
= Y_set_videomode_opengl(w
, h
, fullscreen
);
1824 ERR_failinit("Unable to set video mode\n");
1827 Y_get_videomode(&SCRW
, &SCRH
);
1828 root
= R_cache_new();
1831 R_reload_textures();
1835 void R_toggle_fullscreen (void) {
1836 R_cache_free(root
, 0);
1837 Y_set_fullscreen(!Y_get_fullscreen());
1838 fullscreen
= Y_get_fullscreen();
1839 Y_get_videomode(&SCRW
, &SCRH
);
1840 root
= R_cache_new();
1843 R_reload_textures();
1846 void R_init (void) {
1847 logo("R_init: intialize opengl render\n");
1849 R_set_videomode(SCRW
, SCRH
, fullscreen
);
1852 void R_done (void) {
1853 R_cache_free(root
, 1);
1854 Y_unset_videomode();
1858 void R_setgamma (int g
) {
1859 gamma
= g
< 0 ? 0 : (g
> 4 ? 4 : g
);
1862 int R_getgamma (void) {
1866 void R_get_name (int n
, char s
[8]) {
1867 assert(n
>= 0 && n
< 256);
1868 if (walp
[n
].res
== -1) {
1870 } else if (walp
[n
].res
== -2) {
1871 memcpy(s
, "_WATER_", 8);
1872 s
[7] = '0' + (intptr_t)walp
[n
].n
- 1;
1873 } else if (walani
[n
] > 0) {
1874 memcpy(s
, anm
[walani
[n
] - 1][0], 8);
1876 F_getresname(s
, walp
[n
].res
& 0x7FFF);
1880 static short getani (char n
[8]) {
1882 while (i
< ANIT
- 1 && strncasecmp(n
, anm
[i
][0], 8) != 0) {
1885 return i
< ANIT
- 1 ? i
+ 1 : 0;
1888 int R_get_special_id (int n
) {
1889 assert(n
>= 0 && n
<= 256);
1890 return walp
[n
].res
== -2 ? (intptr_t)walp
[n
].n
: -1;
1893 static void R_reload_textures (void) {
1896 for (i
= 0; i
< max_textures
; i
++) {
1898 if (walp
[i
].res
>= 0) {
1899 walp
[i
] = R_gl_getimage(walp
[i
].res
);
1903 horiz
= R_gl_getimage(horiz
.res
);
1907 void R_begin_load (void) {
1909 for (i
= 0; i
< 256; i
++) {
1910 if (walp
[i
].n
!= NULL
&& walp
[i
].res
>= 0 && walani
[i
] == 0) {
1911 R_gl_free_image(&walp
[i
]);
1913 memset(&walp
[i
], 0, sizeof(image
));
1918 memset(anic
, 0, sizeof(anic
));
1920 max_wall_height
= 0;
1924 void R_load (char s
[8], int f
) {
1925 assert(max_textures
< 256);
1927 walp
[max_textures
] = (image
) {
1935 } else if (strncasecmp(s
, "_WATER_", 7) == 0) {
1936 walp
[max_textures
] = (image
) {
1937 .n
= (void*)((intptr_t)s
[7] - '0' + 1),
1945 walp
[max_textures
] = R_gl_loadimage(s
);
1947 walp
[max_textures
].res
|= 0x8000;
1949 if (s
[0] == 'S' && s
[1] == 'W' && s
[4] == '_') {
1950 walswp
[max_textures
] = 0;
1952 walani
[max_textures
] = getani(s
);
1954 max_wall_width
= max(max_wall_width
, walp
[max_textures
].w
);
1955 max_wall_height
= max(max_wall_height
, walp
[max_textures
].h
);
1959 void R_end_load (void) {
1963 for (i
= 1; i
< 256 && j
< 256; i
++) {
1964 if (walswp
[i
] == 0) {
1967 g
= F_getresid(s
) | (walp
[i
].res
& 0x8000);
1969 while (k
< 256 && walp
[k
].res
!= g
) {
1976 walp
[k
] = R_gl_getimage(g
);
1977 walf
[k
] = g
& 0x8000 ? 1 : 0;
1985 void R_loadsky (int sky
) {
1989 R_gl_free_image(&horiz
);
1990 horiz
= R_gl_loadimage(s
);