New patch

Forum for technical discussions regarding development. If you have a general suggestion, problem or comment, please use one of the other forums.

Moderator: OpenTTD Developers

Post Reply
JohnRus
Engineer
Engineer
Posts: 14
Joined: 06 Dec 2004 23:04
Location: Sankt-Peterburg, Russia
Contact:

New patch

Post by JohnRus »

This patch is for new grafical refresh rate selector

1. In variables.h add this code

Code: Select all

#define MAX_REFRESH_RATES 16
uint16 _refresh_rates[MAX_REFRESH_RATES];
uint16 _num_refresh_rates;
uint16 _currentRefreshRate;
uint16 g_uiMaxRefresh;

void (*enumRefreshRates)(uint16 uiWidth, uint16 uiHeight);
int GetCurRes();
2. in strings.h add this strings to enum

Code: Select all

...,
STR_OPTIONS_REFRESH_CBO,
STR_OPTIONS_REFRESH_TIP,
...
3. in strings.c add this code to GetSpecialPlayerNameString function

Code: Select all

...
//refresh rates
	if (IS_INT_INSIDE(ind, (SPECSTR_REFRESH_START - 0x70E4), (SPECSTR_REFRESH_END - 0x70E4) + 1))
	{
        int i = ind - (SPECSTR_REFRESH_START - 0x70E4);
		return buff + sprintf(buff, _refresh_rates[i]?"%d hz":"default", _refresh_rates[i]);
	}
...
4. in gfx.c add this code

Code: Select all

bool ChangeRefreshInGame(uint16 uiRefreshNumber)
{
	uint16 uiOldRefresh = _display_hz;
	uint16 uiOldRefreshNumber = _currentRefreshRate;

	if(!_fullscreen) return false;
	if(uiRefreshNumber == _currentRefreshRate) return false;

    _display_hz = _refresh_rates[uiRefreshNumber];
	if(!_video_driver->change_resolution(_cur_resolution[0], _cur_resolution[1]))
	{
		_display_hz = uiOldRefresh;
		return false;
	}

	_currentRefreshRate = uiRefreshNumber;

	return true;
}
5. in ttd.h add this code to SpecialStrings enum

Code: Select all

...
SPECSTR_REFRESH_START = 0x7160,
	SPECSTR_REFRESH_END = 0x717F,
...
6. in gfx.h add this function prototype

Code: Select all

bool ChangeRefreshInGame(uint16 uiRefreshNumber);
7. A) in settings_gui.c remove keyword static from int GetCurRes() func
so it would be look as

Code: Select all

int GetCurRes()
{...
B) in Widget _game_options_widgets array add this elements BEFORE WIDGETS_END element in last position

Code: Select all

//refresh rate combobox
{          WWT_6,    14,   115,   169,   160,   171, STR_OPTIONS_REFRESH_CBO,		STR_OPTIONS_REFRESH_TIP},
{   WWT_CLOSEBOX,    14,   158,   168,   161,   170, STR_0225,						STR_OPTIONS_REFRESH_TIP},
so it would be look as

Code: Select all

