Compare commits

...

34 Commits

Author SHA1 Message Date
Michael Lutz
a82f21f24d Update: Changelog for 1.9.2 and prepare for release 2019-07-07 22:54:44 +02:00
Niels Martin Hansen
46908fb63a Fix: Various reliability and correctness improvements to MIDI on Windows. (#7620) 2019-07-07 22:54:44 +02:00
pnda
8efa99f445 Fix #6666: Mismatched parentheses in RTL languages. (#7480) 2019-07-07 22:54:44 +02:00
dP
c6251426d9 Fix: Make GSGoal.QuestionClient work correctly at least for clients with ID < 2**16 (#7560) 2019-07-07 22:54:44 +02:00
unknown
9026736cc1 Fix #5685: Check for free wagons in ScriptVehicleList (#7617) 2019-07-07 22:54:44 +02:00
Niels Martin Hansen
b7a2166962 Fix #7633: Allow zero-cost track conversion to succeed. (#7634) 2019-07-07 22:54:44 +02:00
Michael Lutz
8ea68421b1 Fix #7463: Promote scroll mode setting to basic category. 2019-07-07 22:54:44 +02:00
PeterN
afc5962881 Fix #7577: Check if linkgraph station index is valid before dereferencing. (#7583) 2019-07-07 22:54:44 +02:00
stormcone
9239381d56 Fix #7224: Drag and drop vehicle group creation does not work correctly.
When drag and drop a vehicle into an empty slot in the vehicle group window it tries to create the new group as the subgroup of the first group (GroupID = 0). This is failing if the dragged vehicle's type is different than the first group's vehicle type.
2019-07-07 22:54:44 +02:00
peter1138
9dded61af9 Cleanup: Remove unused string. 2019-07-07 22:54:44 +02:00
peter1138
8fbc5c090b Change: Allow building road stops over self-owned one-way/blocked road. (#7547) 2019-07-07 22:54:44 +02:00
Transportman
00bdd316d7 Fix #7570: Show Github URL in the crashlog window 2019-07-07 22:54:44 +02:00
Corns McGowan
f34284f1a0 Change: Set default setting in server browser of "Advertised" to "Yes". (#7568) 2019-07-07 22:54:44 +02:00
peter1138
c77659c995 Fix: Clicking on scrollbar 'thumb' moved position up instantly. (#7549) 2019-07-07 22:54:44 +02:00
Charles Pigott
e6877d0823 Fix #7255: Prevent crashlog corruption by only printing the 32 most recent news messages. (#7542) 2019-07-07 22:54:44 +02:00
glx22
beba12f9d6 Fix: vcpkg used to patch lzma.h to define LZMA_API_STATIC for static builds (#7614) 2019-07-07 22:54:44 +02:00
glx22
95fd4ec649 Fix 8fc2b48db: [AzurePipeline] copy/paste error (#7557) 2019-05-28 10:20:32 +01:00
peter1138
0fa41c7493 Fix #7491: Send company update admin message when bankruptcy counter changes. 2019-05-28 10:20:32 +01:00
PeterN
60cbcf0742 Fix: Bounds check access to railtype_map. (#7529) 2019-05-28 10:20:32 +01:00
Niels Martin Hansen
e38a4e1e57 Change: Zoom title game by UI zoom level 2019-05-28 10:20:32 +01:00
Niels Martin Hansen
5965f184c2 Fix: Manager name in company news was being clipped 2019-05-28 10:20:32 +01:00
Niels Martin Hansen
db20c7f461 Fix: Scale news ticker scroll speed by UI scale 2019-05-28 10:20:32 +01:00
Niels Martin Hansen
e2e8872e82 Fix: Scale all min size and padding by UI scale 2019-05-28 10:20:32 +01:00
SamuXarick
4750d2836c Fix 50e08f333a: Creating a cargo subsidy with town as source did not consider min population. (#7493) 2019-05-28 10:20:32 +01:00
stormcone
b1c31f9500 Fix: Typos. (#7517) 2019-05-28 10:20:32 +01:00
Charles Pigott
a6879e9180 Fix 5db883f: Railtype bits were moved too late, leading to rails under bridges losing their type 2019-05-28 10:20:32 +01:00
Charles Pigott
5eb7d49024 Fix #6507: Don't try to load invalid depots from older savegames 2019-05-28 10:20:32 +01:00
Charles Pigott
69c0332813 Cleanup: Delete GetSavegameType function since it's been commented out since 2005 2019-05-28 10:20:32 +01:00
Charles Pigott
b11942cf44 Fix: Crash when attempting to load old save game with GRFs set
GroupStatistics pool was not initialised before trying to delete vehicles (specifically, trams with no tram track)
2019-05-28 10:20:32 +01:00
glx22
ef6995e8d4 Fix 2bb80d2: really increase the maximum number of GameScript texts to 64k (#7555) 2019-05-28 10:20:32 +01:00
glx22
c0fd2b969b Fix #7553: check bounds when loading strings (#7554) 2019-05-28 10:20:32 +01:00
peter1138
683778fd7a Codechange: Use std::underlying_type for DECLARE_POSTFIX_INCREMENT. 2019-05-28 10:20:32 +01:00
peter1138
63eeadef17 Fix: Replace int with std::underlying_type in DECLARE_ENUM_AS_BIT_SET.
This fixes 64 bit uses of this macro.
2019-05-28 10:20:32 +01:00
glx22
e526b2ccd3 Fix: [AzurePipeline] ${Agent.JobName} content changed (#7556)
* Fix: [AzurePipeline] ${Agent.JobName} content changed

* Fix: [AzurePipeline] also update commit-checker condition
2019-05-28 10:20:32 +01:00
83 changed files with 404 additions and 314 deletions

View File

@@ -38,10 +38,14 @@ jobs:
strategy:
matrix:
commit-checker: {}
linux-amd64-clang-3.8: {}
linux-amd64-gcc-6: {}
linux-i386-gcc-6: {}
commit-checker:
Tag: 'commit-checker'
linux-amd64-clang-3.8:
Tag: 'linux-amd64-clang-3.8'
linux-amd64-gcc-6:
Tag: 'linux-amd64-gcc-6'
linux-i386-gcc-6:
Tag: 'linux-i386-gcc-6'
steps:
- template: azure-pipelines/templates/ci-git-rebase.yml
@@ -50,7 +54,7 @@ jobs:
- template: azure-pipelines/templates/linux-build.yml
parameters:
Image: compile-farm-ci
Tag: $(Agent.JobName)
Tag: $(Tag)
- job: macos
displayName: 'MacOS'

View File

@@ -24,7 +24,7 @@ steps:
${{ if eq(parameters.Image, 'compile-farm-ci') }}:
displayName: 'Build and test'
# Run the commit-checker only if it is a Pull Request
condition: and(succeeded(), or(ne(variables['Agent.JobName'], 'commit-checker'), eq(variables['Build.Reason'], 'PullRequest')))
condition: and(succeeded(), or(not(contains(variables['Agent.JobName'], 'commit-checker')), eq(variables['Build.Reason'], 'PullRequest')))
inputs:
command: 'Run an image'
imageName: openttd/${{ parameters.Image }}:${{ parameters.Tag }}

View File

@@ -110,14 +110,22 @@ jobs:
strategy:
matrix:
linux-ubuntu-xenial-i386-gcc: {}
linux-ubuntu-xenial-amd64-gcc: {}
linux-ubuntu-bionic-i386-gcc: {}
linux-ubuntu-bionic-amd64-gcc: {}
linux-debian-jessie-i386-gcc: {}
linux-debian-jessie-amd64-gcc: {}
linux-debian-stretch-i386-gcc: {}
linux-debian-stretch-amd64-gcc: {}
linux-ubuntu-xenial-i386-gcc:
Tag: 'linux-ubuntu-xenial-i386-gcc'
linux-ubuntu-xenial-amd64-gcc:
Tag: 'linux-ubuntu-xenial-amd64-gcc'
linux-ubuntu-bionic-i386-gcc:
Tag: 'linux-ubuntu-bionic-i386-gcc'
linux-ubuntu-bionic-amd64-gcc:
Tag: 'linux-ubuntu-bionic-amd64-gcc'
linux-debian-jessie-i386-gcc:
Tag: 'linux-debian-jessie-i386-gcc'
linux-debian-jessie-amd64-gcc:
Tag: 'linux-debian-jessie-amd64-gcc'
linux-debian-stretch-i386-gcc:
Tag: 'linux-debian-stretch-i386-gcc'
linux-debian-stretch-amd64-gcc:
Tag: 'linux-debian-stretch-amd64-gcc'
steps:
- template: release-fetch-source.yml
@@ -125,7 +133,7 @@ jobs:
parameters:
Image: compile-farm
ContainerCommand: '$(Build.BuildNumber)'
Tag: $(Agent.JobName)
Tag: $(Tag)
- template: linux-claim-bundles.yml
- template: release-bundles.yml

View File

@@ -1,3 +1,29 @@
1.9.2 (2019-07-07)
------------------------------------------------------------------------
- Change: Set default setting in server browser of "Advertised" to "Yes" (#7568)
- Change: Allow building road stops over self-owned one-way/blocked road (#7547)
- Fix #7463: Promote scroll mode setting to basic category (#7586)
- Fix: Inconsistent GUI scaling (#7539)
- Fix #7491: Send company update admin message when bankruptcy counter changes (#7492)
- Fix #7553: Check bounds when loading strings (#7554)
- Fix: Really increase the maximum number of GameScript texts to 64k (#7555)
- Fix: Crash when attempting to load old save game with GRFs set (#7546)
- Fix #6507: Don't try to load invalid depots from older savegames (#7546)
- Fix: Railtype bits were moved too late, leading to rails under bridges losing their type (#7546)
- Fix: Bounds check access to railtype_map (#7529)
- Fix: Spurious errors when using more than 32 railtypes (#7533)
- Fix #7633: Allow zero-cost track conversion to succeed (#7634)
- Fix #7577: Check if linkgraph station index is valid before dereferencing (#7583)
- Fix #7224: Drag and drop vehicle group creation does not work correctly (#7581)
- Fix #7570: Show Github URL in the crashlog window (#7571)
- Fix: Clicking on scrollbar 'thumb' moved position up instantly (#7549)
- Fix #7255: Prevent crashlog corruption by only printing the 32 most recent news messages (#7542)
- Fix #5685: Check for free wagons in ScriptVehicleList (#7617)
- Fix: Make GSGoal.QuestionClient work correctly at least for clients with ID < 2**16 (#7560)
- Fix #6666: Mismatched parentheses in RTL languages (#7480)
- Fix: [Windows] Various reliability and correctness improvements to MIDI on Windows (#7620)
1.9.1 (2019-04-08)
------------------------------------------------------------------------
- Fix #6564: Enforce types of arguments for station name strings (#7419)
@@ -8,6 +34,7 @@
- Fix: [Windows] Incorrect error handling could lead to cascading error windows (#7482)
- Fix #7478: Don't remove NewGRF objects on company take-over. (#7483)
1.9.0 (2019-04-01)
------------------------------------------------------------------------
- Fix #7411: Use industry production callback (if used) on initial industry cargo generation (#7412)

View File

@@ -1,6 +1,6 @@
OpenTTD's known bugs
Last updated: 2019-04-08
Release version: 1.9.1
Last updated: 2019-07-07
Release version: 1.9.2
------------------------------------------------------------------------

View File

@@ -1,3 +1,9 @@
openttd (1.9.2-0) unstable; urgency=low
* New upstream release 1.9.2
-- OpenTTD <info@openttd.org> Sun, 07 Jul 2019 23:00:00 +0200
openttd (1.9.1-0) unstable; urgency=low
* New upstream release 1.9.1

View File

@@ -1,6 +1,6 @@
@echo off
set OPENTTD_VERSION=1.9.1
set OPENTTD_VERSION=1.9.2
set OPENSFX_VERSION=0.8.0
set NOSOUND_VERSION=0.8.0
set OPENGFX_VERSION=1.2.0

View File

@@ -17,9 +17,9 @@
#
Name: openttd
Version: 1.9.1
Version: 1.9.2
Release: 0
%define srcver 1.9.1
%define srcver 1.9.2
Summary: An open source reimplementation of Chris Sawyer's Transport Tycoon Deluxe
License: GPL-2.0
Group: Amusements/Games/Strategy/Other

View File

@@ -1,7 +1,7 @@
# Version numbers to update
!define APPV_MAJOR 1
!define APPV_MINOR 9
!define APPV_MAINT 1
!define APPV_MAINT 2
!define APPV_BUILD 0
!define APPV_EXTRA ""

View File

@@ -12,18 +12,20 @@
#ifndef ENUM_TYPE_HPP
#define ENUM_TYPE_HPP
#include <type_traits>
/** Some enums need to have allowed incrementing (i.e. StationClassID) */
#define DECLARE_POSTFIX_INCREMENT(type) \
inline type operator ++(type& e, int) \
#define DECLARE_POSTFIX_INCREMENT(enum_type) \
inline enum_type operator ++(enum_type& e, int) \
{ \
type e_org = e; \
e = (type)((int)e + 1); \
enum_type e_org = e; \
e = (enum_type)((std::underlying_type<enum_type>::type)e + 1); \
return e_org; \
} \
inline type operator --(type& e, int) \
inline enum_type operator --(enum_type& e, int) \
{ \
type e_org = e; \
e = (type)((int)e - 1); \
enum_type e_org = e; \
e = (enum_type)((std::underlying_type<enum_type>::type)e - 1); \
return e_org; \
}
@@ -31,13 +33,13 @@
/** Operators to allow to work with enum as with type safe bit set in C++ */
# define DECLARE_ENUM_AS_BIT_SET(mask_t) \
inline mask_t operator | (mask_t m1, mask_t m2) {return (mask_t)((int)m1 | m2);} \
inline mask_t operator & (mask_t m1, mask_t m2) {return (mask_t)((int)m1 & m2);} \
inline mask_t operator ^ (mask_t m1, mask_t m2) {return (mask_t)((int)m1 ^ m2);} \
inline mask_t operator | (mask_t m1, mask_t m2) {return (mask_t)((std::underlying_type<mask_t>::type)m1 | m2);} \
inline mask_t operator & (mask_t m1, mask_t m2) {return (mask_t)((std::underlying_type<mask_t>::type)m1 & m2);} \
inline mask_t operator ^ (mask_t m1, mask_t m2) {return (mask_t)((std::underlying_type<mask_t>::type)m1 ^ m2);} \
inline mask_t& operator |= (mask_t& m1, mask_t m2) {m1 = m1 | m2; return m1;} \
inline mask_t& operator &= (mask_t& m1, mask_t m2) {m1 = m1 & m2; return m1;} \
inline mask_t& operator ^= (mask_t& m1, mask_t m2) {m1 = m1 ^ m2; return m1;} \
inline mask_t operator ~(mask_t m) {return (mask_t)(~(int)m);}
inline mask_t operator ~(mask_t m) {return (mask_t)(~(std::underlying_type<mask_t>::type)m);}
/**

View File

@@ -303,7 +303,7 @@ char *CrashLog::LogGamelog(char *buffer, const char *last) const
}
/**
* Writes any recent news messages to the buffer.
* Writes up to 32 recent news messages to the buffer, with the most recent first.
* @param buffer The begin where to write at.
* @param last The last position in the buffer to write to.
* @return the position of the \c '\0' character after the buffer.
@@ -312,7 +312,8 @@ char *CrashLog::LogRecentNews(char *buffer, const char *last) const
{
buffer += seprintf(buffer, last, "Recent news messages:\n");
for (NewsItem *news = _oldest_news; news != NULL; news = news->next) {
int i = 0;
for (NewsItem *news = _latest_news; i < 32 && news != NULL; news = news->prev, i++) {
YearMonthDay ymd;
ConvertDateToYMD(news->date, &ymd);
buffer += seprintf(buffer, last, "(%i-%02i-%02i) StringID: %u, Type: %u, Ref1: %u, %u, Ref2: %u, %u\n",

View File

@@ -572,8 +572,10 @@ static void CompanyCheckBankrupt(Company *c)
{
/* If the company has money again, it does not go bankrupt */
if (c->money - c->current_loan >= -_economy.max_loan) {
int previous_months_of_bankruptcy = CeilDiv(c->months_of_bankruptcy, 3);
c->months_of_bankruptcy = 0;
c->bankrupt_asked = 0;
if (previous_months_of_bankruptcy != 0) CompanyAdminUpdate(c);
return;
}
@@ -642,10 +644,15 @@ static void CompanyCheckBankrupt(Company *c)
* that changing the current company is okay. In case of single
* player we are sure (the above check) that we are not the local
* company and thus we won't be moved. */
if (!_networking || _network_server) DoCommandP(0, CCA_DELETE | (c->index << 16) | (CRR_BANKRUPT << 24), 0, CMD_COMPANY_CTRL);
if (!_networking || _network_server) {
DoCommandP(0, CCA_DELETE | (c->index << 16) | (CRR_BANKRUPT << 24), 0, CMD_COMPANY_CTRL);
return;
}
break;
}
}
if (CeilDiv(c->months_of_bankruptcy, 3) != CeilDiv(c->months_of_bankruptcy - 1, 3)) CompanyAdminUpdate(c);
}
/**

View File

@@ -308,7 +308,7 @@ GameStrings *LoadTranslations()
/** Compile the language. */
void GameStrings::Compile()
{
StringData data(1);
StringData data(32);
StringListReader master_reader(data, this->raw_strings[0], true, false);
master_reader.ParseFile();
if (_errors != 0) throw std::exception();

View File

@@ -208,7 +208,7 @@ public:
LEErrorCode status = LE_NO_ERROR;
/* ParagraphLayout does not copy "buff", so it must stay valid.
* "runs" is copied according to the ICU source, but the documentation does not specify anything, so this might break somewhen. */
icu::ParagraphLayout *p = new icu::ParagraphLayout(buff, length, &runs, NULL, NULL, NULL, _current_text_dir == TD_RTL ? UBIDI_DEFAULT_RTL : UBIDI_DEFAULT_LTR, false, status);
icu::ParagraphLayout *p = new icu::ParagraphLayout(buff, length, &runs, NULL, NULL, NULL, _current_text_dir == TD_RTL ? 1 : 0, false, status);
if (status != LE_NO_ERROR) {
delete p;
return NULL;

View File

@@ -236,10 +236,11 @@ CommandCost CmdSetGoalCompleted(TileIndex tile, DoCommandFlag flags, uint32 p1,
* @param flags type of operation
* @param p1 various bitstuffed elements
* - p1 = (bit 0 - 15) - Unique ID to use for this question.
* - p1 = (bit 16 - 23) - Company or client for which this question is.
* - p1 = (bit 24 - 25) - Question type.
* - p1 = (bit 31) - Question target: 0 - company, 1 - client.
* @param p2 Buttons of the question.
* - p1 = (bit 16 - 31) - Company or client for which this question is.
* @param p2 various bitstuffed elements
* - p2 = (bit 0 - 17) - Buttons of the question.
* - p2 = (bit 29 - 30) - Question type.
* - p2 = (bit 31) - Question target: 0 - company, 1 - client.
* @param text Text of the question.
* @return the cost of this operation or an error
*/
@@ -248,36 +249,38 @@ CommandCost CmdGoalQuestion(TileIndex tile, DoCommandFlag flags, uint32 p1, uint
uint16 uniqueid = (GoalType)GB(p1, 0, 16);
CompanyID company = (CompanyID)GB(p1, 16, 8);
#ifdef ENABLE_NETWORK
ClientIndex client = (ClientIndex)GB(p1, 16, 8);
ClientID client = (ClientID)GB(p1, 16, 16);
#endif
byte type = GB(p1, 24, 2);
bool is_client = HasBit(p1, 31);
assert_compile(GOAL_QUESTION_BUTTON_COUNT < 29);
uint32 button_mask = GB(p2, 0, GOAL_QUESTION_BUTTON_COUNT);
byte type = GB(p2, 29, 2);
bool is_client = HasBit(p2, 31);
if (_current_company != OWNER_DEITY) return CMD_ERROR;
if (StrEmpty(text)) return CMD_ERROR;
if (is_client) {
#ifdef ENABLE_NETWORK
if (!NetworkClientInfo::IsValidID(client)) return CMD_ERROR;
if (NetworkClientInfo::GetByClientID(client) == nullptr) return CMD_ERROR;
#else
return CMD_ERROR;
#endif
} else {
if (company != INVALID_COMPANY && !Company::IsValidID(company)) return CMD_ERROR;
}
if (CountBits(p2) < 1 || CountBits(p2) > 3) return CMD_ERROR;
if (p2 >= (1 << GOAL_QUESTION_BUTTON_COUNT)) return CMD_ERROR;
if (CountBits(button_mask) < 1 || CountBits(button_mask) > 3) return CMD_ERROR;
if (type >= GOAL_QUESTION_TYPE_COUNT) return CMD_ERROR;
if (flags & DC_EXEC) {
if (is_client) {
#ifdef ENABLE_NETWORK
if (NetworkClientInfo::Get(client)->client_id != _network_own_client_id) return CommandCost();
if (client != _network_own_client_id) return CommandCost();
#endif
} else {
if (company == INVALID_COMPANY && !Company::IsValidID(_local_company)) return CommandCost();
if (company != INVALID_COMPANY && company != _local_company) return CommandCost();
}
ShowGoalQuestion(uniqueid, type, p2, text);
ShowGoalQuestion(uniqueid, type, button_mask, text);
}
return CommandCost();

View File

@@ -536,7 +536,7 @@ CommandCost CmdAddVehicleGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, u
if (new_g == NEW_GROUP) {
/* Create new group. */
CommandCost ret = CmdCreateGroup(0, flags, v->type, 0, NULL);
CommandCost ret = CmdCreateGroup(0, flags, v->type, INVALID_GROUP, NULL);
if (ret.Failed()) return ret;
new_g = _new_group_id;

View File

@@ -282,7 +282,7 @@ STR_SORT_BY_TIMETABLE_DELAY :تاخير جد
STR_SORT_BY_FACILITY :نوع المحطة
STR_SORT_BY_RATING_MAX :اعلى نسبة شحن
STR_SORT_BY_RATING_MIN :اقل نسبة شحن
STR_SORT_BY_ENGINE_ID :نوع المحرك (قياسي(
STR_SORT_BY_ENGINE_ID :نوع المحرك (قياسي)
STR_SORT_BY_COST :التكلفة
STR_SORT_BY_POWER :الطاقة
STR_SORT_BY_TRACTIVE_EFFORT :قوة الجذب
@@ -1147,7 +1147,7 @@ STR_CONFIG_SETTING_INDUSTRY_DENSITY :الكثافة
STR_CONFIG_SETTING_INDUSTRY_DENSITY_HELPTEXT :إختر مقدار الصناعات التي يجب تكوينها وعلى اي مستوى يجب ان تكون خلال اللعبة
STR_CONFIG_SETTING_SNOWLINE_HEIGHT :ارتفاع خط الثلج: {STRING}
STR_CONFIG_SETTING_SNOWLINE_HEIGHT_HELPTEXT :تحكم على اي ارتفاع يبدأ نزول الثلج في المناطق القطبية,تؤثر الثلوج على مستوى تطور القطاع الصناعي ونمو المدن
STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN :خشونة التضاريس (صفر التكوين فقط ) :({STRING}
STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN :خشونة التضاريس: {STRING}
STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_HELPTEXT :(TerraGenesis only)إختر تكرار الهضبات: الاراض المستويه تحتوي على البضع منها,هضبات موزعه عرضيا اكثر,الاراض الوعرة تحتوي الكثير من الهضاب,التي من الممكن ان تكون متكررة
STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_VERY_SMOOTH :ناعم جدا
STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_SMOOTH :ناعم
@@ -1946,7 +1946,7 @@ STR_RAIL_TOOLBAR_MAGLEV_CONSTRUCTION_CAPTION :بناء الس
STR_RAIL_TOOLBAR_TOOLTIP_BUILD_RAILROAD_TRACK :{BLACK}بناء سكة حديد
STR_RAIL_TOOLBAR_TOOLTIP_BUILD_AUTORAIL :{BLACK}بناء سكة القطار باستخدام البناء التلقائي
STR_RAIL_TOOLBAR_TOOLTIP_BUILD_TRAIN_DEPOT_FOR_BUILDING :{BLACK}بناء ورشة قطارات (لصيانة و شراء القطارات).
STR_RAIL_TOOLBAR_TOOLTIP_BUILD_TRAIN_DEPOT_FOR_BUILDING :{BLACK}بناء ورشة قطارات (لصيانة و شراء القطارات)
STR_RAIL_TOOLBAR_TOOLTIP_CONVERT_RAIL_TO_WAYPOINT :{BLACK}غير السكة الى نقطة عبور
STR_RAIL_TOOLBAR_TOOLTIP_BUILD_RAILROAD_STATION :{BLACK}بناء محطة قطار. مفتاح كنترول يسمح بضم المحطات
STR_RAIL_TOOLBAR_TOOLTIP_BUILD_RAILROAD_SIGNALS :{BLACK}بناء إشارات السكك الحديدية.
@@ -2028,7 +2028,7 @@ STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAMWAY_SECTION :{BLACK}بناء
STR_ROAD_TOOLBAR_TOOLTIP_BUILD_AUTOROAD :{BLACK}بناء الطرق باستخدام النظام الآلي
STR_ROAD_TOOLBAR_TOOLTIP_BUILD_AUTOTRAM :{BLACK}بناء سكة القطار باستخدام النظام الآلي
STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_VEHICLE_DEPOT :{BLACK}بناء ورشة صيانة لعربات الطرق (لشراء و صيانة العربات).
STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAM_VEHICLE_DEPOT :{BLACK}بناء ورشة لصيانة عربات الترام (لشراء و صيانة عربات الترام).
STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAM_VEHICLE_DEPOT :{BLACK}بناء ورشة لصيانة عربات الترام (لشراء و صيانة عربات الترام)
STR_ROAD_TOOLBAR_TOOLTIP_BUILD_BUS_STATION :{BLACK}بناء محطة باصات
STR_ROAD_TOOLBAR_TOOLTIP_BUILD_PASSENGER_TRAM_STATION :{BLACK}بناء محطة ركاب ترام.
STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRUCK_LOADING_BAY :{BLACK}بناء محطة تحميل عربات. مفتاح كنترول يسمح بمجاورة المحطات.
@@ -2590,7 +2590,8 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}ادخل
# Town directory window
STR_TOWN_DIRECTORY_CAPTION :{WHITE}مدن/ بلدات
STR_TOWN_DIRECTORY_NONE :{ORANGE}-بدون-
STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ) {COMMA})
STR_TOWN_DIRECTORY_TOWN :{ORANGE}{RLE}{TOWN}{BLACK} {RLM}({COMMA})
STR_TOWN_DIRECTORY_CITY :{ORANGE}{RLE}{TOWN}{YELLOW} (مدينة){BLACK} {RLM}({COMMA})
STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}اسم المدينة - اضغط على الاسم لتوسيط الشاشة عليها. اضغط + كنترول لفتح شاشة عرض جديدة للضاحية.
STR_TOWN_POPULATION :{BLACK}سكان العالم: {COMMA}
@@ -2678,7 +2679,7 @@ STR_STATION_LIST_STATION :{YELLOW}{STATIO
STR_STATION_LIST_WAYPOINT :{YELLOW}{WAYPOINT}
STR_STATION_LIST_NONE :{YELLOW}- بدون -
STR_STATION_LIST_SELECT_ALL_FACILITIES :{BLACK}اختر جميع المرافق
STR_STATION_LIST_SELECT_ALL_TYPES :{BLACK}اختر كل انواع الشحن (حتى غير المنتظرة(
STR_STATION_LIST_SELECT_ALL_TYPES :{BLACK}اختر كل انواع الشحن (حتى غير المنتظرة)
STR_STATION_LIST_NO_WAITING_CARGO :{BLACK}لا يوجد اي شحنة منتظرة
# Station view window
@@ -2897,7 +2898,7 @@ STR_PURCHASE_INFO_SPEED_OCEAN :{BLACK}السر
STR_PURCHASE_INFO_SPEED_CANAL :{BLACK}السرعة في القناة/النهر: {GOLD}{VELOCITY}
STR_PURCHASE_INFO_RUNNINGCOST :{BLACK}تكلفة التشغيل: {GOLD}{CURRENCY_LONG}/ سنة
STR_PURCHASE_INFO_CAPACITY :{BLACK}السعة: {GOLD}{CARGO_LONG} {STRING}
STR_PURCHASE_INFO_REFITTABLE :)قابل لتغيير(
STR_PURCHASE_INFO_REFITTABLE :(قابل لتغيي)
STR_PURCHASE_INFO_DESIGNED_LIFE :{BLACK}تصميم: {GOLD}{NUM}{BLACK} العمر الافتراضي: {GOLD}{COMMA} سنة
STR_PURCHASE_INFO_RELIABILITY :{BLACK}الاعتمادية القصوى: {GOLD}{COMMA}%
STR_PURCHASE_INFO_COST :{BLACK}التكلفة: {GOLD}{CURRENCY_LONG}
@@ -3193,7 +3194,7 @@ STR_VEHICLE_DETAILS_TRAIN_TOTAL_CARGO_TOOLTIP :{BLACK} عرض
STR_VEHICLE_DETAILS_TRAIN_ARTICULATED_RV_CAPACITY :{BLACK}السعة: {LTBLUE}
# Vehicle refit
STR_REFIT_CAPTION :{WHITE}{VEHICLE} )تغيير(
STR_REFIT_CAPTION :{WHITE}{VEHICLE} (تغيير)
STR_REFIT_TITLE :{GOLD}اختر نوع الحمولة ...
STR_REFIT_NEW_CAPACITY_COST_OF_REFIT :{BLACK}السعة الجديدة: {GOLD}{CARGO_LONG}{}{BLACK}تكلفة التغيير: {RED}{CURRENCY_LONG}
STR_REFIT_NEW_CAPACITY_COST_OF_AIRCRAFT_REFIT :{BLACK}السعة الجديدة: {GOLD}{CARGO_LONG}, {GOLD}{CARGO_LONG}{}{BLACK}تكلفة اعادة التهيئة: {RED}{CURRENCY_LONG}
@@ -3415,7 +3416,7 @@ STR_TIMETABLE_RESET_LATENESS :{BLACK}اعد
STR_TIMETABLE_RESET_LATENESS_TOOLTIP :{BLACK}عدل وقت التاخير للعداد حتى تصل المركبة في الوقت المحدد
STR_TIMETABLE_AUTOFILL :{BLACK}تهيئة تلقائية
STR_TIMETABLE_AUTOFILL_TOOLTIP :{BLACK}املأ الجدولة تلقائيا بقيم الرحلة التالية (مفتاح كنترول لمحاولة ابقائ وقت الانتظار).
STR_TIMETABLE_AUTOFILL_TOOLTIP :{BLACK}مفتاح كنترول لمحاولة ابقائ وقت الانتظار (املأ الجدولة تلقائيا بقيم الرحلة التالية)
STR_TIMETABLE_EXPECTED :{BLACK}متوقع
STR_TIMETABLE_SCHEDULED :{BLACK}مجدول

View File

@@ -4586,7 +4586,6 @@ STR_ERROR_DRIVE_THROUGH_ON_TOWN_ROAD :{WHITE}... гэ
STR_ERROR_DRIVE_THROUGH_DIRECTION :{WHITE}... няправільны кірунак дарогі
STR_ERROR_DRIVE_THROUGH_CORNER :{WHITE}... на прахадных прыпынках нельга рабіць павароты
STR_ERROR_DRIVE_THROUGH_JUNCTION :{WHITE}... на прахадных прыпынках нельга рабіць скрыжаваньнi
STR_ERROR_DRIVE_THROUGH_ON_ONEWAY_ROAD :{WHITE}... дарога аднабаковая ці заблакавана
# Station destruction related errors
STR_ERROR_CAN_T_REMOVE_PART_OF_STATION :{WHITE}Немагчыма выдаліць частку станцыi...

View File

@@ -4276,7 +4276,6 @@ STR_ERROR_DRIVE_THROUGH_ON_TOWN_ROAD :{WHITE}... é u
STR_ERROR_DRIVE_THROUGH_DIRECTION :{WHITE}... rua na direção errada
STR_ERROR_DRIVE_THROUGH_CORNER :{WHITE}... paradas "drive-thru" não podem ter esquinas
STR_ERROR_DRIVE_THROUGH_JUNCTION :{WHITE}... paradas "drive-thru" não podem ter junções
STR_ERROR_DRIVE_THROUGH_ON_ONEWAY_ROAD :{WHITE}... rua é mão única ou está bloqueada
# Station destruction related errors
STR_ERROR_CAN_T_REMOVE_PART_OF_STATION :{WHITE}Impossível remover parte da estação...

View File

@@ -4317,7 +4317,6 @@ STR_ERROR_DRIVE_THROUGH_ON_TOWN_ROAD :{WHITE}... aque
STR_ERROR_DRIVE_THROUGH_DIRECTION :{WHITE}... sentit de la carretera en la direcció incorrecta
STR_ERROR_DRIVE_THROUGH_CORNER :{WHITE}... les estacions d'autobús de pas no poden tenir cantonades
STR_ERROR_DRIVE_THROUGH_JUNCTION :{WHITE}... les estacions d'autobús de pas no poden tenir interseccions
STR_ERROR_DRIVE_THROUGH_ON_ONEWAY_ROAD :{WHITE}... la carretera és d'un sol sentit o està blocada.
# Station destruction related errors
STR_ERROR_CAN_T_REMOVE_PART_OF_STATION :{WHITE}No es pot treure part de la estació...

View File

@@ -4413,7 +4413,6 @@ STR_ERROR_DRIVE_THROUGH_ON_TOWN_ROAD :{WHITE}... ovo
STR_ERROR_DRIVE_THROUGH_DIRECTION :{WHITE}... cesta je orijentirana u krivom smjeru
STR_ERROR_DRIVE_THROUGH_CORNER :{WHITE}... prolazne postaje ne mogu imati zavoje
STR_ERROR_DRIVE_THROUGH_JUNCTION :{WHITE}... prolazne postaje ne mogu imati raskrižja
STR_ERROR_DRIVE_THROUGH_ON_ONEWAY_ROAD :{WHITE}... cesta je jednosmjerna ili je blokirana
# Station destruction related errors
STR_ERROR_CAN_T_REMOVE_PART_OF_STATION :{WHITE}Nije moguće ukloniti dio postaje...

View File

@@ -4339,7 +4339,6 @@ STR_ERROR_DRIVE_THROUGH_ON_TOWN_ROAD :{WHITE}... tato
STR_ERROR_DRIVE_THROUGH_DIRECTION :{WHITE}... silnice je otočena jiným směrem
STR_ERROR_DRIVE_THROUGH_CORNER :{WHITE}... průjezdné zastávky nemohou být v zatáčce
STR_ERROR_DRIVE_THROUGH_JUNCTION :{WHITE}... průjezdné zastávky nemohou být na křižovatce
STR_ERROR_DRIVE_THROUGH_ON_ONEWAY_ROAD :{WHITE}... silnice je jednosměrná nebo uzavřená.
# Station destruction related errors
STR_ERROR_CAN_T_REMOVE_PART_OF_STATION :{WHITE}Nelze odstranit část stanice...

View File

@@ -4317,7 +4317,6 @@ STR_ERROR_DRIVE_THROUGH_ON_TOWN_ROAD :{WHITE}... denn
STR_ERROR_DRIVE_THROUGH_DIRECTION :{WHITE}... vejen peger i den forkerte retning
STR_ERROR_DRIVE_THROUGH_CORNER :{WHITE}... drive-through stops kan ikke have hjørner
STR_ERROR_DRIVE_THROUGH_JUNCTION :{WHITE}... drive-through stops kan ikke have kryds
STR_ERROR_DRIVE_THROUGH_ON_ONEWAY_ROAD :{WHITE}vejen er ensrettet eller blokeret
# Station destruction related errors
STR_ERROR_CAN_T_REMOVE_PART_OF_STATION :{WHITE}Kan ikke fjerne en del af en station...

View File

@@ -4317,7 +4317,6 @@ STR_ERROR_DRIVE_THROUGH_ON_TOWN_ROAD :{WHITE}... deze
STR_ERROR_DRIVE_THROUGH_DIRECTION :{WHITE}... weg is in de verkeerde richting
STR_ERROR_DRIVE_THROUGH_CORNER :{WHITE}... doorrij haltes kunnen geen bochten hebben
STR_ERROR_DRIVE_THROUGH_JUNCTION :{WHITE}... doorrij haltes kunnen geen kruisingen hebben
STR_ERROR_DRIVE_THROUGH_ON_ONEWAY_ROAD :{WHITE}... weg is eenrichtingsverkeer of geblokkeerd
# Station destruction related errors
STR_ERROR_CAN_T_REMOVE_PART_OF_STATION :{WHITE}Kan deel van station niet verwijderen...

View File

@@ -4317,7 +4317,6 @@ STR_ERROR_DRIVE_THROUGH_ON_TOWN_ROAD :{WHITE}... this
STR_ERROR_DRIVE_THROUGH_DIRECTION :{WHITE}... road facing in the wrong direction
STR_ERROR_DRIVE_THROUGH_CORNER :{WHITE}... drive through stops can't have corners
STR_ERROR_DRIVE_THROUGH_JUNCTION :{WHITE}... drive through stops can't have junctions
STR_ERROR_DRIVE_THROUGH_ON_ONEWAY_ROAD :{WHITE}... road is one way or blocked
# Station destruction related errors
STR_ERROR_CAN_T_REMOVE_PART_OF_STATION :{WHITE}Can't remove part of station...

View File

@@ -4317,7 +4317,6 @@ STR_ERROR_DRIVE_THROUGH_ON_TOWN_ROAD :{WHITE}... this
STR_ERROR_DRIVE_THROUGH_DIRECTION :{WHITE}... road facing in the wrong direction
STR_ERROR_DRIVE_THROUGH_CORNER :{WHITE}... drive through stops can't have corners
STR_ERROR_DRIVE_THROUGH_JUNCTION :{WHITE}... drive through stops can't have junctions
STR_ERROR_DRIVE_THROUGH_ON_ONEWAY_ROAD :{WHITE}... road is one way or blocked
# Station destruction related errors
STR_ERROR_CAN_T_REMOVE_PART_OF_STATION :{WHITE}Can't remove part of station...

View File

@@ -4284,7 +4284,6 @@ STR_ERROR_DRIVE_THROUGH_ON_TOWN_ROAD :{WHITE}... see
STR_ERROR_DRIVE_THROUGH_DIRECTION :{WHITE}... tee on vales suunas
STR_ERROR_DRIVE_THROUGH_CORNER :{WHITE}... nurgad ei saa läbisõidupeatustes olla
STR_ERROR_DRIVE_THROUGH_JUNCTION :{WHITE}... ristmikud ei saa olla läbisõidupeatustes
STR_ERROR_DRIVE_THROUGH_ON_ONEWAY_ROAD :{WHITE}... tee on ühesuunaline või blokeeritud
# Station destruction related errors
STR_ERROR_CAN_T_REMOVE_PART_OF_STATION :{WHITE}Siinset jaamablokki ei saa lammutada...

View File

@@ -4317,7 +4317,6 @@ STR_ERROR_DRIVE_THROUGH_ON_TOWN_ROAD :{WHITE}... kunt
STR_ERROR_DRIVE_THROUGH_DIRECTION :{WHITE}... tie on väärin päin
STR_ERROR_DRIVE_THROUGH_CORNER :{WHITE}... läpiajettavissa pysäkeissä ei voi olla mutkia
STR_ERROR_DRIVE_THROUGH_JUNCTION :{WHITE}... läpiajettavissa pysäkeissä ei voi olla risteyksiä
STR_ERROR_DRIVE_THROUGH_ON_ONEWAY_ROAD :{WHITE}... tie on yksisuuntainen tai suljettu
# Station destruction related errors
STR_ERROR_CAN_T_REMOVE_PART_OF_STATION :{WHITE}Aseman osaa ei voi poistaa...

View File

@@ -4318,7 +4318,6 @@ STR_ERROR_DRIVE_THROUGH_ON_TOWN_ROAD :{WHITE}... cett
STR_ERROR_DRIVE_THROUGH_DIRECTION :{WHITE}... mauvaise orientation de la route
STR_ERROR_DRIVE_THROUGH_CORNER :{WHITE}... les arrêts ne peuvent pas avoir de virages
STR_ERROR_DRIVE_THROUGH_JUNCTION :{WHITE}... les arrêts ne peuvent pas avoir de jonctions
STR_ERROR_DRIVE_THROUGH_ON_ONEWAY_ROAD :{WHITE}... la route est à sens unique ou bloquée
# Station destruction related errors
STR_ERROR_CAN_T_REMOVE_PART_OF_STATION :{WHITE}Impossible de supprimer une partie de la gare...

View File

@@ -4496,7 +4496,6 @@ STR_ERROR_DRIVE_THROUGH_ON_TOWN_ROAD :{WHITE}... tha
STR_ERROR_DRIVE_THROUGH_DIRECTION :{WHITE}... tha comhair an rathaid cearr
STR_ERROR_DRIVE_THROUGH_CORNER :{WHITE}... chan urrainn dha dhoiseanan a bhith aig stèiseanan draibhidh troimhe
STR_ERROR_DRIVE_THROUGH_JUNCTION :{WHITE}... chan urrainn dha ghoibhlean a bhith aig stèiseanan draibhidh troimhe
STR_ERROR_DRIVE_THROUGH_ON_ONEWAY_ROAD :{WHITE}... rathad aon-shligheach no bacte
# Station destruction related errors
STR_ERROR_CAN_T_REMOVE_PART_OF_STATION :{WHITE}Cha ghabh pàirt dhen stèisean toirt air falbh...

View File

@@ -4302,7 +4302,6 @@ STR_ERROR_DRIVE_THROUGH_ON_TOWN_ROAD :{WHITE}... dies
STR_ERROR_DRIVE_THROUGH_DIRECTION :{WHITE}... Straße verläuft in die falsche Richtung
STR_ERROR_DRIVE_THROUGH_CORNER :{WHITE}... Bus- und Lkw-Haltestellen können nicht um die Kurve gehen
STR_ERROR_DRIVE_THROUGH_JUNCTION :{WHITE}... Bus- und Lkw-Haltestellen können keine Abzweigung haben
STR_ERROR_DRIVE_THROUGH_ON_ONEWAY_ROAD :{WHITE}...Einbahnstraße oder blockierter Weg
# Station destruction related errors
STR_ERROR_CAN_T_REMOVE_PART_OF_STATION :{WHITE}Dieser Teil der Station kann nicht entfernt werden...

View File

@@ -4430,7 +4430,6 @@ STR_ERROR_DRIVE_THROUGH_ON_TOWN_ROAD :{WHITE}... αυ
STR_ERROR_DRIVE_THROUGH_DIRECTION :{WHITE}... ο δρόμος βλέπει σε λάθος κατεύθυνση
STR_ERROR_DRIVE_THROUGH_CORNER :{WHITE}... οι μη τερματικοί σταθμοί δε μπορούν να έχουν στροφές
STR_ERROR_DRIVE_THROUGH_JUNCTION :{WHITE}... οι μη τερματικοί σταθμοί δε μπορούν να έχουν διασταυρώσεις
STR_ERROR_DRIVE_THROUGH_ON_ONEWAY_ROAD :{WHITE}... ο δρόμος είναι μονόδρομος η μπλοκαρισμένος
# Station destruction related errors
STR_ERROR_CAN_T_REMOVE_PART_OF_STATION :{WHITE}Δεν μπορεί να αφαιρεθεί μέρος του σταθμού...

View File

@@ -4275,7 +4275,6 @@ STR_ERROR_DRIVE_THROUGH_ON_TOWN_ROAD :{WHITE}... כב
STR_ERROR_DRIVE_THROUGH_DIRECTION :{WHITE}הכביש פונה לכיוון לא נכון...
STR_ERROR_DRIVE_THROUGH_CORNER :{WHITE}... לתחנות "על הדרך" לא יכולות להיות פינות
STR_ERROR_DRIVE_THROUGH_JUNCTION :{WHITE}... לתחנות "על הדרך" לא יכולות להיות צמתים
STR_ERROR_DRIVE_THROUGH_ON_ONEWAY_ROAD :{WHITE}... הדרך חד כיוונית או חסומה
# Station destruction related errors
STR_ERROR_CAN_T_REMOVE_PART_OF_STATION :{WHITE}... לא ניתן לבטל חלק מהתחנה

View File

@@ -4381,7 +4381,6 @@ STR_ERROR_DRIVE_THROUGH_ON_TOWN_ROAD :{WHITE}... ez e
STR_ERROR_DRIVE_THROUGH_DIRECTION :{WHITE}... az út a másik irányba vezet
STR_ERROR_DRIVE_THROUGH_CORNER :{WHITE}... áthaladó megállóhelyeken nem lehet kanyar
STR_ERROR_DRIVE_THROUGH_JUNCTION :{WHITE}... áthaladó megállóhelyeken nem lehet elágazás
STR_ERROR_DRIVE_THROUGH_ON_ONEWAY_ROAD :{WHITE}... az út egyirányú vagy blokkolt
# Station destruction related errors
STR_ERROR_CAN_T_REMOVE_PART_OF_STATION :{WHITE}Nem lehet eltávolítani az állomás részét...

View File

@@ -4249,7 +4249,6 @@ STR_ERROR_DRIVE_THROUGH_ON_TOWN_ROAD :{WHITE}... jala
STR_ERROR_DRIVE_THROUGH_DIRECTION :{WHITE}... menghadap pada arah yang salah
STR_ERROR_DRIVE_THROUGH_CORNER :{WHITE}... terminal lintas-lalu tak bisa memiliki sudut
STR_ERROR_DRIVE_THROUGH_JUNCTION :{WHITE}... terminal lintas-lalu tak bisa memiliki simpangan
STR_ERROR_DRIVE_THROUGH_ON_ONEWAY_ROAD :{WHITE}... jalannya satu arah atau terhalang
# Station destruction related errors
STR_ERROR_CAN_T_REMOVE_PART_OF_STATION :{WHITE}Tidak dapat menghapus bagian dari stasiun...

View File

@@ -4347,7 +4347,6 @@ STR_ERROR_DRIVE_THROUGH_ON_TOWN_ROAD :{WHITE}... ques
STR_ERROR_DRIVE_THROUGH_DIRECTION :{WHITE}... strada rivolta nella direzione sbagliata
STR_ERROR_DRIVE_THROUGH_CORNER :{WHITE}... le fermate passanti non possono trovarsi in curva
STR_ERROR_DRIVE_THROUGH_JUNCTION :{WHITE}... le fermate passanti non possono avere raccordi
STR_ERROR_DRIVE_THROUGH_ON_ONEWAY_ROAD :{WHITE}... la strada è bloccata o a senso unico
# Station destruction related errors
STR_ERROR_CAN_T_REMOVE_PART_OF_STATION :{WHITE}Impossibile rimuovere parte della stazione...

View File

@@ -4318,7 +4318,6 @@ STR_ERROR_DRIVE_THROUGH_ON_TOWN_ROAD :{WHITE}... 여
STR_ERROR_DRIVE_THROUGH_DIRECTION :{WHITE}... 도로의 방향과 일치하지 않습니다.
STR_ERROR_DRIVE_THROUGH_CORNER :{WHITE}... 도로 통과 정류장은 곡선도로에 건설할 수 없습니다.
STR_ERROR_DRIVE_THROUGH_JUNCTION :{WHITE}... 도로 통과 정류장은 교차로에 건설할 수 없습니다.
STR_ERROR_DRIVE_THROUGH_ON_ONEWAY_ROAD :{WHITE}... 도로가 일방통행이거나 막혔습니다
# Station destruction related errors
STR_ERROR_CAN_T_REMOVE_PART_OF_STATION :{WHITE}역의 일부를 제거할 수 없습니다...

View File

@@ -4479,7 +4479,6 @@ STR_ERROR_DRIVE_THROUGH_ON_TOWN_ROAD :{WHITE}... via
STR_ERROR_DRIVE_THROUGH_DIRECTION :{WHITE}... viae directio non convenit
STR_ERROR_DRIVE_THROUGH_CORNER :{WHITE}... stationi perviae non licet esse curva
STR_ERROR_DRIVE_THROUGH_JUNCTION :{WHITE}... stationi perviae non licet compita habere
STR_ERROR_DRIVE_THROUGH_ON_ONEWAY_ROAD :{WHITE}... via est monodromus vel obstructa
# Station destruction related errors
STR_ERROR_CAN_T_REMOVE_PART_OF_STATION :{WHITE}Non licet partem stationis removere...

View File

@@ -4276,7 +4276,6 @@ STR_ERROR_DRIVE_THROUGH_ON_TOWN_ROAD :{WHITE}... d'St
STR_ERROR_DRIVE_THROUGH_DIRECTION :{WHITE}... Strooss geet an dei falsch Richtung
STR_ERROR_DRIVE_THROUGH_CORNER :{WHITE}... Duerchfahrtstops kënnen keng Kéiren hunn
STR_ERROR_DRIVE_THROUGH_JUNCTION :{WHITE}... Duerchfahrtstops kënnen keng Kräizungen hunn
STR_ERROR_DRIVE_THROUGH_ON_ONEWAY_ROAD :{WHITE}... Einbahnstrooss oder blockéiert
# Station destruction related errors
STR_ERROR_CAN_T_REMOVE_PART_OF_STATION :{WHITE}Kann den Deel vun der Gare net ofrappen...

View File

@@ -4322,7 +4322,6 @@ STR_ERROR_DRIVE_THROUGH_ON_TOWN_ROAD :{WHITE}... denn
STR_ERROR_DRIVE_THROUGH_DIRECTION :{WHITE}... veien vender i feil retning
STR_ERROR_DRIVE_THROUGH_CORNER :{WHITE}... gjennomkjøringsstopper kan ikke ha hjørner
STR_ERROR_DRIVE_THROUGH_JUNCTION :{WHITE}... gjennomkjøringsstopper kan ikke ha kryss
STR_ERROR_DRIVE_THROUGH_ON_ONEWAY_ROAD :{WHITE}... veien er enveiskjørt eller blokkert
# Station destruction related errors
STR_ERROR_CAN_T_REMOVE_PART_OF_STATION :{WHITE}Kan ikke fjerne del av stasjonen...

View File

@@ -4666,7 +4666,6 @@ STR_ERROR_DRIVE_THROUGH_ON_TOWN_ROAD :{WHITE}... ta d
STR_ERROR_DRIVE_THROUGH_DIRECTION :{WHITE}... droga jest zorientowana w złym kierunku
STR_ERROR_DRIVE_THROUGH_CORNER :{WHITE}... przystanki przelotowe nie mogą mieć zakrętów
STR_ERROR_DRIVE_THROUGH_JUNCTION :{WHITE}... przystanki przelotowe nie mogą mieć skrzyżowań
STR_ERROR_DRIVE_THROUGH_ON_ONEWAY_ROAD :{WHITE}... droga jest jednokierunkowa lub zablokowana
# Station destruction related errors
STR_ERROR_CAN_T_REMOVE_PART_OF_STATION :{WHITE}Nie można usunąć części stacji...

View File

@@ -4318,7 +4318,6 @@ STR_ERROR_DRIVE_THROUGH_ON_TOWN_ROAD :{WHITE}... esta
STR_ERROR_DRIVE_THROUGH_DIRECTION :{WHITE}... estrada orientada na direcção incorrecta
STR_ERROR_DRIVE_THROUGH_CORNER :{WHITE}... estações de passagem não podem ter curvas
STR_ERROR_DRIVE_THROUGH_JUNCTION :{WHITE}... estações de passagem não podem ter cruzamentos
STR_ERROR_DRIVE_THROUGH_ON_ONEWAY_ROAD :{WHITE}... estrada de sentido único ou bloqueada
# Station destruction related errors
STR_ERROR_CAN_T_REMOVE_PART_OF_STATION :{WHITE}Não é possível remover parte da estação...

View File

@@ -4507,7 +4507,6 @@ STR_ERROR_DRIVE_THROUGH_ON_TOWN_ROAD :{WHITE}... эт
STR_ERROR_DRIVE_THROUGH_DIRECTION :{WHITE}... неверное направление дороги
STR_ERROR_DRIVE_THROUGH_CORNER :{WHITE}... на проходных остановках нельзя делать повороты
STR_ERROR_DRIVE_THROUGH_JUNCTION :{WHITE}... на проходных остановках нельзя делать перекрёстки
STR_ERROR_DRIVE_THROUGH_ON_ONEWAY_ROAD :{WHITE}... дорога односторонняя или заблокирована
# Station destruction related errors
STR_ERROR_CAN_T_REMOVE_PART_OF_STATION :{WHITE}Невозможно удалить часть станции...

View File

@@ -4443,7 +4443,6 @@ STR_ERROR_DRIVE_THROUGH_ON_TOWN_ROAD :{WHITE}... ova
STR_ERROR_DRIVE_THROUGH_DIRECTION :{WHITE}... ulica je okrenuta u drugom pravcu
STR_ERROR_DRIVE_THROUGH_CORNER :{WHITE}... stajalište ne može biti na krivini
STR_ERROR_DRIVE_THROUGH_JUNCTION :{WHITE}... stajalište ne može biti na raskrsnici
STR_ERROR_DRIVE_THROUGH_ON_ONEWAY_ROAD :{WHITE}... put je jednosmeran ili blokiran.
# Station destruction related errors
STR_ERROR_CAN_T_REMOVE_PART_OF_STATION :{WHITE}Deo stanice se ne može ukloniti...

View File

@@ -4268,7 +4268,6 @@ STR_ERROR_DRIVE_THROUGH_ON_TOWN_ROAD :{WHITE}... esta
STR_ERROR_DRIVE_THROUGH_DIRECTION :{WHITE}... carretera en la dirección incorrecta
STR_ERROR_DRIVE_THROUGH_CORNER :{WHITE}... las estaciones de autobús de paso no pueden tener esquinas
STR_ERROR_DRIVE_THROUGH_JUNCTION :{WHITE}... las estaciones de autobús de paso no pueden tener intersecciones
STR_ERROR_DRIVE_THROUGH_ON_ONEWAY_ROAD :{WHITE}... carretera de un solo sentido o bloqueada
# Station destruction related errors
STR_ERROR_CAN_T_REMOVE_PART_OF_STATION :{WHITE}No se puede retirar parte de la estación...

View File

@@ -4318,7 +4318,6 @@ STR_ERROR_DRIVE_THROUGH_ON_TOWN_ROAD :{WHITE}... esta
STR_ERROR_DRIVE_THROUGH_DIRECTION :{WHITE}... carretera en el sentido incorrecto
STR_ERROR_DRIVE_THROUGH_CORNER :{WHITE}... las estaciones y paradas intermedias no pueden ponerse sobre esquinas
STR_ERROR_DRIVE_THROUGH_JUNCTION :{WHITE}... las estaciones y paradas intermedias no pueden ponerse sobre intersecciones
STR_ERROR_DRIVE_THROUGH_ON_ONEWAY_ROAD :{WHITE}... la carretera está bloqueada o es de un solo sentido
# Station destruction related errors
STR_ERROR_CAN_T_REMOVE_PART_OF_STATION :{WHITE}No se puede quitar parte de la estación...

View File

@@ -4301,7 +4301,6 @@ STR_ERROR_DRIVE_THROUGH_ON_TOWN_ROAD :{WHITE}... dett
STR_ERROR_DRIVE_THROUGH_DIRECTION :{WHITE}... vägen pekar i fel riktning
STR_ERROR_DRIVE_THROUGH_CORNER :{WHITE}... genomfartshållplatser kan inte ha gatuhörn
STR_ERROR_DRIVE_THROUGH_JUNCTION :{WHITE}... genomfartshållplatser kan inte ha korsningar
STR_ERROR_DRIVE_THROUGH_ON_ONEWAY_ROAD :{WHITE}... vägen är enkelriktad eller blockerad
# Station destruction related errors
STR_ERROR_CAN_T_REMOVE_PART_OF_STATION :{WHITE}Kan ej ta bort del av station...

View File

@@ -4310,7 +4310,6 @@ STR_ERROR_DRIVE_THROUGH_ON_TOWN_ROAD :{WHITE}... bu y
STR_ERROR_DRIVE_THROUGH_DIRECTION :{WHITE}... yol yanlış yönde
STR_ERROR_DRIVE_THROUGH_CORNER :{WHITE}... yol üstü duraklar köşe üzerine inşa edilemez
STR_ERROR_DRIVE_THROUGH_JUNCTION :{WHITE}... yol üstü duraklar kavşak üzerine inşa edilemez
STR_ERROR_DRIVE_THROUGH_ON_ONEWAY_ROAD :{WHITE}... yol tek yön ya da engellenmiş
# Station destruction related errors
STR_ERROR_CAN_T_REMOVE_PART_OF_STATION :{WHITE}İstasyonun parçasi kaldırılamaz...

View File

@@ -4446,7 +4446,6 @@ STR_ERROR_DRIVE_THROUGH_ON_TOWN_ROAD :{WHITE}... ця
STR_ERROR_DRIVE_THROUGH_DIRECTION :{WHITE}... дорога не в тому напрямку
STR_ERROR_DRIVE_THROUGH_CORNER :{WHITE}... проїзні зупинки не можуть мати поворотів
STR_ERROR_DRIVE_THROUGH_JUNCTION :{WHITE}... проїзні зупинки не можуть мати перехресть
STR_ERROR_DRIVE_THROUGH_ON_ONEWAY_ROAD :{WHITE}... дорога одностороння або заблокована
# Station destruction related errors
STR_ERROR_CAN_T_REMOVE_PART_OF_STATION :{WHITE}Не можна зруйнувати частину станції...

View File

@@ -4279,7 +4279,6 @@ STR_ERROR_DRIVE_THROUGH_ON_TOWN_ROAD :{WHITE}... đâ
STR_ERROR_DRIVE_THROUGH_DIRECTION :{WHITE}... đường quay mặt sai hướng
STR_ERROR_DRIVE_THROUGH_CORNER :{WHITE}... đi qua điểm dừng không thể đi qua góc
STR_ERROR_DRIVE_THROUGH_JUNCTION :{WHITE}... đi qua điểm dừng không thể có ngã rẽ
STR_ERROR_DRIVE_THROUGH_ON_ONEWAY_ROAD :{WHITE}... đường 1 chiều hoặc bị chặn
# Station destruction related errors
STR_ERROR_CAN_T_REMOVE_PART_OF_STATION :{WHITE}Không thể xoá bỏ một phần của ga...

View File

@@ -205,6 +205,16 @@ void ZoomInOrOutToCursorWindow(bool in, Window *w)
}
}
void FixTitleGameZoom()
{
if (_game_mode != GM_MENU) return;
ViewPort *vp = FindWindowByClass(WC_MAIN_WINDOW)->viewport;
vp->zoom = _gui_zoom;
vp->virtual_width = ScaleByZoom(vp->width, vp->zoom);
vp->virtual_height = ScaleByZoom(vp->height, vp->zoom);
}
static const struct NWidgetPart _nested_main_window_widgets[] = {
NWidget(NWID_VIEWPORT, INVALID_COLOUR, WID_M_VIEWPORT), SetResize(1, 1),
};

View File

@@ -538,19 +538,19 @@ static void TransmitChannelMsg(IDirectMusicBuffer *buffer, REFERENCE_TIME rt, by
}
}
static void TransmitSysex(IDirectMusicBuffer *buffer, REFERENCE_TIME rt, byte *&msg_start, size_t &remaining)
static void TransmitSysex(IDirectMusicBuffer *buffer, REFERENCE_TIME rt, const byte *&msg_start, size_t &remaining)
{
/* Find end of message. */
byte *msg_end = msg_start;
const byte *msg_end = msg_start;
while (*msg_end != MIDIST_ENDSYSEX) msg_end++;
msg_end++; // Also include SysEx end byte.
if (buffer->PackUnstructured(rt, 0, msg_end - msg_start, msg_start) == E_OUTOFMEMORY) {
if (buffer->PackUnstructured(rt, 0, msg_end - msg_start, const_cast<LPBYTE>(msg_start)) == E_OUTOFMEMORY) {
/* Buffer is full, clear it and try again. */
_port->PlayBuffer(buffer);
buffer->Flush();
buffer->PackUnstructured(rt, 0, msg_end - msg_start, msg_start);
buffer->PackUnstructured(rt, 0, msg_end - msg_start, const_cast<LPBYTE>(msg_start));
}
/* Update position in buffer. */
@@ -558,9 +558,11 @@ static void TransmitSysex(IDirectMusicBuffer *buffer, REFERENCE_TIME rt, byte *&
msg_start = msg_end;
}
static void TransmitSysexConst(IDirectMusicBuffer *buffer, REFERENCE_TIME rt, byte *msg_start, size_t length)
static void TransmitStandardSysex(IDirectMusicBuffer *buffer, REFERENCE_TIME rt, MidiSysexMessage msg)
{
TransmitSysex(buffer, rt, msg_start, length);
size_t length = 0;
const byte *data = MidiGetStandardSysexMessage(msg, length);
TransmitSysex(buffer, rt, data, length);
}
/** Transmit 'Note off' messages to all MIDI channels. */
@@ -571,27 +573,16 @@ static void TransmitNotesOff(IDirectMusicBuffer *buffer, REFERENCE_TIME block_ti
TransmitChannelMsg(_buffer, block_time + 10, MIDIST_CONTROLLER | ch, MIDICT_SUSTAINSW, 0);
TransmitChannelMsg(_buffer, block_time + 10, MIDIST_CONTROLLER | ch, MIDICT_MODE_RESETALLCTRL, 0);
}
/* Explicitly flush buffer to make sure the note off messages are processed
* before we send any additional control messages. */
/* Performing a GM reset stops all sound and resets all parameters. */
TransmitStandardSysex(_buffer, block_time + 20, MidiSysexMessage::ResetGM);
TransmitStandardSysex(_buffer, block_time + 30, MidiSysexMessage::RolandSetReverb);
/* Explicitly flush buffer to make sure the messages are processed,
* as we want sound to stop immediately. */
_port->PlayBuffer(_buffer);
_buffer->Flush();
/* Some songs change the "Pitch bend range" registered parameter. If
* this doesn't get reset, everything else will start sounding wrong. */
for (int ch = 0; ch < 16; ch++) {
/* Running status, only need status for first message
* Select RPN 00.00, set value to 02.00, and de-select again */
TransmitChannelMsg(_buffer, block_time + 10, MIDIST_CONTROLLER | ch, MIDICT_RPN_SELECT_LO, 0x00);
TransmitChannelMsg(_buffer, block_time + 10, MIDICT_RPN_SELECT_HI, 0x00);
TransmitChannelMsg(_buffer, block_time + 10, MIDICT_DATAENTRY, 0x02);
TransmitChannelMsg(_buffer, block_time + 10, MIDICT_DATAENTRY_LO, 0x00);
TransmitChannelMsg(_buffer, block_time + 10, MIDICT_RPN_SELECT_LO, 0x7F);
TransmitChannelMsg(_buffer, block_time + 10, MIDICT_RPN_SELECT_HI, 0x7F);
_port->PlayBuffer(_buffer);
_buffer->Flush();
}
/* Wait until message time has passed. */
Sleep(Clamp((block_time - cur_time) / MS_TO_REFTIME, 5, 1000));
}
@@ -616,13 +607,6 @@ static void MidiThreadProc(void *)
REFERENCE_TIME cur_time;
clock->GetTime(&cur_time);
/* Standard "Enable General MIDI" message */
static byte gm_enable_sysex[] = { 0xF0, 0x7E, 0x00, 0x09, 0x01, 0xF7 };
TransmitSysexConst(_buffer, cur_time, &gm_enable_sysex[0], sizeof(gm_enable_sysex));
/* Roland-specific reverb room control, used by the original game */
static byte roland_reverb_sysex[] = { 0xF0, 0x41, 0x10, 0x42, 0x12, 0x40, 0x01, 0x30, 0x02, 0x04, 0x00, 0x40, 0x40, 0x00, 0x00, 0x09, 0xF7 };
TransmitSysexConst(_buffer, cur_time, &roland_reverb_sysex[0], sizeof(roland_reverb_sysex));
_port->PlayBuffer(_buffer);
_buffer->Flush();
@@ -665,7 +649,7 @@ static void MidiThreadProc(void *)
_playback.do_start = false;
}
/* Turn all notes off in case we are seeking between music titles. */
/* Reset playback device between songs. */
clock->GetTime(&cur_time);
TransmitNotesOff(_buffer, block_time, cur_time);
@@ -751,7 +735,7 @@ static void MidiThreadProc(void *)
block_time = playback_start_time + block.realtime * MIDITIME_TO_REFTIME;
DEBUG(driver, 9, "DMusic thread: Streaming block " PRINTF_SIZE " (cur=" OTTD_PRINTF64 ", block=" OTTD_PRINTF64 ")", current_block, (long long)(current_time / MS_TO_REFTIME), (long long)(block_time / MS_TO_REFTIME));
byte *data = block.data.Begin();
const byte *data = block.data.Begin();
size_t remaining = block.data.Length();
byte last_status = 0;
while (remaining > 0) {

View File

@@ -141,4 +141,19 @@ enum MidiController {
MIDICT_MODE_POLY = 127,
};
/** Well-known MIDI system exclusive message values for use with the MidiGetStandardSysexMessage function. */
enum class MidiSysexMessage {
/** Reset device to General MIDI defaults */
ResetGM,
/** Reset device to (Roland) General Standard defaults */
ResetGS,
/** Reset device to (Yamaha) XG defaults */
ResetXG,
/** Set up Roland SoundCanvas reverb room as TTD does */
RolandSetReverb,
};
const byte *MidiGetStandardSysexMessage(MidiSysexMessage msg, size_t &length);
#endif /* MUSIC_MIDI_H */

View File

@@ -27,6 +27,37 @@
static MidiFile *_midifile_instance = NULL;
/**
* Retrieve a well-known MIDI system exclusive message.
* @param msg Which sysex message to retrieve
* @param[out] length Receives the length of the returned buffer
* @return Pointer to byte buffer with sysex message
*/
const byte *MidiGetStandardSysexMessage(MidiSysexMessage msg, size_t &length)
{
static byte reset_gm_sysex[] = { 0xF0, 0x7E, 0x7F, 0x09, 0x01, 0xF7 };
static byte reset_gs_sysex[] = { 0xF0, 0x41, 0x10, 0x42, 0x12, 0x40, 0x00, 0x7F, 0x00, 0x41, 0xF7 };
static byte reset_xg_sysex[] = { 0xF0, 0x43, 0x10, 0x4C, 0x00, 0x00, 0x7E, 0x00, 0xF7 };
static byte roland_reverb_sysex[] = { 0xF0, 0x41, 0x10, 0x42, 0x12, 0x40, 0x01, 0x30, 0x02, 0x04, 0x00, 0x40, 0x40, 0x00, 0x00, 0x09, 0xF7 };
switch (msg) {
case MidiSysexMessage::ResetGM:
length = lengthof(reset_gm_sysex);
return reset_gm_sysex;
case MidiSysexMessage::ResetGS:
length = lengthof(reset_gs_sysex);
return reset_gs_sysex;
case MidiSysexMessage::ResetXG:
length = lengthof(reset_xg_sysex);
return reset_xg_sysex;
case MidiSysexMessage::RolandSetReverb:
length = lengthof(roland_reverb_sysex);
return roland_reverb_sysex;
default:
NOT_REACHED();
}
}
/**
* Owning byte buffer readable as a stream.
* RAII-compliant to make teardown in error situations easier.

View File

@@ -35,7 +35,7 @@ static struct {
CRITICAL_SECTION lock; ///< synchronization for playback status fields
bool playing; ///< flag indicating that playback is active
bool do_start; ///< flag for starting playback of next_file at next opportunity
int do_start; ///< flag for starting playback of next_file at next opportunity
bool do_stop; ///< flag for stopping playback at next opportunity
byte current_volume; ///< current effective volume setting
byte new_volume; ///< volume setting to change to
@@ -73,10 +73,10 @@ static void TransmitChannelMsg(byte status, byte p1, byte p2 = 0)
midiOutShortMsg(_midi.midi_out, status | (p1 << 8) | (p2 << 16));
}
static void TransmitSysex(byte *&msg_start, size_t &remaining)
static void TransmitSysex(const byte *&msg_start, size_t &remaining)
{
/* find end of message */
byte *msg_end = msg_start;
const byte *msg_end = msg_start;
while (*msg_end != MIDIST_ENDSYSEX) msg_end++;
msg_end++; /* also include sysex end byte */
@@ -97,9 +97,11 @@ static void TransmitSysex(byte *&msg_start, size_t &remaining)
msg_start = msg_end;
}
static void TransmitSysexConst(byte *msg_start, size_t length)
static void TransmitStandardSysex(MidiSysexMessage msg)
{
TransmitSysex(msg_start, length);
size_t length = 0;
const byte *data = MidiGetStandardSysexMessage(msg, length);
TransmitSysex(data, length);
}
/**
@@ -108,82 +110,94 @@ static void TransmitSysexConst(byte *msg_start, size_t length)
*/
void CALLBACK TimerCallback(UINT uTimerID, UINT, DWORD_PTR dwUser, DWORD_PTR, DWORD_PTR)
{
/* Try to check playback status changes.
* If _midi is already locked, skip checking for this cycle and try again
* next cycle, instead of waiting for locks in the realtime callback. */
if (TryEnterCriticalSection(&_midi.lock)) {
/* check for stop */
if (_midi.do_stop) {
DEBUG(driver, 2, "Win32-MIDI: timer: do_stop is set");
midiOutReset(_midi.midi_out);
_midi.playing = false;
_midi.do_stop = false;
/* Ensure only one timer callback is running at once, and prevent races on status flags */
if (!TryEnterCriticalSection(&_midi.lock)) return;
/* check for stop */
if (_midi.do_stop) {
DEBUG(driver, 2, "Win32-MIDI: timer: do_stop is set");
midiOutReset(_midi.midi_out);
_midi.playing = false;
_midi.do_stop = false;
LeaveCriticalSection(&_midi.lock);
return;
}
/* check for start/restart/change song */
if (_midi.do_start != 0) {
/* Have a delay between playback start steps, prevents jumbled-together notes at the start of song */
if (timeGetTime() - _midi.playback_start_time < 50) {
LeaveCriticalSection(&_midi.lock);
return;
}
DEBUG(driver, 2, "Win32-MIDI: timer: do_start step %d", _midi.do_start);
/* check for start/restart/change song */
if (_midi.do_start) {
DEBUG(driver, 2, "Win32-MIDI: timer: do_start is set");
if (_midi.playing) {
midiOutReset(_midi.midi_out);
/* Some songs change the "Pitch bend range" registered
* parameter. If this doesn't get reset, everything else
* will start sounding wrong. */
for (int ch = 0; ch < 16; ch++) {
/* Running status, only need status for first message */
/* Select RPN 00.00, set value to 02.00, and unselect again */
TransmitChannelMsg(MIDIST_CONTROLLER | ch, MIDICT_RPN_SELECT_LO, 0x00);
TransmitChannelMsg(MIDICT_RPN_SELECT_HI, 0x00);
TransmitChannelMsg(MIDICT_DATAENTRY, 0x02);
TransmitChannelMsg(MIDICT_DATAENTRY_LO, 0x00);
TransmitChannelMsg(MIDICT_RPN_SELECT_LO, 0x7F);
TransmitChannelMsg(MIDICT_RPN_SELECT_HI, 0x7F);
}
}
if (_midi.do_start == 1) {
/* Send "all notes off" */
midiOutReset(_midi.midi_out);
_midi.playback_start_time = timeGetTime();
_midi.do_start = 2;
LeaveCriticalSection(&_midi.lock);
return;
} else if (_midi.do_start == 2) {
/* Reset the device to General MIDI defaults */
TransmitStandardSysex(MidiSysexMessage::ResetGM);
_midi.playback_start_time = timeGetTime();
_midi.do_start = 3;
LeaveCriticalSection(&_midi.lock);
return;
} else if (_midi.do_start == 3) {
/* Set up device-specific effects */
TransmitStandardSysex(MidiSysexMessage::RolandSetReverb);
_midi.playback_start_time = timeGetTime();
_midi.do_start = 4;
LeaveCriticalSection(&_midi.lock);
return;
} else if (_midi.do_start == 4) {
/* Load the new file */
_midi.current_file.MoveFrom(_midi.next_file);
std::swap(_midi.next_segment, _midi.current_segment);
_midi.current_segment.start_block = 0;
_midi.playback_start_time = timeGetTime();
_midi.playing = true;
_midi.do_start = false;
_midi.do_start = 0;
_midi.current_block = 0;
MemSetT<byte>(_midi.channel_volumes, 127, lengthof(_midi.channel_volumes));
} else if (!_midi.playing) {
/* not playing, stop the timer */
DEBUG(driver, 2, "Win32-MIDI: timer: not playing, stopping timer");
timeKillEvent(uTimerID);
_midi.timer_id = 0;
LeaveCriticalSection(&_midi.lock);
return;
}
/* check for volume change */
static int volume_throttle = 0;
if (_midi.current_volume != _midi.new_volume) {
if (volume_throttle == 0) {
DEBUG(driver, 2, "Win32-MIDI: timer: volume change");
_midi.current_volume = _midi.new_volume;
volume_throttle = 20 / _midi.time_period;
for (int ch = 0; ch < 16; ch++) {
int vol = ScaleVolume(_midi.channel_volumes[ch], _midi.current_volume);
TransmitChannelMsg(MIDIST_CONTROLLER | ch, MIDICT_CHANVOLUME, vol);
}
}
else {
volume_throttle--;
}
}
} else if (!_midi.playing) {
/* not playing, stop the timer */
DEBUG(driver, 2, "Win32-MIDI: timer: not playing, stopping timer");
timeKillEvent(uTimerID);
_midi.timer_id = 0;
LeaveCriticalSection(&_midi.lock);
return;
}
/* check for volume change */
static int volume_throttle = 0;
if (_midi.current_volume != _midi.new_volume) {
if (volume_throttle == 0) {
DEBUG(driver, 2, "Win32-MIDI: timer: volume change");
_midi.current_volume = _midi.new_volume;
volume_throttle = 20 / _midi.time_period;
for (int ch = 0; ch < 16; ch++) {
byte vol = ScaleVolume(_midi.channel_volumes[ch], _midi.current_volume);
TransmitChannelMsg(MIDIST_CONTROLLER | ch, MIDICT_CHANVOLUME, vol);
}
} else {
volume_throttle--;
}
}
/* skip beginning of file? */
if (_midi.current_segment.start > 0 && _midi.current_block == 0 && _midi.current_segment.start_block == 0) {
/* find first block after start time and pretend playback started earlier
* this is to allow all blocks prior to the actual start to still affect playback,
* as they may contain important controller and program changes */
* this is to allow all blocks prior to the actual start to still affect playback,
* as they may contain important controller and program changes */
uint preload_bytes = 0;
for (size_t bl = 0; bl < _midi.current_file.blocks.size(); bl++) {
MidiFile::DataBlock &block = _midi.current_file.blocks[bl];
@@ -200,7 +214,7 @@ void CALLBACK TimerCallback(UINT uTimerID, UINT, DWORD_PTR dwUser, DWORD_PTR, DW
* The delay compensation is needed to avoid time-compression of following messages.
*/
DEBUG(driver, 2, "Win32-MIDI: timer: start from block %d (ticktime %d, realtime %.3f, bytes %d)", (int)bl, (int)block.ticktime, ((int)block.realtime) / 1000.0, (int)preload_bytes);
_midi.playback_start_time -= block.realtime / 1000 - preload_bytes * 1000 / 3125;
_midi.playback_start_time -= block.realtime / 1000 - (DWORD)(preload_bytes * 1000 / 3125);
break;
}
}
@@ -229,7 +243,7 @@ void CALLBACK TimerCallback(UINT uTimerID, UINT, DWORD_PTR dwUser, DWORD_PTR, DW
break;
}
byte *data = block.data.Begin();
const byte *data = block.data.Begin();
size_t remaining = block.data.Length();
byte last_status = 0;
while (remaining > 0) {
@@ -308,25 +322,28 @@ void CALLBACK TimerCallback(UINT uTimerID, UINT, DWORD_PTR dwUser, DWORD_PTR, DW
_midi.do_stop = true;
}
}
LeaveCriticalSection(&_midi.lock);
}
void MusicDriver_Win32::PlaySong(const MusicSongInfo &song)
{
DEBUG(driver, 2, "Win32-MIDI: PlaySong: entry");
MidiFile new_song;
if (!new_song.LoadSong(song)) return;
DEBUG(driver, 2, "Win32-MIDI: PlaySong: Loaded song");
EnterCriticalSection(&_midi.lock);
if (!_midi.next_file.LoadSong(song)) {
LeaveCriticalSection(&_midi.lock);
return;
}
_midi.next_file.MoveFrom(new_song);
_midi.next_segment.start = song.override_start;
_midi.next_segment.end = song.override_end;
_midi.next_segment.loop = song.loop;
DEBUG(driver, 2, "Win32-MIDI: PlaySong: setting flag");
_midi.do_stop = _midi.playing;
_midi.do_start = true;
_midi.do_start = 1;
if (_midi.timer_id == 0) {
DEBUG(driver, 2, "Win32-MIDI: PlaySong: starting timer");
@@ -347,7 +364,7 @@ void MusicDriver_Win32::StopSong()
bool MusicDriver_Win32::IsSongPlaying()
{
return _midi.playing || _midi.do_start;
return _midi.playing || (_midi.do_start != 0);
}
void MusicDriver_Win32::SetVolume(byte vol)
@@ -381,14 +398,6 @@ const char *MusicDriver_Win32::Start(const char * const *parm)
midiOutReset(_midi.midi_out);
/* Standard "Enable General MIDI" message */
static byte gm_enable_sysex[] = { 0xF0, 0x7E, 0x00, 0x09, 0x01, 0xF7 };
TransmitSysexConst(&gm_enable_sysex[0], sizeof(gm_enable_sysex));
/* Roland-specific reverb room control, used by the original game */
static byte roland_reverb_sysex[] = { 0xF0, 0x41, 0x10, 0x42, 0x12, 0x40, 0x01, 0x30, 0x02, 0x04, 0x00, 0x40, 0x40, 0x00, 0x00, 0x09, 0xF7 };
TransmitSysexConst(&roland_reverb_sysex[0], sizeof(roland_reverb_sysex));
/* prepare multimedia timer */
TIMECAPS timecaps;
if (timeGetDevCaps(&timecaps, sizeof(timecaps)) == MMSYSERR_NOERROR) {

View File

@@ -5480,7 +5480,8 @@ static void RailTypeMapSpriteGroup(ByteReader *buf, uint8 idcount)
{
uint8 *railtypes = AllocaM(uint8, idcount);
for (uint i = 0; i < idcount; i++) {
railtypes[i] = _cur.grffile->railtype_map[buf->ReadByte()];
uint8 id = buf->ReadByte();
railtypes[i] = id < RAILTYPE_END ? _cur.grffile->railtype_map[id] : INVALID_RAILTYPE;
}
uint8 cidcount = buf->ReadByte();

View File

@@ -163,7 +163,7 @@ struct GRFLoadedFeatures {
uint64 used_liveries; ///< Bitmask of #LiveryScheme used by the defined engines.
bool has_newhouses; ///< Set if there are any newhouses loaded.
bool has_newindustries; ///< Set if there are any newindustries loaded.
ShoreReplacement shore; ///< It which way shore sprites were replaced.
ShoreReplacement shore; ///< In which way shore sprites were replaced.
};
/**

View File

@@ -45,8 +45,8 @@ const NewsItem *_statusbar_news_item = NULL;
static uint MIN_NEWS_AMOUNT = 30; ///< preferred minimum amount of news messages
static uint _total_news = 0; ///< current number of news items
NewsItem *_oldest_news = NULL; ///< head of news items queue
static NewsItem *_latest_news = NULL; ///< tail of news items queue
static NewsItem *_oldest_news = NULL; ///< head of news items queue
NewsItem *_latest_news = NULL; ///< tail of news items queue
/**
* Forced news item.
@@ -54,7 +54,7 @@ static NewsItem *_latest_news = NULL; ///< tail of news items queue
* If the message being shown was forced by the user, a pointer is stored
* in _forced_news. Otherwise, \a _forced_news variable is NULL.
*/
static const NewsItem *_forced_news = NULL; ///< item the user has asked for
static const NewsItem *_forced_news = NULL;
/** Current news item (last item shown regularly). */
static const NewsItem *_current_news = NULL;
@@ -331,6 +331,11 @@ struct NewsWindow : Window {
*size = maxdim(*size, GetSpriteSize(SPR_GRADIENT));
break;
case WID_N_MGR_NAME:
SetDParamStr(0, static_cast<const CompanyNewsInformation *>(this->ni->free_data)->president_name);
str = STR_JUST_RAW_STRING;
break;
case WID_N_MESSAGE:
CopyInDParam(0, this->ni->params, lengthof(this->ni->params));
str = this->ni->string_id;

View File

@@ -17,6 +17,6 @@
void ShowLastNewsMessage();
void ShowMessageHistory();
extern NewsItem *_oldest_news;
extern NewsItem *_latest_news;
#endif /* NEWS_GUI_H */

View File

@@ -62,6 +62,7 @@
#include "town.h"
#include "subsidy_func.h"
#include "gfx_layout.h"
#include "viewport_func.h"
#include "viewport_sprite_sorter.h"
#include "framerate_type.h"
@@ -339,6 +340,7 @@ static void LoadIntroGame(bool load_newgrfs = true)
SetLocalCompany(COMPANY_FIRST);
}
FixTitleGameZoom();
_pause_mode = PM_UNPAUSED;
_cursor.fix_at = false;

View File

@@ -203,7 +203,7 @@ public:
char message[1024];
seprintf(message, lastof(message),
"Please send the generated crash information and the last (auto)save to the developers. "
"This will greatly help debugging. The correct place to do this is http://bugs.openttd.org.\n\n"
"This will greatly help debugging. The correct place to do this is https://github.com/OpenTTD/OpenTTD/issues.\n\n"
"Generated file(s):\n%s\n%s\n%s",
this->filename_log, this->filename_save, this->filename_screenshot);

View File

@@ -582,7 +582,7 @@ static bool _expanded;
static const TCHAR _crash_desc[] =
_T("A serious fault condition occurred in the game. The game will shut down.\n")
_T("Please send the crash information and the crash.dmp file (if any) to the developers.\n")
_T("This will greatly help debugging. The correct place to do this is http://bugs.openttd.org. ")
_T("This will greatly help debugging. The correct place to do this is https://github.com/OpenTTD/OpenTTD/issues. ")
_T("The information contained in the report is displayed below.\n")
_T("Press \"Emergency save\" to attempt saving the game. Generated file(s):\n")
_T("%s");

View File

@@ -79,8 +79,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,9,1,!!ISODATE!!
PRODUCTVERSION 1,9,1,!!ISODATE!!
FILEVERSION 1,9,2,!!ISODATE!!
PRODUCTVERSION 1,9,2,!!ISODATE!!
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L

View File

@@ -1565,6 +1565,7 @@ CommandCost CmdConvertRail(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
CommandCost cost(EXPENSES_CONSTRUCTION);
CommandCost error = CommandCost(STR_ERROR_NO_SUITABLE_RAILROAD_TRACK); // by default, there is no track to convert.
bool found_convertible_track = false; // whether we actually did convert some track (see bug #7633)
TileIterator *iter = diagonal ? (TileIterator *)new DiagonalTileIterator(area_start, area_end) : new OrthogonalTileIterator(area_start, area_end);
for (; (tile = *iter) != INVALID_TILE; ++(*iter)) {
@@ -1660,6 +1661,7 @@ CommandCost CmdConvertRail(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
InvalidateWindowData(WC_VEHICLE_DEPOT, tile);
InvalidateWindowData(WC_BUILD_VEHICLE, tile);
}
found_convertible_track = true;
cost.AddCost(RailConvertCost(type, totype));
break;
@@ -1671,6 +1673,7 @@ CommandCost CmdConvertRail(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
YapfNotifyTrackLayoutChange(tile, RemoveFirstTrack(&tracks));
}
}
found_convertible_track = true;
cost.AddCost(RailConvertCost(type, totype) * CountBits(GetTrackBits(tile)));
break;
}
@@ -1733,6 +1736,7 @@ CommandCost CmdConvertRail(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
}
}
found_convertible_track = true;
cost.AddCost((GetTunnelBridgeLength(tile, endtile) + 2) * RailConvertCost(type, totype));
break;
}
@@ -1743,6 +1747,7 @@ CommandCost CmdConvertRail(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
YapfNotifyTrackLayoutChange(tile, track);
}
found_convertible_track = true;
cost.AddCost(RailConvertCost(type, totype));
break;
}
@@ -1760,7 +1765,7 @@ CommandCost CmdConvertRail(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
}
delete iter;
return (cost.GetCost() == 0) ? error : cost;
return found_convertible_track ? cost : error;
}
static CommandCost RemoveTrainDepot(TileIndex tile, DoCommandFlag flags)

View File

@@ -82,7 +82,7 @@ const byte _openttd_revision_tagged = !!ISTAG!!;
* final release will always have a lower version number than the released
* version, thus making comparisons on specific revisions easy.
*/
const uint32 _openttd_newgrf_version = 1 << 28 | 9 << 24 | 1 << 20 | !!ISSTABLETAG!! << 19 | 28004;
const uint32 _openttd_newgrf_version = 1 << 28 | 9 << 24 | 2 << 20 | !!ISSTABLETAG!! << 19 | 28004;
#ifdef __MORPHOS__
/**

View File

@@ -1132,6 +1132,38 @@ bool AfterLoadGame()
}
}
/* Railtype moved from m3 to m8 in version SLV_EXTEND_RAILTYPES. */
if (IsSavegameVersionBefore(SLV_EXTEND_RAILTYPES)) {
for (TileIndex t = 0; t < map_size; t++) {
switch (GetTileType(t)) {
case MP_RAILWAY:
SetRailType(t, (RailType)GB(_m[t].m3, 0, 4));
break;
case MP_ROAD:
if (IsLevelCrossing(t)) {
SetRailType(t, (RailType)GB(_m[t].m3, 0, 4));
}
break;
case MP_STATION:
if (HasStationRail(t)) {
SetRailType(t, (RailType)GB(_m[t].m3, 0, 4));
}
break;
case MP_TUNNELBRIDGE:
if (GetTunnelBridgeTransportType(t) == TRANSPORT_RAIL) {
SetRailType(t, (RailType)GB(_m[t].m3, 0, 4));
}
break;
default:
break;
}
}
}
if (IsSavegameVersionBefore(SLV_42)) {
Vehicle *v;
@@ -1213,38 +1245,6 @@ bool AfterLoadGame()
}
}
/* Railtype moved from m3 to m8 in version SLV_EXTEND_RAILTYPES. */
if (IsSavegameVersionBefore(SLV_EXTEND_RAILTYPES)) {
for (TileIndex t = 0; t < map_size; t++) {
switch (GetTileType(t)) {
case MP_RAILWAY:
SetRailType(t, (RailType)GB(_m[t].m3, 0, 4));
break;
case MP_ROAD:
if (IsLevelCrossing(t)) {
SetRailType(t, (RailType)GB(_m[t].m3, 0, 4));
}
break;
case MP_STATION:
if (HasStationRail(t)) {
SetRailType(t, (RailType)GB(_m[t].m3, 0, 4));
}
break;
case MP_TUNNELBRIDGE:
if (GetTunnelBridgeTransportType(t) == TRANSPORT_RAIL) {
SetRailType(t, (RailType)GB(_m[t].m3, 0, 4));
}
break;
default:
break;
}
}
}
/* Elrails got added in rev 24 */
if (IsSavegameVersionBefore(SLV_24)) {
RailType min_rail = RAILTYPE_ELECTRIC;
@@ -1893,6 +1893,7 @@ bool AfterLoadGame()
}
if (IsSavegameVersionBefore(SLV_62)) {
GroupStatistics::UpdateAfterLoad(); // Ensure statistics pool is initialised before trying to delete vehicles
/* Remove all trams from savegames without tram support.
* There would be trams without tram track under causing crashes sooner or later. */
RoadVehicle *v;
@@ -2304,6 +2305,14 @@ bool AfterLoadGame()
if (IsSavegameVersionBefore(SLV_128)) {
const Depot *d;
FOR_ALL_DEPOTS(d) {
/* At some point, invalid depots were saved into the game (possibly those removed in the past?)
* Remove them here, so they don't cause issues further down the line */
if (!IsDepotTile(d->xy)) {
DEBUG(sl, 0, "Removing invalid depot %d at %d, %d", d->index, TileX(d->xy), TileY(d->xy));
delete d;
d = nullptr;
continue;
}
_m[d->xy].m2 = d->index;
if (IsTileType(d->xy, MP_WATER)) _m[GetOtherShipDepotTile(d->xy)].m2 = d->index;
}

View File

@@ -233,7 +233,8 @@ void AfterLoadLinkGraphs()
LinkGraph *lg;
FOR_ALL_LINK_GRAPHS(lg) {
for (NodeID node_id = 0; node_id < lg->Size(); ++node_id) {
(*lg)[node_id].UpdateLocation(Station::Get((*lg)[node_id].Station())->xy);
const Station *st = Station::GetIfValid((*lg)[node_id].Station());
if (st != nullptr) (*lg)[node_id].UpdateLocation(st->xy);
}
}
@@ -241,7 +242,8 @@ void AfterLoadLinkGraphs()
FOR_ALL_LINK_GRAPH_JOBS(lgj) {
lg = &(const_cast<LinkGraph &>(lgj->Graph()));
for (NodeID node_id = 0; node_id < lg->Size(); ++node_id) {
(*lg)[node_id].UpdateLocation(Station::Get((*lg)[node_id].Station())->xy);
const Station *st = Station::GetIfValid((*lg)[node_id].Station());
if (st != nullptr) (*lg)[node_id].UpdateLocation(st->xy);
}
}
}

View File

@@ -2889,36 +2889,3 @@ void FileToSaveLoad::SetTitle(const char *title)
{
strecpy(this->title, title, lastof(this->title));
}
#if 0
/**
* Function to get the type of the savegame by looking at the file header.
* NOTICE: Not used right now, but could be used if extensions of savegames are garbled
* @param file Savegame to be checked
* @return SL_OLD_LOAD or SL_LOAD of the file
*/
int GetSavegameType(char *file)
{
const SaveLoadFormat *fmt;
uint32 hdr;
FILE *f;
int mode = SL_OLD_LOAD;
f = fopen(file, "rb");
if (fread(&hdr, sizeof(hdr), 1, f) != 1) {
DEBUG(sl, 0, "Savegame is obsolete or invalid format");
mode = SL_LOAD; // don't try to get filename, just show name as it is written
} else {
/* see if we have any loader for this type. */
for (fmt = _saveload_formats; fmt != endof(_saveload_formats); fmt++) {
if (fmt->tag == hdr) {
mode = SL_LOAD; // new type of savegame
break;
}
}
}
fclose(f);
return mode;
}
#endif

View File

@@ -109,7 +109,7 @@
return g != NULL && g->completed;
}
/* static */ bool ScriptGoal::DoQuestion(uint16 uniqueid, uint8 target, bool is_client, Text *question, QuestionType type, int buttons)
/* static */ bool ScriptGoal::DoQuestion(uint16 uniqueid, uint32 target, bool is_client, Text *question, QuestionType type, uint32 buttons)
{
CCountedPtr<Text> counter(question);
@@ -121,7 +121,7 @@
EnforcePrecondition(false, buttons < (1 << ::GOAL_QUESTION_BUTTON_COUNT));
EnforcePrecondition(false, (int)type < ::GOAL_QUESTION_TYPE_COUNT);
return ScriptObject::DoCommand(0, uniqueid | (target << 16) | (type << 24) | (is_client ? (1 << 31) : 0), buttons, CMD_GOAL_QUESTION, text);
return ScriptObject::DoCommand(0, uniqueid | (target << 16), buttons | (type << 29) | (is_client ? (1 << 31) : 0), CMD_GOAL_QUESTION, text);
}
/* static */ bool ScriptGoal::Question(uint16 uniqueid, ScriptCompany::CompanyID company, Text *question, QuestionType type, int buttons)
@@ -138,8 +138,9 @@
EnforcePrecondition(false, ScriptGame::IsMultiplayer());
EnforcePrecondition(false, ScriptClient::ResolveClientID(client) != ScriptClient::CLIENT_INVALID);
#ifdef ENABLE_NETWORK
ClientIndex c = NetworkClientInfo::GetByClientID((::ClientID)client)->index;
return DoQuestion(uniqueid, c, true, question, type, buttons);
/* Can only send 16 bits of client_id before proper fix is implemented */
EnforcePrecondition(false, client < (1 << 16));
return DoQuestion(uniqueid, client, true, question, type, buttons);
#else
return false;
#endif

View File

@@ -211,7 +211,7 @@ protected:
/**
* Does common checks and asks the question.
*/
static bool DoQuestion(uint16 uniqueid, uint8 target, bool is_client, Text *question, QuestionType type, int buttons);
static bool DoQuestion(uint16 uniqueid, uint32 target, bool is_client, Text *question, QuestionType type, uint32 buttons);
};
#endif /* SCRIPT_GOAL_HPP */

View File

@@ -16,6 +16,7 @@
#include "script_station.hpp"
#include "../../depot_map.h"
#include "../../vehicle_base.h"
#include "../../train.h"
#include "../../safeguards.h"
@@ -23,7 +24,7 @@ ScriptVehicleList::ScriptVehicleList()
{
const Vehicle *v;
FOR_ALL_VEHICLES(v) {
if ((v->owner == ScriptObject::GetCompany() || ScriptObject::GetCompany() == OWNER_DEITY) && v->IsPrimaryVehicle()) this->AddItem(v->index);
if ((v->owner == ScriptObject::GetCompany() || ScriptObject::GetCompany() == OWNER_DEITY) && (v->IsPrimaryVehicle() || (v->type == VEH_TRAIN && ::Train::From(v)->IsFreeWagon()))) this->AddItem(v->index);
}
}

View File

@@ -37,6 +37,7 @@
#include "stringfilter_type.h"
#include "querystring_gui.h"
#include "fontcache.h"
#include "zoom_func.h"
#include <vector>
@@ -557,6 +558,7 @@ struct GameOptionsWindow : Window {
_gui_zoom = (ZoomLevel)(ZOOM_LVL_OUT_4X - index);
UpdateCursorSize();
UpdateAllVirtCoords();
FixTitleGameZoom();
ReInitAllWindows();
break;

View File

@@ -995,9 +995,12 @@ static CommandCost CheckFlatLandRoadStop(TileArea tile_area, DoCommandFlag flags
if (ret.Failed()) return ret;
}
num_roadbits += CountBits(GetRoadBits(cur_tile, ROADTYPE_ROAD));
}
if (GetDisallowedRoadDirections(cur_tile) != DRD_NONE) return_cmd_error(STR_ERROR_DRIVE_THROUGH_ON_ONEWAY_ROAD);
if (GetDisallowedRoadDirections(cur_tile) != DRD_NONE) {
CommandCost ret = CheckOwnership(road_owner);
if (ret.Failed()) return ret;
}
}
/* There is a tram, check if we can build road+tram stop over it. */
if (HasBit(cur_rts, ROADTYPE_TRAM)) {

View File

@@ -27,6 +27,7 @@
#include "toolbar_gui.h"
#include "core/geometry_func.hpp"
#include "guitimer_func.h"
#include "zoom_func.h"
#include "widgets/statusbar_widget.h"
@@ -166,7 +167,7 @@ struct StatusBarWindow : Window {
DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, STR_STATUSBAR_PAUSED, TC_FROMSTRING, SA_HOR_CENTER);
} else if (this->ticker_scroll < TICKER_STOP && FindWindowById(WC_NEWS_WINDOW, 0) == NULL && _statusbar_news_item != NULL && _statusbar_news_item->string_id != 0) {
/* Draw the scrolling news text */
if (!DrawScrollingStatusText(_statusbar_news_item, this->ticker_scroll, r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, r.bottom)) {
if (!DrawScrollingStatusText(_statusbar_news_item, ScaleGUITrad(this->ticker_scroll), r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, r.bottom)) {
InvalidateWindowData(WC_STATUS_BAR, 0, SBI_NEWS_DELETED);
if (Company::IsValidID(_local_company)) {
/* This is the default text */

View File

@@ -257,6 +257,13 @@
# if !defined(FT_EXPORT)
# define FT_EXPORT( x ) extern "C" x CDECL
# endif
# endif
/* liblzma from vcpkg (before 5.2.4-2) used to patch lzma.h to define LZMA_API_STATIC for static builds */
# if defined(WITH_LZMA)
# if !defined(LZMA_API_STATIC)
# define LZMA_API_STATIC
# endif
# endif
#define strcasecmp stricmp
@@ -319,13 +326,15 @@
/* MSVCRT of course has to have a different syntax for long long *sigh* */
#if defined(_MSC_VER) || defined(__MINGW32__)
#define OTTD_PRINTF64 "%I64d"
#define OTTD_PRINTFHEX64 "%I64x"
#define PRINTF_SIZE "%Iu"
# define OTTD_PRINTF64 "%I64d"
# define OTTD_PRINTFHEX64 "%I64x"
# define PRINTF_SIZE "%Iu"
# define PRINTF_SIZEX "%IX"
#else
#define OTTD_PRINTF64 "%lld"
#define OTTD_PRINTFHEX64 "%llx"
#define PRINTF_SIZE "%zu"
# define OTTD_PRINTF64 "%lld"
# define OTTD_PRINTFHEX64 "%llx"
# define PRINTF_SIZE "%zu"
# define PRINTF_SIZEX "%zX"
#endif
typedef unsigned char byte;

View File

@@ -29,12 +29,12 @@ struct LangString {
char *name; ///< Name of the string.
char *english; ///< English text.
char *translated; ///< Translated text.
uint16 hash_next; ///< Next hash entry.
uint16 index; ///< The index in the language file.
size_t hash_next; ///< Next hash entry.
size_t index; ///< The index in the language file.
int line; ///< Line of string in source-file.
Case *translated_case; ///< Cases of the translation.
LangString(const char *name, const char *english, int index, int line);
LangString(const char *name, const char *english, size_t index, int line);
~LangString();
void FreeTranslation();
};
@@ -42,10 +42,10 @@ struct LangString {
/** Information about the currently known strings. */
struct StringData {
LangString **strings; ///< Array of all known strings.
uint16 *hash_heads; ///< Hash table for the strings.
size_t *hash_heads; ///< Hash table for the strings.
size_t tabs; ///< The number of 'tabs' of strings.
size_t max_strings; ///< The maximum number of strings.
int next_string_id; ///< The next string ID to allocate.
size_t next_string_id;///< The next string ID to allocate.
StringData(size_t tabs);
~StringData();

View File

@@ -58,7 +58,7 @@ Case::~Case()
* @param index The index in the string table.
* @param line The line this string was found on.
*/
LangString::LangString(const char *name, const char *english, int index, int line) :
LangString::LangString(const char *name, const char *english, size_t index, int line) :
name(stredup(name)), english(stredup(english)), translated(NULL),
hash_next(0), index(index), line(line), translated_case(NULL)
{
@@ -90,7 +90,7 @@ void LangString::FreeTranslation()
StringData::StringData(size_t tabs) : tabs(tabs), max_strings(tabs * TAB_SIZE)
{
this->strings = CallocT<LangString *>(max_strings);
this->hash_heads = CallocT<uint16>(max_strings);
this->hash_heads = CallocT<size_t>(max_strings);
this->next_string_id = 0;
}
@@ -144,9 +144,9 @@ void StringData::Add(const char *s, LangString *ls)
*/
LangString *StringData::Find(const char *s)
{
int idx = this->hash_heads[this->HashStr(s)];
size_t idx = this->hash_heads[this->HashStr(s)];
while (--idx >= 0) {
while (idx-- > 0) {
LangString *ls = this->strings[idx];
if (strcmp(ls->name, s) == 0) return ls;
@@ -764,7 +764,7 @@ void StringReader::HandleString(char *str)
}
if (this->data.strings[this->data.next_string_id] != NULL) {
strgen_error("String ID 0x%X for '%s' already in use by '%s'", this->data.next_string_id, str, this->data.strings[this->data.next_string_id]->name);
strgen_error("String ID 0x" PRINTF_SIZEX " for '%s' already in use by '%s'", this->data.next_string_id, str, this->data.strings[this->data.next_string_id]->name);
return;
}
@@ -830,11 +830,15 @@ void StringReader::ParseFile()
strecpy(_lang.digit_decimal_separator, ".", lastof(_lang.digit_decimal_separator));
_cur_line = 1;
while (this->ReadLine(buf, lastof(buf)) != NULL) {
while (this->data.next_string_id < this->data.max_strings && this->ReadLine(buf, lastof(buf)) != NULL) {
rstrip(buf);
this->HandleString(buf);
_cur_line++;
}
if (this->data.next_string_id == this->data.max_strings) {
strgen_error("Too many strings, maximum allowed is " PRINTF_SIZE, this->data.max_strings);
}
}
/**

View File

@@ -333,6 +333,7 @@ bool FindSubsidyTownCargoRoute()
/* Select a random town. */
const Town *src_town = Town::GetRandom();
if (src_town->cache.population < SUBSIDY_CARGO_MIN_POPULATION) return false;
CargoTypes town_cargo_produced = src_town->cargo_produced;

View File

@@ -2574,6 +2574,7 @@ max = 3
str = STR_CONFIG_SETTING_SCROLLMODE
strhelp = STR_CONFIG_SETTING_SCROLLMODE_HELPTEXT
strval = STR_CONFIG_SETTING_SCROLLMODE_DEFAULT
cat = SC_BASIC
[SDTC_BOOL]
var = gui.smooth_scroll
@@ -3730,7 +3731,7 @@ var = network.lan_internet
type = SLE_UINT8
flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC
guiflags = SGF_NETWORK_ONLY
def = 0
def = 1
min = 0
max = 1

View File

@@ -1991,7 +1991,7 @@ static const char * const _name_romanian_real[] = {
"Motru",
"N\xC4\x83s\xC4\x83ud",
"N\xC4\x83vodari",
"Odobe\xC8x99ti",
"Odobe\xC8\x99ti",
"Olteni\xC8\x9B""a",
"One\xC8\x99ti",
"Oradea",

View File

@@ -34,6 +34,7 @@ void MarkAllViewportsDirty(int left, int top, int right, int bottom);
bool DoZoomInOutWindow(ZoomStateChange how, Window *w);
void ZoomInOrOutToCursorWindow(bool in, Window * w);
Point GetTileZoomCenterWindow(bool in, Window * w);
void FixTitleGameZoom();
void HandleZoomMessage(Window *w, const ViewPort *vp, byte widget_zoom_in, byte widget_zoom_out);
/**

View File

@@ -2634,7 +2634,7 @@ static int MakeNWidget(const NWidgetPart *parts, int count, NWidgetBase **dest,
NWidgetResizeBase *nwrb = dynamic_cast<NWidgetResizeBase *>(*dest);
if (nwrb != NULL) {
assert(parts->u.xy.x >= 0 && parts->u.xy.y >= 0);
nwrb->SetMinimalSize(parts->u.xy.x, parts->u.xy.y);
nwrb->SetMinimalSize(ScaleGUITrad(parts->u.xy.x), ScaleGUITrad(parts->u.xy.y));
}
break;
}
@@ -2664,7 +2664,7 @@ static int MakeNWidget(const NWidgetPart *parts, int count, NWidgetBase **dest,
}
case WPT_PADDING:
if (*dest != NULL) (*dest)->SetPadding(parts->u.padding.top, parts->u.padding.right, parts->u.padding.bottom, parts->u.padding.left);
if (*dest != NULL) (*dest)->SetPadding(ScaleGUITrad(parts->u.padding.top), ScaleGUITrad(parts->u.padding.right), ScaleGUITrad(parts->u.padding.bottom), ScaleGUITrad(parts->u.padding.left));
break;
case WPT_PIPSPACE: {

View File

@@ -2414,7 +2414,7 @@ static void HandleScrollbarScrolling(Window *w)
}
/* Find the item we want to move to and make sure it's inside bounds. */
int pos = min(max(0, i + _scrollbar_start_pos) * sb->GetCount() / _scrollbar_size, max(0, sb->GetCount() - sb->GetCapacity()));
int pos = min(RoundDivSU(max(0, i + _scrollbar_start_pos) * sb->GetCount(), _scrollbar_size), max(0, sb->GetCount() - sb->GetCapacity()));
if (rtl) pos = max(0, sb->GetCount() - sb->GetCapacity() - pos);
if (pos != sb->GetPosition()) {
sb->SetPosition(pos);