Skip to content

Commit 9698470

Browse files
committed
Add an option for scanlines when playing videos.
Shows either no, 50% dimmed or black scanlines. Disabled if the video texture is too small (needs 2 * video height), or the video is shown so small that the scanlines can't be noticed. Closes #2095.
1 parent 7019d7e commit 9698470

File tree

7 files changed

+129
-19
lines changed

7 files changed

+129
-19
lines changed

lib/sequence/sequence.c

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
#include "lib/sound/audio.h"
6666
#include "lib/sound/openal_error.h"
6767
#include "lib/sound/mixer.h"
68+
#include "src/warzoneconfig.h"
6869

6970
#include <theora/theora.h>
7071
#include <physfs.h>
@@ -178,6 +179,8 @@ static int videoY2 = 0;
178179
static int ScrnvidXpos = 0;
179180
static int ScrnvidYpos = 0;
180181

182+
static SCANLINE_MODE use_scanlines;
183+
181184
// Helper; just grab some more compressed bitstream and sync it for page extraction
182185
static int buffer_data(PHYSFS_file* in, ogg_sync_state* oy)
183186
{
@@ -292,7 +295,12 @@ static GLuint video_texture;
292295
*/
293296
static void Allocate_videoFrame(void)
294297
{
295-
RGBAframe = malloc(videodata.ti.frame_width * videodata.ti.frame_height * 4);
298+
int size = videodata.ti.frame_width * videodata.ti.frame_height * 4;
299+
if (use_scanlines)
300+
size *= 2;
301+
302+
RGBAframe = malloc(size);
303+
memset(RGBAframe, 0, size);
296304
glGenTextures(1, &video_texture);
297305
}
298306

@@ -310,6 +318,8 @@ static void video_write(bool update)
310318
unsigned int x = 0, y = 0;
311319
const int video_width = videodata.ti.frame_width;
312320
const int video_height = videodata.ti.frame_height;
321+
// when using scanlines we need to double the height
322+
const int height_factor = (use_scanlines ? 2 : 1);
313323
yuv_buffer yuv;
314324
glErrors();
315325

@@ -323,7 +333,7 @@ static void video_write(bool update)
323333
int rgb_offset = 0;
324334
int y_offset = 0;
325335
int uv_offset = 0;
326-
int half_width = video_width / 2;
336+
const int half_width = video_width / 2;
327337

328338
theora_decode_YUVout(&videodata.td, &yuv);
329339

@@ -347,6 +357,18 @@ static void video_write(bool update)
347357
int B = Vclip((A + 516 * U + 128) >> 8);
348358

349359
RGBAframe[rgb_offset] = (B << 16) | (G << 8) | (R << 0) | (0xFF << 24);
360+
if (use_scanlines == SCANLINES_50)
361+
{
362+
// halve the rgb values for a dimmed scanline
363+
R /= 2;
364+
G /= 2;
365+
B /= 2;
366+
RGBAframe[rgb_offset + video_width] = (B << 16) | (G << 8) | (R << 0) | (0xff << 24);
367+
}
368+
else if (use_scanlines == SCANLINES_BLACK)
369+
{
370+
RGBAframe[rgb_offset + video_width] = (0xFF << 24);
371+
}
350372
rgb_offset++;
351373

352374
// second pixel, U and V (and thus C) are the same as before.
@@ -358,12 +380,26 @@ static void video_write(bool update)
358380
B = Vclip((A + 516 * U + 128) >> 8);
359381

360382
RGBAframe[rgb_offset] = (B << 16) | (G << 8) | (R << 0) | (0xFF << 24);
383+
if (use_scanlines == SCANLINES_50)
384+
{
385+
// halve the rgb values for a dimmed scanline
386+
R /= 2;
387+
G /= 2;
388+
B /= 2;
389+
RGBAframe[rgb_offset + video_width] = (B << 16) | (G << 8) | (R << 0) | (0xff << 24);
390+
}
391+
else if (use_scanlines == SCANLINES_BLACK)
392+
{
393+
RGBAframe[rgb_offset + video_width] = (0xFF << 24);
394+
}
361395
rgb_offset++;
362396
}
397+
if (use_scanlines)
398+
rgb_offset += video_width;
363399
}
364400

