From c136dd2b3268f7aa7b8088814febd77108dcef30 Mon Sep 17 00:00:00 2001 From: translators Date: Mon, 22 Feb 2021 19:01:17 +0000 Subject: [PATCH 1/6] Update: Translations from eints english (us): 78 changes by 2TallTyler polish: 1 change by yazalo --- src/lang/english_US.txt | 89 ++++++++++++++++++++++++++++++++++++----- src/lang/polish.txt | 1 + 2 files changed, 79 insertions(+), 11 deletions(-) diff --git a/src/lang/english_US.txt b/src/lang/english_US.txt index a18ee830cf..88ae9d022f 100644 --- a/src/lang/english_US.txt +++ b/src/lang/english_US.txt @@ -194,6 +194,7 @@ STR_COLOUR_DEFAULT :Default STR_UNITS_VELOCITY_IMPERIAL :{COMMA}{NBSP}mph STR_UNITS_VELOCITY_METRIC :{COMMA}{NBSP}km/h STR_UNITS_VELOCITY_SI :{COMMA}{NBSP}m/s +STR_UNITS_VELOCITY_GAMEUNITS :{DECIMAL}{NBSP}tiles/day STR_UNITS_POWER_IMPERIAL :{COMMA}{NBSP}hp STR_UNITS_POWER_METRIC :{COMMA}{NBSP}hp @@ -312,8 +313,15 @@ STR_SORT_BY_CARGO_CAPACITY :Cargo capacity STR_SORT_BY_RANGE :Range STR_SORT_BY_POPULATION :Population STR_SORT_BY_RATING :Rating +STR_SORT_BY_NUM_VEHICLES :Number of vehicles +STR_SORT_BY_TOTAL_PROFIT_LAST_YEAR :Total profit last year +STR_SORT_BY_TOTAL_PROFIT_THIS_YEAR :Total profit this year +STR_SORT_BY_AVERAGE_PROFIT_LAST_YEAR :Average profit last year +STR_SORT_BY_AVERAGE_PROFIT_THIS_YEAR :Average profit this year # Group by options for vehicle list +STR_GROUP_BY_NONE :None +STR_GROUP_BY_SHARED_ORDERS :Shared orders # Tooltips for the main toolbar STR_TOOLBAR_TOOLTIP_PAUSE_GAME :{BLACK}Pause game @@ -604,7 +612,7 @@ STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_TRANSPORT_COORDINATOR :Transport Coord STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_ROUTE_SUPERVISOR :Route Supervisor STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_DIRECTOR :Director STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_CHIEF_EXECUTIVE :Chief Executive -STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_CHAIRMAN :Chairman +STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_CHAIRMAN :Chairperson STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_PRESIDENT :President STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_TYCOON :Tycoon @@ -687,7 +695,7 @@ STR_PLAYLIST_TOOLTIP_CLICK_TO_REMOVE_TRACK :{BLACK}Click on STR_HIGHSCORE_TOP_COMPANIES_WHO_REACHED :{BIG_FONT}{BLACK}Top companies who reached {NUM} STR_HIGHSCORE_TOP_COMPANIES_NETWORK_GAME :{BIG_FONT}{BLACK}Company League Table in {NUM} STR_HIGHSCORE_POSITION :{BIG_FONT}{BLACK}{COMMA}. -STR_HIGHSCORE_PERFORMANCE_TITLE_BUSINESSMAN :Businessman +STR_HIGHSCORE_PERFORMANCE_TITLE_BUSINESSMAN :Businessperson STR_HIGHSCORE_PERFORMANCE_TITLE_ENTREPRENEUR :Entrepreneur STR_HIGHSCORE_PERFORMANCE_TITLE_INDUSTRIALIST :Industrialist STR_HIGHSCORE_PERFORMANCE_TITLE_CAPITALIST :Capitalist @@ -739,6 +747,7 @@ STR_SMALLMAP_LEGENDA_DOCK :{TINY_FONT}{BLA STR_SMALLMAP_LEGENDA_ROUGH_LAND :{TINY_FONT}{BLACK}Rough Land STR_SMALLMAP_LEGENDA_GRASS_LAND :{TINY_FONT}{BLACK}Grass Land STR_SMALLMAP_LEGENDA_BARE_LAND :{TINY_FONT}{BLACK}Bare Land +STR_SMALLMAP_LEGENDA_RAINFOREST :{TINY_FONT}{BLACK}Rainforest STR_SMALLMAP_LEGENDA_FIELDS :{TINY_FONT}{BLACK}Fields STR_SMALLMAP_LEGENDA_TREES :{TINY_FONT}{BLACK}Trees STR_SMALLMAP_LEGENDA_ROCKS :{TINY_FONT}{BLACK}Rocks @@ -770,6 +779,7 @@ STR_SMALLMAP_TOOLTIP_ENABLE_ALL_CARGOS :{BLACK}Display STR_STATUSBAR_TOOLTIP_SHOW_LAST_NEWS :{BLACK}Show last message or news report STR_STATUSBAR_COMPANY_NAME :{SILVER}- - {COMPANY} - - STR_STATUSBAR_PAUSED :{YELLOW}* * PAUSED * * +STR_STATUSBAR_PAUSED_LINK_GRAPH :{ORANGE}* * PAUSED (waiting for link graph update) * * STR_STATUSBAR_AUTOSAVE :{RED}AUTOSAVE STR_STATUSBAR_SAVING_GAME :{RED}* * SAVING GAME * * @@ -935,6 +945,8 @@ STR_GAME_OPTIONS_CURRENCY_MXN :Mexican Peso (M STR_GAME_OPTIONS_CURRENCY_NTD :New Taiwan Dollar (NTD) STR_GAME_OPTIONS_CURRENCY_CNY :Chinese Renminbi (CNY) STR_GAME_OPTIONS_CURRENCY_HKD :Hong Kong Dollar (HKD) +STR_GAME_OPTIONS_CURRENCY_INR :Indian Rupee (INR) +STR_GAME_OPTIONS_CURRENCY_IDR :Indonesian Rupiah (IDR) ############ end of currency region STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_LEFT :Drive on left @@ -991,6 +1003,7 @@ STR_GAME_OPTIONS_RESOLUTION_OTHER :other STR_GAME_OPTIONS_GUI_ZOOM_FRAME :{BLACK}Interface size STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_TOOLTIP :{BLACK}Select the interface element size to use +STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_AUTO :(auto-detect) STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_NORMAL :Normal STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_2X_ZOOM :Double size STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_4X_ZOOM :Quad size @@ -998,6 +1011,7 @@ STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_4X_ZOOM :Quad size STR_GAME_OPTIONS_FONT_ZOOM :{BLACK}Font size STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_TOOLTIP :{BLACK}Select the interface font size to use +STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_AUTO :(auto-detect) STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_NORMAL :Normal STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_2X_ZOOM :Double size STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_4X_ZOOM :Quad size @@ -1436,6 +1450,7 @@ STR_CONFIG_SETTING_PERSISTENT_BUILDINGTOOLS :Keep building t STR_CONFIG_SETTING_PERSISTENT_BUILDINGTOOLS_HELPTEXT :Keep the building tools for bridges, tunnels, etc. open after use STR_CONFIG_SETTING_EXPENSES_LAYOUT :Group expenses in company finance window: {STRING} STR_CONFIG_SETTING_EXPENSES_LAYOUT_HELPTEXT :Define the layout for the company expenses window +STR_CONFIG_SETTING_AUTO_REMOVE_SIGNALS_HELPTEXT :Automatically remove signals during track construction if the signals are in the way. Note that this can potentially lead to train crashes. STR_CONFIG_SETTING_SOUND_TICKER :News ticker: {STRING} STR_CONFIG_SETTING_SOUND_TICKER_HELPTEXT :Play sound for summarized news messages @@ -1549,6 +1564,10 @@ STR_CONFIG_SETTING_ENDING_YEAR :Scoring end yea STR_CONFIG_SETTING_ENDING_YEAR_HELPTEXT :Year the game ends for scoring purposes. At the end of this year, the company's score is recorded and the high-score screen is displayed, but the players can continue playing after that.{}If this is before the starting year, the high-score screen is never displayed. STR_CONFIG_SETTING_ENDING_YEAR_VALUE :{NUM} STR_CONFIG_SETTING_ENDING_YEAR_ZERO :Never +STR_CONFIG_SETTING_ECONOMY_TYPE_HELPTEXT :Smooth economy makes production changes more often, and in smaller steps. Frozen economy stops production changes and industry closures. This setting may have no effect if industry types are provided by a NewGRF. +STR_CONFIG_SETTING_ECONOMY_TYPE_ORIGINAL :Original +STR_CONFIG_SETTING_ECONOMY_TYPE_SMOOTH :Smooth +STR_CONFIG_SETTING_ECONOMY_TYPE_FROZEN :Frozen STR_CONFIG_SETTING_ALLOW_SHARES :Allow buying shares from other companies: {STRING} STR_CONFIG_SETTING_ALLOW_SHARES_HELPTEXT :When enabled, allow buying and selling of company shares. Shares will only be available for companies reaching a certain age STR_CONFIG_SETTING_MIN_YEARS_FOR_SHARES :Minimum company age to trade shares: {STRING} @@ -1600,6 +1619,10 @@ STR_CONFIG_SETTING_TOWN_CARGOGENMODE_BITCOUNT :Linear STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT :In-game placement of trees: {STRING} STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_HELPTEXT :Control random appearance of trees during the game. This might affect industries which rely on tree growth, for example lumber mills +STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_NO_SPREAD :Grow but don't spread {RED}(breaks lumber mill) +STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_SPREAD_RAINFOREST :Grow but only spread in rain forests +STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_SPREAD_ALL :Grow and spread everywhere +STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_NO_GROWTH_NO_SPREAD :Don't grow, don't spread {RED}(breaks lumber mill) STR_CONFIG_SETTING_TOOLBAR_POS :Position of main toolbar: {STRING} STR_CONFIG_SETTING_TOOLBAR_POS_HELPTEXT :Horizontal position of the main toolbar at the top of the screen @@ -1666,6 +1689,7 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_HELPTEXT :Whenever a spee STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_IMPERIAL :Imperial (mph) STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_METRIC :Metric (km/h) STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_SI :SI (m/s) +STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_GAMEUNITS :Game units (tiles/day) STR_CONFIG_SETTING_LOCALISATION_UNITS_POWER :Vehicle power units: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_POWER_HELPTEXT :Whenever a vehicle's power is shown in the user interface, show it in the selected units @@ -1809,6 +1833,7 @@ STR_ABANDON_SCENARIO_QUERY :{YELLOW}Are you # Cheat window STR_CHEATS :{WHITE}Cheats STR_CHEATS_TOOLTIP :{BLACK}Checkboxes indicate if you have used this cheat before +STR_CHEATS_NOTE :{BLACK}Note: any usage of these settings will be recorded by the savegame STR_CHEAT_MONEY :{LTBLUE}Increase money by {CURRENCY_LONG} STR_CHEAT_CHANGE_COMPANY :{LTBLUE}Playing as company: {ORANGE}{COMMA} STR_CHEAT_EXTRA_DYNAMITE :{LTBLUE}Magic bulldozer (remove industries, unmovable objects): {ORANGE}{STRING} @@ -1960,6 +1985,10 @@ STR_NETWORK_SERVER_LIST_JOIN_GAME :{BLACK}Join gam STR_NETWORK_SERVER_LIST_REFRESH :{BLACK}Refresh server STR_NETWORK_SERVER_LIST_REFRESH_TOOLTIP :{BLACK}Refresh the server info +STR_NETWORK_SERVER_LIST_SEARCH_SERVER_INTERNET :{BLACK}Search internet +STR_NETWORK_SERVER_LIST_SEARCH_SERVER_INTERNET_TOOLTIP :{BLACK}Search internet for public servers +STR_NETWORK_SERVER_LIST_SEARCH_SERVER_LAN :{BLACK}Search LAN +STR_NETWORK_SERVER_LIST_SEARCH_SERVER_LAN_TOOLTIP :{BLACK}Search local area network for servers STR_NETWORK_SERVER_LIST_ADD_SERVER :{BLACK}Add server STR_NETWORK_SERVER_LIST_ADD_SERVER_TOOLTIP :{BLACK}Adds a server to the list which will always be checked for running games STR_NETWORK_SERVER_LIST_START_SERVER :{BLACK}Start server @@ -2184,11 +2213,13 @@ STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_1 :Game still paus STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_2 :Game still paused ({STRING}, {STRING}) STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_3 :Game still paused ({STRING}, {STRING}, {STRING}) STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_4 :Game still paused ({STRING}, {STRING}, {STRING}, {STRING}) +STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_5 :Game still paused ({STRING}, {STRING}, {STRING}, {STRING}, {STRING}) STR_NETWORK_SERVER_MESSAGE_GAME_UNPAUSED :Game unpaused ({STRING}) STR_NETWORK_SERVER_MESSAGE_GAME_REASON_NOT_ENOUGH_PLAYERS :number of players STR_NETWORK_SERVER_MESSAGE_GAME_REASON_CONNECTING_CLIENTS :connecting clients STR_NETWORK_SERVER_MESSAGE_GAME_REASON_MANUAL :manual STR_NETWORK_SERVER_MESSAGE_GAME_REASON_GAME_SCRIPT :game script +STR_NETWORK_SERVER_MESSAGE_GAME_REASON_LINK_GRAPH :waiting for link graph update ############ End of leave-in-this-order STR_NETWORK_MESSAGE_CLIENT_LEAVING :leaving STR_NETWORK_MESSAGE_CLIENT_JOINED :*** {STRING} has joined the game @@ -2316,6 +2347,7 @@ STR_JOIN_WAYPOINT_CAPTION :{WHITE}Join way STR_JOIN_WAYPOINT_CREATE_SPLITTED_WAYPOINT :{YELLOW}Build a separate waypoint # Generic toolbar +STR_TOOLBAR_DISABLED_NO_VEHICLE_AVAILABLE :{BLACK}Disabled as currently no vehicles are available for this infrastructure # Rail construction toolbar STR_RAIL_TOOLBAR_RAILROAD_CONSTRUCTION_CAPTION :Railroad Construction @@ -2511,6 +2543,12 @@ STR_TREES_RANDOM_TYPE :{BLACK}Trees of STR_TREES_RANDOM_TYPE_TOOLTIP :{BLACK}Place trees of random type. Shift toggles building/showing cost estimate STR_TREES_RANDOM_TREES_BUTTON :{BLACK}Random Trees STR_TREES_RANDOM_TREES_TOOLTIP :{BLACK}Plant trees randomly throughout the landscape +STR_TREES_MODE_NORMAL_BUTTON :{BLACK}Normal +STR_TREES_MODE_NORMAL_TOOLTIP :{BLACK}Plant single trees by dragging over the landscape. +STR_TREES_MODE_FOREST_SM_BUTTON :{BLACK}Grove +STR_TREES_MODE_FOREST_SM_TOOLTIP :{BLACK}Plant small forests by dragging over the landscape. +STR_TREES_MODE_FOREST_LG_BUTTON :{BLACK}Forest +STR_TREES_MODE_FOREST_LG_TOOLTIP :{BLACK}Plant large forests by dragging over the landscape. # Land generation window (SE) STR_TERRAFORM_TOOLBAR_LAND_GENERATION_CAPTION :{WHITE}Land Generation @@ -2561,12 +2599,18 @@ STR_FOUND_TOWN_SELECT_LAYOUT_RANDOM :{BLACK}Random # Fund new industry window STR_FUND_INDUSTRY_CAPTION :{WHITE}Fund new industry STR_FUND_INDUSTRY_SELECTION_TOOLTIP :{BLACK}Choose the appropriate industry from this list -STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES :Many random industries +STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES :{BLACK}Create random industries STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_TOOLTIP :{BLACK}Cover the map with randomly placed industries +STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_CAPTION :{WHITE}Create random industries +STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_QUERY :{YELLOW}Are you sure you want to create many random industries? STR_FUND_INDUSTRY_INDUSTRY_BUILD_COST :{BLACK}Cost: {YELLOW}{CURRENCY_LONG} STR_FUND_INDUSTRY_PROSPECT_NEW_INDUSTRY :{BLACK}Prospect STR_FUND_INDUSTRY_BUILD_NEW_INDUSTRY :{BLACK}Build STR_FUND_INDUSTRY_FUND_NEW_INDUSTRY :{BLACK}Fund +STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES :{BLACK}Remove all industries +STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES_TOOLTIP :{BLACK}Remove all industries currently present on the map +STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES_CAPTION :{WHITE}Remove all industries +STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES_QUERY :{YELLOW}Are you sure you want to remove all industries? # Industry cargoes window STR_INDUSTRY_CARGOES_INDUSTRY_CAPTION :{WHITE}Industry chain for {STRING} industry @@ -2587,6 +2631,7 @@ STR_INDUSTRY_CARGOES_SELECT_INDUSTRY_TOOLTIP :{BLACK}Select t # Land area window STR_LAND_AREA_INFORMATION_CAPTION :{WHITE}Land Area Information +STR_LAND_AREA_INFORMATION_LOCATION_TOOLTIP :{BLACK}Center the main view on tile location. Ctrl+Click opens a new viewport on tile location STR_LAND_AREA_INFORMATION_COST_TO_CLEAR_N_A :{BLACK}Cost to clear: {LTBLUE}N/A STR_LAND_AREA_INFORMATION_COST_TO_CLEAR :{BLACK}Cost to clear: {RED}{CURRENCY_LONG} STR_LAND_AREA_INFORMATION_REVENUE_WHEN_CLEARED :{BLACK}Revenue when cleared: {LTBLUE}{CURRENCY_LONG} @@ -3056,6 +3101,7 @@ STR_SIGN_LIST_MATCH_CASE_TOOLTIP :{BLACK}Toggle m # Sign window STR_EDIT_SIGN_CAPTION :{WHITE}Edit sign text +STR_EDIT_SIGN_LOCATION_TOOLTIP :{BLACK}Center the main view on sign location. Ctrl+Click opens a new viewport on sign location STR_EDIT_SIGN_NEXT_SIGN_TOOLTIP :{BLACK}Go to next sign STR_EDIT_SIGN_PREVIOUS_SIGN_TOOLTIP :{BLACK}Go to previous sign @@ -3139,10 +3185,10 @@ STR_GOALS_COMPANY_TITLE :{BLACK}Company STR_GOALS_TOOLTIP_CLICK_ON_SERVICE_TO_CENTER :{BLACK}Click on goal to center main view on industry/town/tile. Ctrl+Click opens a new viewport on industry/town/tile location # Goal question window -STR_GOAL_QUESTION_CAPTION_QUESTION :Question -STR_GOAL_QUESTION_CAPTION_INFORMATION :Information -STR_GOAL_QUESTION_CAPTION_WARNING :Warning -STR_GOAL_QUESTION_CAPTION_ERROR :Error +STR_GOAL_QUESTION_CAPTION_QUESTION :{BLACK}Question +STR_GOAL_QUESTION_CAPTION_INFORMATION :{BLACK}Information +STR_GOAL_QUESTION_CAPTION_WARNING :{BLACK}Warning +STR_GOAL_QUESTION_CAPTION_ERROR :{YELLOW}Error ############ Start of Goal Question button list STR_GOAL_QUESTION_BUTTON_CANCEL :Cancel @@ -3332,6 +3378,8 @@ STR_COMPANY_VIEW_RELOCATE_HQ :{BLACK}Relocate STR_COMPANY_VIEW_RELOCATE_COMPANY_HEADQUARTERS :{BLACK}Rebuild company headquarters elsewhere for 1% cost of company value. Shift+Click shows estimated cost without relocating HQ STR_COMPANY_VIEW_INFRASTRUCTURE_BUTTON :{BLACK}Details STR_COMPANY_VIEW_INFRASTRUCTURE_TOOLTIP :{BLACK}View detailed infrastructure counts +STR_COMPANY_VIEW_GIVE_MONEY_BUTTON :{BLACK}Give money +STR_COMPANY_VIEW_GIVE_MONEY_TOOLTIP :{BLACK}Give money to this company STR_COMPANY_VIEW_NEW_FACE_BUTTON :{BLACK}New Face STR_COMPANY_VIEW_NEW_FACE_TOOLTIP :{BLACK}Select new face for president @@ -3349,6 +3397,7 @@ STR_COMPANY_VIEW_SELL_SHARE_TOOLTIP :{BLACK}Sell 25% STR_COMPANY_VIEW_COMPANY_NAME_QUERY_CAPTION :Company Name STR_COMPANY_VIEW_PRESIDENT_S_NAME_QUERY_CAPTION :President's Name +STR_COMPANY_VIEW_GIVE_MONEY_QUERY_CAPTION :Enter the amount of money you want to give STR_BUY_COMPANY_MESSAGE :{WHITE}We are looking for a transport company to take-over our company.{}{}Do you want to purchase {COMPANY} for {CURRENCY_LONG}? @@ -3370,6 +3419,10 @@ STR_INDUSTRY_DIRECTORY_CAPTION :{WHITE}Industri STR_INDUSTRY_DIRECTORY_NONE :{ORANGE}- None - STR_INDUSTRY_DIRECTORY_ITEM_NOPROD :{ORANGE}{INDUSTRY} STR_INDUSTRY_DIRECTORY_LIST_CAPTION :{BLACK}Industry names - click on name to center main view on industry. Ctrl+Click opens a new viewport on industry location +STR_INDUSTRY_DIRECTORY_ACCEPTED_CARGO_FILTER :{BLACK}Accepted cargo: {SILVER}{STRING} +STR_INDUSTRY_DIRECTORY_PRODUCED_CARGO_FILTER :{BLACK}Produced cargo: {SILVER}{STRING} +STR_INDUSTRY_DIRECTORY_FILTER_ALL_TYPES :All cargo types +STR_INDUSTRY_DIRECTORY_FILTER_NONE :None # Industry view STR_INDUSTRY_VIEW_CAPTION :{WHITE}{INDUSTRY} @@ -3700,6 +3753,10 @@ STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Make aut # Vehicle view STR_VEHICLE_VIEW_CAPTION :{WHITE}{VEHICLE} +STR_VEHICLE_VIEW_TRAIN_CENTER_TOOLTIP :{BLACK}Center main view on train's location. Double click will follow train in main view. Ctrl+Click opens a new viewport on train's location +STR_VEHICLE_VIEW_ROAD_VEHICLE_CENTER_TOOLTIP :{BLACK}Center main view on vehicle's location. Double click will follow vehicle in main view. Ctrl+Click opens a new viewport on vehicle's location +STR_VEHICLE_VIEW_SHIP_CENTER_TOOLTIP :{BLACK}Center main view on ship's location. Double click will follow ship in main view. Ctrl+Click opens a new viewport on ship's location +STR_VEHICLE_VIEW_AIRCRAFT_CENTER_TOOLTIP :{BLACK}Center main view on aircraft's location. Double click will follow aircraft in main view. Ctrl+Click opens a new viewport on aircraft's location STR_VEHICLE_VIEW_TRAIN_SEND_TO_DEPOT_TOOLTIP :{BLACK}Send train to depot. Ctrl+Click will only service STR_VEHICLE_VIEW_ROAD_VEHICLE_SEND_TO_DEPOT_TOOLTIP :{BLACK}Send vehicle to depot. Ctrl+Click will only service @@ -3731,7 +3788,12 @@ STR_VEHICLE_VIEW_ROAD_VEHICLE_SHOW_DETAILS_TOOLTIP :{BLACK}Show roa STR_VEHICLE_VIEW_SHIP_SHOW_DETAILS_TOOLTIP :{BLACK}Show ship details STR_VEHICLE_VIEW_AIRCRAFT_SHOW_DETAILS_TOOLTIP :{BLACK}Show aircraft details +STR_VEHICLE_VIEW_TRAIN_STATUS_START_STOP_TOOLTIP :{BLACK}Current train action - click to stop/start train +STR_VEHICLE_VIEW_ROAD_VEHICLE_STATUS_START_STOP_TOOLTIP :{BLACK}Current vehicle action - click to stop/start vehicle +STR_VEHICLE_VIEW_SHIP_STATE_STATUS_STOP_TOOLTIP :{BLACK}Current ship action - click to stop/start ship +STR_VEHICLE_VIEW_AIRCRAFT_STATUS_START_STOP_TOOLTIP :{BLACK}Current aircraft action - click to stop/start aircraft +STR_VEHICLE_VIEW_ORDER_LOCATION_TOOLTIP :{BLACK}Center main view on order destination. Ctrl+Click opens a new viewport on the order destination's location # Messages in the start stop button in the vehicle view STR_VEHICLE_STATUS_LOADING_UNLOADING :{LTBLUE}Loading / Unloading @@ -4203,6 +4265,7 @@ STR_GAME_SAVELOAD_ERROR_TOO_NEW_SAVEGAME :Savegame is mad STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE :File not readable STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE :File not writable STR_GAME_SAVELOAD_ERROR_DATA_INTEGRITY_CHECK_FAILED :Data integrity check failed +STR_GAME_SAVELOAD_ERROR_PATCHPACK :Savegame is made with a modified version STR_GAME_SAVELOAD_NOT_AVAILABLE : STR_WARNING_LOADGAME_REMOVED_TRAMS :{WHITE}Game was saved in version without streetcar support. All streetcars have been removed @@ -4283,6 +4346,7 @@ STR_ERROR_LOAN_ALREADY_REPAYED :{WHITE}... no l STR_ERROR_CURRENCY_REQUIRED :{WHITE}... {CURRENCY_LONG} required STR_ERROR_CAN_T_REPAY_LOAN :{WHITE}Can't repay loan... STR_ERROR_INSUFFICIENT_FUNDS :{WHITE}Can't give away money that is loaned from the bank... +STR_ERROR_CAN_T_GIVE_MONEY :{WHITE}Can't give away money to this company... STR_ERROR_CAN_T_BUY_COMPANY :{WHITE}Can't buy company... STR_ERROR_CAN_T_BUILD_COMPANY_HEADQUARTERS :{WHITE}Can't build company headquarters... STR_ERROR_CAN_T_BUY_25_SHARE_IN_THIS :{WHITE}Can't buy 25% share in this company... @@ -4409,6 +4473,8 @@ STR_ERROR_DEPOT_WRONG_DEPOT_TYPE :Wrong depot typ STR_ERROR_TRAIN_TOO_LONG_AFTER_REPLACEMENT :{WHITE}{VEHICLE} is too long after replacement STR_ERROR_AUTOREPLACE_NOTHING_TO_DO :{WHITE}No autoreplace/renew rules applied STR_ERROR_AUTOREPLACE_MONEY_LIMIT :(money limit) +STR_ERROR_AUTOREPLACE_INCOMPATIBLE_CARGO :{WHITE}New vehicle can't carry {STRING} +STR_ERROR_AUTOREPLACE_INCOMPATIBLE_REFIT :{WHITE}New vehicle can't do refit in order {NUM} # Rail construction errors STR_ERROR_IMPOSSIBLE_TRACK_COMBINATION :{WHITE}Impossible track combination @@ -4690,10 +4756,10 @@ STR_INDUSTRY_NAME_SUGAR_MINE :Sugar Mine ##id 0x6000 STR_SV_EMPTY : STR_SV_UNNAMED :Unnamed -STR_SV_TRAIN_NAME :Train {COMMA} -STR_SV_ROAD_VEHICLE_NAME :Road Vehicle {COMMA} -STR_SV_SHIP_NAME :Ship {COMMA} -STR_SV_AIRCRAFT_NAME :Aircraft {COMMA} +STR_SV_TRAIN_NAME :Train #{COMMA} +STR_SV_ROAD_VEHICLE_NAME :Road Vehicle #{COMMA} +STR_SV_SHIP_NAME :Ship #{COMMA} +STR_SV_AIRCRAFT_NAME :Aircraft #{COMMA} STR_SV_STNAME :{STRING} STR_SV_STNAME_NORTH :{STRING} North @@ -4995,6 +5061,7 @@ STR_FORMAT_BUOY_NAME :{TOWN} Buoy STR_FORMAT_BUOY_NAME_SERIAL :{TOWN} Buoy #{COMMA} STR_FORMAT_COMPANY_NUM :(Company {COMMA}) STR_FORMAT_GROUP_NAME :Group {COMMA} +STR_FORMAT_GROUP_VEHICLE_NAME :{GROUP} #{COMMA} STR_FORMAT_INDUSTRY_NAME :{TOWN} {STRING} STR_FORMAT_WAYPOINT_NAME :{TOWN} Waypoint STR_FORMAT_WAYPOINT_NAME_SERIAL :{TOWN} Waypoint #{COMMA} diff --git a/src/lang/polish.txt b/src/lang/polish.txt index 5b797a5e5c..0b422159db 100644 --- a/src/lang/polish.txt +++ b/src/lang/polish.txt @@ -1326,6 +1326,7 @@ STR_GAME_OPTIONS_CURRENCY_NTD :Nowy dolar tajw STR_GAME_OPTIONS_CURRENCY_CNY :Juan chiński (CNY) STR_GAME_OPTIONS_CURRENCY_HKD :Dolar hongkoński (HKD) STR_GAME_OPTIONS_CURRENCY_INR :Rupia Indyjska (INR) +STR_GAME_OPTIONS_CURRENCY_IDR :Rupia Indonezyjska (IDR) ############ end of currency region STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_LEFT :Jazda po lewej From 78d96dad2a9ba82b0f5a9777349f1d40087be6e1 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Mon, 22 Feb 2021 21:17:55 +0100 Subject: [PATCH 2/6] Fix #6319: [Win32] don't use clipping; draw whole screen every frame (#8726) When we clip the region that is only been redrawn, something weird happens on Windows. When pushing 60 frames per second on a 60Hz monitor, it appears that the clipped region is often shown of another frame, instead of the current. Examples of this are: - pause the game, move your mouse to the left, and at the right speed it totally disappears. - fast aircrafts seem to be in several places at once, weirdly lagging behind. - in title screen, moving your mouse gives you the idea it is jumping places, instead of smooth movements. In the end, if you do nothing, everything is correct, so it is eventually consistent. Just when we are firing many BitBlt in a clipped region, the in-between is not. What goes wrong exactly, I honestly do not know. On every frame that we push to the DC is a mouse painted, but visually it sometimes appears like it is not. Recording with external software shows it really is there. It is also not our eyes playing tricks on us, as the first example makes it really clear the mouse pointer really is not painted. And to be clear, with the mouse this is easiest reproduceable, as high-speed objects are influences by this most. But this happens for all movement that redraws small regions. Either way, not using clipped regions resolves the issue completely, and there appears to be little to no penalty (I failed to measure any impact of drawing the full screen). So better have a good game than fast code, I guess? --- src/video/win32_v.cpp | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/src/video/win32_v.cpp b/src/video/win32_v.cpp index 980bd7292a..ce390835ca 100644 --- a/src/video/win32_v.cpp +++ b/src/video/win32_v.cpp @@ -334,19 +334,9 @@ void VideoDriver_Win32::Paint() if (IsEmptyRect(_dirty_rect)) return; - /* Convert update region from logical to device coordinates. */ - POINT pt = {0, 0}; - ClientToScreen(_wnd.main_wnd, &pt); - - RECT r = { _dirty_rect.left, _dirty_rect.top, _dirty_rect.right, _dirty_rect.bottom }; - OffsetRect(&r, pt.x, pt.y); - - /* Create a device context that is clipped to the region we need to draw. - * GetDCEx 'consumes' the update region, so we may not destroy it ourself. */ - HRGN rgn = CreateRectRgnIndirect(&r); - HDC dc = GetDCEx(_wnd.main_wnd, rgn, DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN | DCX_INTERSECTRGN); - + HDC dc = GetDC(_wnd.main_wnd); HDC dc2 = CreateCompatibleDC(dc); + HBITMAP old_bmp = (HBITMAP)SelectObject(dc2, _wnd.dib_sect); HPALETTE old_palette = SelectPalette(dc, _wnd.gdi_palette, FALSE); From 59e0d9618b41669335bd5a45183b9ff7d95bfd33 Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Sat, 16 Jan 2021 16:42:59 +0100 Subject: [PATCH 3/6] Codechange: [Win32] Split the video driver into a base class and a GDI backend class. --- src/video/win32_v.cpp | 148 ++++++++++++++++++++++-------------------- src/video/win32_v.h | 37 ++++++----- 2 files changed, 97 insertions(+), 88 deletions(-) diff --git a/src/video/win32_v.cpp b/src/video/win32_v.cpp index ce390835ca..efef2182f4 100644 --- a/src/video/win32_v.cpp +++ b/src/video/win32_v.cpp @@ -108,7 +108,7 @@ static void UpdatePalette(HDC dc, uint start, uint count) SetDIBColorTable(dc, start, count, rgb); } -bool VideoDriver_Win32::ClaimMousePointer() +bool VideoDriver_Win32Base::ClaimMousePointer() { MyShowCursor(false, true); return true; @@ -231,7 +231,7 @@ int RedrawScreenDebug() * @param full_screen Whether to make a full screen window or not. * @return True if the window could be created. */ -bool VideoDriver_Win32::MakeWindow(bool full_screen) +bool VideoDriver_Win32Base::MakeWindow(bool full_screen) { /* full_screen is whether the new window should be fullscreen, * _wnd.fullscreen is whether the current window is. */ @@ -315,7 +315,7 @@ bool VideoDriver_Win32::MakeWindow(bool full_screen) char window_title[64]; seprintf(window_title, lastof(window_title), "OpenTTD %s", _openttd_revision); - _wnd.main_wnd = CreateWindow(_T("OTTD"), MB_TO_WIDE(window_title), style, x, y, w, h, 0, 0, GetModuleHandle(nullptr), 0); + _wnd.main_wnd = CreateWindow(_T("OTTD"), MB_TO_WIDE(window_title), style, x, y, w, h, 0, 0, GetModuleHandle(nullptr), this); if (_wnd.main_wnd == nullptr) usererror("CreateWindow failed"); ShowWindow(_wnd.main_wnd, showstyle); } @@ -328,7 +328,7 @@ bool VideoDriver_Win32::MakeWindow(bool full_screen) } /** Do palette animation and blit to the window. */ -void VideoDriver_Win32::Paint() +void VideoDriver_Win32Base::Paint() { PerformanceMeasurer framerate(PFE_VIDEO); @@ -371,7 +371,7 @@ void VideoDriver_Win32::Paint() _dirty_rect = {}; } -void VideoDriver_Win32::PaintThread() +void VideoDriver_Win32Base::PaintThread() { /* First tell the main thread we're started */ std::unique_lock lock(*_draw_mutex); @@ -390,7 +390,7 @@ void VideoDriver_Win32::PaintThread() } } -/* static */ void VideoDriver_Win32::PaintThreadThunk(VideoDriver_Win32 *drv) +/* static */ void VideoDriver_Win32Base::PaintThreadThunk(VideoDriver_Win32Base *drv) { drv->PaintThread(); } @@ -594,13 +594,16 @@ static void CancelIMEComposition(HWND hwnd) HandleTextInput(nullptr, true); } -static LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { static uint32 keycode = 0; static bool console = false; + VideoDriver_Win32Base *video_driver = (VideoDriver_Win32Base *)GetWindowLongPtr(hwnd, GWLP_USERDATA); + switch (msg) { case WM_CREATE: + SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)((LPCREATESTRUCT)lParam)->lpCreateParams); _cursor.in_window = false; // Win32 has mouse tracking. SetCompositionPos(hwnd); _imm_props = ImmGetProperty(GetKeyboardLayout(0), IGP_PROPERTY); @@ -609,7 +612,7 @@ static LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lP case WM_PAINT: { RECT r; GetUpdateRect(hwnd, &r, FALSE); - static_cast(VideoDriver::GetInstance())->MakeDirty(r.left, r.top, r.right - r.left, r.bottom - r.top); + video_driver->MakeDirty(r.left, r.top, r.right - r.left, r.bottom - r.top); ValidateRect(hwnd, nullptr); return 0; @@ -627,7 +630,7 @@ static LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lP SelectPalette(hDC, hOldPalette, TRUE); ReleaseDC(hwnd, hDC); if (nChanged != 0) { - static_cast(VideoDriver::GetInstance())->MakeDirty(0, 0, _screen.width, _screen.height); + video_driver->MakeDirty(0, 0, _screen.width, _screen.height); } return 0; } @@ -937,7 +940,7 @@ static LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lP if (active && minimized) { /* Restore the game window */ ShowWindow(hwnd, SW_RESTORE); - static_cast(VideoDriver::GetInstance())->MakeWindow(true); + video_driver->MakeWindow(true); } else if (!active && !minimized) { /* Minimise the window and restore desktop */ ShowWindow(hwnd, SW_MINIMIZE); @@ -1053,55 +1056,13 @@ static void FindResolutions() SortResolutions(); } -static FVideoDriver_Win32 iFVideoDriver_Win32; - -const char *VideoDriver_Win32::Start(const StringList &parm) -{ - if (BlitterFactory::GetCurrentBlitter()->GetScreenDepth() == 0) return "Only real blitters supported"; - - this->UpdateAutoResolution(); - - memset(&_wnd, 0, sizeof(_wnd)); - - RegisterWndClass(); - - MakePalette(); - - FindResolutions(); - - DEBUG(driver, 2, "Resolution for display: %ux%u", _cur_resolution.width, _cur_resolution.height); - - /* fullscreen uses those */ - _wnd.width_org = _cur_resolution.width; - _wnd.height_org = _cur_resolution.height; - - AllocateDibSection(_cur_resolution.width, _cur_resolution.height); - this->MakeWindow(_fullscreen); - - MarkWholeScreenDirty(); - - _draw_threaded = !GetDriverParamBool(parm, "no_threads") && !GetDriverParamBool(parm, "no_thread") && std::thread::hardware_concurrency() > 1; - - return nullptr; -} - -void VideoDriver_Win32::Stop() -{ - DeleteObject(_wnd.gdi_palette); - DeleteObject(_wnd.dib_sect); - DestroyWindow(_wnd.main_wnd); - - if (_wnd.fullscreen) ChangeDisplaySettings(nullptr, 0); - MyShowCursor(true); -} - -void VideoDriver_Win32::MakeDirty(int left, int top, int width, int height) +void VideoDriver_Win32Base::MakeDirty(int left, int top, int width, int height) { Rect r = {left, top, left + width, top + height}; _dirty_rect = BoundingRect(_dirty_rect, r); } -void VideoDriver_Win32::CheckPaletteAnim() +void VideoDriver_Win32Base::CheckPaletteAnim() { if (_cur_palette.count_dirty == 0) return; @@ -1109,7 +1070,7 @@ void VideoDriver_Win32::CheckPaletteAnim() this->MakeDirty(0, 0, _screen.width, _screen.height); } -void VideoDriver_Win32::InputLoop() +void VideoDriver_Win32Base::InputLoop() { bool old_ctrl_pressed = _ctrl_pressed; @@ -1143,7 +1104,7 @@ void VideoDriver_Win32::InputLoop() if (old_ctrl_pressed != _ctrl_pressed) HandleCtrlChanged(); } -void VideoDriver_Win32::MainLoop() +void VideoDriver_Win32Base::MainLoop() { MSG mesg; @@ -1163,7 +1124,7 @@ void VideoDriver_Win32::MainLoop() this->draw_lock = std::unique_lock(*_draw_mutex); _draw_continue = true; - _draw_threaded = StartNewThread(&draw_thread, "ottd:draw-win32", &VideoDriver_Win32::PaintThreadThunk, this); + _draw_threaded = StartNewThread(&draw_thread, "ottd:draw-win32", &VideoDriver_Win32Base::PaintThreadThunk, this); /* Free the mutex if we won't be able to use it. */ if (!_draw_threaded) { @@ -1222,7 +1183,7 @@ void VideoDriver_Win32::MainLoop() } } -bool VideoDriver_Win32::ChangeResolution(int w, int h) +bool VideoDriver_Win32Base::ChangeResolution(int w, int h) { std::unique_lock lock; if (_draw_mutex != nullptr) lock = std::unique_lock(*_draw_mutex); @@ -1235,7 +1196,7 @@ bool VideoDriver_Win32::ChangeResolution(int w, int h) return this->MakeWindow(_fullscreen); // _wnd.fullscreen screws up ingame resolution switching } -bool VideoDriver_Win32::ToggleFullscreen(bool full_screen) +bool VideoDriver_Win32Base::ToggleFullscreen(bool full_screen) { std::unique_lock lock; if (_draw_mutex != nullptr) lock = std::unique_lock(*_draw_mutex); @@ -1243,23 +1204,17 @@ bool VideoDriver_Win32::ToggleFullscreen(bool full_screen) return this->MakeWindow(full_screen); } -bool VideoDriver_Win32::AfterBlitterChange() -{ - assert(BlitterFactory::GetCurrentBlitter()->GetScreenDepth() != 0); - return AllocateDibSection(_screen.width, _screen.height, true) && this->MakeWindow(_fullscreen); -} - -void VideoDriver_Win32::AcquireBlitterLock() +void VideoDriver_Win32Base::AcquireBlitterLock() { if (_draw_mutex != nullptr) _draw_mutex->lock(); } -void VideoDriver_Win32::ReleaseBlitterLock() +void VideoDriver_Win32Base::ReleaseBlitterLock() { if (_draw_mutex != nullptr) _draw_mutex->unlock(); } -void VideoDriver_Win32::EditBoxLostFocus() +void VideoDriver_Win32Base::EditBoxLostFocus() { std::unique_lock lock; if (_draw_mutex != nullptr) lock = std::unique_lock(*_draw_mutex); @@ -1269,12 +1224,12 @@ void VideoDriver_Win32::EditBoxLostFocus() SetCandidatePos(_wnd.main_wnd); } -Dimension VideoDriver_Win32::GetScreenSize() const +Dimension VideoDriver_Win32Base::GetScreenSize() const { return { static_cast(GetSystemMetrics(SM_CXSCREEN)), static_cast(GetSystemMetrics(SM_CYSCREEN)) }; } -float VideoDriver_Win32::GetDPIScale() +float VideoDriver_Win32Base::GetDPIScale() { typedef UINT (WINAPI *PFNGETDPIFORWINDOW)(HWND hwnd); typedef UINT (WINAPI *PFNGETDPIFORSYSTEM)(VOID); @@ -1314,13 +1269,62 @@ float VideoDriver_Win32::GetDPIScale() return cur_dpi > 0 ? cur_dpi / 96.0f : 1.0f; // Default Windows DPI value is 96. } -bool VideoDriver_Win32::LockVideoBuffer() +bool VideoDriver_Win32Base::LockVideoBuffer() { if (_draw_threaded) this->draw_lock.lock(); return true; } -void VideoDriver_Win32::UnlockVideoBuffer() +void VideoDriver_Win32Base::UnlockVideoBuffer() { if (_draw_threaded) this->draw_lock.unlock(); } + + +static FVideoDriver_Win32GDI iFVideoDriver_Win32GDI; + +const char *VideoDriver_Win32GDI::Start(const StringList ¶m) +{ + if (BlitterFactory::GetCurrentBlitter()->GetScreenDepth() == 0) return "Only real blitters supported"; + + this->UpdateAutoResolution(); + + memset(&_wnd, 0, sizeof(_wnd)); + + RegisterWndClass(); + + MakePalette(); + + FindResolutions(); + + DEBUG(driver, 2, "Resolution for display: %ux%u", _cur_resolution.width, _cur_resolution.height); + + /* fullscreen uses those */ + _wnd.width_org = _cur_resolution.width; + _wnd.height_org = _cur_resolution.height; + + AllocateDibSection(_cur_resolution.width, _cur_resolution.height); + this->MakeWindow(_fullscreen); + + MarkWholeScreenDirty(); + + _draw_threaded = !GetDriverParam(param, "no_threads") && !GetDriverParam(param, "no_thread") && std::thread::hardware_concurrency() > 1; + + return nullptr; +} + +void VideoDriver_Win32GDI::Stop() +{ + DeleteObject(_wnd.gdi_palette); + DeleteObject(_wnd.dib_sect); + DestroyWindow(_wnd.main_wnd); + + if (_wnd.fullscreen) ChangeDisplaySettings(nullptr, 0); + MyShowCursor(true); +} + +bool VideoDriver_Win32GDI::AfterBlitterChange() +{ + assert(BlitterFactory::GetCurrentBlitter()->GetScreenDepth() != 0); + return AllocateDibSection(_screen.width, _screen.height, true) && this->MakeWindow(_fullscreen); +} diff --git a/src/video/win32_v.h b/src/video/win32_v.h index 6954770855..6834f66ffb 100644 --- a/src/video/win32_v.h +++ b/src/video/win32_v.h @@ -12,13 +12,9 @@ #include "video_driver.hpp" -/** The video driver for windows. */ -class VideoDriver_Win32 : public VideoDriver { +/** Base class for Windows video drivers. */ +class VideoDriver_Win32Base : public VideoDriver { public: - const char *Start(const StringList ¶m) override; - - void Stop() override; - void MakeDirty(int left, int top, int width, int height) override; void MainLoop() override; @@ -27,8 +23,6 @@ public: bool ToggleFullscreen(bool fullscreen) override; - bool AfterBlitterChange() override; - void AcquireBlitterLock() override; void ReleaseBlitterLock() override; @@ -37,10 +31,6 @@ public: void EditBoxLostFocus() override; - const char *GetName() const override { return "win32"; } - - bool MakeWindow(bool full_screen); - protected: Dimension GetScreenSize() const override; float GetDPIScale() override; @@ -51,17 +41,32 @@ protected: void PaintThread() override; void CheckPaletteAnim() override; + bool MakeWindow(bool full_screen); + private: std::unique_lock draw_lock; - static void PaintThreadThunk(VideoDriver_Win32 *drv); + static void PaintThreadThunk(VideoDriver_Win32Base *drv); + + friend LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); +}; +/** The GDI video driver for windows. */ +class VideoDriver_Win32GDI : public VideoDriver_Win32Base { +public: + const char *Start(const StringList ¶m) override; + + void Stop() override; + + bool AfterBlitterChange() override; + + const char *GetName() const override { return "win32"; } }; /** The factory for Windows' video driver. */ -class FVideoDriver_Win32 : public DriverFactoryBase { +class FVideoDriver_Win32GDI : public DriverFactoryBase { public: - FVideoDriver_Win32() : DriverFactoryBase(Driver::DT_VIDEO, 10, "win32", "Win32 GDI Video Driver") {} - Driver *CreateInstance() const override { return new VideoDriver_Win32(); } + FVideoDriver_Win32GDI() : DriverFactoryBase(Driver::DT_VIDEO, 10, "win32", "Win32 GDI Video Driver") {} + Driver *CreateInstance() const override { return new VideoDriver_Win32GDI(); } }; #endif /* VIDEO_WIN32_H */ From 8b90d4abe02ee7927ed3e98ba1846e363b7a5bbd Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Sat, 16 Jan 2021 16:58:48 +0100 Subject: [PATCH 4/6] Codechange: [Win32] Move GDI specific drawing code into the GDI video driver class. --- src/video/win32_v.cpp | 259 +++++++++++++++++++++--------------------- src/video/win32_v.h | 16 ++- 2 files changed, 142 insertions(+), 133 deletions(-) diff --git a/src/video/win32_v.cpp b/src/video/win32_v.cpp index efef2182f4..73c01dea11 100644 --- a/src/video/win32_v.cpp +++ b/src/video/win32_v.cpp @@ -182,23 +182,6 @@ static uint MapWindowsKey(uint sym) return key; } -static bool AllocateDibSection(int w, int h, bool force = false); - -static void ClientSizeChanged(int w, int h) -{ - /* allocate new dib section of the new size */ - if (AllocateDibSection(w, h)) { - /* mark all palette colours dirty */ - _cur_palette.first_dirty = 0; - _cur_palette.count_dirty = 256; - _local_palette = _cur_palette; - - BlitterFactory::GetCurrentBlitter()->PostResize(); - - GameSizeChanged(); - } -} - #ifdef _DEBUG /* Keep this function here.. * It allows you to redraw the screen from within the MSVC debugger */ @@ -327,69 +310,6 @@ bool VideoDriver_Win32Base::MakeWindow(bool full_screen) return true; // the request succeeded } -/** Do palette animation and blit to the window. */ -void VideoDriver_Win32Base::Paint() -{ - PerformanceMeasurer framerate(PFE_VIDEO); - - if (IsEmptyRect(_dirty_rect)) return; - - HDC dc = GetDC(_wnd.main_wnd); - HDC dc2 = CreateCompatibleDC(dc); - - HBITMAP old_bmp = (HBITMAP)SelectObject(dc2, _wnd.dib_sect); - HPALETTE old_palette = SelectPalette(dc, _wnd.gdi_palette, FALSE); - - if (_cur_palette.count_dirty != 0) { - Blitter *blitter = BlitterFactory::GetCurrentBlitter(); - - switch (blitter->UsePaletteAnimation()) { - case Blitter::PALETTE_ANIMATION_VIDEO_BACKEND: - UpdatePalette(dc2, _local_palette.first_dirty, _local_palette.count_dirty); - break; - - case Blitter::PALETTE_ANIMATION_BLITTER: - blitter->PaletteAnimate(_local_palette); - break; - - case Blitter::PALETTE_ANIMATION_NONE: - break; - - default: - NOT_REACHED(); - } - _cur_palette.count_dirty = 0; - } - - BitBlt(dc, 0, 0, _wnd.width, _wnd.height, dc2, 0, 0, SRCCOPY); - SelectPalette(dc, old_palette, TRUE); - SelectObject(dc2, old_bmp); - DeleteDC(dc2); - - ReleaseDC(_wnd.main_wnd, dc); - - _dirty_rect = {}; -} - -void VideoDriver_Win32Base::PaintThread() -{ - /* First tell the main thread we're started */ - std::unique_lock lock(*_draw_mutex); - _draw_signal->notify_one(); - - /* Now wait for the first thing to draw! */ - _draw_signal->wait(*_draw_mutex); - - while (_draw_continue) { - this->Paint(); - - /* Flush GDI buffer to ensure drawing here doesn't conflict with any GDI usage in the main WndProc. */ - GdiFlush(); - - _draw_signal->wait(*_draw_mutex); - } -} - /* static */ void VideoDriver_Win32Base::PaintThreadThunk(VideoDriver_Win32Base *drv) { drv->PaintThread(); @@ -622,18 +542,9 @@ LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) if ((HWND)wParam == hwnd) return 0; FALLTHROUGH; - case WM_QUERYNEWPALETTE: { - HDC hDC = GetWindowDC(hwnd); - HPALETTE hOldPalette = SelectPalette(hDC, _wnd.gdi_palette, FALSE); - UINT nChanged = RealizePalette(hDC); - - SelectPalette(hDC, hOldPalette, TRUE); - ReleaseDC(hwnd, hDC); - if (nChanged != 0) { - video_driver->MakeDirty(0, 0, _screen.width, _screen.height); - } + case WM_QUERYNEWPALETTE: + video_driver->PaletteChanged(hwnd); return 0; - } case WM_CLOSE: HandleExitGameRequest(); @@ -839,7 +750,7 @@ LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) * switched to fullscreen from a maximized state */ _window_maximize = (wParam == SIZE_MAXIMIZED || (_window_maximize && _fullscreen)); if (_window_maximize || _fullscreen) _bck_resolution = _cur_resolution; - ClientSizeChanged(LOWORD(lParam), HIWORD(lParam)); + video_driver->ClientSizeChanged(LOWORD(lParam), HIWORD(lParam)); } return 0; @@ -978,43 +889,6 @@ static void RegisterWndClass() if (!RegisterClass(&wnd)) usererror("RegisterClass failed"); } -static bool AllocateDibSection(int w, int h, bool force) -{ - BITMAPINFO *bi; - HDC dc; - uint bpp = BlitterFactory::GetCurrentBlitter()->GetScreenDepth(); - - w = std::max(w, 64); - h = std::max(h, 64); - - if (!force && w == _screen.width && h == _screen.height) return false; - - bi = (BITMAPINFO*)alloca(sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256); - memset(bi, 0, sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256); - bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - - bi->bmiHeader.biWidth = _wnd.width = w; - bi->bmiHeader.biHeight = -(_wnd.height = h); - - bi->bmiHeader.biPlanes = 1; - bi->bmiHeader.biBitCount = bpp; - bi->bmiHeader.biCompression = BI_RGB; - - if (_wnd.dib_sect) DeleteObject(_wnd.dib_sect); - - dc = GetDC(0); - _wnd.dib_sect = CreateDIBSection(dc, bi, DIB_RGB_COLORS, (VOID**)&_wnd.buffer_bits, nullptr, 0); - if (_wnd.dib_sect == nullptr) usererror("CreateDIBSection failed"); - ReleaseDC(0, dc); - - _screen.width = w; - _screen.pitch = (bpp == 8) ? Align(w, 4) : w; - _screen.height = h; - _screen.dst_ptr = _wnd.buffer_bits; - - return true; -} - static const Dimension default_resolutions[] = { { 640, 480 }, { 800, 600 }, @@ -1183,6 +1057,21 @@ void VideoDriver_Win32Base::MainLoop() } } +void VideoDriver_Win32Base::ClientSizeChanged(int w, int h) +{ + /* Allocate backing store of the new size. */ + if (this->AllocateBackingStore(w, h)) { + /* Mark all palette colours dirty. */ + _cur_palette.first_dirty = 0; + _cur_palette.count_dirty = 256; + _local_palette = _cur_palette; + + BlitterFactory::GetCurrentBlitter()->PostResize(); + + GameSizeChanged(); + } +} + bool VideoDriver_Win32Base::ChangeResolution(int w, int h) { std::unique_lock lock; @@ -1303,7 +1192,7 @@ const char *VideoDriver_Win32GDI::Start(const StringList ¶m) _wnd.width_org = _cur_resolution.width; _wnd.height_org = _cur_resolution.height; - AllocateDibSection(_cur_resolution.width, _cur_resolution.height); + this->AllocateBackingStore(_cur_resolution.width, _cur_resolution.height); this->MakeWindow(_fullscreen); MarkWholeScreenDirty(); @@ -1323,8 +1212,116 @@ void VideoDriver_Win32GDI::Stop() MyShowCursor(true); } +bool VideoDriver_Win32GDI::AllocateBackingStore(int w, int h, bool force) +{ + uint bpp = BlitterFactory::GetCurrentBlitter()->GetScreenDepth(); + + w = std::max(w, 64); + h = std::max(h, 64); + + if (!force && w == _screen.width && h == _screen.height) return false; + + BITMAPINFO *bi = (BITMAPINFO *)alloca(sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256); + memset(bi, 0, sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256); + bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + + bi->bmiHeader.biWidth = _wnd.width = w; + bi->bmiHeader.biHeight = -(_wnd.height = h); + + bi->bmiHeader.biPlanes = 1; + bi->bmiHeader.biBitCount = bpp; + bi->bmiHeader.biCompression = BI_RGB; + + if (_wnd.dib_sect) DeleteObject(_wnd.dib_sect); + + HDC dc = GetDC(0); + _wnd.dib_sect = CreateDIBSection(dc, bi, DIB_RGB_COLORS, (VOID **)&_wnd.buffer_bits, nullptr, 0); + if (_wnd.dib_sect == nullptr) usererror("CreateDIBSection failed"); + ReleaseDC(0, dc); + + _screen.width = w; + _screen.pitch = (bpp == 8) ? Align(w, 4) : w; + _screen.height = h; + _screen.dst_ptr = _wnd.buffer_bits; + + return true; +} + bool VideoDriver_Win32GDI::AfterBlitterChange() { assert(BlitterFactory::GetCurrentBlitter()->GetScreenDepth() != 0); - return AllocateDibSection(_screen.width, _screen.height, true) && this->MakeWindow(_fullscreen); + return this->AllocateBackingStore(_screen.width, _screen.height, true) && this->MakeWindow(_fullscreen); +} + +void VideoDriver_Win32GDI::PaletteChanged(HWND hWnd) +{ + HDC hDC = GetWindowDC(hWnd); + HPALETTE hOldPalette = SelectPalette(hDC, _wnd.gdi_palette, FALSE); + UINT nChanged = RealizePalette(hDC); + + SelectPalette(hDC, hOldPalette, TRUE); + ReleaseDC(hWnd, hDC); + if (nChanged != 0) this->MakeDirty(0, 0, _screen.width, _screen.height); +} + +void VideoDriver_Win32GDI::Paint() +{ + PerformanceMeasurer framerate(PFE_VIDEO); + + if (IsEmptyRect(_dirty_rect)) return; + + HDC dc = GetDC(_wnd.main_wnd); + HDC dc2 = CreateCompatibleDC(dc); + + HBITMAP old_bmp = (HBITMAP)SelectObject(dc2, _wnd.dib_sect); + HPALETTE old_palette = SelectPalette(dc, _wnd.gdi_palette, FALSE); + + if (_cur_palette.count_dirty != 0) { + Blitter *blitter = BlitterFactory::GetCurrentBlitter(); + + switch (blitter->UsePaletteAnimation()) { + case Blitter::PALETTE_ANIMATION_VIDEO_BACKEND: + UpdatePalette(dc2, _local_palette.first_dirty, _local_palette.count_dirty); + break; + + case Blitter::PALETTE_ANIMATION_BLITTER: + blitter->PaletteAnimate(_local_palette); + break; + + case Blitter::PALETTE_ANIMATION_NONE: + break; + + default: + NOT_REACHED(); + } + _cur_palette.count_dirty = 0; + } + + BitBlt(dc, 0, 0, _wnd.width, _wnd.height, dc2, 0, 0, SRCCOPY); + SelectPalette(dc, old_palette, TRUE); + SelectObject(dc2, old_bmp); + DeleteDC(dc2); + + ReleaseDC(_wnd.main_wnd, dc); + + _dirty_rect = {}; +} + +void VideoDriver_Win32GDI::PaintThread() +{ + /* First tell the main thread we're started */ + std::unique_lock lock(*_draw_mutex); + _draw_signal->notify_one(); + + /* Now wait for the first thing to draw! */ + _draw_signal->wait(*_draw_mutex); + + while (_draw_continue) { + this->Paint(); + + /* Flush GDI buffer to ensure drawing here doesn't conflict with any GDI usage in the main WndProc. */ + GdiFlush(); + + _draw_signal->wait(*_draw_mutex); + } } diff --git a/src/video/win32_v.h b/src/video/win32_v.h index 6834f66ffb..cb1658cefe 100644 --- a/src/video/win32_v.h +++ b/src/video/win32_v.h @@ -37,15 +37,20 @@ protected: void InputLoop() override; bool LockVideoBuffer() override; void UnlockVideoBuffer() override; - void Paint() override; - void PaintThread() override; void CheckPaletteAnim() override; bool MakeWindow(bool full_screen); + /** (Re-)create the backing store. */ + virtual bool AllocateBackingStore(int w, int h, bool force = false) = 0; + /** Palette of the window has changed. */ + virtual void PaletteChanged(HWND hWnd) = 0; + private: std::unique_lock draw_lock; + void ClientSizeChanged(int w, int h); + static void PaintThreadThunk(VideoDriver_Win32Base *drv); friend LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); @@ -60,6 +65,13 @@ public: bool AfterBlitterChange() override; const char *GetName() const override { return "win32"; } + +protected: + void Paint() override; + void PaintThread() override; + + bool AllocateBackingStore(int w, int h, bool force = false) override; + void PaletteChanged(HWND hWnd) override; }; /** The factory for Windows' video driver. */ From 78b8fc3e4fea1f1788ea793c4e9cf1e39898135a Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Sat, 16 Jan 2021 16:43:02 +0100 Subject: [PATCH 5/6] Codechange: [Win32] Move GDI-specific variables and related functions into the GDI video driver class. --- src/video/win32_v.cpp | 185 ++++++++++++++++++++---------------------- src/video/win32_v.h | 16 ++++ 2 files changed, 103 insertions(+), 98 deletions(-) diff --git a/src/video/win32_v.cpp b/src/video/win32_v.cpp index 73c01dea11..58dad78512 100644 --- a/src/video/win32_v.cpp +++ b/src/video/win32_v.cpp @@ -41,10 +41,7 @@ #endif static struct { - HWND main_wnd; ///< Handle to system window. - HBITMAP dib_sect; ///< System bitmap object referencing our rendering buffer. void *buffer_bits; ///< Internal rendering buffer. - HPALETTE gdi_palette; ///< Palette object for 8bpp blitter. int width; ///< Width in pixels of our display surface. int height; ///< Height in pixels of our display surface. int width_org; ///< Original monitor resolution width, before we changed it. @@ -71,43 +68,6 @@ static Palette _local_palette; /** Region of the screen that needs redrawing. */ static Rect _dirty_rect; -static void MakePalette() -{ - _cur_palette.first_dirty = 0; - _cur_palette.count_dirty = 256; - _local_palette = _cur_palette; - - LOGPALETTE *pal = (LOGPALETTE*)alloca(sizeof(LOGPALETTE) + (256 - 1) * sizeof(PALETTEENTRY)); - - pal->palVersion = 0x300; - pal->palNumEntries = 256; - - for (uint i = 0; i != 256; i++) { - pal->palPalEntry[i].peRed = _local_palette.palette[i].r; - pal->palPalEntry[i].peGreen = _local_palette.palette[i].g; - pal->palPalEntry[i].peBlue = _local_palette.palette[i].b; - pal->palPalEntry[i].peFlags = 0; - - } - _wnd.gdi_palette = CreatePalette(pal); - if (_wnd.gdi_palette == nullptr) usererror("CreatePalette failed!\n"); -} - -static void UpdatePalette(HDC dc, uint start, uint count) -{ - RGBQUAD rgb[256]; - uint i; - - for (i = 0; i != count; i++) { - rgb[i].rgbRed = _local_palette.palette[start + i].r; - rgb[i].rgbGreen = _local_palette.palette[start + i].g; - rgb[i].rgbBlue = _local_palette.palette[start + i].b; - rgb[i].rgbReserved = 0; - } - - SetDIBColorTable(dc, start, count, rgb); -} - bool VideoDriver_Win32Base::ClaimMousePointer() { MyShowCursor(false, true); @@ -182,33 +142,6 @@ static uint MapWindowsKey(uint sym) return key; } -#ifdef _DEBUG -/* Keep this function here.. - * It allows you to redraw the screen from within the MSVC debugger */ -int RedrawScreenDebug() -{ - HDC dc, dc2; - static int _fooctr; - HBITMAP old_bmp; - HPALETTE old_palette; - - UpdateWindows(); - - dc = GetDC(_wnd.main_wnd); - dc2 = CreateCompatibleDC(dc); - - old_bmp = (HBITMAP)SelectObject(dc2, _wnd.dib_sect); - old_palette = SelectPalette(dc, _wnd.gdi_palette, FALSE); - BitBlt(dc, 0, 0, _wnd.width, _wnd.height, dc2, 0, 0, SRCCOPY); - SelectPalette(dc, old_palette, TRUE); - SelectObject(dc2, old_bmp); - DeleteDC(dc2); - ReleaseDC(_wnd.main_wnd, dc); - - return _fooctr++; -} -#endif - /** * Instantiate a new window. * @param full_screen Whether to make a full screen window or not. @@ -221,9 +154,9 @@ bool VideoDriver_Win32Base::MakeWindow(bool full_screen) _fullscreen = full_screen; /* recreate window? */ - if ((full_screen || _wnd.fullscreen) && _wnd.main_wnd) { - DestroyWindow(_wnd.main_wnd); - _wnd.main_wnd = 0; + if ((full_screen || _wnd.fullscreen) && this->main_wnd) { + DestroyWindow(this->main_wnd); + this->main_wnd = 0; } if (full_screen) { @@ -289,8 +222,8 @@ bool VideoDriver_Win32Base::MakeWindow(bool full_screen) w = r.right - r.left; h = r.bottom - r.top; - if (_wnd.main_wnd != nullptr) { - if (!_window_maximize) SetWindowPos(_wnd.main_wnd, 0, 0, 0, w, h, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER | SWP_NOMOVE); + if (this->main_wnd != nullptr) { + if (!_window_maximize) SetWindowPos(this->main_wnd, 0, 0, 0, w, h, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER | SWP_NOMOVE); } else { int x = (GetSystemMetrics(SM_CXSCREEN) - w) / 2; int y = (GetSystemMetrics(SM_CYSCREEN) - h) / 2; @@ -298,16 +231,16 @@ bool VideoDriver_Win32Base::MakeWindow(bool full_screen) char window_title[64]; seprintf(window_title, lastof(window_title), "OpenTTD %s", _openttd_revision); - _wnd.main_wnd = CreateWindow(_T("OTTD"), MB_TO_WIDE(window_title), style, x, y, w, h, 0, 0, GetModuleHandle(nullptr), this); - if (_wnd.main_wnd == nullptr) usererror("CreateWindow failed"); - ShowWindow(_wnd.main_wnd, showstyle); + this->main_wnd = CreateWindow(_T("OTTD"), MB_TO_WIDE(window_title), style, x, y, w, h, 0, 0, GetModuleHandle(nullptr), this); + if (this->main_wnd == nullptr) usererror("CreateWindow failed"); + ShowWindow(this->main_wnd, showstyle); } } BlitterFactory::GetCurrentBlitter()->PostResize(); - GameSizeChanged(); // invalidate all windows, force redraw - return true; // the request succeeded + GameSizeChanged(); + return true; } /* static */ void VideoDriver_Win32Base::PaintThreadThunk(VideoDriver_Win32Base *drv) @@ -1077,7 +1010,7 @@ bool VideoDriver_Win32Base::ChangeResolution(int w, int h) std::unique_lock lock; if (_draw_mutex != nullptr) lock = std::unique_lock(*_draw_mutex); - if (_window_maximize) ShowWindow(_wnd.main_wnd, SW_SHOWNORMAL); + if (_window_maximize) ShowWindow(this->main_wnd, SW_SHOWNORMAL); _wnd.width = _wnd.width_org = w; _wnd.height = _wnd.height_org = h; @@ -1108,9 +1041,9 @@ void VideoDriver_Win32Base::EditBoxLostFocus() std::unique_lock lock; if (_draw_mutex != nullptr) lock = std::unique_lock(*_draw_mutex); - CancelIMEComposition(_wnd.main_wnd); - SetCompositionPos(_wnd.main_wnd); - SetCandidatePos(_wnd.main_wnd); + CancelIMEComposition(this->main_wnd); + SetCompositionPos(this->main_wnd); + SetCandidatePos(this->main_wnd); } Dimension VideoDriver_Win32Base::GetScreenSize() const @@ -1139,14 +1072,14 @@ float VideoDriver_Win32Base::GetDPIScale() UINT cur_dpi = 0; - if (cur_dpi == 0 && _GetDpiForWindow != nullptr && _wnd.main_wnd != nullptr) { + if (cur_dpi == 0 && _GetDpiForWindow != nullptr && this->main_wnd != nullptr) { /* Per window DPI is supported since Windows 10 Ver 1607. */ - cur_dpi = _GetDpiForWindow(_wnd.main_wnd); + cur_dpi = _GetDpiForWindow(this->main_wnd); } - if (cur_dpi == 0 && _GetDpiForMonitor != nullptr && _wnd.main_wnd != nullptr) { + if (cur_dpi == 0 && _GetDpiForMonitor != nullptr && this->main_wnd != nullptr) { /* Per monitor is supported since Windows 8.1. */ UINT dpiX, dpiY; - if (SUCCEEDED(_GetDpiForMonitor(MonitorFromWindow(_wnd.main_wnd, MONITOR_DEFAULTTOPRIMARY), 0 /* MDT_EFFECTIVE_DPI */, &dpiX, &dpiY))) { + if (SUCCEEDED(_GetDpiForMonitor(MonitorFromWindow(this->main_wnd, MONITOR_DEFAULTTOPRIMARY), 0 /* MDT_EFFECTIVE_DPI */, &dpiX, &dpiY))) { cur_dpi = dpiX; // X and Y are always identical. } } @@ -1182,7 +1115,7 @@ const char *VideoDriver_Win32GDI::Start(const StringList ¶m) RegisterWndClass(); - MakePalette(); + this->MakePalette(); FindResolutions(); @@ -1204,9 +1137,9 @@ const char *VideoDriver_Win32GDI::Start(const StringList ¶m) void VideoDriver_Win32GDI::Stop() { - DeleteObject(_wnd.gdi_palette); - DeleteObject(_wnd.dib_sect); - DestroyWindow(_wnd.main_wnd); + DeleteObject(this->gdi_palette); + DeleteObject(this->dib_sect); + DestroyWindow(this->main_wnd); if (_wnd.fullscreen) ChangeDisplaySettings(nullptr, 0); MyShowCursor(true); @@ -1232,11 +1165,11 @@ bool VideoDriver_Win32GDI::AllocateBackingStore(int w, int h, bool force) bi->bmiHeader.biBitCount = bpp; bi->bmiHeader.biCompression = BI_RGB; - if (_wnd.dib_sect) DeleteObject(_wnd.dib_sect); + if (this->dib_sect) DeleteObject(this->dib_sect); HDC dc = GetDC(0); - _wnd.dib_sect = CreateDIBSection(dc, bi, DIB_RGB_COLORS, (VOID **)&_wnd.buffer_bits, nullptr, 0); - if (_wnd.dib_sect == nullptr) usererror("CreateDIBSection failed"); + this->dib_sect = CreateDIBSection(dc, bi, DIB_RGB_COLORS, (VOID **)&_wnd.buffer_bits, nullptr, 0); + if (this->dib_sect == nullptr) usererror("CreateDIBSection failed"); ReleaseDC(0, dc); _screen.width = w; @@ -1253,10 +1186,46 @@ bool VideoDriver_Win32GDI::AfterBlitterChange() return this->AllocateBackingStore(_screen.width, _screen.height, true) && this->MakeWindow(_fullscreen); } +void VideoDriver_Win32GDI::MakePalette() +{ + _cur_palette.first_dirty = 0; + _cur_palette.count_dirty = 256; + _local_palette = _cur_palette; + + LOGPALETTE *pal = (LOGPALETTE*)alloca(sizeof(LOGPALETTE) + (256 - 1) * sizeof(PALETTEENTRY)); + + pal->palVersion = 0x300; + pal->palNumEntries = 256; + + for (uint i = 0; i != 256; i++) { + pal->palPalEntry[i].peRed = _local_palette.palette[i].r; + pal->palPalEntry[i].peGreen = _local_palette.palette[i].g; + pal->palPalEntry[i].peBlue = _local_palette.palette[i].b; + pal->palPalEntry[i].peFlags = 0; + + } + this->gdi_palette = CreatePalette(pal); + if (this->gdi_palette == nullptr) usererror("CreatePalette failed!\n"); +} + +void VideoDriver_Win32GDI::UpdatePalette(HDC dc, uint start, uint count) +{ + RGBQUAD rgb[256]; + + for (uint i = 0; i != count; i++) { + rgb[i].rgbRed = _local_palette.palette[start + i].r; + rgb[i].rgbGreen = _local_palette.palette[start + i].g; + rgb[i].rgbBlue = _local_palette.palette[start + i].b; + rgb[i].rgbReserved = 0; + } + + SetDIBColorTable(dc, start, count, rgb); +} + void VideoDriver_Win32GDI::PaletteChanged(HWND hWnd) { HDC hDC = GetWindowDC(hWnd); - HPALETTE hOldPalette = SelectPalette(hDC, _wnd.gdi_palette, FALSE); + HPALETTE hOldPalette = SelectPalette(hDC, this->gdi_palette, FALSE); UINT nChanged = RealizePalette(hDC); SelectPalette(hDC, hOldPalette, TRUE); @@ -1270,18 +1239,18 @@ void VideoDriver_Win32GDI::Paint() if (IsEmptyRect(_dirty_rect)) return; - HDC dc = GetDC(_wnd.main_wnd); + HDC dc = GetDC(this->main_wnd); HDC dc2 = CreateCompatibleDC(dc); - HBITMAP old_bmp = (HBITMAP)SelectObject(dc2, _wnd.dib_sect); - HPALETTE old_palette = SelectPalette(dc, _wnd.gdi_palette, FALSE); + HBITMAP old_bmp = (HBITMAP)SelectObject(dc2, this->dib_sect); + HPALETTE old_palette = SelectPalette(dc, this->gdi_palette, FALSE); if (_cur_palette.count_dirty != 0) { Blitter *blitter = BlitterFactory::GetCurrentBlitter(); switch (blitter->UsePaletteAnimation()) { case Blitter::PALETTE_ANIMATION_VIDEO_BACKEND: - UpdatePalette(dc2, _local_palette.first_dirty, _local_palette.count_dirty); + this->UpdatePalette(dc2, _local_palette.first_dirty, _local_palette.count_dirty); break; case Blitter::PALETTE_ANIMATION_BLITTER: @@ -1302,7 +1271,7 @@ void VideoDriver_Win32GDI::Paint() SelectObject(dc2, old_bmp); DeleteDC(dc2); - ReleaseDC(_wnd.main_wnd, dc); + ReleaseDC(this->main_wnd, dc); _dirty_rect = {}; } @@ -1325,3 +1294,23 @@ void VideoDriver_Win32GDI::PaintThread() _draw_signal->wait(*_draw_mutex); } } + + +#ifdef _DEBUG +/* Keep this function here.. + * It allows you to redraw the screen from within the MSVC debugger */ +/* static */ int VideoDriver_Win32GDI::RedrawScreenDebug() +{ + static int _fooctr; + + _screen.dst_ptr = _wnd.buffer_bits; + UpdateWindows(); + + VideoDriver_Win32GDI *drv = static_cast(VideoDriver::GetInstance()); + + drv->Paint(); + GdiFlush(); + + return _fooctr++; +} +#endif diff --git a/src/video/win32_v.h b/src/video/win32_v.h index cb1658cefe..13115e8c9a 100644 --- a/src/video/win32_v.h +++ b/src/video/win32_v.h @@ -15,6 +15,8 @@ /** Base class for Windows video drivers. */ class VideoDriver_Win32Base : public VideoDriver { public: + VideoDriver_Win32Base() : main_wnd(nullptr) {} + void MakeDirty(int left, int top, int width, int height) override; void MainLoop() override; @@ -32,6 +34,8 @@ public: void EditBoxLostFocus() override; protected: + HWND main_wnd; ///< Handle to system window. + Dimension GetScreenSize() const override; float GetDPIScale() override; void InputLoop() override; @@ -58,6 +62,8 @@ private: /** The GDI video driver for windows. */ class VideoDriver_Win32GDI : public VideoDriver_Win32Base { public: + VideoDriver_Win32GDI() : dib_sect(nullptr), gdi_palette(nullptr) {} + const char *Start(const StringList ¶m) override; void Stop() override; @@ -67,11 +73,21 @@ public: const char *GetName() const override { return "win32"; } protected: + HBITMAP dib_sect; ///< System bitmap object referencing our rendering buffer. + HPALETTE gdi_palette; ///< Palette object for 8bpp blitter. + void Paint() override; void PaintThread() override; bool AllocateBackingStore(int w, int h, bool force = false) override; void PaletteChanged(HWND hWnd) override; + void MakePalette(); + void UpdatePalette(HDC dc, uint start, uint count); + +#ifdef _DEBUG +public: + static int RedrawScreenDebug(); +#endif }; /** The factory for Windows' video driver. */ From af4d32357cc4cea6878c61c366378477e62915d0 Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Sat, 16 Jan 2021 16:43:03 +0100 Subject: [PATCH 6/6] Codechange: [Win32] Move common initialization and finalization to the video driver base class. --- src/video/win32_v.cpp | 81 +++++++++++++++++++++++-------------------- src/video/win32_v.h | 7 +++- 2 files changed, 49 insertions(+), 39 deletions(-) diff --git a/src/video/win32_v.cpp b/src/video/win32_v.cpp index 58dad78512..7ebac069dc 100644 --- a/src/video/win32_v.cpp +++ b/src/video/win32_v.cpp @@ -46,7 +46,6 @@ static struct { int height; ///< Height in pixels of our display surface. int width_org; ///< Original monitor resolution width, before we changed it. int height_org; ///< Original monitor resolution height, before we changed it. - bool fullscreen; ///< Whether to use (true) fullscreen mode. bool has_focus; ///< Does our window have system focus? bool running; ///< Is the main loop running? } _wnd; @@ -142,6 +141,13 @@ static uint MapWindowsKey(uint sym) return key; } +/** Colour depth to use for fullscreen display modes. */ +uint8 VideoDriver_Win32Base::GetFullscreenBpp() +{ + /* Check modes for the relevant fullscreen bpp */ + return _support8bpp != S8BPP_HARDWARE ? 32 : BlitterFactory::GetCurrentBlitter()->GetScreenDepth(); +} + /** * Instantiate a new window. * @param full_screen Whether to make a full screen window or not. @@ -154,7 +160,7 @@ bool VideoDriver_Win32Base::MakeWindow(bool full_screen) _fullscreen = full_screen; /* recreate window? */ - if ((full_screen || _wnd.fullscreen) && this->main_wnd) { + if ((full_screen || this->fullscreen) && this->main_wnd) { DestroyWindow(this->main_wnd); this->main_wnd = 0; } @@ -168,13 +174,12 @@ bool VideoDriver_Win32Base::MakeWindow(bool full_screen) DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; - settings.dmBitsPerPel = BlitterFactory::GetCurrentBlitter()->GetScreenDepth(); + settings.dmBitsPerPel = this->GetFullscreenBpp(); settings.dmPelsWidth = _wnd.width_org; settings.dmPelsHeight = _wnd.height_org; /* Check for 8 bpp support. */ - if (settings.dmBitsPerPel == 8 && - (_support8bpp != S8BPP_HARDWARE || ChangeDisplaySettings(&settings, CDS_FULLSCREEN | CDS_TEST) != DISP_CHANGE_SUCCESSFUL)) { + if (settings.dmBitsPerPel == 8 && ChangeDisplaySettings(&settings, CDS_FULLSCREEN | CDS_TEST) != DISP_CHANGE_SUCCESSFUL) { settings.dmBitsPerPel = 32; } @@ -193,7 +198,7 @@ bool VideoDriver_Win32Base::MakeWindow(bool full_screen) this->MakeWindow(false); // don't care about the result return false; // the request failed } - } else if (_wnd.fullscreen) { + } else if (this->fullscreen) { /* restore display? */ ChangeDisplaySettings(nullptr, 0); /* restore the resolution */ @@ -207,8 +212,8 @@ bool VideoDriver_Win32Base::MakeWindow(bool full_screen) int w, h; showstyle = SW_SHOWNORMAL; - _wnd.fullscreen = full_screen; - if (_wnd.fullscreen) { + this->fullscreen = full_screen; + if (this->fullscreen) { style = WS_POPUP; SetRect(&r, 0, 0, _wnd.width_org, _wnd.height_org); } else { @@ -661,7 +666,7 @@ LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) switch (wParam) { case VK_RETURN: case 'F': // Full Screen on ALT + ENTER/F - ToggleFullScreen(!_wnd.fullscreen); + ToggleFullScreen(!video_driver->fullscreen); return 0; case VK_MENU: // Just ALT @@ -780,7 +785,7 @@ LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) bool active = (LOWORD(wParam) != WA_INACTIVE); bool minimized = (HIWORD(wParam) != 0); - if (_wnd.fullscreen) { + if (video_driver->fullscreen) { if (active && minimized) { /* Restore the game window */ ShowWindow(hwnd, SW_RESTORE); @@ -836,20 +841,12 @@ static const Dimension default_resolutions[] = { { 1920, 1200 } }; -static void FindResolutions() +static void FindResolutions(uint8 bpp) { - uint i; - DEVMODEA dm; - - /* Check modes for the relevant fullscreen bpp */ - uint bpp = _support8bpp != S8BPP_HARDWARE ? 32 : BlitterFactory::GetCurrentBlitter()->GetScreenDepth(); - _resolutions.clear(); - /* XXX - EnumDisplaySettingsW crashes with unicows.dll on Windows95 - * Doesn't really matter since we don't pass a string anyways, but still - * a letdown */ - for (i = 0; EnumDisplaySettingsA(nullptr, i, &dm) != 0; i++) { + DEVMODE dm; + for (uint i = 0; EnumDisplaySettings(nullptr, i, &dm) != 0; i++) { if (dm.dmBitsPerPel != bpp || dm.dmPelsWidth < 640 || dm.dmPelsHeight < 480) continue; if (std::find(_resolutions.begin(), _resolutions.end(), Dimension(dm.dmPelsWidth, dm.dmPelsHeight)) != _resolutions.end()) continue; _resolutions.emplace_back(dm.dmPelsWidth, dm.dmPelsHeight); @@ -863,6 +860,29 @@ static void FindResolutions() SortResolutions(); } +void VideoDriver_Win32Base::Initialize() +{ + this->UpdateAutoResolution(); + + memset(&_wnd, 0, sizeof(_wnd)); + + RegisterWndClass(); + FindResolutions(this->GetFullscreenBpp()); + + /* fullscreen uses those */ + _wnd.width = _wnd.width_org = _cur_resolution.width; + _wnd.height = _wnd.height_org = _cur_resolution.height; + + DEBUG(driver, 2, "Resolution for display: %ux%u", _cur_resolution.width, _cur_resolution.height); +} + +void VideoDriver_Win32Base::Stop() +{ + DestroyWindow(this->main_wnd); + + if (this->fullscreen) ChangeDisplaySettings(nullptr, 0); + MyShowCursor(true); +} void VideoDriver_Win32Base::MakeDirty(int left, int top, int width, int height) { Rect r = {left, top, left + width, top + height}; @@ -1109,22 +1129,9 @@ const char *VideoDriver_Win32GDI::Start(const StringList ¶m) { if (BlitterFactory::GetCurrentBlitter()->GetScreenDepth() == 0) return "Only real blitters supported"; - this->UpdateAutoResolution(); - - memset(&_wnd, 0, sizeof(_wnd)); - - RegisterWndClass(); + this->Initialize(); this->MakePalette(); - - FindResolutions(); - - DEBUG(driver, 2, "Resolution for display: %ux%u", _cur_resolution.width, _cur_resolution.height); - - /* fullscreen uses those */ - _wnd.width_org = _cur_resolution.width; - _wnd.height_org = _cur_resolution.height; - this->AllocateBackingStore(_cur_resolution.width, _cur_resolution.height); this->MakeWindow(_fullscreen); @@ -1139,10 +1146,8 @@ void VideoDriver_Win32GDI::Stop() { DeleteObject(this->gdi_palette); DeleteObject(this->dib_sect); - DestroyWindow(this->main_wnd); - if (_wnd.fullscreen) ChangeDisplaySettings(nullptr, 0); - MyShowCursor(true); + this->VideoDriver_Win32Base::Stop(); } bool VideoDriver_Win32GDI::AllocateBackingStore(int w, int h, bool force) diff --git a/src/video/win32_v.h b/src/video/win32_v.h index 13115e8c9a..b50f4e7a5a 100644 --- a/src/video/win32_v.h +++ b/src/video/win32_v.h @@ -15,7 +15,9 @@ /** Base class for Windows video drivers. */ class VideoDriver_Win32Base : public VideoDriver { public: - VideoDriver_Win32Base() : main_wnd(nullptr) {} + VideoDriver_Win32Base() : main_wnd(nullptr), fullscreen(false) {} + + void Stop() override; void MakeDirty(int left, int top, int width, int height) override; @@ -35,6 +37,7 @@ public: protected: HWND main_wnd; ///< Handle to system window. + bool fullscreen; ///< Whether to use (true) fullscreen mode. Dimension GetScreenSize() const override; float GetDPIScale() override; @@ -43,7 +46,9 @@ protected: void UnlockVideoBuffer() override; void CheckPaletteAnim() override; + void Initialize(); bool MakeWindow(bool full_screen); + virtual uint8 GetFullscreenBpp(); /** (Re-)create the backing store. */ virtual bool AllocateBackingStore(int w, int h, bool force = false) = 0;