diff --git a/SConstruct b/SConstruct index f21ee852a..119764f84 100644 --- a/SConstruct +++ b/SConstruct @@ -780,6 +780,26 @@ constexpr A a(){return {};} ''' if not self.Cxx11Compile(context, text=f, msg='for C++11 constexpr'): raise SCons.Errors.StopError("C++ compiler does not support constexpr.") + @_custom_test + def check_constexpr_union_constructor(self,context): + # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56583 + # <=gcc-4.7.x ICE on constexpr union constructors with anonymous + # substructure. + # Works fine without the substructure. + # Works fine in >=gcc-4.8 regardless of substructure. + f = ''' +union U { + struct { + int a; + }; + constexpr U(int b) : + a(b) + { + } +}; +U a{640}; +''' + self.Cxx11Compile(context, text=f, msg='whether compiler supports constexpr union constructors', successflags={'CPPDEFINES' : ['DXX_HAVE_CONSTEXPR_UNION_CONSTRUCTOR']}) @_implicit_test def check_pch(self,context): for how in [{'CXXFLAGS' : ['-x', 'c++-header']}]: diff --git a/common/include/gr.h b/common/include/gr.h index d56348fbf..51efccb8a 100644 --- a/common/include/gr.h +++ b/common/include/gr.h @@ -85,11 +85,6 @@ struct grs_point #define BM_OGL 5 #endif /* def OGL */ -#define SM(w,h) ((((u_int32_t)w)<<16)+(((u_int32_t)h)&0xFFFF)) -#define SM_W(m) (m>>16) -#define SM_H(m) (m&0xFFFF) -#define SM_ORIGINAL 0 - #define BM_FLAG_TRANSPARENT 1 #define BM_FLAG_SUPER_TRANSPARENT 2 #define BM_FLAG_NO_LIGHTING 4 @@ -166,36 +161,71 @@ struct grs_canvas : prohibit_void_ptr // canvas. Saves the current VGA state and screen mode. #ifdef __cplusplus +union screen_mode +{ +private: + uint32_t wh; +public: + struct { + uint16_t width, height; + }; + bool operator==(const screen_mode &rhs) + { + return wh == rhs.wh; + } + bool operator!=(const screen_mode &rhs) + { + return !(*this == rhs); + } + screen_mode() = default; +#ifdef DXX_HAVE_CONSTEXPR_UNION_CONSTRUCTOR + constexpr +#endif + screen_mode(uint16_t &&w, uint16_t &&h) : + width(w), height(h) + { + } +}; + +static inline uint16_t SM_W(const screen_mode &s) +{ + return s.width; +} + +static inline uint16_t SM_H(const screen_mode &s) +{ + return s.height; +} + +uint_fast32_t gr_list_modes(array &modes); +int gr_set_mode(screen_mode mode); class grs_screen : prohibit_void_ptr { // This is a video screen - unsigned short sc_w, sc_h; // Actual Width and Height + screen_mode sc_mode; public: grs_canvas sc_canvas; // Represents the entire screen fix sc_aspect; //aspect ratio (w/h) for this screen - uint_fast32_t get_screen_width() const + uint16_t get_screen_width() const { - return sc_w; + return SM_W(sc_mode); } - uint_fast32_t get_screen_height() const + uint16_t get_screen_height() const { - return sc_h; + return SM_H(sc_mode); } - uint_fast32_t get_screen_width_height() const + screen_mode get_screen_mode() const { - return SM(get_screen_width(), get_screen_height()); + return sc_mode; } void set_screen_width_height(uint16_t w, uint16_t h) { - sc_w = w; - sc_h = h; + sc_mode.width = w; + sc_mode.height = h; } }; int gr_init(); - -int gr_list_modes( array &gsmodes ); -int gr_set_mode(u_int32_t mode); void gr_set_attributes(void); //shut down the 2d. Restore the screen mode. diff --git a/common/main/game.h b/common/main/game.h index 5529ba064..010a4d99d 100644 --- a/common/main/game.h +++ b/common/main/game.h @@ -108,7 +108,7 @@ extern int ft_preference; #define NDL 5 // Number of difficulty levels. extern int Game_mode; -extern u_int32_t Game_screen_mode; +extern screen_mode Game_screen_mode; extern int gauge_message_on; diff --git a/d2x-rebirth/main/movie.cpp b/d2x-rebirth/main/movie.cpp index f8a88e438..3fd227ae9 100644 --- a/d2x-rebirth/main/movie.cpp +++ b/d2x-rebirth/main/movie.cpp @@ -407,7 +407,7 @@ int RunMovie(char *filename, int hires_flag, int must_have,int dx,int dy) gr_palette_load(gr_palette); (void)hires_flag; #else - gr_set_mode(SM((hires_flag?640:320),(hires_flag?480:200))); + gr_set_mode(hires_flag ? screen_mode{640, 480} : screen_mode{320, 200}); #endif MVE_sfCallbacks(MovieShowFrame); MVE_palCallbacks(MovieSetPalette); diff --git a/d2x-rebirth/main/movie.h b/d2x-rebirth/main/movie.h index b48765ec2..7bf8f0e2e 100644 --- a/d2x-rebirth/main/movie.h +++ b/d2x-rebirth/main/movie.h @@ -23,8 +23,7 @@ COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. * */ -#ifndef _MOVIE_H -#define _MOVIE_H +#pragma once #ifdef __cplusplus #include "d2x-rebirth/libmve/mvelib.h" @@ -37,11 +36,11 @@ COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. #define MOVIE_ABORTED 2 // movie started by was aborted #ifdef OGL -#define MOVIE_WIDTH (!GameArg.GfxSkipHiresMovie && grd_curscreen->get_screen_width() < 640 ? 640: grd_curscreen->get_screen_width()) -#define MOVIE_HEIGHT (!GameArg.GfxSkipHiresMovie && grd_curscreen->get_screen_height() < 480 ? 480: grd_curscreen->get_screen_height()) +#define MOVIE_WIDTH (!GameArg.GfxSkipHiresMovie && grd_curscreen->get_screen_width() < 640 ? static_cast(640) : grd_curscreen->get_screen_width()) +#define MOVIE_HEIGHT (!GameArg.GfxSkipHiresMovie && grd_curscreen->get_screen_height() < 480 ? static_cast(480) : grd_curscreen->get_screen_height()) #else -#define MOVIE_WIDTH (!GameArg.GfxSkipHiresMovie?640:320) -#define MOVIE_HEIGHT (!GameArg.GfxSkipHiresMovie?480:200) +#define MOVIE_WIDTH static_cast(!GameArg.GfxSkipHiresMovie? 640 : 320) +#define MOVIE_HEIGHT static_cast(!GameArg.GfxSkipHiresMovie? 480 : 200) #endif extern int PlayMovie(const char *subtitles, const char *filename, int allow_abort); @@ -59,5 +58,3 @@ void close_extra_robot_movie(); extern int MovieHires; // specifies whether movies use low or high res #endif - -#endif /* _MOVIE_H */ diff --git a/similar/arch/ogl/gr.cpp b/similar/arch/ogl/gr.cpp index b79f658d5..6e8fe4be2 100644 --- a/similar/arch/ogl/gr.cpp +++ b/similar/arch/ogl/gr.cpp @@ -460,14 +460,17 @@ void gr_toggle_fullscreen() if (gl_initialized) { if (sdl_no_modeswitch == 0) { - if (!SDL_VideoModeOK(SM_W(Game_screen_mode), SM_H(Game_screen_mode), GameArg.DbgBpp, sdl_video_flags)) + auto gsm = Game_screen_mode; + if (!SDL_VideoModeOK(gsm.width, gsm.height, GameArg.DbgBpp, sdl_video_flags)) { - con_printf(CON_URGENT,"Cannot set %ix%i. Fallback to 640x480",SM_W(Game_screen_mode), SM_H(Game_screen_mode)); - Game_screen_mode=SM(640,480); + con_printf(CON_URGENT, "Cannot set %ix%i. Fallback to 640x480", gsm.width, gsm.height); + gsm.width = 640; + gsm.height = 480; + Game_screen_mode = gsm; } - if (!SDL_SetVideoMode(SM_W(Game_screen_mode), SM_H(Game_screen_mode), GameArg.DbgBpp, sdl_video_flags)) + if (!SDL_SetVideoMode(gsm.width, gsm.height, GameArg.DbgBpp, sdl_video_flags)) { - Error("Could not set %dx%dx%d opengl video mode: %s\n", SM_W(Game_screen_mode), SM_H(Game_screen_mode), GameArg.DbgBpp, SDL_GetError()); + Error("Could not set %dx%dx%d opengl video mode: %s\n", gsm.width, gsm.height, GameArg.DbgBpp, SDL_GetError()); } } #ifdef RPI @@ -570,7 +573,7 @@ static void ogl_get_verinfo(void) } // returns possible (fullscreen) resolutions if any. -int gr_list_modes( array &gsmodes ) +uint_fast32_t gr_list_modes(array &gsmodes) { SDL_Rect** modes; int modesnum = 0; @@ -602,46 +605,37 @@ int gr_list_modes( array &gsmodes ) if (modes[i]->w > 0xFFF0 || modes[i]->h > 0xFFF0 // resolutions saved in 32bits. so skip bigger ones (unrealistic in 2010) (changed to 0xFFF0 to fix warning) || modes[i]->w < 320 || modes[i]->h < 200) // also skip everything smaller than 320x200 continue; - gsmodes[modesnum] = SM(modes[i]->w,modes[i]->h); + gsmodes[modesnum].width = modes[i]->w; + gsmodes[modesnum].height = modes[i]->h; modesnum++; - if (modesnum >= 50) // that really seems to be enough big boy. + if (modesnum >= gsmodes.size()) // that really seems to be enough big boy. break; } return modesnum; } } -static int gr_check_mode(uint32_t mode) +static int gr_check_mode(const screen_mode mode) { - unsigned int w, h; - w=SM_W(mode); - h=SM_H(mode); if (sdl_no_modeswitch == 0) { - return SDL_VideoModeOK(w, h, GameArg.DbgBpp, sdl_video_flags); + return SDL_VideoModeOK(SM_W(mode), SM_H(mode), GameArg.DbgBpp, sdl_video_flags); } else { // just tell the caller that any mode is valid... return 32; } } -int gr_set_mode(u_int32_t mode) +int gr_set_mode(screen_mode mode) { - unsigned int w, h; unsigned char *gr_bm_data; - - if (mode<=0) - return 0; - - w=SM_W(mode); - h=SM_H(mode); - if (!gr_check_mode(mode)) { - con_printf(CON_URGENT,"Cannot set %ix%i. Fallback to 640x480",w,h); - w=640; - h=480; - Game_screen_mode=mode=SM(w,h); + con_printf(CON_URGENT, "Cannot set %ix%i. Fallback to 640x480", mode.width, mode.height); + mode.width = 640; + mode.height = 480; + Game_screen_mode = mode; } + const uint_fast32_t w = SM_W(mode), h = SM_H(mode); gr_bm_data = grd_curscreen->sc_canvas.cv_bitmap.get_bitmap_data();//since we use realloc, we want to keep this pointer around. unsigned char *gr_new_bm_data = (unsigned char *)d_realloc(gr_bm_data,w*h); diff --git a/similar/arch/sdl/gr.cpp b/similar/arch/sdl/gr.cpp index 829618619..a557cd8bd 100644 --- a/similar/arch/sdl/gr.cpp +++ b/similar/arch/sdl/gr.cpp @@ -48,7 +48,7 @@ void gr_flip() } // returns possible (fullscreen) resolutions if any. -int gr_list_modes( array &gsmodes ) +uint_fast32_t gr_list_modes(array &gsmodes) { SDL_Rect** modes; int modesnum = 0; @@ -73,42 +73,36 @@ int gr_list_modes( array &gsmodes ) if (modes[i]->w > 0xFFF0 || modes[i]->h > 0xFFF0 // resolutions saved in 32bits. so skip bigger ones (unrealistic in 2010) (kreatordxx - made 0xFFF0 to kill warning) || modes[i]->w < 320 || modes[i]->h < 200) // also skip everything smaller than 320x200 continue; - gsmodes[modesnum] = SM(modes[i]->w,modes[i]->h); + gsmodes[modesnum].width = modes[i]->w; + gsmodes[modesnum].height = modes[i]->h; modesnum++; - if (modesnum >= 50) // that really seems to be enough big boy. + if (modesnum >= gsmodes.size()) // that really seems to be enough big boy. break; } return modesnum; } } -int gr_set_mode(u_int32_t mode) +int gr_set_mode(screen_mode mode) { - unsigned int w, h; - - if (mode<=0) - return 0; - - w=SM_W(mode); - h=SM_H(mode); screen=NULL; SDL_WM_SetCaption(DESCENT_VERSION, DXX_SDL_WINDOW_CAPTION); SDL_WM_SetIcon( SDL_LoadBMP( DXX_SDL_WINDOW_ICON_BITMAP ), NULL ); const auto sdl_video_flags = ::sdl_video_flags; - if(SDL_VideoModeOK(w,h,GameArg.DbgBpp,sdl_video_flags)) + if(SDL_VideoModeOK(SM_W(mode), SM_H(mode), GameArg.DbgBpp, sdl_video_flags)) { - screen=SDL_SetVideoMode(w, h, GameArg.DbgBpp, sdl_video_flags); } else { - con_printf(CON_URGENT,"Cannot set %ix%i. Fallback to 640x480",w,h); - w=640; - h=480; - Game_screen_mode=mode=SM(w,h); - screen=SDL_SetVideoMode(w, h, GameArg.DbgBpp, sdl_video_flags); + con_printf(CON_URGENT,"Cannot set %hux%hu. Fallback to 640x480", SM_W(mode), SM_H(mode)); + mode.width = 640; + mode.height = 480; + Game_screen_mode = mode; } + const unsigned w = SM_W(mode), h = SM_H(mode); + screen = SDL_SetVideoMode(w, h, GameArg.DbgBpp, sdl_video_flags); if (screen == NULL) { diff --git a/similar/main/config.cpp b/similar/main/config.cpp index b52e3fe30..2885d2982 100644 --- a/similar/main/config.cpp +++ b/similar/main/config.cpp @@ -217,7 +217,10 @@ int ReadConfigFile() if ( GameCfg.MusicVolume > 8 ) GameCfg.MusicVolume = 8; if (GameCfg.ResolutionX >= 320 && GameCfg.ResolutionY >= 200) - Game_screen_mode = SM(GameCfg.ResolutionX,GameCfg.ResolutionY); + { + Game_screen_mode.width = GameCfg.ResolutionX; + Game_screen_mode.height = GameCfg.ResolutionY; + } return 0; } diff --git a/similar/main/game.cpp b/similar/main/game.cpp index c1002fc6b..1ec87e91b 100644 --- a/similar/main/game.cpp +++ b/similar/main/game.cpp @@ -173,8 +173,7 @@ void reset_palette_add() PaletteBlueAdd = 0; } - -u_int32_t Game_screen_mode = SM(640,480); +screen_mode Game_screen_mode{640, 480}; //initialize the various canvases on the game screen //called every time the screen mode or cockpit changes @@ -189,11 +188,15 @@ void init_cockpit() PlayerCfg.CockpitMode[1] = CM_FULL_SCREEN; #ifndef OGL + if (PlayerCfg.CockpitMode[1] != CM_LETTERBOX) + { #if defined(DXX_BUILD_DESCENT_II) - int HiresGFXAvailable = !GameArg.GfxSkipHiresGFX; + int HiresGFXAvailable = !GameArg.GfxSkipHiresGFX; #endif - if ( Game_screen_mode != (HiresGFXAvailable? SM(640,480) : SM(320,200)) && PlayerCfg.CockpitMode[1] != CM_LETTERBOX) { - PlayerCfg.CockpitMode[1] = CM_FULL_SCREEN; + auto full_screen_mode = HiresGFXAvailable ? screen_mode{640, 480} : screen_mode{320, 200}; + if (Game_screen_mode != full_screen_mode) { + PlayerCfg.CockpitMode[1] = CM_FULL_SCREEN; + } } #endif @@ -228,14 +231,14 @@ void init_cockpit() break; case CM_LETTERBOX: { - int x,y,w,h; + const unsigned gsm_height = SM_H(Game_screen_mode); + const unsigned w = SM_W(Game_screen_mode); + const unsigned h = (gsm_height * 3) / 4; // true letterbox size (16:9) + const unsigned x = 0; + const unsigned y = (gsm_height - h) / 2; - x = 0; w = SM_W(Game_screen_mode); - h = (SM_H(Game_screen_mode) * 3) / 4; // true letterbox size (16:9) - y = (SM_H(Game_screen_mode)-h)/2; - - gr_rect(x,0,w,SM_H(Game_screen_mode)-h); - gr_rect(x,SM_H(Game_screen_mode)-h,w,SM_H(Game_screen_mode)); + gr_rect(x, 0, w, gsm_height - h); + gr_rect(x, gsm_height - h, w, gsm_height); game_init_render_sub_buffers( x, y, w, h ); break; @@ -272,7 +275,7 @@ void game_init_render_sub_buffers( int x, int y, int w, int h ) //mode if cannot init requested mode) int set_screen_mode(int sm) { - if ( (Screen_mode == sm) && !((sm==SCREEN_GAME) && (grd_curscreen->get_screen_width_height() != Game_screen_mode)) && !(sm==SCREEN_MENU) ) + if ( (Screen_mode == sm) && !((sm==SCREEN_GAME) && (grd_curscreen->get_screen_mode() != Game_screen_mode)) && !(sm==SCREEN_MENU) ) { gr_set_current_canvas(NULL); return 1; @@ -287,33 +290,42 @@ int set_screen_mode(int sm) switch( Screen_mode ) { case SCREEN_MENU: - if (grd_curscreen->get_screen_width_height() != Game_screen_mode) + if (grd_curscreen->get_screen_mode() != Game_screen_mode) if (gr_set_mode(Game_screen_mode)) Error("Cannot set screen mode."); break; case SCREEN_GAME: - if (grd_curscreen->get_screen_width_height() != Game_screen_mode) + if (grd_curscreen->get_screen_mode() != Game_screen_mode) if (gr_set_mode(Game_screen_mode)) Error("Cannot set screen mode."); break; #ifdef EDITOR case SCREEN_EDITOR: - if (grd_curscreen->get_screen_width_height() != SM(800,600)) { + { + const screen_mode editor_mode{800, 600}; + if (grd_curscreen->get_screen_mode() != editor_mode) + { int gr_error; - if ((gr_error=gr_set_mode(SM(800,600)))!=0) { //force into game scrren + if ((gr_error = gr_set_mode(editor_mode)) != 0) { //force into game scrren Warning("Cannot init editor screen (error=%d)",gr_error); return 0; } } + } break; #endif #if defined(DXX_BUILD_DESCENT_II) case SCREEN_MOVIE: - if (grd_curscreen->get_screen_width_height() != SM(MOVIE_WIDTH,MOVIE_HEIGHT)) { - if (gr_set_mode(SM(MOVIE_WIDTH,MOVIE_HEIGHT))) Error("Cannot set screen mode for game!"); + { + const screen_mode movie_mode{MOVIE_WIDTH, MOVIE_HEIGHT}; + if (grd_curscreen->get_screen_mode() != movie_mode) + { + if (gr_set_mode(movie_mode)) + Error("Cannot set screen mode for game!"); gr_palette_load( gr_palette ); } + } break; #endif default: diff --git a/similar/main/menu.cpp b/similar/main/menu.cpp index 508177c5e..6c12c24ed 100644 --- a/similar/main/menu.cpp +++ b/similar/main/menu.cpp @@ -945,17 +945,15 @@ static int gcd(int a, int b) void change_res() { - array modes; - u_int32_t new_mode = 0; - int i = 0, mc = 0, citem = -1, opt_cval = -1, opt_fullscr = -1; + array modes; + int i = 0, mc = 0, citem = -1; - unsigned num_presets = gr_list_modes(modes); + const auto num_presets = gr_list_modes(modes); - { newmenu_item m[50+8]; char restext[50][12], crestext[12], casptext[12]; - range_for (const auto i, partial_range(modes, num_presets)) + range_for (const auto &i, partial_range(modes, num_presets)) { snprintf(restext[mc], sizeof(restext[mc]), "%ix%i", SM_W(i), SM_H(i)); @@ -967,19 +965,19 @@ void change_res() nm_set_item_text(m[mc], ""); mc++; // little space for overview // the fields for custom resolution and aspect - opt_cval = mc; + const auto opt_cval = mc; nm_set_item_radio(m[mc], "use custom values", (citem == -1), 0); mc++; nm_set_item_text(m[mc], "resolution:"); mc++; snprintf(crestext, sizeof(crestext), "%ix%i", SM_W(Game_screen_mode), SM_H(Game_screen_mode)); nm_set_item_input(m[mc], crestext); - modes[mc] = 0; mc++; + mc++; nm_set_item_text(m[mc], "aspect:"); mc++; snprintf(casptext, sizeof(casptext), "%ix%i", GameCfg.AspectY, GameCfg.AspectX); nm_set_item_input(m[mc], casptext); - modes[mc] = 0; mc++; + mc++; nm_set_item_text(m[mc], ""); mc++; // little space for overview // fullscreen - opt_fullscr = mc; + const auto opt_fullscr = mc; nm_set_item_checkbox(m[mc], "Fullscreen", gr_check_fullscreen()); mc++; @@ -997,25 +995,27 @@ void change_res() if (m[opt_fullscr].value != gr_check_fullscreen()) gr_toggle_fullscreen(); + screen_mode new_mode; if (i == opt_cval) // set custom resolution and aspect { char *x; unsigned long w = strtoul(crestext, &x, 10), h; - uint32_t cmode; + screen_mode cmode; if (*x != 'x' || ((h = strtoul(x + 1, &x, 10)), *x)) { nm_messagebox(TXT_WARNING, 1, "OK", "Entered resolution is bad.\nReverting ..."); - cmode = 0; + cmode = {}; } else if (w < 320 || h < 200) { // oh oh - the resolution is too small. Revert! nm_messagebox( TXT_WARNING, 1, "OK", "Entered resolution is too small.\nReverting ..." ); - cmode = 0; + cmode = {}; } else { - cmode = SM(w, h); + cmode.width = w; + cmode.height = h; } auto casp = cmode; w = strtoul(casptext, &x, 10); @@ -1026,17 +1026,20 @@ void change_res() else { // we even have a custom aspect set up - casp = SM(w, h); + casp.width = w; + casp.height = h; } - GameCfg.AspectY = SM_W(casp)/gcd(SM_W(casp),SM_H(casp)); - GameCfg.AspectX = SM_H(casp)/gcd(SM_W(casp),SM_H(casp)); + const auto g = gcd(SM_W(casp), SM_H(casp)); + GameCfg.AspectY = SM_W(casp) / g; + GameCfg.AspectX = SM_H(casp) / g; new_mode = cmode; } else if (i >= 0 && i < num_presets) // set preset resolution { new_mode = modes[i]; - GameCfg.AspectY = SM_W(new_mode)/gcd(SM_W(new_mode),SM_H(new_mode)); - GameCfg.AspectX = SM_H(new_mode)/gcd(SM_W(new_mode),SM_H(new_mode)); + const auto g = gcd(SM_W(new_mode), SM_H(new_mode)); + GameCfg.AspectY = SM_W(new_mode) / g; + GameCfg.AspectX = SM_H(new_mode) / g; } // clean up and apply everything @@ -1054,7 +1057,6 @@ void change_res() } } game_init_render_buffers(SM_W(Game_screen_mode), SM_H(Game_screen_mode)); - } } static void input_config_sensitivity()