13 #include "sound.h" // snd_vol
14 #include "music.h" // mus_vol
22 #include "switch.h" // sw_secrets
24 #include <OpenGL/GL.h>
25 #include <stdlib.h> // malloc free abs
26 #include <assert.h> // assert
29 #define VGA_TRANSPARENT_COLOR 0
30 #define DEFAULT_SKY_COLOR 0x97
32 #define PLAYER_COLOR_OFFSET 7
38 typedef struct vgaimg
{
53 typedef struct image
{
61 int SCRW
= 320; // public
62 int SCRH
= 200; // public
64 static int fullscreen
;
65 static SDL_Surface
*surf
;
66 static rgb playpal
[256];
67 static byte bright
[256];
70 static image scrnh
[3]; // TITLEPIC INTERPIC ENDPIC
71 static image ltn
[2][2];
74 static image smk_spr
[SMSN
];
75 static image smk_fspr
[FLSN
];
78 static image fx_spr
[15];
79 static char fx_sprd
[15];
82 static image wp_spr
[49*2];
83 static char wp_sprd
[49*2];
86 static image item_spr
[58];
87 static char item_sprd
[58];
90 static image plr_spr
[27*2];
91 static image plr_msk
[27*2];
92 static char plr_sprd
[27*2];
93 static image plr_wpn
[11][6];
96 static image pl_spr
[2];
97 static image pl_msk
[2];
98 static image mn_spr
[MN_TN
][29*2];
99 static image mn_man_msk
[29*2];
100 static char mn_sprd
[MN_TN
][29*2];
101 static image mn_fspr
[8];
102 static image mn_sgun
[2];
105 static image sth
[22];
106 static image bfh
[160 - '!'];
107 static image sfh
[160 - '!'];
110 static image keys
[3];
116 static image msklh
[2];
126 static const char *anm
[ANIT
- 1][5] = {
127 {"WALL22_1", "WALL23_1", "WALL23_2", NULL
, NULL
},
128 {"WALL58_1", "WALL58_2", "WALL58_3", NULL
, NULL
},
129 {"W73A_1", "W73A_2", NULL
, NULL
, NULL
},
130 {"RP2_1", "RP2_2", "RP2_3", "RP2_4", NULL
}
132 static int max_wall_width
;
133 static int max_wall_height
;
134 static int max_textures
;
135 static image walp
[256];
136 static byte walani
[256];
137 static image anip
[ANIT
][5];
138 static byte anic
[ANIT
];
141 /* Generic helpers */
143 static void R_init_playpal (void) {
145 byte
*vgapal
= M_lock(F_getresid("PLAYPAL"));
146 for (i
= 0; i
< 256; i
++) {
148 .r
= vgapal
[i
* 3 + 0] * 255 / 63,
149 .g
= vgapal
[i
* 3 + 1] * 255 / 63,
150 .b
= vgapal
[i
* 3 + 2] * 255 / 63,
152 bright
[i
] = ((int)vgapal
[i
* 3 + 0] + vgapal
[i
* 3 + 1] + vgapal
[i
* 3 + 2]) * 8 / (63 * 3);
157 static vgaimg
*R_getvga (int id
) {
158 int loaded
= M_was_locked(id
);
159 vgaimg
*v
= M_lock(id
);
160 if (v
!= NULL
&& !loaded
) {
161 v
->w
= short2host(v
->w
);
162 v
->h
= short2host(v
->h
);
163 v
->x
= short2host(v
->x
);
164 v
->y
= short2host(v
->y
);
169 static rgba
*R_extract_flame_spr (vgaimg
*v
) {
170 static const byte flametab
[16] = {
171 0xBC, 0xBA, 0xB8, 0xB6, 0xB4, 0xB2, 0xB0, 0xD5,
172 0xD6, 0xD7, 0xA1, 0xA0, 0xE3, 0xE2, 0xE1, 0xE0
175 rgba
*s
= malloc(v
->w
* v
->h
* sizeof(rgba
));
177 for (j
= 0; j
< v
->h
; j
++) {
178 for (i
= 0; i
< v
->w
; i
++) {
179 int k
= j
* v
->w
+ i
;
180 byte c
= v
->data
[k
] + bright
[DEFAULT_SKY_COLOR
];
182 .r
= playpal
[flametab
[c
]].r
,
183 .g
= playpal
[flametab
[c
]].g
,
184 .b
= playpal
[flametab
[c
]].b
,
185 .a
= v
->data
[k
] == VGA_TRANSPARENT_COLOR
? 0x00 : 0xFF,
193 static rgba
*R_extract_smoke_spr (vgaimg
*v
) {
195 rgba
*s
= malloc(v
->w
* v
->h
* sizeof(rgba
));
197 for (j
= 0; j
< v
->h
; j
++) {
198 for (i
= 0; i
< v
->w
; i
++) {
199 int k
= j
* v
->w
+ i
;
200 byte c
= ((v
->data
[k
] + bright
[DEFAULT_SKY_COLOR
]) + 0x60) ^ 0x0F;
201 byte a
= 0xFF - ((int)playpal
[c
].r
+ playpal
[c
].g
+ playpal
[c
].b
) / 3;
206 .a
= v
->data
[k
] == VGA_TRANSPARENT_COLOR
? 0x00 : a
,
214 static rgba
*R_extract_mask_spr (vgaimg
*v
) {
216 rgba
*s
= malloc(v
->w
* v
->h
* sizeof(rgba
));
218 for (j
= 0; j
< v
->h
; j
++) {
219 for (i
= 0; i
< v
->w
; i
++) {
220 int k
= j
* v
->w
+ i
;
222 if (c
>= 0x70 && c
<= 0x7F) {
223 byte mask
= c
- 0x70;
224 mask
= 0xFF - ((mask
<< 4) | mask
);
245 static rgba
*R_extract_rgba_spr (vgaimg
*v
) {
247 rgba
*s
= malloc(v
->w
* v
->h
* sizeof(rgba
));
249 for (j
= 0; j
< v
->h
; j
++) {
250 for (i
= 0; i
< v
->w
; i
++) {
251 int k
= j
* v
->w
+ i
;
257 .a
= c
== VGA_TRANSPARENT_COLOR
? 0x00 : 0xFF,
267 static image
R_gl_create_image (const rgba
*buf
, int w
, int h
) {
269 glGenTextures(1, &tex
);
271 glBindTexture(GL_TEXTURE_2D
, tex
);
272 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
273 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
274 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, w
, h
, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, buf
);
275 glBindTexture(GL_TEXTURE_2D
, 0);
284 static image
R_gl_get_special_image (int id
, rgba
*(*fn
)(vgaimg
*)) {
285 image img
= (image
) { .res
= -1 };
286 vgaimg
*v
= R_getvga(id
);
288 rgba
*buf
= (*fn
)(v
);
289 img
= R_gl_create_image(buf
, v
->w
, v
->h
);
299 static image
R_gl_getimage (int id
) {
300 return R_gl_get_special_image(id
, &R_extract_rgba_spr
);
303 static image
R_gl_loadimage (const char name
[8]) {
304 return R_gl_getimage(F_getresid(name
));
307 static image
R_gl_get_special_spr (const char n
[4], int s
, int d
, rgba
*(*fn
)(vgaimg
*)) {
308 return R_gl_get_special_image(F_getsprid(n
, s
, d
), fn
);
311 static void R_gl_free_image (image
*img
) {
312 if (img
->id
!= 0 && img
->res
>= 0) {
313 glDeleteTextures(1, &img
->id
);
318 static void R_gl_draw_quad (int x
, int y
, int w
, int h
) {
320 glVertex2i(x
+ w
, y
);
322 glVertex2i(x
, y
+ h
);
323 glVertex2i(x
+ w
, y
+ h
);
327 static void R_gl_draw_textured (image
*img
, int x
, int y
, int w
, int h
, int flip
) {
330 glBindTexture(GL_TEXTURE_2D
, img
->id
);
331 glEnable(GL_TEXTURE_2D
);
333 glTexCoord2f(ax
, 0); glVertex2i(x
+ w
, y
);
334 glTexCoord2f(bx
, 0); glVertex2i(x
, y
);
335 glTexCoord2f(bx
, 1); glVertex2i(x
, y
+ h
);
336 glTexCoord2f(ax
, 1); glVertex2i(x
+ w
, y
+ h
);
338 glDisable(GL_TEXTURE_2D
);
339 glBindTexture(GL_TEXTURE_2D
, 0);
342 /* fit image into rectangle without applying offset and transparency */
343 static void R_gl_draw_image_ext (image
*img
, int x
, int y
, int w
, int h
) {
345 glColor3ub(255, 255, 255);
346 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
347 R_gl_draw_textured(img
, x
, y
, w
, h
, 0);
350 /* draw sprite with offset and coloring */
351 static void R_gl_draw_image_color (image
*img
, int x
, int y
, int flip
) {
352 int xx
= flip
? x
- img
->w
+ img
->x
: x
- img
->x
;
354 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
355 R_gl_draw_textured(img
, xx
, y
- img
->y
, img
->w
, img
->h
, flip
);
359 /* draw sprite with offset */
360 static void R_gl_draw_image (image
*img
, int x
, int y
, int flip
) {
361 int xx
= flip
? x
- img
->w
+ img
->x
: x
- img
->x
;
363 glColor3ub(255, 255, 255);
364 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
365 R_gl_draw_textured(img
, xx
, y
- img
->y
, img
->w
, img
->h
, flip
);
368 static void R_gl_set_color (byte c
) {
369 glColor3ub(playpal
[c
].r
, playpal
[c
].g
, playpal
[c
].b
);
372 static void R_gl_setclip (int x
, int y
, int w
, int h
) {
373 glScissor(x
, SCRH
- h
- y
, w
, h
);
376 static void R_gl_setmatrix (void) {
377 glScissor(0, 0, SCRW
, SCRH
);
378 glViewport(0, 0, SCRW
, SCRH
);
379 glMatrixMode(GL_PROJECTION
);
381 glOrtho(0, SCRW
, SCRH
, 0, 0, 1);
382 glMatrixMode(GL_MODELVIEW
);
388 static image
Z_getspr (const char n
[4], int s
, int d
, char *dir
) {
389 int h
= F_getsprid(n
, s
, d
);
391 *dir
= (h
& 0x8000) ? 1 : 0;
393 return R_gl_getimage(h
);
396 static void Z_putch_generic (image img
[], int off
, int ch
) {
398 if (ch
> 32 && ch
< 160) {
402 R_gl_draw_image(p
, prx
, pry
, 0);
409 static void Z_printf_generic (image img
[], int off
, const char *fmt
, va_list ap
) {
412 vsprintf(buf
, fmt
, ap
);
413 for (i
= 0; buf
[i
]; ++i
) {
421 Z_putch_generic(img
, off
, (byte
)buf
[i
]);
426 static void Z_gotoxy (int x
, int y
) {
431 static void Z_printbf (const char *fmt
, ...) {
434 Z_printf_generic(bfh
, 12, fmt
, a
);
438 static void Z_printsf (const char *fmt
, ...) {
441 Z_printf_generic(sfh
, 7, fmt
, a
);
445 static void Z_printhf (const char *fmt
, ...) {
450 vsprintf(buf
, fmt
, a
);
452 for (i
= 0; buf
[i
]; ++i
) {
483 R_gl_draw_image(&sth
[c
], prx
, pry
, 0);
491 static image
*PL_getspr (int s
, int d
, int msk
) {
492 int i
= (s
- 'A') * 2 + d
;
493 return msk
? &plr_msk
[i
] : &plr_spr
[i
];
496 static void GM_draw (void) {
497 enum {MENU
, MSG
}; // copypasted from menu.c!
499 CANCEL
, NEWGAME
, LOADGAME
, SAVEGAME
, OPTIONS
, QUITGAME
, QUIT
, ENDGAME
, ENDGM
,
500 PLR1
, PLR2
, COOP
, DM
, VOLUME
, GAMMA
, LOAD
, SAVE
, PLCOLOR
, PLCEND
, MUSIC
, INTERP
,
501 SVOLM
, SVOLP
, MVOLM
, MVOLP
, GAMMAM
, GAMMAP
, PL1CM
, PL1CP
, PL2CM
, PL2CP
502 }; // copypasted from menu.c!
503 int i
, j
, k
, x
, y
, cx
, cy
;
509 if (mnu
->type
== MENU
) {
510 y
= cy
- (mnu
->n
* 16 - 20) / 2;
511 Z_gotoxy(cx
- mnu
->x
, y
- 10); Z_printbf("%s", mnu
->ttl
);
512 for (i
= 0; i
< mnu
->n
; i
++) {
513 if (mnu
->t
[i
] == LOAD
|| mnu
->t
[i
] == SAVE
) {
515 R_gl_draw_image(&mslotl
, cx
- mnu
->x
, j
, 0);
516 for (k
= 8; k
< 184; k
+= 8) {
517 R_gl_draw_image(&mslotm
, cx
- mnu
->x
+ k
, j
, 0);
519 R_gl_draw_image(&mslotr
, cx
- mnu
->x
+ 184, j
, 0);
520 Z_gotoxy(cx
- mnu
->x
+ 4, j
- 8);
521 if (input
&& i
== save_mnu
.cur
) {
522 Z_printsf("%s_", ibuf
);
524 Z_printsf("%s", savname
[i
]);
527 x
= mnu
->t
[i
] >= SVOLM
? (mnu
->t
[i
] >= PL1CM
? 50 : 152) : 0;
528 Z_gotoxy(cx
- mnu
->x
+ x
, y
+ i
* 16 + 20);
529 Z_printbf("%s", mnu
->m
[i
]);
532 Z_printbf(" '%s'", g_music
);
535 Z_printbf("%s", fullscreen
? "ON" : "OFF");
541 img
= PL_getspr(*panimp
, 0, 0);
542 R_gl_draw_image(img
, cx
- mnu
->x
+ (mnu
->t
[i
] == PL1CM
? 15 : 35), y
+ i
* 16 + 20 + 14, 0);
543 img
= PL_getspr(*panimp
, 0, 1);
544 R_gl_set_color(pcolortab
[(mnu
->t
[i
] == PL1CM
) ? p1color
: p2color
] + PLAYER_COLOR_OFFSET
);
545 R_gl_draw_image_color(img
, cx
- mnu
->x
+ (mnu
->t
[i
] == PL1CM
? 15 : 35), y
+ i
* 16 + 20 + 14, 0);
554 R_gl_draw_image(&mbarl
, cx
- mnu
->x
, j
, 0);
555 for (k
= 8; k
< 144; k
+= 8) {
556 R_gl_draw_image(&mbarm
, cx
- mnu
->x
+ k
, j
, 0);
558 R_gl_draw_image(&mbarr
, cx
- mnu
->x
+ 144, j
, 0);
573 R_gl_draw_image(&mbaro
, cx
- mnu
->x
+ 8 + k
, j
, 0);
578 R_gl_draw_image(&msklh
[(gm_tm
/ 6) & 1], cx
- mnu
->x
- 25, y
+ mnu
->cur
* 16 + 20 - 8, 0);
579 } else if (mnu
->type
== MSG
) {
580 Z_gotoxy(cx
- strlen(mnu
->ttl
) * 7 / 2, cy
- 10); Z_printsf(mnu
->ttl
);
581 Z_gotoxy(cx
- 24, SCRH
/ 2); Z_printsf("(Y/N)");
583 ERR_fatal("Unknown menu type %i\n", mnu
->type
);
590 static void R_draw_fld (byte
*fld
, int minx
, int miny
, int maxx
, int maxy
, int fg
) {
592 assert(minx
>= 0 && minx
<= FLDW
);
593 assert(miny
>= 0 && miny
<= FLDH
);
594 assert(maxx
>= 0 && maxx
<= FLDW
);
595 assert(maxy
>= 0 && maxy
<= FLDH
);
596 for (j
= miny
; j
< maxy
; j
++) {
597 for (i
= minx
; i
< maxx
; i
++) {
598 byte id
= fld
[j
* FLDW
+ i
];
600 if (walp
[id
].res
< 0) {
602 switch (walp
[id
].id
) {
604 glColor4ub(0, 0, 255, 127);
607 glColor4ub(0, 127, 0, 127);
610 glColor4ub(127, 0, 0, 127);
613 glColor4ub(0, 0, 0, 127);
617 glBlendFunc(GL_DST_COLOR
, GL_SRC_COLOR
);
618 R_gl_draw_quad(i
* CELW
, j
* CELW
, CELW
, CELH
);
621 R_gl_draw_image(&walp
[id
], i
* CELW
, j
* CELH
, 0);
628 static void R_draw_dots (void) {
631 for (i
= 0; i
< MAXDOT
; i
++) {
633 R_gl_set_color(dot
[i
].c
);
634 glVertex2i(dot
[i
].o
.x
, dot
[i
].o
.y
+ 1);
640 static void R_draw_items (void) {
642 for (i
= 0; i
< MAXITEM
; ++i
) {
644 if (it
[i
].t
&& it
[i
].s
>= 0) {
645 switch (it
[i
].t
& 0x7FFF) {
647 s
= it
[i
].s
/ 9 + 18;
650 s
= it
[i
].s
/ 9 + 20;
653 s
= it
[i
].s
/ 2 + 22;
656 s
= it
[i
].s
/ 2 + 26;
662 s
= it
[i
].s
/ 2 + (it
[i
].t
- I_SUPER
) * 4 + 35;
664 case I_GOR1
: case I_FCAN
:
665 s
= it
[i
].s
/ 2 + (it
[i
].t
- I_GOR1
) * 3 + 51;
676 s
= (it
[i
].t
& 0x7FFF) - I_KEYR
+ 31;
682 s
= (it
[i
].t
& 0x7FFF) - 1;
686 R_gl_draw_image(&item_spr
[s
], it
[i
].o
.x
, it
[i
].o
.y
, item_sprd
[s
]);
691 static int standspr (player_t
*p
) {
694 } else if (p
->f
& PLF_DOWN
) {
701 static int wpnspr (player_t
*p
) {
704 } else if(p
->f
& PLF_DOWN
) {
711 static void R_draw_player (player_t
*p
) {
712 enum {STAND
, GO
, DIE
, SLOP
, DEAD
, MESS
, OUT
, FALL
}; // copypasted from player.c!
713 static const int wytab
[] = {-1, -2, -1, 0};
720 if (p
->f
& PLF_FIRE
) {
723 } else if (p
->pain
) {
746 s
= plr_goanim
[p
->s
/ 8];
747 w
= (p
->f
& PLF_FIRE
) ? 'B' : 'A';
749 wy
= 1 + wytab
[s
- 'A'];
753 s
= plr_dieanim
[p
->s
];
756 s
= plr_slopanim
[p
->s
];
766 R_gl_draw_image(&plr_wpn
[(int)p
->wpn
][w
-'A'], p
->o
.x
+ wx
, p
->o
.y
+ wy
, p
->d
);
769 R_gl_draw_image(&plr_spr
[(s
- 'A') * 2 + p
->d
], p
->o
.x
, p
->o
.y
, plr_sprd
[(s
- 'A') * 2 + p
->d
]);
770 R_gl_set_color(p
->color
+ PLAYER_COLOR_OFFSET
);
771 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
]);
775 static void R_draw_monsters (void) {
776 enum {SLEEP
, GO
, RUN
, CLIMB
, DIE
, DEAD
, ATTACK
, SHOOT
, PAIN
, WAIT
, REVIVE
, RUNOUT
}; // copypasted from monster.c!
778 for (i
= 0; i
< MAXMN
; i
++) {
779 if (mn
[i
].t
!= MN_NONE
) {
782 if (mn
[i
].t
< MN__LAST
) {
783 if ((mn
[i
].t
!= MN_SOUL
&& mn
[i
].t
!= MN_PAIN
) || mn
[i
].st
!= DEAD
) {
784 int ap
= mn
[i
].ap
[mn
[i
].ac
];
785 int d
= (ap
- 'A') * 2 + mn
[i
].d
;
786 int dir
= mn_sprd
[mn
[i
].t
- 1][d
];
787 if (mn
[i
].t
== MN_MAN
&& (ap
== 'E' || ap
== 'F')) {
788 R_gl_draw_image(&mn_sgun
[ap
- 'E'], x
, y
, mn
[i
].d
);
790 R_gl_draw_image(&mn_spr
[mn
[i
].t
- 1][d
], x
, y
, dir
);
791 if (mn
[i
].t
== MN_MAN
) {
792 R_gl_set_color(MANCOLOR
+ PLAYER_COLOR_OFFSET
);
793 R_gl_draw_image_color(&mn_man_msk
[d
], x
, y
, dir
);
796 if (mn
[i
].t
== MN_VILE
&& mn
[i
].st
== SHOOT
) {
797 R_gl_draw_image(&mn_fspr
[mn
[i
].ac
/ 3], mn
[i
].tx
, mn
[i
].ty
, 0);
799 } else if (mn
[i
].t
== MN_PL_DEAD
|| mn
[i
].t
== MN_PL_MESS
) {
800 int type
= mn
[i
].t
- MN_PL_DEAD
;
801 R_gl_draw_image(&pl_spr
[type
], x
, y
, 0);
802 R_gl_set_color(mn
[i
].d
);
803 R_gl_draw_image_color(&pl_msk
[type
], x
, y
, 0);
809 static void R_draw_weapons (void) {
810 enum {NONE
, ROCKET
, PLASMA
, APLASMA
, BALL1
, BALL2
, BALL7
, BFGBALL
, BFGHIT
, MANF
, REVF
, FIRE
}; // copypasted from weapons.c!
812 for (i
= 0; i
< MAXWPN
; ++i
) {
820 d
= wp
[i
].o
.xv
> 0 ? 1 : 0;
868 d
= wp
[i
].o
.xv
>= 0 ? 1 : 0;
872 d
= wp
[i
].o
.xv
>=0 ? 1 : 0;
884 s
= wp
[i
].s
/ 2 + 26;
888 R_gl_draw_image(&wp_spr
[s
* 2 + d
], wp
[i
].o
.x
, wp
[i
].o
.y
, wp_sprd
[s
* 2 + d
]);
893 static void R_draw_smoke (void) {
895 for (i
= 0; i
< MAXSMOK
; ++i
) {
900 if (s
>= (SMSN
- 1) * 3) {
903 s
= SMSN
- 1 - s
/ 3;
905 R_gl_draw_image(&smk_spr
[s
], sm
[i
].x
>> 8, (sm
[i
].y
>> 8) + 1, 0);
914 R_gl_draw_image(&smk_fspr
[s
], sm
[i
].x
>> 8, (sm
[i
].y
>> 8) + 1, 0);
921 static void R_draw_effects (void) {
922 enum {NONE
, TFOG
, IFOG
, BUBL
}; // copypasted from fx.c
924 for (i
= 0; i
< MAXFX
; ++i
) {
928 R_gl_draw_image(&fx_spr
[s
], fx
[i
].x
, fx
[i
].y
, fx_sprd
[s
]);
931 s
= fx
[i
].s
/ 2 + 10;
932 R_gl_draw_image(&fx_spr
[s
], fx
[i
].x
, fx
[i
].y
, fx_sprd
[s
]);
936 R_gl_set_color(0xC0 + fx
[i
].s
);
937 glVertex2i(fx
[i
].x
>> 8, (fx
[i
].y
>> 8) + 1);
944 static int get_pu_st (int t
) {
947 } else if((t
/ 9) & 1) {
954 static void R_draw_view (int x
, int y
, int w
, int h
, int camx
, int camy
) {
956 R_gl_setclip(x
, y
, w
, h
);
957 glTranslatef(x
, y
, 0);
958 if (w_horiz
&& horiz
.id
!= 0) {
959 R_gl_draw_image_ext(&horiz
, 0, 0, w
, h
);
960 if (sky_type
== 2 && lt_time
< 0) {
961 image
*tanderbolt
= <n
[lt_type
][lt_time
< -5 ? 0 : 1];
963 R_gl_draw_image(tanderbolt
, 0, lt_ypos
, 0);
965 R_gl_draw_image(tanderbolt
, w
- 1, lt_ypos
, 1);
970 R_gl_set_color(DEFAULT_SKY_COLOR
);
971 R_gl_draw_quad(0, 0, w
, h
);
973 int maxx
= min((camx
+ w
) / CELW
+ 1, FLDW
);
974 int maxy
= min((camy
+ h
) / CELH
+ 1, FLDH
);
975 int minx
= max((camx
- max_wall_width
) / CELW
, 0);
976 int miny
= max((camy
- max_wall_height
) / CELH
, 0);
977 glTranslatef(-camx
, -camy
, 0);
978 R_draw_fld((byte
*)fldb
, minx
, miny
, maxx
, maxy
, 0);
989 R_draw_fld((byte
*)fldf
, minx
, miny
, maxx
, maxy
, 1);
990 glTranslatef(camx
, camy
, 0);
991 if (sky_type
== 2 && (lt_time
== -4 || lt_time
== -2)) {
992 glColor4ub(255, 255, 255, 255);
994 glBlendFunc(GL_DST_COLOR
, GL_SRC_COLOR
);
995 R_gl_draw_quad(0, 0, w
, h
);
1000 static void R_draw_player_view (player_t
*p
, int x
, int y
, int w
, int h
) {
1001 p
->looky
= min(max(p
->looky
, -SCRH
/ 4), SCRH
/ 4); // TODO remove writeback
1004 int cx
= min(max(p
->o
.x
, cw
/ 2), FLDW
* CELW
- cw
/ 2);
1005 int cy
= min(max(p
->o
.y
- 12 + p
->looky
, h
/ 2), FLDH
* CELH
- h
/ 2);
1006 int camx
= max(cx
- cw
/ 2, 0);
1007 int camy
= max(cy
- h
/ 2, 0);
1009 R_draw_view(x
, y
+ 1, cw
, h
- 2, camx
, camy
);
1010 glTranslatef(x
, y
, 0);
1012 if (get_pu_st(p
->invl
)) {
1014 glColor4ub(191, 191, 191, 255);
1015 glBlendFunc(GL_ONE_MINUS_DST_COLOR
, GL_ZERO
);
1016 R_gl_draw_quad(0, 0, cw
, h
);
1019 if (p
->suit
&& get_pu_st(p
->suit
)) {
1021 glColor4ub(0, 255, 0, 192);
1022 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
1023 R_gl_draw_quad(0, 0, cw
, h
);
1025 int f
= min(max(p
->pain
* 3, 0), 255);
1028 glColor4ub(255, 0, 0, f
);
1029 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
1030 R_gl_draw_quad(0, 0, cw
, h
);
1033 R_gl_setclip(x
, y
, w
, h
);
1034 glTranslatef(-x
+ cw
, 0, 0);
1035 R_gl_draw_image(&stone
, 0, 0, 0);
1038 R_gl_draw_image(&stone2
, 0, i
, 0);
1041 if (p
->drawst
& PL_DRAWAIR
) {
1042 if (p
->air
< PL_AIR
) {
1043 int a
= min(max(p
->air
, 0), MAXAIR
) * 100 / MAXAIR
;
1044 glDisable(GL_BLEND
);
1045 R_gl_set_color(0xC8);
1046 R_gl_draw_quad(10, 49, a
, 2);
1049 if (p
->drawst
& PL_DRAWLIFE
) {
1051 Z_printhf("%3d%%", p
->life
);
1053 if (p
->drawst
& PL_DRAWARMOR
) {
1054 Z_gotoxy(10, 7 + 19);
1055 Z_printhf("%3d%%", p
->armor
);
1057 if (p
->drawst
& PL_DRAWWPN
) {
1084 R_gl_draw_image(&sth
[12 + p
->wpn
], st
- 88, 58 + 19, 0);
1088 Z_gotoxy(st
- 10 - 5 * 14, 58 + 2);
1089 Z_printhf("%5d", i
);
1092 if (p
->drawst
& PL_DRAWFRAG
&& g_dm
) {
1093 Z_gotoxy(st
- 5 - 5 * 14, 77 + 5);
1094 Z_printhf("%5d", p
->frag
);
1096 if (p
->drawst
& PL_DRAWKEYS
) {
1098 for (k
= p
->keys
>> 4, n
= 0, x
= st
- 75; n
< 3; n
++, k
>>= 1, x
+= 9) {
1100 R_gl_draw_image(&keys
[n
], x
, 91, 0);
1104 if (p
->drawst
& PL_DRAWLIVES
&& !_2pl
) {
1105 Z_gotoxy(st
- 35, 17);
1106 Z_printhf("%d", p
->lives
);
1113 static void pl_info (player_t
*p
, int x
, int y
) {
1114 dword t
= p
->kills
* 10920 / g_time
;
1115 Z_gotoxy(x
+ 25, y
); Z_printbf("KILLS");
1116 Z_gotoxy(x
+ 25, y
+ 15); Z_printbf("KPM");
1117 Z_gotoxy(x
+ 25, y
+ 30); Z_printbf("SECRETS %u / %u", p
->secrets
, sw_secrets
);
1118 Z_gotoxy(x
+ 255, y
); Z_printbf("%u", p
->kills
);
1119 Z_gotoxy(x
+ 255, y
+ 15); Z_printbf("%u.%u", t
/ 10, t
% 10);
1122 static void R_draw_intermission (void) {
1125 Z_gotoxy(cx
- 14*12/2, 20);
1126 Z_printbf("LEVEL COMPLETE");
1127 Z_calc_time(g_time
, &hr
, &mn
, &sc
);
1128 Z_gotoxy(cx
- 12*12/2, 40);
1129 Z_printbf("TIME %u:%02u:%02u", hr
, mn
, sc
);
1132 Z_gotoxy(cx
- 10*12/2, h
);
1133 Z_printbf("PLAYER ONE");
1136 pl_info(&pl1
, cx
- 160, h
);
1138 h
+= 30 + SCRH
/ 10;
1139 Z_gotoxy(cx
- 10*12/2, h
);
1140 Z_printbf("PLAYER TWO");
1142 pl_info(&pl2
, cx
- 160, h
);
1146 static void W_act (void) {
1148 if (g_time
% 3 == 0) {
1149 for (i
= 1; i
< max_textures
; i
++) {
1153 if (anip
[a
][anic
[a
]].res
== -1) {
1156 walp
[i
] = anip
[a
][anic
[a
]];
1162 void R_draw (void) {
1164 glClearColor(0, 0, 0, 1);
1165 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
1166 glEnable(GL_SCISSOR_TEST
);
1177 R_gl_draw_image_ext(&scrnh
[0], 0, 0, SCRW
, SCRH
);
1180 R_gl_draw_image_ext(&scrnh
[1], 0, 0, SCRW
, SCRH
);
1181 R_draw_intermission();
1184 R_gl_draw_image_ext(&scrnh
[2], 0, 0, SCRW
, SCRH
);
1188 R_draw_player_view(&pl1
, 0, 0, SCRW
, SCRH
/ 2);
1189 R_draw_player_view(&pl2
, 0, SCRH
/ 2, SCRW
, SCRH
/ 2);
1191 R_draw_player_view(&pl1
, 0, 0, SCRW
, SCRH
);
1193 R_gl_setclip(0, 0, SCRW
, SCRH
);
1197 SDL_GL_SwapBuffers();
1200 void R_alloc (void) {
1203 logo("R_alloc: load graphics\n");
1205 scrnh
[0] = R_gl_loadimage("TITLEPIC");
1206 scrnh
[1] = R_gl_loadimage("INTERPIC");
1207 scrnh
[2] = R_gl_loadimage("ENDPIC");
1208 for (i
= 0; i
< 2; i
++) {
1209 sprintf(s
, "LTN%c", '1' + i
);
1210 for (j
= 0; j
< 2; j
++) {
1211 ltn
[i
][j
] = Z_getspr(s
, j
, 0, NULL
);
1215 for (i
= 0; i
< SMSN
; i
++) {
1216 smk_spr
[i
] = R_gl_get_special_spr("SMOK", i
, 0, &R_extract_smoke_spr
);
1218 for (i
= 0; i
< FLSN
; i
++) {
1219 smk_fspr
[i
] = R_gl_get_special_spr("SMOK", i
, 0, &R_extract_flame_spr
);
1222 for (i
= 0; i
< 10; i
++) {
1223 fx_spr
[i
] = Z_getspr("TFOG", i
, 0, fx_sprd
+ i
);
1225 for (; i
< 15; i
++) {
1226 fx_spr
[i
] = Z_getspr("IFOG", i
- 10, 0, fx_sprd
+ i
);
1229 for (i
= 0; i
< 4; i
++) {
1230 wp_spr
[i
* 2] = Z_getspr("MISL", i
, 1, wp_sprd
+ i
* 2);
1231 wp_spr
[i
* 2 + 1] = Z_getspr("MISL", i
, 2, wp_sprd
+ i
* 2 + 1);
1233 for (; i
< 6; i
++) {
1234 wp_spr
[i
* 2] = Z_getspr("PLSS", i
- 4, 1, wp_sprd
+ i
* 2);
1235 wp_spr
[i
* 2 + 1] = Z_getspr("PLSS", i
- 4, 2, wp_sprd
+ i
* 2 + 1);
1237 for (; i
< 11; i
++) {
1238 wp_spr
[i
* 2] = Z_getspr("PLSE", i
- 6, 1, wp_sprd
+ i
* 2);
1239 wp_spr
[i
* 2 + 1] = Z_getspr("PLSE", i
- 6, 2, wp_sprd
+ i
* 2 + 1);
1241 for (; i
< 13; i
++) {
1242 wp_spr
[i
* 2] = Z_getspr("APLS", i
- 11, 1, wp_sprd
+ i
* 2);
1243 wp_spr
[i
* 2 + 1] = Z_getspr("APLS", i
- 11, 2, wp_sprd
+ i
* 2 + 1);
1245 for (; i
< 18; i
++) {
1246 wp_spr
[i
* 2] = Z_getspr("APBX", i
- 13, 1, wp_sprd
+ i
* 2);
1247 wp_spr
[i
* 2 + 1] = Z_getspr("APBX", i
- 13, 2, wp_sprd
+ i
* 2 + 1);
1249 for(; i
< 20; i
++) {
1250 wp_spr
[i
* 2] = Z_getspr("BFS1", i
- 18, 1, wp_sprd
+ i
* 2);
1251 wp_spr
[i
* 2 + 1] = Z_getspr("BFS1", i
- 18, 2, wp_sprd
+ i
* 2 + 1);
1253 for (; i
< 26; i
++) {
1254 wp_spr
[i
* 2] = Z_getspr("BFE1", i
- 20, 1, wp_sprd
+ i
* 2);
1255 wp_spr
[i
* 2 + 1] = Z_getspr("BFE1", i
- 20, 2, wp_sprd
+ i
* 2 + 1);
1257 for (; i
< 30; i
++) {
1258 wp_spr
[i
* 2] = Z_getspr("BFE2", i
- 26, 1, wp_sprd
+ i
* 2);
1259 wp_spr
[i
* 2 + 1] = Z_getspr("BFE2", i
- 26, 2, wp_sprd
+ i
* 2 + 1);
1261 for (; i
< 32; i
++) {
1262 wp_spr
[i
* 2] = Z_getspr("MISL", i
- 30 + 4, 1, wp_sprd
+ i
* 2);
1263 wp_spr
[i
* 2 + 1] = Z_getspr("MISL", i
- 30 + 4, 2, wp_sprd
+ i
* 2 + 1);
1265 for (; i
< 37; i
++) {
1266 wp_spr
[i
* 2] = Z_getspr("BAL1", i
- 32, 1, wp_sprd
+ i
* 2);
1267 wp_spr
[i
* 2 + 1] = Z_getspr("BAL1", i
- 32, 2, wp_sprd
+ i
* 2 + 1);
1269 for (; i
< 42; i
++) {
1270 wp_spr
[i
* 2] = Z_getspr("BAL7", i
- 37, 1, wp_sprd
+ i
* 2);
1271 wp_spr
[i
* 2 + 1] = Z_getspr("BAL7", i
- 37, 2, wp_sprd
+ i
* 2 + 1);
1273 for (; i
< 47; i
++) {
1274 wp_spr
[i
* 2] = Z_getspr("BAL2", i
- 42, 1, wp_sprd
+ i
* 2);
1275 wp_spr
[i
* 2 + 1] = Z_getspr("BAL2", i
- 42, 2, wp_sprd
+ i
* 2 + 1);
1277 for (; i
< 49; i
++) {
1278 wp_spr
[i
* 2] = Z_getspr("MANF", i
- 47, 1, wp_sprd
+ i
* 2);
1279 wp_spr
[i
* 2 + 1] = Z_getspr("MANF", i
- 47, 2, wp_sprd
+ i
* 2 + 1);
1282 static const char snm
[18][4] = {
1283 "CLIP", "SHEL", "ROCK", "CELL", "AMMO", "SBOX", "BROK", "CELP",
1284 "STIM", "MEDI", "BPAK",
1285 "CSAW", "SHOT", "SGN2", "MGUN", "LAUN", "PLAS", "BFUG"
1287 static const char n4
[4][4] = {
1288 "SOUL", "SMRT", "SMGT", "SMBT"
1290 static const char n3
[2][4] = {
1293 for (i
= 0; i
< 18; i
++) {
1294 item_spr
[i
] = Z_getspr(snm
[i
], 0, 0, item_sprd
+ i
);
1296 for (; i
< 20; i
++) {
1297 item_spr
[i
] = Z_getspr("ARM1", i
- 18, 0, item_sprd
+ i
);
1298 item_spr
[i
+ 2] = Z_getspr("ARM2", i
- 18, 0, item_sprd
+ i
);
1301 for (; i
< 26; i
++) {
1302 item_spr
[i
] = Z_getspr("MEGA", i
- 22, 0, item_sprd
+ i
);
1304 for (; i
< 30; i
++) {
1305 item_spr
[i
] = Z_getspr("PINV", i
- 26, 0, item_sprd
+ i
);
1307 item_spr
[30] = Z_getspr("AQUA", 0, 0, item_sprd
+ 30);
1308 item_spr
[31] = Z_getspr("KEYR", 0, 0, item_sprd
+ 31);
1309 item_spr
[32] = Z_getspr("KEYG", 0, 0, item_sprd
+ 32);
1310 item_spr
[33] = Z_getspr("KEYB", 0, 0, item_sprd
+ 33);
1311 item_spr
[34] = Z_getspr("SUIT", 0, 0, item_sprd
+ 34);
1312 for (n
= 35, j
= 0; j
< 4; j
++) {
1313 for (i
= 0; i
< 4; i
++, n
++) {
1314 item_spr
[n
] = Z_getspr(n4
[j
], i
, 0, item_sprd
+ n
);
1317 for (j
= 0; j
< 2; j
++) {
1318 for (i
= 0; i
< 3; i
++, n
++) {
1319 item_spr
[n
] = Z_getspr(n3
[j
], i
, 0, item_sprd
+ n
);
1322 item_spr
[57] = Z_getspr("GUN2", 0, 0, item_sprd
+ 57);
1324 for (i
= 0; i
< 27; i
++) {
1325 plr_spr
[i
* 2] = Z_getspr("PLAY", i
, 1, plr_sprd
+ i
* 2);
1326 plr_msk
[i
* 2] = R_gl_get_special_spr("PLAY", i
, 1, &R_extract_mask_spr
);
1327 plr_spr
[i
* 2 + 1] = Z_getspr("PLAY", i
, 2, plr_sprd
+ i
* 2 + 1);
1328 plr_msk
[i
* 2 + 1] = R_gl_get_special_spr("PLAY", i
, 2, &R_extract_mask_spr
);
1330 strncpy(s
, "PWPx", 4);
1331 for (i
= 1; i
< 11; i
++) {
1332 s
[3] = (i
< 10 ? '0' : 'A' - 10) + i
;
1333 for (j
= 0; j
< 6; j
++) {
1334 plr_wpn
[i
][j
] = Z_getspr(s
, j
, 1, NULL
);
1338 static const char msn
[MN_TN
][4] = {
1339 "SARG", "TROO", "POSS", "SPOS", "CYBR", "CPOS", "BOSS", "BOS2", "HEAD", "SKUL",
1340 "PAIN", "SPID", "BSPI", "FATT", "SKEL", "VILE", "FISH", "BAR1", "ROBO", "PLAY"
1342 static const int mms
[MN_TN
] = {
1343 14*2, 21*2, 21*2, 21*2, 16*2, 20*2, 15*2, 15*2, 12*2, 11*2,
1344 13*2, 19*2, 16*2, 20*2, 17*2, 29*2, 6*2, 2*2, 17*2, 23*2
1346 mn_sgun
[0] = Z_getspr("PWP4", 0, 1, NULL
);
1347 mn_sgun
[1] = Z_getspr("PWP4", 1, 1, NULL
);
1348 for (j
= 0; j
< MN_TN
; j
++) {
1349 for (i
= 0; i
< mms
[j
]; i
++) {
1350 mn_spr
[j
][i
] = Z_getspr(msn
[j
], i
/ 2, (i
& 1) + 1, &mn_sprd
[j
][i
]);
1351 if (j
== MN_MAN
- 1) {
1352 mn_man_msk
[i
] = R_gl_get_special_spr(msn
[j
], i
/ 2, (i
& 1) + 1, &R_extract_mask_spr
);
1355 if (j
== MN_BARREL
- 1) {
1356 for (i
= 4; i
< 14; i
++) {
1357 mn_spr
[j
][i
] = Z_getspr("BEXP", i
/ 2 - 2, (i
& 1) + 1, &mn_sprd
[j
][i
]);
1361 for (i
= 0; i
< 8; i
++) {
1362 mn_fspr
[i
] = Z_getspr("FIRE", i
, 0, NULL
);
1364 pl_spr
[0] = Z_getspr("PLAY", 'N' - 'A', 0, NULL
);
1365 pl_msk
[0] = R_gl_get_special_spr("PLAY", 'N' - 'A', 0, &R_extract_mask_spr
);
1366 pl_spr
[1] = Z_getspr("PLAY", 'W' - 'A', 0, NULL
);
1367 pl_msk
[1] = R_gl_get_special_spr("PLAY", 'W' - 'A', 0, &R_extract_mask_spr
);
1369 static const char mnm
[22][8]={
1370 "STTNUM0", "STTNUM1", "STTNUM2", "STTNUM3", "STTNUM4",
1371 "STTNUM5", "STTNUM6", "STTNUM7", "STTNUM8", "STTNUM9",
1372 "STTMINUS", "STTPRCNT",
1373 "FISTA0", "CSAWA0", "PISTA0", "SHOTA0", "SGN2A0", "MGUNA0", "LAUNA0",
1374 "PLASA0", "BFUGA0", "GUN2A0"
1376 stone
= R_gl_loadimage("STONE");
1377 stone2
= R_gl_loadimage("STONE2");
1378 keys
[0] = R_gl_loadimage("KEYRA0");
1379 keys
[1] = R_gl_loadimage("KEYGA0");
1380 keys
[2] = R_gl_loadimage("KEYBA0");
1381 for (i
= 0; i
< 22; i
++) {
1382 sth
[i
] = R_gl_loadimage(mnm
[i
]);
1384 strcpy(s
, "STBF_*");
1385 for (i
= '!'; i
< 160; i
++) {
1387 bfh
[i
- '!'] = R_gl_getimage(F_findres(s
));
1389 for (i
= '!'; i
< 160; i
++) {
1390 sprintf(s
, "STCFN%03d", i
);
1391 sfh
[i
- '!'] = R_gl_getimage(F_findres(s
));
1393 strcpy(s
, "WINUM*");
1394 for (i
= '0'; i
<= '9'; i
++) {
1396 bfh
[i
- '!'] = R_gl_loadimage(s
);
1398 bfh
[':' - '!'] = R_gl_loadimage("WICOLON");
1400 msklh
[0] = R_gl_loadimage("M_SKULL1");
1401 msklh
[1] = R_gl_loadimage("M_SKULL2");
1402 mbarl
= R_gl_loadimage("M_THERML");
1403 mbarm
= R_gl_loadimage("M_THERMM");
1404 mbarr
= R_gl_loadimage("M_THERMR");
1405 mbaro
= R_gl_loadimage("M_THERMO");
1406 mslotl
= R_gl_loadimage("M_LSLEFT");
1407 mslotm
= R_gl_loadimage("M_LSCNTR");
1408 mslotr
= R_gl_loadimage("M_LSRGHT");
1410 for (i
= 1; i
< ANIT
; i
++) {
1411 for (j
= 0; anm
[i
- 1][j
]; j
++) {
1412 anip
[i
][j
] = R_gl_loadimage(anm
[i
- 1][j
]);
1415 anip
[i
][j
] = (image
) {
1424 void R_init (void) {
1425 Uint32 flags
= SDL_OPENGL
;
1427 flags
= flags
| SDL_FULLSCREEN
;
1429 if (SCRW
<= 0 || SCRH
<= 0) {
1430 ERR_failinit("Invalid screen size %ix%i\n", SCRW
, SCRH
);
1433 R_init_playpal(); // only onece
1435 surf
= SDL_SetVideoMode(SCRW
, SCRH
, 0, flags
);
1437 ERR_failinit("Unable to set video mode: %s\n", SDL_GetError());
1442 void R_done (void) {
1446 void R_setgamma (int g
) {
1447 gamma
= g
< 0 ? 0 : (g
> 4 ? 4 : g
);
1450 int R_getgamma (void) {
1454 void R_toggle_fullscreen (void) {
1455 fullscreen
= !fullscreen
;
1457 R_init(); // recreate window
1461 void R_get_name (int n
, char s
[8]) {
1462 assert(n
>= 0 && n
< 256);
1463 if (walp
[n
].res
== -1) {
1465 } else if (walp
[n
].res
== -2) {
1466 memcpy(s
, "_WATER_", 8);
1467 s
[7] = '0' + walp
[n
].id
- 1;
1468 } else if (walani
[n
] > 0) {
1469 memcpy(s
, anm
[walani
[n
] - 1][0], 8);
1471 F_getresname(s
, walp
[n
].res
& 0x7FFF);
1475 static short getani (char n
[8]) {
1477 while (i
< ANIT
&& strncasecmp(n
, anm
[i
][0], 8) != 0) {
1480 return i
< ANIT
? i
+ 1 : 0;
1483 int R_get_special_id (int n
) {
1484 assert(n
>= 0 && n
<= 256);
1485 return walp
[n
].res
== -2 ? walp
[n
].id
: -1;
1488 void R_begin_load (void) {
1490 for (i
= 0; i
< 256; i
++) {
1491 if (walp
[i
].id
!= 0 && walp
[i
].res
>= 0 && walani
[i
] == 0) {
1492 R_gl_free_image(&walp
[i
]);
1494 memset(&walp
[i
], 0, sizeof(image
));
1499 memset(anic
, 0, sizeof(anic
));
1501 max_wall_height
= 0;
1505 void R_load (char s
[8], int f
) {
1506 assert(max_textures
< 256);
1508 walp
[max_textures
] = (image
) {
1516 } else if (strncasecmp(s
, "_WATER_", 7) == 0) {
1517 walp
[max_textures
] = (image
) {
1518 .id
= s
[7] - '0' + 1,
1526 walp
[max_textures
] = R_gl_loadimage(s
);
1528 walp
[max_textures
].res
|= 0x8000;
1530 if (s
[0] == 'S' && s
[1] == 'W' && s
[4] == '_') {
1531 walswp
[max_textures
] = 0;
1533 walani
[max_textures
] = getani(s
);
1535 max_wall_width
= max(max_wall_width
, walp
[max_textures
].w
);
1536 max_wall_height
= max(max_wall_height
, walp
[max_textures
].h
);
1540 void R_end_load (void) {
1544 for (i
= 1; i
< 256 && j
< 256; i
++) {
1545 if (walswp
[i
] == 0) {
1548 g
= F_getresid(s
) | (walp
[i
].res
& 0x8000);
1550 while (k
< 256 && walp
[k
].res
!= g
) {
1556 walp
[k
] = R_gl_getimage(g
);
1557 walf
[k
] = g
& 0x8000 ? 1 : 0;
1565 void R_loadsky (int sky
) {
1567 logo("R_loadsky(%i)\n", sky
);
1570 R_gl_free_image(&horiz
);
1571 horiz
= R_gl_loadimage(s
);