365401
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, video_width,
366-
video_height, GL_RGBA, GL_UNSIGNED_BYTE, RGBAframe);
402+
video_height * height_factor, GL_RGBA, GL_UNSIGNED_BYTE, RGBAframe);
367403
glErrors();
368404
}
369405

@@ -380,9 +416,9 @@ static void video_write(bool update)
380416
glVertex2f(videoX1, videoY1);
381417
glTexCoord2f(256 * video_width / texture_width, 0);
382418
glVertex2f(videoX2, videoY1); //screenWidth
383-
glTexCoord2f(256 * video_width / texture_width, 256 * video_height / texture_height);
419+
glTexCoord2f(256 * video_width / texture_width, 256 * video_height * height_factor / texture_height);
384420
glVertex2f(videoX2, videoY2); //screenWidth,screenHeight
385-
glTexCoord2f(0, 256 * video_height / texture_height);
421+
glTexCoord2f(0, 256 * video_height * height_factor / texture_height);
386422
glVertex2f(videoX1, videoY2); //screenHeight
387423
glEnd();
388424

@@ -716,6 +752,11 @@ bool seq_Play(const char* filename)
716752
debug(LOG_ERROR, "Video not in YUV420 format!");
717753
return false;
718754
}
755+
// disable scanlines if the video is too large for the texture or shown too small
756+
use_scanlines = war_getScanlineMode();
757+
if (videodata.ti.frame_height * 2 > texture_height || videoY2 < videodata.ti.frame_height * 2)
758+
use_scanlines = SCANLINES_OFF;
759+
719760
Allocate_videoFrame();
720761

721762
glBindTexture(GL_TEXTURE_2D, video_texture);
@@ -1024,8 +1065,6 @@ void seq_SetDisplaySize(int sizeX, int sizeY, int posX, int posY)
10241065
videoY1 += offset;
10251066
videoY2 -= offset;
10261067
}
1027-
1028-
10291068
}
10301069

10311070
ScrnvidXpos = posX;

lib/sequence/sequence.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,10 @@ extern void seq_Shutdown(void);
2929
extern int seq_GetFrameNumber(void);
3030
extern void seq_SetDisplaySize(int sizeX, int sizeY, int posX, int posY);
3131

32+
typedef enum {
33+
SCANLINES_OFF,
34+
SCANLINES_50,
35+
SCANLINES_BLACK
36+
} SCANLINE_MODE;
37+
3238
#endif // __INCLUDED_LIB_SEQUENCE_SEQUENCE_H__

src/configuration.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,15 @@ BOOL loadConfig(void)
356356
war_SetFMVmode(FMV_2X);
357357
}
358358

359+
if (getWarzoneKeyNumeric("scanlines", &val))
360+
{
361+
war_setScanlineMode(val);
362+
}
363+
else
364+
{
365+
war_setScanlineMode(SCANLINES_OFF);
366+
}
367+
359368
// //////////////////////////
360369
// subtitles
361370
if(getWarzoneKeyNumeric("subtitles", &val))
@@ -724,6 +733,7 @@ BOOL saveConfig(void)
724733
setWarzoneKeyNumeric("shadows",(SDWORD)(getDrawShadows())); // shadows
725734
setWarzoneKeyNumeric("sound", (SDWORD)war_getSoundEnabled());
726735
setWarzoneKeyNumeric("FMVmode",(SDWORD)(war_GetFMVmode())); // sequences
736+
setWarzoneKeyNumeric("scanlines", (SDWORD)war_getScanlineMode());
727737
setWarzoneKeyNumeric("subtitles",(SDWORD)(seq_GetSubtitles())); // subtitles
728738
setWarzoneKeyNumeric("radarObjectMode",(SDWORD)bEnemyAllyRadarColor); // enemy/allies radar view
729739
setWarzoneKeyNumeric("radarTerrainMode",(SDWORD)radarDrawMode);

src/frontend.c

Lines changed: 49 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -499,52 +499,69 @@ static BOOL startGraphicsOptionsMenu(void)
499499
break;
500500
}
501501

