diff --git a/CHANGELOG.txt b/CHANGELOG.txt index a5cb08b58..0742d9a91 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,5 +1,9 @@ D2X-Rebirth Changelog +20100624 +-------- +arch/ogl/gr.c, arch/sdl/gr.c, include/gr.h, main/menu.c: Added function to list valid resolutions and build resolutions menu dynamically with the resulting list + 20100623 -------- main/menu.c, main/newmenu.c, main/newmenu.h, main/net_ipx.c: Making menus recreated on the fly in case resolution or font-size changes; Removing arguments to pass width and height to menu which was not used except on one IPX menu; Fixing measurement of menu strings of type NM_TYPE_INPUT_MENU; Fixing slight bug in freeing IPX netlist diff --git a/arch/ogl/gr.c b/arch/ogl/gr.c index 9d428a959..5efab5d8e 100644 --- a/arch/ogl/gr.c +++ b/arch/ogl/gr.c @@ -104,7 +104,7 @@ void gr_do_fullscreen(int f) cury=480; Game_screen_mode=SM(curx,cury); } - + ogl_init_window(curx,cury); } } @@ -198,13 +198,46 @@ void ogl_get_verinfo(void) #endif } +// returns possible (fullscreen) resolutions if any. +int gr_list_modes( u_int32_t gsmodes[] ) +{ + SDL_Rect** modes; + int i = 0, modesnum = 0; + int sdl_check_flags = SDL_OPENGL | SDL_FULLSCREEN; // always use Fullscreen as lead. + + modes = SDL_ListModes(NULL, sdl_check_flags); + + if (modes == (SDL_Rect**)0) // check if we get any modes - if not, return 0 + return 0; + + + if (modes == (SDL_Rect**)-1) + { + return 0; // can obviously use any resolution... strange! + } + else + { + for (i = 0; modes[i]; ++i) + { + if (modes[i]->w > 0xFFFF || modes[i]->h > 0xFFFF // resolutions saved in 32bits. so skip bigger ones (unrealistic in 2010) + || modes[i]->w < 320 || modes[i]->h < 200) // also skip everything smaller than 320x200 + continue; + gsmodes[modesnum] = SM(modes[i]->w,modes[i]->h); + modesnum++; + if (modesnum >= 50) // that really seems to be enough big boy. + break; + } + return modesnum; + } +} + int gr_check_mode(u_int32_t mode) { unsigned int w, h; - + w=SM_W(mode); h=SM_H(mode); - + return SDL_VideoModeOK(w, h, GameArg.DbgBpp, SDL_OPENGL | (ogl_fullscreen?SDL_FULLSCREEN:0)); } @@ -391,7 +424,7 @@ int gr_init(int mode) ogl_init_pixel_buffers(256, 128); // for gamefont_init gr_installed = 1; - + return 0; } @@ -434,7 +467,7 @@ void ogl_urect(int left,int top,int right,int bot) { GLfloat xo,yo,xf,yf; int c=COLOR; - + xo=(left+grd_curcanv->cv_bitmap.bm_x)/(float)last_width; xf = (right + 1 + grd_curcanv->cv_bitmap.bm_x) / (float)last_width; yo=1.0-(top+grd_curcanv->cv_bitmap.bm_y)/(float)last_height; @@ -492,7 +525,7 @@ void ogl_do_palfx(void) glVertex2f(1,1); glVertex2f(1,0); glEnd(); - glEnable(GL_BLEND); + glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } @@ -615,7 +648,7 @@ void save_screen_shot(int automap_flag) static int savenum=0; char savename[13+sizeof(SCRNS_DIR)]; unsigned char *buf; - + if (!GameArg.DbgGlReadPixelsOk){ if (!automap_flag) hud_message(MSGC_GAME_FEEDBACK,"glReadPixels not supported on your configuration"); diff --git a/arch/sdl/gr.c b/arch/sdl/gr.c index 9d8a0a0a9..41f2f5d89 100644 --- a/arch/sdl/gr.c +++ b/arch/sdl/gr.c @@ -30,7 +30,7 @@ void gr_flip() dest.x = src.x = dest.y = src.y = 0; dest.w = src.w = canvas->w; dest.h = src.h = canvas->h; - + SDL_BlitSurface(canvas, &src, screen, &dest); SDL_Flip(screen); } @@ -42,6 +42,41 @@ void gr_set_draw_buffer(int buf) buf = buf; } +// returns possible (fullscreen) resolutions if any. +int gr_list_modes( u_int32_t gsmodes[] ) +{ + SDL_Rect** modes; + int i = 0, modesnum = 0; + int sdl_check_flags = sdl_video_flags; + + sdl_check_flags |= SDL_FULLSCREEN; // always use Fullscreen as lead. + + modes = SDL_ListModes(NULL, sdl_check_flags); + + if (modes == (SDL_Rect**)0) // check if we get any modes - if not, return 0 + return 0; + + + if (modes == (SDL_Rect**)-1) + { + return 0; // can obviously use any resolution... strange! + } + else + { + for (i = 0; modes[i]; ++i) + { + if (modes[i]->w > 0xFFFF || modes[i]->h > 0xFFFF // resolutions saved in 32bits. so skip bigger ones (unrealistic in 2010) + || modes[i]->w < 320 || modes[i]->h < 200) // also skip everything smaller than 320x200 + continue; + gsmodes[modesnum] = SM(modes[i]->w,modes[i]->h); + modesnum++; + if (modesnum >= 50) // that really seems to be enough big boy. + break; + } + return modesnum; + } +} + int gr_check_mode(u_int32_t mode) { unsigned int w, h; @@ -195,7 +230,7 @@ void gr_palette_step_up( int r, int g, int b ) int temp; SDL_Palette *palette; SDL_Color colors[256]; - + if ( (r==last_r) && (g==last_g) && (b==last_b) ) return; @@ -242,7 +277,7 @@ void gr_palette_step_up( int r, int g, int b ) #undef min static inline int min(int x, int y) { return x < y ? x : y; } -void gr_palette_load( ubyte *pal ) +void gr_palette_load( ubyte *pal ) { int i, j; SDL_Palette *palette; diff --git a/include/gr.h b/include/gr.h index 6630e76db..324d55bd3 100644 --- a/include/gr.h +++ b/include/gr.h @@ -147,6 +147,7 @@ typedef struct _grs_screen { // This is a video screen int gr_init(int mode); +int gr_list_modes( u_int32_t gsmodes[] ); int gr_check_mode(u_int32_t mode); int gr_set_mode(u_int32_t mode); void gr_set_attributes(void); diff --git a/main/menu.c b/main/menu.c index 727cd0497..f27a7f2d0 100644 --- a/main/menu.c +++ b/main/menu.c @@ -980,92 +980,99 @@ int gcd(int a, int b) return gcd(b, a%b); } -int change_res_poll() { return 0; } - void change_res() { - newmenu_item m[15]; - u_int32_t modes[15]; - int i = 0, mc = 0, num_presets = 0; - char customres[16], aspect[16]; - int fullscreenc; - u_int32_t screen_mode = 0, aspect_mode = 0; + u_int32_t modes[50], new_mode = 0; + int i = 0, mc = 0, num_presets = 0, citem = -1, opt_cval = -1, opt_cres = -1, opt_casp = -1, opt_fullscr = -1; - // the list of pre-defined resolutions - if (gr_check_mode(SM(320,200))) { m[mc].type = NM_TYPE_RADIO; m[mc].text = "320x200 (16x10)"; m[mc].value = (Game_screen_mode == SM(320,200)); m[mc].group = 0; modes[mc] = SM(320,200); mc++; } - if (gr_check_mode(SM(640,480))) { m[mc].type = NM_TYPE_RADIO; m[mc].text = "640x480 (4x3)"; m[mc].value = (Game_screen_mode == SM(640,480)); m[mc].group = 0; modes[mc] = SM(640,480); mc++; } - if (gr_check_mode(SM(800,600))) { m[mc].type = NM_TYPE_RADIO; m[mc].text = "800x600 (4x3)"; m[mc].value = (Game_screen_mode == SM(800,600)); m[mc].group = 0; modes[mc] = SM(800,600); mc++; } - if (gr_check_mode(SM(1024,768))) { m[mc].type = NM_TYPE_RADIO; m[mc].text = "1024x768 (4x3)"; m[mc].value = (Game_screen_mode == SM(1024,768)); m[mc].group = 0; modes[mc] = SM(1024,768); mc++; } - if (gr_check_mode(SM(1280,800))) { m[mc].type = NM_TYPE_RADIO; m[mc].text = "1280x800 (16x10)"; m[mc].value = (Game_screen_mode == SM(1280,800)); m[mc].group = 0; modes[mc] = SM(1280,800); mc++; } - if (gr_check_mode(SM(1280,1024))) { m[mc].type = NM_TYPE_RADIO; m[mc].text = "1280x1024 (5x4)"; m[mc].value = (Game_screen_mode == SM(1280,1024)); m[mc].group = 0; modes[mc] = SM(1280,1024); mc++; } - if (gr_check_mode(SM(1440,900))) { m[mc].type = NM_TYPE_RADIO; m[mc].text = "1440x900 (16x10)"; m[mc].value = (Game_screen_mode == SM(1440,900)); m[mc].group = 0; modes[mc] = SM(1440,900); mc++; } - if (gr_check_mode(SM(1600,1200))) { m[mc].type = NM_TYPE_RADIO; m[mc].text = "1600x1200 (4x3)"; m[mc].value = (Game_screen_mode == SM(1600,1200)); m[mc].group = 0; modes[mc] = SM(1600,1200); mc++; } - if (gr_check_mode(SM(1920,1200))) { m[mc].type = NM_TYPE_RADIO; m[mc].text = "1920x1200 (16x10)"; m[mc].value = (Game_screen_mode == SM(1920,1200)); m[mc].group = 0; modes[mc] = SM(1920,1200); mc++; } - num_presets = mc; + num_presets = gr_list_modes( modes ); - // now see which field is true and break there - m[mc].value=0; - for (i = 0; i < mc; i++) + { + newmenu_item m[num_presets+8]; + char restext[num_presets][12], crestext[12], casptext[12]; + + for (i = 0; i <= num_presets-1; i++) + { + snprintf(restext[mc], sizeof(restext[mc]), "%ix%i", SM_W(modes[i]), SM_H(modes[i])); + m[mc].type = NM_TYPE_RADIO; + m[mc].text = restext[mc]; + m[mc].value = ((citem == -1) && (Game_screen_mode == modes[i]) && GameCfg.AspectY == SM_W(modes[i])/gcd(SM_W(modes[i]),SM_H(modes[i])) && GameCfg.AspectX == SM_H(modes[i])/gcd(SM_W(modes[i]),SM_H(modes[i]))); + m[mc].group = 0; if (m[mc].value) - break; + citem = mc; + mc++; + } - // the field for custom resolution and aspect - m[mc].type = NM_TYPE_RADIO; m[mc].text = "use custom values"; m[mc].value = (i == mc); m[mc].group = 0; modes[mc] = 0; mc++; + m[mc].type = NM_TYPE_TEXT; m[mc].text = ""; mc++; // little space for overview + // the fields for custom resolution and aspect + opt_cval = mc; + m[mc].type = NM_TYPE_RADIO; m[mc].text = "use custom values"; m[mc].value = (citem == -1); m[mc].group = 0; mc++; m[mc].type = NM_TYPE_TEXT; m[mc].text = "resolution:"; mc++; - sprintf(customres, "%ix%i", SM_W(Game_screen_mode), SM_H(Game_screen_mode)); - m[mc].type = NM_TYPE_INPUT; m[mc].text = customres; m[mc].text_len = 11; modes[mc] = 0; mc++; + snprintf(crestext, sizeof(crestext), "%ix%i", SM_W(Game_screen_mode), SM_H(Game_screen_mode)); + opt_cres = mc; + m[mc].type = NM_TYPE_INPUT; m[mc].text = crestext; m[mc].text_len = 11; modes[mc] = 0; mc++; m[mc].type = NM_TYPE_TEXT; m[mc].text = "aspect:"; mc++; - sprintf(aspect, "%ix%i", GameCfg.AspectY, GameCfg.AspectX); - m[mc].type = NM_TYPE_INPUT; m[mc].text = aspect; m[mc].text_len = 11; modes[mc] = 0; mc++; - - // fullscreen toggle - fullscreenc = mc; m[mc].type = NM_TYPE_CHECK; m[mc].text = "Fullscreen"; m[mc].value = gr_check_fullscreen(); mc++; + opt_casp = mc; + snprintf(casptext, sizeof(casptext), "%ix%i", GameCfg.AspectY, GameCfg.AspectX); + m[mc].type = NM_TYPE_INPUT; m[mc].text = casptext; m[mc].text_len = 11; modes[mc] = 0; mc++; + m[mc].type = NM_TYPE_TEXT; m[mc].text = ""; mc++; // little space for overview + // fullscreen + opt_fullscr = mc; + m[mc].type = NM_TYPE_CHECK; m[mc].text = "Fullscreen"; m[mc].value = gr_check_fullscreen(); mc++; // create the menu - i = newmenu_do1(NULL, "Screen Resolution", mc, m, change_res_poll, NULL, 0); + newmenu_do1(NULL, "Screen Resolution", mc, m, NULL, NULL, 0); // menu is done, now do what we need to do + // check which resolution field was selected + for (i = 0; i <= mc; i++) + if ((m[i].type == NM_TYPE_RADIO) && (m[i].group==0) && (m[i].value == 1)) + break; + // now check for fullscreen toggle and apply if necessary - if (m[fullscreenc].value != gr_check_fullscreen()) + if (m[opt_fullscr].value != gr_check_fullscreen()) gr_toggle_fullscreen(); - // check which preset field was selected - for (i = 0; (m[i].value == 0) && (i < num_presets); i++); - - if (modes[i]==0) // no preset selected, use custom values and set screen_mode and aspect + if (i == opt_cval) // set custom resolution and aspect { - if (!strchr(customres, 'x')) + u_int32_t cmode = Game_screen_mode, casp = Game_screen_mode; + + if (!strchr(crestext, 'x')) return; - screen_mode = SM(atoi(customres), atoi(strchr(customres, 'x')+1)); - if (SM_W(screen_mode) < 320 || SM_H(screen_mode) < 200) // oh oh - the resolution is too small. Revert! + cmode = SM(atoi(crestext), atoi(strchr(crestext, 'x')+1)); + if (SM_W(cmode) < 320 || SM_H(cmode) < 200) // oh oh - the resolution is too small. Revert! { nm_messagebox( TXT_WARNING, 1, "OK", "Entered resolution is too small.\nReverting ..." ); - return; + cmode = new_mode; } - if (strchr(aspect, 'x')) // we even have a custom aspect set up - { - aspect_mode = SM(atoi(aspect), atoi(strchr(aspect, 'x')+1)); - GameCfg.AspectY = SM_W(aspect_mode)/gcd(SM_W(aspect_mode),SM_H(aspect_mode)); - GameCfg.AspectX = SM_H(aspect_mode)/gcd(SM_W(aspect_mode),SM_H(aspect_mode)); - } - } - else // a preset field is selected - set screen_mode and aspect - { - screen_mode = modes[i]; - GameCfg.AspectY = SM_W(screen_mode)/gcd(SM_W(screen_mode),SM_H(screen_mode)); - GameCfg.AspectX = SM_H(screen_mode)/gcd(SM_W(screen_mode),SM_H(screen_mode)); - } + casp = cmode; + if (strchr(casptext, 'x')) // we even have a custom aspect set up + { + casp = SM(atoi(casptext), atoi(strchr(casptext, 'x')+1)); + } + GameCfg.AspectY = SM_W(casp)/gcd(SM_W(casp),SM_H(casp)); + GameCfg.AspectX = SM_H(casp)/gcd(SM_W(casp),SM_H(casp)); + 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)); + } // clean up and apply everything newmenu_close(); set_screen_mode(SCREEN_MENU); - Game_screen_mode = screen_mode; - gr_set_mode(Game_screen_mode); + if (new_mode != Game_screen_mode) + gr_set_mode(new_mode); + Game_screen_mode = new_mode; init_cockpit(); - game_init_render_buffers(SM_W(screen_mode), SM_H(screen_mode), VR_NONE); + game_init_render_buffers(SM_W(Game_screen_mode), SM_H(Game_screen_mode), VR_NONE); + } } int input_menuset(newmenu *menu, d_event *event, void *userdata)