static const Widget _game_options_widgets[] = {
{   WWT_CLOSEBOX,    14,     0,    10,     0,    13, STR_00C5,								STR_018B_CLOSE_WINDOW},
{    WWT_CAPTION,    14,    11,   369,     0,    13, STR_00B1_GAME_OPTIONS,		STR_018C_WINDOW_TITLE_DRAG_THIS},
{      WWT_PANEL,    14,     0,   369,    14,   238, 0x0,											STR_NULL},
{      WWT_FRAME,    14,    10,   179,    20,    55, STR_02E0_CURRENCY_UNITS,	STR_NULL},
{          WWT_6,    14,    20,   169,    34,    45, STR_02E1,								STR_02E2_CURRENCY_UNITS_SELECTION},
{   WWT_CLOSEBOX,    14,   158,   168,    35,    44, STR_0225,								STR_02E2_CURRENCY_UNITS_SELECTION},
{      WWT_FRAME,    14,   190,   359,    20,    55, STR_02E3_DISTANCE_UNITS,	STR_NULL},
{          WWT_6,    14,   200,   349,    34,    45, STR_02E4,								STR_02E5_DISTANCE_UNITS_SELECTION},
{   WWT_CLOSEBOX,    14,   338,   348,    35,    44, STR_0225,								STR_02E5_DISTANCE_UNITS_SELECTION},
{      WWT_FRAME,    14,    10,   179,    62,    97, STR_02E6_ROAD_VEHICLES,	STR_NULL},
{          WWT_6,    14,    20,   169,    76,    87, STR_02E7,								STR_02E8_SELECT_SIDE_OF_ROAD_FOR},
{   WWT_CLOSEBOX,    14,   158,   168,    77,    86, STR_0225,								STR_02E8_SELECT_SIDE_OF_ROAD_FOR},
{      WWT_FRAME,    14,   190,   359,    62,    97, STR_02EB_TOWN_NAMES,			STR_NULL},
{          WWT_6,    14,   200,   349,    76,    87, STR_02EC,								STR_02ED_SELECT_STYLE_OF_TOWN_NAMES},
{   WWT_CLOSEBOX,    14,   338,   348,    77,    86, STR_0225,								STR_02ED_SELECT_STYLE_OF_TOWN_NAMES},
{      WWT_FRAME,    14,    10,   179,   104,   139, STR_02F4_AUTOSAVE,				STR_NULL},
{          WWT_6,    14,    20,   169,   118,   129, STR_02F5,								STR_02F6_SELECT_INTERVAL_BETWEEN},
{   WWT_CLOSEBOX,    14,   158,   168,   119,   128, STR_0225,								STR_02F6_SELECT_INTERVAL_BETWEEN},

{      WWT_FRAME,    14,    10,   359,   194,   228, STR_02BC_VEHICLE_DESIGN_NAMES,				STR_NULL},
{          WWT_6,    14,    20,   119,   207,   218, STR_02BD,								STR_02C1_VEHICLE_DESIGN_NAMES_SELECTION},
{   WWT_CLOSEBOX,    14,   108,   118,   208,   217, STR_0225,								STR_02C1_VEHICLE_DESIGN_NAMES_SELECTION},
{   WWT_CLOSEBOX,    14,   130,   349,   207,   218, STR_02C0_SAVE_CUSTOM_NAMES_TO_DISK,	STR_02C2_SAVE_CUSTOMIZED_VEHICLE},

{      WWT_FRAME,    14,   190,   359,   104,   139, STR_OPTIONS_LANG,				STR_NULL},
{          WWT_6,    14,   200,   349,   118,   129, STR_OPTIONS_LANG_CBO,		STR_OPTIONS_LANG_TIP},
{   WWT_CLOSEBOX,    14,   338,   348,   119,   128, STR_0225,								STR_OPTIONS_LANG_TIP},

{      WWT_FRAME,    14,    10,   179,   146,   190, STR_OPTIONS_RES,				STR_NULL},
{          WWT_6,    14,    20,   110,   160,   171, STR_OPTIONS_RES_CBO,			STR_OPTIONS_RES_TIP},
{   WWT_CLOSEBOX,    14,    99,   109,   161,   170, STR_0225,						STR_OPTIONS_RES_TIP},
{    WWT_TEXTBTN,    14,   149,   169,   176,   184, STR_EMPTY,						STR_OPTIONS_FULLSCREEN_TIP},

{      WWT_FRAME,    14,   190,   359,   146,   190, STR_OPTIONS_SCREENSHOT_FORMAT,				STR_NULL},
{          WWT_6,    14,   200,   349,   160,   171, STR_OPTIONS_SCREENSHOT_FORMAT_CBO,		STR_OPTIONS_SCREENSHOT_FORMAT_TIP},
{   WWT_CLOSEBOX,    14,   338,   348,   161,   170, STR_0225,								STR_OPTIONS_SCREENSHOT_FORMAT_TIP},

//refresh rate combobox
{          WWT_6,    14,   115,   169,   160,   171, STR_OPTIONS_REFRESH_CBO,		STR_OPTIONS_REFRESH_TIP},
{   WWT_CLOSEBOX,    14,   158,   168,   161,   170, STR_0225,						STR_OPTIONS_REFRESH_TIP},

{   WIDGETS_END},
};
C) modify GameOptionsWndProc(Window *w, WindowEvent *e) function. So it would be look like

Code: Select all