502+
// Scanlines
503+
addTextButton(FRONTEND_SCANLINES, FRONTEND_POS3X - 35, FRONTEND_POS3Y, _("Scanlines"), 0);
504+
switch (war_getScanlineMode())
505+
{
506+
case SCANLINES_OFF:
507+
addTextButton(FRONTEND_SCANLINES_R, FRONTEND_POS3M - 55, FRONTEND_POS3Y, _("Off"), 0);
508+
break;
509+
510+
case SCANLINES_50:
511+
addTextButton(FRONTEND_SCANLINES_R, FRONTEND_POS3M - 55, FRONTEND_POS3Y, _("50%"), 0);
512+
break;
513+
514+
case SCANLINES_BLACK:
515+
addTextButton(FRONTEND_SCANLINES_R, FRONTEND_POS3M - 55, FRONTEND_POS3Y, _("Black"), 0);
516+
break;
517+
}
518+
502519
////////////
503520
// screenshake
504-
addTextButton(FRONTEND_SSHAKE, FRONTEND_POS3X-35, FRONTEND_POS3Y, _("Screen Shake"), 0);
521+
addTextButton(FRONTEND_SSHAKE, FRONTEND_POS4X-35, FRONTEND_POS4Y, _("Screen Shake"), 0);
505522
if(getShakeStatus())
506523
{// shaking on
507-
addTextButton(FRONTEND_SSHAKE_R, FRONTEND_POS3M-55, FRONTEND_POS3Y, _("On"), 0);
524+
addTextButton(FRONTEND_SSHAKE_R, FRONTEND_POS4M-55, FRONTEND_POS4Y, _("On"), 0);
508525
}
509526
else
510527
{//shaking off.
511-
addTextButton(FRONTEND_SSHAKE_R, FRONTEND_POS3M-55, FRONTEND_POS3Y, _("Off"), 0);
528+
addTextButton(FRONTEND_SSHAKE_R, FRONTEND_POS4M-55, FRONTEND_POS4Y, _("Off"), 0);
512529
}
513530

514531
////////////
515532
// fog
516-
addTextButton(FRONTEND_FOGTYPE, FRONTEND_POS4X-35, FRONTEND_POS4Y, _("Fog"), 0);
533+
addTextButton(FRONTEND_FOGTYPE, FRONTEND_POS5X-35, FRONTEND_POS5Y, _("Fog"), 0);
517534
if(war_GetFog())
518535
{
519-
addTextButton(FRONTEND_FOGTYPE_R,FRONTEND_POS4M-55,FRONTEND_POS4Y, _("Mist"), 0);
536+
addTextButton(FRONTEND_FOGTYPE_R,FRONTEND_POS5M-55,FRONTEND_POS5Y, _("Mist"), 0);
520537
}
521538
else
522539
{
523-
addTextButton(FRONTEND_FOGTYPE_R,FRONTEND_POS4M-55,FRONTEND_POS4Y, _("Fog Of War"), 0);
540+
addTextButton(FRONTEND_FOGTYPE_R,FRONTEND_POS5M-55,FRONTEND_POS5Y, _("Fog Of War"), 0);
524541
}
525542

526543
////////////
527544
//subtitle mode.
528-
addTextButton(FRONTEND_SUBTITLES, FRONTEND_POS5X - 35, FRONTEND_POS5Y, _("Subtitles"), 0);
545+
addTextButton(FRONTEND_SUBTITLES, FRONTEND_POS6X - 35, FRONTEND_POS6Y, _("Subtitles"), 0);
529546
if (!seq_GetSubtitles())
530547
{
531-
addTextButton(FRONTEND_SUBTITLES_R, FRONTEND_POS5M - 55, FRONTEND_POS5Y, _("Off"), 0);
548+
addTextButton(FRONTEND_SUBTITLES_R, FRONTEND_POS6M - 55, FRONTEND_POS6Y, _("Off"), 0);
532549
}
533550
else
534551
{
535-
addTextButton(FRONTEND_SUBTITLES_R, FRONTEND_POS5M - 55, FRONTEND_POS5Y, _("On"), 0);
552+
addTextButton(FRONTEND_SUBTITLES_R, FRONTEND_POS6M - 55, FRONTEND_POS6Y, _("On"), 0);
536553
}
537554