static void GameOptionsWndProc(Window *w, WindowEvent *e)
{
	int i;

	switch(e->event)
	{
	case WE_PAINT:
	{
		StringID str = STR_02BE_DEFAULT;

		i = GetCurRes();
		
		w->disabled_state = (_vehicle_design_names & 1) ? (++str, 0) : (1 << 21);
		
		SetDParam(0, str);
		SetDParam(1, _currency_string_list[_opt_mod_ptr->currency]);
		SetDParam(2, _opt_mod_ptr->kilometers + STR_0139_IMPERIAL_MILES);
		SetDParam(3, STR_02E9_DRIVE_ON_LEFT + _opt_mod_ptr->road_side);
		SetDParam(4, STR_TOWNNAME_ENGLISH + _opt_mod_ptr->town_name);
		SetDParam(5, _autosave_dropdown[_opt_mod_ptr->autosave]);
		SetDParam(6, SPECSTR_LANGUAGE_START + _dynlang.curr);
		
		SetDParam(7, i == _num_resolutions ? STR_RES_OTHER : SPECSTR_RESOLUTION_START + i);		
		SetDParam(8, SPECSTR_SCREENSHOT_START + _cur_screenshot_format);
		(_fullscreen) ? SETBIT(w->click_state, 28) : CLRBIT(w->click_state, 28); // fullscreen button
		
		SetDParam(9, SPECSTR_REFRESH_START + _currentRefreshRate);

		DrawWindowWidgets(w);
		
		DrawString(20, 175, STR_OPTIONS_FULLSCREEN, 0); // fullscreen
	}	break;

	case WE_CLICK:
		switch(e->click.widget) {
		case 5:
			ShowDropDownMenu(w, _currency_string_list, _opt_mod_ptr->currency, e->click.widget, _game_mode == GM_MENU ? 0 : ~GetMaskOfAllowedCurrencies());
			return;
		case 8:
			ShowDropDownMenu(w, _distances_dropdown, _opt_mod_ptr->kilometers, e->click.widget, 0);
			return;
		case 11: {
			int i = _opt_mod_ptr->road_side;
			ShowDropDownMenu(w, _driveside_dropdown, i, e->click.widget, (_game_mode == GM_MENU) ? 0 : (-1) ^ (1 << i));
			return;
		}
		case 14: {
			int i = _opt_mod_ptr->town_name;
			ShowDropDownMenu(w, BuildDynamicDropdown(STR_TOWNNAME_ENGLISH, SPECSTR_TOWNNAME_LAST - SPECSTR_TOWNNAME_START + 1), i, e->click.widget, (_game_mode == GM_MENU) ? 0 : (-1) ^ (1 << i));
			return;
		}
		case 17:
			ShowDropDownMenu(w, _autosave_dropdown, _opt_mod_ptr->autosave, e->click.widget, 0);
			return;
		case 20:
			ShowDropDownMenu(w, _designnames_dropdown, (_vehicle_design_names&1)?1:0, e->click.widget, (_vehicle_design_names&2)?0:2);
			return;
		case 21:
			return;
		case 24:
			ShowDropDownMenu(w, _dynlang.dropdown, _dynlang.curr, e->click.widget, 0);
			return;
		case 27:
			// setup resolution dropdown
			ShowDropDownMenu(w, BuildDynamicDropdown(SPECSTR_RESOLUTION_START, _num_resolutions), GetCurRes(), e->click.widget, 0);
			return;
		case 28: /* Click fullscreen on/off */
			(_fullscreen) ? CLRBIT(w->click_state, 28) : SETBIT(w->click_state, 28);
			ToggleFullScreen(!_fullscreen); // toggle full-screen on/off
			SetWindowDirty(w);
			return;
		case 31: /* Setup screenshot format dropdown */
			ShowDropDownMenu(w, BuildDynamicDropdown(SPECSTR_SCREENSHOT_START, _num_screenshot_formats), _cur_screenshot_format, e->click.widget, 0);
			return;
		case 33:
			//setup refresh dropdown
			ShowDropDownMenu(w, BuildDynamicDropdown(SPECSTR_REFRESH_START, _num_refresh_rates), _currentRefreshRate, e->click.widget, 0);
			return;
		}
		break;

	case WE_DROPDOWN_SELECT:
		switch(e->dropdown.button) {
		case 20:
			if (e->dropdown.index == 0) {
				DeleteCustomEngineNames();
				MarkWholeScreenDirty();
			} else if (!(_vehicle_design_names&1)) {
				LoadCustomEngineNames();
				MarkWholeScreenDirty();
			}
			break;
		case 5:
			_opt_mod_ptr->currency = _opt.currency = e->dropdown.index;
			MarkWholeScreenDirty();
			break;
		case 8:
			_opt_mod_ptr->kilometers = e->dropdown.index;
			MarkWholeScreenDirty();
			break;
		case 11:
			if (_game_mode == GM_MENU)
				DoCommandP(0, e->dropdown.index, 0, NULL, CMD_SET_ROAD_DRIVE_SIDE | CMD_MSG(STR_EMPTY));
			break;
		case 14:
			if (_game_mode == GM_MENU)
				DoCommandP(0, e->dropdown.index, 0, NULL, CMD_SET_TOWN_NAME_TYPE | CMD_MSG(STR_EMPTY));
			break;
		case 17:
			_opt_mod_ptr->autosave = e->dropdown.index;
			SetWindowDirty(w);
			break;

		// change interface language
		case 24:
			ReadLanguagePack(e->dropdown.index);
			MarkWholeScreenDirty();
			break;

		// change resolution
		case 27:
			if(e->dropdown.index < _num_resolutions)
			{
				if(ChangeResInGame(_resolutions[e->dropdown.index][0],_resolutions[e->dropdown.index][1]))
				{
                    SetWindowDirty(w);
				}
			}
			break;

		// change screenshot format
		case 31:
			SetScreenshotFormat(e->dropdown.index);
			SetWindowDirty(w);
			break;

		//change refresh
		case 33:
			if(e->dropdown.index < _num_refresh_rates)
			{
				if(ChangeRefreshInGame(e->dropdown.index)) SetWindowDirty(w);
			}
			break;
		}
		break;
	}
}
8. in win32.c add this code

Code: Select all

void EnumRefreshRates(uint16 uiWidth, uint16 uiHeight)
{
	DEVMODE displayMode;
	DWORD dwModeNumber = 0;
	g_uiMaxRefresh = 0;

	_num_refresh_rates = 0;
	while(EnumDisplaySettings(NULL, dwModeNumber, &displayMode))
	{
		if((displayMode.dmBitsPerPel == _fullscreen_bpp)&(displayMode.dmPelsWidth == (DWORD)uiWidth)&(displayMode.dmPelsWidth == (DWORD)uiWidth)&(displayMode.dmPelsHeight == (DWORD)uiHeight))
		{
			_refresh_rates[_num_refresh_rates] = displayMode.dmDisplayFrequency;
            if(_refresh_rates[_num_refresh_rates] == _display_hz) _currentRefreshRate = _num_refresh_rates;

			if(displayMode.dmDisplayFrequency >= g_uiMaxRefresh) g_uiMaxRefresh = displayMode.dmDisplayFrequency;

            _num_refresh_rates++;
            if(_num_refresh_rates >= MAX_REFRESH_RATES) break;
		}

		dwModeNumber++;
	}

	//why not before previous code block? because we need correct maximum refresh rate for first run
	if(!_wnd.fullscreen)
	{
		_num_refresh_rates = 1;
		_refresh_rates[0] = 0;
		_currentRefreshRate = 0;
		return;
	}

	if(!_display_hz) _currentRefreshRate = 0;
}
and modify MakeWindow:

Code: Select all