538555
////////////
539556
//shadows
540-
addTextButton(FRONTEND_SHADOWS, FRONTEND_POS6X - 35, FRONTEND_POS6Y, _("Shadows"), 0);
557+
addTextButton(FRONTEND_SHADOWS, FRONTEND_POS7X - 35, FRONTEND_POS7Y, _("Shadows"), 0);
541558
if (getDrawShadows())
542559
{
543-
addTextButton(FRONTEND_SHADOWS_R, FRONTEND_POS6M - 55, FRONTEND_POS6Y, _("On"), 0);
560+
addTextButton(FRONTEND_SHADOWS_R, FRONTEND_POS7M - 55, FRONTEND_POS7Y, _("On"), 0);
544561
}
545562
else
546563
{ // not flipped
547-
addTextButton(FRONTEND_SHADOWS_R, FRONTEND_POS6M - 55, FRONTEND_POS6Y, _("Off"), 0);
564+
addTextButton(FRONTEND_SHADOWS_R, FRONTEND_POS7M - 55, FRONTEND_POS7Y, _("Off"), 0);
548565
}
549566

550567
// Add some text down the side of the form
@@ -651,6 +668,26 @@ BOOL runGraphicsOptionsMenu(void)
651668
}
652669
break;
653670

671+
case FRONTEND_SCANLINES:
672+
case FRONTEND_SCANLINES_R:
673+
switch (mode = war_getScanlineMode())
674+
{
675+
case SCANLINES_OFF:
676+
war_setScanlineMode(SCANLINES_50);
677+
widgSetString(psWScreen, FRONTEND_SCANLINES_R, _("50%"));
678+
break;
679+
680+
case SCANLINES_50:
681+
war_setScanlineMode(SCANLINES_BLACK);
682+
widgSetString(psWScreen, FRONTEND_SCANLINES_R, _("Black"));
683+
break;
684+
685+
case SCANLINES_BLACK:
686+
war_setScanlineMode(SCANLINES_OFF);
687+
widgSetString(psWScreen, FRONTEND_SCANLINES_R, _("Off"));
688+
break;
689+
}
690+
654691
default:
655692
break;
656693
}

src/frontend.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,8 @@ enum
200200
FRONTEND_SSHAKE_R,
201201
FRONTEND_FMVMODE,
202202
FRONTEND_FMVMODE_R,
203+
FRONTEND_SCANLINES,
204+
FRONTEND_SCANLINES_R,
203205
FRONTEND_SUBTITLES,
204206
FRONTEND_SUBTITLES_R,
205207
FRONTEND_SHADOWS,

src/warzoneconfig.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
typedef struct _warzoneGlobals
4545
{
4646
FMV_MODE FMVmode;
47+
SCANLINE_MODE scanlines;
4748
BOOL bFog;
4849
SWORD effectsLevel;
4950
BOOL Fullscreen;
@@ -182,6 +183,18 @@ FMV_MODE war_GetFMVmode(void)
182183
return warGlobs.FMVmode;
183184
}
184185

186+
void war_setScanlineMode(SCANLINE_MODE mode)
187+
{
188+
debug(LOG_VIDEO, "%d", mode);
189+
warGlobs.scanlines = mode;
190+
}
191+
192+
SCANLINE_MODE war_getScanlineMode(void)
193+
{
194+
debug(LOG_VIDEO, "%d", warGlobs.scanlines);
195+
return warGlobs.scanlines;
196+
}
197+
185198
void war_SetPauseOnFocusLoss(bool enabled)
186199
{
187200
warGlobs.pauseOnFocusLoss = enabled;

src/warzoneconfig.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#define __INCLUDED_SRC_WARZONECONFIG_H__
2626

2727
#include "lib/framework/frame.h"
28+
#include "lib/sequence/sequence.h"
2829

2930
/***************************************************************************/
3031
/*
@@ -68,6 +69,8 @@ extern bool war_GetColouredCursor(void);
6869
extern void war_SetColouredCursor(bool enabled);
6970
extern bool war_GetMusicEnabled(void);
7071
extern void war_SetMusicEnabled(bool enabled);
72+
void war_setScanlineMode(SCANLINE_MODE mode);
73+
SCANLINE_MODE war_getScanlineMode(void);
7174

7275
/**
7376
* Enable or disable sound initialization

0 commit comments

Comments
 (0)