static void MakeWindow(bool full_screen)
{
	_fullscreen = full_screen;

	_wnd.double_size = _double_size && !full_screen;

	// recreate window?
	if((full_screen|_wnd.fullscreen) && _wnd.main_wnd) {
		DestroyWindow(_wnd.main_wnd);
		_wnd.main_wnd = 0;
	}

	if(full_screen)
	{
		DEVMODE settings;

		//calculte maximum refresh rate for selecting resolution
		{
			int i = GetCurRes();
			enumRefreshRates(_wnd.width_org, _wnd.height_org);

			if(_display_hz > g_uiMaxRefresh) _display_hz = 0;
		}

		memset(&settings, 0, sizeof(DEVMODE));
		settings.dmSize = sizeof(DEVMODE);

		settings.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
		settings.dmPelsWidth = _wnd.width_org;
		settings.dmPelsHeight = _wnd.height_org;

		if(_fullscreen_bpp)
		{
			settings.dmBitsPerPel = _fullscreen_bpp;
			settings.dmFields |= DM_BITSPERPEL;
		}

        if((settings.dmDisplayFrequency = _display_hz) != 0)
		{
            settings.dmFields |= DM_DISPLAYFREQUENCY;
		}

        if(!ChangeDisplaySettings(&settings, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL)
		{
			MakeWindow(false);
			return;
		}
	}
	else if(_wnd.fullscreen)
	{
		//restore display?
		ChangeDisplaySettings(NULL, 0);
	}

	{
		RECT r;
		uint style;
		int x, y, w, h;

		if((_wnd.fullscreen=full_screen) != false)
		{
			style = WS_POPUP | WS_VISIBLE;
			SetRect(&r, 0, 0, _wnd.width_org, _wnd.height_org);
		}
		else
		{
			style = WS_OVERLAPPEDWINDOW | WS_VISIBLE;
			SetRect(&r, 0, 0, _wnd.width, _wnd.height);
		}

		AdjustWindowRect(&r, style, FALSE);
		w = r.right - r.left;
		h = r.bottom - r.top;
		x = (GetSystemMetrics(SM_CXSCREEN)-w)>>1;
		y = (GetSystemMetrics(SM_CYSCREEN)-h)>>1;

		if(_wnd.main_wnd)
		{
			SetWindowPos(_wnd.main_wnd, 0, x, y, w, h, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER);
		}
		else
		{
			char Windowtitle[50] = "OpenTTD ";
			#ifdef WITH_REV_HACK
				// also show revision number/release in window title
				extern const char _openttd_revision[];
				strncat(Windowtitle, _openttd_revision, sizeof(Windowtitle)-(strlen(Windowtitle) + 1));
			#endif
			_wnd.main_wnd = CreateWindow("TTD", Windowtitle, style, x, y, w, h, 0, 0, _inst, 0);
			if (_wnd.main_wnd == NULL)
				error("CreateWindow failed");
		}
	}

	//calculte available refresh rates for selected resolution
	{
		int i = GetCurRes();
        enumRefreshRates(_resolutions[i][0], _resolutions[i][1]);
	}

	GameSizeChanged(); // invalidate all windows, force redraw
}
and add

Code: Select all

enumRefreshRates = EnumRefreshRates;
to WinMain so it would be look like

Code: Select all

int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPTSTR lpCmdLine,int nCmdShow)
{
	int argc;
	char *argv[64]; // max 64 command line arguments
	_inst = hInstance;
	
	enumRefreshRates = EnumRefreshRates;

.....
9. in english.txt lang file add this strings

Code: Select all

STR_OPTIONS_REFRESH_CBO						:{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING}
STR_OPTIONS_REFRESH_TIP						:{BLACK}Select the screen refresh to use

Done.
Big thanks for LordOfThePigs.
DaleStan
TTDPatch Developer
TTDPatch Developer
Posts: 10285
Joined: 18 Feb 2004 03:06
Contact:

Post by DaleStan »

You'll have better luck getting this integrated if you run diff on the two files/file sets, and post the .patch file instead.

diff should be available on all *nix distros, and is also available in Cygwin.
To get a good answer, ask a Smart Question. Similarly, if you want a bug fixed, write a Useful Bug Report. No TTDPatch crashlog? Then follow directions.
Projects: NFORenum (download) | PlaneSet (Website) | grfcodec (download) | grfdebug.log parser
User avatar
Celestar
Director
Director
Posts: 574
Joined: 02 Jul 2004 10:56
Contact:

Post by Celestar »

I agree with Dalestan here, if you want this applied (looks quite well on a quick first glance), you need to run "svn diff > filename.diff" and post that diff here and/or on sourceforge. None of the developers will want to copy and paste parts of the code from the forums manually.

Celestar
User avatar
dominik81
OpenTTD Developer
OpenTTD Developer
Posts: 768
Joined: 16 Aug 2003 12:55
Location: Bonn, Germany

Post by dominik81 »

Maybe our FAQ about OpenTTD development will help you to get started as well: Link
"There's a readme that comes with the source. I suggest you read it."
- Korenn
JohnRus
Engineer
Engineer
Posts: 14
Joined: 06 Dec 2004 23:04
Location: Sankt-Peterburg, Russia
Contact:

Post by JohnRus »

Ok. I am fully agree with you.

This is my patch.
JohnRus
Engineer
Engineer
Posts: 14
Joined: 06 Dec 2004 23:04
Location: Sankt-Peterburg, Russia
Contact:

Post by JohnRus »

attacment
Attachments
johnrus_13122004_2.diff
diff
(16.64 KiB) Downloaded 254 times
Post Reply

Return to “OpenTTD Development”

Who is online

Users browsing this forum: No registered users and 23 guests